=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ftp/fetch.c,v retrieving revision 1.122 retrieving revision 1.123 diff -c -r1.122 -r1.123 *** src/usr.bin/ftp/fetch.c 2014/05/20 01:25:23 1.122 --- src/usr.bin/ftp/fetch.c 2014/07/05 09:20:54 1.123 *************** *** 1,4 **** ! /* $OpenBSD: fetch.c,v 1.122 2014/05/20 01:25:23 guenther Exp $ */ /* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */ /*- --- 1,4 ---- ! /* $OpenBSD: fetch.c,v 1.123 2014/07/05 09:20:54 guenther Exp $ */ /* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */ /*- *************** *** 76,81 **** --- 76,82 ---- void abortfile(int); char hextochar(const char *); char *urldecode(const char *); + char *recode_credentials(const char *_userinfo); int ftp_printf(FILE *, SSL *, const char *, ...) __attribute__((format(printf, 3, 4))); char *ftp_readline(FILE *, SSL *, size_t *); size_t ftp_read(FILE *, SSL *, char *, size_t); *************** *** 97,104 **** #define FTP_PROXY "ftp_proxy" /* env var with ftp 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')) static const char at_encoding_warning[] = --- 98,103 ---- *************** *** 393,399 **** struct addrinfo hints, *res0, *res, *ares = NULL; const char * volatile savefile; char * volatile proxyurl = NULL; ! char *cookie = NULL; volatile int s = -1, out; volatile sig_t oldintr, oldinti; FILE *fin = NULL; --- 392,398 ---- struct addrinfo hints, *res0, *res, *ares = NULL; const char * volatile savefile; char * volatile proxyurl = NULL; ! char *credentials = NULL; volatile int s = -1, out; volatile sig_t oldintr, oldinti; FILE *fin = NULL; *************** *** 402,410 **** ssize_t len, wlen; #ifndef SMALL char *sslpath = NULL, *sslhost = NULL; ! char *locbase, *full_host = NULL, *auth = NULL; const char *scheme; ! int ishttpsurl = 0; SSL_CTX *ssl_ctx = NULL; #endif /* !SMALL */ SSL *ssl = NULL; --- 401,409 ---- ssize_t len, wlen; #ifndef SMALL char *sslpath = NULL, *sslhost = NULL; ! char *locbase, *full_host = NULL; const char *scheme; ! int ishttpurl = 0, ishttpsurl = 0; SSL_CTX *ssl_ctx = NULL; #endif /* !SMALL */ SSL *ssl = NULL; *************** *** 420,425 **** --- 419,425 ---- if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) { host = newline + sizeof(HTTP_URL) - 1; #ifndef SMALL + ishttpurl = 1; scheme = HTTP_URL; #endif /* !SMALL */ } else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) { *************** *** 472,488 **** * contain the path. Basic auth from RFC 2617, valid * characters for path are in RFC 3986 section 3.3. */ ! if (proxyenv == NULL && ! (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) { if ((p = strchr(host, '@')) != NULL) { ! size_t authlen = (strlen(host) + 5) * 4 / 3; ! *p = 0; /* Kill @ */ ! 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; } } --- 472,481 ---- * contain the path. Basic auth from RFC 2617, valid * characters for path are in RFC 3986 section 3.3. */ ! if (proxyenv == NULL && (ishttpurl || ishttpsurl)) { if ((p = strchr(host, '@')) != NULL) { ! *p = '\0'; ! credentials = recode_credentials(host); host = p + 1; } } *************** *** 544,560 **** path = strchr(host, '@'); /* look for credentials in proxy */ if (!EMPTYSTRING(path)) { *path = '\0'; ! cookie = strchr(host, ':'); ! if (EMPTYSTRING(cookie)) { warnx("Malformed proxy URL: %s", proxyenv); goto cleanup_url_get; } ! cookie = malloc(COOKIE_MAX_LEN); ! 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 */ /* * This removes the password from proxyurl, * filling with stars --- 537,549 ---- path = strchr(host, '@'); /* look for credentials in proxy */ if (!EMPTYSTRING(path)) { *path = '\0'; ! if (strchr(host, ':') == NULL) { warnx("Malformed proxy URL: %s", proxyenv); goto cleanup_url_get; } ! credentials = recode_credentials(host); *path = '@'; /* restore @ in proxyurl */ + /* * This removes the password from proxyurl, * filling with stars *************** *** 565,570 **** --- 554,560 ---- host = path + 1; } + path = newline; } *************** *** 697,703 **** if (debug) fprintf(ttyout, "host %s, port %s, path %s, " "save as %s, auth %s.\n", ! host, portnum, path, savefile, auth); #endif /* !SMALL */ memset(&hints, 0, sizeof(hints)); --- 687,693 ---- if (debug) fprintf(ttyout, "host %s, port %s, path %s, " "save as %s, auth %s.\n", ! host, portnum, path, savefile, credentials); #endif /* !SMALL */ memset(&hints, 0, sizeof(hints)); *************** *** 793,799 **** #ifndef SMALL if (proxyenv && sslhost) ! proxy_connect(s, sslhost, cookie); #endif /* !SMALL */ break; } --- 783,789 ---- #ifndef SMALL if (proxyenv && sslhost) ! proxy_connect(s, sslhost, credentials); #endif /* !SMALL */ break; } *************** *** 890,899 **** * Host: directive must use the destination host address for * the original URI (path). We do not attach it at this moment. */ ! if (cookie) ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" "Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", ! epath, cookie, buf ? buf : "", HTTP_USER_AGENT); else ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", epath, buf ? buf : "", HTTP_USER_AGENT); --- 880,890 ---- * Host: directive must use the destination host address for * the original URI (path). We do not attach it at this moment. */ ! if (credentials) ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" "Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", ! epath, credentials, buf ? buf : "", ! HTTP_USER_AGENT); else ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", epath, buf ? buf : "", HTTP_USER_AGENT); *************** *** 908,921 **** else restart_point = 0; } ! if (auth) { ftp_printf(fin, ssl, "GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", epath, restart_point ? "HTTP/1.1\r\nConnection: close" : "HTTP/1.0", ! auth); ! free(auth); ! auth = NULL; } else #endif /* SMALL */ ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, --- 899,912 ---- else restart_point = 0; } ! if (credentials) { ftp_printf(fin, ssl, "GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ", epath, restart_point ? "HTTP/1.1\r\nConnection: close" : "HTTP/1.0", ! credentials); ! free(credentials); ! credentials = NULL; } else #endif /* SMALL */ ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, *************** *** 1231,1237 **** SSL_free(ssl); } free(full_host); ! free(auth); #endif /* !SMALL */ if (fin != NULL) fclose(fin); --- 1222,1228 ---- SSL_free(ssl); } free(full_host); ! free(credentials); #endif /* !SMALL */ if (fin != NULL) fclose(fin); *************** *** 1240,1246 **** free(buf); free(proxyurl); free(newline); ! free(cookie); return (rval); } --- 1231,1237 ---- free(buf); free(proxyurl); free(newline); ! free(credentials); return (rval); } *************** *** 1316,1324 **** --- 1307,1319 ---- /* * Loop through as long as there's files to fetch. */ + username = pass = NULL; for (rval = 0; (rval == 0) && (argpos < argc); free(url), argpos++) { if (strchr(argv[argpos], ':') == NULL) break; + + free(username); + free(pass); host = dir = file = portnum = username = pass = NULL; /* *************** *** 1375,1380 **** --- 1370,1376 ---- if (strchr(pass, '@') != NULL || (passagain != NULL && passagain < dir)) { warnx(at_encoding_warning); + username = pass = NULL; goto bad_ftp_url; } *************** *** 1382,1387 **** --- 1378,1384 ---- bad_ftp_url: warnx("Invalid URL: %s", argv[argpos]); rval = argpos + 1; + username = pass = NULL; continue; } username = urldecode(username); *************** *** 1616,1621 **** --- 1613,1638 ---- *ret = '\0'; 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