1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#define APR_WANT_MEMFUNC 18251875Speter#include "apr_want.h" 19251875Speter#include "apr_general.h" 20251875Speter 21251875Speter#include "apr_arch_misc.h" 22251875Speter#include <sys/stat.h> 23251875Speter#if APR_HAVE_SYS_TYPES_H 24251875Speter#include <sys/types.h> 25251875Speter#endif 26251875Speter#if APR_HAVE_SYS_SOCKET_H 27251875Speter#include <sys/socket.h> 28251875Speter#endif 29251875Speter#if APR_HAVE_FCNTL_H 30251875Speter#include <fcntl.h> 31251875Speter#endif 32251875Speter#if APR_HAVE_UNISTD_H 33251875Speter#include <unistd.h> 34251875Speter#endif 35251875Speter#if APR_HAVE_SYS_UN_H 36251875Speter#include <sys/un.h> 37251875Speter#endif 38251875Speter#if defined(HAVE_UUID_H) 39251875Speter#include <uuid.h> 40251875Speter#elif defined(HAVE_UUID_UUID_H) 41251875Speter#include <uuid/uuid.h> 42251875Speter#elif defined(HAVE_SYS_UUID_H) 43251875Speter#include <sys/uuid.h> 44251875Speter#endif 45251875Speter 46251875Speter#ifndef SHUT_RDWR 47251875Speter#define SHUT_RDWR 2 48251875Speter#endif 49251875Speter 50251875Speter#if APR_HAS_OS_UUID 51251875Speter 52251875Speter#if defined(HAVE_UUID_CREATE) 53251875Speter 54251875SpeterAPR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data) 55251875Speter{ 56251875Speter uint32_t rv; 57251875Speter uuid_t g; 58251875Speter 59251875Speter uuid_create(&g, &rv); 60251875Speter 61251875Speter if (rv != uuid_s_ok) 62251875Speter return APR_EGENERAL; 63251875Speter 64251875Speter memcpy(uuid_data, &g, sizeof(uuid_t)); 65251875Speter 66251875Speter return APR_SUCCESS; 67251875Speter} 68251875Speter 69251875Speter#elif defined(HAVE_UUID_GENERATE) 70251875Speter 71251875SpeterAPR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data) 72251875Speter{ 73251875Speter uuid_t g; 74251875Speter 75251875Speter uuid_generate(g); 76251875Speter 77251875Speter memcpy(uuid_data, g, sizeof(uuid_t)); 78251875Speter 79251875Speter return APR_SUCCESS; 80251875Speter} 81251875Speter#endif 82251875Speter 83251875Speter#endif /* APR_HAS_OS_UUID */ 84251875Speter 85251875Speter#if APR_HAS_RANDOM 86251875Speter 87251875SpeterAPR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, 88251875Speter apr_size_t length) 89251875Speter{ 90251875Speter#ifdef DEV_RANDOM 91251875Speter 92251875Speter int fd = -1; 93251875Speter 94251875Speter /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then 95251875Speter * gives EOF, so reading 'length' bytes may require opening the 96251875Speter * device several times. */ 97251875Speter do { 98251875Speter apr_ssize_t rc; 99251875Speter 100251875Speter if (fd == -1) 101251875Speter if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1) 102251875Speter return errno; 103251875Speter 104251875Speter do { 105251875Speter rc = read(fd, buf, length); 106251875Speter } while (rc == -1 && errno == EINTR); 107251875Speter 108251875Speter if (rc < 0) { 109251875Speter int errnum = errno; 110251875Speter close(fd); 111251875Speter return errnum; 112251875Speter } 113251875Speter else if (rc == 0) { 114251875Speter close(fd); 115251875Speter fd = -1; /* force open() again */ 116251875Speter } 117251875Speter else { 118251875Speter buf += rc; 119251875Speter length -= rc; 120251875Speter } 121251875Speter } while (length > 0); 122251875Speter 123251875Speter close(fd); 124251875Speter#elif defined(OS2) 125251875Speter static UCHAR randbyte(); 126251875Speter unsigned int idx; 127251875Speter 128251875Speter for (idx=0; idx<length; idx++) 129251875Speter buf[idx] = randbyte(); 130251875Speter 131251875Speter#elif defined(HAVE_EGD) 132251875Speter /* use EGD-compatible socket daemon (such as EGD or PRNGd). 133251875Speter * message format: 134251875Speter * 0x00 (get entropy level) 135251875Speter * 0xMM (msb) 0xmm 0xll 0xLL (lsb) 136251875Speter * 0x01 (read entropy nonblocking) 0xNN (bytes requested) 137251875Speter * 0xMM (bytes granted) MM bytes 138251875Speter * 0x02 (read entropy blocking) 0xNN (bytes desired) 139251875Speter * [block] NN bytes 140251875Speter * 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data) 141251875Speter * NN bytes 142251875Speter * (no response - write only) 143251875Speter * 0x04 (report PID) 144251875Speter * 0xMM (length of PID string, not null-terminated) MM chars 145251875Speter */ 146251875Speter static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL }; 147251875Speter const char **egdsockname = NULL; 148251875Speter 149251875Speter int egd_socket, egd_path_len, rv, bad_errno; 150251875Speter struct sockaddr_un addr; 151251875Speter apr_socklen_t egd_addr_len; 152251875Speter apr_size_t resp_expected; 153251875Speter unsigned char req[2], resp[255]; 154251875Speter unsigned char *curbuf = buf; 155251875Speter 156251875Speter for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) { 157251875Speter egd_path_len = strlen(*egdsockname); 158251875Speter 159251875Speter if (egd_path_len > sizeof(addr.sun_path)) { 160251875Speter return APR_EINVAL; 161251875Speter } 162251875Speter 163251875Speter memset(&addr, 0, sizeof(struct sockaddr_un)); 164251875Speter addr.sun_family = AF_UNIX; 165251875Speter memcpy(addr.sun_path, *egdsockname, egd_path_len); 166251875Speter egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + 167251875Speter egd_path_len; 168251875Speter 169251875Speter egd_socket = socket(PF_UNIX, SOCK_STREAM, 0); 170251875Speter 171251875Speter if (egd_socket == -1) { 172251875Speter return errno; 173251875Speter } 174251875Speter 175251875Speter rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len); 176251875Speter 177251875Speter if (rv == -1) { 178251875Speter bad_errno = errno; 179251875Speter continue; 180251875Speter } 181251875Speter 182251875Speter /* EGD can only return 255 bytes of data at a time. Silly. */ 183251875Speter while (length > 0) { 184251875Speter apr_ssize_t srv; 185251875Speter req[0] = 2; /* We'll block for now. */ 186251875Speter req[1] = length > 255 ? 255: length; 187251875Speter 188251875Speter srv = write(egd_socket, req, 2); 189251875Speter if (srv == -1) { 190251875Speter bad_errno = errno; 191251875Speter shutdown(egd_socket, SHUT_RDWR); 192251875Speter close(egd_socket); 193251875Speter break; 194251875Speter } 195251875Speter 196251875Speter if (srv != 2) { 197251875Speter shutdown(egd_socket, SHUT_RDWR); 198251875Speter close(egd_socket); 199251875Speter return APR_EGENERAL; 200251875Speter } 201251875Speter 202251875Speter resp_expected = req[1]; 203251875Speter srv = read(egd_socket, resp, resp_expected); 204251875Speter if (srv == -1) { 205251875Speter bad_errno = errno; 206251875Speter shutdown(egd_socket, SHUT_RDWR); 207251875Speter close(egd_socket); 208251875Speter return bad_errno; 209251875Speter } 210251875Speter 211251875Speter memcpy(curbuf, resp, srv); 212251875Speter curbuf += srv; 213251875Speter length -= srv; 214251875Speter } 215251875Speter 216251875Speter shutdown(egd_socket, SHUT_RDWR); 217251875Speter close(egd_socket); 218251875Speter } 219251875Speter 220251875Speter if (length > 0) { 221251875Speter /* We must have iterated through the list of sockets, 222251875Speter * and no go. Return the errno. 223251875Speter */ 224251875Speter return bad_errno; 225251875Speter } 226251875Speter 227251875Speter#elif defined(HAVE_TRUERAND) /* use truerand */ 228251875Speter 229251875Speter extern int randbyte(void); /* from the truerand library */ 230251875Speter unsigned int idx; 231251875Speter 232251875Speter /* this will increase the startup time of the server, unfortunately... 233251875Speter * (generating 20 bytes takes about 8 seconds) 234251875Speter */ 235251875Speter for (idx=0; idx<length; idx++) 236251875Speter buf[idx] = (unsigned char) randbyte(); 237251875Speter 238251875Speter#endif /* DEV_RANDOM */ 239251875Speter 240251875Speter return APR_SUCCESS; 241251875Speter} 242251875Speter 243251875Speter#undef STR 244251875Speter#undef XSTR 245251875Speter 246251875Speter#ifdef OS2 247251875Speter#include "randbyte_os2.inc" 248251875Speter#endif 249251875Speter 250251875Speter#endif /* APR_HAS_RANDOM */ 251