diff --git a/lib/formdata.c b/lib/formdata.c index 90fbd1143..4c3cf203c 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -48,7 +48,7 @@ static char *Curl_basename(char *path); #endif static size_t readfromfile(struct Form *form, char *buffer, size_t size); -static char *formboundary(struct Curl_easy *data); +static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len); /* What kind of Content-Type to use on un-specified files with unrecognized extensions. */ @@ -1159,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data, struct FormData *firstform; struct curl_httppost *file; CURLcode result = CURLE_OK; - curl_off_t size = 0; /* support potentially ENORMOUS formposts */ - char *boundary; - char *fileboundary = NULL; + char fileboundary[42]; struct curl_slist *curList; + char boundary[42]; *finalform = NULL; /* default form is empty */ if(!post) return result; /* no input => no output! */ - boundary = formboundary(data); - if(!boundary) - return CURLE_OUT_OF_MEMORY; + result = formboundary(data, boundary, sizeof(boundary)); + if(result) + return result; /* Make the first line of the output */ result = AddFormDataf(&form, NULL, @@ -1182,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data, boundary); if(result) { - free(boundary); return result; } /* we DO NOT include that line in the total size of the POST, since it'll be @@ -1225,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data, /* If used, this is a link to more file names, we must then do the magic to include several files with the same field name */ - free(fileboundary); - fileboundary = formboundary(data); - if(!fileboundary) { - result = CURLE_OUT_OF_MEMORY; + result = formboundary(data, fileboundary, sizeof(fileboundary)); + if(result) { break; } @@ -1379,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data, if(result) { Curl_formclean(&firstform); - free(fileboundary); - free(boundary); return result; } *sizep = size; - - free(fileboundary); - free(boundary); - *finalform = firstform; return result; @@ -1562,16 +1552,17 @@ char *Curl_formpostheader(void *formp, size_t *len) * formboundary() creates a suitable boundary string and returns an allocated * one. */ -static char *formboundary(struct Curl_easy *data) +static CURLcode formboundary(struct Curl_easy *data, + char *buffer, size_t buflen) { /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) combinations */ - unsigned int rnd[2]; - CURLcode result = Curl_rand(data, &rnd[0], 2); - if(result) - return NULL; + DEBUGASSERT(buflen >= 41); - return aprintf("------------------------%08x%08x", rnd[0], rnd[1]); + memset(buffer, '-', 24); + Curl_rand_hex(data, (unsigned char *)&buffer[24], 17); + + return CURLE_OK; } #else /* CURL_DISABLE_HTTP */ diff --git a/lib/rand.c b/lib/rand.c index 8a1408425..a61a070ee 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -47,10 +47,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) char *force_entropy = getenv("CURL_ENTROPY"); if(force_entropy) { if(!seeded) { + unsigned int seed = 0; size_t elen = strlen(force_entropy); - size_t clen = sizeof(randseed); + size_t clen = sizeof(seed); size_t min = elen < clen ? elen : clen; - memcpy((char *)&randseed, force_entropy, min); + memcpy((char *)&seed, force_entropy, min); + randseed = ntohl(seed); seeded = TRUE; } else @@ -115,18 +117,63 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) * */ -CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr, - unsigned int num) +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) { CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; - unsigned int i; assert(num > 0); - for(i = 0; i < num; i++) { - result = randit(data, rndptr++); + while(num) { + unsigned int r; + size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int); + + result = randit(data, &r); if(result) return result; + + while(left) { + *rnd++ = (unsigned char)(r & 0xFF); + r >>= 8; + --num; + --left; + } } + + return result; +} + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ + +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const char *hex = "0123456789abcdef"; + unsigned char buffer[128]; + unsigned char *bufp = buffer; + DEBUGASSERT(num > 1); + + if((num/2 >= sizeof(buffer)) || !(num&1)) + /* make sure it fits in the local buffer and that it is an odd number! */ + return CURLE_BAD_FUNCTION_ARGUMENT; + + num--; /* save one for zero termination */ + + result = Curl_rand(data, buffer, num/2); + if(result) + return result; + + while(num) { + *rnd++ = hex[(*bufp & 0xF0)>>4]; + *rnd++ = hex[*bufp & 0x0F]; + bufp++; + num -= 2; + } + *rnd = 0; + return result; } diff --git a/lib/rand.h b/lib/rand.h index 0f8986120..c6fae3553 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ /* - * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * Curl_rand() stores 'num' number of random unsigned characters in the buffer * 'rnd' points to. * * If libcurl is built without TLS support or with a TLS backend that lacks a @@ -37,7 +37,11 @@ * easy handle! * */ -CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd, - unsigned int num); +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); + +/* Same as above but outputs only random lowercase hex characters. + Does NOT terminate.*/ +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num); #endif /* HEADER_CURL_RAND_H */ diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 268474c78..185098ed6 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -360,7 +360,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, char qop_options[64]; int qop_values; char cnonce[33]; - unsigned int entropy[4]; char nonceCount[] = "00000001"; char method[] = "AUTHENTICATE"; char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; @@ -387,15 +386,11 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) return CURLE_BAD_CONTENT_ENCODING; - /* Generate 16 bytes of random data */ - result = Curl_rand(data, &entropy[0], 4); + /* Generate 32 random hex chars, 32 bytes + 1 zero termination */ + result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce)); if(result) return result; - /* Convert the random data into a 32 byte hex string */ - snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x", - entropy[0], entropy[1], entropy[2], entropy[3]); - /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) @@ -684,12 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, digest->nc = 1; if(!digest->cnonce) { - unsigned int rnd[4]; - result = Curl_rand(data, &rnd[0], 4); + result = Curl_rand_hex(data, (unsigned char *)cnoncebuf, + sizeof(cnoncebuf)); if(result) return result; - snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x", - rnd[0], rnd[1], rnd[2], rnd[3]); result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce, &cnonce_sz); diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index d02eec491..42196455f 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -555,10 +555,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, #if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) if(ntlm->target_info_len) { unsigned char ntbuffer[0x18]; - unsigned int entropy[2]; + unsigned char entropy[8]; unsigned char ntlmv2hash[0x18]; - result = Curl_rand(data, &entropy[0], 2); + result = Curl_rand(data, entropy, 8); if(result) return result; @@ -572,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return result; /* LMv2 response */ - result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, - (unsigned char *)&entropy[0], + result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0], lmresp); if(result) return result; /* NTLMv2 response */ - result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, - (unsigned char *)&entropy[0], + result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp, &ntresplen); if(result) return result; @@ -596,10 +594,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, unsigned char ntbuffer[0x18]; unsigned char tmp[0x18]; unsigned char md5sum[MD5_DIGEST_LENGTH]; - unsigned int entropy[2]; + unsigned char entropy[8]; /* Need to create 8 bytes random data */ - result = Curl_rand(data, &entropy[0], 2); + result = Curl_rand(data, entropy, 8); if(result) return result;