- close(p[0]);
-
- debug("Time elapsed: %d msec", msec_elapsed);
-
- if (waitpid(pid, &status, 0) == -1) {
- debug("Couldn't wait for child '%s' completion: %s", src->cmdstring,
- strerror(errno));
- return(0.0);
- }
-
- RAND_add(&status, sizeof(&status), 0.0);
-
- if (error_abort) {
- /* closing p[0] on timeout causes the entropy command to
- * SIGPIPE. Take whatever output we got, and mark this command
- * as slow */
- debug("Command '%s' timed out", src->cmdstring);
- src->sticky_badness *= 2;
- src->badness = src->sticky_badness;
- return(total_bytes_read);
- }
-
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status)==0) {
- return(total_bytes_read);
- } else {
- debug("Exit status was %d", WEXITSTATUS(status));
- src->badness = src->sticky_badness = 128;
- return (0.0);
- }
- } else if (WIFSIGNALED(status)) {
- debug("Returned on uncaught signal %d !", status);
- src->badness = src->sticky_badness = 128;
- return(0.0);
- } else
- return(0.0);
-}
-
-/*
- * prng seedfile functions
- */
-int
-prng_check_seedfile(char *filename) {
-
- struct stat st;
-
- /* FIXME raceable: eg replace seed between this stat and subsequent open */
- /* Not such a problem because we don't trust the seed file anyway */
- if (lstat(filename, &st) == -1) {
- /* Fail on hard errors */
- if (errno != ENOENT)
- fatal("Couldn't stat random seed file \"%s\": %s", filename,
- strerror(errno));
-
- return(0);
- }
-
- /* regular file? */
- if (!S_ISREG(st.st_mode))
- fatal("PRNG seedfile %.100s is not a regular file", filename);
-
- /* mode 0600, owned by root or the current user? */
- if (((st.st_mode & 0177) != 0) || !(st.st_uid == getuid()))
- fatal("PRNG seedfile %.100s must be mode 0600, owned by uid %d",
- filename, getuid());
-
- return(1);
-}
-
-void
-prng_write_seedfile(void) {
- int fd;
- char seed[1024];
- char filename[1024];
- struct passwd *pw;
-
- /* Don't bother if we have already saved a seed */
- if (prng_seed_saved)
- return;
-
- prng_seed_saved = 1;
-
- pw = getpwuid(getuid());
- if (pw == NULL)
- fatal("Couldn't get password entry for current user (%i): %s",
- getuid(), strerror(errno));
-
- /* Try to ensure that the parent directory is there */
- snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
- SSH_USER_DIR);
- mkdir(filename, 0700);
-
- snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
- SSH_PRNG_SEED_FILE);
-
- debug("writing PRNG seed to file %.100s", filename);
-
- RAND_bytes(seed, sizeof(seed));
-
- /* Don't care if the seed doesn't exist */
- prng_check_seedfile(filename);
-
- if ((fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0600)) == -1)
- fatal("couldn't access PRNG seedfile %.100s (%.100s)", filename,
- strerror(errno));
-
- if (atomicio(write, fd, &seed, sizeof(seed)) != sizeof(seed))
- fatal("problem writing PRNG seedfile %.100s (%.100s)", filename,
- strerror(errno));
-
- close(fd);
-}
-
-void
-prng_read_seedfile(void) {
- int fd;
- char seed[1024];
- char filename[1024];
- struct passwd *pw;
-
- pw = getpwuid(getuid());
- if (pw == NULL)
- fatal("Couldn't get password entry for current user (%i): %s",
- getuid(), strerror(errno));
-
- snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
- SSH_PRNG_SEED_FILE);
-
- debug("loading PRNG seed from file %.100s", filename);
-
- if (!prng_check_seedfile(filename)) {
- verbose("Random seed file not found, creating new");
- prng_write_seedfile();
-
- /* Reseed immediatly */
- (void)stir_from_system();
- (void)stir_from_programs();