diff options
Diffstat (limited to 'entropy.c')
-rw-r--r-- | entropy.c | 207 |
1 files changed, 140 insertions, 67 deletions
@@ -35,7 +35,7 @@ | |||
35 | #include <openssl/rand.h> | 35 | #include <openssl/rand.h> |
36 | #include <openssl/sha.h> | 36 | #include <openssl/sha.h> |
37 | 37 | ||
38 | RCSID("$Id: entropy.c,v 1.7 2000/05/01 14:03:56 damien Exp $"); | 38 | RCSID("$Id: entropy.c,v 1.8 2000/05/01 23:56:41 damien Exp $"); |
39 | 39 | ||
40 | #ifdef EGD_SOCKET | 40 | #ifdef EGD_SOCKET |
41 | #ifndef offsetof | 41 | #ifndef offsetof |
@@ -111,8 +111,6 @@ void get_random_bytes(unsigned char *buf, int len) | |||
111 | * FIXME: proper entropy estimations. All current values are guesses | 111 | * FIXME: proper entropy estimations. All current values are guesses |
112 | * FIXME: (ATL) do estimates at compile time? | 112 | * FIXME: (ATL) do estimates at compile time? |
113 | * FIXME: More entropy sources | 113 | * FIXME: More entropy sources |
114 | * FIXME: (ATL) bring in entropy sources from file | ||
115 | * FIXME: (ATL) add heuristic to increase the timeout if needed | ||
116 | */ | 114 | */ |
117 | 115 | ||
118 | /* slow command timeouts (all in milliseconds) */ | 116 | /* slow command timeouts (all in milliseconds) */ |
@@ -120,7 +118,8 @@ void get_random_bytes(unsigned char *buf, int len) | |||
120 | static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC; | 118 | static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC; |
121 | 119 | ||
122 | static int prng_seed_loaded = 0; | 120 | static int prng_seed_loaded = 0; |
123 | static int prng_seed_saved = 0; | 121 | static int prng_seed_saved = 0; |
122 | static int prng_commands_loaded = 0; | ||
124 | 123 | ||
125 | typedef struct | 124 | typedef struct |
126 | { | 125 | { |
@@ -131,9 +130,9 @@ typedef struct | |||
131 | /* Increases by factor of two each timeout */ | 130 | /* Increases by factor of two each timeout */ |
132 | unsigned int sticky_badness; | 131 | unsigned int sticky_badness; |
133 | /* Path to executable */ | 132 | /* Path to executable */ |
134 | const char *path; | 133 | char *path; |
135 | /* argv to pass to executable */ | 134 | /* argv to pass to executable */ |
136 | const char *args[5]; | 135 | char *args[5]; |
137 | } entropy_source_t; | 136 | } entropy_source_t; |
138 | 137 | ||
139 | double stir_from_system(void); | 138 | double stir_from_system(void); |
@@ -143,67 +142,10 @@ double stir_clock(double entropy_estimate); | |||
143 | double stir_rusage(int who, double entropy_estimate); | 142 | double stir_rusage(int who, double entropy_estimate); |
144 | double hash_output_from_command(entropy_source_t *src, char *hash); | 143 | double hash_output_from_command(entropy_source_t *src, char *hash); |
145 | 144 | ||
146 | entropy_source_t entropy_sources[] = { | 145 | /* this is initialised from a file, by prng_read_commands() */ |
147 | #ifdef PROG_LS | 146 | entropy_source_t *entropy_sources = NULL; |
148 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/var/log", NULL } }, | 147 | #define MIN_ENTROPY_SOURCES 16 |
149 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/var/adm", NULL } }, | 148 | |
150 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/var/mail", NULL } }, | ||
151 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/var/spool/mail", NULL } }, | ||
152 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/proc", NULL } }, | ||
153 | { 0.002, 0, 1, PROG_LS, { "ls", "-alni", "/tmp", NULL } }, | ||
154 | #endif | ||
155 | #ifdef PROG_NETSTAT | ||
156 | { 0.005, 0, 1, PROG_NETSTAT, { "netstat","-an", NULL, NULL } }, | ||
157 | { 0.010, 0, 1, PROG_NETSTAT, { "netstat","-in", NULL, NULL } }, | ||
158 | { 0.002, 0, 1, PROG_NETSTAT, { "netstat","-rn", NULL, NULL } }, | ||
159 | { 0.002, 0, 1, PROG_NETSTAT, { "netstat","-s", NULL, NULL } }, | ||
160 | #endif | ||
161 | #ifdef PROG_ARP | ||
162 | { 0.002, 0, 1, PROG_ARP, { "arp","-a","-n", NULL } }, | ||
163 | #endif | ||
164 | #ifdef PROG_IFCONFIG | ||
165 | { 0.002, 0, 1, PROG_IFCONFIG, { "ifconfig", "-a", NULL, NULL } }, | ||
166 | #endif | ||
167 | #ifdef PROG_PS | ||
168 | { 0.003, 0, 1, PROG_PS, { "ps", "laxww", NULL, NULL } }, | ||
169 | { 0.003, 0, 1, PROG_PS, { "ps", "-al", NULL, NULL } }, | ||
170 | { 0.003, 0, 1, PROG_PS, { "ps", "-efl", NULL, NULL } }, | ||
171 | #endif | ||
172 | #ifdef PROG_W | ||
173 | { 0.005, 0, 1, PROG_W, { "w", NULL, NULL, NULL } }, | ||
174 | #endif | ||
175 | #ifdef PROG_WHO | ||
176 | { 0.001, 0, 1, PROG_WHO, { "who","-i", NULL, NULL } }, | ||
177 | #endif | ||
178 | #ifdef PROG_LAST | ||
179 | { 0.001, 0, 1, PROG_LAST, { "last", NULL, NULL, NULL } }, | ||
180 | #endif | ||
181 | #ifdef PROG_LASTLOG | ||
182 | { 0.001, 0, 1, PROG_LASTLOG, { "lastlog", NULL, NULL, NULL } }, | ||
183 | #endif | ||
184 | #ifdef PROG_DF | ||
185 | { 0.010, 0, 1, PROG_DF, { "df", NULL, NULL, NULL } }, | ||
186 | { 0.010, 0, 1, PROG_DF, { "df", "-i", NULL, NULL } }, | ||
187 | #endif | ||
188 | #ifdef PROG_VMSTAT | ||
189 | { 0.010, 0, 1, PROG_VMSTAT, { "vmstat", NULL, NULL, NULL } }, | ||
190 | #endif | ||
191 | #ifdef PROG_UPTIME | ||
192 | { 0.001, 0, 1, PROG_UPTIME, { "uptime", NULL, NULL, NULL } }, | ||
193 | #endif | ||
194 | #ifdef PROG_IPCS | ||
195 | { 0.001, 0, 1, PROG_IPCS, { "-a", NULL, NULL, NULL } }, | ||
196 | #endif | ||
197 | #ifdef PROG_TAIL | ||
198 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/log/messages", NULL, NULL } }, | ||
199 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/log/syslog", NULL, NULL } }, | ||
200 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/adm/messages", NULL, NULL } }, | ||
201 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/adm/syslog", NULL, NULL } }, | ||
202 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/log/maillog", NULL, NULL } }, | ||
203 | { 0.001, 0, 1, PROG_TAIL, { "tail", "-200", "/var/adm/maillog", NULL, NULL } }, | ||
204 | #endif | ||
205 | { 0.000, 0, 0, NULL, { NULL, NULL, NULL, NULL, NULL } }, | ||
206 | }; | ||
207 | 149 | ||
208 | double | 150 | double |
209 | stir_from_system(void) | 151 | stir_from_system(void) |
@@ -597,6 +539,131 @@ prng_read_seedfile(void) { | |||
597 | RAND_add(&seed, sizeof(seed), 0.0); | 539 | RAND_add(&seed, sizeof(seed), 0.0); |
598 | } | 540 | } |
599 | 541 | ||
542 | |||
543 | /* | ||
544 | * entropy command initialisation functions | ||
545 | */ | ||
546 | #define WHITESPACE " \t\n" | ||
547 | |||
548 | int | ||
549 | prng_read_commands(char *cmdfilename) | ||
550 | { | ||
551 | FILE *f; | ||
552 | char line[1024]; | ||
553 | char cmd[1024], path[256]; | ||
554 | double est; | ||
555 | char *cp; | ||
556 | int linenum; | ||
557 | entropy_source_t *entcmd; | ||
558 | int num_cmds = 64; | ||
559 | int cur_cmd = 0; | ||
560 | |||
561 | f = fopen(cmdfilename, "r"); | ||
562 | if (!f) { | ||
563 | fatal("couldn't read entropy commands file %.100s: %.100s", | ||
564 | cmdfilename, strerror(errno)); | ||
565 | } | ||
566 | |||
567 | linenum = 0; | ||
568 | |||
569 | entcmd = (entropy_source_t *)xmalloc(num_cmds * sizeof(entropy_source_t)); | ||
570 | memset(entcmd, '\0', num_cmds * sizeof(entropy_source_t)); | ||
571 | |||
572 | while (fgets(line, sizeof(line), f)) { | ||
573 | linenum++; | ||
574 | |||
575 | /* skip leading whitespace, test for blank line or comment */ | ||
576 | cp = line + strspn(line, WHITESPACE); | ||
577 | if ((*cp == 0) || (*cp == '#')) | ||
578 | continue; /* done with this line */ | ||
579 | |||
580 | switch (*cp) { | ||
581 | int arg; | ||
582 | char *argv; | ||
583 | |||
584 | case '"': | ||
585 | /* first token, command args (incl. argv[0]) in double quotes */ | ||
586 | cp = strtok(cp, "\""); | ||
587 | if (cp==NULL) { | ||
588 | error("missing or bad command string, %.100s line %d -- ignored", | ||
589 | cmdfilename, linenum); | ||
590 | continue; | ||
591 | } | ||
592 | strncpy(cmd, cp, sizeof(cmd)); | ||
593 | /* second token, full command path */ | ||
594 | if ((cp = strtok(NULL, WHITESPACE)) == NULL) { | ||
595 | error("missing command path, %.100s line %d -- ignored", | ||
596 | cmdfilename, linenum); | ||
597 | continue; | ||
598 | } | ||
599 | if (strncmp("undef", cp, 5)==0) /* did configure mark this as dead? */ | ||
600 | continue; | ||
601 | |||
602 | strncpy(path, cp, sizeof(path)); | ||
603 | /* third token, entropy rate estimate for this command */ | ||
604 | if ( (cp = strtok(NULL, WHITESPACE)) == NULL) { | ||
605 | error("missing entropy estimate, %.100s line %d -- ignored", | ||
606 | cmdfilename, linenum); | ||
607 | continue; | ||
608 | } | ||
609 | est = strtod(cp, &argv);/* FIXME: (ATL) no error checking here */ | ||
610 | |||
611 | /* end of line */ | ||
612 | if ((cp = strtok(NULL, WHITESPACE)) != NULL) { | ||
613 | error("garbage at end of line %d in %.100s -- ignored", | ||
614 | linenum, cmdfilename); | ||
615 | continue; | ||
616 | } | ||
617 | |||
618 | /* split the command args */ | ||
619 | cp = strtok(cmd, WHITESPACE); | ||
620 | arg = 0; argv = NULL; | ||
621 | do { | ||
622 | char *s = (char*)xmalloc(strlen(cp)+1); | ||
623 | strncpy(s, cp, strlen(cp)+1); | ||
624 | entcmd[cur_cmd].args[arg] = s; | ||
625 | arg++; | ||
626 | } while ((arg < 5) && (cp = strtok(NULL, WHITESPACE))); | ||
627 | if (strtok(NULL, WHITESPACE)) | ||
628 | error("ignored extra command elements (max 5), %.100s line %d", | ||
629 | cmdfilename, linenum); | ||
630 | |||
631 | /* copy the command path and rate estimate */ | ||
632 | entcmd[cur_cmd].path = (char *)xmalloc(strlen(path)+1); | ||
633 | strncpy(entcmd[cur_cmd].path, path, strlen(path)+1); | ||
634 | entcmd[cur_cmd].rate = est; | ||
635 | /* initialise other values */ | ||
636 | entcmd[cur_cmd].sticky_badness = 1; | ||
637 | |||
638 | cur_cmd++; | ||
639 | |||
640 | /* If we've filled the array, reallocate it twice the size */ | ||
641 | /* Do this now because even if this we're on the last command, | ||
642 | we need another slot to mark the last entry */ | ||
643 | if (cur_cmd == num_cmds) { | ||
644 | num_cmds *= 2; | ||
645 | entcmd = xrealloc(entcmd, num_cmds * sizeof(entropy_source_t)); | ||
646 | } | ||
647 | break; | ||
648 | |||
649 | default: | ||
650 | error("bad entropy command, %.100s line %d", cmdfilename, | ||
651 | linenum); | ||
652 | continue; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /* zero the last entry */ | ||
657 | memset(&entcmd[cur_cmd], '\0', sizeof(entropy_source_t)); | ||
658 | /* trim to size */ | ||
659 | entropy_sources = xrealloc(entcmd, (cur_cmd+1) * sizeof(entropy_source_t)); | ||
660 | |||
661 | debug("loaded %d entropy commands from %.100s", cur_cmd, cmdfilename); | ||
662 | |||
663 | return (cur_cmd >= MIN_ENTROPY_SOURCES); | ||
664 | } | ||
665 | |||
666 | |||
600 | #endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ | 667 | #endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */ |
601 | 668 | ||
602 | #if defined(EGD_SOCKET) || defined(RANDOM_POOL) | 669 | #if defined(EGD_SOCKET) || defined(RANDOM_POOL) |
@@ -634,6 +701,12 @@ prng_seed_cleanup(void *junk) | |||
634 | void | 701 | void |
635 | seed_rng(void) | 702 | seed_rng(void) |
636 | { | 703 | { |
704 | if (!prng_commands_loaded) { | ||
705 | if (!prng_read_commands(SSH_PRNG_COMMAND_FILE)) | ||
706 | fatal("PRNG initialisation failed -- exiting."); | ||
707 | prng_commands_loaded = 1; | ||
708 | } | ||
709 | |||
637 | debug("Seeding random number generator."); | 710 | debug("Seeding random number generator."); |
638 | debug("OpenSSL random status is now %i\n", RAND_status()); | 711 | debug("OpenSSL random status is now %i\n", RAND_status()); |
639 | debug("%i bytes from system calls", (int)stir_from_system()); | 712 | debug("%i bytes from system calls", (int)stir_from_system()); |