View Issue Details

IDProjectCategoryView StatusLast Update
0000515LDMud 3.3Otherpublic2009-01-04 13:34
Reporterzesstra Assigned Tozesstra  
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Product Version3.3 
Fixed in Version3.3.718 
Summary0000515: Seeding the PRG with a more reliable source of randomness
DescriptionCurrently the random number generator ist seeded with the system clock at driver startup. This enables people guessing the seed. While this is probably not a big problem in case of a mud, IMHO it is still desirable to enable users to seed the PRG from /dev/urandom or /dev/urandom. (I know, it is possible to seed with a user-defined seed, but this is limited to a single 32-bit value.)
I will attach a small patch, which introduces a command-line argument to choose whether to seed from the current driver time/system clock or with 624 32-bit values from /dev/random or /dev/urandom.
TagsNo tags attached.
Attached Files
randomseed.diff (7,117 bytes)   
--- ldmud-3.3.714.orig/src/main.c	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714/src/main.c	2007-09-14 10:13:49.000000000 +0200
@@ -108,8 +108,6 @@
 
 Bool allow_filename_spaces = MY_FALSE; /* Allow spaces in filenames */
 
-static uint32 random_seed = 0;  /* The seed for the pseudo-random generator. */
-
 static char * hostname = NULL;
 static char * hostaddr = NULL;
   /* Hostname and -addr given on the commandline. They are passed as
@@ -274,9 +272,11 @@
     put_number(&const1, 1);
 
     current_time = get_current_time();
-    random_seed = (uint32)current_time;
-    seed_random(random_seed);
-
+    
+    // init PRG from system clock - if --random-seed or --randominit is given on 
+    // the command-line it will re-seeded later.
+    seed_random(0);
+    
     do {
         dummy_current_object_for_loads = NULL_object;
 #ifdef DEBUG
@@ -430,11 +430,6 @@
         for (i = 0; i < (int)(sizeof avg_consts / sizeof avg_consts[0]); i++)
             avg_consts[i] = exp(- i / 900.0);
 
-        printf("%s Random seed: 0x%lx\n"
-              , time_stamp(), (unsigned long)random_seed);
-        debug_message("%s Random seed: 0x%lx\n"
-                     , time_stamp(), (unsigned long)random_seed);
-
 #ifdef USE_MYSQL
         if (!pkg_mysql_init())
         {
@@ -1044,6 +1039,7 @@
  , cNoHeart         /* --no-heart           */
  , cNoPreload       /* --no-preload         */
  , cPidFile         /* --pidfile            */
+ , cRandominit      /* --randominit         */
  , cRandomSeed      /* --random-seed        */
  , cRegexp          /* --regexp             */
  , cResetTime       /* --reset-time         */
@@ -1482,6 +1478,13 @@
         "    Write the pid of the driver process into <filename>.\n"
       }
 
+    , { 0,   "randominit",         cRandominit,      MY_TRUE
+      , "  --randominit <0|1|2>\n"
+      , "  --randominit <0|1|2>\n"
+        "    Determines the source of the seed for the random number generator.\n"
+        "    0 - init from clock, 1 - init from /dev/random, 2 - init from /dev/urandom\n"
+      }
+
     , { 0,   "random-seed",        cRandomSeed,     MY_TRUE
       , "  --random-seed <num>\n"
       , "  --random-seed <num>\n"
@@ -2513,14 +2516,23 @@
             free(debug_file);
         debug_file = strdup(pValue);
         break;
+        
+    case cRandominit:
+    	// seeds PRG from /dev/urandom, /dev/random or system clock
+#ifdef HAVE_STRTOUL
+        seed_random((ph_uint)strtoul(pValue, (char **)0, 10));
+#else
+        seed_random((ph_uint)strtol(pValue, (char **)0, 10));
+#endif
+    	break;
 
     case cRandomSeed:
+    	// seeds PRG with given value
 #ifdef HAVE_STRTOUL
-        random_seed = strtoul(pValue, (char **)0, 0);
+        seed_random_from_int(strtoul(pValue, (char **)0, 0));
 #else
-        random_seed = (uint32)strtol(pValue, (char **)0, 0);
+        seed_random_from_int((uint32)strtol(pValue, (char **)0, 0));
 #endif
-        seed_random(random_seed);
         break;
 
     case cReserved:
--- ldmud-3.3.714.orig/src/random.h	2006-07-10 04:42:06.000000000 +0200
+++ ldmud-3.3.714/src/random.h	2007-09-14 10:22:10.000000000 +0200
@@ -3,7 +3,12 @@
 
 #include "driver.h"
 
+#define PRG_SEED_CLOCK     0
+#define PRG_SEED_RANDOM    1
+#define PRG_SEED_URANDOM   2
+
 extern uint32 random_number(uint32 n);
-extern void seed_random(uint32 seed);
+extern void seed_random_from_int(uint32 seed);
+extern void seed_random(ph_uint mode);
 
 #endif  /* RANDOM_H__ */
--- ldmud-3.3.714.orig/src/random.c	2006-07-10 04:42:06.000000000 +0200
+++ ldmud-3.3.714/src/random.c	2007-09-14 21:29:29.000000000 +0200
@@ -45,7 +45,10 @@
  *---------------------------------------------------------------------------
  */
 
+#include <stdio.h>
+
 #include "driver.h"
+#include "backend.h"
 #include "random.h"
 
 /* Period parameters */  
@@ -236,20 +239,63 @@
 
 /*-------------------------------------------------------------------------*/
 void
-seed_random (uint32 seed)
+seed_random_from_int (uint32 seed)
 
 /* Initialize the generator */
 
 {
+    printf("%s Seeding PRG with: 0x%lx\n"
+                 , time_stamp(), (unsigned long)seed);
+    debug_message("%s Seeding PRG with: 0x%lx\n"
+                 , time_stamp(), (unsigned long)seed);
+
     unsigned long init[4];
     init[0] = seed & 0xFFF;
     init[1] = (seed >>= 8) & 0xFFF;
     init[2] = (seed >>= 8) & 0xFFF;
     init[3] = (seed >>= 8) & 0xFFF;
     init_by_array(init, 4);
-} /* seed_random() */
+} /* seed_random_from_int() */
 
 /*-------------------------------------------------------------------------*/
