Source-Changes-HG archive

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

[src/trunk]: src/usr.bin/ftp * change fetch_ftp() to be fully rfc 1738 compli...



details:   https://anonhg.NetBSD.org/src/rev/aca3ead7a099
branches:  trunk
changeset: 474588:aca3ead7a099
user:      lukem <lukem%NetBSD.org@localhost>
date:      Mon Jul 12 13:20:34 1999 +0000

description:
* change fetch_ftp() to be fully rfc 1738 compliant; if the URL contains
  the an empty directory (e.g, between `some' and `path' in
  `ftp://host/some//path'), then execute `CWD ' (without a path).
  This command will probably fail on rfc 959 compliant servers, so
  issue a warning in this case and bail. [noted by cgd].
  (i wonder if the people who wrote rfc 1738 actually realised that this
  requirement appears to contravene the spec for `cwd' in rfc 959 ?)
* replace isurl() with isipv6addr(), and use appropriately. fixes
  auto-login with `classic ftp URLs' (e.g, `ftp somehost:')
* cleanup and rework some of the ipv6 stuff in parse_url()
* prevent potential coredump in fetch_ftp() when parsing `;type=X'
* KNF a few lines
* fix a couple of comments
* cleanup the man page a bit

diffstat:

 usr.bin/ftp/extern.h |    4 +-
 usr.bin/ftp/fetch.c  |  176 +++++++++++++++++++++++++++++---------------------
 usr.bin/ftp/ftp.1    |   35 ++++++----
 usr.bin/ftp/main.c   |    6 +-
 usr.bin/ftp/util.c   |   24 ++++++-
 5 files changed, 149 insertions(+), 96 deletions(-)

diffs (truncated from 548 to 300 lines):

diff -r 931db40ffa40 -r aca3ead7a099 usr.bin/ftp/extern.h
--- a/usr.bin/ftp/extern.h      Mon Jul 12 12:34:57 1999 +0000
+++ b/usr.bin/ftp/extern.h      Mon Jul 12 13:20:34 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: extern.h,v 1.33 1999/07/11 20:37:39 itojun Exp $       */
+/*     $NetBSD: extern.h,v 1.34 1999/07/12 13:20:34 lukem Exp $        */
 
 /*
  * Copyright (C) 1997 and 1998 WIDE Project.
@@ -111,7 +111,7 @@
 void   idle __P((int, char **));
 int     initconn __P((void));
 void   intr __P((void));
-int    isurl __P((const char *));
+int    isipv6addr __P((const char *));
 void   list_vertical __P((StringList *));
 void   lcd __P((int, char **));
 void   lostpeer __P((void));
diff -r 931db40ffa40 -r aca3ead7a099 usr.bin/ftp/fetch.c
--- a/usr.bin/ftp/fetch.c       Mon Jul 12 12:34:57 1999 +0000
+++ b/usr.bin/ftp/fetch.c       Mon Jul 12 13:20:34 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fetch.c,v 1.62 1999/07/06 22:11:37 tron Exp $  */
+/*     $NetBSD: fetch.c,v 1.63 1999/07/12 13:20:34 lukem Exp $ */
 
 /*-
  * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: fetch.c,v 1.62 1999/07/06 22:11:37 tron Exp $");
+__RCSID("$NetBSD: fetch.c,v 1.63 1999/07/12 13:20:34 lukem Exp $");
 #endif /* not lint */
 
 /*
@@ -252,16 +252,19 @@
 
 /*
  * Parse URL of form:
- *     <type>://[<user>[:<password>@]]<host>[:<port>]/<url-path>
+ *     <type>://[<user>[:<password>@]]<host>[:<port>][/<path>]
  * Returns -1 if a parse error occurred, otherwise 0.
- * Only permit [<user>[:<password>@]] for ftp:// URLs
  * It's the caller's responsibility to url_decode() the returned
  * user, pass and path.
+ *
  * Sets type to url_t, each of the given char ** pointers to a
  * malloc(3)ed strings of the relevant section, and port to
  * the number given, or ftpport if ftp://, or httpport if http://.
  *
- * XXX: this is not totally RFC 1738 compliant; path will have the
+ * If <host> is surrounded by `[' and ']', it's parsed as an
+ * IPv6 address (as per draft-ietf-ipngwg-url-literal-01.txt).
+ *
+ * XXX: this is not totally RFC 1738 compliant; <path> will have the
  * leading `/' unless it's an ftp:// URL, as this makes things easier
  * for file:// and http:// URLs. ftp:// URLs have the `/' between the
  * host and the url-path removed, but any additional leading slashes
@@ -271,10 +274,11 @@
  * Examples:
  *      input url                       output path
  *      ---------                       -----------
- *     "http://host";                   NULL
- *     "http://host/";                  "/"
- *     "http://host/dir/file";          "/dir/file"
- *     "ftp://host/dir/file";           "dir/file"
+ *     "ftp://host";                    NULL
+ *     "http://host/";                  NULL
+ *     "file://host/dir/file"          "dir/file"
+ *     "ftp://host/";                   ""
+ *     "ftp://host//";                  NULL
  *     "ftp://host//dir/file";          "/dir/file"
  */
 static int
@@ -288,7 +292,7 @@
        char            **port;
        char            **path;
 {
-       char *cp, *ep, *thost;
+       char *cp, *ep, *thost, *tport;
        size_t len;
 
        if (url == NULL || desc == NULL || type == NULL || user == NULL
@@ -296,17 +300,17 @@
                errx(1, "parse_url: invoked with NULL argument!");
 
        *type = UNKNOWN_URL_T;
-       *user = *pass = *host = *path = NULL;
-       *port = NULL;
+       *user = *pass = *host = *port = *path = NULL;
+       tport = NULL;
 
        if (strncasecmp(url, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
                url += sizeof(HTTP_URL) - 1;
                *type = HTTP_URL_T;
-               *port = strdup(httpport);
+               tport = httpport;
        } else if (strncasecmp(url, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
                url += sizeof(FTP_URL) - 1;
                *type = FTP_URL_T;
-               *port = strdup(ftpport);
+               tport = ftpport;
        } else if (strncasecmp(url, FILE_URL, sizeof(FILE_URL) - 1) == 0) {
                url += sizeof(FILE_URL) - 1;
                *type = FILE_URL_T;
@@ -338,52 +342,66 @@
                *path = xstrdup(ep);
        }
 
-       cp = strchr(thost, '@');
-                                       /* look for user[:pass]@ in URLs */
+       cp = strchr(thost, '@');        /* look for user[:pass]@ in URLs */
        if (cp != NULL) {
                if (*type == FTP_URL_T)
                        anonftp = 0;    /* disable anonftp */
                *user = thost;
                *cp = '\0';
-               *host = xstrdup(cp + 1);
+               thost = xstrdup(cp + 1);
                cp = strchr(*user, ':');
                if (cp != NULL) {
                        *cp = '\0';
                        *pass = xstrdup(cp + 1);
                }
-       } else
-               *host = thost;
+       }
 
-       /* look for IPv6 address URL */
-       if (*thost == '[' && (cp = strrchr(thost, ']'))) {
-               size_t len = cp - thost - 1 ;
-               *host = (char *)xmalloc(len + 1);
-               strncpy(*host, thost + 1, len);
-               (*host)[len] = '\0';
-               cp = strrchr(++cp, ':');
-       } else if ((cp = strrchr(thost, ':')) != NULL) {
-               size_t len = cp - thost;
-               *host = (char *)xmalloc(len + 1);
-               strncpy(*host, thost, len);
-               (*host)[len] = '\0';
-       } else {
-               *host = xstrdup(thost);
-               cp = NULL;
-       }
+#ifdef INET6
+                       /*
+                        * Check if thost is an encoded IPv6 address, as per
+                        * draft-ietf-ipngwg-url-literal-01.txt:
+                        *      `[' ipv6-address ']'
+                        */
+       if (*thost == '[') {
+               cp = thost + 1;
+               if ((ep = strchr(cp, ']')) == NULL ||
+                   (ep[1] != '\0' && ep[1] != '\0')) {
+                       warnx("Invalid address `%s' in %s `%s'",
+                           thost, desc, url);
+                       goto cleanup_parse_url;
+               }
+               len = ep - cp;          /* change `[xxx]' -> `xxx' */
+               memmove(thost, thost + 1, len);
+               thost[len] = '\0';
+               if (! isipv6addr(thost)) {
+                       warnx("Invalid IPv6 address `%s' in %s `%s'",
+                           thost, desc, url);
+                       goto cleanup_parse_url;
+               }
+               cp = ep + 1;
+               if (*cp == ':')
+                       cp++;
+               else
+                       cp = NULL;
+       } else
+#endif /* INET6 */
+           if ((cp = strchr(thost, ':')) != NULL)
+               *cp++ =  '\0';
+       *host = thost;
 
                        /* look for [:port] */
        if (cp != NULL) {
                long nport;
 
-               *cp = '\0';
-               nport = strtol(cp + 1, &ep, 10);
+               nport = strtol(cp, &ep, 10);
                if (nport < 1 || nport > MAX_IN_PORT_T || *ep != '\0') {
                        warnx("Invalid port `%s' in %s `%s'", cp, desc, url);
                        goto cleanup_parse_url;
                }
-               *port = (char *)xmalloc(6);     /* large enough for "65535\0" */
-               snprintf(*port, 6, "%ld", nport);
+               tport = cp;
        }
+       if (tport != NULL);
+               *port = xstrdup(tport);
 
        if (debug)
                fprintf(ttyout,
@@ -420,7 +438,7 @@
        size_t                  len;
        char                    *cp, *ep, *buf, *savefile;
        char                    *auth, *location, *message;
-       char                    *user, *pass, *host, *path, *decodedpath;
+       char                    *user, *pass, *host, *port, *path, *decodedpath;
        char                    *puser, *ppass;
        off_t                   hashbytes;
        int                      (*closefunc) __P((FILE *));
@@ -428,7 +446,6 @@
        time_t                  mtime;
        url_t                   urltype;
        in_port_t               portnum;
-       char                    *port;
        int                     error;
 
        closefunc = NULL;
@@ -620,7 +637,7 @@
                        warnx("Unknown port for URL `%s'", url);
                        goto cleanup_fetch_url;
                }
-               sin.sin_port = port;
+               sin.sin_port = portnum;
 
                s = socket(AF_INET, SOCK_STREAM, 0);
                if (s == -1) {
@@ -687,11 +704,12 @@
                                close(s);
                                res = res->ai_next;
                                if (res) {
-                                       getnameinfo(res->ai_addr, res->ai_addrlen,
-                                               hbuf, sizeof(hbuf), NULL, 0,
-                                               NI_NUMERICHOST);
+                                       getnameinfo(res->ai_addr,
+                                           res->ai_addrlen, hbuf, sizeof(hbuf),
+                                           NULL, 0, NI_NUMERICHOST);
                                        if (verbose)
-                                               fprintf(ttyout, "Trying %s...\n", hbuf);
+                                               fprintf(ttyout,
+                                                   "Trying %s...\n", hbuf);
                                        continue;
                                }
                                warn("Can't connect to %s", host);
@@ -1159,7 +1177,7 @@
 
 /*
  * Retrieve ftp URL or classic ftp argument using FTP.
- * Returns -1 on failure, 0 on completed xfer, 1 if ftp connection
+ * Returns 1 on failure, 0 on completed xfer, -1 if ftp connection
  * is still open (e.g, ftp xfer with trailing /)
  */
 static int
@@ -1194,7 +1212,7 @@
                 */
 
                                        /* check for trailing ';type=[aid]' */
-               if (path != NULL && (cp = strrchr(path, ';')) != NULL) {
+               if (! EMPTYSTRING(path) && (cp = strrchr(path, ';')) != NULL) {
                        if (strcasecmp(cp, ";type=a") == 0)
                                type = TYPE_A;
                        else if (strcasecmp(cp, ";type=i") == 0)
@@ -1229,7 +1247,7 @@
                 * If we are dealing with classic `host:path' syntax,
                 * then a path of the form `/file' (resulting from
                 * input of the form `host:/file') means that we should
-                * do "CWD /" before retreiving the file.  So we set
+                * do "CWD /" before retrieving the file.  So we set
                 * dir="/" and file="file".
                 *
                 * But if we are dealing with URLs like
@@ -1262,7 +1280,8 @@
                        file = dir;
                        dir = NULL;
                }
-       }
+       } else
+               dir = NULL;
        if (urltype == FTP_URL_T && file != NULL) {
                url_decode(file);       
                /* but still don't url_decode(dir) */
@@ -1317,12 +1336,12 @@
                errx(1, "fetch_ftp: unknown transfer type %d\n", type);
        }
 
-                       /*
-                        * Change directories, if necessary.
-                        *
-                        * Note: don't use EMPTYSTRING(dir) below, because
-                        * dir="" means something different from dir=NULL.
-                        */
+               /*
+                * Change directories, if necessary.
+                *
+                * Note: don't use EMPTYSTRING(dir) below, because
+                * dir=="" means something different from dir==NULL.
+                */
        if (dir != NULL && !dirhasglob) {
                char *nextpart;
 
@@ -1341,21 +1360,30 @@
                 * slashes in the path) and RFC 1738 says that we should
                 * still do `CWD ' (with a null argument) in such cases.



Home | Main Index | Thread Index | Old Index