rand.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. #define APR_WANT_MEMFUNC
  17. #include "apr_want.h"
  18. #include "apr_general.h"
  19. #include "apr_arch_misc.h"
  20. #include <sys/stat.h>
  21. #if APR_HAVE_SYS_TYPES_H
  22. #include <sys/types.h>
  23. #endif
  24. #if APR_HAVE_SYS_SOCKET_H
  25. #include <sys/socket.h>
  26. #endif
  27. #if APR_HAVE_FCNTL_H
  28. #include <fcntl.h>
  29. #endif
  30. #if APR_HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #if APR_HAVE_SYS_UN_H
  34. #include <sys/un.h>
  35. #endif
  36. #if defined(HAVE_UUID_H)
  37. #include <uuid.h>
  38. #elif defined(HAVE_UUID_UUID_H)
  39. #include <uuid/uuid.h>
  40. #elif defined(HAVE_SYS_UUID_H)
  41. #include <sys/uuid.h>
  42. #endif
  43. #ifndef SHUT_RDWR
  44. #define SHUT_RDWR 2
  45. #endif
  46. #if APR_HAS_OS_UUID
  47. #if defined(HAVE_UUID_CREATE)
  48. APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
  49. {
  50. uint32_t rv;
  51. uuid_t g;
  52. uuid_create(&g, &rv);
  53. if (rv != uuid_s_ok)
  54. return APR_EGENERAL;
  55. memcpy(uuid_data, &g, sizeof(uuid_t));
  56. return APR_SUCCESS;
  57. }
  58. #elif defined(HAVE_UUID_GENERATE)
  59. APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
  60. {
  61. uuid_t g;
  62. uuid_generate(g);
  63. memcpy(uuid_data, g, sizeof(uuid_t));
  64. return APR_SUCCESS;
  65. }
  66. #endif
  67. #endif /* APR_HAS_OS_UUID */
  68. #if APR_HAS_RANDOM
  69. APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
  70. apr_size_t length)
  71. {
  72. #ifdef DEV_RANDOM
  73. int fd = -1;
  74. /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
  75. * gives EOF, so reading 'length' bytes may require opening the
  76. * device several times. */
  77. do {
  78. apr_ssize_t rc;
  79. if (fd == -1)
  80. if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
  81. return errno;
  82. rc = read(fd, buf, length);
  83. if (rc < 0) {
  84. int errnum = errno;
  85. close(fd);
  86. return errnum;
  87. }
  88. else if (rc == 0) {
  89. close(fd);
  90. fd = -1; /* force open() again */
  91. }
  92. else {
  93. buf += rc;
  94. length -= rc;
  95. }
  96. } while (length > 0);
  97. close(fd);
  98. #elif defined(OS2)
  99. static UCHAR randbyte();
  100. unsigned int idx;
  101. for (idx=0; idx<length; idx++)
  102. buf[idx] = randbyte();
  103. #elif defined(HAVE_EGD)
  104. /* use EGD-compatible socket daemon (such as EGD or PRNGd).
  105. * message format:
  106. * 0x00 (get entropy level)
  107. * 0xMM (msb) 0xmm 0xll 0xLL (lsb)
  108. * 0x01 (read entropy nonblocking) 0xNN (bytes requested)
  109. * 0xMM (bytes granted) MM bytes
  110. * 0x02 (read entropy blocking) 0xNN (bytes desired)
  111. * [block] NN bytes
  112. * 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data)
  113. * NN bytes
  114. * (no response - write only)
  115. * 0x04 (report PID)
  116. * 0xMM (length of PID string, not null-terminated) MM chars
  117. */
  118. static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL };
  119. const char **egdsockname = NULL;
  120. int egd_socket, egd_path_len, rv, bad_errno;
  121. struct sockaddr_un addr;
  122. apr_socklen_t egd_addr_len;
  123. apr_size_t resp_expected;
  124. unsigned char req[2], resp[255];
  125. unsigned char *curbuf = buf;
  126. for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) {
  127. egd_path_len = strlen(*egdsockname);
  128. if (egd_path_len > sizeof(addr.sun_path)) {
  129. return APR_EINVAL;
  130. }
  131. memset(&addr, 0, sizeof(struct sockaddr_un));
  132. addr.sun_family = AF_UNIX;
  133. memcpy(addr.sun_path, *egdsockname, egd_path_len);
  134. egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) +
  135. egd_path_len;
  136. egd_socket = socket(PF_UNIX, SOCK_STREAM, 0);
  137. if (egd_socket == -1) {
  138. return errno;
  139. }
  140. rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len);
  141. if (rv == -1) {
  142. bad_errno = errno;
  143. continue;
  144. }
  145. /* EGD can only return 255 bytes of data at a time. Silly. */
  146. while (length > 0) {
  147. apr_ssize_t srv;
  148. req[0] = 2; /* We'll block for now. */
  149. req[1] = length > 255 ? 255: length;
  150. srv = write(egd_socket, req, 2);
  151. if (srv == -1) {
  152. bad_errno = errno;
  153. shutdown(egd_socket, SHUT_RDWR);
  154. close(egd_socket);
  155. break;
  156. }
  157. if (srv != 2) {
  158. shutdown(egd_socket, SHUT_RDWR);
  159. close(egd_socket);
  160. return APR_EGENERAL;
  161. }
  162. resp_expected = req[1];
  163. srv = read(egd_socket, resp, resp_expected);
  164. if (srv == -1) {
  165. bad_errno = errno;
  166. shutdown(egd_socket, SHUT_RDWR);
  167. close(egd_socket);
  168. return bad_errno;
  169. }
  170. memcpy(curbuf, resp, srv);
  171. curbuf += srv;
  172. length -= srv;
  173. }
  174. shutdown(egd_socket, SHUT_RDWR);
  175. close(egd_socket);
  176. }
  177. if (length > 0) {
  178. /* We must have iterated through the list of sockets,
  179. * and no go. Return the errno.
  180. */
  181. return bad_errno;
  182. }
  183. #elif defined(HAVE_TRUERAND) /* use truerand */
  184. extern int randbyte(void); /* from the truerand library */
  185. unsigned int idx;
  186. /* this will increase the startup time of the server, unfortunately...
  187. * (generating 20 bytes takes about 8 seconds)
  188. */
  189. for (idx=0; idx<length; idx++)
  190. buf[idx] = (unsigned char) randbyte();
  191. #endif /* DEV_RANDOM */
  192. return APR_SUCCESS;
  193. }
  194. #undef STR
  195. #undef XSTR
  196. #ifdef OS2
  197. #include "randbyte_os2.inc"
  198. #endif
  199. #endif /* APR_HAS_RANDOM */