2003-07-23 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / cipher / rndunix.c
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
104 #ifndef EAGAIN
105 #define EAGAIN  EWOULDBLOCK
106 #endif
107 #ifndef STDIN_FILENO
108 #define STDIN_FILENO 0
109 #endif
110 #ifndef STDOUT_FILENO
111 #define STDOUT_FILENO 1
112 #endif
113
114 #define GATHER_BUFSIZE          49152   /* Usually about 25K are filled */
115
116 /* The structure containing information on random-data sources.  Each
117  * record contains the source and a relative estimate of its usefulness
118  * (weighting) which is used to scale the number of kB of output from the
119  * source (total = data_bytes / usefulness).  Usually the weighting is in the
120  * range 1-3 (or 0 for especially useless sources), resulting in a usefulness
121  * rating of 1...3 for each kB of source output (or 0 for the useless
122  * sources).
123  *
124  * If the source is constantly changing (certain types of network statistics
125  * have this characteristic) but the amount of output is small, the weighting
126  * is given as a negative value to indicate that the output should be treated
127  * as if a minimum of 1K of output had been obtained.  If the source produces
128  * a lot of output then the scale factor is fractional, resulting in a
129  * usefulness rating of < 1 for each kB of source output.
130  *
131  * In order to provide enough randomness to satisfy the requirements for a
132  * slow poll, we need to accumulate at least 20 points of usefulness (a
133  * typical system should get about 30 points).
134  *
135  * Some potential options are missed out because of special considerations.
136  * pstat -i and pstat -f can produce amazing amounts of output (the record
137  * is 600K on an Oracle server) which floods the buffer and doesn't yield
138  * anything useful (apart from perhaps increasing the entropy of the vmstat
139  * output a bit), so we don't bother with this.  pstat in general produces
140  * quite a bit of output, but it doesn't change much over time, so it gets
141  * very low weightings.  netstat -s produces constantly-changing output but
142  * also produces quite a bit of it, so it only gets a weighting of 2 rather
143  * than 3.  The same holds for netstat -in, which gets 1 rather than 2.
144  *
145  * Some binaries are stored in different locations on different systems so
146  * alternative paths are given for them.  The code sorts out which one to
147  * run by itself, once it finds an exectable somewhere it moves on to the
148  * next source.  The sources are arranged roughly in their order of
149  * usefulness, occasionally sources which provide a tiny amount of
150  * relatively useless data are placed ahead of ones which provide a large
151  * amount of possibly useful data because another 100 bytes can't hurt, and
152  * it means the buffer won't be swamped by one or two high-output sources.
153  * All the high-output sources are clustered towards the end of the list
154  * for this reason.  Some binaries are checked for in a certain order, for
155  * example under Slowaris /usr/ucb/ps understands aux as an arg, but the
156  * others don't.  Some systems have conditional defines enabling alternatives
157  * to commands which don't understand the usual options but will provide
158  * enough output (in the form of error messages) to look like they're the
159  * real thing, causing alternative options to be skipped (we can't check the
160  * return either because some commands return peculiar, non-zero status even
161  * when they're working correctly).
162  *
163  * In order to maximise use of the buffer, the code performs a form of run-
164  * length compression on its input where a repeated sequence of bytes is
165  * replaced by the occurrence count mod 256.  Some commands output an awful
166  * lot of whitespace, this measure greatly increases the amount of data we
167  * can fit in the buffer.
168  *
169  * When we scale the weighting using the SC() macro, some preprocessors may
170  * give a division by zero warning for the most obvious expression
171  * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
172  * trap), so we define a value SC_0 which evaluates to zero when fed to
173  * '1024 / SC_0' */
174
175 #define SC( weight )    ( 1024 / weight )       /* Scale factor */
176 #define SC_0                    16384   /* SC( SC_0 ) evalutes to 0 */
177
178 static struct RI {
179     const char *path;           /* Path to check for existence of source */
180     const char *arg;            /* Args for source */
181     const int usefulness;       /* Usefulness of source */
182     FILE *pipe;                 /* Pipe to source as FILE * */
183     int pipeFD;                 /* Pipe to source as FD */
184     pid_t pid;                  /* pid of child for waitpid() */
185     int length;                 /* Quantity of output produced */
186     const int hasAlternative;       /* Whether source has alt.location */
187 } dataSources[] = {
188
189     {   "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1    },
190     {   "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
191     {   "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1     },
192     {   "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
193     {   "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
194     {   "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1     },
195     {   "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
196     {   "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
197     {   "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
198     {   "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
199     {   "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
200     {   "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
201     {   "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
202     {   "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
203     {   "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
204     {   "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
205     {   "/bin/netstat",     "-in", SC(-1), NULL, 0, 0, 0, 1 },
206     {   "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
207     {   "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
208     {   "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
209     {   "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
210     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
211                                     SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
212     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
213                                     SC(-1), NULL, 0, 0, 0, 0 },  /* UDP out */
214     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
215                                     SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
216     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
217                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
218     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
219                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
220     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
221                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
222     {   "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0     },
223     {   "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1           },
224     {   "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0          },
225     {   "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1          },
226     {   "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0             },
227     {   "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0  },
228     {   "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
229     {   "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1   },
230     {   "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
231     {   "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1       },
232     {   "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0  },
233     {   "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1       },
234     {   "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
235     {   "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
236     {   "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
237     {   "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1  },
238     {   "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0  },
239 #if defined( __sgi ) || defined( __hpux )
240     {   "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1           },
241 #endif                          /* __sgi || __hpux */
242     {   "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
243     {   "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
244     {   "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0          },
245     {   "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0           }, /*QNX*/
246     {   "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1      },
247     {   "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0         },
248     /* Unreliable source, depends on system usage */
249     {   "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1         },
250     {   "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0        },
251     {   "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1         },
252     {   "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0        },
253     {   "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1         },
254     {   "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0        },
255     {   "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1         },
256     {   "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0        },
257     {   "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1         },
258     {   "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0        },
259     /* pstat is your friend */
260     {   "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1   },
261 #ifdef __sgi
262     {   "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0    },
263 #endif                          /* __sgi */
264 #ifdef __hpux
265     {   "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0        },
266 #endif                          /* __hpux */
267     {   "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0  },
268     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
269                                 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
270     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
271                                 SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
272     {   "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
273     {   "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
274     {   "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1  },
275     {   "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
276     {   "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
277                                 SC(0.1), NULL, 0, 0, 0, 0 },
278     {   "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1     },
279     {   "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
280     {   "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
281     {   "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
282     /* This is very environment-dependant.  If network traffic is low, it'll
283      * probably time out before delivering 5 packets, which is OK because
284      * it'll probably be fixed stuff like ARP anyway */
285     {   "/usr/sbin/advfsstat", "-b usr_domain",
286                                 SC(SC_0), NULL, 0, 0, 0, 0},
287     {   "/usr/sbin/advfsstat", "-l 2 usr_domain",
288                                 SC(0.5), NULL, 0, 0, 0, 0},
289     {   "/usr/sbin/advfsstat", "-p usr_domain",
290                                 SC(SC_0), NULL, 0, 0, 0, 0},
291     /* This is a complex and screwball program.  Some systems have things
292      * like rX_dmn, x = integer, for RAID systems, but the statistics are
293      * pretty dodgy */
294 #ifdef __QNXNTO__                                                             
295     { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
296              NULL, 0, 0, 0, 0       },
297 #endif     
298 #if 0
299     /* The following aren't enabled since they're somewhat slow and not very
300      * unpredictable, however they give an indication of the sort of sources
301      * you can use (for example the finger might be more useful on a
302      * firewalled internal network) */
303     {   "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
304     {   "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
305                                 SC(0.9), NULL, 0, 0, 0, 0 },
306     {   "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
307 #endif                          /* 0 */
308     {   NULL, NULL, 0, NULL, 0, 0, 0, 0 }
309 };
310
311 static byte *gather_buffer;         /* buffer for gathering random noise */
312 static int gather_buffer_size;      /* size of the memory buffer */
313 static uid_t gatherer_uid;
314
315 /* The message structure used to communicate with the parent */
316 typedef struct {
317     int  usefulness;    /* usefulness of data */
318     int  ndata;         /* valid bytes in data */
319     char data[500];     /* gathered data */
320 } GATHER_MSG;
321
322 #ifndef HAVE_WAITPID
323 pid_t
324 waitpid(pid_t pid, int *statptr, int options)
325 {
326 #ifdef HAVE_WAIT4
327         return wait4(pid, statptr, options, NULL);
328 #else
329         /* If wait4 is also not available, try wait3 for SVR3 variants */
330         /* Less ideal because can't actually request a specific pid */
331         /* For that reason, first check to see if pid is for an */
332         /*   existing process. */
333         int tmp_pid, dummystat;;
334         if (kill(pid, 0) == -1) {
335                 errno = ECHILD;
336                 return -1;
337         }
338         if (statptr == NULL)
339                 statptr = &dummystat;
340         while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
341                     (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
342             ;
343         return tmp_pid;
344 #endif
345 }
346 #endif
347
348 /* Under SunOS popen() doesn't record the pid of the child process.  When
349  * pclose() is called, instead of calling waitpid() for the correct child, it
350  * calls wait() repeatedly until the right child is reaped.  The problem is
351  * that this reaps any other children that happen to have died at that
352  * moment, and when their pclose() comes along, the process hangs forever.
353  * The fix is to use a wrapper for popen()/pclose() which saves the pid in
354  * the dataSources structure (code adapted from GNU-libc's popen() call).
355  *
356  * Aut viam inveniam aut faciam */
357
358 static FILE *
359 my_popen(struct RI *entry)
360 {
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           #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
512             fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
513           #else
514             #warning O_NONBLOCK is missing
515           #endif
516             FD_SET(dataSources[i].pipeFD, &fds);
517             dataSources[i].length = 0;
518
519             /* If there are alternatives for this command, don't try and
520              * execute them */
521             while (dataSources[i].hasAlternative) {
522                 if( dbgfp && dbgall )
523                     fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
524                 i++;
525             }
526         }
527     }
528
529
530     /* Suck all the data we can get from each of the sources */
531     bufPos = 0;
532     moreSources = 1;
533     while (moreSources && bufPos <= gather_buffer_size) {
534         /* Wait for data to become available from any of the sources, with a
535          * timeout of 10 seconds.  This adds even more randomness since data
536          * becomes available in a nondeterministic fashion.  Kudos to HP's QA
537          * department for managing to ship a select() which breaks its own
538          * prototype */
539         tv.tv_sec = 10;
540         tv.tv_usec = 0;
541
542 #if defined( __hpux ) && ( OS_VERSION == 9 )
543         if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
544 #else  /*  */
545         if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
546 #endif /* __hpux */
547             break;
548
549         /* One of the sources has data available, read it into the buffer */
550         for (i = 0; dataSources[i].path != NULL; i++) {
551             if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
552                 size_t noBytes;
553
554                 if ((noBytes = fread(gather_buffer + bufPos, 1,
555                                      gather_buffer_size - bufPos,
556                                      dataSources[i].pipe)) == 0) {
557                     if (my_pclose(&dataSources[i]) == 0) {
558                         int total = 0;
559
560                         /* Try and estimate how much entropy we're getting
561                          * from a data source */
562                         if (dataSources[i].usefulness) {
563                             if (dataSources[i].usefulness < 0)
564                                 total = (dataSources[i].length + 999)
565                                         / -dataSources[i].usefulness;
566                             else
567                                 total = dataSources[i].length
568                                         / dataSources[i].usefulness;
569                         }
570                         if( dbgfp )
571                             fprintf(dbgfp,
572                                "%s %s contributed %d bytes, "
573                                "usefulness = %d\n", dataSources[i].path,
574                                (dataSources[i].arg != NULL) ?
575                                        dataSources[i].arg : "",
576                                       dataSources[i].length, total);
577                         if( dataSources[i].length )
578                             usefulness += total;
579                     }
580                     dataSources[i].pipe = NULL;
581                 }
582                 else {
583                     int currPos = bufPos;
584                     int endPos = bufPos + noBytes;
585
586                     /* Run-length compress the input byte sequence */
587                     while (currPos < endPos) {
588                         int ch = gather_buffer[currPos];
589
590                         /* If it's a single byte, just copy it over */
591                         if (ch != gather_buffer[currPos + 1]) {
592                             gather_buffer[bufPos++] = ch;
593                             currPos++;
594                         }
595                         else {
596                             int count = 0;
597
598                             /* It's a run of repeated bytes, replace them
599                              * with the byte count mod 256 */
600                             while ((ch == gather_buffer[currPos])
601                                     && currPos < endPos) {
602                                 count++;
603                                 currPos++;
604                             }
605                             gather_buffer[bufPos++] = count;
606                             noBytes -= count - 1;
607                         }
608                     }
609
610                     /* Remember the number of (compressed) bytes of input we
611                      * obtained */
612                     dataSources[i].length += noBytes;
613                 }
614             }
615         }
616
617         /* Check if there is more input available on any of the sources */
618         moreSources = 0;
619         FD_ZERO(&fds);
620         for (i = 0; dataSources[i].path != NULL; i++) {
621             if (dataSources[i].pipe != NULL) {
622                 FD_SET(dataSources[i].pipeFD, &fds);
623                 moreSources = 1;
624             }
625         }
626     }
627
628     if( dbgfp ) {
629         fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
630         fflush(dbgfp);
631     }
632     *nbytes = bufPos;
633     return usefulness;
634 }
635
636 /****************
637  * Start the gatherer process which writes messages of
638  * type GATHERER_MSG to pipedes
639  */
640 static void
641 start_gatherer( int pipefd )
642 {
643     FILE *dbgfp = NULL;
644     int dbgall;
645
646     {
647         const char *s = getenv("GNUPG_RNDUNIX_DBG");
648         if( s ) {
649             dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
650             if( !dbgfp )
651                 log_info("can't open debug file `%s': %s\n",
652                              s, strerror(errno) );
653             else
654                 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
655         }
656         dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
657     }
658     /* close all files but the ones we need */
659     {   int nmax, n1, n2, i;
660 #ifdef _SC_OPEN_MAX
661         if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
662           #ifdef _POSIX_OPEN_MAX
663             nmax = _POSIX_OPEN_MAX;
664           #else
665             nmax = 20; /* assume a reasonable value */
666           #endif
667         }
668 #else
669         nmax = 20; /* assume a reasonable value */
670 #endif
671         n1 = fileno( stderr );
672         n2 = dbgfp? fileno( dbgfp ) : -1;
673         for(i=0; i < nmax; i++ ) {
674             if( i != n1 && i != n2 && i != pipefd )
675                 close(i);
676         }
677         errno = 0;
678     }
679
680
681
682     /* Set up the buffer */
683     gather_buffer_size = GATHER_BUFSIZE;
684     gather_buffer = malloc( gather_buffer_size );
685     if( !gather_buffer ) {
686         log_error("out of core while allocating the gatherer buffer\n");
687         exit(2);
688     }
689
690     /* Reset the SIGC(H)LD handler to the system default.  This is necessary
691      * because if the program which cryptlib is a part of installs its own
692      * SIGC(H)LD handler, it will end up reaping the cryptlib children before
693      * cryptlib can.  As a result, my_pclose() will call waitpid() on a
694      * process which has already been reaped by the installed handler and
695      * return an error, so the read data won't be added to the randomness
696      * pool.  There are two types of SIGC(H)LD naming, the SysV SIGCLD and
697      * the BSD/Posix SIGCHLD, so we need to handle either possibility */
698 #ifdef SIGCLD
699     signal(SIGCLD, SIG_DFL);
700 #else
701     signal(SIGCHLD, SIG_DFL);
702 #endif
703
704     fclose(stderr);             /* Arrghh!!  It's Stuart code!! */
705
706     for(;;) {
707         GATHER_MSG msg;
708         size_t nbytes;
709         const char *p;
710
711         msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
712         p = gather_buffer;
713         while( nbytes ) {
714             msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
715             memcpy( msg.data, p, msg.ndata );
716             nbytes -= msg.ndata;
717             p += msg.ndata;
718
719             while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
720                 if( errno == EINTR )
721                     continue;
722                 if( errno == EAGAIN ) {
723                     struct timeval tv;
724                     tv.tv_sec = 0;
725                     tv.tv_usec = 50000;
726                     select(0, NULL, NULL, NULL, &tv);
727                     continue;
728                 }
729                 if( errno == EPIPE ) /* parent has exited, so give up */
730                    exit(0);
731
732                 /* we can't do very much here because stderr is closed */
733                 if( dbgfp )
734                     fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
735                                     strerror(errno) );
736                 /* we start a new poll to give the system some time */
737                 nbytes = 0;
738                 break;
739             }
740         }
741     }
742     /* we are killed when the parent dies */
743 }
744
745
746 static int
747 read_a_msg( int fd, GATHER_MSG *msg )
748 {
749     char *buffer = (char*)msg;
750     size_t length = sizeof( *msg );
751     int n;
752
753     do {
754         do {
755             n = read(fd, buffer, length );
756         } while( n == -1 && errno == EINTR );
757         if( n == -1 )
758             return -1;
759         buffer += n;
760         length -= n;
761     } while( length );
762     return 0;
763 }
764
765
766 /****************
767  * Using a level of 0 should never block and better add nothing
768  * to the pool.  So this is just a dummy for this gatherer.
769  */
770 int
771 rndunix_gather_random( void (*add)(const void*, size_t, int), int requester,
772                        size_t length, int level )
773 {
774     static pid_t gatherer_pid = 0;
775     static int pipedes[2];
776     GATHER_MSG msg;
777     size_t n;
778
779     if( !level )
780         return 0;
781
782     if( !gatherer_pid ) {
783         /* make sure we are not setuid */
784         if( getuid() != geteuid() )
785             BUG();
786         /* time to start the gatherer process */
787         if( pipe( pipedes ) ) {
788             log_error("pipe() failed: %s\n", strerror(errno));
789             return -1;
790         }
791         gatherer_pid = fork();
792         if( gatherer_pid == -1 ) {
793             log_error("can't for gatherer process: %s\n", strerror(errno));
794             return -1;
795         }
796         if( !gatherer_pid ) {
797             start_gatherer( pipedes[1] );
798             /* oops, can't happen */
799             return -1;
800         }
801     }
802
803     /* now read from the gatherer */
804     while( length ) {
805         int goodness;
806         ulong subtract;
807
808         if( read_a_msg( pipedes[0], &msg ) ) {
809             log_error("reading from gatherer pipe failed: %s\n",
810                                                             strerror(errno));
811             return -1;
812         }
813
814
815         if( level > 1 ) {
816             if( msg.usefulness > 30 )
817                 goodness = 100;
818             else if ( msg.usefulness )
819                 goodness = msg.usefulness * 100 / 30;
820             else
821                 goodness = 0;
822         }
823         else if( level ) {
824             if( msg.usefulness > 15 )
825                 goodness = 100;
826             else if ( msg.usefulness )
827                 goodness = msg.usefulness * 100 / 15;
828             else
829                 goodness = 0;
830         }
831         else
832             goodness = 100; /* goodness of level 0 is always 100 % */
833
834         n = msg.ndata;
835         if( n > length )
836             n = length;
837         (*add)( msg.data, n, requester );
838
839         /* this is the trick how e cope with the goodness */
840         subtract = (ulong)n * goodness / 100;
841         /* subtract at least 1 byte to avoid infinite loops */
842         length -= subtract ? subtract : 1;
843     }
844
845     return 0;
846 }