1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 07:38:49 -05:00

rand: treat fake entropy the same regardless of endianness

When the random seed is purposely made predictable for testing purposes
by using the CURL_ENTROPY environment variable, process that data in an
endian agnostic way so the the initial random seed is the same
regardless of endianness.

- Change Curl_rand to write to a char array instead of int array.

- Add Curl_rand_hex to write random hex characters to a buffer.

Fixes #1315
Closes #1468

Co-authored-by: Daniel Stenberg
Reported-by: Michael Kaufmann
This commit is contained in:
Jay Satiro 2017-05-08 23:23:28 +02:00 committed by Daniel Stenberg
parent 9e9509e46a
commit 1cafede9f2
5 changed files with 87 additions and 54 deletions

View File

@ -48,7 +48,7 @@ static char *Curl_basename(char *path);
#endif #endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size); 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 /* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */ extensions. */
@ -1159,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData *firstform; struct FormData *firstform;
struct curl_httppost *file; struct curl_httppost *file;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
curl_off_t size = 0; /* support potentially ENORMOUS formposts */ curl_off_t size = 0; /* support potentially ENORMOUS formposts */
char *boundary; char fileboundary[42];
char *fileboundary = NULL;
struct curl_slist *curList; struct curl_slist *curList;
char boundary[42];
*finalform = NULL; /* default form is empty */ *finalform = NULL; /* default form is empty */
if(!post) if(!post)
return result; /* no input => no output! */ return result; /* no input => no output! */
boundary = formboundary(data); result = formboundary(data, boundary, sizeof(boundary));
if(!boundary) if(result)
return CURLE_OUT_OF_MEMORY; return result;
/* Make the first line of the output */ /* Make the first line of the output */
result = AddFormDataf(&form, NULL, result = AddFormDataf(&form, NULL,
@ -1182,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
boundary); boundary);
if(result) { if(result) {
free(boundary);
return result; return result;
} }
/* we DO NOT include that line in the total size of the POST, since it'll be /* 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 /* 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 */ the magic to include several files with the same field name */
free(fileboundary); result = formboundary(data, fileboundary, sizeof(fileboundary));
fileboundary = formboundary(data); if(result) {
if(!fileboundary) {
result = CURLE_OUT_OF_MEMORY;
break; break;
} }
@ -1379,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
if(result) { if(result) {
Curl_formclean(&firstform); Curl_formclean(&firstform);
free(fileboundary);
free(boundary);
return result; return result;
} }
*sizep = size; *sizep = size;
free(fileboundary);
free(boundary);
*finalform = firstform; *finalform = firstform;
return result; return result;
@ -1562,16 +1552,17 @@ char *Curl_formpostheader(void *formp, size_t *len)
* formboundary() creates a suitable boundary string and returns an allocated * formboundary() creates a suitable boundary string and returns an allocated
* one. * 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) /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */ combinations */
unsigned int rnd[2]; DEBUGASSERT(buflen >= 41);
CURLcode result = Curl_rand(data, &rnd[0], 2);
if(result)
return NULL;
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 */ #else /* CURL_DISABLE_HTTP */

View File

@ -47,10 +47,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
char *force_entropy = getenv("CURL_ENTROPY"); char *force_entropy = getenv("CURL_ENTROPY");
if(force_entropy) { if(force_entropy) {
if(!seeded) { if(!seeded) {
unsigned int seed = 0;
size_t elen = strlen(force_entropy); size_t elen = strlen(force_entropy);
size_t clen = sizeof(randseed); size_t clen = sizeof(seed);
size_t min = elen < clen ? elen : clen; size_t min = elen < clen ? elen : clen;
memcpy((char *)&randseed, force_entropy, min); memcpy((char *)&seed, force_entropy, min);
randseed = ntohl(seed);
seeded = TRUE; seeded = TRUE;
} }
else 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, CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
unsigned int num)
{ {
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
unsigned int i;
assert(num > 0); assert(num > 0);
for(i = 0; i < num; i++) { while(num) {
result = randit(data, rndptr++); unsigned int r;
size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
result = randit(data, &r);
if(result) if(result)
return 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; return result;
} }

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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. * 'rnd' points to.
* *
* If libcurl is built without TLS support or with a TLS backend that lacks a * If libcurl is built without TLS support or with a TLS backend that lacks a
@ -37,7 +37,11 @@
* easy handle! * easy handle!
* *
*/ */
CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd, CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
unsigned int 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 */ #endif /* HEADER_CURL_RAND_H */

View File

@ -360,7 +360,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
char qop_options[64]; char qop_options[64];
int qop_values; int qop_values;
char cnonce[33]; char cnonce[33];
unsigned int entropy[4];
char nonceCount[] = "00000001"; char nonceCount[] = "00000001";
char method[] = "AUTHENTICATE"; char method[] = "AUTHENTICATE";
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; 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)) if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING; return CURLE_BAD_CONTENT_ENCODING;
/* Generate 16 bytes of random data */ /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
result = Curl_rand(data, &entropy[0], 4); result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result) if(result)
return 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 */ /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
ctxt = Curl_MD5_init(Curl_DIGEST_MD5); ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
if(!ctxt) if(!ctxt)
@ -684,12 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->nc = 1; digest->nc = 1;
if(!digest->cnonce) { if(!digest->cnonce) {
unsigned int rnd[4]; result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
result = Curl_rand(data, &rnd[0], 4); sizeof(cnoncebuf));
if(result) if(result)
return 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), result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
&cnonce, &cnonce_sz); &cnonce, &cnonce_sz);

View File

@ -555,10 +555,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) #if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
if(ntlm->target_info_len) { if(ntlm->target_info_len) {
unsigned char ntbuffer[0x18]; unsigned char ntbuffer[0x18];
unsigned int entropy[2]; unsigned char entropy[8];
unsigned char ntlmv2hash[0x18]; unsigned char ntlmv2hash[0x18];
result = Curl_rand(data, &entropy[0], 2); result = Curl_rand(data, entropy, 8);
if(result) if(result)
return result; return result;
@ -572,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return result; return result;
/* LMv2 response */ /* LMv2 response */
result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
(unsigned char *)&entropy[0],
&ntlm->nonce[0], lmresp); &ntlm->nonce[0], lmresp);
if(result) if(result)
return result; return result;
/* NTLMv2 response */ /* NTLMv2 response */
result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
(unsigned char *)&entropy[0],
ntlm, &ntlmv2resp, &ntresplen); ntlm, &ntlmv2resp, &ntresplen);
if(result) if(result)
return result; return result;
@ -596,10 +594,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned char ntbuffer[0x18]; unsigned char ntbuffer[0x18];
unsigned char tmp[0x18]; unsigned char tmp[0x18];
unsigned char md5sum[MD5_DIGEST_LENGTH]; unsigned char md5sum[MD5_DIGEST_LENGTH];
unsigned int entropy[2]; unsigned char entropy[8];
/* Need to create 8 bytes random data */ /* Need to create 8 bytes random data */
result = Curl_rand(data, &entropy[0], 2); result = Curl_rand(data, entropy, 8);
if(result) if(result)
return result; return result;