Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/ftp PR/50438: NONAKA Kimihiro: ftp(1): CONNECT metho...



details:   https://anonhg.NetBSD.org/src/rev/0bbe2fd307e5
branches:  trunk
changeset: 342330:0bbe2fd307e5
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Dec 16 21:11:47 2015 +0000

description:
PR/50438: NONAKA Kimihiro: ftp(1): CONNECT method support
Please test!

diffstat:

 usr.bin/ftp/fetch.c |  302 ++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 248 insertions(+), 54 deletions(-)

diffs (truncated from 449 to 300 lines):

diff -r 8c643c0b681b -r 0bbe2fd307e5 usr.bin/ftp/fetch.c
--- a/usr.bin/ftp/fetch.c       Wed Dec 16 19:46:55 2015 +0000
+++ b/usr.bin/ftp/fetch.c       Wed Dec 16 21:11:47 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fetch.c,v 1.214 2015/12/16 19:17:16 christos Exp $     */
+/*     $NetBSD: fetch.c,v 1.215 2015/12/16 21:11:47 christos Exp $     */
 
 /*-
  * Copyright (c) 1997-2015 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: fetch.c,v 1.214 2015/12/16 19:17:16 christos Exp $");
+__RCSID("$NetBSD: fetch.c,v 1.215 2015/12/16 21:11:47 christos Exp $");
 #endif /* not lint */
 
 /*
@@ -184,6 +184,18 @@
        ui->portnum = 0;
 }
 
+#ifdef WITH_SSL
+static void
+copyurlinfo(struct urlinfo *dui, struct urlinfo *sui)
+{
+       dui->host = ftp_strdup(sui->host);
+       dui->port = ftp_strdup(sui->port);
+       dui->path = ftp_strdup(sui->path);
+       dui->utype = sui->utype;
+       dui->portnum = sui->portnum;
+}
+#endif
+
 static void
 freeurlinfo(struct urlinfo *ui)
 {
@@ -721,10 +733,9 @@
 }
 
 static int
-print_get(FETCH *fin, int isproxy, const struct urlinfo *ui)
+print_get(FETCH *fin, int hasleading, int isproxy, const struct urlinfo *ui)
 {
-       int hasleading = 0;
-       const char *leading = "  (";
+       const char *leading = hasleading ? ", " : "  (";
 
        if (isproxy) {
                if (verbose) {
@@ -807,66 +818,87 @@
 #define C_OK 0
 #define C_CLEANUP 1
 #define C_IMPROPER 2
+#define C_PROXY 3
+#define C_NOPROXY 4
 
+static int
+getresponseline(FETCH *fin, char *buf, size_t buflen, int *len)
+{
+       const char *errormsg;
+
+       alarmtimer(quit_time ? quit_time : 60);
+       *len = fetch_getline(fin, buf, buflen, &errormsg);
+       alarmtimer(0);
+       if (*len < 0) {
+               if (*errormsg == '\n')
+                       errormsg++;
+               warnx("Receiving HTTP reply: %s", errormsg);
+               return C_CLEANUP;
+       }
+       while (*len > 0 && (ISLWS(buf[*len-1])))
+               buf[--*len] = '\0';
+
+       if (*len)
+               DPRINTF("%s: received `%s'\n", __func__, buf);
+       return C_OK;
+}
+
+static int
+getresponse(FETCH *fin, char **cp, size_t buflen, int *hcode)
+{
+       int len, rv;
+       char *ep, *buf = *cp;
+
+       *hcode = 0;
+       if ((rv = getresponseline(fin, buf, buflen, &len)) != C_OK)
+               return rv;
+
+       /* Determine HTTP response code */
+       *cp = strchr(buf, ' ');
+       if (*cp == NULL)
+               return C_IMPROPER;
+
+       (*cp)++;
+
+       *hcode = strtol(*cp, &ep, 10);
+       if (*ep != '\0' && !isspace((unsigned char)*ep))
+               return C_IMPROPER;
+
+       return C_OK;
+}
 
 static int
 negotiate_connection(FETCH *fin, const char *url, const char *penv,
     off_t *rangestart, off_t *rangeend, off_t *entitylen,
     time_t *mtime, struct authinfo *wauth, struct authinfo *pauth,
-    int *rval, int *ischunked)
+    int *rval, int *ischunked, char **auth)
 {
        int                     len, hcode, rv;
        char                    buf[FTPBUFLEN], *ep;
-       const char              *errormsg, *cp, *token;
-       char                    *location, *message, *auth;
+       const char              *cp, *token;
+       char                    *location, *message;
 
-       auth = message = location = NULL;
+       *auth = message = location = NULL;
 
        /* 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);
+       ep = buf;
+       switch (getresponse(fin, &ep, sizeof(buf), &hcode)) {
+       case C_CLEANUP:
                goto cleanup_fetch_url;
+       case C_IMPROPER:
+               goto improper;
+       case C_OK:
+               message = ftp_strdup(ep);
+               break;
        }
-       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);
 
        /* Read the rest of the header. */
 
        for (;;) {
-               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);
+               if ((rv = getresponseline(fin, buf, sizeof(buf), &len)) != C_OK)
                        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);
 
        /*
         * Look for some headers
@@ -960,8 +992,8 @@
                                    "scheme `%s'\n", __func__, token);
                                continue;
                        }
-                       FREEPTR(auth);
-                       auth = ftp_strdup(token);
+                       FREEPTR(*auth);
+                       *auth = ftp_strdup(token);
                        DPRINTF("%s: parsed auth as `%s'\n",
                            __func__, cp);
                }
@@ -1021,7 +1053,7 @@
                if (verbose || aauth.auth == NULL ||
                    aauth.user == NULL || aauth.pass == NULL)
                        fprintf(ttyout, "%s\n", message);
-               if (EMPTYSTRING(auth)) {
+               if (EMPTYSTRING(*auth)) {
                        warnx(
                    "No authentication challenge provided by server");
                        goto cleanup_fetch_url;
@@ -1043,7 +1075,7 @@
                }
 
                authp = &aauth.auth;
-               if (auth_url(auth, authp, &aauth) == 0) {
+               if (auth_url(*auth, authp, &aauth) == 0) {
                        *rval = fetch_url(url, penv,
                            pauth->auth, wauth->auth);
                        memset(*authp, 0, strlen(*authp));
@@ -1069,12 +1101,143 @@
        rv = C_IMPROPER;
        goto out;
 out:
-       FREEPTR(auth);
        FREEPTR(message);
        FREEPTR(location);
        return rv;
 }              /* end of ftp:// or http:// specific setup */
 
