Hi,
dovecot tries to use OpenSSL's PRNG to generate random numbers if
there is no /dev/urandom found. Unfortunately, it is flawed in its
present
form, since the PRNG is not seeded before RAND_bytes() is called in
src/lib/randgen.c (on systems which have /dev/urandom, OpenSSL
automatically seeds its PRNG from the urandom device).
Here's a patch to address this issue: it tries to seed the PRNG if there
is no /dev/urandom present (which is likely the case if dovecot uses
OpenSSL's RAND API). It can also be fetched from
http://innoidea.com/~vili/dovecot_rng_init.diff
-Vilmos Nebehaj
Index: configure.in
==================================================================RCS file:
/home/cvs/dovecot/configure.in,v
retrieving revision 1.266
diff -u -r1.266 configure.in
--- configure.in 28 Feb 2006 08:36:41 -0000 1.266
+++ configure.in 10 Mar 2006 17:15:01 -0000
@@ -358,7 +358,8 @@
AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize
madvise \
strcasecmp stricmp vsnprintf vsyslog writev pread \
setrlimit setproctitle seteuid setreuid setegid setresgid \
- strtoull strtouq setpriority quotactl getmntent kqueue kevent)
+ strtoull strtouq setpriority quotactl getmntent kqueue kevent \
+ getrusage)
dnl * I/O loop function
have_ioloop=no
Index: src/lib/lib.h
==================================================================RCS file:
/home/cvs/dovecot/src/lib/lib.h,v
retrieving revision 1.20
diff -u -r1.20 lib.h
--- src/lib/lib.h 25 Sep 2005 10:44:04 -0000 1.20
+++ src/lib/lib.h 10 Mar 2006 17:15:02 -0000
@@ -20,6 +20,13 @@
# include <stdint.h> /* C99 int types, we mostly need uintmax_t */
#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/resource.h>
+#endif
+
#include "compat.h"
#include "macros.h"
#include "failures.h"
Index: src/lib/randgen.c
==================================================================RCS file:
/home/cvs/dovecot/src/lib/randgen.c,v
retrieving revision 1.13
diff -u -r1.13 randgen.c
--- src/lib/randgen.c 6 Jan 2005 19:08:19 -0000 1.13
+++ src/lib/randgen.c 10 Mar 2006 17:15:03 -0000
@@ -81,6 +81,42 @@
return buf;
}
+static void random_init_rng(void)
+{
+ int counter = 0;
+ struct timeval tv;
+#ifdef HAVE_GETRUSAGE
+ struct rusage ru;
+#endif
+
+ /*
+ * If the RNG is already seeded, we can return
+ * immediately.
+ */
+ if (RAND_status() == 1)
+ return;
+
+ /*
+ * Else, try to seed it. Unfortunately we don't have
+ * /dev/urandom, so we can only use weak random sources.
+ */
+ while (RAND_status() != 1) {
+ if (gettimeofday(&tv, NULL) < 0)
+ i_fatal("gettimeofday() failed: %m");
+ RAND_add((const void *)&tv, sizeof(tv),
+ (double)sizeof(tv) / 2);
+#ifdef HAVE_GETRUSAGE
+ if (getrusage(RUSAGE_SELF, &ru) < 0)
+ i_fatal("getrusage() failed: %m");
+ RAND_add((const void *)&ru, sizeof(ru),
+ (double)sizeof(ru) / 2);
+#endif
+
+ if (counter++ > 100)
+ i_fatal("could not get enough entropy");
+ }
+}
+
void random_fill(void *buf, size_t size)
{
if (RAND_bytes(buf, size) != 1)
@@ -91,6 +127,8 @@
{
unsigned int seed;
+ random_init_rng();
+
random_fill(&seed, sizeof(seed));
srand(seed);
}