Improve the noise collection for the internal random pool.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Nov 2002 15:23:20 +0000 (15:23 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Nov 2002 15:23:20 +0000 (15:23 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@2182 cda61777-01e9-0310-a592-d414129be87e

unix/uxcons.c
unix/uxnoise.c
unix/uxplink.c
unix/uxstore.c

index 6b3da51..197466e 100644 (file)
@@ -25,6 +25,10 @@ void cleanup_exit(int code)
      * Clean up.
      */
     sk_cleanup();
+
+    if (cfg.protocol == PROT_SSH)
+       random_save_seed();
+
     exit(code);
 }
 
index 91f9c2b..873a331 100644 (file)
@@ -7,58 +7,76 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/resource.h>
 
 #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));
 }
 
 /*
index 6c5b554..ba7b78f 100644 (file)
@@ -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 */
 }
index 9047988..d787ba4 100644 (file)
@@ -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)