From 3e25a9817f47fbb8660cc6a3b2f3eea239526c6c Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 28 Jul 2010 21:22:22 +0200 Subject: [PATCH] Introduce --trust-server-names. Close CVE-2010-2252. --- NEWS | 3 +++ doc/wget.texi | 11 +++++++++++ src/ChangeLog | 15 +++++++++++++++ src/ftp.c | 2 +- src/http.c | 18 ++++++++++-------- src/http.h | 4 ++-- src/init.c | 1 + src/main.c | 3 +++ src/options.h | 1 + src/retr.c | 3 ++- 10 files changed, 49 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 899807e4..d4a98037 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,9 @@ Please send GNU Wget bug reports to . ** GNU TLS backend works again. ** Now --timestamping and --continue works well together. + +** By default, on server redirects, use the original URL to get the + local file name. Close CVE-2010-2252. * Changes in Wget 1.12 diff --git a/doc/wget.texi b/doc/wget.texi index d5eaf4e5..627e0059 100644 --- a/doc/wget.texi +++ b/doc/wget.texi @@ -1498,6 +1498,13 @@ This option is useful for some file-downloading CGI programs that use @code{Content-Disposition} headers to describe what the name of a downloaded file should be. +@cindex Trust server names +@item --trust-server-names + +If this is set to on, on a redirect the last component of the +redirection URL will be used as the local file name. By default it is +used the last component in the original URL. + @cindex authentication @item --auth-no-challenge @@ -2810,6 +2817,10 @@ Set the connect timeout---the same as @samp{--connect-timeout}. Turn on recognition of the (non-standard) @samp{Content-Disposition} HTTP header---if set to @samp{on}, the same as @samp{--content-disposition}. +@item trust_server_names = on/off +If set to on, use the last component of a redirection URL for the local +file name. + @item continue = on/off If set to on, force continuation of preexistent partially retrieved files. See @samp{-c} before setting it. diff --git a/src/ChangeLog b/src/ChangeLog index 5c8dea7a..60e82d94 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2010-07-28 Giuseppe Scrivano + + * http.h (http_loop): Add new argument `original_url' + * http.c (http_loop): Add new argument `original_url'. Use + `original_url' to get a filename if `trustservernames' is false. + + * init.c (commands): Add "trustservernames". + + * options.h (library): Add variable `trustservernames'. + + * main.c (option_data): Add trust-server-names. + (print_help): Describe --trust-server-names. + + * retr.c (retrieve_url): Pass new argument to `http_loop'. + 2010-07-20 Alan Jenkins (tiny change) * http.c (gethttp): Check content-length was set before trying to diff --git a/src/ftp.c b/src/ftp.c index 42b0671e..93953690 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -2137,7 +2137,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) of URL. Inherently, its capabilities are limited on what can be encoded into a URL. */ uerr_t -ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, +ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, bool recursive, bool glob) { ccon con; /* FTP connection */ diff --git a/src/http.c b/src/http.c index 1c1e165c..67952967 100644 --- a/src/http.c +++ b/src/http.c @@ -2593,8 +2593,9 @@ File %s already there; not retrieving.\n\n"), quote (hs->local_file)); /* The genuine HTTP loop! This is the part where the retrieval is retried, and retried, and retried, and... */ uerr_t -http_loop (struct url *u, char **newloc, char **local_file, const char *referer, - int *dt, struct url *proxy, struct iri *iri) +http_loop (struct url *u, struct url *original_url, char **newloc, + char **local_file, const char *referer, int *dt, struct url *proxy, + struct iri *iri) { int count; bool got_head = false; /* used for time-stamping and filename detection */ @@ -2641,7 +2642,8 @@ http_loop (struct url *u, char **newloc, char **local_file, const char *referer, } else if (!opt.content_disposition) { - hstat.local_file = url_file_name (u); + hstat.local_file = + url_file_name (opt.trustservernames ? u : original_url); got_name = true; } @@ -2679,7 +2681,7 @@ File %s already there; not retrieving.\n\n"), /* Send preliminary HEAD request if -N is given and we have an existing * destination file. */ - file_name = url_file_name (u); + file_name = url_file_name (opt.trustservernames ? u : original_url); if (opt.timestamping && (file_exists_p (file_name) || opt.content_disposition)) send_head_first = true; @@ -3039,9 +3041,9 @@ Remote file exists.\n\n")); /* Remember that we downloaded the file for later ".orig" code. */ if (*dt & ADDED_HTML_EXTENSION) - downloaded_file(FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); + downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); else - downloaded_file(FILE_DOWNLOADED_NORMALLY, hstat.local_file); + downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file); ret = RETROK; goto exit; @@ -3072,9 +3074,9 @@ Remote file exists.\n\n")); /* Remember that we downloaded the file for later ".orig" code. */ if (*dt & ADDED_HTML_EXTENSION) - downloaded_file(FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); + downloaded_file (FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, hstat.local_file); else - downloaded_file(FILE_DOWNLOADED_NORMALLY, hstat.local_file); + downloaded_file (FILE_DOWNLOADED_NORMALLY, hstat.local_file); ret = RETROK; goto exit; diff --git a/src/http.h b/src/http.h index 293b82e4..1b923ebb 100644 --- a/src/http.h +++ b/src/http.h @@ -33,8 +33,8 @@ as that of the covered work. */ struct url; -uerr_t http_loop (struct url *, char **, char **, const char *, int *, - struct url *, struct iri *); +uerr_t http_loop (struct url *, struct url *, char **, char **, const char *, + int *, struct url *, struct iri *); void save_cookies (void); void http_cleanup (void); time_t http_atotm (const char *); diff --git a/src/init.c b/src/init.c index e3e7af21..22394d11 100644 --- a/src/init.c +++ b/src/init.c @@ -252,6 +252,7 @@ static const struct { { "timeout", NULL, cmd_spec_timeout }, { "timestamping", &opt.timestamping, cmd_boolean }, { "tries", &opt.ntry, cmd_number_inf }, + { "trustservernames", &opt.trustservernames, cmd_boolean }, { "useproxy", &opt.use_proxy, cmd_boolean }, { "user", &opt.user, cmd_string }, { "useragent", NULL, cmd_spec_useragent }, diff --git a/src/main.c b/src/main.c index 3a241fbb..5f40897a 100644 --- a/src/main.c +++ b/src/main.c @@ -266,6 +266,7 @@ static struct cmdline_option option_data[] = { "timeout", 'T', OPT_VALUE, "timeout", -1 }, { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 }, { "tries", 't', OPT_VALUE, "tries", -1 }, + { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 }, { "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 }, { "user", 0, OPT_VALUE, "user", -1 }, { "user-agent", 'U', OPT_VALUE, "useragent", -1 }, @@ -680,6 +681,8 @@ Recursive accept/reject:\n"), N_("\ -I, --include-directories=LIST list of allowed directories.\n"), N_("\ + --trust-server-names use the name specified by the redirection url last component.\n"), + N_("\ -X, --exclude-directories=LIST list of excluded directories.\n"), N_("\ -np, --no-parent don't ascend to the parent directory.\n"), diff --git a/src/options.h b/src/options.h index 07872ec1..9fbedb78 100644 --- a/src/options.h +++ b/src/options.h @@ -242,6 +242,7 @@ struct options char *encoding_remote; char *locale; + bool trustservernames; #ifdef __VMS int ftp_stmlf; /* Force Stream_LF format for binary FTP. */ #endif /* def __VMS */ diff --git a/src/retr.c b/src/retr.c index 911117b7..0604f681 100644 --- a/src/retr.c +++ b/src/retr.c @@ -731,7 +731,8 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file, #endif || (proxy_url && proxy_url->scheme == SCHEME_HTTP)) { - result = http_loop (u, &mynewloc, &local_file, refurl, dt, proxy_url, iri); + result = http_loop (u, orig_parsed, &mynewloc, &local_file, refurl, dt, + proxy_url, iri); } else if (u->scheme == SCHEME_FTP) { -- 2.39.2