Apache HTTPD
rand.c
Go to the documentation of this file.
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
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
97{
98 uuid_t g;
99
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
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
134 struct sockaddr_un addr;
137 unsigned char req[2], resp[255];
138 unsigned char *curbuf = buf;
139
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);
152
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) {
163 continue;
164 }
165
166 /* EGD can only return 255 bytes of data at a time. Silly. */
167 while (length > 0) {
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) {
176 close(egd_socket);
177 break;
178 }
179
180 if (srv != 2) {
182 close(egd_socket);
183 return APR_EGENERAL;
184 }
185
186 resp_expected = req[1];
188 if (srv == -1) {
191 close(egd_socket);
192 return bad_errno;
193 }
194
196 curbuf += srv;
197 length -= srv;
198 }
199
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
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 {
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 */
#define socket
#define shutdown
#define connect
APR Miscellaneous library routines.
APR Standard Headers Support.
const unsigned char * buf
Definition util_md5.h:50
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_EINVAL
Definition apr_errno.h:711
apr_file_t * fd
int apr_off_t * length
apr_dbd_t int errnum
Definition apr_dbd.h:353
apr_redis_t * rc
Definition apr_redis.h:173
#define UCHAR
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_sockaddr_t * addr
apr_sockaddr_t * sockaddr
return NULL
Definition mod_so.c:359
#define SHUT_RDWR
Definition rand.c:72