/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define APR_WANT_MEMFUNC #include "apr_want.h" #include "apr_general.h" #include "apr_arch_misc.h" #include #if APR_HAVE_SYS_TYPES_H #include #endif #if APR_HAVE_SYS_SOCKET_H #include #endif #if APR_HAVE_FCNTL_H #include #endif #if APR_HAVE_UNISTD_H #include #endif #if APR_HAVE_SYS_UN_H #include #endif #ifndef SHUT_RDWR #define SHUT_RDWR 2 #endif #if APR_HAS_RANDOM APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, #ifdef APR_ENABLE_FOR_1_0 apr_size_t length) #else int length) #endif { #ifdef DEV_RANDOM int fd = -1; /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then * gives EOF, so reading 'length' bytes may require opening the * device several times. */ do { apr_ssize_t rc; if (fd == -1) if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1) return errno; rc = read(fd, buf, length); if (rc < 0) { int errnum = errno; close(fd); return errnum; } else if (rc == 0) { close(fd); fd = -1; /* force open() again */ } else { buf += rc; length -= rc; } } while (length > 0); close(fd); #elif defined(OS2) static UCHAR randbyte(); unsigned int idx; for (idx=0; idx 0; egdsockname++) { egd_path_len = strlen(*egdsockname); if (egd_path_len > sizeof(addr.sun_path)) { return APR_EINVAL; } memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; memcpy(addr.sun_path, *egdsockname, egd_path_len); egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + egd_path_len; egd_socket = socket(PF_UNIX, SOCK_STREAM, 0); if (egd_socket == -1) { return errno; } rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len); if (rv == -1) { bad_errno = errno; continue; } /* EGD can only return 255 bytes of data at a time. Silly. */ while (length > 0) { apr_ssize_t srv; req[0] = 2; /* We'll block for now. */ req[1] = length > 255 ? 255: length; srv = write(egd_socket, req, 2); if (srv == -1) { bad_errno = errno; shutdown(egd_socket, SHUT_RDWR); close(egd_socket); break; } if (srv != 2) { shutdown(egd_socket, SHUT_RDWR); close(egd_socket); return APR_EGENERAL; } resp_expected = req[1]; srv = read(egd_socket, resp, resp_expected); if (srv == -1) { bad_errno = errno; shutdown(egd_socket, SHUT_RDWR); close(egd_socket); return bad_errno; } memcpy(curbuf, resp, srv); curbuf += srv; length -= srv; } shutdown(egd_socket, SHUT_RDWR); close(egd_socket); } if (length > 0) { /* We must have iterated through the list of sockets, * and no go. Return the errno. */ return bad_errno; } #elif defined(HAVE_TRUERAND) /* use truerand */ extern int randbyte(void); /* from the truerand library */ unsigned int idx; /* this will increase the startup time of the server, unfortunately... * (generating 20 bytes takes about 8 seconds) */ for (idx=0; idx