On Wed, Apr 16, 2003 at 10:50:17AM +0100, David Reid wrote:
> > "David Reid" <[EMAIL PROTECTED]> writes:
> >
> > > Ben's point is more (I think) that if we say we're providing randomness
> then
> > > we should provide that.
> >
> > But a caller isn't allowed to *explicitly* ask for poor-quality,
> > non-blocking randomness? Why not? If the word "randomness" bothers
> > people, then let's create a new function that never uses the word:
> > apr_generate_bits_nonblocking() or something.
> >
> > Nobody is arguing that we shouldn't have a function that produces
> > high-quality randomness. Most of the time, that's what people want.
> > But we *also* need the ability to produce very poor randomness which
> > doesn't ever block for entropy.
>
> Why? Please provide some cases that aren't SVN specific...
The issue is the UUID code in apr-util, and it's not really SVN
specific. Here's how I'd do it: add apr_generate_weak_random_bytes(),
which MAY use /dev/urandom if available. Any objections to the below
patch?
(you could do this with a "non-blocking" interface which returns EAGAIN
when /dev/random runs dry. But then the caller would have to fall back
on their pet gettimeofday()-based random byte generator, which won't be
as good as /dev/urandom, so I prefer this solution)
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.525
diff -u -r1.525 configure.in
--- configure.in 15 Apr 2003 21:45:57 -0000 1.525
+++ configure.in 16 Apr 2003 11:02:12 -0000
@@ -1686,6 +1686,16 @@
if test "$rand" = "1"; then
AC_DEFINE_UNQUOTED(DEV_RANDOM, ["$apr_devrandom"], [Define to path of
random device])
AC_MSG_RESULT([$apr_devrandom])
+ if test "x$apr_devrandom" != "x/dev/urandom"; then
+ AC_MSG_CHECKING(for /dev/urandom)
+ # See whether an alternative interface is also available
+ if test -r /dev/urandom; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DEVURANDOM, 1, [Define if /dev/urandom is available])
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
fi
fi
Index: include/apr_general.h
===================================================================
RCS file: /home/cvs/apr/include/apr_general.h,v
retrieving revision 1.80
diff -u -r1.80 apr_general.h
--- include/apr_general.h 5 Mar 2003 21:22:26 -0000 1.80
+++ include/apr_general.h 16 Apr 2003 11:02:12 -0000
@@ -265,7 +265,8 @@
/* TODO: I'm not sure this is the best place to put this prototype...*/
/**
- * Generate random bytes.
+ * Generate random bytes of highest quality available. This function may
+ * take some time to complete if no entropy sources are available.
* @param buf Buffer to fill with random bytes
* @param length Length of buffer in bytes (becomes apr_size_t in APR 1.0)
*/
@@ -275,6 +276,15 @@
#else
APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf,
int length);
+/** Generate weak random bytes; on some platforms, this function may
+ * be able to provide weaker quality random bytes quickly, when high
+ * quality random bytes are not available. On other platforms it will
+ * be equivalent to apr_generate_random_bytes.
+ * @param buf Buffer to fill with random bytes
+ * @param length Length of buffer in bytes (becomes apr_size_t in APR 1.0)
+ */
+APR_DECLARE(apr_status_t) apr_generate_weak_random_bytes(unsigned char * buf,
+ int length);
#endif
#endif
Index: misc/unix/rand.c
===================================================================
RCS file: /home/cvs/apr/misc/unix/rand.c,v
retrieving revision 1.21
diff -u -r1.21 rand.c
--- misc/unix/rand.c 13 Jan 2003 18:23:09 -0000 1.21
+++ misc/unix/rand.c 16 Apr 2003 11:02:12 -0000
@@ -80,15 +80,10 @@
#if APR_HAS_RANDOM
-APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
-#ifdef APR_ENABLE_FOR_1_0
- apr_size_t length)
-#else
- int length)
-#endif
-{
#ifdef DEV_RANDOM
-
+/* FIXME: use size_t length for 1.0 */
+static apr_ssize_t read_random(const char *device, char *buf, int length)
+{
int fd = -1;
/* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
@@ -98,7 +93,7 @@
apr_ssize_t rc;
if (fd == -1)
- if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
+ if ((fd = open(device, O_RDONLY)) == -1)
return errno;
rc = read(fd, buf, length);
@@ -118,6 +113,28 @@
} while (length > 0);
close(fd);
+
+ return APR_SUCCESS;
+}
+#endif
+
+/* FIXME: use size_t length for 1.0 */
+APR_DECLARE(apr_status_t) apr_generate_weak_random_bytes(unsigned char *buf,
+ int length)
+{
+#if defined(HAVE_DEVURANDOM)
+ return read_random("/dev/urandom", buf, length);
+#else
+ return apr_generate_random_bytes(buf, length);
+#endif
+}
+
+/* FIXME: use size_t length for 1.0 */
+APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
+ int length)
+{
+#ifdef DEV_RANDOM
+ return read_random(DEV_RANDOM, buf, length);
#elif defined(OS2)
static UCHAR randbyte();
unsigned int idx;
@@ -125,6 +142,7 @@
for (idx=0; idx<length; idx++)
buf[idx] = randbyte();
+ return APR_SUCCESS;
#elif defined(HAVE_EGD)
/* use EGD-compatible socket daemon (such as EGD or PRNGd).
* message format:
@@ -221,6 +239,7 @@
return bad_errno;
}
+ return APR_SUCCESS;
#elif defined(HAVE_TRUERAND) /* use truerand */
extern int randbyte(void); /* from the truerand library */
@@ -232,9 +251,8 @@
for (idx=0; idx<length; idx++)
buf[idx] = (unsigned char) randbyte();
-#endif /* DEV_RANDOM */
-
return APR_SUCCESS;
+#endif /* DEV_RANDOM */
}
#undef STR
Index: test/testrand.c
===================================================================
RCS file: /home/cvs/apr/test/testrand.c,v
retrieving revision 1.10
diff -u -r1.10 testrand.c
--- test/testrand.c 1 Jan 2003 00:01:56 -0000 1.10
+++ test/testrand.c 16 Apr 2003 11:02:12 -0000
@@ -71,7 +71,7 @@
* what it is right now.
*/
for (i = 1; i <= 8; i++) {
- rv = apr_generate_random_bytes(c, i * 255);
+ rv = apr_generate_weak_random_bytes(c, i * 255);
apr_assert_success(tc, "apr_generate_random_bytes failed", rv);
}
#endif