diff options
Diffstat (limited to 'source4/heimdal/lib/hcrypto/rand-unix.c')
-rw-r--r-- | source4/heimdal/lib/hcrypto/rand-unix.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/source4/heimdal/lib/hcrypto/rand-unix.c b/source4/heimdal/lib/hcrypto/rand-unix.c index 0c2185776c..07d81eb620 100644 --- a/source4/heimdal/lib/hcrypto/rand-unix.c +++ b/source4/heimdal/lib/hcrypto/rand-unix.c @@ -40,11 +40,15 @@ RCSID("$Id$"); #include <stdio.h> #include <stdlib.h> #include <rand.h> +#include <heim_threads.h> #include <roken.h> #include "randi.h" +static int random_fd = -1; +static HEIMDAL_MUTEX random_mutex = HEIMDAL_MUTEX_INITIALIZER; + /* * Unix /dev/random */ @@ -88,31 +92,47 @@ unix_seed(const void *indata, int size) } + static int unix_bytes(unsigned char *outdata, int size) { ssize_t count; - int fd; + int once = 0; if (size <= 0) return 0; - fd = get_device_fd(O_RDONLY); - if (fd < 0) - return 0; + HEIMDAL_MUTEX_lock(&random_mutex); + if (random_fd == -1) { + retry: + random_fd = get_device_fd(O_RDONLY); + if (random_fd < 0) { + HEIMDAL_MUTEX_unlock(&random_mutex); + return 0; + } + } while (size > 0) { - count = read (fd, outdata, size); - if (count < 0 && errno == EINTR) - continue; - else if (count <= 0) { - close(fd); + HEIMDAL_MUTEX_unlock(&random_mutex); + count = read (random_fd, outdata, size); + HEIMDAL_MUTEX_lock(&random_mutex); + if (random_fd < 0) { + if (errno == EINTR) + continue; + else if (errno == EBADF && once++ == 0) { + close(random_fd); + random_fd = -1; + goto retry; + } + return 0; + } else if (count <= 0) { + HEIMDAL_MUTEX_unlock(&random_mutex); return 0; } outdata += count; size -= count; } - close(fd); + HEIMDAL_MUTEX_unlock(&random_mutex); return 1; } |