diff options
author | Daniel Stenberg <daniel@haxx.se> | 2014-10-17 12:59:32 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2014-11-05 08:05:14 +0100 |
commit | b3875606925536f82fc61f3114ac42f29eaf6945 (patch) | |
tree | 229666d262222b2f34967e00fb5300ec69cda258 | |
parent | d997c8b2f6521d78c6ef63411cfeb226f7927281 (diff) | |
download | curl-b3875606925536f82fc61f3114ac42f29eaf6945.tar.gz |
curl_easy_duphandle: CURLOPT_COPYPOSTFIELDS read out of bounds
When duplicating a handle, the data to post was duplicated using
strdup() when it could be binary and contain zeroes and it was not even
zero terminated! This caused read out of bounds crashes/segfaults.
Since the lib/strdup.c file no longer is easily shared with the curl
tool with this change, it now uses its own version instead.
Bug: http://curl.haxx.se/docs/adv_20141105.html
CVE: CVE-2014-3707
Reported-By: Symeon Paraschoudis
-rw-r--r-- | lib/formdata.c | 52 | ||||
-rw-r--r-- | lib/strdup.c | 32 | ||||
-rw-r--r-- | lib/strdup.h | 3 | ||||
-rw-r--r-- | lib/url.c | 22 | ||||
-rw-r--r-- | lib/urldata.h | 11 | ||||
-rw-r--r-- | src/Makefile.inc | 4 | ||||
-rw-r--r-- | src/tool_setup.h | 5 | ||||
-rw-r--r-- | src/tool_strdup.c | 47 | ||||
-rw-r--r-- | src/tool_strdup.h | 30 |
9 files changed, 145 insertions, 61 deletions
diff --git a/lib/formdata.c b/lib/formdata.c index 1abfbc42b..73d3b6d72 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -36,6 +36,7 @@ #include "strequal.h" #include "curl_memory.h" #include "sendf.h" +#include "strdup.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -210,46 +211,6 @@ static const char *ContentTypeForFilename(const char *filename, /*************************************************************************** * - * memdup() - * - * Copies the 'source' data to a newly allocated buffer buffer (that is - * returned). Uses buffer_length if not null, else uses strlen to determine - * the length of the buffer to be copied - * - * Returns the new pointer or NULL on failure. - * - ***************************************************************************/ -static char *memdup(const char *src, size_t buffer_length) -{ - size_t length; - bool add = FALSE; - char *buffer; - - if(buffer_length) - length = buffer_length; - else if(src) { - length = strlen(src); - add = TRUE; - } - else - /* no length and a NULL src pointer! */ - return strdup(""); - - buffer = malloc(length+add); - if(!buffer) - return NULL; /* fail */ - - memcpy(buffer, src, length); - - /* if length unknown do null termination */ - if(add) - buffer[length] = '\0'; - - return buffer; -} - -/*************************************************************************** - * * FormAdd() * * Stores a formpost parameter and builds the appropriate linked list. @@ -678,9 +639,12 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, (form == first_form) ) { /* Note that there's small risk that form->name is NULL here if the app passed in a bad combo, so we better check for that first. */ - if(form->name) + if(form->name) { /* copy name (without strdup; possibly contains null characters) */ - form->name = memdup(form->name, form->namelength); + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name)+1); + } if(!form->name) { return_value = CURL_FORMADD_MEMORY; break; @@ -691,7 +655,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | HTTPPOST_CALLBACK)) && form->value) { /* copy value (without strdup; possibly contains null characters) */ - form->value = memdup(form->value, form->contentslength); + form->value = Curl_memdup(form->value, form->contentslength? + form->contentslength: + strlen(form->value)+1); if(!form->value) { return_value = CURL_FORMADD_MEMORY; break; diff --git a/lib/strdup.c b/lib/strdup.c index 3b776b184..4b5bd4042 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -19,12 +19,12 @@ * KIND, either express or implied. * ***************************************************************************/ -/* - * This file is 'mem-include-scan' clean. See test 1132. - */ #include "curl_setup.h" - #include "strdup.h" +#include "curl_memory.h" + +/* The last #include file should be: */ +#include "memdebug.h" #ifndef HAVE_STRDUP char *curlx_strdup(const char *str) @@ -50,3 +50,25 @@ char *curlx_strdup(const char *str) } #endif + +/*************************************************************************** + * + * Curl_memdup(source, length) + * + * Copies the 'source' data to a newly allocated buffer (that is + * returned). Copies 'length' bytes. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +char *Curl_memdup(const char *src, size_t length) +{ + char *buffer = malloc(length); + if(!buffer) + return NULL; /* fail */ + + memcpy(buffer, src, length); + + /* if length unknown do null termination */ + return buffer; +} diff --git a/lib/strdup.h b/lib/strdup.h index 49af9117e..23a71f863 100644 --- a/lib/strdup.h +++ b/lib/strdup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,5 +26,6 @@ #ifndef HAVE_STRDUP extern char *curlx_strdup(const char *str); #endif +char *Curl_memdup(const char *src, size_t buffer_length); #endif /* HEADER_CURL_STRDUP_H */ @@ -125,6 +125,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out); #include "multihandle.h" #include "pipeline.h" #include "dotdot.h" +#include "strdup.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -270,8 +271,9 @@ void Curl_freeset(struct SessionHandle *data) { /* Free all dynamic strings stored in the data->set substructure. */ enum dupstring i; - for(i=(enum dupstring)0; i < STRING_LAST; i++) + for(i=(enum dupstring)0; i < STRING_LAST; i++) { Curl_safefree(data->set.str[i]); + } if(data->change.referer_alloc) { Curl_safefree(data->change.referer); @@ -356,14 +358,24 @@ CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src) memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); /* duplicate all strings */ - for(i=(enum dupstring)0; i< STRING_LAST; i++) { + for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { result = setstropt(&dst->set.str[i], src->set.str[i]); if(result) - break; + return result; } - /* If a failure occurred, freeing has to be performed externally. */ - return result; + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], src->set.postfieldsize); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + return CURLE_OK; } /* diff --git a/lib/urldata.h b/lib/urldata.h index 5a65c4a74..62a2b8048 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1372,7 +1372,6 @@ enum dupstring { STRING_KRB_LEVEL, /* krb security level */ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find $HOME/.netrc */ - STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ STRING_PROXY, /* proxy to use */ STRING_SET_RANGE, /* range, if used */ STRING_SET_REFERER, /* custom string for the HTTP referer field */ @@ -1415,7 +1414,15 @@ enum dupstring { STRING_BEARER, /* <bearer>, if used */ - /* -- end of strings -- */ + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, + + /* -- below this are pointers to binary data that cannot be strdup'ed. + Each such pointer must be added manually to Curl_dupset() --- */ + + STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + STRING_LAST /* not used, just an end-of-list marker */ }; diff --git a/src/Makefile.inc b/src/Makefile.inc index 64d55ecf9..401a635ad 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -11,7 +11,6 @@ # the official API, but we re-use the code here to avoid duplication. CURLX_CFILES = \ ../lib/strtoofft.c \ - ../lib/strdup.c \ ../lib/rawstr.c \ ../lib/nonblock.c \ ../lib/warnless.c @@ -19,7 +18,6 @@ CURLX_CFILES = \ CURLX_HFILES = \ ../lib/curl_setup.h \ ../lib/strtoofft.h \ - ../lib/strdup.h \ ../lib/rawstr.h \ ../lib/nonblock.h \ ../lib/warnless.h @@ -55,6 +53,7 @@ CURL_CFILES = \ tool_panykey.c \ tool_paramhlp.c \ tool_parsecfg.c \ + tool_strdup.c \ tool_setopt.c \ tool_sleep.c \ tool_urlglob.c \ @@ -99,6 +98,7 @@ CURL_HFILES = \ tool_setopt.h \ tool_setup.h \ tool_sleep.h \ + tool_strdup.h \ tool_urlglob.h \ tool_util.h \ tool_version.h \ diff --git a/src/tool_setup.h b/src/tool_setup.h index c94686f96..3d7c15809 100644 --- a/src/tool_setup.h +++ b/src/tool_setup.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -67,8 +67,7 @@ #endif #ifndef HAVE_STRDUP -# include "strdup.h" -# define strdup(ptr) curlx_strdup(ptr) +# include "tool_strdup.h" #endif #endif /* HEADER_CURL_TOOL_SETUP_H */ diff --git a/src/tool_strdup.c b/src/tool_strdup.c new file mode 100644 index 000000000..d661a82f7 --- /dev/null +++ b/src/tool_strdup.c @@ -0,0 +1,47 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "strdup.h" + +#ifndef HAVE_STRDUP +char *strdup(const char *str) +{ + size_t len; + char *newstr; + + if(!str) + return (char *)NULL; + + len = strlen(str); + + if(len >= ((size_t)-1) / sizeof(char)) + return (char *)NULL; + + newstr = malloc((len+1)*sizeof(char)); + if(!newstr) + return (char *)NULL; + + memcpy(newstr,str,(len+1)*sizeof(char)); + + return newstr; + +} +#endif diff --git a/src/tool_strdup.h b/src/tool_strdup.h new file mode 100644 index 000000000..83c8102c3 --- /dev/null +++ b/src/tool_strdup.h @@ -0,0 +1,30 @@ +#ifndef HEADER_TOOL_STRDUP_H +#define HEADER_TOOL_STRDUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "tool_setup.h" + +#ifndef HAVE_STRDUP +extern char *strdup(const char *str); +#endif + +#endif /* HEADER_TOOL_STRDUP_H */ |