From 2040d4dde54a8ca0840b5b76b2e3e665af7c09fb Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 31 Oct 2014 06:57:19 -0600 Subject: [PATCH] Use arc4random() for mkstemp/mkdtemp if available. If not, try to seed from /dev/urandom before falling back to the gettimeofday seed. --- config.h.in | 3 +++ configure | 2 +- configure.ac | 2 +- lib/util/mktemp.c | 58 ++++++++++++++++++++++++++++++++--------------- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/config.h.in b/config.h.in index 0acb6d1fe..0b0234a1b 100644 --- a/config.h.in +++ b/config.h.in @@ -52,6 +52,9 @@ /* Define to 1 if you use AIX general authentication. */ #undef HAVE_AIXAUTH +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF diff --git a/configure b/configure index b0b21aab7..7310c3f1d 100755 --- a/configure +++ b/configure @@ -18401,7 +18401,7 @@ fi done if test X"$ac_cv_func_mkstemps$ac_cv_func_mkdtemp" != X"yesyes"; then - for ac_func in random lrand48 + for ac_func in arc4random random lrand48 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 546b98126..f4fa0c775 100644 --- a/configure.ac +++ b/configure.ac @@ -2520,7 +2520,7 @@ AC_CHECK_FUNCS(closefrom, [], [AC_LIBOBJ(closefrom) ]) AC_CHECK_FUNCS(mkstemps mkdtemp, [], [break]) if test X"$ac_cv_func_mkstemps$ac_cv_func_mkdtemp" != X"yesyes"; then - AC_CHECK_FUNCS(random lrand48, [break]) + AC_CHECK_FUNCS(arc4random random lrand48, [break]) AC_LIBOBJ(mktemp) # If either mkdtemp() or mkstemps() is missing, replace both. SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkstemps) diff --git a/lib/util/mktemp.c b/lib/util/mktemp.c index 87ed760fa..50ce6ccda 100644 --- a/lib/util/mktemp.c +++ b/lib/util/mktemp.c @@ -50,35 +50,57 @@ #define INT_MAX 0x7fffffff #endif -#ifdef HAVE_RANDOM -# define RAND random -# define SRAND srandom +#if defined(HAVE_ARC4RANDOM) +# define RAND() arc4random() # define SEED_T unsigned int +#elif defined(HAVE_RANDOM) +# define RAND() random() +# define SRAND(_x) srandom((_x)) +# define SEED_T unsigned int +#elif defined(HAVE_LRAND48) +# define RAND() lrand48() +# define SRAND(_x) srand48((_x)) +# define SEED_T long #else -# ifdef HAVE_LRAND48 -# define RAND lrand48 -# define SRAND srand48 -# define SEED_T long -# else -# define RAND rand -# define SRAND srand -# define SEED_T unsigned int -# endif +# define RAND() rand() +# define SRAND(_x) srand((_x)) +# define SEED_T unsigned int #endif static void seed_random(void) { - SEED_T seed; +#ifdef SRAND struct timeval tv; + SEED_T seed; + int fd; /* - * Seed from time of day and process id multiplied by small primes. + * Seed from /dev/urandom if possible. */ - (void) gettimeofday(&tv, NULL); - seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 + - (getpid() % 1000) * 983; + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + ssize_t nread; + + do { + nread = read(fd, &seed, sizeof(seed)); + } while (nread == -1 && errno == EINTR); + close(fd); + if (nread != (ssize_t)sizeof(seed)) + fd = -1; + } + + /* + * If no /dev/urandom, seed from time of day and process id + * multiplied by small primes. + */ + if (fd == -1) { + (void) gettimeofday(&tv, NULL); + seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 + + (getpid() % 1000) * 983; + } SRAND(seed); +#endif } static unsigned int @@ -98,7 +120,7 @@ static int mktemp_internal(char *path, int slen, int mode) { char *start, *cp, *ep; - const char *tempchars = TEMPCHARS; + const char tempchars[] = TEMPCHARS; unsigned int r, tries; int fd; -- 2.40.0