diff options
-rw-r--r-- | cli-authpubkey.c | 2 | ||||
-rw-r--r-- | cli-main.c | 8 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | dbrandom.c | 144 | ||||
-rw-r--r-- | includes.h | 4 |
5 files changed, 105 insertions, 58 deletions
diff --git a/cli-authpubkey.c b/cli-authpubkey.c index fef0f27..42c4e3f 100644 --- a/cli-authpubkey.c +++ b/cli-authpubkey.c @@ -184,7 +184,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, /* Returns 1 if a key was tried */ int cli_auth_pubkey() { - enum signature_type sigtype; + enum signature_type sigtype = DROPBEAR_SIGNATURE_NONE; TRACE(("enter cli_auth_pubkey")) #if DROPBEAR_CLI_AGENTFWD @@ -131,6 +131,12 @@ static void cli_dropbear_log(int priority, const char* format, va_list param) { char printbuf[1024]; + const char *name; + + name = cli_opts.progname; + if (!name) { + name = "dbclient"; + } vsnprintf(printbuf, sizeof(printbuf), format, param); @@ -140,7 +146,7 @@ static void cli_dropbear_log(int priority, } #endif - fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf); + fprintf(stderr, "%s: %s\n", name, printbuf); fflush(stderr); } diff --git a/configure.ac b/configure.ac index bcb6e4a..848c261 100644 --- a/configure.ac +++ b/configure.ac @@ -370,7 +370,8 @@ AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \ crypt.h \ pty.h libutil.h libgen.h inttypes.h stropts.h utmp.h \ utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \ - pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h]) + pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \ + sys/random.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -526,7 +527,7 @@ AC_CHECK_FUNCS(clock_gettime) AC_CHECK_HEADERS([mach/mach_time.h]) AC_CHECK_FUNCS(mach_absolute_time) -AC_CHECK_FUNCS(explicit_bzero memset_s) +AC_CHECK_FUNCS(explicit_bzero memset_s getrandom) AC_ARG_ENABLE(bundled-libtom, [ --enable-bundled-libtom Force using bundled libtomcrypt/libtommath even if a system version exists. @@ -49,24 +49,19 @@ static int donerandinit = 0; * */ -/* Pass len=0 to hash an entire file */ +/* Pass wantlen=0 to hash an entire file */ static int process_file(hash_state *hs, const char *filename, - unsigned int len, int prngd) -{ - static int already_blocked = 0; + unsigned int wantlen, int prngd) { int readfd; unsigned int readcount; int ret = DROPBEAR_FAILURE; + if (prngd) { #if DROPBEAR_USE_PRNGD - if (prngd) - { readfd = connect_unix(filename); - } - else #endif - { + } else { readfd = open(filename, O_RDONLY); } @@ -75,58 +70,31 @@ process_file(hash_state *hs, const char *filename, } readcount = 0; - while (len == 0 || readcount < len) - { + while (wantlen == 0 || readcount < wantlen) { int readlen, wantread; unsigned char readbuf[4096]; - if (!already_blocked && !prngd) - { - int res; - struct timeval timeout; - fd_set read_fds; - - timeout.tv_sec = 2; - timeout.tv_usec = 0; - - DROPBEAR_FD_ZERO(&read_fds); - FD_SET(readfd, &read_fds); - res = select(readfd + 1, &read_fds, NULL, NULL, &timeout); - if (res == 0) - { - dropbear_log(LOG_WARNING, "Warning: Reading the randomness source '%s' seems to have blocked.\nYou may need to find a better entropy source.", filename); - already_blocked = 1; - } - } - - if (len == 0) - { + if (wantlen == 0) { wantread = sizeof(readbuf); - } - else - { - wantread = MIN(sizeof(readbuf), len-readcount); + } else { + wantread = MIN(sizeof(readbuf), wantlen-readcount); } #if DROPBEAR_USE_PRNGD - if (prngd) - { + if (prngd) { char egdcmd[2]; egdcmd[0] = 0x02; /* blocking read */ egdcmd[1] = (unsigned char)wantread; - if (write(readfd, egdcmd, 2) < 0) - { + if (write(readfd, egdcmd, 2) < 0) { dropbear_exit("Can't send command to egd"); } } #endif - readlen = read(readfd, readbuf, wantread); if (readlen <= 0) { if (readlen < 0 && errno == EINTR) { continue; } - if (readlen == 0 && len == 0) - { + if (readlen == 0 && wantlen == 0) { /* whole file was read as requested */ break; } @@ -193,6 +161,63 @@ void fuzz_seed(void) { } #endif + +#ifdef HAVE_GETRANDOM +/* Reads entropy seed with getrandom(). + * May block if the kernel isn't ready. + * Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ +static int process_getrandom(hash_state *hs) { + char buf[INIT_SEED_SIZE]; + ssize_t ret; + + /* First try non-blocking so that we can warn about waiting */ + ret = getrandom(buf, sizeof(buf), GRND_NONBLOCK); + if (ret == -1) { + if (errno == ENOSYS) { + /* Old kernel */ + return DROPBEAR_FAILURE; + } + /* Other errors fall through to blocking getrandom() */ + TRACE(("first getrandom() failed: %d %s", errno, strerror(errno))) + if (errno == EAGAIN) { + dropbear_log(LOG_WARNING, "Waiting for kernel randomness to be initialised..."); + } + } + + /* Wait blocking if needed. Loop in case we get EINTR */ + while (ret != sizeof(buf)) { + ret = getrandom(buf, sizeof(buf), 0); + + if (ret == sizeof(buf)) { + /* Success */ + break; + } + if (ret == -1 && errno == EINTR) { + /* Try again. */ + continue; + } + if (ret >= 0) { + TRACE(("Short read %zd from getrandom() shouldn't happen", ret)) + /* Try again? */ + continue; + } + + /* Unexpected problem, fall back to /dev/urandom */ + TRACE(("2nd getrandom() failed: %d %s", errno, strerror(errno))) + break; + } + + if (ret == sizeof(buf)) { + /* Success, stir in the entropy */ + sha1_process(hs, (void*)buf, sizeof(buf)); + return DROPBEAR_SUCCESS; + } + + return DROPBEAR_FAILURE; + +} +#endif /* HAVE_GETRANDOM */ + /* Initialise the prng from /dev/urandom or prngd. This function can * be called multiple times */ void seedrandom() { @@ -202,6 +227,7 @@ void seedrandom() { pid_t pid; struct timeval tv; clock_t clockval; + int urandom_seeded = 0; #if DROPBEAR_FUZZ if (fuzz.fuzzing) { @@ -215,20 +241,30 @@ void seedrandom() { /* existing state */ sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); -#if DROPBEAR_USE_PRNGD - if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) - != DROPBEAR_SUCCESS) { - dropbear_exit("Failure reading random device %s", - DROPBEAR_PRNGD_SOCKET); +#ifdef HAVE_GETRANDOM + if (process_getrandom(&hs) == DROPBEAR_SUCCESS) { + urandom_seeded = 1; } +#endif + + if (!urandom_seeded) { +#if DROPBEAR_USE_PRNGD + if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) + != DROPBEAR_SUCCESS) { + dropbear_exit("Failure reading random device %s", + DROPBEAR_PRNGD_SOCKET); + urandom_seeded = 1; + } #else - /* non-blocking random source (probably /dev/urandom) */ - if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0) - != DROPBEAR_SUCCESS) { - dropbear_exit("Failure reading random device %s", - DROPBEAR_URANDOM_DEV); - } + /* non-blocking random source (probably /dev/urandom) */ + if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0) + != DROPBEAR_SUCCESS) { + dropbear_exit("Failure reading random device %s", + DROPBEAR_URANDOM_DEV); + urandom_seeded = 1; + } #endif + } /* urandom_seeded */ /* A few other sources to fall back on. * Add more here for other platforms */ @@ -124,6 +124,10 @@ #include <sys/uio.h> #endif +#ifdef HAVE_SYS_RANDOM_H +#include <sys/random.h> +#endif + #ifdef BUNDLED_LIBTOM #include "libtomcrypt/src/headers/tomcrypt.h" #include "libtommath/tommath.h" |