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

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