Move csrand() to a new file csrand.c

A set of APIs similar to arc4random(3) is complex enough to deserve its
own file.

Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
Alejandro Colomar 2022-12-30 19:46:09 +01:00 committed by Serge Hallyn
parent 986ef4e69c
commit be1f4f7972
4 changed files with 65 additions and 51 deletions

View File

@ -356,6 +356,9 @@ extern /*@dependent@*/ /*@null@*/struct commonio_entry *__pw_get_head (void);
extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent); extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent);
extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent); extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent);
/* csrand.c */
unsigned long csrand (void);
/* remove_tree.c */ /* remove_tree.c */
extern int remove_tree (const char *root, bool remove_root); extern int remove_tree (const char *root, bool remove_root);

View File

@ -52,6 +52,7 @@ libmisc_la_SOURCES = \
pwd2spwd.c \ pwd2spwd.c \
pwdcheck.c \ pwdcheck.c \
pwd_init.c \ pwd_init.c \
csrand.c \
remove_tree.c \ remove_tree.c \
rlogin.c \ rlogin.c \
root_flag.c \ root_flag.c \

61
libmisc/csrand.c Normal file
View File

@ -0,0 +1,61 @@
#include <config.h>
#ident "$Id$"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#if HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
#include "bit.h"
#include "prototypes.h"
#include "shadowlog.h"
/*
* Return a uniformly-distributed CS random u_long value.
*/
unsigned long
csrand(void)
{
FILE *fp;
unsigned long r;
#ifdef HAVE_GETENTROPY
/* getentropy may exist but lack kernel support. */
if (getentropy(&r, sizeof(r)) == 0)
return r;
#endif
#ifdef HAVE_GETRANDOM
/* Likewise getrandom. */
if (getrandom(&r, sizeof(r), 0) == sizeof(r))
return r;
#endif
#ifdef HAVE_ARC4RANDOM_BUF
/* arc4random_buf can never fail. */
arc4random_buf(&r, sizeof(r));
return r;
#endif
/* Use /dev/urandom as a last resort. */
fp = fopen("/dev/urandom", "r");
if (NULL == fp) {
goto fail;
}
if (fread(&r, sizeof(r), 1, fp) != 1) {
fclose(fp);
goto fail;
}
fclose(fp);
return r;
fail:
fprintf(log_get_logfd(), _("Unable to obtain random bytes.\n"));
exit(1);
}

View File

@ -20,9 +20,6 @@
#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"
@ -89,7 +86,6 @@
#define GENSALT_SETTING_SIZE 100 #define GENSALT_SETTING_SIZE 100
/* local function prototypes */ /* local function prototypes */
static long csrand (void);
#if !USE_XCRYPT_GENSALT #if !USE_XCRYPT_GENSALT
static /*@observer@*/const char *gensalt (size_t salt_size); static /*@observer@*/const char *gensalt (size_t salt_size);
#endif /* !USE_XCRYPT_GENSALT */ #endif /* !USE_XCRYPT_GENSALT */
@ -109,53 +105,6 @@ static /*@observer@*/unsigned long YESCRYPT_get_salt_cost (/*@null@*/const int *
static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost); static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost);
#endif /* USE_YESCRYPT */ #endif /* USE_YESCRYPT */
/* Read sizeof (long) random bytes from /dev/urandom. */
static long csrand (void)
{
long randval = 0;
#ifdef HAVE_GETENTROPY
/* getentropy may exist but lack kernel support. */
if (getentropy (&randval, sizeof (randval)) == 0) {
goto end;
}
#endif
#ifdef HAVE_GETRANDOM
/* Likewise getrandom. */
if ((size_t) getrandom (&randval, sizeof (randval), 0) == sizeof (randval)) {
goto end;
}
#endif
#ifdef HAVE_ARC4RANDOM_BUF
/* arc4random_buf, if it exists, can never fail. */
arc4random_buf (&randval, sizeof (randval));
goto end;
#endif
/* Use /dev/urandom as a last resort. */
FILE *f = fopen ("/dev/urandom", "r");
if (NULL == f) {
goto fail;
}
if (fread (&randval, sizeof (randval), 1, f) != 1) {
fclose(f);
goto fail;
}
fclose(f);
goto end;
fail:
fprintf (log_get_logfd(),
_("Unable to obtain random bytes.\n"));
exit (1);
end:
return randval;
}
#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT)
/* /*