Blame SOURCES/wget-1.14-CVE-2016-4971.patch

87e294
diff --git a/src/ftp.c b/src/ftp.c
87e294
index 2be2c76..345718f 100644
87e294
--- a/src/ftp.c
87e294
+++ b/src/ftp.c
87e294
@@ -234,14 +234,15 @@ print_length (wgint size, wgint start, bool authoritative)
87e294
   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
87e294
 }
87e294
 
87e294
-static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
87e294
+static uerr_t ftp_get_listing (struct url *, struct url *, ccon *, struct fileinfo **);
87e294
 
87e294
 /* Retrieves a file with denoted parameters through opening an FTP
87e294
    connection to the server.  It always closes the data connection,
87e294
    and closes the control connection in case of error.  If warc_tmp
87e294
    is non-NULL, the downloaded data will be written there as well.  */
87e294
 static uerr_t
87e294
-getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
87e294
+getftp (struct url *u, struct url *original_url,
87e294
+        wgint passed_expected_bytes, wgint *qtyread,
87e294
         wgint restval, ccon *con, int count, FILE *warc_tmp)
87e294
 {
87e294
   int csock, dtsock, local_sock, res;
87e294
@@ -944,7 +945,7 @@ Error in server response, closing control connection.\n"));
87e294
 	  bool exists = false;
87e294
 	  uerr_t res;
87e294
 	  struct fileinfo *f;
87e294
-	  res = ftp_get_listing (u, con, &f);
87e294
+	  res = ftp_get_listing (u, original_url, con, &f);
87e294
 	  /* Set the DO_RETR command flag again, because it gets unset when
87e294
 	     calling ftp_get_listing() and would otherwise cause an assertion
87e294
 	     failure earlier on when this function gets repeatedly called
87e294
@@ -1392,7 +1393,8 @@ Error in server response, closing control connection.\n"));
87e294
    This loop either gets commands from con, or (if ON_YOUR_OWN is
87e294
    set), makes them up to retrieve the file given by the URL.  */
87e294
 static uerr_t
87e294
-ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
87e294
+ftp_loop_internal (struct url *u, struct url *original_url, struct fileinfo *f,
87e294
+        ccon *con, char **local_file)
87e294
 {
87e294
   int count, orig_lp;
87e294
   wgint restval, len = 0, qtyread = 0;
87e294
@@ -1415,7 +1417,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
87e294
   else
87e294
     {
87e294
       /* URL-derived file.  Consider "-O file" name. */
87e294
-      con->target = url_file_name (u, NULL);
87e294
+      con->target = url_file_name (opt.trustservernames || !original_url ? u : original_url, NULL);
87e294
       if (!opt.output_document)
87e294
         locf = con->target;
87e294
       else
87e294
@@ -1524,7 +1526,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
87e294
 
87e294
       /* If we are working on a WARC record, getftp should also write
87e294
          to the warc_tmp file. */
87e294
-      err = getftp (u, len, &qtyread, restval, con, count, warc_tmp);
87e294
+      err = getftp (u, original_url, len, &qtyread, restval, con, count, warc_tmp);
87e294
 
87e294
       if (con->csock == -1)
87e294
         con->st &= ~DONE_CWD;
87e294
@@ -1677,7 +1679,8 @@ Removing file due to --delete-after in ftp_loop_internal():\n"));
87e294
 /* Return the directory listing in a reusable format.  The directory
87e294
    is specifed in u->dir.  */
87e294
 static uerr_t
87e294
-ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
87e294
+ftp_get_listing (struct url *u, struct url *original_url, ccon *con,
87e294
+                 struct fileinfo **f)
87e294
 {
87e294
   uerr_t err;
87e294
   char *uf;                     /* url file name */
87e294
@@ -1698,7 +1701,7 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
87e294
 
87e294
   con->target = xstrdup (lf);
87e294
   xfree (lf);
87e294
-  err = ftp_loop_internal (u, NULL, con, NULL);
87e294
+  err = ftp_loop_internal (u, original_url, NULL, con, NULL);
87e294
   lf = xstrdup (con->target);
87e294
   xfree (con->target);
87e294
   con->target = old_target;
87e294
@@ -1721,8 +1724,9 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
87e294
   return err;
87e294
 }
87e294
 
87e294
-static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
87e294
-static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
87e294
+static uerr_t ftp_retrieve_dirs (struct url *, struct url *,
87e294
+                                 struct fileinfo *, ccon *);
87e294
+static uerr_t ftp_retrieve_glob (struct url *, struct url *, ccon *, int);
87e294
 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
87e294
 static void freefileinfo (struct fileinfo *f);
87e294
 
87e294
@@ -1734,7 +1738,8 @@ static void freefileinfo (struct fileinfo *f);
87e294
    If opt.recursive is set, after all files have been retrieved,
87e294
    ftp_retrieve_dirs will be called to retrieve the directories.  */
87e294
 static uerr_t
87e294
-ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
87e294
+ftp_retrieve_list (struct url *u, struct url *original_url,
87e294
+                   struct fileinfo *f, ccon *con)
87e294
 {
87e294
   static int depth = 0;
87e294
   uerr_t err;
87e294
@@ -1893,7 +1898,9 @@ Already have correct symlink %s -> %s\n\n"),
87e294
           else                /* opt.retr_symlinks */
87e294
             {
87e294
               if (dlthis)
87e294
-                err = ftp_loop_internal (u, f, con, NULL);
87e294
+                {
87e294
+                  err = ftp_loop_internal (u, original_url, f, con, NULL);
87e294
+                }
87e294
             } /* opt.retr_symlinks */
87e294
           break;
87e294
         case FT_DIRECTORY:
87e294
@@ -1904,7 +1911,9 @@ Already have correct symlink %s -> %s\n\n"),
87e294
         case FT_PLAINFILE:
87e294
           /* Call the retrieve loop.  */
87e294
           if (dlthis)
87e294
-            err = ftp_loop_internal (u, f, con, NULL);
87e294
+            {
87e294
+              err = ftp_loop_internal (u, original_url, f, con, NULL);
87e294
+            }
87e294
           break;
87e294
         case FT_UNKNOWN:
87e294
           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
87e294
@@ -1969,7 +1978,7 @@ Already have correct symlink %s -> %s\n\n"),
87e294
   /* We do not want to call ftp_retrieve_dirs here */
87e294
   if (opt.recursive &&
87e294
       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
87e294
-    err = ftp_retrieve_dirs (u, orig, con);
87e294
+    err = ftp_retrieve_dirs (u, original_url, orig, con);
87e294
   else if (opt.recursive)
87e294
     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
87e294
              depth, opt.reclevel));
87e294
@@ -1982,7 +1991,8 @@ Already have correct symlink %s -> %s\n\n"),
87e294
    ftp_retrieve_glob on each directory entry.  The function knows
87e294
    about excluded directories.  */
87e294
 static uerr_t
87e294
-ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
87e294
+ftp_retrieve_dirs (struct url *u, struct url *original_url,
87e294
+                   struct fileinfo *f, ccon *con)
87e294
 {
87e294
   char *container = NULL;
87e294
   int container_size = 0;
87e294
@@ -2032,7 +2042,7 @@ Not descending to %s as it is excluded/not-included.\n"),
87e294
       odir = xstrdup (u->dir);  /* because url_set_dir will free
87e294
                                    u->dir. */
87e294
       url_set_dir (u, newdir);
87e294
-      ftp_retrieve_glob (u, con, GLOB_GETALL);
87e294
+      ftp_retrieve_glob (u, original_url, con, GLOB_GETALL);
87e294
       url_set_dir (u, odir);
87e294
       xfree (odir);
87e294
 
87e294
@@ -2091,14 +2101,15 @@ is_invalid_entry (struct fileinfo *f)
87e294
    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
87e294
    directory.  */
87e294
 static uerr_t
87e294
-ftp_retrieve_glob (struct url *u, ccon *con, int action)
87e294
+ftp_retrieve_glob (struct url *u, struct url *original_url,
87e294
+                   ccon *con, int action)
87e294
 {
87e294
   struct fileinfo *f, *start;
87e294
   uerr_t res;
87e294
 
87e294
   con->cmd |= LEAVE_PENDING;
87e294
 
87e294
-  res = ftp_get_listing (u, con, &start;;
87e294
+  res = ftp_get_listing (u, original_url, con, &start;;
87e294
   if (res != RETROK)
87e294
     return res;
87e294
   /* First: weed out that do not conform the global rules given in
87e294
@@ -2194,7 +2205,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
87e294
   if (start)
87e294
     {
87e294
       /* Just get everything.  */
87e294
-      res = ftp_retrieve_list (u, start, con);
87e294
+      res = ftp_retrieve_list (u, original_url, start, con);
87e294
     }
87e294
   else
87e294
     {
87e294
@@ -2210,7 +2221,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
87e294
         {
87e294
           /* Let's try retrieving it anyway.  */
87e294
           con->st |= ON_YOUR_OWN;
87e294
-          res = ftp_loop_internal (u, NULL, con, NULL);
87e294
+          res = ftp_loop_internal (u, original_url, NULL, con, NULL);
87e294
           return res;
87e294
         }
87e294
 
87e294
@@ -2230,8 +2241,8 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
87e294
    of URL.  Inherently, its capabilities are limited on what can be
87e294
    encoded into a URL.  */
87e294
 uerr_t
87e294
-ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
87e294
-          bool recursive, bool glob)
87e294
+ftp_loop (struct url *u, struct url *original_url, char **local_file, int *dt,
87e294
+          struct url *proxy, bool recursive, bool glob)
87e294
 {
87e294
   ccon con;                     /* FTP connection */
87e294
   uerr_t res;
87e294
@@ -2252,16 +2263,17 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
87e294
   if (!*u->file && !recursive)
87e294
     {
87e294
       struct fileinfo *f;
87e294
-      res = ftp_get_listing (u, &con, &f);
87e294
+      res = ftp_get_listing (u, original_url, &con, &f);
87e294
 
87e294
       if (res == RETROK)
87e294
         {
87e294
           if (opt.htmlify && !opt.spider)
87e294
             {
87e294
+              struct url *url_file = opt.trustservernames ? u : original_url;
87e294
               char *filename = (opt.output_document
87e294
                                 ? xstrdup (opt.output_document)
87e294
                                 : (con.target ? xstrdup (con.target)
87e294
-                                   : url_file_name (u, NULL)));
87e294
+                                   : url_file_name (url_file, NULL)));
87e294
               res = ftp_index (filename, u, f);
87e294
               if (res == FTPOK && opt.verbose)
87e294
                 {
87e294
@@ -2306,11 +2318,13 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
87e294
           /* ftp_retrieve_glob is a catch-all function that gets called
87e294
              if we need globbing, time-stamping, recursion or preserve
87e294
              permissions.  Its third argument is just what we really need.  */
87e294
-          res = ftp_retrieve_glob (u, &con,
87e294
+          res = ftp_retrieve_glob (u, original_url, &con,
87e294
                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
87e294
         }
87e294
       else
87e294
-        res = ftp_loop_internal (u, NULL, &con, local_file);
87e294
+        {
87e294
+          res = ftp_loop_internal (u, original_url, NULL, &con, local_file);
87e294
+        }
87e294
     }
87e294
   if (res == FTPOK)
87e294
     res = RETROK;
87e294
diff --git a/src/ftp.h b/src/ftp.h
87e294
index be00d88..2abc9c0 100644
87e294
--- a/src/ftp.h
87e294
+++ b/src/ftp.h
87e294
@@ -129,7 +129,8 @@ enum wget_ftp_fstatus
87e294
 };
87e294
 
87e294
 struct fileinfo *ftp_parse_ls (const char *, const enum stype);
87e294
-uerr_t ftp_loop (struct url *, char **, int *, struct url *, bool, bool);
87e294
+uerr_t ftp_loop (struct url *, struct url *, char **, int *, struct url *,
87e294
+                 bool, bool);
87e294
 
87e294
 uerr_t ftp_index (const char *, struct url *, struct fileinfo *);
87e294
 
87e294
diff --git a/src/retr.c b/src/retr.c
87e294
index 66624dc..21fad56 100644
87e294
--- a/src/retr.c
87e294
+++ b/src/retr.c
87e294
@@ -794,7 +794,8 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
87e294
       if (redirection_count)
87e294
         oldrec = glob = false;
87e294
 
87e294
-      result = ftp_loop (u, &local_file, dt, proxy_url, recursive, glob);
87e294
+      result = ftp_loop (u, orig_parsed, &local_file, dt, proxy_url,
87e294
+                         recursive, glob);
87e294
       recursive = oldrec;
87e294
 
87e294
       /* There is a possibility of having HTTP being redirected to