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