1/* 2 * Copyright (c) 1999 3 * Philipp Mergenthaler <philipp.mergenthaler@stud.uni-karlsruhe.de> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30#include "sysinstall.h" 31#include <sys/socket.h> 32#include <netinet/in.h> 33#include <arpa/inet.h> 34#include <sys/param.h> 35#include <netdb.h> 36 37extern const char *ftp_dirs[]; /* defined in ftp.c */ 38 39Boolean 40checkAccess(Boolean connectCheckOnly, Boolean isProxy) 41{ 42 int rv, s, af; 43 bool el, found=FALSE; /* end of header line */ 44 char *cp, buf[PATH_MAX], req[BUFSIZ]; 45 struct addrinfo hints, *res, *res0; 46 47 af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC; 48 memset(&hints, 0, sizeof(hints)); 49 hints.ai_family = af; 50 hints.ai_socktype = SOCK_STREAM; 51 hints.ai_protocol = 0; 52 if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST), 53 variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) { 54 msgConfirm("%s", gai_strerror(rv)); 55 variable_unset(VAR_HTTP_HOST); 56 return FALSE; 57 } 58 s = -1; 59 for (res = res0; res; res = res->ai_next) { 60 if ((s = socket(res->ai_family, res->ai_socktype, 61 res->ai_protocol)) < 0) 62 continue; 63 if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) 64 break; 65 close(s); 66 s = -1; 67 } 68 freeaddrinfo(res0); 69 if (s == -1) { 70 if (isProxy) { 71 msgConfirm("Couldn't connect to proxy %s:%s", 72 variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 73 } else { 74 msgConfirm("Couldn't connect to server http://%s:%s/", 75 variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 76 } 77 variable_unset(VAR_HTTP_HOST); 78 return FALSE; 79 } 80 if (connectCheckOnly) { 81 close(s); 82 return TRUE; 83 } 84 85 msgNotify("Checking access to\n %s", variable_get(VAR_HTTP_PATH)); 86 if (isProxy) 87 sprintf(req,"GET %s/ HTTP/1.0\r\n\r\n", variable_get(VAR_HTTP_PATH)); 88 else 89 sprintf(req,"GET /%s/ HTTP/1.0\r\n\r\n", variable_get(VAR_HTTP_PATH)); 90 write(s,req,strlen(req)); 91/* 92 * scan the headers of the response 93 * this is extremely quick'n dirty 94 * 95 */ 96 bzero(buf, PATH_MAX); 97 cp=buf; 98 el=FALSE; 99 rv=read(s,cp,1); 100 variable_set2(VAR_HTTP_FTP_MODE,"",0); 101 while (rv>0) { 102 if ((*cp == '\012') && el) { 103 /* reached end of a header line */ 104 if (!strncmp(buf,"HTTP",4)) { 105 if (strtol((char *)(buf+9),0,0) == 200) { 106 found = TRUE; 107 } 108 } 109 110 /* 111 * Some proxies fetch files with certain extensions in "ascii mode" 112 * instead of "binary mode" for FTP. The FTP server then translates 113 * all LF to CRLF. 114 * 115 * You can force Squid to use binary mode by appending ";type=i" to 116 * the URL, which is what I do here. For other proxies, the 117 * LF->CRLF substitution is reverted in distExtract(). 118 */ 119 if (isProxy && !strncmp(buf,"Server: ",8)) { 120 if (!strncmp(buf,"Server: Squid",13)) { 121 variable_set2(VAR_HTTP_FTP_MODE,";type=i",0); 122 } else { 123 variable_set2(VAR_HTTP_FTP_MODE,"",0); 124 } 125 } 126 /* ignore other headers */ 127 /* check for "\015\012" at beginning of line, i.e. end of headers */ 128 if ((cp-buf) == 1) 129 break; 130 cp=buf; 131 rv=read(s,cp,1); 132 } else { 133 el=FALSE; 134 if (*cp == '\015') 135 el=TRUE; 136 cp++; 137 rv=read(s,cp,1); 138 } 139 } 140 close(s); 141 return found; 142} 143 144Boolean 145mediaInitHTTP(Device *dev) 146{ 147 bool found=FALSE; /* end of header line */ 148 char *rel, req[BUFSIZ]; 149 int fdir; 150 151 /* 152 * First verify the proxy access 153 */ 154 checkAccess(TRUE, TRUE); 155 while (variable_get(VAR_HTTP_HOST) == NULL) { 156 if (DITEM_STATUS(mediaSetHTTP(NULL)) == DITEM_FAILURE) 157 return FALSE; 158 checkAccess(TRUE, TRUE); 159 } 160again: 161 /* If the release is specified as "__RELEASE" or "any", then just 162 * assume that the path the user gave is ok. 163 */ 164 rel = variable_get(VAR_RELNAME); 165 /* 166 msgConfirm("rel: -%s-", rel); 167 */ 168 169 if (strcmp(rel, "__RELEASE") && strcmp(rel, "any")) { 170 for (fdir = 0; ftp_dirs[fdir]; fdir++) { 171 sprintf(req, "%s/%s/%s", variable_get(VAR_FTP_PATH), 172 ftp_dirs[fdir], rel); 173 variable_set2(VAR_HTTP_PATH, req, 0); 174 if (checkAccess(FALSE, TRUE)) { 175 found = TRUE; 176 break; 177 } 178 } 179 } else { 180 variable_set2(VAR_HTTP_PATH, variable_get(VAR_FTP_PATH), 0); 181 found = checkAccess(FALSE, TRUE); 182 } 183 if (!found) { 184 msgConfirm("No such directory: %s\n" 185 "please check the URL and try again.", variable_get(VAR_HTTP_PATH)); 186 variable_unset(VAR_HTTP_PATH); 187 dialog_clear_norefresh(); 188 clear(); 189 if (DITEM_STATUS(mediaSetHTTP(NULL)) != DITEM_FAILURE) goto again; 190 } 191 return found; 192} 193 194FILE * 195mediaGetHTTP(Device *dev, char *file, Boolean probe) 196{ 197 FILE *fp; 198 int rv, s, af; 199 bool el; /* end of header line */ 200 char *cp, buf[PATH_MAX], req[BUFSIZ]; 201 struct addrinfo hints, *res, *res0; 202 203 af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC; 204 memset(&hints, 0, sizeof(hints)); 205 hints.ai_family = af; 206 hints.ai_socktype = SOCK_STREAM; 207 hints.ai_protocol = 0; 208 if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST), 209 variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) { 210 msgConfirm("%s", gai_strerror(rv)); 211 return NULL; 212 } 213 s = -1; 214 for (res = res0; res; res = res->ai_next) { 215 if ((s = socket(res->ai_family, res->ai_socktype, 216 res->ai_protocol)) < 0) 217 continue; 218 if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) 219 break; 220 close(s); 221 s = -1; 222 } 223 freeaddrinfo(res0); 224 if (s == -1) { 225 msgConfirm("Couldn't connect to proxy %s:%s", 226 variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 227 return NULL; 228 } 229 230 sprintf(req,"GET %s/%s%s HTTP/1.0\r\n\r\n", 231 variable_get(VAR_HTTP_PATH), file, variable_get(VAR_HTTP_FTP_MODE)); 232 233 if (isDebug()) { 234 msgDebug("sending http request: %s\n",req); 235 } 236 write(s,req,strlen(req)); 237 238/* 239 * scan the headers of the response 240 * this is extremely quick'n dirty 241 * 242 */ 243 cp=buf; 244 el=FALSE; 245 rv=read(s,cp,1); 246 while (rv>0) { 247 if ((*cp == '\012') && el) { 248 /* reached end of a header line */ 249 if (!strncmp(buf,"HTTP",4)) { 250 rv=strtol((char *)(buf+9),0,0); 251 *(cp-1)='\0'; /* chop the CRLF off */ 252 if (probe && (rv != 200)) { 253 return NULL; 254 } else if (rv >= 500) { 255 msgConfirm("Server error %s when sending %s, you could try an other server",buf, req); 256 return NULL; 257 } else if (rv == 404) { 258 msgConfirm("%s was not found, maybe directory or release-version are wrong?",req); 259 return NULL; 260 } else if (rv >= 400) { 261 msgConfirm("Client error %s, you could try an other server",buf); 262 return NULL; 263 } else if (rv >= 300) { 264 msgConfirm("Error %s",buf); 265 return NULL; 266 } else if (rv != 200) { 267 msgConfirm("Error %s when sending %s, you could try an other server",buf, req); 268 return NULL; 269 } 270 } 271 /* ignore other headers */ 272 /* check for "\015\012" at beginning of line, i.e. end of headers */ 273 if ((cp-buf) == 1) 274 break; 275 cp=buf; 276 rv=read(s,cp,1); 277 } else { 278 el=FALSE; 279 if (*cp == '\015') 280 el=TRUE; 281 cp++; 282 rv=read(s,cp,1); 283 } 284 } 285 fp=fdopen(s,"r"); 286 return fp; 287} 288