]> granicus.if.org Git - curl/commitdiff
rand: treat fake entropy the same regardless of endianness
authorJay Satiro <raysatiro@yahoo.com>
Mon, 8 May 2017 21:23:28 +0000 (23:23 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 8 May 2017 21:24:29 +0000 (23:24 +0200)
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
lib/formdata.c
lib/rand.c
lib/rand.h
lib/vauth/digest.c
lib/vauth/ntlm.c

index 90fbd11437546a0aed88a65eb6d52d54b18cd0c0..4c3cf203cfbb9ec23e26d930cc0336eb9668edad 100644 (file)
@@ -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 */
index 8a1408425a11c40f08d3a324099c239f172c8adc..a61a070ee1d37ea62b44eac2098bcba15761612e 100644 (file)
@@ -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;
 }
index 0f8986120efa5d481c85c1a38ad17d0bab2cb38b..c6fae35537cb8af367b37a3df3527d5535bf9274 100644 (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
  * 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
  * 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 */
index 268474c78e656a991c5d89a9ae507c3f6c57fe37..185098ed68ebf998554050452542a1ebfbe7958d 100644 (file)
@@ -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);
index d02eec491c6331cadcd03cbad540a2805de4a077..42196455f6ac61905b739d870e6c7d7adc1bf316 100644 (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(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;