See ChangeLog: Mon Jul 17 16:35:47 CEST 2000 Werner Koch
[gnupg.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 <sys/signal.h>
86 #endif                          /* __QNX__ */
87 #include <sys/stat.h>
88 #include <sys/types.h>          /* Verschiedene komische Typen */
89 #if defined( __hpux ) && ( OS_VERSION == 9 )
90 #include <vfork.h>
91 #endif                          /* __hpux 9.x, after that it's in unistd.h */
92 #include <sys/wait.h>
93 /* #include <kitchensink.h> */
94 #ifdef __QNX__
95 #include <signal.h>
96 #include <process.h>
97 #endif                /* __QNX__ */
98 #include <errno.h>
99
100 #include "types.h"  /* for byte and u32 typedefs */
101 #ifndef IS_MODULE
102 #include "dynload.h"
103 #endif
104 #include "g10lib.h"
105
106 #ifndef EAGAIN
107 #define EAGAIN  EWOULDBLOCK
108 #endif
109 #ifndef STDIN_FILENO
110 #define STDIN_FILENO 0
111 #endif
112 #ifndef STDOUT_FILENO
113 #define STDOUT_FILENO 1
114 #endif
115
116 #define GATHER_BUFSIZE          49152   /* Usually about 25K are filled */
117
118 /* The structure containing information on random-data sources.  Each
119  * record contains the source and a relative estimate of its usefulness
120  * (weighting) which is used to scale the number of kB of output from the
121  * source (total = data_bytes / usefulness).  Usually the weighting is in the
122  * range 1-3 (or 0 for especially useless sources), resulting in a usefulness
123  * rating of 1...3 for each kB of source output (or 0 for the useless
124  * sources).
125  *
126  * If the source is constantly changing (certain types of network statistics
127  * have this characteristic) but the amount of output is small, the weighting
128  * is given as a negative value to indicate that the output should be treated
129  * as if a minimum of 1K of output had been obtained.  If the source produces
130  * a lot of output then the scale factor is fractional, resulting in a
131  * usefulness rating of < 1 for each kB of source output.
132  *
133  * In order to provide enough randomness to satisfy the requirements for a
134  * slow poll, we need to accumulate at least 20 points of usefulness (a
135  * typical system should get about 30 points).
136  *
137  * Some potential options are missed out because of special considerations.
138  * pstat -i and pstat -f can produce amazing amounts of output (the record
139  * is 600K on an Oracle server) which floods the buffer and doesn't yield
140  * anything useful (apart from perhaps increasing the entropy of the vmstat
141  * output a bit), so we don't bother with this.  pstat in general produces
142  * quite a bit of output, but it doesn't change much over time, so it gets
143  * very low weightings.  netstat -s produces constantly-changing output but
144  * also produces quite a bit of it, so it only gets a weighting of 2 rather
145  * than 3.  The same holds for netstat -in, which gets 1 rather than 2.
146  *
147  * Some binaries are stored in different locations on different systems so
148  * alternative paths are given for them.  The code sorts out which one to
149  * run by itself, once it finds an exectable somewhere it moves on to the
150  * next source.  The sources are arranged roughly in their order of
151  * usefulness, occasionally sources which provide a tiny amount of
152  * relatively useless data are placed ahead of ones which provide a large
153  * amount of possibly useful data because another 100 bytes can't hurt, and
154  * it means the buffer won't be swamped by one or two high-output sources.
155  * All the high-output sources are clustered towards the end of the list
156  * for this reason.  Some binaries are checked for in a certain order, for
157  * example under Slowaris /usr/ucb/ps understands aux as an arg, but the
158  * others don't.  Some systems have conditional defines enabling alternatives
159  * to commands which don't understand the usual options but will provide
160  * enough output (in the form of error messages) to look like they're the
161  * real thing, causing alternative options to be skipped (we can't check the
162  * return either because some commands return peculiar, non-zero status even
163  * when they're working correctly).
164  *
165  * In order to maximise use of the buffer, the code performs a form of run-
166  * length compression on its input where a repeated sequence of bytes is
167  * replaced by the occurrence count mod 256.  Some commands output an awful
168  * lot of whitespace, this measure greatly increases the amount of data we
169  * can fit in the buffer.
170  *
171  * When we scale the weighting using the SC() macro, some preprocessors may
172  * give a division by zero warning for the most obvious expression
173  * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
174  * trap), so we define a value SC_0 which evaluates to zero when fed to
175  * '1024 / SC_0' */
176
177 #define SC( weight )    ( 1024 / weight )       /* Scale factor */
178 #define SC_0                    16384   /* SC( SC_0 ) evalutes to 0 */
179
180 static struct RI {
181     const char *path;           /* Path to check for existence of source */
182     const char *arg;            /* Args for source */
183     const int usefulness;       /* Usefulness of source */
184     FILE *pipe;                 /* Pipe to source as FILE * */
185     int pipeFD;                 /* Pipe to source as FD */
186     pid_t pid;                  /* pid of child for waitpid() */
187     int length;                 /* Quantity of output produced */
188     const int hasAlternative;       /* Whether source has alt.location */
189 } dataSources[] = {
190
191     {   "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1    },
192     {   "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
193     {   "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1     },
194     {   "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
195     {   "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
196     {   "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1     },
197     {   "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
198     {   "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
199     {   "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
200     {   "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
201     {   "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
202     {   "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
203     {   "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
204     {   "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1  },
205     {   "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
206     {   "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
207     {   "/bin/netstat",     "-in", SC(-1), NULL, 0, 0, 0, 1 },
208     {   "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
209     {   "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
210     {   "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
211     {   "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
212     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
213                                     SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
214     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
215                                     SC(-1), NULL, 0, 0, 0, 0 },  /* UDP out */
216     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
217                                     SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
218     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.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.11.0",
221                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
222     {   "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
223                                     SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
224     {   "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0     },
225     {   "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1           },
226     {   "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0          },
227     {   "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1          },
228     {   "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0             },
229     {   "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0  },
230     {   "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
231     {   "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1   },
232     {   "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
233     {   "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1       },
234     {   "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0  },
235     {   "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1       },
236     {   "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0  },
237     {   "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
238     {   "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1   },
239     {   "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1  },
240     {   "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0  },
241 #if defined( __sgi ) || defined( __hpux )
242     {   "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1           },
243 #endif                          /* __sgi || __hpux */
244     {   "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
245     {   "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1       },
246     {   "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0          },
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 #if 0
296     /* The following aren't enabled since they're somewhat slow and not very
297      * unpredictable, however they give an indication of the sort of sources
298      * you can use (for example the finger might be more useful on a
299      * firewalled internal network) */
300     {   "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
301     {   "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
302                                 SC(0.9), NULL, 0, 0, 0, 0 },
303     {   "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
304 #endif                          /* 0 */
305     {   NULL, NULL, 0, NULL, 0, 0, 0, 0 }
306 };
307
308 static byte *gather_buffer;         /* buffer for gathering random noise */
309 static int gather_buffer_size;      /* size of the memory buffer */
310 static uid_t gatherer_uid;
311
312 /* The message structure used to communicate with the parent */
313 typedef struct {
314     int  usefulness;    /* usefulness of data */
315     int  ndata;         /* valid bytes in data */
316     char data[500];     /* gathered data */
317 } GATHER_MSG;
318
319 #ifndef HAVE_WAITPID
320 pid_t
321 waitpid(pid_t pid, int *statptr, int options)
322 {
323      #ifdef HAVE_WAIT4
324         return wait4(pid, statptr, options, NULL);
325      #else
326         /* If wait4 is also not available, try wait3 for SVR3 variants */
327         /* Less ideal because can't actually request a specific pid */
328         /* For that reason, first check to see if pid is for an */
329         /*   existing process. */
330         int tmp_pid, dummystat;;
331         if (kill(pid, 0) == -1) {
332                 errno = ECHILD;
333                 return -1;
334         }
335         if (statptr == NULL)
336                 statptr = &dummystat;
337         while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
338                     (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
339             ;
340         return tmp_pid;
341      #endif
342 }
343 #endif
344
345 /* Under SunOS popen() doesn't record the pid of the child process.  When
346  * pclose() is called, instead of calling waitpid() for the correct child, it
347  * calls wait() repeatedly until the right child is reaped.  The problem is
348  * that this reaps any other children that happen to have died at that
349  * moment, and when their pclose() comes along, the process hangs forever.
350  * The fix is to use a wrapper for popen()/pclose() which saves the pid in
351  * the dataSources structure (code adapted from GNU-libc's popen() call).
352  *
353  * Aut viam inveniam aut faciam */
354
355 static FILE *
356 my_popen(struct RI *entry)
357 {
358
359     int pipedes[2];
360     FILE *stream;
361
362     /* Create the pipe */
363     if (pipe(pipedes) < 0)
364         return (NULL);
365
366     /* Fork off the child ("vfork() is like an OS orgasm.  All OS's want to
367      * do it, but most just end up faking it" - Chris Wedgwood).  If your OS
368      * supports it, you should try to use vfork() here because it's somewhat
369      * more efficient */
370 #if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
371         defined(__hpux)
372     entry->pid = vfork();
373 #else                           /*  */
374     entry->pid = fork();
375 #endif                          /* Unixen which have vfork() */
376     if (entry->pid == (pid_t) - 1) {
377         /* The fork failed */
378         close(pipedes[0]);
379         close(pipedes[1]);
380         return (NULL);
381     }
382
383     if (entry->pid == (pid_t) 0) {
384         struct passwd *passwd;
385
386         /* We are the child.  Make the read side of the pipe be stdout */
387         if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
388             exit(127);
389
390         /* Now that everything is set up, give up our permissions to make
391          * sure we don't read anything sensitive.  If the getpwnam() fails,
392          * we default to -1, which is usually nobody */
393         if (gatherer_uid == (uid_t)-1 && \
394             (passwd = getpwnam("nobody")) != NULL)
395             gatherer_uid = passwd->pw_uid;
396
397         setuid(gatherer_uid);
398
399         /* Close the pipe descriptors */
400         close(pipedes[STDIN_FILENO]);
401         close(pipedes[STDOUT_FILENO]);
402
403         /* Try and exec the program */
404         execl(entry->path, entry->path, entry->arg, NULL);
405
406         /* Die if the exec failed */
407         exit(127);
408     }
409
410     /* We are the parent.  Close the irrelevant side of the pipe and open
411      * the relevant side as a new stream.  Mark our side of the pipe to
412      * close on exec, so new children won't see it */
413     close(pipedes[STDOUT_FILENO]);
414
415 #ifdef FD_CLOEXEC
416     fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
417 #endif
418
419     stream = fdopen(pipedes[STDIN_FILENO], "r");
420
421     if (stream == NULL) {
422         int savedErrno = errno;
423
424         /* The stream couldn't be opened or the child structure couldn't be
425          * allocated.  Kill the child and close the other side of the pipe */
426         kill(entry->pid, SIGKILL);
427         if (stream == NULL)
428             close(pipedes[STDOUT_FILENO]);
429         else
430             fclose(stream);
431
432         waitpid(entry->pid, NULL, 0);
433
434         entry->pid = 0;
435         errno = savedErrno;
436         return (NULL);
437     }
438
439     return (stream);
440 }
441
442 static int
443 my_pclose(struct RI *entry)
444 {
445     int status = 0;
446
447     if (fclose(entry->pipe))
448         return (-1);
449
450     /* We ignore the return value from the process because some programs
451      * return funny values which would result in the input being discarded
452      * even if they executed successfully.  This isn't a problem because the
453      * result data size threshold will filter out any programs which exit
454      * with a usage message without producing useful output */
455     if (waitpid(entry->pid, NULL, 0) != entry->pid)
456         status = -1;
457
458     entry->pipe = NULL;
459     entry->pid = 0;
460     return (status);
461 }
462
463
464 /* Unix slow poll (without special support for Linux)
465  *
466  * If a few of the randomness sources create a large amount of output then
467  * the slowPoll() stops once the buffer has been filled (but before all the
468  * randomness sources have been sucked dry) so that the 'usefulness' factor
469  * remains below the threshold.  For this reason the gatherer buffer has to
470  * be fairly sizeable on moderately loaded systems.  This is something of a
471  * bug since the usefulness should be influenced by the amount of output as
472  * well as the source type */
473
474
475 static int
476 slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
477 {
478     int moreSources;
479     struct timeval tv;
480     fd_set fds;
481   #if defined( __hpux )
482     size_t maxFD = 0;
483   #else
484     int maxFD = 0;
485   #endif /* OS-specific brokenness */
486     int bufPos, i, usefulness = 0;
487
488
489     /* Fire up each randomness source */
490     FD_ZERO(&fds);
491     for (i = 0; dataSources[i].path != NULL; i++) {
492         /* Since popen() is a fairly heavy function, we check to see whether
493          * the executable exists before we try to run it */
494         if (access(dataSources[i].path, X_OK)) {
495             if( dbgfp && dbgall )
496                 fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
497                                dataSources[i].hasAlternative ?
498                                         ", has alternatives" : "");
499             dataSources[i].pipe = NULL;
500         }
501         else
502             dataSources[i].pipe = my_popen(&dataSources[i]);
503
504         if (dataSources[i].pipe != NULL) {
505             dataSources[i].pipeFD = fileno(dataSources[i].pipe);
506             if (dataSources[i].pipeFD > maxFD)
507                 maxFD = dataSources[i].pipeFD;
508           #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
509             fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
510           #else
511             #warning O_NONBLOCK is missing
512           #endif
513             FD_SET(dataSources[i].pipeFD, &fds);
514             dataSources[i].length = 0;
515
516             /* If there are alternatives for this command, don't try and
517              * execute them */
518             while (dataSources[i].hasAlternative) {
519                 if( dbgfp && dbgall )
520                     fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
521                 i++;
522             }
523         }
524     }
525
526
527     /* Suck all the data we can get from each of the sources */
528     bufPos = 0;
529     moreSources = 1;
530     while (moreSources && bufPos <= gather_buffer_size) {
531         /* Wait for data to become available from any of the sources, with a
532          * timeout of 10 seconds.  This adds even more randomness since data
533          * becomes available in a nondeterministic fashion.  Kudos to HP's QA
534          * department for managing to ship a select() which breaks its own
535          * prototype */
536         tv.tv_sec = 10;
537         tv.tv_usec = 0;
538
539       #if defined( __hpux ) && ( OS_VERSION == 9 )
540         if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
541       #else  /*  */
542         if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
543       #endif /* __hpux */
544             break;
545
546         /* One of the sources has data available, read it into the buffer */
547         for (i = 0; dataSources[i].path != NULL; i++) {
548             if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
549                 size_t noBytes;
550
551                 if ((noBytes = fread(gather_buffer + bufPos, 1,
552                                      gather_buffer_size - bufPos,
553                                      dataSources[i].pipe)) == 0) {
554                     if (my_pclose(&dataSources[i]) == 0) {
555                         int total = 0;
556
557                         /* Try and estimate how much entropy we're getting
558                          * from a data source */
559                         if (dataSources[i].usefulness) {
560                             if (dataSources[i].usefulness < 0)
561                                 total = (dataSources[i].length + 999)
562                                         / -dataSources[i].usefulness;
563                             else
564                                 total = dataSources[i].length
565                                         / dataSources[i].usefulness;
566                         }
567                         if( dbgfp )
568                             fprintf(dbgfp,
569                                "%s %s contributed %d bytes, "
570                                "usefulness = %d\n", dataSources[i].path,
571                                (dataSources[i].arg != NULL) ?
572                                        dataSources[i].arg : "",
573                                       dataSources[i].length, total);
574                         if( dataSources[i].length )
575                             usefulness += total;
576                     }
577                     dataSources[i].pipe = NULL;
578                 }
579                 else {
580                     int currPos = bufPos;
581                     int endPos = bufPos + noBytes;
582
583                     /* Run-length compress the input byte sequence */
584                     while (currPos < endPos) {
585                         int ch = gather_buffer[currPos];
586
587                         /* If it's a single byte, just copy it over */
588                         if (ch != gather_buffer[currPos + 1]) {
589                             gather_buffer[bufPos++] = ch;
590                             currPos++;
591                         }
592                         else {
593                             int count = 0;
594
595                             /* It's a run of repeated bytes, replace them
596                              * with the byte count mod 256 */
597                             while ((ch == gather_buffer[currPos])
598                                     && currPos < endPos) {
599                                 count++;
600                                 currPos++;
601                             }
602                             gather_buffer[bufPos++] = count;
603                             noBytes -= count - 1;
604                         }
605                     }
606
607                     /* Remember the number of (compressed) bytes of input we
608                      * obtained */
609                     dataSources[i].length += noBytes;
610                 }
611             }
612         }
613
614         /* Check if there is more input available on any of the sources */
615         moreSources = 0;
616         FD_ZERO(&fds);
617         for (i = 0; dataSources[i].path != NULL; i++) {
618             if (dataSources[i].pipe != NULL) {
619                 FD_SET(dataSources[i].pipeFD, &fds);
620                 moreSources = 1;
621             }
622         }
623     }
624
625     if( dbgfp ) {
626         fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
627         fflush(dbgfp);
628     }
629     *nbytes = bufPos;
630     return usefulness;
631 }
632
633 /****************
634  * Start the gatherer process which writes messages of
635  * type GATHERER_MSG to pipedes
636  */
637 static void
638 start_gatherer( int pipefd )
639 {
640     FILE *dbgfp = NULL;
641     int dbgall;
642
643     {
644         const char *s = getenv("GNUPG_RNDUNIX_DBG");
645         if( s ) {
646             dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
647             if( !dbgfp )
648                 g10_log_info("can't open debug file `%s': %s\n",
649                              s, strerror(errno) );
650             else
651                 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
652         }
653         dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
654     }
655     /* close all files but the ones we need */
656     {   int nmax, n1, n2, i;
657       #ifdef _SC_OPEN_MAX
658         if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
659           #ifdef _POSIX_OPEN_MAX
660             nmax = _POSIX_OPEN_MAX;
661           #else
662             nmax = 20; /* assume a reasonable value */
663           #endif
664         }
665       #else
666         nmax = 20; /* assume a reasonable value */
667       #endif
668         n1 = fileno( stderr );
669         n2 = dbgfp? fileno( dbgfp ) : -1;
670         for(i=0; i < nmax; i++ ) {
671             if( i != n1 && i != n2 && i != pipefd )
672                 close(i);
673         }
674         errno = 0;
675     }
676
677
678
679     /* Set up the buffer */
680     gather_buffer_size = GATHER_BUFSIZE;
681     gather_buffer = malloc( gather_buffer_size );
682     if( !gather_buffer ) {
683         g10_log_error("out of core while allocating the gatherer buffer\n");
684         exit(2);
685     }
686
687     /* Reset the SIGC(H)LD handler to the system default.  This is necessary
688      * because if the program which cryptlib is a part of installs its own
689      * SIGC(H)LD handler, it will end up reaping the cryptlib children before
690      * cryptlib can.  As a result, my_pclose() will call waitpid() on a
691      * process which has already been reaped by the installed handler and
692      * return an error, so the read data won't be added to the randomness
693      * pool.  There are two types of SIGC(H)LD naming, the SysV SIGCLD and
694      * the BSD/Posix SIGCHLD, so we need to handle either possibility */
695   #ifdef SIGCLD
696     signal(SIGCLD, SIG_DFL);
697   #else
698     signal(SIGCHLD, SIG_DFL);
699   #endif
700
701     fclose(stderr);             /* Arrghh!!  It's Stuart code!! */
702
703     for(;;) {
704         GATHER_MSG msg;
705         size_t nbytes;
706         const char *p;
707
708         msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
709         p = gather_buffer;
710         while( nbytes ) {
711             msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
712             memcpy( msg.data, p, msg.ndata );
713             nbytes -= msg.ndata;
714             p += msg.ndata;
715
716             while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
717                 if( errno == EINTR )
718                     continue;
719                 if( errno == EAGAIN ) {
720                     struct timeval tv;
721                     tv.tv_sec = 0;
722                     tv.tv_usec = 50000;
723                     select(0, NULL, NULL, NULL, &tv);
724                     continue;
725                 }
726                 if( errno == EPIPE ) /* parent has exited, so give up */
727                    exit(0);
728
729                 /* we can't do very much here because stderr is closed */
730                 if( dbgfp )
731                     fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
732                                     strerror(errno) );
733                 /* we start a new poll to give the system some time */
734                 nbytes = 0;
735                 break;
736             }
737         }
738     }
739     /* we are killed when the parent dies */
740 }
741
742
743 static int
744 read_a_msg( int fd, GATHER_MSG *msg )
745 {
746     char *buffer = (char*)msg;
747     size_t length = sizeof( *msg );
748     int n;
749
750     do {
751         do {
752             n = read(fd, buffer, length );
753         } while( n == -1 && errno == EINTR );
754         if( n == -1 )
755             return -1;
756         buffer += n;
757         length -= n;
758     } while( length );
759     return 0;
760 }
761
762
763 /****************
764  * Using a level of 0 should never block and better add nothing
765  * to the pool.  So this is just a dummy for this gatherer.
766  */
767 static int
768 gather_random( void (*add)(const void*, size_t, int), int requester,
769                size_t length, int level )
770 {
771     static pid_t gatherer_pid = 0;
772     static int pipedes[2];
773     GATHER_MSG msg;
774     size_t n;
775
776     if( !level )
777         return 0;
778
779     if( !gatherer_pid ) {
780         /* make sure we are not setuid */
781         if( getuid() != geteuid() )
782             BUG();
783         /* time to start the gatherer process */
784         if( pipe( pipedes ) ) {
785             g10_log_error("pipe() failed: %s\n", strerror(errno));
786             return -1;
787         }
788         gatherer_pid = fork();
789         if( gatherer_pid == -1 ) {
790             g10_log_error("can't for gatherer process: %s\n", strerror(errno));
791             return -1;
792         }
793         if( !gatherer_pid ) {
794             start_gatherer( pipedes[1] );
795             /* oops, can't happen */
796             return -1;
797         }
798     }
799
800     /* now read from the gatherer */
801     while( length ) {
802         int goodness;
803         ulong subtract;
804
805         if( read_a_msg( pipedes[0], &msg ) ) {
806             g10_log_error("reading from gatherer pipe failed: %s\n",
807                                                             strerror(errno));
808             return -1;
809         }
810
811
812         if( level > 1 ) {
813             if( msg.usefulness > 30 )
814                 goodness = 100;
815             else if ( msg.usefulness )
816                 goodness = msg.usefulness * 100 / 30;
817             else
818                 goodness = 0;
819         }
820         else if( level ) {
821             if( msg.usefulness > 15 )
822                 goodness = 100;
823             else if ( msg.usefulness )
824                 goodness = msg.usefulness * 100 / 15;
825             else
826                 goodness = 0;
827         }
828         else
829             goodness = 100; /* goodness of level 0 is always 100 % */
830
831         n = msg.ndata;
832         if( n > length )
833             n = length;
834         (*add)( msg.data, n, requester );
835
836         /* this is the trick how e cope with the goodness */
837         subtract = (ulong)n * goodness / 100;
838         /* subtract at least 1 byte to avoid infinite loops */
839         length -= subtract ? subtract : 1;
840     }
841
842     return 0;
843 }
844
845
846
847 #ifndef IS_MODULE
848 static
849 #endif
850 const char * const gnupgext_version = "RNDUNIX ($Revision$)";
851
852
853 static struct {
854     int class;
855     int version;
856     void *func;
857 } func_table[] = {
858     { 40, 1, gather_random },
859 };
860
861 /****************
862  * Enumerate the names of the functions together with informations about
863  * this function. Set sequence to an integer with a initial value of 0 and
864  * do not change it.
865  * If what is 0 all kind of functions are returned.
866  * Return values: class := class of function:
867  *                         10 = message digest algorithm info function
868  *                         11 = integer with available md algorithms
869  *                         20 = cipher algorithm info function
870  *                         21 = integer with available cipher algorithms
871  *                         30 = public key algorithm info function
872  *                         31 = integer with available pubkey algorithms
873  *                         40 = get read_random_source() function
874  *                         41 = get fast_random_poll function
875  *                version = interface version of the function/pointer
876  *                          (currently this is 1 for all functions)
877  */
878
879 #ifndef IS_MODULE
880 static
881 #endif
882 void *
883 gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
884 {
885     void *ret;
886     int i = *sequence;
887
888     do {
889         if ( i >= DIM(func_table) || i < 0 ) {
890             return NULL;
891         }
892         *class = func_table[i].class;
893         *vers  = func_table[i].version;
894         ret = func_table[i].func;
895         i++;
896     } while ( what && what != *class );
897
898     *sequence = i;
899     return ret;
900 }
901
902 #ifndef IS_MODULE
903 void
904 rndunix_constructor(void)
905 {
906     register_internal_cipher_extension( gnupgext_version,
907                                         gnupgext_enum_func );
908 }
909 #endif
910
911