diff options
Diffstat (limited to 'ssh-rand-helper.c')
-rw-r--r-- | ssh-rand-helper.c | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/ssh-rand-helper.c b/ssh-rand-helper.c index 86af3893d..d7d8d0f3b 100644 --- a/ssh-rand-helper.c +++ b/ssh-rand-helper.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include "pathnames.h" | 39 | #include "pathnames.h" |
40 | #include "log.h" | 40 | #include "log.h" |
41 | 41 | ||
42 | RCSID("$Id: ssh-rand-helper.c,v 1.18 2004/07/17 04:07:42 dtucker Exp $"); | 42 | RCSID("$Id: ssh-rand-helper.c,v 1.23 2005/02/16 02:32:30 dtucker Exp $"); |
43 | 43 | ||
44 | /* Number of bytes we write out */ | 44 | /* Number of bytes we write out */ |
45 | #define OUTPUT_SEED_SIZE 48 | 45 | #define OUTPUT_SEED_SIZE 48 |
@@ -209,6 +209,22 @@ done: | |||
209 | return rval; | 209 | return rval; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int | ||
213 | seed_from_prngd(unsigned char *buf, size_t bytes) | ||
214 | { | ||
215 | #ifdef PRNGD_PORT | ||
216 | debug("trying egd/prngd port %d", PRNGD_PORT); | ||
217 | if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0) | ||
218 | return 0; | ||
219 | #endif | ||
220 | #ifdef PRNGD_SOCKET | ||
221 | debug("trying egd/prngd socket %s", PRNGD_SOCKET); | ||
222 | if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0) | ||
223 | return 0; | ||
224 | #endif | ||
225 | return -1; | ||
226 | } | ||
227 | |||
212 | double | 228 | double |
213 | stir_gettimeofday(double entropy_estimate) | 229 | stir_gettimeofday(double entropy_estimate) |
214 | { | 230 | { |
@@ -534,10 +550,11 @@ prng_check_seedfile(char *filename) | |||
534 | void | 550 | void |
535 | prng_write_seedfile(void) | 551 | prng_write_seedfile(void) |
536 | { | 552 | { |
537 | int fd; | 553 | int fd, save_errno; |
538 | unsigned char seed[SEED_FILE_SIZE]; | 554 | unsigned char seed[SEED_FILE_SIZE]; |
539 | char filename[MAXPATHLEN]; | 555 | char filename[MAXPATHLEN], tmpseed[MAXPATHLEN]; |
540 | struct passwd *pw; | 556 | struct passwd *pw; |
557 | mode_t old_umask; | ||
541 | 558 | ||
542 | pw = getpwuid(getuid()); | 559 | pw = getpwuid(getuid()); |
543 | if (pw == NULL) | 560 | if (pw == NULL) |
@@ -552,7 +569,10 @@ prng_write_seedfile(void) | |||
552 | snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir, | 569 | snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir, |
553 | SSH_PRNG_SEED_FILE); | 570 | SSH_PRNG_SEED_FILE); |
554 | 571 | ||
555 | debug("writing PRNG seed to file %.100s", filename); | 572 | strlcpy(tmpseed, filename, sizeof(tmpseed)); |
573 | if (strlcat(tmpseed, ".XXXXXXXXXX", sizeof(tmpseed)) >= | ||
574 | sizeof(tmpseed)) | ||
575 | fatal("PRNG seed filename too long"); | ||
556 | 576 | ||
557 | if (RAND_bytes(seed, sizeof(seed)) <= 0) | 577 | if (RAND_bytes(seed, sizeof(seed)) <= 0) |
558 | fatal("PRNG seed extraction failed"); | 578 | fatal("PRNG seed extraction failed"); |
@@ -560,15 +580,31 @@ prng_write_seedfile(void) | |||
560 | /* Don't care if the seed doesn't exist */ | 580 | /* Don't care if the seed doesn't exist */ |
561 | prng_check_seedfile(filename); | 581 | prng_check_seedfile(filename); |
562 | 582 | ||
563 | if ((fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0600)) == -1) { | 583 | old_umask = umask(0177); |
564 | debug("WARNING: couldn't access PRNG seedfile %.100s " | 584 | |
565 | "(%.100s)", filename, strerror(errno)); | 585 | if ((fd = mkstemp(tmpseed)) == -1) { |
586 | debug("WARNING: couldn't make temporary PRNG seedfile %.100s " | ||
587 | "(%.100s)", tmpseed, strerror(errno)); | ||
566 | } else { | 588 | } else { |
567 | if (atomicio(vwrite, fd, &seed, sizeof(seed)) < sizeof(seed)) | 589 | debug("writing PRNG seed to file %.100s", tmpseed); |
590 | if (atomicio(vwrite, fd, &seed, sizeof(seed)) < sizeof(seed)) { | ||
591 | save_errno = errno; | ||
592 | close(fd); | ||
593 | unlink(tmpseed); | ||
568 | fatal("problem writing PRNG seedfile %.100s " | 594 | fatal("problem writing PRNG seedfile %.100s " |
569 | "(%.100s)", filename, strerror(errno)); | 595 | "(%.100s)", filename, strerror(save_errno)); |
596 | } | ||
570 | close(fd); | 597 | close(fd); |
598 | debug("moving temporary PRNG seed to file %.100s", filename); | ||
599 | if (rename(tmpseed, filename) == -1) { | ||
600 | save_errno = errno; | ||
601 | unlink(tmpseed); | ||
602 | fatal("problem renaming PRNG seedfile from %.100s " | ||
603 | "to %.100s (%.100s)", tmpseed, filename, | ||
604 | strerror(save_errno)); | ||
605 | } | ||
571 | } | 606 | } |
607 | umask(old_umask); | ||
572 | } | 608 | } |
573 | 609 | ||
574 | void | 610 | void |
@@ -747,7 +783,7 @@ usage(void) | |||
747 | fprintf(stderr, "Usage: %s [options]\n", __progname); | 783 | fprintf(stderr, "Usage: %s [options]\n", __progname); |
748 | fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); | 784 | fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); |
749 | fprintf(stderr, " Multiple -v increases verbosity.\n"); | 785 | fprintf(stderr, " Multiple -v increases verbosity.\n"); |
750 | fprintf(stderr, " -x Force output in hexidecimal (for debugging)\n"); | 786 | fprintf(stderr, " -x Force output in hexadecimal (for debugging)\n"); |
751 | fprintf(stderr, " -X Force output in binary\n"); | 787 | fprintf(stderr, " -X Force output in binary\n"); |
752 | fprintf(stderr, " -b bytes Number of bytes to output (default %d)\n", | 788 | fprintf(stderr, " -b bytes Number of bytes to output (default %d)\n", |
753 | OUTPUT_SEED_SIZE); | 789 | OUTPUT_SEED_SIZE); |
@@ -815,21 +851,16 @@ main(int argc, char **argv) | |||
815 | debug("Seeded RNG with %i bytes from system calls", | 851 | debug("Seeded RNG with %i bytes from system calls", |
816 | (int)stir_from_system()); | 852 | (int)stir_from_system()); |
817 | 853 | ||
818 | #ifdef PRNGD_PORT | 854 | /* try prngd, fall back to commands if prngd fails or not configured */ |
819 | if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == -1) | 855 | if (seed_from_prngd(buf, bytes) == 0) { |
820 | fatal("Entropy collection failed"); | 856 | RAND_add(buf, bytes, bytes); |
821 | RAND_add(buf, bytes, bytes); | 857 | } else { |
822 | #elif defined(PRNGD_SOCKET) | 858 | /* Read in collection commands */ |
823 | if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == -1) | 859 | if (prng_read_commands(SSH_PRNG_COMMAND_FILE) == -1) |
824 | fatal("Entropy collection failed"); | 860 | fatal("PRNG initialisation failed -- exiting."); |
825 | RAND_add(buf, bytes, bytes); | 861 | debug("Seeded RNG with %i bytes from programs", |
826 | #else | 862 | (int)stir_from_programs()); |
827 | /* Read in collection commands */ | 863 | } |
828 | if (prng_read_commands(SSH_PRNG_COMMAND_FILE) == -1) | ||
829 | fatal("PRNG initialisation failed -- exiting."); | ||
830 | debug("Seeded RNG with %i bytes from programs", | ||
831 | (int)stir_from_programs()); | ||
832 | #endif | ||
833 | 864 | ||
834 | #ifdef USE_SEED_FILES | 865 | #ifdef USE_SEED_FILES |
835 | prng_write_seedfile(); | 866 | prng_write_seedfile(); |
@@ -857,3 +888,15 @@ main(int argc, char **argv) | |||
857 | 888 | ||
858 | return ret == bytes ? 0 : 1; | 889 | return ret == bytes ? 0 : 1; |
859 | } | 890 | } |
891 | |||
892 | /* | ||
893 | * We may attempt to re-seed during mkstemp if we are using the one in the | ||
894 | * compat library (via mkstemp -> _gettemp -> arc4random -> seed_rng) so we | ||
895 | * need our own seed_rng(). We must also check that we have enough entropy. | ||
896 | */ | ||
897 | void | ||
898 | seed_rng(void) | ||
899 | { | ||
900 | if (!RAND_status()) | ||
901 | fatal("Not enough entropy in RNG"); | ||
902 | } | ||