[exim-cvs] cvs commit: exim/exim-src/src expand.c functions.…

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Tom Kistner
Ημερομηνία:  
Προς: exim-cvs
Αντικείμενο: [exim-cvs] cvs commit: exim/exim-src/src expand.c functions.h host.c tls-openssl.c
tom 2009/10/16 10:10:40 BST

  Modified files:
    exim-src/src         expand.c functions.h host.c tls-openssl.c 
  Log:
  Bugzilla #722


  Revision  Changes    Path
  1.104     +86 -0     exim/exim-src/src/expand.c
  1.46      +1 -0      exim/exim-src/src/functions.h
  1.30      +5 -0      exim/exim-src/src/host.c
  1.17      +71 -3     exim/exim-src/src/tls-openssl.c


  Index: expand.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/expand.c,v
  retrieving revision 1.103
  retrieving revision 1.104
  diff -u -r1.103 -r1.104
  --- expand.c    15 Oct 2009 08:27:37 -0000    1.103
  +++ expand.c    16 Oct 2009 09:10:40 -0000    1.104
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/expand.c,v 1.103 2009/10/15 08:27:37 tom Exp $ */
  +/* $Cambridge: exim/exim-src/src/expand.c,v 1.104 2009/10/16 09:10:40 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -187,6 +187,7 @@
     US"nh",
     US"nhash",
     US"quote",
  +  US"randint",
     US"rfc2047",
     US"rfc2047d",
     US"rxquote",
  @@ -219,6 +220,7 @@
     EOP_NH,
     EOP_NHASH,
     EOP_QUOTE,
  +  EOP_RANDINT,
     EOP_RFC2047,
     EOP_RFC2047D,
     EOP_RXQUOTE,
  @@ -760,6 +762,75 @@



   /*************************************************
  +*        Pseudo-random number generation         *
  +*************************************************/
  +
  +/* Pseudo-random number generation.  The result is not "expected" to be
  +cryptographically strong but not so weak that someone will shoot themselves
  +in the foot using it as a nonce in some email header scheme or whatever
  +weirdness they'll twist this into.  The result should ideally handle fork().
  +
  +However, if we're stuck unable to provide this, then we'll fall back to
  +appallingly bad randomness.
  +
  +If SUPPORT_TLS is defined and OpenSSL is used, then this will not be used.
  +The GNUTLS randomness functions found do not seem amenable to extracting
  +random numbers outside of a TLS context.  Any volunteers?
  +
  +Arguments:
  +  max       range maximum
  +Returns     a random number in range [0, max-1]
  +*/
  +
  +#if !defined(SUPPORT_TLS) || defined(USE_GNUTLS)
  +int
  +pseudo_random_number(int max)
  +{
  +  static pid_t pid = 0;
  +  pid_t p2;
  +#if defined(HAVE_SRANDOM) && !defined(HAVE_SRANDOMDEV)
  +  struct timeval tv;
  +#endif
  +
  +  p2 = getpid();
  +  if (p2 != pid)
  +    {
  +    if (pid != 0)
  +      {
  +
  +#ifdef HAVE_ARC4RANDOM
  +      /* cryptographically strong randomness, common on *BSD platforms, not
  +      so much elsewhere.  Alas. */
  +      arc4random_stir();
  +#elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
  +#ifdef HAVE_SRANDOMDEV
  +      /* uses random(4) for seeding */
  +      srandomdev();
  +#else
  +      gettimeofday(&tv, NULL);
  +      srandom(tv.tv_sec | tv.tv_usec | getpid());
  +#endif
  +#else
  +      /* Poor randomness and no seeding here */
  +#endif
  +
  +      }
  +    pid = p2;
  +    }
  +
  +#ifdef HAVE_ARC4RANDOM
  +  return arc4random() % max;
  +#elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
  +  return random() % max;
  +#else
  +  /* This one returns a 16-bit number, definitely not crypto-strong */
  +  return random_number(max);
  +#endif
  +}
  +
  +#endif
  +
  +/*************************************************
   *             Pick out a name from a string      *
   *************************************************/


  @@ -5704,6 +5775,21 @@
           continue;
           }


  +      /* pseudo-random number less than N */
  +
  +      case EOP_RANDINT:
  +        {
  +        int max;
  +        uschar *s;
  +
  +        max = expand_string_integer(sub, TRUE);
  +        if (expand_string_message != NULL)
  +          goto EXPAND_FAILED;
  +        s = string_sprintf("%d", pseudo_random_number(max));
  +        yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
  +        continue;
  +        }
  +
         /* Unknown operator */


         default:


  Index: functions.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/functions.h,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -r1.45 -r1.46
  --- functions.h    14 Oct 2009 13:52:48 -0000    1.45
  +++ functions.h    16 Oct 2009 09:10:40 -0000    1.46
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/functions.h,v 1.45 2009/10/14 13:52:48 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/functions.h,v 1.46 2009/10/16 09:10:40 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -190,6 +190,7 @@
   extern uschar *parse_message_id(uschar *, uschar **, uschar **);
   extern uschar *parse_quote_2047(uschar *, int, uschar *, uschar *, int, BOOL);
   extern uschar *parse_date_time(uschar *str, time_t *t);
  +extern int     pseudo_random_number(int);


   extern BOOL    queue_action(uschar *, int, uschar **, int, int);
   extern void    queue_check_only(void);


  Index: host.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/host.c,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- host.c    18 Oct 2007 12:01:00 -0000    1.29
  +++ host.c    16 Oct 2009 09:10:40 -0000    1.30
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/host.c,v 1.29 2007/10/18 12:01:00 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/host.c,v 1.30 2009/10/16 09:10:40 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -70,6 +70,9 @@
   very good for the uses to which it is put. When running the regression tests,
   start with a fixed seed.


  +If you need better, see pseudo_random_number() which is potentially stronger,
  +if a crypto library is available, but might end up just calling this instead.
  +
   Arguments:
     limit:    one more than the largest number required


  @@ -79,6 +82,8 @@
   int
   random_number(int limit)
   {
  +if (limit < 1)
  +  return 0;
   if (random_seed == 0)
     {
     if (running_in_test_harness) random_seed = 42; else


  Index: tls-openssl.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-openssl.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- tls-openssl.c    16 Oct 2009 08:34:50 -0000    1.16
  +++ tls-openssl.c    16 Oct 2009 09:10:40 -0000    1.17
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.16 2009/10/16 08:34:50 tom Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.17 2009/10/16 09:10:40 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -26,8 +26,8 @@
   /* Structure for collecting random data for seeding. */


   typedef struct randstuff {
  -  time_t t;
  -  pid_t  p;
  +  struct timeval tv;
  +  pid_t          p;
   } randstuff;


   /* Local static variables */
  @@ -327,7 +327,7 @@
   if (!RAND_status())
     {
     randstuff r;
  -  r.t = time(NULL);
  +  gettimeofday(&r.tv, NULL);
     r.p = getpid();


     RAND_seed((uschar *)(&r), sizeof(r));
  @@ -1053,4 +1053,72 @@
   fprintf(f, "OpenSSL runtime version: %s\n", SSLeay_version(SSLEAY_VERSION));
   }


  +
  +
  +
  +/*************************************************
  +*        Pseudo-random number generation         *
  +*************************************************/
  +
  +/* Pseudo-random number generation.  The result is not expected to be
  +cryptographically strong but not so weak that someone will shoot themselves
  +in the foot using it as a nonce in input in some email header scheme or
  +whatever weirdness they'll twist this into.  The result should handle fork()
  +and avoid repeating sequences.  OpenSSL handles that for us.
  +
  +Arguments:
  +  max       range maximum
  +Returns     a random number in range [0, max-1]
  +*/
  +
  +int
  +pseudo_random_number(int max)
  +{
  +unsigned int r;
  +int i, needed_len;
  +uschar *p;
  +uschar smallbuf[sizeof(r)];
  +
  +if (max <= 1)
  +  return 0;
  +
  +/* OpenSSL auto-seeds from /dev/random, etc, but this a double-check. */
  +if (!RAND_status())
  +  {
  +  randstuff r;
  +  gettimeofday(&r.tv, NULL);
  +  r.p = getpid();
  +
  +  RAND_seed((uschar *)(&r), sizeof(r));
  +  }
  +/* We're after pseudo-random, not random; if we still don't have enough data
  +in the internal PRNG then our options are limited.  We could sleep and hope
  +for entropy to come along (prayer technique) but if the system is so depleted
  +in the first place then something is likely to just keep taking it.  Instead,
  +we'll just take whatever little bit of pseudo-random we can still manage to
  +get. */
  +
  +needed_len = sizeof(r);
  +/* Don't take 8 times more entropy than needed if int is 8 octets and we were
  +asked for a number less than 10. */
  +for (r = max, i = 0; r; ++i)
  +  r >>= 1;
  +i = (i + 7) / 8;
  +if (i < needed_len)
  +  needed_len = i;
  +
  +/* We do not care if crypto-strong */
  +(void) RAND_pseudo_bytes(smallbuf, needed_len);
  +r = 0;
  +for (p = smallbuf; needed_len; --needed_len, ++p)
  +  {
  +  r *= 256;
  +  r += *p;
  +  }
  +
  +/* We don't particularly care about weighted results; if someone wants
  +smooth distribution and cares enough then they should submit a patch then. */
  +return r % max;
  +}
  +
   /* End of tls-openssl.c */