+
+void 
+seed_random(ph_uint mode)
+    /* Depending on mode seed the generator with an array of 624 p_int from
+    * /dev/urandom, /dev/random or use the current driver time (the latter
+    * ist also used as fall-back)
+    */
+{
+    FILE *seedsrc = NULL; // Filepointer
+    
+    if (mode==PRG_SEED_RANDOM) {
+        seedsrc = fopen("/dev/random","rb");
+    }
+    else if (mode==PRG_SEED_URANDOM) {
+        seedsrc = fopen("/dev/urandom","rb");
+    }
+    // try getting 624 32-bit values from /dev/(u)random
+    if (seedsrc) {
+        uint32 seeddata[N];
+        ph_uint count = fread( seeddata, sizeof(uint32), N, seedsrc );
+        fclose(seedsrc);
+        if( count == N ) {
+            init_by_array( seeddata, N ); // seed PRG
+            printf("%s Seeding PRG from %s.\n", time_stamp(),
+                    (mode==PRG_SEED_RANDOM?"/dev/random":"/dev/urandom"));
+            debug_message("%s Seeding PRG from %s.\n", time_stamp(),
+                    (mode==PRG_SEED_RANDOM?"/dev/random":"/dev/urandom"));
+            return;
+        } // if (count == N)
+    } // if (seedsrc)
+    // Fall-back: driver clock
+    printf("%s Seeding PRG with current driver time\n"
+                 , time_stamp());
+    debug_message("%s Seeding PRG with current driver time\n"
+                 , time_stamp());
+    seed_random_from_int((uint32)current_time);
+} /* seed_random_from_int() */
+
 uint32
 random_number (uint32 n)
 
--- ldmud-3.3.714.orig/doc/driver/invocation	2006-07-10 04:40:33.000000000 +0200
+++ ldmud-3.3.714/doc/driver/invocation	2007-09-14 21:31:17.000000000 +0200
@@ -245,7 +245,15 @@
       --y|--yydebug
         Enable debugging of the LPC compiler.
         Only available if compiled with YYDEBUG.
-
+				
+      --randominit
+        Chooses the source of the seed for the random number generator.
+        Possible values are: 0 (system clock, default), 1 (/dev/random)
+        and 2 (/dev/urandom).
+        Option 1 and 2 prevent guessing of the PRG seed, 2 is recommended
+        because /dev/urandom doesn't block upon read.
+        (Note: the last one of --randominit and --random-seed wins!)
+				
       --random-seed <num>
         Seed value for the random number generator. If not given, the
         driver chooses a seed value on its own.
@@ -333,3 +341,4 @@
     LDMud 3.3.475/3.2.11 added --tls-key, --tls-cert.
     LDMud 3.3.672/3.2.11 added --tls-trustfile, --tls-trustdirectory.
     LDMud 3.3.677 added --max-mapping-keys.
+		LDMud 3.3.x added --randominit.
randomseed.diff (7,117 bytes)   

Relationships

related to 0000527 resolvedzesstra New version of the Mersenne Twister needed for 64 bit platforms 

Activities

zesstra

2007-09-14 13:37

administrator   ~0000541

Ok, my suggested patch does the following:
- rename random_seed(uint32) to random_seed_from_int(uint32)
- introduce random_seed(ph_uint mode): Seeds the PRG from current_time (mode==0), from /dev/random (mode==1) or from /dev/urandom (mode==2). If /dev/(u)random doesn't supply the 624 uint32 values, current_time will be used as fallback.
- move debug messages concerning the seeding of the PRG from main.c to random.c (seed_random_from_int() and seed_random()).
- removes now unneeded static uint32 random_seed from main.c
- add command-line option --randominit which takes 0|1|2.
- adds --randominit to doc/driver/invocation

The default behaviour of the driver should not be changed by this, /dev/(u)random will only be used if specified at command-line. --random-seed is also usable as before.
BTW: The last one of --randominit or -random-seed in the arguments wins.

zesstra

2009-01-04 13:34

administrator   ~0000848

Combined patch with SFMT (0000527) committed as r2470.

Issue History

Date Modified Username Field Change
2007-09-14 02:37 zesstra New Issue
2007-09-14 13:37 zesstra Note Added: 0000541
2007-09-14 13:38 zesstra File Added: randomseed.diff
2008-06-30 02:57 zesstra Status new => assigned
2008-06-30 02:57 zesstra Assigned To => zesstra
2008-07-02 06:17 zesstra Relationship added related to 0000527
2009-01-04 13:34 zesstra Note Added: 0000848
2009-01-04 13:34 zesstra Status assigned => resolved
2009-01-04 13:34 zesstra Fixed in Version => 3.3.718
2009-01-04 13:34 zesstra Resolution open => fixed