X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/86b416a7b0dcaa6ade285a86b69afd28cbf8ac58..27c47c0ad07c3e63270ef33b5f3f7226d4d58582:/entropy.c diff --git a/entropy.c b/entropy.c index 260d5bdf..9588f792 100644 --- a/entropy.c +++ b/entropy.c @@ -26,6 +26,7 @@ #include #include +#include /* SunOS 4.4.4 needs this */ #ifdef HAVE_FLOATINGPOINT_H @@ -67,46 +68,85 @@ RCSID("$Id$"); # define SAVED_IDS_WORK_WITH_SETEUID #endif -#if defined(EGD_SOCKET) || defined(RANDOM_POOL) +static void +check_openssl_version(void) +{ + if (SSLeay() != OPENSSL_VERSION_NUMBER) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); +} + +#if defined(PRNGD_SOCKET) || defined(PRNGD_PORT) +# define USE_PRNGD +#endif + +#if defined(USE_PRNGD) || defined(RANDOM_POOL) -#ifdef EGD_SOCKET -/* Collect entropy from EGD */ -int get_random_bytes(unsigned char *buf, int len) +#ifdef USE_PRNGD +/* Collect entropy from PRNGD/EGD */ +int +get_random_bytes(unsigned char *buf, int len) { int fd; char msg[2]; +#ifdef PRNGD_PORT + struct sockaddr_in addr; +#else struct sockaddr_un addr; +#endif int addr_len, rval, errors; mysig_t old_sigpipe; + memset(&addr, '\0', sizeof(addr)); + +#ifdef PRNGD_PORT + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(PRNGD_PORT); + addr_len = sizeof(struct sockaddr_in); +#else /* use IP socket PRNGD_SOCKET instead */ /* Sanity checks */ - if (sizeof(EGD_SOCKET) > sizeof(addr.sun_path)) + if (sizeof(PRNGD_SOCKET) > sizeof(addr.sun_path)) fatal("Random pool path is too long"); if (len > 255) - fatal("Too many bytes to read from EGD"); + fatal("Too many bytes to read from PRNGD"); - memset(&addr, '\0', sizeof(addr)); addr.sun_family = AF_UNIX; - strlcpy(addr.sun_path, EGD_SOCKET, sizeof(addr.sun_path)); - addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(EGD_SOCKET); + strlcpy(addr.sun_path, PRNGD_SOCKET, sizeof(addr.sun_path)); + addr_len = offsetof(struct sockaddr_un, sun_path) + + sizeof(PRNGD_SOCKET); +#endif old_sigpipe = mysignal(SIGPIPE, SIG_IGN); errors = rval = 0; reopen: - fd = socket(AF_UNIX, SOCK_STREAM, 0); +#ifdef PRNGD_PORT + fd = socket(addr.sin_family, SOCK_STREAM, 0); + if (fd == -1) { + error("Couldn't create AF_INET socket: %s", strerror(errno)); + goto done; + } +#else + fd = socket(addr.sun_family, SOCK_STREAM, 0); if (fd == -1) { error("Couldn't create AF_UNIX socket: %s", strerror(errno)); goto done; } +#endif if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) { - error("Couldn't connect to EGD socket \"%s\": %s", - addr.sun_path, strerror(errno)); +#ifdef PRNGD_PORT + error("Couldn't connect to PRNGD port %d: %s", + PRNGD_PORT, strerror(errno)); +#else + error("Couldn't connect to PRNGD socket \"%s\": %s", + addr.sun_path, strerror(errno)); +#endif goto done; } - /* Send blocking read request to EGD */ + /* Send blocking read request to PRNGD */ msg[0] = 0x02; msg[1] = len; @@ -116,8 +156,8 @@ reopen: errors++; goto reopen; } - error("Couldn't write to EGD socket \"%s\": %s", - EGD_SOCKET, strerror(errno)); + error("Couldn't write to PRNGD socket: %s", + strerror(errno)); goto done; } @@ -127,8 +167,8 @@ reopen: errors++; goto reopen; } - error("Couldn't read from EGD socket \"%s\": %s", - EGD_SOCKET, strerror(errno)); + error("Couldn't read from PRNGD socket: %s", + strerror(errno)); goto done; } @@ -139,10 +179,11 @@ done: close(fd); return(rval); } -#else /* !EGD_SOCKET */ +#else /* !USE_PRNGD */ #ifdef RANDOM_POOL /* Collect entropy from /dev/urandom or pipe */ -int get_random_bytes(unsigned char *buf, int len) +static int +get_random_bytes(unsigned char *buf, int len) { int random_pool; @@ -165,16 +206,16 @@ int get_random_bytes(unsigned char *buf, int len) return(1); } #endif /* RANDOM_POOL */ -#endif /* EGD_SOCKET */ +#endif /* USE_PRNGD */ /* * Seed OpenSSL's random number pool from Kernel random number generator - * or EGD + * or PRNGD/EGD */ void seed_rng(void) { - char buf[32]; + unsigned char buf[32]; debug("Seeding random number generator"); @@ -188,10 +229,13 @@ seed_rng(void) memset(buf, '\0', sizeof(buf)); } -/* No-op */ -void init_rng(void) {} +void +init_rng(void) +{ + check_openssl_version(); +} -#else /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ +#else /* defined(USE_PRNGD) || defined(RANDOM_POOL) */ /* * FIXME: proper entropy estimations. All current values are guesses @@ -363,8 +407,7 @@ stir_rusage(int who, double entropy_estimate) } -static -int +static int _get_timeval_msec_difference(struct timeval *t1, struct timeval *t2) { int secdiff, usecdiff; @@ -462,7 +505,9 @@ hash_output_from_command(entropy_source_t *src, char *hash) break; case 1: /* command input */ - bytes_read = read(p[0], buf, sizeof(buf)); + do { + bytes_read = read(p[0], buf, sizeof(buf)); + } while (bytes_read == -1 && errno == EINTR); RAND_add(&bytes_read, sizeof(&bytes_read), 0.0); if (bytes_read == -1) { error_abort = 1; @@ -802,8 +847,10 @@ seed_rng(void) /* commands */ old_sigchld_handler = mysignal(SIGCHLD, SIG_DFL); - debug("Seeded RNG with %i bytes from programs", (int)stir_from_programs()); - debug("Seeded RNG with %i bytes from system calls", (int)stir_from_system()); + debug("Seeded RNG with %i bytes from programs", + (int)stir_from_programs()); + debug("Seeded RNG with %i bytes from system calls", + (int)stir_from_system()); if (!RAND_status()) fatal("Not enough entropy in RNG"); @@ -814,10 +861,13 @@ seed_rng(void) fatal("Couldn't initialise builtin random number generator -- exiting."); } -void init_rng(void) +void +init_rng(void) { int original_euid; + check_openssl_version(); + original_uid = getuid(); original_euid = geteuid(); @@ -837,8 +887,8 @@ void init_rng(void) * Propagate the privileged uid to all of our uids. * Set the effective uid to the given (unprivileged) uid. */ - if (original_uid != original_euid && setuid(original_euid) == -1 || - seteuid(original_uid) == -1) + if (original_uid != original_euid && (setuid(original_euid) == -1 || + seteuid(original_uid) == -1)) fatal("Couldn't give up privileges"); #endif /* SAVED_IDS_WORK_WITH_SETEUID */ @@ -853,8 +903,8 @@ void init_rng(void) * Propagate the real uid (usually more privileged) to effective uid * as well. */ - if (original_uid != original_euid && seteuid(original_euid) == -1 || - setuid(original_uid) == -1) + if (original_uid != original_euid && (seteuid(original_euid) == -1 || + setuid(original_uid) == -1)) fatal("Couldn't restore privileges"); #endif /* SAVED_IDS_WORK_WITH_SETEUID */ @@ -864,4 +914,4 @@ void init_rng(void) prng_initialised = 1; } -#endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ +#endif /* defined(USE_PRNGD) || defined(RANDOM_POOL) */