]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
libmisc/salt.c: Use secure system ressources to obtain random bytes. 380/head
authorBjörn Esser <besser82@fedoraproject.org>
Sun, 4 Jul 2021 10:10:11 +0000 (12:10 +0200)
committerBjörn Esser <besser82@fedoraproject.org>
Sun, 4 Jul 2021 11:00:32 +0000 (13:00 +0200)
In a previous commit we introduced /dev/urandom as a source to obtain
random bytes from.  This may not be available on all systems, or when
operating inside of a chroot.

Almost all systems provide functions to obtain random bytes from
secure system ressources.  Thus we should prefer to use these, and
fall back to /dev/urandom, if there is no such function present, as
a last resort.

Signed-off-by: Björn Esser <besser82@fedoraproject.org>
configure.ac
libmisc/salt.c

index 010072c7ff3f6ab733fef3b51a2cb11c50111663..111de09e52a297840dd68640829a0c2d3e79ce20 100644 (file)
@@ -44,18 +44,19 @@ AC_HEADER_STDBOOL
 
 AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
        utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
-       utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \
-       locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \
-       attr/error_context.h)
+       utime.h ulimit.h sys/capability.h sys/random.h sys/resource.h \
+       gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \
+       attr/libattr.h attr/error_context.h)
 
 dnl shadow now uses the libc's shadow implementation
 AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
 
-AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
-       gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
-       lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
-       getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \
-       ruserok dlopen)
+AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \
+       gethostname getentropy getrandom getspnam gettimeofday getusershell \
+       getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \
+       setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \
+       getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \
+       dlopen)
 AC_SYS_LARGEFILE
 
 dnl Checks for typedefs, structures, and compiler characteristics.
index af9f011fa3833900d979a2d129f53f8c75896aff..13408a537f1b2764918c52572342b1616843f2ec 100644 (file)
@@ -15,6 +15,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#if HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
 #include "prototypes.h"
 #include "defines.h"
 #include "getdef.h"
@@ -128,19 +131,46 @@ static /*@observer@*/char *l64a (long value)
 static long read_random_bytes (void)
 {
        long randval = 0;
-       FILE *f = fopen ("/dev/urandom", "r");
 
-       if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval))
-       {
-               fprintf (shadow_logfd,
-                        _("Unable to read from /dev/urandom.\n"));
+#ifdef HAVE_ARC4RANDOM_BUF
+       /* arc4random_buf, if it exists, can never fail.  */
+       arc4random_buf (&randval, sizeof (randval));
+       goto end;
 
+#elif defined(HAVE_GETENTROPY)
+       /* getentropy may exist but lack kernel support.  */
+       if (getentropy (&randval, sizeof (randval))) {
+               goto fail;
+       }
+
+       goto end;
+
+#elif defined(HAVE_GETRANDOM)
+       /* Likewise getrandom.  */
+       if ((size_t) getrandom (&randval, sizeof (randval), 0) != sizeof (randval)) {
+               goto fail;
+       }
+
+       goto end;
+
+#else
+       FILE *f = fopen ("/dev/urandom", "r");
+
+       if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) {
                fclose(f);
-               exit (1);
+               goto fail;
        }
 
        fclose(f);
+       goto end;
+#endif
+
+fail:
+       fprintf (shadow_logfd,
+                _("Unable to obtain random bytes.\n"));
+       exit (1);
 
+end:
        return randval;
 }