+#ifdef WITH_SSL
+static int
+connectmethod(int s, FETCH *fin, struct urlinfo *oui, struct urlinfo *ui,
+    struct authinfo *wauth, struct authinfo *pauth,
+    char **auth, int *hasleading)
+{
+       void *ssl;
+       int hcode, rv;
+       const char *leading = *hasleading ? ", " : "  (";
+       const char *cp;
+       char buf[FTPBUFLEN], *ep;
+       char *message = NULL;
+
+       if (strchr(oui->host, ':')) {
+               char *h, *p;
+
+               /*
+                * strip off IPv6 scope identifier,
+                * since it is local to the node
+                */
+               h = ftp_strdup(oui->host);
+               if (isipv6addr(h) && (p = strchr(h, '%')) != NULL) {
+                       *p = '\0';
+               }
+               fetch_printf(fin, "CONNECT [%s]:%s HTTP/1.1\r\n",
+                   h, oui->port);
+               fetch_printf(fin, "Host: [%s]:%s\r\n", h, oui->port);
+               free(h);
+       } else {
+               fetch_printf(fin, "CONNECT %s:%s HTTP/1.1\r\n",
+                   oui->host, oui->port);
+               fetch_printf(fin, "Host: %s:%s\r\n",
+                   oui->host, oui->port);
+       }
+
+       print_agent(fin);
+       *hasleading = print_proxy(fin, leading, wauth->auth, pauth->auth);
+
+       if (verbose) {
+               leading = ", ";
+               (*hasleading)++;
+       } else {
+               leading = "  (";
+               *hasleading = 0;
+       }
+       if (pauth->auth) {
+               if (verbose) {
+                       fprintf(ttyout, "%swith proxy authorization" , leading);
+                       leading = ", ";
+                       (*hasleading)++;
+               }
+               fetch_printf(fin, "Proxy-Authorization: %s\r\n", pauth->auth);
+       }
+
+       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 */
+       ep = buf;
+       switch (getresponse(fin, &ep, sizeof(buf), &hcode)) {
+       case C_CLEANUP:
+               goto cleanup_fetch_url;
+       case C_IMPROPER:
+               goto improper;
+       case C_OK:
+               message = ftp_strdup(ep);
+               break;
+       }
+               
+       for (;;) {
+               int len;
+               if (getresponseline(fin, buf, sizeof(buf), &len) != C_OK)
+                       goto cleanup_fetch_url;
+               if (len == 0)



Home | Main Index | Thread Index | Old Index