summaryrefslogtreecommitdiffstats
path: root/meta/recipes-support/curl
diff options
context:
space:
mode:
authorArmin Kuster <akuster@mvista.com>2016-02-05 08:57:11 -0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-02-07 22:55:24 +0000
commitf4341a9b6fef02285f368e43585e5cd0452fe728 (patch)
tree4f34c144b6215b5884b93c11c08bd995b4791943 /meta/recipes-support/curl
parent35f4306ed4c505c8cc4d756e209dfd4eb0fbe424 (diff)
downloadpoky-f4341a9b6fef02285f368e43585e5cd0452fe728.tar.gz
curl: Security fix CVE-2016-0754
CVE-2016-0754 curl: remote file name path traversal in curl tool for Windows (From OE-Core rev: b2c9b48dea2fd968c307a809ff95f2e686435222) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-support/curl')
-rw-r--r--meta/recipes-support/curl/curl/CVE-2016-0754.patch417
-rw-r--r--meta/recipes-support/curl/curl_7.44.0.bb3
2 files changed, 419 insertions, 1 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2016-0754.patch b/meta/recipes-support/curl/curl/CVE-2016-0754.patch
new file mode 100644
index 0000000000..f0402de081
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2016-0754.patch
@@ -0,0 +1,417 @@
1From b1bb4ca6d8777683b6a549fb61dba36759da26f4 Mon Sep 17 00:00:00 2001
2From: Ray Satiro <raysatiro@yahoo.com>
3Date: Tue, 26 Jan 2016 23:23:15 +0100
4Subject: [PATCH] curl: avoid local drive traversal when saving file (Windows)
5
6curl does not sanitize colons in a remote file name that is used as the
7local file name. This may lead to a vulnerability on systems where the
8colon is a special path character. Currently Windows/DOS is the only OS
9where this vulnerability applies.
10
11CVE-2016-0754
12
13Bug: http://curl.haxx.se/docs/adv_20160127B.html
14
15Upstream-Status: Backport
16http://curl.haxx.se/CVE-2016-0754.patch
17
18CVE: CVE-2016-0754
19Signed-off-by: Armin Kuster <akuster@mvista.com>
20
21---
22 src/tool_cb_hdr.c | 40 ++++++------
23 src/tool_doswin.c | 174 ++++++++++++++++++++++++++++++++++++++++++++---------
24 src/tool_doswin.h | 2 +-
25 src/tool_operate.c | 29 ++++++---
26 4 files changed, 187 insertions(+), 58 deletions(-)
27
28diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
29index fd208e8..0fca39f 100644
30--- a/src/tool_cb_hdr.c
31+++ b/src/tool_cb_hdr.c
32@@ -26,10 +26,11 @@
33 #define ENABLE_CURLX_PRINTF
34 /* use our own printf() functions */
35 #include "curlx.h"
36
37 #include "tool_cfgable.h"
38+#include "tool_doswin.h"
39 #include "tool_msgs.h"
40 #include "tool_cb_hdr.h"
41
42 #include "memdebug.h" /* keep this as LAST include */
43
44@@ -112,22 +113,28 @@ size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
45 /* this expression below typecasts 'cb' only to avoid
46 warning: signed and unsigned type in conditional expression
47 */
48 len = (ssize_t)cb - (p - str);
49 filename = parse_filename(p, len);
50- if(filename) {
51- outs->filename = filename;
52- outs->alloc_filename = TRUE;
53- outs->is_cd_filename = TRUE;
54- outs->s_isreg = TRUE;
55- outs->fopened = FALSE;
56- outs->stream = NULL;
57- hdrcbdata->honor_cd_filename = FALSE;
58- break;
59- }
60- else
61+ if(!filename)
62+ return failure;
63+
64+#if defined(MSDOS) || defined(WIN32)
65+ if(sanitize_file_name(&filename)) {
66+ free(filename);
67 return failure;
68+ }
69+#endif /* MSDOS || WIN32 */
70+
71+ outs->filename = filename;
72+ outs->alloc_filename = TRUE;
73+ outs->is_cd_filename = TRUE;
74+ outs->s_isreg = TRUE;
75+ outs->fopened = FALSE;
76+ outs->stream = NULL;
77+ hdrcbdata->honor_cd_filename = FALSE;
78+ break;
79 }
80 }
81
82 return cb;
83 }
84@@ -179,19 +186,16 @@ static char *parse_filename(const char *ptr, size_t len)
85 return NULL;
86 }
87 }
88
89 /* scan for the end letter and stop there */
90- q = p;
91- while(*q) {
92- if(q[1] && (q[0] == '\\'))
93- q++;
94- else if(q[0] == stop)
95+ for(q = p; *q; ++q) {
96+ if(*q == stop) {
97+ *q = '\0';
98 break;
99- q++;
100+ }
101 }
102- *q = '\0';
103
104 /* make sure the file name doesn't end in \r or \n */
105 q = strchr(p, '\r');
106 if(q)
107 *q = '\0';
108diff --git a/src/tool_doswin.c b/src/tool_doswin.c
109index dd6e8bb..9c6a7a3 100644
110--- a/src/tool_doswin.c
111+++ b/src/tool_doswin.c
112@@ -83,46 +83,110 @@ __pragma(warning(pop))
113 # define _use_lfn(f) ALWAYS_FALSE /* long file names never available */
114 #elif defined(__DJGPP__)
115 # include <fcntl.h> /* _use_lfn(f) prototype */
116 #endif
117
118-static const char *msdosify (const char *file_name);
119-static char *rename_if_dos_device_name (char *file_name);
120+static char *msdosify(const char *file_name);
121+static char *rename_if_dos_device_name(const char *file_name);
122
123-/*
124- * sanitize_dos_name: returns a newly allocated string holding a
125- * valid file name which will be a transformation of given argument
126- * in case this wasn't already a valid file name.
127- *
128- * This function takes ownership of given argument, free'ing it before
129- * returning. Caller is responsible of free'ing returned string. Upon
130- * out of memory condition function returns NULL.
131- */
132
133-char *sanitize_dos_name(char *file_name)
134+/*
135+Sanitize *file_name.
136+Success: (CURLE_OK) *file_name points to a sanitized version of the original.
137+ This function takes ownership of the original *file_name and frees it.
138+Failure: (!= CURLE_OK) *file_name is unchanged.
139+*/
140+CURLcode sanitize_file_name(char **file_name)
141 {
142- char new_name[PATH_MAX];
143+ size_t len;
144+ char *p, *sanitized;
145+
146+ /* Calculate the maximum length of a filename.
147+ FILENAME_MAX is often the same as PATH_MAX, in other words it does not
148+ discount the path information. PATH_MAX size is calculated based on:
149+ <drive-letter><colon><path-sep><max-filename-len><NULL> */
150+ const size_t max_filename_len = PATH_MAX - 3 - 1;
151+
152+ if(!file_name || !*file_name)
153+ return CURLE_BAD_FUNCTION_ARGUMENT;
154+
155+ len = strlen(*file_name);
156+
157+ if(len >= max_filename_len)
158+ len = max_filename_len - 1;
159
160- if(!file_name)
161- return NULL;
162+ sanitized = malloc(len + 1);
163
164- if(strlen(file_name) >= PATH_MAX)
165- file_name[PATH_MAX-1] = '\0'; /* truncate it */
166+ if(!sanitized)
167+ return CURLE_OUT_OF_MEMORY;
168
169- strcpy(new_name, msdosify(file_name));
170+ strncpy(sanitized, *file_name, len);
171+ sanitized[len] = '\0';
172
173- Curl_safefree(file_name);
174+ for(p = sanitized; *p; ++p ) {
175+ const char *banned;
176+ if(1 <= *p && *p <= 31) {
177+ *p = '_';
178+ continue;
179+ }
180+ for(banned = "|<>/\\\":?*"; *banned; ++banned) {
181+ if(*p == *banned) {
182+ *p = '_';
183+ break;
184+ }
185+ }
186+ }
187
188- return strdup(rename_if_dos_device_name(new_name));
189+#ifdef MSDOS
190+ /* msdosify checks for more banned characters for MSDOS, however it allows
191+ for some path information to pass through. since we are sanitizing only a
192+ filename and cannot allow a path it's important this call be done in
193+ addition to and not instead of the banned character check above. */
194+ p = msdosify(sanitized);
195+ if(!p) {
196+ free(sanitized);
197+ return CURLE_BAD_FUNCTION_ARGUMENT;
198+ }
199+ sanitized = p;
200+ len = strlen(sanitized);
201+#endif
202+
203+ p = rename_if_dos_device_name(sanitized);
204+ if(!p) {
205+ free(sanitized);
206+ return CURLE_BAD_FUNCTION_ARGUMENT;
207+ }
208+ sanitized = p;
209+ len = strlen(sanitized);
210+
211+ /* dos_device_name rename will rename a device name, possibly changing the
212+ length. If the length is too long now we can't truncate it because we
213+ could end up with a device name. In practice this shouldn't be a problem
214+ because device names are short, but you never know. */
215+ if(len >= max_filename_len) {
216+ free(sanitized);
217+ return CURLE_BAD_FUNCTION_ARGUMENT;
218+ }
219+
220+ *file_name = sanitized;
221+ return CURLE_OK;
222 }
223
224-/* The following functions are taken with modification from the DJGPP
225- * port of tar 1.12. They use algorithms originally from DJTAR. */
226+/* The functions msdosify, rename_if_dos_device_name and __crt0_glob_function
227+ * were taken with modification from the DJGPP port of tar 1.12. They use
228+ * algorithms originally from DJTAR.
229+ */
230
231-static const char *msdosify (const char *file_name)
232+/*
233+Extra sanitization MSDOS for file_name.
234+Returns a copy of file_name that is sanitized by MSDOS standards.
235+Warning: path information may pass through. For sanitizing a filename use
236+sanitize_file_name which calls this function after sanitizing path info.
237+*/
238+static char *msdosify(const char *file_name)
239 {
240- static char dos_name[PATH_MAX];
241+ char dos_name[PATH_MAX];
242 static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
243 "|<>\\\":?*"; /* illegal in DOS & W95 */
244 static const char *illegal_chars_w95 = &illegal_chars_dos[8];
245 int idx, dot_idx;
246 const char *s = file_name;
247@@ -199,39 +263,89 @@ static const char *msdosify (const char *file_name)
248 else
249 idx++;
250 }
251
252 *d = '\0';
253- return dos_name;
254+ return strdup(dos_name);
255 }
256
257-static char *rename_if_dos_device_name (char *file_name)
258+/*
259+Rename file_name if it's a representation of a device name.
260+Returns a copy of file_name, and the copy will have contents different from the
261+original if a device name was found.
262+*/
263+static char *rename_if_dos_device_name(const char *file_name)
264 {
265 /* We could have a file whose name is a device on MS-DOS. Trying to
266 * retrieve such a file would fail at best and wedge us at worst. We need
267 * to rename such files. */
268- char *base;
269+ char *p, *base;
270 struct_stat st_buf;
271 char fname[PATH_MAX];
272
273 strncpy(fname, file_name, PATH_MAX-1);
274 fname[PATH_MAX-1] = '\0';
275 base = basename(fname);
276 if(((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
277 size_t blen = strlen(base);
278
279- if(strlen(fname) >= PATH_MAX-1) {
280+ if(strlen(fname) == PATH_MAX-1) {
281 /* Make room for the '_' */
282 blen--;
283 base[blen] = '\0';
284 }
285 /* Prepend a '_'. */
286 memmove(base + 1, base, blen + 1);
287 base[0] = '_';
288- strcpy(file_name, fname);
289 }
290- return file_name;
291+
292+ /* The above stat check does not identify devices for me in Windows 7. For
293+ example a stat on COM1 returns a regular file S_IFREG. According to MSDN
294+ stat doc that is the correct behavior, so I assume the above code is
295+ legacy, maybe MSDOS or DJGPP specific? */
296+
297+ /* Rename devices.
298+ Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS */
299+ for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) {
300+ size_t p_len;
301+ int x = (curl_strnequal(p, "CON", 3) ||
302+ curl_strnequal(p, "PRN", 3) ||
303+ curl_strnequal(p, "AUX", 3) ||
304+ curl_strnequal(p, "NUL", 3)) ? 3 :
305+ (curl_strnequal(p, "CLOCK$", 6)) ? 6 :
306+ (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ?
307+ (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0;
308+
309+ if(!x)
310+ continue;
311+
312+ /* the devices may be accessible with an extension or ADS, for
313+ example CON.AIR and CON:AIR both access console */
314+ if(p[x] == '.' || p[x] == ':') {
315+ p[x] = '_';
316+ continue;
317+ }
318+ else if(p[x]) /* no match */
319+ continue;
320+
321+ p_len = strlen(p);
322+
323+ if(strlen(fname) == PATH_MAX-1) {
324+ /* Make room for the '_' */
325+ p_len--;
326+ p[p_len] = '\0';
327+ }
328+ /* Prepend a '_'. */
329+ memmove(p + 1, p, p_len + 1);
330+ p[0] = '_';
331+
332+ /* if fname was just modified then the basename pointer must be updated */
333+ if(p == fname)
334+ base = basename(fname);
335+ }
336+
337+ return strdup(fname);
338 }
339
340 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
341
342 /*
343diff --git a/src/tool_doswin.h b/src/tool_doswin.h
344index cd216db..fc83f16 100644
345--- a/src/tool_doswin.h
346+++ b/src/tool_doswin.h
347@@ -23,11 +23,11 @@
348 ***************************************************************************/
349 #include "tool_setup.h"
350
351 #if defined(MSDOS) || defined(WIN32)
352
353-char *sanitize_dos_name(char *file_name);
354+CURLcode sanitize_file_name(char **filename);
355
356 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
357
358 char **__crt0_glob_function(char *arg);
359
360diff --git a/src/tool_operate.c b/src/tool_operate.c
361index 30d60cb..272ebd4 100644
362--- a/src/tool_operate.c
363+++ b/src/tool_operate.c
364@@ -541,30 +541,41 @@ static CURLcode operate_do(struct GlobalConfig *global,
365 if(!outfile) {
366 /* extract the file name from the URL */
367 result = get_url_file_name(&outfile, this_url);
368 if(result)
369 goto show_error;
370+
371+#if defined(MSDOS) || defined(WIN32)
372+ result = sanitize_file_name(&outfile);
373+ if(result) {
374+ Curl_safefree(outfile);
375+ goto show_error;
376+ }
377+#endif /* MSDOS || WIN32 */
378+
379 if(!*outfile && !config->content_disposition) {
380 helpf(global->errors, "Remote file name has no length!\n");
381 result = CURLE_WRITE_ERROR;
382 goto quit_urls;
383 }
384-#if defined(MSDOS) || defined(WIN32)
385- /* For DOS and WIN32, we do some major replacing of
386- bad characters in the file name before using it */
387- outfile = sanitize_dos_name(outfile);
388- if(!outfile) {
389- result = CURLE_OUT_OF_MEMORY;
390- goto show_error;
391- }
392-#endif /* MSDOS || WIN32 */
393 }
394 else if(urls) {
395 /* fill '#1' ... '#9' terms from URL pattern */
396 char *storefile = outfile;
397 result = glob_match_url(&outfile, storefile, urls);
398 Curl_safefree(storefile);
399+
400+#if defined(MSDOS) || defined(WIN32)
401+ if(!result) {
402+ result = sanitize_file_name(&outfile);
403+ if(result) {
404+ Curl_safefree(outfile);
405+ goto show_error;
406+ }
407+ }
408+#endif /* MSDOS || WIN32 */
409+
410 if(result) {
411 /* bad globbing */
412 warnf(config->global, "bad output glob!\n");
413 goto quit_urls;
414 }
415--
4162.7.0
417
diff --git a/meta/recipes-support/curl/curl_7.44.0.bb b/meta/recipes-support/curl/curl_7.44.0.bb
index f6d350e86a..852c4dd472 100644
--- a/meta/recipes-support/curl/curl_7.44.0.bb
+++ b/meta/recipes-support/curl/curl_7.44.0.bb
@@ -12,7 +12,8 @@ SRC_URI = "http://curl.haxx.se/download/curl-${PV}.tar.bz2 \
12# curl likes to set -g0 in CFLAGS, so we stop it 12# curl likes to set -g0 in CFLAGS, so we stop it
13# from mucking around with debug options 13# from mucking around with debug options
14# 14#
15SRC_URI += " file://configure_ac.patch" 15SRC_URI += " file://configure_ac.patch \
16 file://CVE-2016-0754.patch"
16 17
17SRC_URI[md5sum] = "6b952ca00e5473b16a11f05f06aa8dae" 18SRC_URI[md5sum] = "6b952ca00e5473b16a11f05f06aa8dae"
18SRC_URI[sha256sum] = "1e2541bae6582bb697c0fbae49e1d3e6fad5d05d5aa80dbd6f072e0a44341814" 19SRC_URI[sha256sum] = "1e2541bae6582bb697c0fbae49e1d3e6fad5d05d5aa80dbd6f072e0a44341814"