shadow-utils/shadow-4.8.1-salt_c_use_dev...

115 lines
3.1 KiB
Diff

From bc8257cf73328e450511b13cbd35e1994feccb30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
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 <besser82@fedoraproject.org>
---
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 <sys/time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#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';