summaryrefslogtreecommitdiff
path: root/ssh-rand-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-rand-helper.c')
-rw-r--r--ssh-rand-helper.c93
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
42RCSID("$Id: ssh-rand-helper.c,v 1.18 2004/07/17 04:07:42 dtucker Exp $"); 42RCSID("$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
212static int
213seed_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
212double 228double
213stir_gettimeofday(double entropy_estimate) 229stir_gettimeofday(double entropy_estimate)
214{ 230{
@@ -534,10 +550,11 @@ prng_check_seedfile(char *filename)
534void 550void
535prng_write_seedfile(void) 551prng_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
574void 610void
@@ -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 */
897void
898seed_rng(void)
899{
900 if (!RAND_status())
901 fatal("Not enough entropy in RNG");
902}