The big extension module removal.
[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 "dynload.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
395         /* We are the child.  Make the read side of the pipe be stdout */
396         if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
397             exit(127);
398
399         /* Now that everything is set up, give up our permissions to make
400          * sure we don't read anything sensitive.  If the getpwnam() fails,
401          * we default to -1, which is usually nobody */
402         if (gatherer_uid == (uid_t)-1 && \
403             (passwd = getpwnam("nobody")) != NULL)
404             gatherer_uid = passwd->pw_uid;
405
406         setuid(gatherer_uid);
407
408         /* Close the pipe descriptors */
409         close(pipedes[STDIN_FILENO]);
410         close(pipedes[STDOUT_FILENO]);
411
412         /* Try and exec the program */
413         execl(entry->path, entry->path, entry->arg, NULL);
414
415         /* Die if the exec failed */
416         exit(127);
417     }
418
419     /* We are the parent.  Close the irrelevant side of the pipe and open
420      * the relevant side as a new stream.  Mark our side of the pipe to
421      * close on exec, so new children won't see it */
422     close(pipedes[STDOUT_FILENO]);
423
424 #ifdef FD_CLOEXEC
425     fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
426 #endif
427
428     stream = fdopen(pipedes[STDIN_FILENO], "r");
429
430     if (stream == NULL) {
431         int savedErrno = errno;
432
433         /* The stream couldn't be opened or the child structure couldn't be
434          * allocated.  Kill the child and close the other side of the pipe */
435         kill(entry->pid, SIGKILL);
436         if (stream == NULL)
437             close(pipedes[STDOUT_FILENO]);
438         else
439             fclose(stream);
440
441         waitpid(entry->pid, NULL, 0);
442
443         entry->pid = 0;
444         errno = savedErrno;
445         return (NULL);
446     }
447
448     return (stream);
449 }
450
451 static int
452 my_pclose(struct RI *entry)
453 {
454     int status = 0;
455
456     if (fclose(entry->pipe))
457         return (-1);
458
459     /* We ignore the return value from the process because some programs
460      * return funny values which would result in the input being discarded
461      * even if they executed successfully.  This isn't a problem because the
462      * result data size threshold will filter out any programs which exit
463      * with a usage message without producing useful output */
464     if (waitpid(entry->pid, NULL, 0) != entry->pid)
465         status = -1;
466
467     entry->pipe = NULL;
468     entry->pid = 0;
469     return (status);
470 }
471
472
473 /* Unix slow poll (without special support for Linux)
474  *
475  * If a few of the randomness sources create a large amount of output then
476  * the slowPoll() stops once the buffer has been filled (but before all the
477  * randomness sources have been sucked dry) so that the 'usefulness' factor
478  * remains below the threshold.  For this reason the gatherer buffer has to
479  * be fairly sizeable on moderately loaded systems.  This is something of a
480  * bug since the usefulness should be influenced by the amount of output as
481  * well as the source type */
482
483
484 static int
485 slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
486 {
487     int moreSources;
488     struct timeval tv;
489     fd_set fds;
490   #if defined( __hpux )
491     size_t maxFD = 0;
492   #else
493     int maxFD = 0;
494   #endif /* OS-specific brokenness */
495     int bufPos, i, usefulness = 0;
496
497
498     /* Fire up each randomness source */
499     FD_ZERO(&fds);
500     for (i = 0; dataSources[i].path != NULL; i++) {
501         /* Since popen() is a fairly heavy function, we check to see whether
502          * the executable exists before we try to run it */
503         if (access(dataSources[i].path, X_OK)) {
504             if( dbgfp && dbgall )
505                 fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
506                                dataSources[i].hasAlternative ?
507                                         ", has alternatives" : "");
508             dataSources[i].pipe = NULL;
509         }
510         else
511             dataSources[i].pipe = my_popen(&dataSources[i]);
512
513         if (dataSources[i].pipe != NULL) {
514             dataSources[i].pipeFD = fileno(dataSources[i].pipe);
515             if (dataSources[i].pipeFD > maxFD)
516                 maxFD = dataSources[i].pipeFD;
517           #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
518             fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
519           #endif
520             FD_SET(dataSources[i].pipeFD, &fds);
521             dataSources[i].length = 0;
522
523             /* If there are alternatives for this command, don't try and
524              * execute them */
525             while (dataSources[i].hasAlternative) {
526                 if( dbgfp && dbgall )
527                     fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
528                 i++;
529             }
530         }
531     }
532
533
534     /* Suck all the data we can get from each of the sources */
535     bufPos = 0;
536     moreSources = 1;
537     while (moreSources && bufPos <= gather_buffer_size) {
538         /* Wait for data to become available from any of the sources, with a
539          * timeout of 10 seconds.  This adds even more randomness since data
540          * becomes available in a nondeterministic fashion.  Kudos to HP's QA
541          * department for managing to ship a select() which breaks its own
542          * prototype */
543         tv.tv_sec = 10;
544         tv.tv_usec = 0;
545
546       #if defined( __hpux ) && ( OS_VERSION == 9 )
547         if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
548       #else  /*  */
549         if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
550       #endif /* __hpux */
551             break;
552
553         /* One of the sources has data available, read it into the buffer */
554         for (i = 0; dataSources[i].path != NULL; i++) {
555             if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
556                 size_t noBytes;
557
558                 if ((noBytes = fread(gather_buffer + bufPos, 1,
559                                      gather_buffer_size - bufPos,
560                                      dataSources[i].pipe)) == 0) {
561                     if (my_pclose(&dataSources[i]) == 0) {
562                         int total = 0;
563
564                         /* Try and estimate how much entropy we're getting
565                          * from a data source */
566                         if (dataSources[i].usefulness) {
567                             if (dataSources[i].usefulness < 0)
568                                 total = (dataSources[i].length + 999)
569                                         / -dataSources[i].usefulness;
570                             else
571                                 total = dataSources[i].length
572                                         / dataSources[i].usefulness;
573                         }
574                         if( dbgfp )
575                             fprintf(dbgfp,
576                                "%s %s contributed %d bytes, "
577                                "usefulness = %d\n", dataSources[i].path,
578                                (dataSources[i].arg != NULL) ?
579                                        dataSources[i].arg : "",
580                                       dataSources[i].length, total);
581                         if( dataSources[i].length )
582                             usefulness += total;
583                     }
584                     dataSources[i].pipe = NULL;
585                 }
586                 else {
587                     int currPos = bufPos;
588                     int endPos = bufPos + noBytes;
589
590                     /* Run-length compress the input byte sequence */
591                     while (currPos < endPos) {
592                         int ch = gather_buffer[currPos];
593
594                         /* If it's a single byte, just copy it over */
595                         if (ch != gather_buffer[currPos + 1]) {
596                             gather_buffer[bufPos++] = ch;
597                             currPos++;
598                         }
599                         else {
600                             int count = 0;
601
602                             /* It's a run of repeated bytes, replace them
603                              * with the byte count mod 256 */
604                             while ((ch == gather_buffer[currPos])
605                                     && currPos < endPos) {
606                                 count++;
607                                 currPos++;
608                             }
609                             gather_buffer[bufPos++] = count;
610                             noBytes -= count - 1;
611                         }
612                     }
613
614                     /* Remember the number of (compressed) bytes of input we
615                      * obtained */
616                     dataSources[i].length += noBytes;
617                 }
618             }
619         }
620
621         /* Check if there is more input available on any of the sources */
622         moreSources = 0;
623         FD_ZERO(&fds);
624         for (i = 0; dataSources[i].path != NULL; i++) {
625             if (dataSources[i].pipe != NULL) {
626                 FD_SET(dataSources[i].pipeFD, &fds);
627                 moreSources = 1;
628             }
629         }
630     }
631
632     if( dbgfp ) {
633         fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
634         fflush(dbgfp);
635     }
636     *nbytes = bufPos;
637     return usefulness;
638 }
639
640 /****************
641  * Start the gatherer process which writes messages of
642  * type GATHERER_MSG to pipedes
643  */
644 static void
645 start_gatherer( int pipefd )
646 {
647     FILE *dbgfp = NULL;
648     int dbgall;
649
650     {
651         const char *s = getenv("GNUPG_RNDUNIX_DBG");
652         if( s ) {
653             dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
654             if( !dbgfp )
655                 g10_log_info("can't open debug file `%s': %s\n",
656                              s, strerror(errno) );
657             else
658                 fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
659         }
660         dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
661     }
662     /* close all files but the ones we need */
663     {   int nmax, n1, n2, i;
664       #ifdef _SC_OPEN_MAX
665         if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
666           #ifdef _POSIX_OPEN_MAX
667             nmax = _POSIX_OPEN_MAX;
668           #else
669             nmax = 20; /* assume a reasonable value */
670           #endif
671         }
672       #else
673         nmax = 20; /* assume a reasonable value */
674       #endif
675         n1 = fileno( stderr );
676         n2 = dbgfp? fileno( dbgfp ) : -1;
677         for(i=0; i < nmax; i++ ) {
678             if( i != n1 && i != n2 && i != pipefd )
679                 close(i);
680         }
681         errno = 0;
682     }
683
684
685
686     /* Set up the buffer */
687     gather_buffer_size = GATHER_BUFSIZE;
688     gather_buffer = malloc( gather_buffer_size );
689     if( !gather_buffer ) {
690         g10_log_error("out of core while allocating the gatherer buffer\n");
691         exit(2);
692     }
693
694     /* Reset the SIGC(H)LD handler to the system default.  This is necessary
695      * because if the program which cryptlib is a part of installs its own
696      * SIGC(H)LD handler, it will end up reaping the cryptlib children before
697      * cryptlib can.  As a result, my_pclose() will call waitpid() on a
698      * process which has already been reaped by the installed handler and
699      * return an error, so the read data won't be added to the randomness
700      * pool.  There are two types of SIGC(H)LD naming, the SysV SIGCLD and
701      * the BSD/Posix SIGCHLD, so we need to handle either possibility */
702   #ifdef SIGCLD
703     signal(SIGCLD, SIG_DFL);
704   #else
705     signal(SIGCHLD, SIG_DFL);
706   #endif
707
708     fclose(stderr);             /* Arrghh!!  It's Stuart code!! */
709
710     for(;;) {
711         GATHER_MSG msg;
712         size_t nbytes;
713         const char *p;
714
715         msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
716         p = gather_buffer;
717         while( nbytes ) {
718             msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
719             memcpy( msg.data, p, msg.ndata );
720             nbytes -= msg.ndata;
721             p += msg.ndata;
722
723             while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
724                 if( errno == EINTR )
725                     continue;
726                 if( errno == EAGAIN ) {
727                     struct timeval tv;
728                     tv.tv_sec = 0;
729                     tv.tv_usec = 50000;
730                     select(0, NULL, NULL, NULL, &tv);
731                     continue;
732                 }
733                 if( errno == EPIPE ) /* parent has exited, so give up */
734                    exit(0);
735
736                 /* we can't do very much here because stderr is closed */
737                 if( dbgfp )
738                     fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
739                                     strerror(errno) );
740                 /* we start a new poll to give the system some time */
741                 nbytes = 0;
742                 break;
743             }
744         }
745     }
746     /* we are killed when the parent dies */
747 }
748
749
750 static int
751 read_a_msg( int fd, GATHER_MSG *msg )
752 {
753     char *buffer = (char*)msg;
754     size_t length = sizeof( *msg );
755     int n;
756
757     do {
758         do {
759             n = read(fd, buffer, length );
760         } while( n == -1 && errno == EINTR );
761         if( n == -1 )
762             return -1;
763         buffer += n;
764         length -= n;
765     } while( length );
766     return 0;
767 }
768
769
770 /****************
771  * Using a level of 0 should never block and better add nothing
772  * to the pool.  So this is just a dummy for this gatherer.
773  */
774 int
775 rndunix_gather_random( void (*add)(const void*, size_t, int), int requester,
776                        size_t length, int level )
777 {
778     static pid_t gatherer_pid = 0;
779     static int pipedes[2];
780     GATHER_MSG msg;
781     size_t n;
782
783     if( !level )
784         return 0;
785
786     if( !gatherer_pid ) {
787         /* make sure we are not setuid */
788         if( getuid() != geteuid() )
789             BUG();
790         /* time to start the gatherer process */
791         if( pipe( pipedes ) ) {
792             g10_log_error("pipe() failed: %s\n", strerror(errno));
793             return -1;
794         }
795         gatherer_pid = fork();
796         if( gatherer_pid == -1 ) {
797             g10_log_error("can't for gatherer process: %s\n", strerror(errno));
798             return -1;
799         }
800         if( !gatherer_pid ) {
801             start_gatherer( pipedes[1] );
802             /* oops, can't happen */
803             return -1;
804         }
805     }
806
807     /* now read from the gatherer */
808     while( length ) {
809         int goodness;
810         ulong subtract;
811
812         if( read_a_msg( pipedes[0], &msg ) ) {
813             g10_log_error("reading from gatherer pipe failed: %s\n",
814                                                             strerror(errno));
815             return -1;
816         }
817
818
819         if( level > 1 ) {
820             if( msg.usefulness > 30 )
821                 goodness = 100;
822             else if ( msg.usefulness )
823                 goodness = msg.usefulness * 100 / 30;
824             else
825                 goodness = 0;
826         }
827         else if( level ) {
828             if( msg.usefulness > 15 )
829                 goodness = 100;
830             else if ( msg.usefulness )
831                 goodness = msg.usefulness * 100 / 15;
832             else
833                 goodness = 0;
834         }
835         else
836             goodness = 100; /* goodness of level 0 is always 100 % */
837
838         n = msg.ndata;
839         if( n > length )
840             n = length;
841         (*add)( msg.data, n, requester );
842
843         /* this is the trick how e cope with the goodness */
844         subtract = (ulong)n * goodness / 100;
845         /* subtract at least 1 byte to avoid infinite loops */
846         length -= subtract ? subtract : 1;
847     }
848
849     return 0;
850 }
851
852 #endif /*USE_RNDUNIX*/