source: trunk/third/openssh/entropy.c @ 18759

Revision 18759, 4.6 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2001 Damien Miller.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
27#include <openssl/rand.h>
28#include <openssl/crypto.h>
29
30#include "ssh.h"
31#include "misc.h"
32#include "xmalloc.h"
33#include "atomicio.h"
34#include "pathnames.h"
35#include "log.h"
36
37/*
38 * Portable OpenSSH PRNG seeding:
39 * If OpenSSL has not "internally seeded" itself (e.g. pulled data from
40 * /dev/random), then we execute a "ssh-rand-helper" program which
41 * collects entropy and writes it to stdout. The child program must
42 * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr
43 * attached, so error/debugging output should be visible.
44 *
45 * XXX: we should tell the child how many bytes we need.
46 */
47
48RCSID("$Id: entropy.c,v 1.1.1.2 2003-02-05 19:02:58 zacheiss Exp $");
49
50#ifndef OPENSSL_PRNG_ONLY
51#define RANDOM_SEED_SIZE 48
52static uid_t original_uid, original_euid;
53#endif
54
55void
56seed_rng(void)
57{
58#ifndef OPENSSL_PRNG_ONLY
59        int devnull;
60        int p[2];
61        pid_t pid;
62        int ret;
63        unsigned char buf[RANDOM_SEED_SIZE];
64        mysig_t old_sigchld;
65
66        if (RAND_status() == 1) {
67                debug3("RNG is ready, skipping seeding");
68                return;
69        }
70
71        debug3("Seeding PRNG from %s", SSH_RAND_HELPER);
72
73        if ((devnull = open("/dev/null", O_RDWR)) == -1)
74                fatal("Couldn't open /dev/null: %s", strerror(errno));
75        if (pipe(p) == -1)
76                fatal("pipe: %s", strerror(errno));
77
78        old_sigchld = mysignal(SIGCHLD, SIG_DFL);
79        if ((pid = fork()) == -1)
80                fatal("Couldn't fork: %s", strerror(errno));
81        if (pid == 0) {
82                dup2(devnull, STDIN_FILENO);
83                dup2(p[1], STDOUT_FILENO);
84                /* Keep stderr open for errors */
85                close(p[0]);
86                close(p[1]);
87                close(devnull);
88
89                if (original_uid != original_euid &&
90                    ( seteuid(getuid()) == -1 ||
91                      setuid(original_uid) == -1) ) {
92                        fprintf(stderr, "(rand child) setuid(%d): %s\n",
93                            original_uid, strerror(errno));
94                        _exit(1);
95                }
96               
97                execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL);
98                fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n",
99                    SSH_RAND_HELPER, strerror(errno));
100                _exit(1);
101        }
102
103        close(devnull);
104        close(p[1]);
105
106        memset(buf, '\0', sizeof(buf));
107        ret = atomicio(read, p[0], buf, sizeof(buf));
108        if (ret == -1)
109                fatal("Couldn't read from ssh-rand-helper: %s",
110                    strerror(errno));
111        if (ret != sizeof(buf))
112                fatal("ssh-rand-helper child produced insufficient data");
113
114        close(p[0]);
115
116        if (waitpid(pid, &ret, 0) == -1)
117               fatal("Couldn't wait for ssh-rand-helper completion: %s",
118                   strerror(errno));
119        mysignal(SIGCHLD, old_sigchld);
120
121        /* We don't mind if the child exits upon a SIGPIPE */
122        if (!WIFEXITED(ret) &&
123            (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE))
124                fatal("ssh-rand-helper terminated abnormally");
125        if (WEXITSTATUS(ret) != 0)
126                fatal("ssh-rand-helper exit with exit status %d", ret);
127
128        RAND_add(buf, sizeof(buf), sizeof(buf));
129        memset(buf, '\0', sizeof(buf));
130
131#endif /* OPENSSL_PRNG_ONLY */
132        if (RAND_status() != 1)
133                fatal("PRNG is not seeded");
134}
135
136void
137init_rng(void)
138{
139        /*
140         * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
141         * We match major, minor, fix and status (not patch)
142         */
143        if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
144                fatal("OpenSSL version mismatch. Built against %lx, you "
145                    "have %lx", OPENSSL_VERSION_NUMBER, SSLeay());
146
147#ifndef OPENSSL_PRNG_ONLY
148        if ((original_uid = getuid()) == -1)
149                fatal("getuid: %s", strerror(errno));
150        if ((original_euid = geteuid()) == -1)
151                fatal("geteuid: %s", strerror(errno));
152#endif
153}
154
Note: See TracBrowser for help on using the repository browser.