From d9c40fd6ed72588278c633ee5db5c2eefad6ba7c Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 2 Nov 2002 15:23:20 +0000 Subject: [PATCH] Improve the noise collection for the internal random pool. git-svn-id: svn://svn.tartarus.org/sgt/putty@2182 cda61777-01e9-0310-a592-d414129be87e --- unix/uxcons.c | 4 +++ unix/uxnoise.c | 84 +++++++++++++++++++++++++++++++++++++++------------------- unix/uxplink.c | 3 ++- unix/uxstore.c | 36 ++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 29 deletions(-) diff --git a/unix/uxcons.c b/unix/uxcons.c index 6b3da51b..197466ea 100644 --- a/unix/uxcons.c +++ b/unix/uxcons.c @@ -25,6 +25,10 @@ void cleanup_exit(int code) * Clean up. */ sk_cleanup(); + + if (cfg.protocol == PROT_SSH) + random_save_seed(); + exit(code); } diff --git a/unix/uxnoise.c b/unix/uxnoise.c index 91f9c2be..873a3313 100644 --- a/unix/uxnoise.c +++ b/unix/uxnoise.c @@ -7,58 +7,76 @@ #include #include #include +#include #include "putty.h" #include "ssh.h" #include "storage.h" -/* - * FIXME. This module currently depends critically on /dev/urandom, - * because it has no fallback mechanism for doing anything else. - */ - -static void read_dev_urandom(char *buf, int len) +static int read_dev_urandom(char *buf, int len) { int fd; int ngot, ret; fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - perror("/dev/urandom: open"); - exit(1); - } + if (fd < 0) + return 0; ngot = 0; while (ngot < len) { ret = read(fd, buf+ngot, len-ngot); if (ret < 0) { - perror("/dev/urandom: read"); - exit(1); + close(fd); + return 0; } ngot += ret; } + + return 1; } /* - * This function is called once, at PuTTY startup. Currently it - * will read 32 bytes out of /dev/urandom and seed the internal - * generator with them. + * This function is called once, at PuTTY startup. It will do some + * slightly silly things such as fetching an entire process listing + * and scanning /tmp, load the saved random seed from disk, and + * also read 32 bytes out of /dev/urandom. */ void noise_get_heavy(void (*func) (void *, int)) { - char buf[32]; - read_dev_urandom(buf, sizeof(buf)); - func(buf, sizeof(buf)); + char buf[512]; + FILE *fp; + int ret; + + if (read_dev_urandom(buf, 32)) + func(buf, 32); + + fp = popen("ps -axu 2>/dev/null", "r"); + while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0) + func(buf, ret); + pclose(fp); + + fp = popen("ls -al /tmp 2>/dev/null", "r"); + while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0) + func(buf, ret); + pclose(fp); + + read_random_seed(func); } void random_save_seed(void) { - /* Currently we do nothing here. FIXME? */ + int len; + void *data; + + if (random_active) { + random_get_savedata(&data, &len); + write_random_seed(data, len); + } } /* - * This function is called every time the urandom pool needs + * This function is called every time the random pool needs * stirring, and will acquire the system time. */ void noise_get_light(void (*func) (void *, int)) @@ -69,16 +87,28 @@ void noise_get_light(void (*func) (void *, int)) } /* - * This function is called on a timer, and it will just pull some - * stuff out of /dev/urandom. FIXME: really I suspect we ought not - * to deplete /dev/urandom like this. Better to grab something more - * harmless. + * This function is called on a timer, and grabs as much changeable + * system data as it can quickly get its hands on. */ void noise_regular(void) { - char buf[4]; - read_dev_urandom(buf, sizeof(buf)); - random_add_noise(buf, sizeof(buf)); + int fd; + int ret; + char buf[512]; + struct rusage rusage; + + if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) { + while ( (ret = read(fd, buf, sizeof(buf))) > 0) + random_add_noise(buf, ret); + close(fd); + } + if ((fd = open("/proc/stat", O_RDONLY)) >= 0) { + while ( (ret = read(fd, buf, sizeof(buf))) > 0) + random_add_noise(buf, ret); + close(fd); + } + getrusage(RUSAGE_SELF, &rusage); + random_add_noise(&rusage, sizeof(rusage)); } /* diff --git a/unix/uxplink.c b/unix/uxplink.c index 6c5b5544..ba7b78f9 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -584,5 +584,6 @@ int main(int argc, char **argv) fprintf(stderr, "Remote process exit code unavailable\n"); exitcode = 1; /* this is an error condition */ } - return exitcode; + cleanup_exit(exitcode); + return exitcode; /* shouldn't happen, but placates gcc */ } diff --git a/unix/uxstore.c b/unix/uxstore.c index 9047988b..d787ba40 100644 --- a/unix/uxstore.c +++ b/unix/uxstore.c @@ -156,7 +156,7 @@ void enum_settings_finish(void *handle) } enum { - INDEX_DIR, INDEX_HOSTKEYS + INDEX_DIR, INDEX_HOSTKEYS, INDEX_RANDSEED }; static void make_filename(char *filename, int index) @@ -169,6 +169,7 @@ static void make_filename(char *filename, int index) strncpy(filename + len, index == INDEX_DIR ? "/.putty" : index == INDEX_HOSTKEYS ? "/.putty/sshhostkeys" : + index == INDEX_RANDSEED ? "/.putty/randomseed" : "/.putty/ERROR", FILENAME_MAX - len); filename[FILENAME_MAX-1] = '\0'; } @@ -297,10 +298,43 @@ void store_host_key(char *hostname, int port, char *keytype, char *key) void read_random_seed(noise_consumer_t consumer) { + int fd; + char fname[FILENAME_MAX]; + + make_filename(fname, INDEX_RANDSEED); + fd = open(fname, O_RDONLY); + if (fd) { + char buf[512]; + int ret; + while ( (ret = read(fd, buf, sizeof(buf))) > 0) + consumer(buf, ret); + close(fd); + } } void write_random_seed(void *data, int len) { + int fd; + char fname[FILENAME_MAX]; + + make_filename(fname, INDEX_RANDSEED); + fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0600); + if (fd < 0) { + char dir[FILENAME_MAX]; + + make_filename(dir, INDEX_DIR); + mkdir(dir, 0700); + fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0600); + } + + while (len > 0) { + int ret = write(fd, data, len); + if (ret <= 0) break; + len -= ret; + data = (char *)data + len; + } + + close(fd); } void cleanup_all(void) -- 2.11.0