]> granicus.if.org Git - nethack/commitdiff
read rng seed from random number source device
authorPatric Mueller <bhaak@gmx.net>
Fri, 11 Jan 2019 18:08:22 +0000 (19:08 +0100)
committerPatric Mueller <bhaak@gmx.net>
Mon, 28 Jan 2019 09:01:45 +0000 (10:01 +0100)
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().

include/extern.h
include/unixconf.h
src/hacklib.c
src/options.c

index 4f63d99631c6675d942f2f7c07285cb982cc61ce..d85ad5f8cd1fb4d1396b5b8c91a1cc9de1c6a6d2 100644 (file)
@@ -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
index 0c42c60402a5a5729cd68893f0254f67aa7711d9..3e4748ea2a2ee75bb08833062ecbe5e3d04a3068 100644 (file)
 # 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 */
index d0c6915f0b97ae1858a8048a09ea0a4e27d330bc..8ceb9fcde3d88844f9bf836a266cef60c7d59a08 100644 (file)
@@ -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
index b3fb0b79e364b0bc43ad9b0a708d2039d48b3d31..8fe27c8d4a4b66b37ba0c31a129f2cc311fc415b 100644 (file)
@@ -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;