Commit 1cafede9 authored by Jay Satiro's avatar Jay Satiro Committed by Daniel Stenberg
Browse files

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
parent 9e9509e4
Loading
Loading
Loading
Loading
+15 −24
Original line number Diff line number Diff line
@@ -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);

  memset(buffer, '-', 24);
  Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);

  return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
  return CURLE_OK;
}

#else  /* CURL_DISABLE_HTTP */
+54 −7
Original line number Diff line number Diff line
@@ -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;
}
+8 −4
Original line number Diff line number Diff line
@@ -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
@@ -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 */
+4 −11
Original line number Diff line number Diff line
@@ -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);
+6 −8
Original line number Diff line number Diff line
@@ -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;