From c82ed0c15e0e9e47df0b4c22672b72e35f061a9d From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sun, 4 Jul 2021 12:10:11 +0200 Subject: [PATCH] libmisc/salt.c: Use secure system ressources to obtain random bytes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- configure.ac | 17 +++++++++-------- libmisc/salt.c | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 14 deletions(-) Index: shadow-4.8.1/configure.ac =================================================================== --- shadow-4.8.1.orig/configure.ac +++ shadow-4.8.1/configure.ac @@ -44,18 +44,19 @@ AC_HEADER_STDBOOL AC_CHECK_HEADERS(crypt.h 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: shadow-4.8.1/libmisc/salt.c =================================================================== --- shadow-4.8.1.orig/libmisc/salt.c +++ shadow-4.8.1/libmisc/salt.c @@ -15,6 +15,9 @@ #include #include #include +#if HAVE_SYS_RANDOM_H +#include +#endif #include "prototypes.h" #include "defines.h" #include "getdef.h" @@ -128,19 +131,46 @@ static /*@observer@*/char *l64a (long va 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; }