libmisc/salt.c: Use secure system ressources to obtain random bytes.

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>
This commit is contained in:
Björn Esser 2021-07-04 12:10:11 +02:00
parent 9eb191edc4
commit c82ed0c15e
No known key found for this signature in database
GPG Key ID: F52E98007594C21D
2 changed files with 45 additions and 14 deletions

View File

@ -44,18 +44,19 @@ AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ 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 \ 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 \ utime.h ulimit.h sys/capability.h sys/random.h sys/resource.h \
locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \
attr/error_context.h) attr/libattr.h attr/error_context.h)
dnl shadow now uses the libc's shadow implementation 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_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ gethostname getentropy getrandom getspnam gettimeofday getusershell \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \
ruserok dlopen) getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \
dlopen)
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.

View File

@ -15,6 +15,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#if HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include "getdef.h" #include "getdef.h"
@ -128,19 +131,46 @@ static /*@observer@*/char *l64a (long value)
static long read_random_bytes (void) static long read_random_bytes (void)
{ {
long randval = 0; long randval = 0;
#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"); FILE *f = fopen ("/dev/urandom", "r");
if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) {
{
fprintf (shadow_logfd,
_("Unable to read from /dev/urandom.\n"));
fclose(f); fclose(f);
exit (1); goto fail;
} }
fclose(f); fclose(f);
goto end;
#endif
fail:
fprintf (shadow_logfd,
_("Unable to obtain random bytes.\n"));
exit (1);
end:
return randval; return randval;
} }