]>
Commit | Line | Data |
---|---|---|
b1322259 | 1 | /* |
33388b44 | 2 | * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. |
4ec2d4d2 | 3 | * |
0db63de9 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
b1322259 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
4ec2d4d2 UM |
8 | */ |
9 | ||
effaf4de | 10 | #include <openssl/opensslconf.h> |
effaf4de | 11 | |
705536e2 RS |
12 | #include <openssl/crypto.h> |
13 | #include <openssl/e_os2.h> | |
14 | #include <openssl/rand.h> | |
4ec2d4d2 | 15 | |
e0c89df9 RS |
16 | /* |
17 | * Query an EGD | |
4ec2d4d2 UM |
18 | */ |
19 | ||
705536e2 | 20 | #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI) |
2fbc8a2a | 21 | int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) |
0f113f3e | 22 | { |
a2371fa9 | 23 | return -1; |
0f113f3e MC |
24 | } |
25 | ||
4ec2d4d2 | 26 | int RAND_egd(const char *path) |
0f113f3e | 27 | { |
75e2c877 | 28 | return -1; |
0f113f3e | 29 | } |
1921eaad | 30 | |
0f113f3e MC |
31 | int RAND_egd_bytes(const char *path, int bytes) |
32 | { | |
75e2c877 | 33 | return -1; |
0f113f3e | 34 | } |
e0c89df9 | 35 | |
705536e2 | 36 | #else |
e0c89df9 | 37 | |
705536e2 RS |
38 | # include <unistd.h> |
39 | # include <stddef.h> | |
40 | # include <sys/types.h> | |
41 | # include <sys/socket.h> | |
42 | # ifndef NO_SYS_UN_H | |
43 | # ifdef OPENSSL_SYS_VXWORKS | |
44 | # include <streams/un.h> | |
0423f812 | 45 | # else |
705536e2 RS |
46 | # include <sys/un.h> |
47 | # endif | |
48 | # else | |
0f113f3e MC |
49 | struct sockaddr_un { |
50 | short sun_family; /* AF_UNIX */ | |
51 | char sun_path[108]; /* path name (gag) */ | |
8bf49ea1 | 52 | }; |
705536e2 RS |
53 | # endif /* NO_SYS_UN_H */ |
54 | # include <string.h> | |
55 | # include <errno.h> | |
4ec2d4d2 | 56 | |
cdb5129e | 57 | # if defined(OPENSSL_SYS_TANDEM) |
08073700 RB |
58 | /* |
59 | * HPNS: | |
60 | * | |
61 | * Our current MQ 5.3 EGD requies compatability-mode sockets | |
62 | * This code forces the mode to compatibility if required | |
63 | * and then restores the mode. | |
64 | * | |
65 | * Needs review: | |
66 | * | |
67 | * The better long-term solution is to either run two EGD's each in one of | |
68 | * the two modes or revise the EGD code to listen on two different sockets | |
69 | * (each in one of the two modes). | |
70 | */ | |
71 | _variable | |
72 | int hpns_socket(int family, | |
73 | int type, | |
74 | int protocol, | |
75 | char* transport) | |
76 | { | |
77 | int socket_rc; | |
78 | char current_transport[20]; | |
79 | ||
80 | # define AF_UNIX_PORTABILITY "$ZAFN2" | |
81 | # define AF_UNIX_COMPATIBILITY "$ZPLS" | |
82 | ||
83 | if (!_arg_present(transport) || transport != NULL || transport[0] == '\0') | |
84 | return socket(family, type, protocol); | |
85 | ||
86 | socket_transport_name_get(AF_UNIX, current_transport, 20); | |
87 | ||
1287dabd | 88 | if (strcmp(current_transport, transport) == 0) |
08073700 RB |
89 | return socket(family, type, protocol); |
90 | ||
91 | /* set the requested socket transport */ | |
92 | if (socket_transport_name_set(AF_UNIX, transport)) | |
93 | return -1; | |
94 | ||
1287dabd | 95 | socket_rc = socket(family, type, protocol); |
08073700 RB |
96 | |
97 | /* set mode back to what it was */ | |
98 | if (socket_transport_name_set(AF_UNIX, current_transport)) | |
99 | return -1; | |
100 | ||
101 | return socket_rc; | |
102 | } | |
103 | ||
104 | /*#define socket(a,b,c,...) hpns_socket(a,b,c,__VA_ARGS__) */ | |
105 | ||
106 | static int hpns_connect_attempt = 0; | |
107 | ||
108 | # endif /* defined(OPENSSL_SYS_HPNS) */ | |
109 | ||
110 | ||
6343829a | 111 | int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) |
0f113f3e | 112 | { |
e0c89df9 | 113 | FILE *fp = NULL; |
0f113f3e | 114 | struct sockaddr_un addr; |
e0c89df9 RS |
115 | int mybuffer, ret = -1, i, numbytes, fd; |
116 | unsigned char tempbuf[255]; | |
4ec2d4d2 | 117 | |
e0c89df9 RS |
118 | if (bytes > (int)sizeof(tempbuf)) |
119 | return -1; | |
120 | ||
121 | /* Make socket. */ | |
0f113f3e MC |
122 | memset(&addr, 0, sizeof(addr)); |
123 | addr.sun_family = AF_UNIX; | |
124 | if (strlen(path) >= sizeof(addr.sun_path)) | |
75e2c877 | 125 | return -1; |
0904e79a | 126 | strcpy(addr.sun_path, path); |
e0c89df9 | 127 | i = offsetof(struct sockaddr_un, sun_path) + strlen(path); |
cdb5129e | 128 | #if defined(OPENSSL_SYS_TANDEM) |
08073700 RB |
129 | fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_COMPATIBILITY); |
130 | #else | |
0f113f3e | 131 | fd = socket(AF_UNIX, SOCK_STREAM, 0); |
08073700 | 132 | #endif |
e0c89df9 | 133 | if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL) |
75e2c877 RS |
134 | return -1; |
135 | setbuf(fp, NULL); | |
e0c89df9 RS |
136 | |
137 | /* Try to connect */ | |
1287dabd | 138 | for (;;) { |
e0c89df9 RS |
139 | if (connect(fd, (struct sockaddr *)&addr, i) == 0) |
140 | break; | |
705536e2 | 141 | # ifdef EISCONN |
e0c89df9 RS |
142 | if (errno == EISCONN) |
143 | break; | |
705536e2 | 144 | # endif |
e0c89df9 | 145 | switch (errno) { |
705536e2 | 146 | # ifdef EINTR |
e0c89df9 | 147 | case EINTR: |
705536e2 RS |
148 | # endif |
149 | # ifdef EAGAIN | |
e0c89df9 | 150 | case EAGAIN: |
705536e2 RS |
151 | # endif |
152 | # ifdef EINPROGRESS | |
e0c89df9 | 153 | case EINPROGRESS: |
705536e2 RS |
154 | # endif |
155 | # ifdef EALREADY | |
e0c89df9 | 156 | case EALREADY: |
705536e2 | 157 | # endif |
e0c89df9 RS |
158 | /* No error, try again */ |
159 | break; | |
160 | default: | |
cdb5129e | 161 | # if defined(OPENSSL_SYS_TANDEM) |
08073700 RB |
162 | if (hpns_connect_attempt == 0) { |
163 | /* try the other kind of AF_UNIX socket */ | |
164 | close(fd); | |
165 | fd = hpns_socket(AF_UNIX, SOCK_STREAM, 0, AF_UNIX_PORTABILITY); | |
166 | if (fd == -1) | |
167 | return -1; | |
168 | ++hpns_connect_attempt; | |
169 | break; /* try the connect again */ | |
170 | } | |
171 | # endif | |
172 | ||
e0c89df9 | 173 | ret = -1; |
0f113f3e | 174 | goto err; |
0f113f3e | 175 | } |
0f113f3e | 176 | } |
e0c89df9 RS |
177 | |
178 | /* Make request, see how many bytes we can get back. */ | |
179 | tempbuf[0] = 1; | |
180 | tempbuf[1] = bytes; | |
181 | if (fwrite(tempbuf, sizeof(char), 2, fp) != 2 || fflush(fp) == EOF) | |
182 | goto err; | |
183 | if (fread(tempbuf, sizeof(char), 1, fp) != 1 || tempbuf[0] == 0) | |
184 | goto err; | |
185 | numbytes = tempbuf[0]; | |
186 | ||
187 | /* Which buffer are we using? */ | |
188 | mybuffer = buf == NULL; | |
189 | if (mybuffer) | |
190 | buf = tempbuf; | |
191 | ||
192 | /* Read bytes. */ | |
193 | i = fread(buf, sizeof(char), numbytes, fp); | |
194 | if (i < numbytes) | |
195 | goto err; | |
196 | ret = numbytes; | |
197 | if (mybuffer) | |
75e2c877 | 198 | RAND_add(tempbuf, i, i); |
e0c89df9 | 199 | |
599c0353 | 200 | err: |
e0c89df9 RS |
201 | if (fp != NULL) |
202 | fclose(fp); | |
a2371fa9 | 203 | return ret; |
0f113f3e | 204 | } |
a8ebe469 | 205 | |
6343829a | 206 | int RAND_egd_bytes(const char *path, int bytes) |
0f113f3e | 207 | { |
e0c89df9 | 208 | int num; |
599c0353 | 209 | |
0f113f3e | 210 | num = RAND_query_egd_bytes(path, NULL, bytes); |
c2114afc | 211 | if (num < 0) |
e0c89df9 RS |
212 | return -1; |
213 | if (RAND_status() != 1) | |
214 | return -1; | |
215 | return num; | |
0f113f3e | 216 | } |
1921eaad | 217 | |
a8ebe469 | 218 | int RAND_egd(const char *path) |
0f113f3e | 219 | { |
75e2c877 | 220 | return RAND_egd_bytes(path, 255); |
0f113f3e | 221 | } |
1921eaad | 222 | |
4ec2d4d2 | 223 | #endif |