version 1.122, 2014/05/20 01:25:23 |
version 1.123, 2014/07/05 09:20:54 |
|
|
void abortfile(int); |
void abortfile(int); |
char hextochar(const char *); |
char hextochar(const char *); |
char *urldecode(const char *); |
char *urldecode(const char *); |
|
char *recode_credentials(const char *_userinfo); |
int ftp_printf(FILE *, SSL *, const char *, ...) __attribute__((format(printf, 3, 4))); |
int ftp_printf(FILE *, SSL *, const char *, ...) __attribute__((format(printf, 3, 4))); |
char *ftp_readline(FILE *, SSL *, size_t *); |
char *ftp_readline(FILE *, SSL *, size_t *); |
size_t ftp_read(FILE *, SSL *, char *, size_t); |
size_t ftp_read(FILE *, SSL *, char *, size_t); |
|
|
#define FTP_PROXY "ftp_proxy" /* env var with ftp proxy location */ |
#define FTP_PROXY "ftp_proxy" /* env var with ftp proxy location */ |
#define HTTP_PROXY "http_proxy" /* env var with http proxy location */ |
#define HTTP_PROXY "http_proxy" /* env var with http proxy location */ |
|
|
#define COOKIE_MAX_LEN 42 |
|
|
|
#define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0')) |
#define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0')) |
|
|
static const char at_encoding_warning[] = |
static const char at_encoding_warning[] = |
|
|
struct addrinfo hints, *res0, *res, *ares = NULL; |
struct addrinfo hints, *res0, *res, *ares = NULL; |
const char * volatile savefile; |
const char * volatile savefile; |
char * volatile proxyurl = NULL; |
char * volatile proxyurl = NULL; |
char *cookie = NULL; |
char *credentials = NULL; |
volatile int s = -1, out; |
volatile int s = -1, out; |
volatile sig_t oldintr, oldinti; |
volatile sig_t oldintr, oldinti; |
FILE *fin = NULL; |
FILE *fin = NULL; |
|
|
ssize_t len, wlen; |
ssize_t len, wlen; |
#ifndef SMALL |
#ifndef SMALL |
char *sslpath = NULL, *sslhost = NULL; |
char *sslpath = NULL, *sslhost = NULL; |
char *locbase, *full_host = NULL, *auth = NULL; |
char *locbase, *full_host = NULL; |
const char *scheme; |
const char *scheme; |
int ishttpsurl = 0; |
int ishttpurl = 0, ishttpsurl = 0; |
SSL_CTX *ssl_ctx = NULL; |
SSL_CTX *ssl_ctx = NULL; |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
SSL *ssl = NULL; |
SSL *ssl = NULL; |
|
|
if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) { |
if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) { |
host = newline + sizeof(HTTP_URL) - 1; |
host = newline + sizeof(HTTP_URL) - 1; |
#ifndef SMALL |
#ifndef SMALL |
|
ishttpurl = 1; |
scheme = HTTP_URL; |
scheme = HTTP_URL; |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
} else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) { |
} else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) { |
|
|
* contain the path. Basic auth from RFC 2617, valid |
* contain the path. Basic auth from RFC 2617, valid |
* characters for path are in RFC 3986 section 3.3. |
* characters for path are in RFC 3986 section 3.3. |
*/ |
*/ |
if (proxyenv == NULL && |
if (proxyenv == NULL && (ishttpurl || ishttpsurl)) { |
(!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) { |
|
if ((p = strchr(host, '@')) != NULL) { |
if ((p = strchr(host, '@')) != NULL) { |
size_t authlen = (strlen(host) + 5) * 4 / 3; |
*p = '\0'; |
*p = 0; /* Kill @ */ |
credentials = recode_credentials(host); |
if ((auth = malloc(authlen)) == NULL) |
|
err(1, "Can't allocate memory for " |
|
"authorization"); |
|
if (b64_ntop(host, strlen(host), |
|
auth, authlen) == -1) |
|
errx(1, "error in base64 encoding"); |
|
host = p + 1; |
host = p + 1; |
} |
} |
} |
} |
|
|
path = strchr(host, '@'); /* look for credentials in proxy */ |
path = strchr(host, '@'); /* look for credentials in proxy */ |
if (!EMPTYSTRING(path)) { |
if (!EMPTYSTRING(path)) { |
*path = '\0'; |
*path = '\0'; |
cookie = strchr(host, ':'); |
if (strchr(host, ':') == NULL) { |
if (EMPTYSTRING(cookie)) { |
|
warnx("Malformed proxy URL: %s", proxyenv); |
warnx("Malformed proxy URL: %s", proxyenv); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
cookie = malloc(COOKIE_MAX_LEN); |
credentials = recode_credentials(host); |
if (cookie == NULL) |
|
errx(1, "out of memory"); |
|
if (b64_ntop(host, strlen(host), cookie, COOKIE_MAX_LEN) == -1) |
|
errx(1, "error in base64 encoding"); |
|
*path = '@'; /* restore @ in proxyurl */ |
*path = '@'; /* restore @ in proxyurl */ |
|
|
/* |
/* |
* This removes the password from proxyurl, |
* This removes the password from proxyurl, |
* filling with stars |
* filling with stars |
|
|
|
|
host = path + 1; |
host = path + 1; |
} |
} |
|
|
path = newline; |
path = newline; |
} |
} |
|
|
|
|
if (debug) |
if (debug) |
fprintf(ttyout, "host %s, port %s, path %s, " |
fprintf(ttyout, "host %s, port %s, path %s, " |
"save as %s, auth %s.\n", |
"save as %s, auth %s.\n", |
host, portnum, path, savefile, auth); |
host, portnum, path, savefile, credentials); |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
|
|
memset(&hints, 0, sizeof(hints)); |
memset(&hints, 0, sizeof(hints)); |
|
|
|
|
#ifndef SMALL |
#ifndef SMALL |
if (proxyenv && sslhost) |
if (proxyenv && sslhost) |
proxy_connect(s, sslhost, cookie); |
proxy_connect(s, sslhost, credentials); |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
break; |
break; |
} |
} |
|
|
* Host: directive must use the destination host address for |
* Host: directive must use the destination host address for |
* the original URI (path). We do not attach it at this moment. |
* the original URI (path). We do not attach it at this moment. |
*/ |
*/ |
if (cookie) |
if (credentials) |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" |
"Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", |
"Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", |
epath, cookie, buf ? buf : "", HTTP_USER_AGENT); |
epath, credentials, buf ? buf : "", |
|
HTTP_USER_AGENT); |
else |
else |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", |
epath, buf ? buf : "", HTTP_USER_AGENT); |
epath, buf ? buf : "", HTTP_USER_AGENT); |
|
|
else |
else |
restart_point = 0; |
restart_point = 0; |
} |
} |
if (auth) { |
if (credentials) { |
ftp_printf(fin, ssl, |
ftp_printf(fin, ssl, |
"GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", |
"GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", |
epath, restart_point ? |
epath, restart_point ? |
"HTTP/1.1\r\nConnection: close" : "HTTP/1.0", |
"HTTP/1.1\r\nConnection: close" : "HTTP/1.0", |
auth); |
credentials); |
free(auth); |
free(credentials); |
auth = NULL; |
credentials = NULL; |
} else |
} else |
#endif /* SMALL */ |
#endif /* SMALL */ |
ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, |
ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, |
|
|
SSL_free(ssl); |
SSL_free(ssl); |
} |
} |
free(full_host); |
free(full_host); |
free(auth); |
free(credentials); |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
if (fin != NULL) |
if (fin != NULL) |
fclose(fin); |
fclose(fin); |
|
|
free(buf); |
free(buf); |
free(proxyurl); |
free(proxyurl); |
free(newline); |
free(newline); |
free(cookie); |
free(credentials); |
return (rval); |
return (rval); |
} |
} |
|
|
|
|
/* |
/* |
* Loop through as long as there's files to fetch. |
* Loop through as long as there's files to fetch. |
*/ |
*/ |
|
username = pass = NULL; |
for (rval = 0; (rval == 0) && (argpos < argc); free(url), argpos++) { |
for (rval = 0; (rval == 0) && (argpos < argc); free(url), argpos++) { |
if (strchr(argv[argpos], ':') == NULL) |
if (strchr(argv[argpos], ':') == NULL) |
break; |
break; |
|
|
|
free(username); |
|
free(pass); |
host = dir = file = portnum = username = pass = NULL; |
host = dir = file = portnum = username = pass = NULL; |
|
|
/* |
/* |
|
|
if (strchr(pass, '@') != NULL || |
if (strchr(pass, '@') != NULL || |
(passagain != NULL && passagain < dir)) { |
(passagain != NULL && passagain < dir)) { |
warnx(at_encoding_warning); |
warnx(at_encoding_warning); |
|
username = pass = NULL; |
goto bad_ftp_url; |
goto bad_ftp_url; |
} |
} |
|
|
|
|
bad_ftp_url: |
bad_ftp_url: |
warnx("Invalid URL: %s", argv[argpos]); |
warnx("Invalid URL: %s", argv[argpos]); |
rval = argpos + 1; |
rval = argpos + 1; |
|
username = pass = NULL; |
continue; |
continue; |
} |
} |
username = urldecode(username); |
username = urldecode(username); |
|
|
*ret = '\0'; |
*ret = '\0'; |
|
|
return ret-reallen; |
return ret-reallen; |
|
} |
|
|
|
char * |
|
recode_credentials(const char *userinfo) |
|
{ |
|
char *ui, *creds; |
|
size_t ulen, credsize; |
|
|
|
/* url-decode the user and pass */ |
|
ui = urldecode(userinfo); |
|
|
|
ulen = strlen(ui); |
|
credsize = (ulen + 2) / 3 * 4 + 1; |
|
creds = malloc(credsize); |
|
if (creds == NULL) |
|
errx(1, "out of memory"); |
|
if (b64_ntop(ui, ulen, creds, credsize) == -1) |
|
errx(1, "error in base64 encoding"); |
|
free(ui); |
|
return (creds); |
} |
} |
|
|
char |
char |