From: Patric Mueller Date: Fri, 11 Jan 2019 18:08:22 +0000 (+0100) Subject: read rng seed from random number source device X-Git-Tag: NetHack-3.6.2_Released~79^2^2~3^2~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86d694c61b62750d314c01f57cdb6c3fa0ca0f5c;p=nethack read rng seed from random number source device Linux and BSD system have random number source devices that can be used as source for a unguessable seed source. Other platforms fall back to generate the seed with gettime(). --- diff --git a/include/extern.h b/include/extern.h index 4f63d9963..d85ad5f8c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -925,7 +925,8 @@ E char *FDECL(strstri, (const char *, const char *)); #endif E boolean FDECL(fuzzymatch, (const char *, const char *, const char *, BOOLEAN_P)); -E void NDECL(setrandom); +E void NDECL(init_random); +E void NDECL(reseed_random); E time_t NDECL(getnow); E int NDECL(getyear); #if 0 diff --git a/include/unixconf.h b/include/unixconf.h index 0c42c6040..3e4748ea2 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -408,5 +408,18 @@ # define RUNTIME_PASTEBUF_SUPPORT #endif +/* + * /dev/random is blocking on Linux, so there we default to /dev/urandom which + * should still be good enough. + * BSD systems usually have /dev/random that is supposed to be used. + */ +#ifdef LINUX +# define DEV_RANDOM "/dev/urandom" +#else +# ifdef BSD +# define DEV_RANDOM "/dev/random" +# endif +#endif + #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/src/hacklib.c b/src/hacklib.c index d0c6915f0..8ceb9fcde 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -848,12 +848,23 @@ extern struct tm *FDECL(localtime, (time_t *)); #endif STATIC_DCL struct tm *NDECL(getlt); -void -setrandom() +/* Returns a number suitable as seed for the random number generator. */ +static unsigned long +get_random_seed() { - unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ + unsigned long seed = 0; +#ifdef DEV_RANDOM + FILE *fptr = NULL; + + fptr = fopen(DEV_RANDOM, "r"); + if (fptr) { + fread(&seed, sizeof(long), 1, fptr); + } + fclose(fptr); +#else + seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ -#if defined(UNIX) || defined(VMS) +# if defined(UNIX) || defined(VMS) { unsigned long pid = (unsigned long) getpid(); @@ -864,28 +875,46 @@ setrandom() seed *= pid; } } +# endif #endif + return seed; +} +/* Sets the seed for the random number generator */ +static void +set_random(unsigned long seed) +{ /* the types are different enough here that sweeping the different * routine names into one via #defines is even more confusing */ #ifdef RANDOM /* srandom() from sys/share/random.c */ srandom((unsigned int) seed); #else -#if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ +# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ || defined(CYGWIN32) /* system srandom() */ -#if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) +# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) (void) -#endif +# endif srandom((int) seed); -#else -#ifdef UNIX /* system srand48() */ +# else +# ifdef UNIX /* system srand48() */ srand48((long) seed); -#else /* poor quality system routine */ +# else /* poor quality system routine */ srand((int) seed); +# endif #endif #endif -#endif +} + +/* + * Initializes the random number generator. + * Only call once. + */ +void +init_random() +{ + unsigned long seed = get_random_seed(); + set_random(seed); } time_t diff --git a/src/options.c b/src/options.c index b3fb0b79e..8fe27c8d4 100644 --- a/src/options.c +++ b/src/options.c @@ -692,7 +692,7 @@ initoptions_init() reset_commands(TRUE); /* init */ /* initialize the random number generator */ - setrandom(); + init_random(); /* for detection of configfile options specified multiple times */ iflags.opt_booldup = iflags.opt_compdup = (int *) 0;