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