···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 sha256 = "1jcpvl5sxb2ag8yahpy370c5jlfb097a21k2mhsidh4wxdhrnmgy";
11 };
120013 preConfigure = ''
14 for i in "doc/texi2pod.pl" "util/rmold.pl"; do
15 sed -i "$i" -e 's|/usr/bin.*perl|${perl}/bin/perl|g'
···10 sha256 = "1jcpvl5sxb2ag8yahpy370c5jlfb097a21k2mhsidh4wxdhrnmgy";
11 };
1213+ patches = [ ./cve-2016-4971.patch ];
14+15 preConfigure = ''
16 for i in "doc/texi2pod.pl" "util/rmold.pl"; do
17 sed -i "$i" -e 's|/usr/bin.*perl|${perl}/bin/perl|g'