aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c')
-rw-r--r--[-rwxr-xr-x]linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c1696
1 files changed, 848 insertions, 848 deletions
diff --git a/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c
index db5be70..3ebb823 100755..100644
--- a/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c
+++ b/linden/indra/libgcrypt/libgcrypt-1.2.2/cipher/rndunix.c
@@ -1,848 +1,848 @@
1/**************************************************************************** 1/****************************************************************************
2 * * 2 * *
3 * * 3 * *
4 * Unix Randomness-Gathering Code * 4 * Unix Randomness-Gathering Code *
5 * * 5 * *
6 * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. * 6 * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
7 * Heavily modified for GnuPG by Werner Koch * 7 * Heavily modified for GnuPG by Werner Koch *
8 * * 8 * *
9 * * 9 * *
10 ****************************************************************************/ 10 ****************************************************************************/
11 11
12/* This module is part of the cryptlib continuously seeded pseudorandom 12/* This module is part of the cryptlib continuously seeded pseudorandom
13 number generator. For usage conditions, see lib_rand.c 13 number generator. For usage conditions, see lib_rand.c
14 14
15 [Here is the notice from lib_rand.c:] 15 [Here is the notice from lib_rand.c:]
16 16
17 This module and the misc/rnd*.c modules represent the cryptlib 17 This module and the misc/rnd*.c modules represent the cryptlib
18 continuously seeded pseudorandom number generator (CSPRNG) as described in 18 continuously seeded pseudorandom number generator (CSPRNG) as described in
19 my 1998 Usenix Security Symposium paper "The generation of random numbers 19 my 1998 Usenix Security Symposium paper "The generation of random numbers
20 for cryptographic purposes". 20 for cryptographic purposes".
21 21
22 The CSPRNG code is copyright Peter Gutmann (and various others) 1996, 22 The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
23 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG 23 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
24 modules and use in source and binary forms, with or without modification, 24 modules and use in source and binary forms, with or without modification,
25 are permitted provided that the following conditions are met: 25 are permitted provided that the following conditions are met:
26 26
27 1. Redistributions of source code must retain the above copyright notice 27 1. Redistributions of source code must retain the above copyright notice
28 and this permission notice in its entirety. 28 and this permission notice in its entirety.
29 29
30 2. Redistributions in binary form must reproduce the copyright notice in 30 2. Redistributions in binary form must reproduce the copyright notice in
31 the documentation and/or other materials provided with the distribution. 31 the documentation and/or other materials provided with the distribution.
32 32
33 3. A copy of any bugfixes or enhancements made must be provided to the 33 3. A copy of any bugfixes or enhancements made must be provided to the
34 author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the 34 author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
35 baseline version of the code. 35 baseline version of the code.
36 36
37 ALTERNATIVELY, the code may be distributed under the terms of the GNU 37 ALTERNATIVELY, the code may be distributed under the terms of the GNU
38 General Public License, version 2 or any later version published by the 38 General Public License, version 2 or any later version published by the
39 Free Software Foundation, in which case the provisions of the GNU GPL are 39 Free Software Foundation, in which case the provisions of the GNU GPL are
40 required INSTEAD OF the above restrictions. 40 required INSTEAD OF the above restrictions.
41 41
42 Although not required under the terms of the GPL, it would still be nice if 42 Although not required under the terms of the GPL, it would still be nice if
43 you could make any changes available to the author to allow a consistent 43 you could make any changes available to the author to allow a consistent
44 code base to be maintained */ 44 code base to be maintained */
45 45
46 46
47/* Fixme: We use plain mallocs here beucase it may be used as a module 47/* Fixme: We use plain mallocs here beucase it may be used as a module
48 * should be changed. */ 48 * should be changed. */
49 49
50/* General includes */ 50/* General includes */
51 51
52#include <config.h> 52#include <config.h>
53#include <stdlib.h> 53#include <stdlib.h>
54#include <stdio.h> 54#include <stdio.h>
55#include <string.h> 55#include <string.h>
56#include <assert.h> 56#include <assert.h>
57 57
58/* OS-specific includes */ 58/* OS-specific includes */
59 59
60#ifdef __osf__ 60#ifdef __osf__
61 /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in 61 /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
62 * via the following includes are various endianness defines, so we 62 * via the following includes are various endianness defines, so we
63 * undefine the cryptlib ones, which aren't really needed for this module 63 * undefine the cryptlib ones, which aren't really needed for this module
64 * anyway */ 64 * anyway */
65#undef BIG_ENDIAN 65#undef BIG_ENDIAN
66#undef LITTLE_ENDIAN 66#undef LITTLE_ENDIAN
67#endif /* __osf__ */ 67#endif /* __osf__ */
68 68
69#include <unistd.h> 69#include <unistd.h>
70#include <fcntl.h> 70#include <fcntl.h>
71#include <pwd.h> 71#include <pwd.h>
72#ifndef __QNX__ 72#ifndef __QNX__
73#include <sys/errno.h> 73#include <sys/errno.h>
74#include <sys/ipc.h> 74#include <sys/ipc.h>
75#endif /* __QNX__ */ 75#endif /* __QNX__ */
76#include <sys/time.h> /* SCO and SunOS need this before resource.h */ 76#include <sys/time.h> /* SCO and SunOS need this before resource.h */
77#ifndef __QNX__ 77#ifndef __QNX__
78#include <sys/resource.h> 78#include <sys/resource.h>
79#endif /* __QNX__ */ 79#endif /* __QNX__ */
80#if defined( _AIX ) || defined( __QNX__ ) 80#if defined( _AIX ) || defined( __QNX__ )
81#include <sys/select.h> 81#include <sys/select.h>
82#endif /* _AIX */ 82#endif /* _AIX */
83#ifndef __QNX__ 83#ifndef __QNX__
84#include <sys/shm.h> 84#include <sys/shm.h>
85#include <signal.h> 85#include <signal.h>
86#include <sys/signal.h> 86#include <sys/signal.h>
87#endif /* __QNX__ */ 87#endif /* __QNX__ */
88#include <sys/stat.h> 88#include <sys/stat.h>
89#include <sys/types.h> /* Verschiedene komische Typen */ 89#include <sys/types.h> /* Verschiedene komische Typen */
90#if defined( __hpux ) && ( OS_VERSION == 9 ) 90#if defined( __hpux ) && ( OS_VERSION == 9 )
91#include <vfork.h> 91#include <vfork.h>
92#endif /* __hpux 9.x, after that it's in unistd.h */ 92#endif /* __hpux 9.x, after that it's in unistd.h */
93#include <sys/wait.h> 93#include <sys/wait.h>
94/* #include <kitchensink.h> */ 94/* #include <kitchensink.h> */
95#ifdef __QNX__ 95#ifdef __QNX__
96#include <signal.h> 96#include <signal.h>
97#include <process.h> 97#include <process.h>
98#endif /* __QNX__ */ 98#endif /* __QNX__ */
99#include <errno.h> 99#include <errno.h>
100 100
101#include "types.h" /* for byte and u32 typedefs */ 101#include "types.h" /* for byte and u32 typedefs */
102#include "g10lib.h" 102#include "g10lib.h"
103#include "rand-internal.h" 103#include "rand-internal.h"
104 104
105#ifndef EAGAIN 105#ifndef EAGAIN
106#define EAGAIN EWOULDBLOCK 106#define EAGAIN EWOULDBLOCK
107#endif 107#endif
108#ifndef STDIN_FILENO 108#ifndef STDIN_FILENO
109#define STDIN_FILENO 0 109#define STDIN_FILENO 0
110#endif 110#endif
111#ifndef STDOUT_FILENO 111#ifndef STDOUT_FILENO
112#define STDOUT_FILENO 1 112#define STDOUT_FILENO 1
113#endif 113#endif
114 114
115#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */ 115#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
116 116
117/* The structure containing information on random-data sources. Each 117/* The structure containing information on random-data sources. Each
118 * record contains the source and a relative estimate of its usefulness 118 * record contains the source and a relative estimate of its usefulness
119 * (weighting) which is used to scale the number of kB of output from the 119 * (weighting) which is used to scale the number of kB of output from the
120 * source (total = data_bytes / usefulness). Usually the weighting is in the 120 * source (total = data_bytes / usefulness). Usually the weighting is in the
121 * range 1-3 (or 0 for especially useless sources), resulting in a usefulness 121 * range 1-3 (or 0 for especially useless sources), resulting in a usefulness
122 * rating of 1...3 for each kB of source output (or 0 for the useless 122 * rating of 1...3 for each kB of source output (or 0 for the useless
123 * sources). 123 * sources).
124 * 124 *
125 * If the source is constantly changing (certain types of network statistics 125 * If the source is constantly changing (certain types of network statistics
126 * have this characteristic) but the amount of output is small, the weighting 126 * have this characteristic) but the amount of output is small, the weighting
127 * is given as a negative value to indicate that the output should be treated 127 * is given as a negative value to indicate that the output should be treated
128 * as if a minimum of 1K of output had been obtained. If the source produces 128 * as if a minimum of 1K of output had been obtained. If the source produces
129 * a lot of output then the scale factor is fractional, resulting in a 129 * a lot of output then the scale factor is fractional, resulting in a
130 * usefulness rating of < 1 for each kB of source output. 130 * usefulness rating of < 1 for each kB of source output.
131 * 131 *
132 * In order to provide enough randomness to satisfy the requirements for a 132 * In order to provide enough randomness to satisfy the requirements for a
133 * slow poll, we need to accumulate at least 20 points of usefulness (a 133 * slow poll, we need to accumulate at least 20 points of usefulness (a
134 * typical system should get about 30 points). 134 * typical system should get about 30 points).
135 * 135 *
136 * Some potential options are missed out because of special considerations. 136 * Some potential options are missed out because of special considerations.
137 * pstat -i and pstat -f can produce amazing amounts of output (the record 137 * pstat -i and pstat -f can produce amazing amounts of output (the record
138 * is 600K on an Oracle server) which floods the buffer and doesn't yield 138 * is 600K on an Oracle server) which floods the buffer and doesn't yield
139 * anything useful (apart from perhaps increasing the entropy of the vmstat 139 * anything useful (apart from perhaps increasing the entropy of the vmstat
140 * output a bit), so we don't bother with this. pstat in general produces 140 * output a bit), so we don't bother with this. pstat in general produces
141 * quite a bit of output, but it doesn't change much over time, so it gets 141 * quite a bit of output, but it doesn't change much over time, so it gets
142 * very low weightings. netstat -s produces constantly-changing output but 142 * very low weightings. netstat -s produces constantly-changing output but
143 * also produces quite a bit of it, so it only gets a weighting of 2 rather 143 * also produces quite a bit of it, so it only gets a weighting of 2 rather
144 * than 3. The same holds for netstat -in, which gets 1 rather than 2. 144 * than 3. The same holds for netstat -in, which gets 1 rather than 2.
145 * 145 *
146 * Some binaries are stored in different locations on different systems so 146 * Some binaries are stored in different locations on different systems so
147 * alternative paths are given for them. The code sorts out which one to 147 * alternative paths are given for them. The code sorts out which one to
148 * run by itself, once it finds an exectable somewhere it moves on to the 148 * run by itself, once it finds an exectable somewhere it moves on to the
149 * next source. The sources are arranged roughly in their order of 149 * next source. The sources are arranged roughly in their order of
150 * usefulness, occasionally sources which provide a tiny amount of 150 * usefulness, occasionally sources which provide a tiny amount of
151 * relatively useless data are placed ahead of ones which provide a large 151 * relatively useless data are placed ahead of ones which provide a large
152 * amount of possibly useful data because another 100 bytes can't hurt, and 152 * amount of possibly useful data because another 100 bytes can't hurt, and
153 * it means the buffer won't be swamped by one or two high-output sources. 153 * it means the buffer won't be swamped by one or two high-output sources.
154 * All the high-output sources are clustered towards the end of the list 154 * All the high-output sources are clustered towards the end of the list
155 * for this reason. Some binaries are checked for in a certain order, for 155 * for this reason. Some binaries are checked for in a certain order, for
156 * example under Slowaris /usr/ucb/ps understands aux as an arg, but the 156 * example under Slowaris /usr/ucb/ps understands aux as an arg, but the
157 * others don't. Some systems have conditional defines enabling alternatives 157 * others don't. Some systems have conditional defines enabling alternatives
158 * to commands which don't understand the usual options but will provide 158 * to commands which don't understand the usual options but will provide
159 * enough output (in the form of error messages) to look like they're the 159 * enough output (in the form of error messages) to look like they're the
160 * real thing, causing alternative options to be skipped (we can't check the 160 * real thing, causing alternative options to be skipped (we can't check the
161 * return either because some commands return peculiar, non-zero status even 161 * return either because some commands return peculiar, non-zero status even
162 * when they're working correctly). 162 * when they're working correctly).
163 * 163 *
164 * In order to maximise use of the buffer, the code performs a form of run- 164 * In order to maximise use of the buffer, the code performs a form of run-
165 * length compression on its input where a repeated sequence of bytes is 165 * length compression on its input where a repeated sequence of bytes is
166 * replaced by the occurrence count mod 256. Some commands output an awful 166 * replaced by the occurrence count mod 256. Some commands output an awful
167 * lot of whitespace, this measure greatly increases the amount of data we 167 * lot of whitespace, this measure greatly increases the amount of data we
168 * can fit in the buffer. 168 * can fit in the buffer.
169 * 169 *
170 * When we scale the weighting using the SC() macro, some preprocessors may 170 * When we scale the weighting using the SC() macro, some preprocessors may
171 * give a division by zero warning for the most obvious expression 171 * give a division by zero warning for the most obvious expression
172 * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero 172 * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
173 * trap), so we define a value SC_0 which evaluates to zero when fed to 173 * trap), so we define a value SC_0 which evaluates to zero when fed to
174 * '1024 / SC_0' */ 174 * '1024 / SC_0' */
175 175
176#define SC( weight ) ( 1024 / weight ) /* Scale factor */ 176#define SC( weight ) ( 1024 / weight ) /* Scale factor */
177#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */ 177#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */
178 178
179static struct RI { 179static struct RI {
180 const char *path; /* Path to check for existence of source */ 180 const char *path; /* Path to check for existence of source */
181 const char *arg; /* Args for source */ 181 const char *arg; /* Args for source */
182 const int usefulness; /* Usefulness of source */ 182 const int usefulness; /* Usefulness of source */
183 FILE *pipe; /* Pipe to source as FILE * */ 183 FILE *pipe; /* Pipe to source as FILE * */
184 int pipeFD; /* Pipe to source as FD */ 184 int pipeFD; /* Pipe to source as FD */
185 pid_t pid; /* pid of child for waitpid() */ 185 pid_t pid; /* pid of child for waitpid() */
186 int length; /* Quantity of output produced */ 186 int length; /* Quantity of output produced */
187 const int hasAlternative; /* Whether source has alt.location */ 187 const int hasAlternative; /* Whether source has alt.location */
188} dataSources[] = { 188} dataSources[] = {
189 189
190 { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 }, 190 { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 },
191 { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0}, 191 { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
192 { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 }, 192 { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 },
193 { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0}, 193 { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
194 { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0}, 194 { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
195 { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 }, 195 { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 },
196 { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0}, 196 { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
197 { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, 197 { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
198 { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, 198 { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
199 { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1}, 199 { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
200 { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0}, 200 { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
201 { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0}, 201 { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
202 { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, 202 { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
203 { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, 203 { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
204 { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, 204 { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
205 { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 }, 205 { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
206 { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, 206 { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
207 { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, 207 { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
208 { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, 208 { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
209 { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1}, 209 { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
210 { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0}, 210 { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
211 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0", 211 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
212 SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */ 212 SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
213 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0", 213 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
214 SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */ 214 SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */
215 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0", 215 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
216 SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */ 216 SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
217 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0", 217 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
218 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ 218 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
219 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0", 219 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
220 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ 220 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
221 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0", 221 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
222 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ 222 SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
223 { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, 223 { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
224 { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 }, 224 { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 },
225 { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 }, 225 { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 },
226 { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 }, 226 { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 },
227 { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 }, 227 { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 },
228 { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, 228 { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
229 { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, 229 { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
230 { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, 230 { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
231 { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, 231 { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
232 { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 }, 232 { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 },
233 { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 }, 233 { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 },
234 { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, 234 { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
235 { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, 235 { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
236 { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, 236 { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
237 { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, 237 { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
238 { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, 238 { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
239 { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 }, 239 { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 },
240#if defined( __sgi ) || defined( __hpux ) 240#if defined( __sgi ) || defined( __hpux )
241 { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 }, 241 { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 },
242#endif /* __sgi || __hpux */ 242#endif /* __sgi || __hpux */
243 { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, 243 { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
244 { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, 244 { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
245 { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 }, 245 { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 },
246 { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/ 246 { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/
247 { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 }, 247 { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 },
248 { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 }, 248 { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 },
249 /* Unreliable source, depends on system usage */ 249 /* Unreliable source, depends on system usage */
250 { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 }, 250 { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 },
251 { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 }, 251 { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 },
252 { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 }, 252 { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 },
253 { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 }, 253 { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 },
254 { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 }, 254 { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 },
255 { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 }, 255 { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 },
256 { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 }, 256 { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 },
257 { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 }, 257 { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 },
258 { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, 258 { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
259 { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, 259 { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
260 /* pstat is your friend */ 260 /* pstat is your friend */
261 { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 }, 261 { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 },
262#ifdef __sgi 262#ifdef __sgi
263 { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, 263 { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
264#endif /* __sgi */ 264#endif /* __sgi */
265#ifdef __hpux 265#ifdef __hpux
266 { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, 266 { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
267#endif /* __hpux */ 267#endif /* __hpux */
268 { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 }, 268 { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 },
269 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0", 269 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
270 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ 270 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
271 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0", 271 { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
272 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ 272 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
273 { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, 273 { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
274 { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, 274 { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
275 { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, 275 { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
276 { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 }, 276 { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
277 { "/usr/sbin/ripquery", "-nw 1 127.0.0.1", 277 { "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
278 SC(0.1), NULL, 0, 0, 0, 0 }, 278 SC(0.1), NULL, 0, 0, 0, 0 },
279 { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, 279 { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
280 { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, 280 { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
281 { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, 281 { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
282 { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 }, 282 { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
283 /* This is very environment-dependant. If network traffic is low, it'll 283 /* This is very environment-dependant. If network traffic is low, it'll
284 * probably time out before delivering 5 packets, which is OK because 284 * probably time out before delivering 5 packets, which is OK because
285 * it'll probably be fixed stuff like ARP anyway */ 285 * it'll probably be fixed stuff like ARP anyway */
286 { "/usr/sbin/advfsstat", "-b usr_domain", 286 { "/usr/sbin/advfsstat", "-b usr_domain",
287 SC(SC_0), NULL, 0, 0, 0, 0}, 287 SC(SC_0), NULL, 0, 0, 0, 0},
288 { "/usr/sbin/advfsstat", "-l 2 usr_domain", 288 { "/usr/sbin/advfsstat", "-l 2 usr_domain",
289 SC(0.5), NULL, 0, 0, 0, 0}, 289 SC(0.5), NULL, 0, 0, 0, 0},
290 { "/usr/sbin/advfsstat", "-p usr_domain", 290 { "/usr/sbin/advfsstat", "-p usr_domain",
291 SC(SC_0), NULL, 0, 0, 0, 0}, 291 SC(SC_0), NULL, 0, 0, 0, 0},
292 /* This is a complex and screwball program. Some systems have things 292 /* This is a complex and screwball program. Some systems have things
293 * like rX_dmn, x = integer, for RAID systems, but the statistics are 293 * like rX_dmn, x = integer, for RAID systems, but the statistics are
294 * pretty dodgy */ 294 * pretty dodgy */
295#ifdef __QNXNTO__ 295#ifdef __QNXNTO__
296 { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3), 296 { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
297 NULL, 0, 0, 0, 0 }, 297 NULL, 0, 0, 0, 0 },
298#endif 298#endif
299#if 0 299#if 0
300 /* The following aren't enabled since they're somewhat slow and not very 300 /* The following aren't enabled since they're somewhat slow and not very
301 * unpredictable, however they give an indication of the sort of sources 301 * unpredictable, however they give an indication of the sort of sources
302 * you can use (for example the finger might be more useful on a 302 * you can use (for example the finger might be more useful on a
303 * firewalled internal network) */ 303 * firewalled internal network) */
304 { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 }, 304 { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
305 { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html", 305 { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
306 SC(0.9), NULL, 0, 0, 0, 0 }, 306 SC(0.9), NULL, 0, 0, 0, 0 },
307 { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 }, 307 { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
308#endif /* 0 */ 308#endif /* 0 */
309 { NULL, NULL, 0, NULL, 0, 0, 0, 0 } 309 { NULL, NULL, 0, NULL, 0, 0, 0, 0 }
310}; 310};
311 311
312static byte *gather_buffer; /* buffer for gathering random noise */ 312static byte *gather_buffer; /* buffer for gathering random noise */
313static int gather_buffer_size; /* size of the memory buffer */ 313static int gather_buffer_size; /* size of the memory buffer */
314static uid_t gatherer_uid; 314static uid_t gatherer_uid;
315 315
316/* The message structure used to communicate with the parent */ 316/* The message structure used to communicate with the parent */
317typedef struct { 317typedef struct {
318 int usefulness; /* usefulness of data */ 318 int usefulness; /* usefulness of data */
319 int ndata; /* valid bytes in data */ 319 int ndata; /* valid bytes in data */
320 char data[500]; /* gathered data */ 320 char data[500]; /* gathered data */
321} GATHER_MSG; 321} GATHER_MSG;
322 322
323#ifndef HAVE_WAITPID 323#ifndef HAVE_WAITPID
324static pid_t 324static pid_t
325waitpid(pid_t pid, int *statptr, int options) 325waitpid(pid_t pid, int *statptr, int options)
326{ 326{
327#ifdef HAVE_WAIT4 327#ifdef HAVE_WAIT4
328 return wait4(pid, statptr, options, NULL); 328 return wait4(pid, statptr, options, NULL);
329#else 329#else
330 /* If wait4 is also not available, try wait3 for SVR3 variants */ 330 /* If wait4 is also not available, try wait3 for SVR3 variants */
331 /* Less ideal because can't actually request a specific pid */ 331 /* Less ideal because can't actually request a specific pid */
332 /* For that reason, first check to see if pid is for an */ 332 /* For that reason, first check to see if pid is for an */
333 /* existing process. */ 333 /* existing process. */
334 int tmp_pid, dummystat;; 334 int tmp_pid, dummystat;;
335 if (kill(pid, 0) == -1) { 335 if (kill(pid, 0) == -1) {
336 errno = ECHILD; 336 errno = ECHILD;
337 return -1; 337 return -1;
338 } 338 }
339 if (statptr == NULL) 339 if (statptr == NULL)
340 statptr = &dummystat; 340 statptr = &dummystat;
341 while (((tmp_pid = wait3(statptr, options, 0)) != pid) && 341 while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
342 (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) 342 (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
343 ; 343 ;
344 return tmp_pid; 344 return tmp_pid;
345#endif 345#endif
346} 346}
347#endif 347#endif
348 348
349/* Under SunOS popen() doesn't record the pid of the child process. When 349/* Under SunOS popen() doesn't record the pid of the child process. When
350 * pclose() is called, instead of calling waitpid() for the correct child, it 350 * pclose() is called, instead of calling waitpid() for the correct child, it
351 * calls wait() repeatedly until the right child is reaped. The problem is 351 * calls wait() repeatedly until the right child is reaped. The problem is
352 * that this reaps any other children that happen to have died at that 352 * that this reaps any other children that happen to have died at that
353 * moment, and when their pclose() comes along, the process hangs forever. 353 * moment, and when their pclose() comes along, the process hangs forever.
354 * The fix is to use a wrapper for popen()/pclose() which saves the pid in 354 * The fix is to use a wrapper for popen()/pclose() which saves the pid in
355 * the dataSources structure (code adapted from GNU-libc's popen() call). 355 * the dataSources structure (code adapted from GNU-libc's popen() call).
356 * 356 *
357 * Aut viam inveniam aut faciam */ 357 * Aut viam inveniam aut faciam */
358 358
359static FILE * 359static FILE *
360my_popen(struct RI *entry) 360my_popen(struct RI *entry)
361{ 361{
362 int pipedes[2]; 362 int pipedes[2];
363 FILE *stream; 363 FILE *stream;
364 364
365 /* Create the pipe */ 365 /* Create the pipe */
366 if (pipe(pipedes) < 0) 366 if (pipe(pipedes) < 0)
367 return (NULL); 367 return (NULL);
368 368
369 /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to 369 /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to
370 * do it, but most just end up faking it" - Chris Wedgwood). If your OS 370 * do it, but most just end up faking it" - Chris Wedgwood). If your OS
371 * supports it, you should try to use vfork() here because it's somewhat 371 * supports it, you should try to use vfork() here because it's somewhat
372 * more efficient */ 372 * more efficient */
373#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \ 373#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
374 defined(__hpux) 374 defined(__hpux)
375 entry->pid = vfork(); 375 entry->pid = vfork();
376#else /* */ 376#else /* */
377 entry->pid = fork(); 377 entry->pid = fork();
378#endif /* Unixen which have vfork() */ 378#endif /* Unixen which have vfork() */
379 if (entry->pid == (pid_t) - 1) { 379 if (entry->pid == (pid_t) - 1) {
380 /* The fork failed */ 380 /* The fork failed */
381 close(pipedes[0]); 381 close(pipedes[0]);
382 close(pipedes[1]); 382 close(pipedes[1]);
383 return (NULL); 383 return (NULL);
384 } 384 }
385 385
386 if (entry->pid == (pid_t) 0) { 386 if (entry->pid == (pid_t) 0) {
387 struct passwd *passwd; 387 struct passwd *passwd;
388 388
389 /* We are the child. Make the read side of the pipe be stdout */ 389 /* We are the child. Make the read side of the pipe be stdout */
390 if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) 390 if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
391 exit(127); 391 exit(127);
392 392
393 /* Now that everything is set up, give up our permissions to make 393 /* Now that everything is set up, give up our permissions to make
394 * sure we don't read anything sensitive. If the getpwnam() fails, 394 * sure we don't read anything sensitive. If the getpwnam() fails,
395 * we default to -1, which is usually nobody */ 395 * we default to -1, which is usually nobody */
396 if (gatherer_uid == (uid_t)-1 && \ 396 if (gatherer_uid == (uid_t)-1 && \
397 (passwd = getpwnam("nobody")) != NULL) 397 (passwd = getpwnam("nobody")) != NULL)
398 gatherer_uid = passwd->pw_uid; 398 gatherer_uid = passwd->pw_uid;
399 399
400 setuid(gatherer_uid); 400 setuid(gatherer_uid);
401 401
402 /* Close the pipe descriptors */ 402 /* Close the pipe descriptors */
403 close(pipedes[STDIN_FILENO]); 403 close(pipedes[STDIN_FILENO]);
404 close(pipedes[STDOUT_FILENO]); 404 close(pipedes[STDOUT_FILENO]);
405 405
406 /* Try and exec the program */ 406 /* Try and exec the program */
407 execl(entry->path, entry->path, entry->arg, NULL); 407 execl(entry->path, entry->path, entry->arg, NULL);
408 408
409 /* Die if the exec failed */ 409 /* Die if the exec failed */
410 exit(127); 410 exit(127);
411 } 411 }
412 412
413 /* We are the parent. Close the irrelevant side of the pipe and open 413 /* We are the parent. Close the irrelevant side of the pipe and open
414 * the relevant side as a new stream. Mark our side of the pipe to 414 * the relevant side as a new stream. Mark our side of the pipe to
415 * close on exec, so new children won't see it */ 415 * close on exec, so new children won't see it */
416 close(pipedes[STDOUT_FILENO]); 416 close(pipedes[STDOUT_FILENO]);
417 417
418#ifdef FD_CLOEXEC 418#ifdef FD_CLOEXEC
419 fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); 419 fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
420#endif 420#endif
421 421
422 stream = fdopen(pipedes[STDIN_FILENO], "r"); 422 stream = fdopen(pipedes[STDIN_FILENO], "r");
423 423
424 if (stream == NULL) { 424 if (stream == NULL) {
425 int savedErrno = errno; 425 int savedErrno = errno;
426 426
427 /* The stream couldn't be opened or the child structure couldn't be 427 /* The stream couldn't be opened or the child structure couldn't be
428 * allocated. Kill the child and close the other side of the pipe */ 428 * allocated. Kill the child and close the other side of the pipe */
429 kill(entry->pid, SIGKILL); 429 kill(entry->pid, SIGKILL);
430 if (stream == NULL) 430 if (stream == NULL)
431 close(pipedes[STDOUT_FILENO]); 431 close(pipedes[STDOUT_FILENO]);
432 else 432 else
433 fclose(stream); 433 fclose(stream);
434 434
435 waitpid(entry->pid, NULL, 0); 435 waitpid(entry->pid, NULL, 0);
436 436
437 entry->pid = 0; 437 entry->pid = 0;
438 errno = savedErrno; 438 errno = savedErrno;
439 return (NULL); 439 return (NULL);
440 } 440 }
441 441
442 return (stream); 442 return (stream);
443} 443}
444 444
445static int 445static int
446my_pclose(struct RI *entry) 446my_pclose(struct RI *entry)
447{ 447{
448 int status = 0; 448 int status = 0;
449 449
450 if (fclose(entry->pipe)) 450 if (fclose(entry->pipe))
451 return (-1); 451 return (-1);
452 452
453 /* We ignore the return value from the process because some programs 453 /* We ignore the return value from the process because some programs
454 * return funny values which would result in the input being discarded 454 * return funny values which would result in the input being discarded
455 * even if they executed successfully. This isn't a problem because the 455 * even if they executed successfully. This isn't a problem because the
456 * result data size threshold will filter out any programs which exit 456 * result data size threshold will filter out any programs which exit
457 * with a usage message without producing useful output */ 457 * with a usage message without producing useful output */
458 if (waitpid(entry->pid, NULL, 0) != entry->pid) 458 if (waitpid(entry->pid, NULL, 0) != entry->pid)
459 status = -1; 459 status = -1;
460 460
461 entry->pipe = NULL; 461 entry->pipe = NULL;
462 entry->pid = 0; 462 entry->pid = 0;
463 return (status); 463 return (status);
464} 464}
465 465
466 466
467/* Unix slow poll (without special support for Linux) 467/* Unix slow poll (without special support for Linux)
468 * 468 *
469 * If a few of the randomness sources create a large amount of output then 469 * If a few of the randomness sources create a large amount of output then
470 * the slowPoll() stops once the buffer has been filled (but before all the 470 * the slowPoll() stops once the buffer has been filled (but before all the
471 * randomness sources have been sucked dry) so that the 'usefulness' factor 471 * randomness sources have been sucked dry) so that the 'usefulness' factor
472 * remains below the threshold. For this reason the gatherer buffer has to 472 * remains below the threshold. For this reason the gatherer buffer has to
473 * be fairly sizeable on moderately loaded systems. This is something of a 473 * be fairly sizeable on moderately loaded systems. This is something of a
474 * bug since the usefulness should be influenced by the amount of output as 474 * bug since the usefulness should be influenced by the amount of output as
475 * well as the source type */ 475 * well as the source type */
476 476
477 477
478static int 478static int
479slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) 479slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
480{ 480{
481 int moreSources; 481 int moreSources;
482 struct timeval tv; 482 struct timeval tv;
483 fd_set fds; 483 fd_set fds;
484#if defined( __hpux ) 484#if defined( __hpux )
485 size_t maxFD = 0; 485 size_t maxFD = 0;
486#else 486#else
487 int maxFD = 0; 487 int maxFD = 0;
488#endif /* OS-specific brokenness */ 488#endif /* OS-specific brokenness */
489 int bufPos, i, usefulness = 0; 489 int bufPos, i, usefulness = 0;
490 490
491 491
492 /* Fire up each randomness source */ 492 /* Fire up each randomness source */
493 FD_ZERO(&fds); 493 FD_ZERO(&fds);
494 for (i = 0; dataSources[i].path != NULL; i++) { 494 for (i = 0; dataSources[i].path != NULL; i++) {
495 /* Since popen() is a fairly heavy function, we check to see whether 495 /* Since popen() is a fairly heavy function, we check to see whether
496 * the executable exists before we try to run it */ 496 * the executable exists before we try to run it */
497 if (access(dataSources[i].path, X_OK)) { 497 if (access(dataSources[i].path, X_OK)) {
498 if( dbgfp && dbgall ) 498 if( dbgfp && dbgall )
499 fprintf(dbgfp, "%s not present%s\n", dataSources[i].path, 499 fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
500 dataSources[i].hasAlternative ? 500 dataSources[i].hasAlternative ?
501 ", has alternatives" : ""); 501 ", has alternatives" : "");
502 dataSources[i].pipe = NULL; 502 dataSources[i].pipe = NULL;
503 } 503 }
504 else 504 else
505 dataSources[i].pipe = my_popen(&dataSources[i]); 505 dataSources[i].pipe = my_popen(&dataSources[i]);
506 506
507 if (dataSources[i].pipe != NULL) { 507 if (dataSources[i].pipe != NULL) {
508 dataSources[i].pipeFD = fileno(dataSources[i].pipe); 508 dataSources[i].pipeFD = fileno(dataSources[i].pipe);
509 if (dataSources[i].pipeFD > maxFD) 509 if (dataSources[i].pipeFD > maxFD)
510 maxFD = dataSources[i].pipeFD; 510 maxFD = dataSources[i].pipeFD;
511 511
512#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */ 512#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
513 fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK); 513 fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
514#else 514#else
515#error O_NONBLOCK is missing 515#error O_NONBLOCK is missing
516#endif 516#endif
517 517
518 FD_SET(dataSources[i].pipeFD, &fds); 518 FD_SET(dataSources[i].pipeFD, &fds);
519 dataSources[i].length = 0; 519 dataSources[i].length = 0;
520 520
521 /* If there are alternatives for this command, don't try and 521 /* If there are alternatives for this command, don't try and
522 * execute them */ 522 * execute them */
523 while (dataSources[i].hasAlternative) { 523 while (dataSources[i].hasAlternative) {
524 if( dbgfp && dbgall ) 524 if( dbgfp && dbgall )
525 fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path); 525 fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
526 i++; 526 i++;
527 } 527 }
528 } 528 }
529 } 529 }
530 530
531 531
532 /* Suck all the data we can get from each of the sources */ 532 /* Suck all the data we can get from each of the sources */
533 bufPos = 0; 533 bufPos = 0;
534 moreSources = 1; 534 moreSources = 1;
535 while (moreSources && bufPos <= gather_buffer_size) { 535 while (moreSources && bufPos <= gather_buffer_size) {
536 /* Wait for data to become available from any of the sources, with a 536 /* Wait for data to become available from any of the sources, with a
537 * timeout of 10 seconds. This adds even more randomness since data 537 * timeout of 10 seconds. This adds even more randomness since data
538 * becomes available in a nondeterministic fashion. Kudos to HP's QA 538 * becomes available in a nondeterministic fashion. Kudos to HP's QA
539 * department for managing to ship a select() which breaks its own 539 * department for managing to ship a select() which breaks its own
540 * prototype */ 540 * prototype */
541 tv.tv_sec = 10; 541 tv.tv_sec = 10;
542 tv.tv_usec = 0; 542 tv.tv_usec = 0;
543 543
544#if defined( __hpux ) && ( OS_VERSION == 9 ) 544#if defined( __hpux ) && ( OS_VERSION == 9 )
545 if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) 545 if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
546#else /* */ 546#else /* */
547 if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) 547 if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
548#endif /* __hpux */ 548#endif /* __hpux */
549 break; 549 break;
550 550
551 /* One of the sources has data available, read it into the buffer */ 551 /* One of the sources has data available, read it into the buffer */
552 for (i = 0; dataSources[i].path != NULL; i++) { 552 for (i = 0; dataSources[i].path != NULL; i++) {
553 if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { 553 if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
554 size_t noBytes; 554 size_t noBytes;
555 555
556 if ((noBytes = fread(gather_buffer + bufPos, 1, 556 if ((noBytes = fread(gather_buffer + bufPos, 1,
557 gather_buffer_size - bufPos, 557 gather_buffer_size - bufPos,
558 dataSources[i].pipe)) == 0) { 558 dataSources[i].pipe)) == 0) {
559 if (my_pclose(&dataSources[i]) == 0) { 559 if (my_pclose(&dataSources[i]) == 0) {
560 int total = 0; 560 int total = 0;
561 561
562 /* Try and estimate how much entropy we're getting 562 /* Try and estimate how much entropy we're getting
563 * from a data source */ 563 * from a data source */
564 if (dataSources[i].usefulness) { 564 if (dataSources[i].usefulness) {
565 if (dataSources[i].usefulness < 0) 565 if (dataSources[i].usefulness < 0)
566 total = (dataSources[i].length + 999) 566 total = (dataSources[i].length + 999)
567 / -dataSources[i].usefulness; 567 / -dataSources[i].usefulness;
568 else 568 else
569 total = dataSources[i].length 569 total = dataSources[i].length
570 / dataSources[i].usefulness; 570 / dataSources[i].usefulness;
571 } 571 }
572 if( dbgfp ) 572 if( dbgfp )
573 fprintf(dbgfp, 573 fprintf(dbgfp,
574 "%s %s contributed %d bytes, " 574 "%s %s contributed %d bytes, "
575 "usefulness = %d\n", dataSources[i].path, 575 "usefulness = %d\n", dataSources[i].path,
576 (dataSources[i].arg != NULL) ? 576 (dataSources[i].arg != NULL) ?
577 dataSources[i].arg : "", 577 dataSources[i].arg : "",
578 dataSources[i].length, total); 578 dataSources[i].length, total);
579 if( dataSources[i].length ) 579 if( dataSources[i].length )
580 usefulness += total; 580 usefulness += total;
581 } 581 }
582 dataSources[i].pipe = NULL; 582 dataSources[i].pipe = NULL;
583 } 583 }
584 else { 584 else {
585 int currPos = bufPos; 585 int currPos = bufPos;
586 int endPos = bufPos + noBytes; 586 int endPos = bufPos + noBytes;
587 587
588 /* Run-length compress the input byte sequence */ 588 /* Run-length compress the input byte sequence */
589 while (currPos < endPos) { 589 while (currPos < endPos) {
590 int ch = gather_buffer[currPos]; 590 int ch = gather_buffer[currPos];
591 591
592 /* If it's a single byte, just copy it over */ 592 /* If it's a single byte, just copy it over */
593 if (ch != gather_buffer[currPos + 1]) { 593 if (ch != gather_buffer[currPos + 1]) {
594 gather_buffer[bufPos++] = ch; 594 gather_buffer[bufPos++] = ch;
595 currPos++; 595 currPos++;
596 } 596 }
597 else { 597 else {
598 int count = 0; 598 int count = 0;
599 599
600 /* It's a run of repeated bytes, replace them 600 /* It's a run of repeated bytes, replace them
601 * with the byte count mod 256 */ 601 * with the byte count mod 256 */
602 while ((ch == gather_buffer[currPos]) 602 while ((ch == gather_buffer[currPos])
603 && currPos < endPos) { 603 && currPos < endPos) {
604 count++; 604 count++;
605 currPos++; 605 currPos++;
606 } 606 }
607 gather_buffer[bufPos++] = count; 607 gather_buffer[bufPos++] = count;
608 noBytes -= count - 1; 608 noBytes -= count - 1;
609 } 609 }
610 } 610 }
611 611
612 /* Remember the number of (compressed) bytes of input we 612 /* Remember the number of (compressed) bytes of input we
613 * obtained */ 613 * obtained */
614 dataSources[i].length += noBytes; 614 dataSources[i].length += noBytes;
615 } 615 }
616 } 616 }
617 } 617 }
618 618
619 /* Check if there is more input available on any of the sources */ 619 /* Check if there is more input available on any of the sources */
620 moreSources = 0; 620 moreSources = 0;
621 FD_ZERO(&fds); 621 FD_ZERO(&fds);
622 for (i = 0; dataSources[i].path != NULL; i++) { 622 for (i = 0; dataSources[i].path != NULL; i++) {
623 if (dataSources[i].pipe != NULL) { 623 if (dataSources[i].pipe != NULL) {
624 FD_SET(dataSources[i].pipeFD, &fds); 624 FD_SET(dataSources[i].pipeFD, &fds);
625 moreSources = 1; 625 moreSources = 1;
626 } 626 }
627 } 627 }
628 } 628 }
629 629
630 if( dbgfp ) { 630 if( dbgfp ) {
631 fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); 631 fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
632 fflush(dbgfp); 632 fflush(dbgfp);
633 } 633 }
634 *nbytes = bufPos; 634 *nbytes = bufPos;
635 return usefulness; 635 return usefulness;
636} 636}
637 637
638/**************** 638/****************
639 * Start the gatherer process which writes messages of 639 * Start the gatherer process which writes messages of
640 * type GATHERER_MSG to pipedes 640 * type GATHERER_MSG to pipedes
641 */ 641 */
642static void 642static void
643start_gatherer( int pipefd ) 643start_gatherer( int pipefd )
644{ 644{
645 FILE *dbgfp = NULL; 645 FILE *dbgfp = NULL;
646 int dbgall; 646 int dbgall;
647 647
648 { 648 {
649 const char *s = getenv("GNUPG_RNDUNIX_DBG"); 649 const char *s = getenv("GNUPG_RNDUNIX_DBG");
650 if( s ) { 650 if( s ) {
651 dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a"); 651 dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
652 if( !dbgfp ) 652 if( !dbgfp )
653 log_info("can't open debug file `%s': %s\n", 653 log_info("can't open debug file `%s': %s\n",
654 s, strerror(errno) ); 654 s, strerror(errno) );
655 else 655 else
656 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid()); 656 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
657 } 657 }
658 dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL"); 658 dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
659 } 659 }
660 /* close all files but the ones we need */ 660 /* close all files but the ones we need */
661 { int nmax, n1, n2, i; 661 { int nmax, n1, n2, i;
662#ifdef _SC_OPEN_MAX 662#ifdef _SC_OPEN_MAX
663 if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) { 663 if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
664#ifdef _POSIX_OPEN_MAX 664#ifdef _POSIX_OPEN_MAX
665 nmax = _POSIX_OPEN_MAX; 665 nmax = _POSIX_OPEN_MAX;
666#else 666#else
667 nmax = 20; /* assume a reasonable value */ 667 nmax = 20; /* assume a reasonable value */
668#endif 668#endif
669 } 669 }
670#else /*!_SC_OPEN_MAX*/ 670#else /*!_SC_OPEN_MAX*/
671 nmax = 20; /* assume a reasonable value */ 671 nmax = 20; /* assume a reasonable value */
672#endif /*!_SC_OPEN_MAX*/ 672#endif /*!_SC_OPEN_MAX*/
673 n1 = fileno( stderr ); 673 n1 = fileno( stderr );
674 n2 = dbgfp? fileno( dbgfp ) : -1; 674 n2 = dbgfp? fileno( dbgfp ) : -1;
675 for(i=0; i < nmax; i++ ) { 675 for(i=0; i < nmax; i++ ) {
676 if( i != n1 && i != n2 && i != pipefd ) 676 if( i != n1 && i != n2 && i != pipefd )
677 close(i); 677 close(i);
678 } 678 }
679 errno = 0; 679 errno = 0;
680 } 680 }
681 681
682 682
683 /* Set up the buffer */ 683 /* Set up the buffer */
684 gather_buffer_size = GATHER_BUFSIZE; 684 gather_buffer_size = GATHER_BUFSIZE;
685 gather_buffer = malloc( gather_buffer_size ); 685 gather_buffer = malloc( gather_buffer_size );
686 if( !gather_buffer ) { 686 if( !gather_buffer ) {
687 log_error("out of core while allocating the gatherer buffer\n"); 687 log_error("out of core while allocating the gatherer buffer\n");
688 exit(2); 688 exit(2);
689 } 689 }
690 690
691 /* Reset the SIGC(H)LD handler to the system default. This is necessary 691 /* Reset the SIGC(H)LD handler to the system default. This is necessary
692 * because if the program which cryptlib is a part of installs its own 692 * because if the program which cryptlib is a part of installs its own
693 * SIGC(H)LD handler, it will end up reaping the cryptlib children before 693 * SIGC(H)LD handler, it will end up reaping the cryptlib children before
694 * cryptlib can. As a result, my_pclose() will call waitpid() on a 694 * cryptlib can. As a result, my_pclose() will call waitpid() on a
695 * process which has already been reaped by the installed handler and 695 * process which has already been reaped by the installed handler and
696 * return an error, so the read data won't be added to the randomness 696 * return an error, so the read data won't be added to the randomness
697 * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and 697 * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and
698 * the BSD/Posix SIGCHLD, so we need to handle either possibility */ 698 * the BSD/Posix SIGCHLD, so we need to handle either possibility */
699#ifdef SIGCLD 699#ifdef SIGCLD
700 signal(SIGCLD, SIG_DFL); 700 signal(SIGCLD, SIG_DFL);
701#else 701#else
702 signal(SIGCHLD, SIG_DFL); 702 signal(SIGCHLD, SIG_DFL);
703#endif 703#endif
704 704
705 fclose(stderr); /* Arrghh!! It's Stuart code!! */ 705 fclose(stderr); /* Arrghh!! It's Stuart code!! */
706 706
707 for(;;) { 707 for(;;) {
708 GATHER_MSG msg; 708 GATHER_MSG msg;
709 size_t nbytes; 709 size_t nbytes;
710 const char *p; 710 const char *p;
711 711
712 msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes ); 712 msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
713 p = gather_buffer; 713 p = gather_buffer;
714 while( nbytes ) { 714 while( nbytes ) {
715 msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes; 715 msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
716 memcpy( msg.data, p, msg.ndata ); 716 memcpy( msg.data, p, msg.ndata );
717 nbytes -= msg.ndata; 717 nbytes -= msg.ndata;
718 p += msg.ndata; 718 p += msg.ndata;
719 719
720 while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) { 720 while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
721 if( errno == EINTR ) 721 if( errno == EINTR )
722 continue; 722 continue;
723 if( errno == EAGAIN ) { 723 if( errno == EAGAIN ) {
724 struct timeval tv; 724 struct timeval tv;
725 tv.tv_sec = 0; 725 tv.tv_sec = 0;
726 tv.tv_usec = 50000; 726 tv.tv_usec = 50000;
727 select(0, NULL, NULL, NULL, &tv); 727 select(0, NULL, NULL, NULL, &tv);
728 continue; 728 continue;
729 } 729 }
730 if( errno == EPIPE ) /* parent has exited, so give up */ 730 if( errno == EPIPE ) /* parent has exited, so give up */
731 exit(0); 731 exit(0);
732 732
733 /* we can't do very much here because stderr is closed */ 733 /* we can't do very much here because stderr is closed */
734 if( dbgfp ) 734 if( dbgfp )
735 fprintf(dbgfp, "gatherer can't write to pipe: %s\n", 735 fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
736 strerror(errno) ); 736 strerror(errno) );
737 /* we start a new poll to give the system some time */ 737 /* we start a new poll to give the system some time */
738 nbytes = 0; 738 nbytes = 0;
739 break; 739 break;
740 } 740 }
741 } 741 }
742 } 742 }
743 /* we are killed when the parent dies */ 743 /* we are killed when the parent dies */
744} 744}
745 745
746 746
747static int 747static int
748read_a_msg( int fd, GATHER_MSG *msg ) 748read_a_msg( int fd, GATHER_MSG *msg )
749{ 749{
750 char *buffer = (char*)msg; 750 char *buffer = (char*)msg;
751 size_t length = sizeof( *msg ); 751 size_t length = sizeof( *msg );
752 int n; 752 int n;
753 753
754 do { 754 do {
755 do { 755 do {
756 n = read(fd, buffer, length ); 756 n = read(fd, buffer, length );
757 } while( n == -1 && errno == EINTR ); 757 } while( n == -1 && errno == EINTR );
758 if( n == -1 ) 758 if( n == -1 )
759 return -1; 759 return -1;
760 buffer += n; 760 buffer += n;
761 length -= n; 761 length -= n;
762 } while( length ); 762 } while( length );
763 return 0; 763 return 0;
764} 764}
765 765
766 766
767/**************** 767/****************
768 * Using a level of 0 should never block and better add nothing 768 * Using a level of 0 should never block and better add nothing
769 * to the pool. So this is just a dummy for this gatherer. 769 * to the pool. So this is just a dummy for this gatherer.
770 */ 770 */
771int 771int
772_gcry_rndunix_gather_random (void (*add)(const void*, size_t, int), 772_gcry_rndunix_gather_random (void (*add)(const void*, size_t, int),
773 int requester, 773 int requester,
774 size_t length, int level ) 774 size_t length, int level )
775{ 775{
776 static pid_t gatherer_pid = 0; 776 static pid_t gatherer_pid = 0;
777 static int pipedes[2]; 777 static int pipedes[2];
778 GATHER_MSG msg; 778 GATHER_MSG msg;
779 size_t n; 779 size_t n;
780 780
781 if( !level ) 781 if( !level )
782 return 0; 782 return 0;
783 783
784 if( !gatherer_pid ) { 784 if( !gatherer_pid ) {
785 /* make sure we are not setuid */ 785 /* make sure we are not setuid */
786 if( getuid() != geteuid() ) 786 if( getuid() != geteuid() )
787 BUG(); 787 BUG();
788 /* time to start the gatherer process */ 788 /* time to start the gatherer process */
789 if( pipe( pipedes ) ) { 789 if( pipe( pipedes ) ) {
790 log_error("pipe() failed: %s\n", strerror(errno)); 790 log_error("pipe() failed: %s\n", strerror(errno));
791 return -1; 791 return -1;
792 } 792 }
793 gatherer_pid = fork(); 793 gatherer_pid = fork();
794 if( gatherer_pid == -1 ) { 794 if( gatherer_pid == -1 ) {
795 log_error("can't for gatherer process: %s\n", strerror(errno)); 795 log_error("can't for gatherer process: %s\n", strerror(errno));
796 return -1; 796 return -1;
797 } 797 }
798 if( !gatherer_pid ) { 798 if( !gatherer_pid ) {
799 start_gatherer( pipedes[1] ); 799 start_gatherer( pipedes[1] );
800 /* oops, can't happen */ 800 /* oops, can't happen */
801 return -1; 801 return -1;
802 } 802 }
803 } 803 }
804 804
805 /* now read from the gatherer */ 805 /* now read from the gatherer */
806 while( length ) { 806 while( length ) {
807 int goodness; 807 int goodness;
808 ulong subtract; 808 ulong subtract;
809 809
810 if( read_a_msg( pipedes[0], &msg ) ) { 810 if( read_a_msg( pipedes[0], &msg ) ) {
811 log_error("reading from gatherer pipe failed: %s\n", 811 log_error("reading from gatherer pipe failed: %s\n",
812 strerror(errno)); 812 strerror(errno));
813 return -1; 813 return -1;
814 } 814 }
815 815
816 816
817 if( level > 1 ) { 817 if( level > 1 ) {
818 if( msg.usefulness > 30 ) 818 if( msg.usefulness > 30 )
819 goodness = 100; 819 goodness = 100;
820 else if ( msg.usefulness ) 820 else if ( msg.usefulness )
821 goodness = msg.usefulness * 100 / 30; 821 goodness = msg.usefulness * 100 / 30;
822 else 822 else
823 goodness = 0; 823 goodness = 0;
824 } 824 }
825 else if( level ) { 825 else if( level ) {
826 if( msg.usefulness > 15 ) 826 if( msg.usefulness > 15 )
827 goodness = 100; 827 goodness = 100;
828 else if ( msg.usefulness ) 828 else if ( msg.usefulness )
829 goodness = msg.usefulness * 100 / 15; 829 goodness = msg.usefulness * 100 / 15;
830 else 830 else
831 goodness = 0; 831 goodness = 0;
832 } 832 }
833 else 833 else
834 goodness = 100; /* goodness of level 0 is always 100 % */ 834 goodness = 100; /* goodness of level 0 is always 100 % */
835 835
836 n = msg.ndata; 836 n = msg.ndata;
837 if( n > length ) 837 if( n > length )
838 n = length; 838 n = length;
839 (*add)( msg.data, n, requester ); 839 (*add)( msg.data, n, requester );
840 840
841 /* this is the trick how we cope with the goodness */ 841 /* this is the trick how we cope with the goodness */
842 subtract = (ulong)n * goodness / 100; 842 subtract = (ulong)n * goodness / 100;
843 /* subtract at least 1 byte to avoid infinite loops */ 843 /* subtract at least 1 byte to avoid infinite loops */
844 length -= subtract ? subtract : 1; 844 length -= subtract ? subtract : 1;
845 } 845 }
846 846
847 return 0; 847 return 0;
848} 848}