"Fossies" - the Fresh Open Source Software Archive 
Member "apr-1.7.0/misc/unix/rand.c" (21 Jun 2018, 7572 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "rand.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.6.5_vs_1.7.0.
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define APR_WANT_MEMFUNC
18 #include "apr_want.h"
19 #include "apr_general.h"
20
21 #include "apr_arch_misc.h"
22 #include <sys/stat.h>
23 #if APR_HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #if APR_HAVE_SYS_SOCKET_H
27 #include <sys/socket.h>
28 #endif
29 #if APR_HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32 #if APR_HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #if APR_HAVE_SYS_UN_H
36 #include <sys/un.h>
37 #endif
38 #if defined(HAVE_UUID_H)
39 #include <uuid.h>
40 #elif defined(HAVE_UUID_UUID_H)
41 #include <uuid/uuid.h>
42 #elif defined(HAVE_SYS_UUID_H)
43 #include <sys/uuid.h>
44 #endif
45
46 #if defined(SYS_RANDOM)
47 #if defined(HAVE_SYS_RANDOM_H) && \
48 defined(HAVE_GETRANDOM)
49
50 #include <sys/random.h>
51 #define USE_GETRANDOM
52
53 #elif defined(HAVE_SYS_SYSCALL_H) && \
54 defined(HAVE_LINUX_RANDOM_H) && \
55 defined(HAVE_DECL_SYS_GETRANDOM) && \
56 HAVE_DECL_SYS_GETRANDOM
57
58 #ifndef _GNU_SOURCE
59 #define _GNU_SOURCE
60 #endif
61 #include <unistd.h>
62 #include <sys/syscall.h>
63 #include <linux/random.h>
64 #define getrandom(buf, buflen, flags) \
65 syscall(SYS_getrandom, (buf), (buflen), (flags))
66 #define USE_GETRANDOM
67
68 #endif /* HAVE_SYS_RANDOM_H */
69 #endif /* SYS_RANDOM */
70
71 #ifndef SHUT_RDWR
72 #define SHUT_RDWR 2
73 #endif
74
75 #if APR_HAS_OS_UUID
76
77 #if defined(HAVE_UUID_CREATE)
78
79 APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
80 {
81 uint32_t rv;
82 uuid_t g;
83
84 uuid_create(&g, &rv);
85
86 if (rv != uuid_s_ok)
87 return APR_EGENERAL;
88
89 memcpy(uuid_data, &g, sizeof(uuid_t));
90
91 return APR_SUCCESS;
92 }
93
94 #elif defined(HAVE_UUID_GENERATE)
95
96 APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
97 {
98 uuid_t g;
99
100 uuid_generate(g);
101
102 memcpy(uuid_data, g, sizeof(uuid_t));
103
104 return APR_SUCCESS;
105 }
106 #endif
107
108 #endif /* APR_HAS_OS_UUID */
109
110 #if APR_HAS_RANDOM
111
112 APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
113 apr_size_t length)
114 {
115 #if defined(HAVE_EGD)
116 /* use EGD-compatible socket daemon (such as EGD or PRNGd).
117 * message format:
118 * 0x00 (get entropy level)
119 * 0xMM (msb) 0xmm 0xll 0xLL (lsb)
120 * 0x01 (read entropy nonblocking) 0xNN (bytes requested)
121 * 0xMM (bytes granted) MM bytes
122 * 0x02 (read entropy blocking) 0xNN (bytes desired)
123 * [block] NN bytes
124 * 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data)
125 * NN bytes
126 * (no response - write only)
127 * 0x04 (report PID)
128 * 0xMM (length of PID string, not null-terminated) MM chars
129 */
130 static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL };
131 const char **egdsockname = NULL;
132
133 int egd_socket, egd_path_len, rv, bad_errno;
134 struct sockaddr_un addr;
135 apr_socklen_t egd_addr_len;
136 apr_size_t resp_expected;
137 unsigned char req[2], resp[255];
138 unsigned char *curbuf = buf;
139
140 for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) {
141 egd_path_len = strlen(*egdsockname);
142
143 if (egd_path_len > sizeof(addr.sun_path)) {
144 return APR_EINVAL;
145 }
146
147 memset(&addr, 0, sizeof(struct sockaddr_un));
148 addr.sun_family = AF_UNIX;
149 memcpy(addr.sun_path, *egdsockname, egd_path_len);
150 egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) +
151 egd_path_len;
152
153 egd_socket = socket(PF_UNIX, SOCK_STREAM, 0);
154
155 if (egd_socket == -1) {
156 return errno;
157 }
158
159 rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len);
160
161 if (rv == -1) {
162 bad_errno = errno;
163 continue;
164 }
165
166 /* EGD can only return 255 bytes of data at a time. Silly. */
167 while (length > 0) {
168 apr_ssize_t srv;
169 req[0] = 2; /* We'll block for now. */
170 req[1] = length > 255 ? 255: length;
171
172 srv = write(egd_socket, req, 2);
173 if (srv == -1) {
174 bad_errno = errno;
175 shutdown(egd_socket, SHUT_RDWR);
176 close(egd_socket);
177 break;
178 }
179
180 if (srv != 2) {
181 shutdown(egd_socket, SHUT_RDWR);
182 close(egd_socket);
183 return APR_EGENERAL;
184 }
185
186 resp_expected = req[1];
187 srv = read(egd_socket, resp, resp_expected);
188 if (srv == -1) {
189 bad_errno = errno;
190 shutdown(egd_socket, SHUT_RDWR);
191 close(egd_socket);
192 return bad_errno;
193 }
194
195 memcpy(curbuf, resp, srv);
196 curbuf += srv;
197 length -= srv;
198 }
199
200 shutdown(egd_socket, SHUT_RDWR);
201 close(egd_socket);
202 }
203
204 if (length > 0) {
205 /* We must have iterated through the list of sockets,
206 * and no go. Return the errno.
207 */
208 return bad_errno;
209 }
210
211 #elif defined(SYS_RANDOM) && defined(USE_GETRANDOM)
212
213 do {
214 int rc;
215
216 rc = getrandom(buf, length, 0);
217 if (rc == -1) {
218 if (errno == EINTR) {
219 continue;
220 }
221 return errno;
222 }
223
224 buf += rc;
225 length -= rc;
226 } while (length > 0);
227
228 #elif defined(SYS_RANDOM) && defined(HAVE_ARC4RANDOM_BUF)
229
230 arc4random_buf(buf, length);
231
232 #elif defined(DEV_RANDOM)
233
234 int fd = -1;
235
236 /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
237 * gives EOF, so reading 'length' bytes may require opening the
238 * device several times. */
239 do {
240 apr_ssize_t rc;
241
242 if (fd == -1)
243 if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
244 return errno;
245
246 do {
247 rc = read(fd, buf, length);
248 } while (rc == -1 && errno == EINTR);
249
250 if (rc < 0) {
251 int errnum = errno;
252 close(fd);
253 return errnum;
254 }
255 else if (rc == 0) {
256 close(fd);
257 fd = -1; /* force open() again */
258 }
259 else {
260 buf += rc;
261 length -= rc;
262 }
263 } while (length > 0);
264
265 close(fd);
266
267 #elif defined(OS2)
268
269 static UCHAR randbyte();
270 unsigned int idx;
271
272 for (idx=0; idx<length; idx++)
273 buf[idx] = randbyte();
274
275 #elif defined(HAVE_TRUERAND) /* use truerand */
276
277 extern int randbyte(void); /* from the truerand library */
278 unsigned int idx;
279
280 /* this will increase the startup time of the server, unfortunately...
281 * (generating 20 bytes takes about 8 seconds)
282 */
283 for (idx=0; idx<length; idx++)
284 buf[idx] = (unsigned char) randbyte();
285
286 #else
287
288 #error APR_HAS_RANDOM defined with no implementation
289
290 #endif /* DEV_RANDOM */
291
292 return APR_SUCCESS;
293 }
294
295 #undef STR
296 #undef XSTR
297
298 #ifdef OS2
299 #include "randbyte_os2.inc"
300 #endif
301
302 #endif /* APR_HAS_RANDOM */