Diffstat (limited to 'pwmanager/libcrypt/cipher/rndunix.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | pwmanager/libcrypt/cipher/rndunix.c | 848 |
1 files changed, 848 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/rndunix.c b/pwmanager/libcrypt/cipher/rndunix.c new file mode 100644 index 0000000..3ebb823 --- a/dev/null +++ b/pwmanager/libcrypt/cipher/rndunix.c | |||
@@ -0,0 +1,848 @@ | |||
1 | /**************************************************************************** | ||
2 | * * | ||
3 | * * | ||
4 | * Unix Randomness-Gathering Code * | ||
5 | * * | ||
6 | * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. * | ||
7 | * Heavily modified for GnuPG by Werner Koch * | ||
8 | * * | ||
9 | * * | ||
10 | ****************************************************************************/ | ||
11 | |||
12 | /* This module is part of the cryptlib continuously seeded pseudorandom | ||
13 | number generator. For usage conditions, see lib_rand.c | ||
14 | |||
15 | [Here is the notice from lib_rand.c:] | ||
16 | |||
17 | This module and the misc/rnd*.c modules represent the cryptlib | ||
18 | continuously seeded pseudorandom number generator (CSPRNG) as described in | ||
19 | my 1998 Usenix Security Symposium paper "The generation of random numbers | ||
20 | for cryptographic purposes". | ||
21 | |||
22 | The CSPRNG code is copyright Peter Gutmann (and various others) 1996, | ||
23 | 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG | ||
24 | modules and use in source and binary forms, with or without modification, | ||
25 | are permitted provided that the following conditions are met: | ||
26 | |||
27 | 1. Redistributions of source code must retain the above copyright notice | ||
28 | and this permission notice in its entirety. | ||
29 | |||
30 | 2. Redistributions in binary form must reproduce the copyright notice in | ||
31 | the documentation and/or other materials provided with the distribution. | ||
32 | |||
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 | ||
35 | baseline version of the code. | ||
36 | |||
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 | ||
39 | Free Software Foundation, in which case the provisions of the GNU GPL are | ||
40 | required INSTEAD OF the above restrictions. | ||
41 | |||
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 | ||
44 | code base to be maintained */ | ||
45 | |||
46 | |||
47 | /* Fixme: We use plain mallocs here beucase it may be used as a module | ||
48 | * should be changed. */ | ||
49 | |||
50 | /* General includes */ | ||
51 | |||
52 | #include <config.h> | ||
53 | #include <stdlib.h> | ||
54 | #include <stdio.h> | ||
55 | #include <string.h> | ||
56 | #include <assert.h> | ||
57 | |||
58 | /* OS-specific includes */ | ||
59 | |||
60 | #ifdef __osf__ | ||
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 | ||
63 | * undefine the cryptlib ones, which aren't really needed for this module | ||
64 | * anyway */ | ||
65 | #undef BIG_ENDIAN | ||
66 | #undef LITTLE_ENDIAN | ||
67 | #endif /* __osf__ */ | ||
68 | |||
69 | #include <unistd.h> | ||
70 | #include <fcntl.h> | ||
71 | #include <pwd.h> | ||
72 | #ifndef __QNX__ | ||
73 | #include <sys/errno.h> | ||
74 | #include <sys/ipc.h> | ||
75 | #endif /* __QNX__ */ | ||
76 | #include <sys/time.h> /* SCO and SunOS need this before resource.h */ | ||
77 | #ifndef __QNX__ | ||
78 | #include <sys/resource.h> | ||
79 | #endif /* __QNX__ */ | ||
80 | #if defined( _AIX ) || defined( __QNX__ ) | ||
81 | #include <sys/select.h> | ||
82 | #endif /* _AIX */ | ||
83 | #ifndef __QNX__ | ||
84 | #include <sys/shm.h> | ||
85 | #include <signal.h> | ||
86 | #include <sys/signal.h> | ||
87 | #endif /* __QNX__ */ | ||
88 | #include <sys/stat.h> | ||
89 | #include <sys/types.h> /* Verschiedene komische Typen */ | ||
90 | #if defined( __hpux ) && ( OS_VERSION == 9 ) | ||
91 | #include <vfork.h> | ||
92 | #endif /* __hpux 9.x, after that it's in unistd.h */ | ||
93 | #include <sys/wait.h> | ||
94 | /* #include <kitchensink.h> */ | ||
95 | #ifdef __QNX__ | ||
96 | #include <signal.h> | ||
97 | #include <process.h> | ||
98 | #endif /* __QNX__ */ | ||
99 | #include <errno.h> | ||
100 | |||
101 | #include "types.h" /* for byte and u32 typedefs */ | ||
102 | #include "g10lib.h" | ||
103 | #include "rand-internal.h" | ||
104 | |||
105 | #ifndef EAGAIN | ||
106 | #define EAGAINEWOULDBLOCK | ||
107 | #endif | ||
108 | #ifndef STDIN_FILENO | ||
109 | #define STDIN_FILENO 0 | ||
110 | #endif | ||
111 | #ifndef STDOUT_FILENO | ||
112 | #define STDOUT_FILENO 1 | ||
113 | #endif | ||
114 | |||
115 | #define GATHER_BUFSIZE 49152/* Usually about 25K are filled */ | ||
116 | |||
117 | /* The structure containing information on random-data sources. Each | ||
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 | ||
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 | ||
122 | * rating of 1...3 for each kB of source output (or 0 for the useless | ||
123 | * sources). | ||
124 | * | ||
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 | ||
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 | ||
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. | ||
131 | * | ||
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 | ||
134 | * typical system should get about 30 points). | ||
135 | * | ||
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 | ||
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 | ||
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 | ||
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 | ||
144 | * than 3. The same holds for netstat -in, which gets 1 rather than 2. | ||
145 | * | ||
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 | ||
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 | ||
150 | * usefulness, occasionally sources which provide a tiny amount of | ||
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 | ||
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 | ||
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 | ||
157 | * others don't. Some systems have conditional defines enabling alternatives | ||
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 | ||
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 | ||
162 | * when they're working correctly). | ||
163 | * | ||
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 | ||
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 | ||
168 | * can fit in the buffer. | ||
169 | * | ||
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 | ||
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 | ||
174 | * '1024 / SC_0' */ | ||
175 | |||
176 | #define SC( weight ) ( 1024 / weight )/* Scale factor */ | ||
177 | #define SC_0 16384/* SC( SC_0 ) evalutes to 0 */ | ||
178 | |||
179 | static struct RI { | ||
180 | const char *path; /* Path to check for existence of source */ | ||
181 | const char *arg; /* Args for source */ | ||
182 | const int usefulness;/* Usefulness of source */ | ||
183 | FILE *pipe; /* Pipe to source as FILE * */ | ||
184 | int pipeFD; /* Pipe to source as FD */ | ||
185 | pid_t pid; /* pid of child for waitpid() */ | ||
186 | int length; /* Quantity of output produced */ | ||
187 | const int hasAlternative; /* Whether source has alt.location */ | ||
188 | } dataSources[] = { | ||
189 | |||
190 | {"/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 }, | ||
191 | {"/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0}, | ||
192 | {"/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 }, | ||
193 | {"/usr/bin/vmstat", "-c", SC(-3), 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 }, | ||
196 | {"/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0}, | ||
197 | {"/usr/ucb/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}, | ||
200 | {"/usr/etc/netstat", "-s", 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 }, | ||
203 | {"/usr/bin/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 }, | ||
206 | {"/bin/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 }, | ||
209 | {"/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1}, | ||
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", | ||
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", | ||
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", | ||
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", | ||
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", | ||
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", | ||
222 | SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ | ||
223 | {"/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, | ||
224 | {"/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 }, | ||
225 | {"/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 }, | ||
226 | {"/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 }, | ||
227 | {"/bin/df", 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 }, | ||
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 }, | ||
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 }, | ||
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 }, | ||
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 }, | ||
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 }, | ||
240 | #if defined( __sgi ) || defined( __hpux ) | ||
241 | {"/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 }, | ||
242 | #endif /* __sgi || __hpux */ | ||
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 }, | ||
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*/ | ||
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 }, | ||
249 | /* Unreliable source, depends on system usage */ | ||
250 | {"/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 }, | ||
251 | {"/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 }, | ||
252 | {"/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 }, | ||
253 | {"/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 }, | ||
254 | {"/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 }, | ||
255 | {"/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 }, | ||
256 | {"/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 }, | ||
257 | {"/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 }, | ||
258 | {"/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, | ||
259 | {"/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, | ||
260 | /* pstat is your friend */ | ||
261 | {"/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 }, | ||
262 | #ifdef __sgi | ||
263 | {"/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, | ||
264 | #endif /* __sgi */ | ||
265 | #ifdef __hpux | ||
266 | {"/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, | ||
267 | #endif /* __hpux */ | ||
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", | ||
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", | ||
272 | SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ | ||
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 }, | ||
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 }, | ||
277 | {"/usr/sbin/ripquery", "-nw 1 127.0.0.1", | ||
278 | SC(0.1), NULL, 0, 0, 0, 0 }, | ||
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 }, | ||
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 }, | ||
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 | ||
285 | * it'll probably be fixed stuff like ARP anyway */ | ||
286 | {"/usr/sbin/advfsstat", "-b usr_domain", | ||
287 | SC(SC_0), NULL, 0, 0, 0, 0}, | ||
288 | {"/usr/sbin/advfsstat", "-l 2 usr_domain", | ||
289 | SC(0.5), NULL, 0, 0, 0, 0}, | ||
290 | {"/usr/sbin/advfsstat", "-p usr_domain", | ||
291 | SC(SC_0), NULL, 0, 0, 0, 0}, | ||
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 | ||
294 | * pretty dodgy */ | ||
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), | ||
297 | NULL, 0, 0, 0, 0 }, | ||
298 | #endif | ||
299 | #if 0 | ||
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 | ||
302 | * you can use (for example the finger might be more useful on a | ||
303 | * firewalled internal network) */ | ||
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", | ||
306 | 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 */ | ||
309 | {NULL, NULL, 0, NULL, 0, 0, 0, 0 } | ||
310 | }; | ||
311 | |||
312 | static byte *gather_buffer; /* buffer for gathering random noise */ | ||
313 | static int gather_buffer_size; /* size of the memory buffer */ | ||
314 | static uid_t gatherer_uid; | ||
315 | |||
316 | /* The message structure used to communicate with the parent */ | ||
317 | typedef struct { | ||
318 | int usefulness;/* usefulness of data */ | ||
319 | int ndata; /* valid bytes in data */ | ||
320 | char data[500];/* gathered data */ | ||
321 | } GATHER_MSG; | ||
322 | |||
323 | #ifndef HAVE_WAITPID | ||
324 | static pid_t | ||
325 | waitpid(pid_t pid, int *statptr, int options) | ||
326 | { | ||
327 | #ifdef HAVE_WAIT4 | ||
328 | return wait4(pid, statptr, options, NULL); | ||
329 | #else | ||
330 | /* If wait4 is also not available, try wait3 for SVR3 variants */ | ||
331 | /* Less ideal because can't actually request a specific pid */ | ||
332 | /* For that reason, first check to see if pid is for an */ | ||
333 | /* existing process. */ | ||
334 | int tmp_pid, dummystat;; | ||
335 | if (kill(pid, 0) == -1) { | ||
336 | errno = ECHILD; | ||
337 | return -1; | ||
338 | } | ||
339 | if (statptr == NULL) | ||
340 | statptr = &dummystat; | ||
341 | while (((tmp_pid = wait3(statptr, options, 0)) != pid) && | ||
342 | (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) | ||
343 | ; | ||
344 | return tmp_pid; | ||
345 | #endif | ||
346 | } | ||
347 | #endif | ||
348 | |||
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 | ||
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 | ||
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 | ||
355 | * the dataSources structure (code adapted from GNU-libc's popen() call). | ||
356 | * | ||
357 | * Aut viam inveniam aut faciam */ | ||
358 | |||
359 | static FILE * | ||
360 | my_popen(struct RI *entry) | ||
361 | { | ||
362 | int pipedes[2]; | ||
363 | FILE *stream; | ||
364 | |||
365 | /* Create the pipe */ | ||
366 | if (pipe(pipedes) < 0) | ||
367 | return (NULL); | ||
368 | |||
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 | ||
371 | * supports it, you should try to use vfork() here because it's somewhat | ||
372 | * more efficient */ | ||
373 | #if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \ | ||
374 | defined(__hpux) | ||
375 | entry->pid = vfork(); | ||
376 | #else /* */ | ||
377 | entry->pid = fork(); | ||
378 | #endif /* Unixen which have vfork() */ | ||
379 | if (entry->pid == (pid_t) - 1) { | ||
380 | /* The fork failed */ | ||
381 | close(pipedes[0]); | ||
382 | close(pipedes[1]); | ||
383 | return (NULL); | ||
384 | } | ||
385 | |||
386 | if (entry->pid == (pid_t) 0) { | ||
387 | struct passwd *passwd; | ||
388 | |||
389 | /* We are the child. Make the read side of the pipe be stdout */ | ||
390 | if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) | ||
391 | exit(127); | ||
392 | |||
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, | ||
395 | * we default to -1, which is usually nobody */ | ||
396 | if (gatherer_uid == (uid_t)-1 && \ | ||
397 | (passwd = getpwnam("nobody")) != NULL) | ||
398 | gatherer_uid = passwd->pw_uid; | ||
399 | |||
400 | setuid(gatherer_uid); | ||
401 | |||
402 | /* Close the pipe descriptors */ | ||
403 | close(pipedes[STDIN_FILENO]); | ||
404 | close(pipedes[STDOUT_FILENO]); | ||
405 | |||
406 | /* Try and exec the program */ | ||
407 | execl(entry->path, entry->path, entry->arg, NULL); | ||
408 | |||
409 | /* Die if the exec failed */ | ||
410 | exit(127); | ||
411 | } | ||
412 | |||
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 | ||
415 | * close on exec, so new children won't see it */ | ||
416 | close(pipedes[STDOUT_FILENO]); | ||
417 | |||
418 | #ifdef FD_CLOEXEC | ||
419 | fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); | ||
420 | #endif | ||
421 | |||
422 | stream = fdopen(pipedes[STDIN_FILENO], "r"); | ||
423 | |||
424 | if (stream == NULL) { | ||
425 | int savedErrno = errno; | ||
426 | |||
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 */ | ||
429 | kill(entry->pid, SIGKILL); | ||
430 | if (stream == NULL) | ||
431 | close(pipedes[STDOUT_FILENO]); | ||
432 | else | ||
433 | fclose(stream); | ||
434 | |||
435 | waitpid(entry->pid, NULL, 0); | ||
436 | |||
437 | entry->pid = 0; | ||
438 | errno = savedErrno; | ||
439 | return (NULL); | ||
440 | } | ||
441 | |||
442 | return (stream); | ||
443 | } | ||
444 | |||
445 | static int | ||
446 | my_pclose(struct RI *entry) | ||
447 | { | ||
448 | int status = 0; | ||
449 | |||
450 | if (fclose(entry->pipe)) | ||
451 | return (-1); | ||
452 | |||
453 | /* We ignore the return value from the process because some programs | ||
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 | ||
456 | * result data size threshold will filter out any programs which exit | ||
457 | * with a usage message without producing useful output */ | ||
458 | if (waitpid(entry->pid, NULL, 0) != entry->pid) | ||
459 | status = -1; | ||
460 | |||
461 | entry->pipe = NULL; | ||
462 | entry->pid = 0; | ||
463 | return (status); | ||
464 | } | ||
465 | |||
466 | |||
467 | /* Unix slow poll (without special support for Linux) | ||
468 | * | ||
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 | ||
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 | ||
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 | ||
475 | * well as the source type */ | ||
476 | |||
477 | |||
478 | static int | ||
479 | slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) | ||
480 | { | ||
481 | int moreSources; | ||
482 | struct timeval tv; | ||
483 | fd_set fds; | ||
484 | #if defined( __hpux ) | ||
485 | size_t maxFD = 0; | ||
486 | #else | ||
487 | int maxFD = 0; | ||
488 | #endif /* OS-specific brokenness */ | ||
489 | int bufPos, i, usefulness = 0; | ||
490 | |||
491 | |||
492 | /* Fire up each randomness source */ | ||
493 | FD_ZERO(&fds); | ||
494 | for (i = 0; dataSources[i].path != NULL; i++) { | ||
495 | /* Since popen() is a fairly heavy function, we check to see whether | ||
496 | * the executable exists before we try to run it */ | ||
497 | if (access(dataSources[i].path, X_OK)) { | ||
498 | if( dbgfp && dbgall ) | ||
499 | fprintf(dbgfp, "%s not present%s\n", dataSources[i].path, | ||
500 | dataSources[i].hasAlternative ? | ||
501 | ", has alternatives" : ""); | ||
502 | dataSources[i].pipe = NULL; | ||
503 | } | ||
504 | else | ||
505 | dataSources[i].pipe = my_popen(&dataSources[i]); | ||
506 | |||
507 | if (dataSources[i].pipe != NULL) { | ||
508 | dataSources[i].pipeFD = fileno(dataSources[i].pipe); | ||
509 | if (dataSources[i].pipeFD > maxFD) | ||
510 | maxFD = dataSources[i].pipeFD; | ||
511 | |||
512 | #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */ | ||
513 | fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK); | ||
514 | #else | ||
515 | #error O_NONBLOCK is missing | ||
516 | #endif | ||
517 | |||
518 | FD_SET(dataSources[i].pipeFD, &fds); | ||
519 | dataSources[i].length = 0; | ||
520 | |||
521 | /* If there are alternatives for this command, don't try and | ||
522 | * execute them */ | ||
523 | while (dataSources[i].hasAlternative) { | ||
524 | if( dbgfp && dbgall ) | ||
525 | fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path); | ||
526 | i++; | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | |||
532 | /* Suck all the data we can get from each of the sources */ | ||
533 | bufPos = 0; | ||
534 | moreSources = 1; | ||
535 | while (moreSources && bufPos <= gather_buffer_size) { | ||
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 | ||
538 | * becomes available in a nondeterministic fashion. Kudos to HP's QA | ||
539 | * department for managing to ship a select() which breaks its own | ||
540 | * prototype */ | ||
541 | tv.tv_sec = 10; | ||
542 | tv.tv_usec = 0; | ||
543 | |||
544 | #if defined( __hpux ) && ( OS_VERSION == 9 ) | ||
545 | if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) | ||
546 | #else /* */ | ||
547 | if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) | ||
548 | #endif /* __hpux */ | ||
549 | break; | ||
550 | |||
551 | /* One of the sources has data available, read it into the buffer */ | ||
552 | for (i = 0; dataSources[i].path != NULL; i++) { | ||
553 | if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { | ||
554 | size_t noBytes; | ||
555 | |||
556 | if ((noBytes = fread(gather_buffer + bufPos, 1, | ||
557 | gather_buffer_size - bufPos, | ||
558 | dataSources[i].pipe)) == 0) { | ||
559 | if (my_pclose(&dataSources[i]) == 0) { | ||
560 | int total = 0; | ||
561 | |||
562 | /* Try and estimate how much entropy we're getting | ||
563 | * from a data source */ | ||
564 | if (dataSources[i].usefulness) { | ||
565 | if (dataSources[i].usefulness < 0) | ||
566 | total = (dataSources[i].length + 999) | ||
567 | / -dataSources[i].usefulness; | ||
568 | else | ||
569 | total = dataSources[i].length | ||
570 | / dataSources[i].usefulness; | ||
571 | } | ||
572 | if( dbgfp ) | ||
573 | fprintf(dbgfp, | ||
574 | "%s %s contributed %d bytes, " | ||
575 | "usefulness = %d\n", dataSources[i].path, | ||
576 | (dataSources[i].arg != NULL) ? | ||
577 | dataSources[i].arg : "", | ||
578 | dataSources[i].length, total); | ||
579 | if( dataSources[i].length ) | ||
580 | usefulness += total; | ||
581 | } | ||
582 | dataSources[i].pipe = NULL; | ||
583 | } | ||
584 | else { | ||
585 | int currPos = bufPos; | ||
586 | int endPos = bufPos + noBytes; | ||
587 | |||
588 | /* Run-length compress the input byte sequence */ | ||
589 | while (currPos < endPos) { | ||
590 | int ch = gather_buffer[currPos]; | ||
591 | |||
592 | /* If it's a single byte, just copy it over */ | ||
593 | if (ch != gather_buffer[currPos + 1]) { | ||
594 | gather_buffer[bufPos++] = ch; | ||
595 | currPos++; | ||
596 | } | ||
597 | else { | ||
598 | int count = 0; | ||
599 | |||
600 | /* It's a run of repeated bytes, replace them | ||
601 | * with the byte count mod 256 */ | ||
602 | while ((ch == gather_buffer[currPos]) | ||
603 | && currPos < endPos) { | ||
604 | count++; | ||
605 | currPos++; | ||
606 | } | ||
607 | gather_buffer[bufPos++] = count; | ||
608 | noBytes -= count - 1; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | /* Remember the number of (compressed) bytes of input we | ||
613 | * obtained */ | ||
614 | dataSources[i].length += noBytes; | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /* Check if there is more input available on any of the sources */ | ||
620 | moreSources = 0; | ||
621 | FD_ZERO(&fds); | ||
622 | for (i = 0; dataSources[i].path != NULL; i++) { | ||
623 | if (dataSources[i].pipe != NULL) { | ||
624 | FD_SET(dataSources[i].pipeFD, &fds); | ||
625 | moreSources = 1; | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | |||
630 | if( dbgfp ) { | ||
631 | fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); | ||
632 | fflush(dbgfp); | ||
633 | } | ||
634 | *nbytes = bufPos; | ||
635 | return usefulness; | ||
636 | } | ||
637 | |||
638 | /**************** | ||
639 | * Start the gatherer process which writes messages of | ||
640 | * type GATHERER_MSG to pipedes | ||
641 | */ | ||
642 | static void | ||
643 | start_gatherer( int pipefd ) | ||
644 | { | ||
645 | FILE *dbgfp = NULL; | ||
646 | int dbgall; | ||
647 | |||
648 | { | ||
649 | const char *s = getenv("GNUPG_RNDUNIX_DBG"); | ||
650 | if( s ) { | ||
651 | dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a"); | ||
652 | if( !dbgfp ) | ||
653 | log_info("can't open debug file `%s': %s\n", | ||
654 | s, strerror(errno) ); | ||
655 | else | ||
656 | fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid()); | ||
657 | } | ||
658 | dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL"); | ||
659 | } | ||
660 | /* close all files but the ones we need */ | ||
661 | {int nmax, n1, n2, i; | ||
662 | #ifdef _SC_OPEN_MAX | ||
663 | if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) { | ||
664 | #ifdef _POSIX_OPEN_MAX | ||
665 | nmax = _POSIX_OPEN_MAX; | ||
666 | #else | ||
667 | nmax = 20; /* assume a reasonable value */ | ||
668 | #endif | ||
669 | } | ||
670 | #else /*!_SC_OPEN_MAX*/ | ||
671 | nmax = 20; /* assume a reasonable value */ | ||
672 | #endif /*!_SC_OPEN_MAX*/ | ||
673 | n1 = fileno( stderr ); | ||
674 | n2 = dbgfp? fileno( dbgfp ) : -1; | ||
675 | for(i=0; i < nmax; i++ ) { | ||
676 | if( i != n1 && i != n2 && i != pipefd ) | ||
677 | close(i); | ||
678 | } | ||
679 | errno = 0; | ||
680 | } | ||
681 | |||
682 | |||
683 | /* Set up the buffer */ | ||
684 | gather_buffer_size = GATHER_BUFSIZE; | ||
685 | gather_buffer = malloc( gather_buffer_size ); | ||
686 | if( !gather_buffer ) { | ||
687 | log_error("out of core while allocating the gatherer buffer\n"); | ||
688 | exit(2); | ||
689 | } | ||
690 | |||
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 | ||
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 | ||
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 | ||
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 */ | ||
699 | #ifdef SIGCLD | ||
700 | signal(SIGCLD, SIG_DFL); | ||
701 | #else | ||
702 | signal(SIGCHLD, SIG_DFL); | ||
703 | #endif | ||
704 | |||
705 | fclose(stderr); /* Arrghh!! It's Stuart code!! */ | ||
706 | |||
707 | for(;;) { | ||
708 | GATHER_MSG msg; | ||
709 | size_t nbytes; | ||
710 | const char *p; | ||
711 | |||
712 | msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes ); | ||
713 | p = gather_buffer; | ||
714 | while( nbytes ) { | ||
715 | msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes; | ||
716 | memcpy( msg.data, p, msg.ndata ); | ||
717 | nbytes -= msg.ndata; | ||
718 | p += msg.ndata; | ||
719 | |||
720 | while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) { | ||
721 | if( errno == EINTR ) | ||
722 | continue; | ||
723 | if( errno == EAGAIN ) { | ||
724 | struct timeval tv; | ||
725 | tv.tv_sec = 0; | ||
726 | tv.tv_usec = 50000; | ||
727 | select(0, NULL, NULL, NULL, &tv); | ||
728 | continue; | ||
729 | } | ||
730 | if( errno == EPIPE ) /* parent has exited, so give up */ | ||
731 | exit(0); | ||
732 | |||
733 | /* we can't do very much here because stderr is closed */ | ||
734 | if( dbgfp ) | ||
735 | fprintf(dbgfp, "gatherer can't write to pipe: %s\n", | ||
736 | strerror(errno) ); | ||
737 | /* we start a new poll to give the system some time */ | ||
738 | nbytes = 0; | ||
739 | break; | ||
740 | } | ||
741 | } | ||
742 | } | ||
743 | /* we are killed when the parent dies */ | ||
744 | } | ||
745 | |||
746 | |||
747 | static int | ||
748 | read_a_msg( int fd, GATHER_MSG *msg ) | ||
749 | { | ||
750 | char *buffer = (char*)msg; | ||
751 | size_t length = sizeof( *msg ); | ||
752 | int n; | ||
753 | |||
754 | do { | ||
755 | do { | ||
756 | n = read(fd, buffer, length ); | ||
757 | } while( n == -1 && errno == EINTR ); | ||
758 | if( n == -1 ) | ||
759 | return -1; | ||
760 | buffer += n; | ||
761 | length -= n; | ||
762 | } while( length ); | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | |||
767 | /**************** | ||
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. | ||
770 | */ | ||
771 | int | ||
772 | _gcry_rndunix_gather_random (void (*add)(const void*, size_t, int), | ||
773 | int requester, | ||
774 | size_t length, int level ) | ||
775 | { | ||
776 | static pid_t gatherer_pid = 0; | ||
777 | static int pipedes[2]; | ||
778 | GATHER_MSG msg; | ||
779 | size_t n; | ||
780 | |||
781 | if( !level ) | ||
782 | return 0; | ||
783 | |||
784 | if( !gatherer_pid ) { | ||
785 | /* make sure we are not setuid */ | ||
786 | if( getuid() != geteuid() ) | ||
787 | BUG(); | ||
788 | /* time to start the gatherer process */ | ||
789 | if( pipe( pipedes ) ) { | ||
790 | log_error("pipe() failed: %s\n", strerror(errno)); | ||
791 | return -1; | ||
792 | } | ||
793 | gatherer_pid = fork(); | ||
794 | if( gatherer_pid == -1 ) { | ||
795 | log_error("can't for gatherer process: %s\n", strerror(errno)); | ||
796 | return -1; | ||
797 | } | ||
798 | if( !gatherer_pid ) { | ||
799 | start_gatherer( pipedes[1] ); | ||
800 | /* oops, can't happen */ | ||
801 | return -1; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | /* now read from the gatherer */ | ||
806 | while( length ) { | ||
807 | int goodness; | ||
808 | ulong subtract; | ||
809 | |||
810 | if( read_a_msg( pipedes[0], &msg ) ) { | ||
811 | log_error("reading from gatherer pipe failed: %s\n", | ||
812 | strerror(errno)); | ||
813 | return -1; | ||
814 | } | ||
815 | |||
816 | |||
817 | if( level > 1 ) { | ||
818 | if( msg.usefulness > 30 ) | ||
819 | goodness = 100; | ||
820 | else if ( msg.usefulness ) | ||
821 | goodness = msg.usefulness * 100 / 30; | ||
822 | else | ||
823 | goodness = 0; | ||
824 | } | ||
825 | else if( level ) { | ||
826 | if( msg.usefulness > 15 ) | ||
827 | goodness = 100; | ||
828 | else if ( msg.usefulness ) | ||
829 | goodness = msg.usefulness * 100 / 15; | ||
830 | else | ||
831 | goodness = 0; | ||
832 | } | ||
833 | else | ||
834 | goodness = 100; /* goodness of level 0 is always 100 % */ | ||
835 | |||
836 | n = msg.ndata; | ||
837 | if( n > length ) | ||
838 | n = length; | ||
839 | (*add)( msg.data, n, requester ); | ||
840 | |||
841 | /* this is the trick how we cope with the goodness */ | ||
842 | subtract = (ulong)n * goodness / 100; | ||
843 | /* subtract at least 1 byte to avoid infinite loops */ | ||
844 | length -= subtract ? subtract : 1; | ||
845 | } | ||
846 | |||
847 | return 0; | ||
848 | } | ||