summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hcrypto/rand-unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/hcrypto/rand-unix.c')
-rw-r--r--source4/heimdal/lib/hcrypto/rand-unix.c40
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;
}