Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)

wget: apply patch for cve-2016-4971 vulnerability

Patch pulled from: https://bugzilla.redhat.com/show_bug.cgi?id=1343666

Backport of #16368.

authored by

Eric Merritt and committed by
Gabriel Ebner
ea170edd 4b6a974a

+295
+293
pkgs/tools/networking/wget/cve-2016-4971.patch
··· 1 + From 07ec1cebc0dfd9e7c18a8aaead89bf72827810aa Mon Sep 17 00:00:00 2001 2 + From: Giuseppe Scrivano <gscrivan@redhat.com> 3 + Date: Mon, 6 Jun 2016 21:20:24 +0200 4 + Subject: [PATCH] ftp: honor --trust-server-names 5 + 6 + If not --trust-server-names is used, FTP will also get the destination 7 + file name from the original url specified by the user instead of the 8 + redirected url. 9 + 10 + * src/ftp.c (ftp_get_listing): Add argument original_url. 11 + (getftp): Likewise. 12 + (ftp_loop_internal): Likewise. Use original_url to generate the 13 + file name if --trust-server-names is not provided. 14 + (ftp_retrieve_glob): Likewise. 15 + (ftp_loop): Likewise. 16 + 17 + Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> 18 + --- 19 + src/ftp.c | 71 +++++++++++++++++++++++++++++++++++++------------------------- 20 + src/ftp.h | 3 ++- 21 + src/retr.c | 3 ++- 22 + 3 files changed, 47 insertions(+), 30 deletions(-) 23 + 24 + diff --git a/src/ftp.c b/src/ftp.c 25 + index cc90c3d..88a9777 100644 26 + --- a/src/ftp.c 27 + +++ b/src/ftp.c 28 + @@ -236,7 +236,7 @@ print_length (wgint size, wgint start, bool authoritative) 29 + logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n"); 30 + } 31 + 32 + -static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **); 33 + +static uerr_t ftp_get_listing (struct url *, struct url *, ccon *, struct fileinfo **); 34 + 35 + static uerr_t 36 + get_ftp_greeting(int csock, ccon *con) 37 + @@ -315,7 +315,8 @@ init_control_ssl_connection (int csock, struct url *u, bool *using_control_secur 38 + and closes the control connection in case of error. If warc_tmp 39 + is non-NULL, the downloaded data will be written there as well. */ 40 + static uerr_t 41 + -getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread, 42 + +getftp (struct url *u, struct url *original_url, 43 + + wgint passed_expected_bytes, wgint *qtyread, 44 + wgint restval, ccon *con, int count, wgint *last_expected_bytes, 45 + FILE *warc_tmp) 46 + { 47 + @@ -1188,7 +1189,7 @@ Error in server response, closing control connection.\n")); 48 + { 49 + bool exists = false; 50 + struct fileinfo *f; 51 + - uerr_t _res = ftp_get_listing (u, con, &f); 52 + + uerr_t _res = ftp_get_listing (u, original_url, con, &f); 53 + /* Set the DO_RETR command flag again, because it gets unset when 54 + calling ftp_get_listing() and would otherwise cause an assertion 55 + failure earlier on when this function gets repeatedly called 56 + @@ -1779,8 +1780,8 @@ exit_error: 57 + This loop either gets commands from con, or (if ON_YOUR_OWN is 58 + set), makes them up to retrieve the file given by the URL. */ 59 + static uerr_t 60 + -ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file, 61 + - bool force_full_retrieve) 62 + +ftp_loop_internal (struct url *u, struct url *original_url, struct fileinfo *f, 63 + + ccon *con, char **local_file, bool force_full_retrieve) 64 + { 65 + int count, orig_lp; 66 + wgint restval, len = 0, qtyread = 0; 67 + @@ -1805,7 +1806,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi 68 + { 69 + /* URL-derived file. Consider "-O file" name. */ 70 + xfree (con->target); 71 + - con->target = url_file_name (u, NULL); 72 + + con->target = url_file_name (opt.trustservernames || !original_url ? u : original_url, NULL); 73 + if (!opt.output_document) 74 + locf = con->target; 75 + else 76 + @@ -1923,8 +1924,8 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi 77 + 78 + /* If we are working on a WARC record, getftp should also write 79 + to the warc_tmp file. */ 80 + - err = getftp (u, len, &qtyread, restval, con, count, &last_expected_bytes, 81 + - warc_tmp); 82 + + err = getftp (u, original_url, len, &qtyread, restval, con, count, 83 + + &last_expected_bytes, warc_tmp); 84 + 85 + if (con->csock == -1) 86 + con->st &= ~DONE_CWD; 87 + @@ -2092,7 +2093,8 @@ Removing file due to --delete-after in ftp_loop_internal():\n")); 88 + /* Return the directory listing in a reusable format. The directory 89 + is specifed in u->dir. */ 90 + static uerr_t 91 + -ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f) 92 + +ftp_get_listing (struct url *u, struct url *original_url, ccon *con, 93 + + struct fileinfo **f) 94 + { 95 + uerr_t err; 96 + char *uf; /* url file name */ 97 + @@ -2113,7 +2115,7 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f) 98 + 99 + con->target = xstrdup (lf); 100 + xfree (lf); 101 + - err = ftp_loop_internal (u, NULL, con, NULL, false); 102 + + err = ftp_loop_internal (u, original_url, NULL, con, NULL, false); 103 + lf = xstrdup (con->target); 104 + xfree (con->target); 105 + con->target = old_target; 106 + @@ -2136,8 +2138,9 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f) 107 + return err; 108 + } 109 + 110 + -static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *); 111 + -static uerr_t ftp_retrieve_glob (struct url *, ccon *, int); 112 + +static uerr_t ftp_retrieve_dirs (struct url *, struct url *, 113 + + struct fileinfo *, ccon *); 114 + +static uerr_t ftp_retrieve_glob (struct url *, struct url *, ccon *, int); 115 + static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **); 116 + static void freefileinfo (struct fileinfo *f); 117 + 118 + @@ -2149,7 +2152,8 @@ static void freefileinfo (struct fileinfo *f); 119 + If opt.recursive is set, after all files have been retrieved, 120 + ftp_retrieve_dirs will be called to retrieve the directories. */ 121 + static uerr_t 122 + -ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con) 123 + +ftp_retrieve_list (struct url *u, struct url *original_url, 124 + + struct fileinfo *f, ccon *con) 125 + { 126 + static int depth = 0; 127 + uerr_t err; 128 + @@ -2310,7 +2314,10 @@ Already have correct symlink %s -> %s\n\n"), 129 + else /* opt.retr_symlinks */ 130 + { 131 + if (dlthis) 132 + - err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve); 133 + + { 134 + + err = ftp_loop_internal (u, original_url, f, con, NULL, 135 + + force_full_retrieve); 136 + + } 137 + } /* opt.retr_symlinks */ 138 + break; 139 + case FT_DIRECTORY: 140 + @@ -2321,7 +2328,10 @@ Already have correct symlink %s -> %s\n\n"), 141 + case FT_PLAINFILE: 142 + /* Call the retrieve loop. */ 143 + if (dlthis) 144 + - err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve); 145 + + { 146 + + err = ftp_loop_internal (u, original_url, f, con, NULL, 147 + + force_full_retrieve); 148 + + } 149 + break; 150 + case FT_UNKNOWN: 151 + logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"), 152 + @@ -2386,7 +2396,7 @@ Already have correct symlink %s -> %s\n\n"), 153 + /* We do not want to call ftp_retrieve_dirs here */ 154 + if (opt.recursive && 155 + !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel)) 156 + - err = ftp_retrieve_dirs (u, orig, con); 157 + + err = ftp_retrieve_dirs (u, original_url, orig, con); 158 + else if (opt.recursive) 159 + DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"), 160 + depth, opt.reclevel)); 161 + @@ -2399,7 +2409,8 @@ Already have correct symlink %s -> %s\n\n"), 162 + ftp_retrieve_glob on each directory entry. The function knows 163 + about excluded directories. */ 164 + static uerr_t 165 + -ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con) 166 + +ftp_retrieve_dirs (struct url *u, struct url *original_url, 167 + + struct fileinfo *f, ccon *con) 168 + { 169 + char *container = NULL; 170 + int container_size = 0; 171 + @@ -2449,7 +2460,7 @@ Not descending to %s as it is excluded/not-included.\n"), 172 + odir = xstrdup (u->dir); /* because url_set_dir will free 173 + u->dir. */ 174 + url_set_dir (u, newdir); 175 + - ftp_retrieve_glob (u, con, GLOB_GETALL); 176 + + ftp_retrieve_glob (u, original_url, con, GLOB_GETALL); 177 + url_set_dir (u, odir); 178 + xfree (odir); 179 + 180 + @@ -2508,14 +2519,15 @@ is_invalid_entry (struct fileinfo *f) 181 + GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole 182 + directory. */ 183 + static uerr_t 184 + -ftp_retrieve_glob (struct url *u, ccon *con, int action) 185 + +ftp_retrieve_glob (struct url *u, struct url *original_url, 186 + + ccon *con, int action) 187 + { 188 + struct fileinfo *f, *start; 189 + uerr_t res; 190 + 191 + con->cmd |= LEAVE_PENDING; 192 + 193 + - res = ftp_get_listing (u, con, &start); 194 + + res = ftp_get_listing (u, original_url, con, &start); 195 + if (res != RETROK) 196 + return res; 197 + /* First: weed out that do not conform the global rules given in 198 + @@ -2611,7 +2623,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) 199 + if (start) 200 + { 201 + /* Just get everything. */ 202 + - res = ftp_retrieve_list (u, start, con); 203 + + res = ftp_retrieve_list (u, original_url, start, con); 204 + } 205 + else 206 + { 207 + @@ -2627,7 +2639,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) 208 + { 209 + /* Let's try retrieving it anyway. */ 210 + con->st |= ON_YOUR_OWN; 211 + - res = ftp_loop_internal (u, NULL, con, NULL, false); 212 + + res = ftp_loop_internal (u, original_url, NULL, con, NULL, false); 213 + return res; 214 + } 215 + 216 + @@ -2647,8 +2659,8 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) 217 + of URL. Inherently, its capabilities are limited on what can be 218 + encoded into a URL. */ 219 + uerr_t 220 + -ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, 221 + - bool recursive, bool glob) 222 + +ftp_loop (struct url *u, struct url *original_url, char **local_file, int *dt, 223 + + struct url *proxy, bool recursive, bool glob) 224 + { 225 + ccon con; /* FTP connection */ 226 + uerr_t res; 227 + @@ -2669,16 +2681,17 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, 228 + if (!*u->file && !recursive) 229 + { 230 + struct fileinfo *f; 231 + - res = ftp_get_listing (u, &con, &f); 232 + + res = ftp_get_listing (u, original_url, &con, &f); 233 + 234 + if (res == RETROK) 235 + { 236 + if (opt.htmlify && !opt.spider) 237 + { 238 + + struct url *url_file = opt.trustservernames ? u : original_url; 239 + char *filename = (opt.output_document 240 + ? xstrdup (opt.output_document) 241 + : (con.target ? xstrdup (con.target) 242 + - : url_file_name (u, NULL))); 243 + + : url_file_name (url_file, NULL))); 244 + res = ftp_index (filename, u, f); 245 + if (res == FTPOK && opt.verbose) 246 + { 247 + @@ -2723,11 +2736,13 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, 248 + /* ftp_retrieve_glob is a catch-all function that gets called 249 + if we need globbing, time-stamping, recursion or preserve 250 + permissions. Its third argument is just what we really need. */ 251 + - res = ftp_retrieve_glob (u, &con, 252 + + res = ftp_retrieve_glob (u, original_url, &con, 253 + ispattern ? GLOB_GLOBALL : GLOB_GETONE); 254 + } 255 + else 256 + - res = ftp_loop_internal (u, NULL, &con, local_file, false); 257 + + { 258 + + res = ftp_loop_internal (u, original_url, NULL, &con, local_file, false); 259 + + } 260 + } 261 + if (res == FTPOK) 262 + res = RETROK; 263 + diff --git a/src/ftp.h b/src/ftp.h 264 + index 84ded26..f02e377 100644 265 + --- a/src/ftp.h 266 + +++ b/src/ftp.h 267 + @@ -169,7 +169,8 @@ enum wget_ftp_fstatus 268 + }; 269 + 270 + struct fileinfo *ftp_parse_ls (const char *, const enum stype); 271 + -uerr_t ftp_loop (struct url *, char **, int *, struct url *, bool, bool); 272 + +uerr_t ftp_loop (struct url *, struct url *, char **, int *, struct url *, 273 + + bool, bool); 274 + 275 + uerr_t ftp_index (const char *, struct url *, struct fileinfo *); 276 + 277 + diff --git a/src/retr.c b/src/retr.c 278 + index ddd46cb..074283a 100644 279 + --- a/src/retr.c 280 + +++ b/src/retr.c 281 + @@ -830,7 +830,8 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file, 282 + if (redirection_count) 283 + oldrec = glob = false; 284 + 285 + - result = ftp_loop (u, &local_file, dt, proxy_url, recursive, glob); 286 + + result = ftp_loop (u, orig_parsed, &local_file, dt, proxy_url, 287 + + recursive, glob); 288 + recursive = oldrec; 289 + 290 + /* There is a possibility of having HTTP being redirected to 291 + -- 292 + 2.5.5 293 +
+2
pkgs/tools/networking/wget/default.nix
··· 10 10 sha256 = "1jcpvl5sxb2ag8yahpy370c5jlfb097a21k2mhsidh4wxdhrnmgy"; 11 11 }; 12 12 13 + patches = [ ./cve-2016-4971.patch ]; 14 + 13 15 preConfigure = '' 14 16 for i in "doc/texi2pod.pl" "util/rmold.pl"; do 15 17 sed -i "$i" -e 's|/usr/bin.*perl|${perl}/bin/perl|g'