File wget-do-not-propagate-credentials.patch of Package wget.37321
From 6a023c8a63cb87020826b62e834da5d6760b9029 Mon Sep 17 00:00:00 2001
From: vlefebvre <valentin.lefebvre@suse.com>
Date: Wed, 4 Dec 2024 18:18:41 +0100
Subject: [PATCH] Discard Authentication and Cookie header
* src/http.c: (unredirectable_headerline) check if a header line is
included in a list of value that cannot be sent after a redirect.
* src/http.c: (get_http) Do not set user header, when
location_changed, from unredirectable_headerline.
* src/http.h: (http_loop) Add argument location_changed.
Fix CVE-2021-31879. If wget for an http URL is redirected to a
different site (hostnameparts of URLs differ), then any "Authenticate" and
"Cookie" header entries are discarded.
Signed-off-by: vlefebvre <valentin.lefebvre@suse.com>
---
src/http.c | 42 ++++++++++++++++++++++++++++++++++++++----
src/http.h | 2 +-
src/retr.c | 4 ++--
3 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/src/http.c b/src/http.c
index 07af1867..383321cb 100644
--- a/src/http.c
+++ b/src/http.c
@@ -3149,6 +3149,31 @@ fail:
}
#endif /* HAVE_METALINK */
+/*
+ * Check if the corresponding header line should not
+ * be sent after a redirect
+ */
+static bool
+unredirectable_headerline(char *line)
+{
+ static const struct {
+ size_t len;
+ const char *name;
+ } field_name[] = {
+ { 14, "Authorization:" },
+ { 7, "Cookie:" }
+ };
+
+ /*
+ * Note: According to RFC 2616, Field names are case-insensitive.
+ */
+ for (unsigned i = 0; i < countof(field_name); i++)
+ if (c_strncasecmp(line, field_name[i].name, field_name[i].len) == 0)
+ return true;
+
+ return false;
+}
+
/* Retrieve a document through HTTP protocol. It recognizes status
code, and correctly handles redirections. It closes the network
socket. If it receives an error from the functions below it, it
@@ -3161,7 +3186,7 @@ fail:
server, and u->url will be requested. */
static uerr_t
gethttp (const struct url *u, struct url *original_url, struct http_stat *hs,
- int *dt, struct url *proxy, struct iri *iri, int count)
+ int *dt, struct url *proxy, struct iri *iri, int count, bool location_changed)
{
struct request *req = NULL;
@@ -3305,7 +3330,16 @@ gethttp (const struct url *u, struct url *original_url, struct http_stat *hs,
{
int i;
for (i = 0; opt.user_headers[i]; i++)
- request_set_user_header (req, opt.user_headers[i]);
+ {
+ /*
+ * IF we have been redirected
+ * AND the user-supplied header line should NOT be sent to the new host
+ * DO NOT append that header line
+ */
+ if (location_changed && unredirectable_headerline(opt.user_headers[i]))
+ continue;
+ request_set_user_header (req, opt.user_headers[i]);
+ }
}
proxyauth = NULL;
@@ -4230,7 +4264,7 @@ check_retry_on_http_error (const int statcode)
uerr_t
http_loop (const struct url *u, struct url *original_url, char **newloc,
char **local_file, const char *referer, int *dt, struct url *proxy,
- struct iri *iri)
+ struct iri *iri, bool location_changed)
{
int count;
bool got_head = false; /* used for time-stamping and filename detection */
@@ -4417,7 +4451,7 @@ http_loop (const struct url *u, struct url *original_url, char **newloc,
*dt &= ~SEND_NOCACHE;
/* Try fetching the document, or at least its head. */
- err = gethttp (u, original_url, &hstat, dt, proxy, iri, count);
+ err = gethttp (u, original_url, &hstat, dt, proxy, iri, count, location_changed);
/* Time? */
tms = datetime_str (time (NULL));
diff --git a/src/http.h b/src/http.h
index 570f7683..55f9b82f 100644
--- a/src/http.h
+++ b/src/http.h
@@ -36,7 +36,7 @@ as that of the covered work. */
struct url;
uerr_t http_loop (const struct url *, struct url *, char **, char **, const char *,
- int *, struct url *, struct iri *);
+ int *, struct url *, struct iri *, bool);
void save_cookies (void);
void http_cleanup (void);
time_t http_atotm (const char *);
diff --git a/src/retr.c b/src/retr.c
index 26eb9f17..3d82a44a 100644
--- a/src/retr.c
+++ b/src/retr.c
@@ -874,7 +874,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
{
uerr_t result;
char *url;
- bool location_changed;
+ bool location_changed = 0;
bool iri_fallbacked = 0;
int dummy;
char *mynewloc, *proxy;
@@ -971,7 +971,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
}
#endif
result = http_loop (u, orig_parsed, &mynewloc, &local_file, refurl, dt,
- proxy_url, iri);
+ proxy_url, iri, location_changed);
}
else if (u->scheme == SCHEME_FTP
#ifdef HAVE_SSL
--
2.43.0