mirror of
https://git.yoctoproject.org/git/poky
synced 2026-01-01 13:58:04 +00:00
wget: Security fix CVE-2016-4971
affects wget < 1.18.0 (From OE-Core rev: 15b6586ae64f745777ba5c42f4cf055aeeed83d8) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
8f62c3dc44
commit
661aff850e
294
meta/recipes-extended/wget/wget/CVE-2016-4971.patch
Normal file
294
meta/recipes-extended/wget/wget/CVE-2016-4971.patch
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
From e996e322ffd42aaa051602da182d03178d0f13e1 Mon Sep 17 00:00:00 2001
|
||||
From: Giuseppe Scrivano <gscrivan@redhat.com>
|
||||
Date: Mon, 6 Jun 2016 21:20:24 +0200
|
||||
Subject: [PATCH] ftp: understand --trust-server-names on a HTTP->FTP redirect
|
||||
|
||||
If not --trust-server-names is used, FTP will also get the destination
|
||||
file name from the original url specified by the user instead of the
|
||||
redirected url. Closes CVE-2016-4971.
|
||||
|
||||
* src/ftp.c (ftp_get_listing): Add argument original_url.
|
||||
(getftp): Likewise.
|
||||
(ftp_loop_internal): Likewise. Use original_url to generate the
|
||||
file name if --trust-server-names is not provided.
|
||||
(ftp_retrieve_glob): Likewise.
|
||||
(ftp_loop): Likewise.
|
||||
|
||||
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
|
||||
|
||||
Upstream-Status: Backport
|
||||
CVE: CVE-2016-4971
|
||||
Signed-off-by: Armin Kuster <akuster@mvista.com>
|
||||
|
||||
---
|
||||
src/ftp.c | 71 +++++++++++++++++++++++++++++++++++++-------------------------
|
||||
src/ftp.h | 3 ++-
|
||||
src/retr.c | 3 ++-
|
||||
3 files changed, 47 insertions(+), 30 deletions(-)
|
||||
|
||||
Index: wget-1.16.3/src/ftp.c
|
||||
===================================================================
|
||||
--- wget-1.16.3.orig/src/ftp.c
|
||||
+++ wget-1.16.3/src/ftp.c
|
||||
@@ -235,14 +235,15 @@ print_length (wgint size, wgint start, b
|
||||
logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
|
||||
}
|
||||
|
||||
-static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
|
||||
+static uerr_t ftp_get_listing (struct url *, struct url *, ccon *, struct fileinfo **);
|
||||
|
||||
/* Retrieves a file with denoted parameters through opening an FTP
|
||||
connection to the server. It always closes the data connection,
|
||||
and closes the control connection in case of error. If warc_tmp
|
||||
is non-NULL, the downloaded data will be written there as well. */
|
||||
static uerr_t
|
||||
-getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
|
||||
+getftp (struct url *u, struct url *original_url,
|
||||
+ wgint passed_expected_bytes, wgint *qtyread,
|
||||
wgint restval, ccon *con, int count, wgint *last_expected_bytes,
|
||||
FILE *warc_tmp)
|
||||
{
|
||||
@@ -996,7 +997,7 @@ Error in server response, closing contro
|
||||
{
|
||||
bool exists = false;
|
||||
struct fileinfo *f;
|
||||
- uerr_t _res = ftp_get_listing (u, con, &f);
|
||||
+ uerr_t _res = ftp_get_listing (u, original_url, con, &f);
|
||||
/* Set the DO_RETR command flag again, because it gets unset when
|
||||
calling ftp_get_listing() and would otherwise cause an assertion
|
||||
failure earlier on when this function gets repeatedly called
|
||||
@@ -1540,8 +1541,8 @@ Error in server response, closing contro
|
||||
This loop either gets commands from con, or (if ON_YOUR_OWN is
|
||||
set), makes them up to retrieve the file given by the URL. */
|
||||
static uerr_t
|
||||
-ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file,
|
||||
- bool force_full_retrieve)
|
||||
+ftp_loop_internal (struct url *u, struct url *original_url, struct fileinfo *f,
|
||||
+ ccon *con, char **local_file, bool force_full_retrieve)
|
||||
{
|
||||
int count, orig_lp;
|
||||
wgint restval, len = 0, qtyread = 0;
|
||||
@@ -1566,7 +1567,7 @@ ftp_loop_internal (struct url *u, struct
|
||||
{
|
||||
/* URL-derived file. Consider "-O file" name. */
|
||||
xfree (con->target);
|
||||
- con->target = url_file_name (u, NULL);
|
||||
+ con->target = url_file_name (opt.trustservernames || !original_url ? u : original_url, NULL);
|
||||
if (!opt.output_document)
|
||||
locf = con->target;
|
||||
else
|
||||
@@ -1684,8 +1685,8 @@ ftp_loop_internal (struct url *u, struct
|
||||
|
||||
/* If we are working on a WARC record, getftp should also write
|
||||
to the warc_tmp file. */
|
||||
- err = getftp (u, len, &qtyread, restval, con, count, &last_expected_bytes,
|
||||
- warc_tmp);
|
||||
+ err = getftp (u, original_url, len, &qtyread, restval, con, count,
|
||||
+ &last_expected_bytes, warc_tmp);
|
||||
|
||||
if (con->csock == -1)
|
||||
con->st &= ~DONE_CWD;
|
||||
@@ -1838,7 +1839,8 @@ Removing file due to --delete-after in f
|
||||
/* Return the directory listing in a reusable format. The directory
|
||||
is specifed in u->dir. */
|
||||
static uerr_t
|
||||
-ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
|
||||
+ftp_get_listing (struct url *u, struct url *original_url, ccon *con,
|
||||
+ struct fileinfo **f)
|
||||
{
|
||||
uerr_t err;
|
||||
char *uf; /* url file name */
|
||||
@@ -1859,7 +1861,7 @@ ftp_get_listing (struct url *u, ccon *co
|
||||
|
||||
con->target = xstrdup (lf);
|
||||
xfree (lf);
|
||||
- err = ftp_loop_internal (u, NULL, con, NULL, false);
|
||||
+ err = ftp_loop_internal (u, original_url, NULL, con, NULL, false);
|
||||
lf = xstrdup (con->target);
|
||||
xfree (con->target);
|
||||
con->target = old_target;
|
||||
@@ -1882,8 +1884,9 @@ ftp_get_listing (struct url *u, ccon *co
|
||||
return err;
|
||||
}
|
||||
|
||||
-static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
|
||||
-static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
|
||||
+static uerr_t ftp_retrieve_dirs (struct url *, struct url *,
|
||||
+ struct fileinfo *, ccon *);
|
||||
+static uerr_t ftp_retrieve_glob (struct url *, struct url *, ccon *, int);
|
||||
static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
|
||||
static void freefileinfo (struct fileinfo *f);
|
||||
|
||||
@@ -1895,7 +1898,8 @@ static void freefileinfo (struct fileinf
|
||||
If opt.recursive is set, after all files have been retrieved,
|
||||
ftp_retrieve_dirs will be called to retrieve the directories. */
|
||||
static uerr_t
|
||||
-ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
|
||||
+ftp_retrieve_list (struct url *u, struct url *original_url,
|
||||
+ struct fileinfo *f, ccon *con)
|
||||
{
|
||||
static int depth = 0;
|
||||
uerr_t err;
|
||||
@@ -2056,7 +2060,10 @@ Already have correct symlink %s -> %s\n\
|
||||
else /* opt.retr_symlinks */
|
||||
{
|
||||
if (dlthis)
|
||||
- err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
|
||||
+ {
|
||||
+ err = ftp_loop_internal (u, original_url, f, con, NULL,
|
||||
+ force_full_retrieve);
|
||||
+ }
|
||||
} /* opt.retr_symlinks */
|
||||
break;
|
||||
case FT_DIRECTORY:
|
||||
@@ -2067,7 +2074,10 @@ Already have correct symlink %s -> %s\n\
|
||||
case FT_PLAINFILE:
|
||||
/* Call the retrieve loop. */
|
||||
if (dlthis)
|
||||
- err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
|
||||
+ {
|
||||
+ err = ftp_loop_internal (u, original_url, f, con, NULL,
|
||||
+ force_full_retrieve);
|
||||
+ }
|
||||
break;
|
||||
case FT_UNKNOWN:
|
||||
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
|
||||
@@ -2132,7 +2142,7 @@ Already have correct symlink %s -> %s\n\
|
||||
/* We do not want to call ftp_retrieve_dirs here */
|
||||
if (opt.recursive &&
|
||||
!(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
|
||||
- err = ftp_retrieve_dirs (u, orig, con);
|
||||
+ err = ftp_retrieve_dirs (u, original_url, orig, con);
|
||||
else if (opt.recursive)
|
||||
DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
|
||||
depth, opt.reclevel));
|
||||
@@ -2145,7 +2155,8 @@ Already have correct symlink %s -> %s\n\
|
||||
ftp_retrieve_glob on each directory entry. The function knows
|
||||
about excluded directories. */
|
||||
static uerr_t
|
||||
-ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
|
||||
+ftp_retrieve_dirs (struct url *u, struct url *original_url,
|
||||
+ struct fileinfo *f, ccon *con)
|
||||
{
|
||||
char *container = NULL;
|
||||
int container_size = 0;
|
||||
@@ -2195,7 +2206,7 @@ Not descending to %s as it is excluded/n
|
||||
odir = xstrdup (u->dir); /* because url_set_dir will free
|
||||
u->dir. */
|
||||
url_set_dir (u, newdir);
|
||||
- ftp_retrieve_glob (u, con, GLOB_GETALL);
|
||||
+ ftp_retrieve_glob (u, original_url, con, GLOB_GETALL);
|
||||
url_set_dir (u, odir);
|
||||
xfree (odir);
|
||||
|
||||
@@ -2254,14 +2265,15 @@ is_invalid_entry (struct fileinfo *f)
|
||||
GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
|
||||
directory. */
|
||||
static uerr_t
|
||||
-ftp_retrieve_glob (struct url *u, ccon *con, int action)
|
||||
+ftp_retrieve_glob (struct url *u, struct url *original_url,
|
||||
+ ccon *con, int action)
|
||||
{
|
||||
struct fileinfo *f, *start;
|
||||
uerr_t res;
|
||||
|
||||
con->cmd |= LEAVE_PENDING;
|
||||
|
||||
- res = ftp_get_listing (u, con, &start);
|
||||
+ res = ftp_get_listing (u, original_url, con, &start);
|
||||
if (res != RETROK)
|
||||
return res;
|
||||
/* First: weed out that do not conform the global rules given in
|
||||
@@ -2357,7 +2369,7 @@ ftp_retrieve_glob (struct url *u, ccon *
|
||||
if (start)
|
||||
{
|
||||
/* Just get everything. */
|
||||
- res = ftp_retrieve_list (u, start, con);
|
||||
+ res = ftp_retrieve_list (u, original_url, start, con);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2373,7 +2385,7 @@ ftp_retrieve_glob (struct url *u, ccon *
|
||||
{
|
||||
/* Let's try retrieving it anyway. */
|
||||
con->st |= ON_YOUR_OWN;
|
||||
- res = ftp_loop_internal (u, NULL, con, NULL, false);
|
||||
+ res = ftp_loop_internal (u, original_url, NULL, con, NULL, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2393,8 +2405,8 @@ ftp_retrieve_glob (struct url *u, ccon *
|
||||
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,
|
||||
- bool recursive, bool glob)
|
||||
+ftp_loop (struct url *u, struct url *original_url, char **local_file, int *dt,
|
||||
+ struct url *proxy, bool recursive, bool glob)
|
||||
{
|
||||
ccon con; /* FTP connection */
|
||||
uerr_t res;
|
||||
@@ -2415,16 +2427,17 @@ ftp_loop (struct url *u, char **local_fi
|
||||
if (!*u->file && !recursive)
|
||||
{
|
||||
struct fileinfo *f;
|
||||
- res = ftp_get_listing (u, &con, &f);
|
||||
+ res = ftp_get_listing (u, original_url, &con, &f);
|
||||
|
||||
if (res == RETROK)
|
||||
{
|
||||
if (opt.htmlify && !opt.spider)
|
||||
{
|
||||
+ struct url *url_file = opt.trustservernames ? u : original_url;
|
||||
char *filename = (opt.output_document
|
||||
? xstrdup (opt.output_document)
|
||||
: (con.target ? xstrdup (con.target)
|
||||
- : url_file_name (u, NULL)));
|
||||
+ : url_file_name (url_file, NULL)));
|
||||
res = ftp_index (filename, u, f);
|
||||
if (res == FTPOK && opt.verbose)
|
||||
{
|
||||
@@ -2469,11 +2482,13 @@ ftp_loop (struct url *u, char **local_fi
|
||||
/* ftp_retrieve_glob is a catch-all function that gets called
|
||||
if we need globbing, time-stamping, recursion or preserve
|
||||
permissions. Its third argument is just what we really need. */
|
||||
- res = ftp_retrieve_glob (u, &con,
|
||||
+ res = ftp_retrieve_glob (u, original_url, &con,
|
||||
ispattern ? GLOB_GLOBALL : GLOB_GETONE);
|
||||
}
|
||||
else
|
||||
- res = ftp_loop_internal (u, NULL, &con, local_file, false);
|
||||
+ {
|
||||
+ res = ftp_loop_internal (u, original_url, NULL, &con, local_file, false);
|
||||
+ }
|
||||
}
|
||||
if (res == FTPOK)
|
||||
res = RETROK;
|
||||
Index: wget-1.16.3/src/ftp.h
|
||||
===================================================================
|
||||
--- wget-1.16.3.orig/src/ftp.h
|
||||
+++ wget-1.16.3/src/ftp.h
|
||||
@@ -150,7 +150,8 @@ enum wget_ftp_fstatus
|
||||
};
|
||||
|
||||
struct fileinfo *ftp_parse_ls (const char *, const enum stype);
|
||||
-uerr_t ftp_loop (struct url *, char **, int *, struct url *, bool, bool);
|
||||
+uerr_t ftp_loop (struct url *, struct url *, char **, int *, struct url *,
|
||||
+ bool, bool);
|
||||
|
||||
uerr_t ftp_index (const char *, struct url *, struct fileinfo *);
|
||||
|
||||
Index: wget-1.16.3/src/retr.c
|
||||
===================================================================
|
||||
--- wget-1.16.3.orig/src/retr.c
|
||||
+++ wget-1.16.3/src/retr.c
|
||||
@@ -807,7 +807,8 @@ retrieve_url (struct url * orig_parsed,
|
||||
if (redirection_count)
|
||||
oldrec = glob = false;
|
||||
|
||||
- result = ftp_loop (u, &local_file, dt, proxy_url, recursive, glob);
|
||||
+ result = ftp_loop (u, orig_parsed, &local_file, dt, proxy_url,
|
||||
+ recursive, glob);
|
||||
recursive = oldrec;
|
||||
|
||||
/* There is a possibility of having HTTP being redirected to
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
From 0e6d6ca963f13e0c4d239cd9e7aea62d176da8eb Mon Sep 17 00:00:00 2001
|
||||
From: Nikolay Merinov <kim.roader@gmail.com>
|
||||
Date: Fri, 17 Apr 2015 23:32:30 +0500
|
||||
Subject: [PATCH] Fix timestamping and continue behaviour with ftp protocol.
|
||||
|
||||
* src/ftp.c (ftp_loop_internal): Add option `force_full_retrieve' that force to
|
||||
retrieve full file.
|
||||
(ftp_retrieve_list): Pass `true' as `force_full_retrieve' option to
|
||||
`ftp_loop_internal' if we want to download file with newer timestamp than local
|
||||
copy.
|
||||
|
||||
Upstream-Status: Backport
|
||||
In support of CVE-2016-4971
|
||||
Signed-off-by: Armin Kuster <akuster@mvista.com>
|
||||
|
||||
---
|
||||
src/ftp.c | 21 +++++++++++++--------
|
||||
1 file changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
Index: wget-1.16.3/src/ftp.c
|
||||
===================================================================
|
||||
--- wget-1.16.3.orig/src/ftp.c
|
||||
+++ wget-1.16.3/src/ftp.c
|
||||
@@ -1540,7 +1540,8 @@ Error in server response, closing contro
|
||||
This loop either gets commands from con, or (if ON_YOUR_OWN is
|
||||
set), makes them up to retrieve the file given by the URL. */
|
||||
static uerr_t
|
||||
-ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
|
||||
+ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file,
|
||||
+ bool force_full_retrieve)
|
||||
{
|
||||
int count, orig_lp;
|
||||
wgint restval, len = 0, qtyread = 0;
|
||||
@@ -1642,6 +1643,8 @@ ftp_loop_internal (struct url *u, struct
|
||||
/* Decide whether or not to restart. */
|
||||
if (con->cmd & DO_LIST)
|
||||
restval = 0;
|
||||
+ else if (force_full_retrieve)
|
||||
+ restval = 0;
|
||||
else if (opt.start_pos >= 0)
|
||||
restval = opt.start_pos;
|
||||
else if (opt.always_rest
|
||||
@@ -1856,7 +1859,7 @@ ftp_get_listing (struct url *u, ccon *co
|
||||
|
||||
con->target = xstrdup (lf);
|
||||
xfree (lf);
|
||||
- err = ftp_loop_internal (u, NULL, con, NULL);
|
||||
+ err = ftp_loop_internal (u, NULL, con, NULL, false);
|
||||
lf = xstrdup (con->target);
|
||||
xfree (con->target);
|
||||
con->target = old_target;
|
||||
@@ -1901,6 +1904,7 @@ ftp_retrieve_list (struct url *u, struct
|
||||
time_t tml;
|
||||
bool dlthis; /* Download this (file). */
|
||||
const char *actual_target = NULL;
|
||||
+ bool force_full_retrieve = false;
|
||||
|
||||
/* Increase the depth. */
|
||||
++depth;
|
||||
@@ -1980,9 +1984,10 @@ ftp_retrieve_list (struct url *u, struct
|
||||
Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
|
||||
dlthis = false;
|
||||
}
|
||||
- else if (eq_size)
|
||||
+ else if (f->tstamp > tml)
|
||||
{
|
||||
- /* Remote file is newer or sizes cannot be matched */
|
||||
+ /* Remote file is newer */
|
||||
+ force_full_retrieve = true;
|
||||
logprintf (LOG_VERBOSE, _("\
|
||||
Remote file is newer than local file %s -- retrieving.\n\n"),
|
||||
quote (con->target));
|
||||
@@ -2051,7 +2056,7 @@ Already have correct symlink %s -> %s\n\
|
||||
else /* opt.retr_symlinks */
|
||||
{
|
||||
if (dlthis)
|
||||
- err = ftp_loop_internal (u, f, con, NULL);
|
||||
+ err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
|
||||
} /* opt.retr_symlinks */
|
||||
break;
|
||||
case FT_DIRECTORY:
|
||||
@@ -2062,7 +2067,7 @@ Already have correct symlink %s -> %s\n\
|
||||
case FT_PLAINFILE:
|
||||
/* Call the retrieve loop. */
|
||||
if (dlthis)
|
||||
- err = ftp_loop_internal (u, f, con, NULL);
|
||||
+ err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
|
||||
break;
|
||||
case FT_UNKNOWN:
|
||||
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
|
||||
@@ -2368,7 +2373,7 @@ ftp_retrieve_glob (struct url *u, ccon *
|
||||
{
|
||||
/* Let's try retrieving it anyway. */
|
||||
con->st |= ON_YOUR_OWN;
|
||||
- res = ftp_loop_internal (u, NULL, con, NULL);
|
||||
+ res = ftp_loop_internal (u, NULL, con, NULL, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2468,7 +2473,7 @@ ftp_loop (struct url *u, char **local_fi
|
||||
ispattern ? GLOB_GLOBALL : GLOB_GETONE);
|
||||
}
|
||||
else
|
||||
- res = ftp_loop_internal (u, NULL, &con, local_file);
|
||||
+ res = ftp_loop_internal (u, NULL, &con, local_file, false);
|
||||
}
|
||||
if (res == FTPOK)
|
||||
res = RETROK;
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
SRC_URI = "${GNU_MIRROR}/wget/wget-${PV}.tar.gz \
|
||||
file://fix_makefile.patch \
|
||||
file://0001-Unset-need_charset_alias-when-building-for-musl.patch \
|
||||
file://Fix-timestamping-and-continue-behaviour-with-ftp-pro.patch \
|
||||
file://CVE-2016-4971.patch \
|
||||
"
|
||||
|
||||
SRC_URI[md5sum] = "f61d9011b99f824106a5d5a05dd0f63d"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user