NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/50438: ftp(1): CONNECT method support
>Number: 50438
>Category: bin
>Synopsis: ftp(1): CONNECT method support
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Nov 17 01:40:00 +0000 2015
>Originator: NONAKA Kimihiro
>Release: HEAD (20151113)
>Organization:
>Environment:
NetBSD netbsd 7.99.21 NetBSD 7.99.21 (KOHARU) #0: Tue Nov 17 09:51:25 JST 2015 nonaka@netbsd:/home/snapshot/NetBSD/HEAD.20151113/obj.NetBSD-amd64/amd64/sys/arch/amd64/compile/KOHARU amd64
>Description:
ftp(1) lacks CONNECT method for https connection via proxy.
>How-To-Repeat:
1) Install http proxy software (e.g. pkgsrc/www/tinyproxy)
2) Set https_proxy shell variable
3) ftp https://github.com/index.html
I tested with tinyproxy.
$ ftp https://github.com/index.html
Trying 127.0.0.1:8888 ...
Requesting https://github.com/index.html
(via 127.0.0.1:8888)
ftp: Error retrieving file `501 Not Implemented'
>Fix:
Please apply the following patch.
Index: usr.bin/ftp/fetch.c
===================================================================
RCS file: /cvsroot/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.207
diff -u -r1.207 fetch.c
--- usr.bin/ftp/fetch.c 12 Sep 2015 19:38:42 -0000 1.207
+++ usr.bin/ftp/fetch.c 17 Nov 2015 00:44:24 -0000
@@ -529,8 +529,11 @@
time_t mtime;
url_t urltype;
in_port_t portnum;
+ int proxyauthdone;
#ifdef WITH_SSL
void *ssl;
+ url_t ourltype;
+ char *ohost, *oport;
#endif
DPRINTF("%s: `%s' proxyenv `%s'\n", __func__, url, STRorNULL(penv));
@@ -542,9 +545,13 @@
s = -1;
savefile = NULL;
auth = location = message = NULL;
- ischunked = isproxy = hcode = 0;
+ ischunked = isproxy = hcode = proxyauthdone = 0;
rval = 1;
uuser = pass = host = path = decodedpath = puser = ppass = NULL;
+#ifdef WITH_SSL
+ ourltype = UNKNOWN_URL_T;
+ ohost = oport = NULL;
+#endif
if (sigsetjmp(httpabort, 1))
goto cleanup_fetch_url;
@@ -552,6 +559,13 @@
if (parse_url(url, "URL", &urltype, &uuser, &pass, &host, &port,
&portnum, &path) == -1)
goto cleanup_fetch_url;
+#ifdef WITH_SSL
+ if (urltype == HTTPS_URL_T) {
+ ourltype = urltype;
+ ohost = host;
+ oport = port;
+ }
+#endif
if (urltype == FILE_URL_T && ! EMPTYSTRING(host)
&& strcasecmp(host, "localhost") != 0) {
@@ -721,8 +735,14 @@
goto cleanup_fetch_url;
}
+#ifdef WITH_SSL
+ if (ohost != host)
+#endif
FREEPTR(host);
host = phost;
+#ifdef WITH_SSL
+ if (oport != port)
+#endif
FREEPTR(port);
port = pport;
FREEPTR(path);
@@ -823,10 +843,168 @@
leading = ", ";
hasleading++;
}
+#ifdef WITH_SSL
+ if (ourltype == HTTPS_URL_T) {
+ if (strchr(ohost, ':')) {
+ char *h, *p;
+
+ /*
+ * strip off IPv6 scope identifier,
+ * since it is local to the node
+ */
+ h = ftp_strdup(ohost);
+ if (isipv6addr(h) &&
+ (p = strchr(h, '%')) != NULL) {
+ *p = '\0';
+ }
+ fetch_printf(fin,
+ "CONNECT [%s]:%s HTTP/1.1\r\n",
+ h, oport);
+ fetch_printf(fin, "Host: [%s]:%s\r\n",
+ h, oport);
+ free(h);
+ } else {
+ fetch_printf(fin,
+ "CONNECT %s:%s HTTP/1.1\r\n",
+ ohost, oport);
+ fetch_printf(fin, "Host: %s:%s\r\n",
+ ohost, oport);
+ }
+ useragent = getenv("FTPUSERAGENT");
+ if (useragent != NULL) {
+ fetch_printf(fin, "User-Agent: %s\r\n",
+ useragent);
+ } else {
+ fetch_printf(fin,
+ "User-Agent: %s/%s\r\n",
+ FTP_PRODUCT, FTP_VERSION);
+ }
+ if (proxyauth) {
+ if (verbose) {
+ fprintf(ttyout,
+ "%swith proxy authorization"
+ , leading);
+ leading = ", ";
+ hasleading++;
+ }
+ fetch_printf(fin,
+ "Proxy-Authorization: %s\r\n",
+ proxyauth);
+ }
+ if (verbose && hasleading)
+ fputs(")\n", ttyout);
+ leading = " (";
+ hasleading = 0;
+ fetch_printf(fin, "\r\n");
+ if (fetch_flush(fin) == EOF) {
+ warn("Writing HTTP request");
+ alarmtimer(0);
+ goto cleanup_fetch_url;
+ }
+ alarmtimer(0);
+
+ /* Read the response */
+ alarmtimer(quit_time ? quit_time : 60);
+ len = fetch_getline(fin, buf, sizeof(buf),
+ &errormsg);
+ alarmtimer(0);
+ if (len < 0) {
+ if (*errormsg == '\n')
+ errormsg++;
+ warnx("Receiving HTTP reply: %s",
+ errormsg);
+ goto cleanup_fetch_url;
+ }
+ while (len > 0 && (ISLWS(buf[len-1])))
+ buf[--len] = '\0';
+ DPRINTF("%s: received `%s'\n", __func__, buf);
+
+ /* Determine HTTP response code */
+ cp = strchr(buf, ' ');
+ if (cp == NULL)
+ goto improper;
+ else
+ cp++;
+ hcode = strtol(cp, &ep, 10);
+ if (*ep != '\0' && !isspace((unsigned char)*ep))
+ goto improper;
+ message = ftp_strdup(cp);
+
+ while (1) {
+ alarmtimer(quit_time ? quit_time : 60);
+ len = fetch_getline(fin, buf,
+ sizeof(buf), &errormsg);
+ alarmtimer(0);
+ if (len < 0) {
+ if (*errormsg == '\n')
+ errormsg++;
+ warnx("Receiving HTTP reply: %s"
+ , errormsg);
+ goto cleanup_fetch_url;
+ }
+ while (len > 0 && (ISLWS(buf[len-1])))
+ buf[--len] = '\0';
+ if (len == 0)
+ break;
+ DPRINTF("%s: received `%s'\n",
+ __func__, buf);
+
+ if (match_token(&cp,
+ "Proxy-Authenticate:")) {
+ if (!(token = match_token(&cp,
+ "Basic"))) {
+ DPRINTF("%s: skipping "
+ "unknown auth "
+ "scheme `%s'\n",
+ __func__, token);
+ continue;
+ }
+ FREEPTR(auth);
+ auth = ftp_strdup(token);
+ DPRINTF("%s: parsed auth as "
+ "`%s'\n", __func__, cp);
+ proxyauthdone = 1;
+ }
+ }
+
+ /* finished parsing header */
+ switch (hcode) {
+ case 200:
+ break;
+ default:
+ if (message)
+ warnx("Error proxy connect "
+ "`%s'", message);
+ else
+ warnx("Unknown error proxy "
+ "connect");
+ goto cleanup_fetch_url;
+ }
+
+ if ((ssl = fetch_start_ssl(s, host)) == NULL)
+ goto cleanup_fetch_url;
+ fetch_set_ssl(fin, ssl);
+ ssl = NULL;
+
+ urltype = ourltype;
+ if (host != ohost) {
+ FREEPTR(host);
+ host = ohost;
+ }
+ if (port != oport) {
+ FREEPTR(port);
+ port = oport;
+ }
+ goto no_proxy;
+ }
+#endif
fetch_printf(fin, "GET %s HTTP/1.0\r\n", path);
if (flushcache)
fetch_printf(fin, "Pragma: no-cache\r\n");
} else {
+#ifdef WITH_SSL
+no_proxy:
+#endif
fetch_printf(fin, "GET %s HTTP/1.1\r\n", path);
if (strchr(host, ':')) {
char *h, *p;
@@ -881,7 +1059,7 @@
}
fetch_printf(fin, "Authorization: %s\r\n", wwwauth);
}
- if (proxyauth) {
+ if (proxyauth && !proxyauthdone) {
if (verbose) {
fprintf(ttyout,
"%swith proxy authorization", leading);
@@ -1395,6 +1573,12 @@
if (pass != NULL)
memset(pass, 0, strlen(pass));
FREEPTR(pass);
+#ifdef WITH_SSL
+ if (host != ohost)
+ FREEPTR(ohost);
+ if (port != oport)
+ FREEPTR(oport);
+#endif
FREEPTR(host);
FREEPTR(port);
FREEPTR(path);
Home |
Main Index |
Thread Index |
Old Index