From bc8257cf73328e450511b13cbd35e1994feccb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Wed, 23 Jun 2021 16:06:47 +0200 Subject: [PATCH] libmisc/salt.c: Obtain random bytes from /dev/urandom. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the random() function to obtain pseudo-random bytes for generating salt strings is considered to be dangerous. See CWE-327. We really should use a more reliable source for obtaining pseudo-random bytes like /dev/urandom. Fixes #376. Signed-off-by: Björn Esser --- libmisc/salt.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/libmisc/salt.c b/libmisc/salt.c index e17093fc..af9f011f 100644 --- a/libmisc/salt.c +++ b/libmisc/salt.c @@ -11,11 +11,10 @@ #ident "$Id$" -#include -#include -#include -#include #include +#include +#include +#include #include "prototypes.h" #include "defines.h" #include "getdef.h" @@ -74,7 +73,7 @@ #define GENSALT_SETTING_SIZE 100 /* local function prototypes */ -static void seedRNG (void); +static long read_random_bytes (void); static /*@observer@*/const char *gensalt (size_t salt_size); #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) static long shadow_random (long min, long max); @@ -125,23 +124,27 @@ static /*@observer@*/char *l64a (long value) } #endif /* !HAVE_L64A */ -static void seedRNG (void) +/* Read sizeof (long) random bytes from /dev/urandom. */ +static long read_random_bytes (void) { - struct timeval tv; - static int seeded = 0; + long randval = 0; + FILE *f = fopen ("/dev/urandom", "r"); - if (0 == seeded) { - (void) gettimeofday (&tv, NULL); - srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ()); - seeded = 1; + if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) + { + fprintf (shadow_logfd, + _("Unable to read from /dev/urandom.\n")); + + fclose(f); + exit (1); } + + fclose(f); + + return randval; } #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -/* It is not clear what is the maximum value of random(). - * We assume 2^31-1.*/ -#define RANDOM_MAX 0x7FFFFFFF - /* * Return a random number between min and max (both included). * @@ -151,8 +154,9 @@ static long shadow_random (long min, long max) { double drand; long ret; - seedRNG (); - drand = (double) (max - min + 1) * random () / RANDOM_MAX; + + drand = (double) (read_random_bytes () & RAND_MAX) / (double) RAND_MAX; + drand *= (double) (max - min + 1); /* On systems were this is not random() range is lower, we favor * higher numbers of salt. */ ret = (long) (max + 1 - drand); @@ -354,10 +358,9 @@ static /*@observer@*/const char *gensalt (size_t salt_size) assert (salt_size >= MIN_SALT_SIZE && salt_size <= MAX_SALT_SIZE); - seedRNG (); - strcat (salt, l64a (random())); + strcat (salt, l64a (read_random_bytes ())); do { - strcat (salt, l64a (random())); + strcat (salt, l64a (read_random_bytes ())); } while (strlen (salt) < salt_size); salt[salt_size] = '\0';