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