]>
Commit | Line | Data |
---|---|---|
58964a49 | 1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
2 | * All rights reserved. |
3 | * | |
4 | * This package is an SSL implementation written | |
5 | * by Eric Young (eay@cryptsoft.com). | |
6 | * The implementation was written so as to conform with Netscapes SSL. | |
0f113f3e | 7 | * |
d02b48c6 RE |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions | |
10 | * apply to all code found in this distribution, be it the RC4, RSA, | |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
12 | * included with this distribution is covered by the same copyright terms | |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
0f113f3e | 14 | * |
d02b48c6 RE |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. | |
17 | * If this package is used in a product, Eric Young should be given attribution | |
18 | * as the author of the parts of the library used. | |
19 | * This can be in the form of a textual message at program startup or | |
20 | * in documentation (online or textual) provided with the package. | |
0f113f3e | 21 | * |
d02b48c6 RE |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions | |
24 | * are met: | |
25 | * 1. Redistributions of source code must retain the copyright | |
26 | * notice, this list of conditions and the following disclaimer. | |
27 | * 2. Redistributions in binary form must reproduce the above copyright | |
28 | * notice, this list of conditions and the following disclaimer in the | |
29 | * documentation and/or other materials provided with the distribution. | |
30 | * 3. All advertising materials mentioning features or use of this software | |
31 | * must display the following acknowledgement: | |
32 | * "This product includes cryptographic software written by | |
33 | * Eric Young (eay@cryptsoft.com)" | |
34 | * The word 'cryptographic' can be left out if the rouines from the library | |
35 | * being used are not cryptographic related :-). | |
0f113f3e | 36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
d02b48c6 RE |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
0f113f3e | 39 | * |
d02b48c6 RE |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
50 | * SUCH DAMAGE. | |
0f113f3e | 51 | * |
d02b48c6 RE |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
54 | * copied and put under another distribution licence | |
55 | * [including the GNU Public Licence.] | |
56 | */ | |
7e1b7485 RS |
57 | /* ==================================================================== |
58 | * Copyright (c) 199-2015 The OpenSSL Project. All rights reserved. | |
59 | * | |
60 | * Redistribution and use in source and binary forms, with or without | |
61 | * modification, are permitted provided that the following conditions | |
62 | * are met: | |
63 | * | |
64 | * 1. Redistributions of source code must retain the above copyright | |
65 | * notice, this list of conditions and the following disclaimer. | |
66 | * | |
67 | * 2. Redistributions in binary form must reproduce the above copyright | |
68 | * notice, this list of conditions and the following disclaimer in | |
69 | * the documentation and/or other materials provided with the | |
70 | * distribution. | |
71 | * | |
72 | * 3. All advertising materials mentioning features or use of this | |
73 | * software must display the following acknowledgment: | |
74 | * "This product includes software developed by the OpenSSL Project | |
75 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
76 | * | |
77 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
78 | * endorse or promote products derived from this software without | |
79 | * prior written permission. For written permission, please contact | |
80 | * licensing@OpenSSL.org. | |
81 | * | |
82 | * 5. Products derived from this software may not be called "OpenSSL" | |
83 | * nor may "OpenSSL" appear in their names without prior written | |
84 | * permission of the OpenSSL Project. | |
85 | * | |
86 | * 6. Redistributions of any form whatsoever must retain the following | |
87 | * acknowledgment: | |
88 | * "This product includes software developed by the OpenSSL Project | |
89 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
90 | * | |
91 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
92 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
94 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
95 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
96 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
97 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
98 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
99 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
100 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
101 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
102 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
103 | * ==================================================================== | |
104 | */ | |
d02b48c6 | 105 | |
7e1b7485 | 106 | /* socket-related functions used by s_client and s_server */ |
8c197cc5 UM |
107 | #include <stdio.h> |
108 | #include <stdlib.h> | |
109 | #include <string.h> | |
110 | #include <errno.h> | |
111 | #include <signal.h> | |
112 | ||
0f113f3e MC |
113 | /* |
114 | * With IPv6, it looks like Digital has mixed up the proper order of | |
115 | * recursive header file inclusion, resulting in the compiler complaining | |
116 | * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is | |
117 | * needed to have fileno() declared correctly... So let's define u_int | |
118 | */ | |
bc36ee62 | 119 | #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) |
0f113f3e | 120 | # define __U_INT |
7d7d2cbc UM |
121 | typedef unsigned int u_int; |
122 | #endif | |
123 | ||
02cc82ff | 124 | #define USE_SOCKETS |
02cc82ff RL |
125 | #include "apps.h" |
126 | #undef USE_SOCKETS | |
02cc82ff RL |
127 | #include "s_apps.h" |
128 | #include <openssl/ssl.h> | |
129 | ||
4579924b | 130 | #ifdef FLAT_INC |
0f113f3e | 131 | # include "e_os.h" |
4579924b | 132 | #else |
0f113f3e | 133 | # include "../e_os.h" |
4579924b RL |
134 | #endif |
135 | ||
136 | #ifndef OPENSSL_NO_SOCK | |
137 | ||
0f113f3e MC |
138 | # if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) |
139 | # include "netdb.h" | |
140 | # endif | |
b764ab95 | 141 | |
0f113f3e | 142 | # if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) |
8d6e6048 | 143 | static void ssl_sock_cleanup(void); |
0f113f3e | 144 | # endif |
8d6e6048 | 145 | static int ssl_sock_init(void); |
105d62cb | 146 | static int init_client_ip(int *sock, const unsigned char ip[4], int port, |
0f113f3e | 147 | int type); |
36d16f8e | 148 | static int init_server(int *sock, int port, int type); |
0f113f3e | 149 | static int init_server_long(int *sock, int port, char *ip, int type); |
863fe2ec | 150 | static int do_accept(int acc_sock, int *sock, char **host); |
76c3ff69 | 151 | static int host_ip(const char *str, unsigned char ip[4]); |
0f113f3e | 152 | # ifndef NO_SYS_UN_H |
a9351320 GT |
153 | static int init_server_unix(int *sock, const char *path); |
154 | static int do_accept_unix(int acc_sock, int *sock); | |
0f113f3e | 155 | # endif |
863fe2ec | 156 | |
0f113f3e MC |
157 | # if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) |
158 | static int wsa_init_done = 0; | |
159 | # endif | |
4d8743f4 | 160 | |
0f113f3e | 161 | # ifdef OPENSSL_SYS_WINDOWS |
d02b48c6 | 162 | static struct WSAData wsa_state; |
0f113f3e | 163 | static int wsa_init_done = 0; |
d02b48c6 | 164 | |
0f113f3e | 165 | # endif /* OPENSSL_SYS_WINDOWS */ |
d02b48c6 | 166 | |
0f113f3e | 167 | # ifdef OPENSSL_SYS_WINDOWS |
8d6e6048 | 168 | static void ssl_sock_cleanup(void) |
0f113f3e MC |
169 | { |
170 | if (wsa_init_done) { | |
171 | wsa_init_done = 0; | |
172 | # ifndef OPENSSL_SYS_WINCE | |
173 | WSACancelBlockingCall(); | |
174 | # endif | |
175 | WSACleanup(); | |
176 | } | |
177 | } | |
178 | # elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) | |
4d8743f4 | 179 | static void sock_cleanup(void) |
0f113f3e MC |
180 | { |
181 | if (wsa_init_done) { | |
182 | wsa_init_done = 0; | |
183 | WSACleanup(); | |
184 | } | |
185 | } | |
4d8743f4 RL |
186 | # endif |
187 | ||
0f113f3e MC |
188 | static int ssl_sock_init(void) |
189 | { | |
190 | # ifdef WATT32 | |
191 | extern int _watt_do_exit; | |
192 | _watt_do_exit = 0; | |
193 | if (sock_init()) | |
194 | return (0); | |
195 | # elif defined(OPENSSL_SYS_WINDOWS) | |
196 | if (!wsa_init_done) { | |
197 | int err; | |
198 | ||
199 | # ifdef SIGINT | |
200 | signal(SIGINT, (void (*)(int))ssl_sock_cleanup); | |
201 | # endif | |
202 | wsa_init_done = 1; | |
203 | memset(&wsa_state, 0, sizeof(wsa_state)); | |
204 | if (WSAStartup(0x0101, &wsa_state) != 0) { | |
205 | err = WSAGetLastError(); | |
206 | BIO_printf(bio_err, "unable to start WINSOCK, error code=%d\n", | |
207 | err); | |
208 | return (0); | |
209 | } | |
210 | } | |
211 | # elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) | |
212 | WORD wVerReq; | |
213 | WSADATA wsaData; | |
214 | int err; | |
215 | ||
216 | if (!wsa_init_done) { | |
217 | ||
218 | # ifdef SIGINT | |
219 | signal(SIGINT, (void (*)(int))sock_cleanup); | |
220 | # endif | |
221 | ||
222 | wsa_init_done = 1; | |
223 | wVerReq = MAKEWORD(2, 0); | |
224 | err = WSAStartup(wVerReq, &wsaData); | |
225 | if (err != 0) { | |
226 | BIO_printf(bio_err, "unable to start WINSOCK2, error code=%d\n", | |
227 | err); | |
228 | return (0); | |
229 | } | |
230 | } | |
7e1b7485 | 231 | # endif |
0f113f3e MC |
232 | return (1); |
233 | } | |
d02b48c6 | 234 | |
76c3ff69 | 235 | int init_client(int *sock, const char *host, int port, int type) |
0f113f3e MC |
236 | { |
237 | unsigned char ip[4]; | |
d02b48c6 | 238 | |
0f113f3e MC |
239 | ip[0] = ip[1] = ip[2] = ip[3] = 0; |
240 | if (!host_ip(host, &(ip[0]))) | |
241 | return 0; | |
242 | return init_client_ip(sock, ip, port, type); | |
243 | } | |
d02b48c6 | 244 | |
105d62cb | 245 | static int init_client_ip(int *sock, const unsigned char ip[4], int port, |
0f113f3e MC |
246 | int type) |
247 | { | |
248 | unsigned long addr; | |
249 | struct sockaddr_in them; | |
250 | int s, i; | |
251 | ||
252 | if (!ssl_sock_init()) | |
253 | return (0); | |
254 | ||
16f8d4eb | 255 | memset(&them, 0, sizeof(them)); |
0f113f3e MC |
256 | them.sin_family = AF_INET; |
257 | them.sin_port = htons((unsigned short)port); | |
258 | addr = (unsigned long) | |
259 | ((unsigned long)ip[0] << 24L) | | |
260 | ((unsigned long)ip[1] << 16L) | | |
261 | ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]); | |
262 | them.sin_addr.s_addr = htonl(addr); | |
263 | ||
264 | if (type == SOCK_STREAM) | |
265 | s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
266 | else /* ( type == SOCK_DGRAM) */ | |
267 | s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
268 | ||
b13fdc48 | 269 | if (s == (int)INVALID_SOCKET) { |
0f113f3e MC |
270 | perror("socket"); |
271 | return (0); | |
272 | } | |
273 | # if defined(SO_KEEPALIVE) | |
274 | if (type == SOCK_STREAM) { | |
275 | i = 0; | |
276 | i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)); | |
277 | if (i < 0) { | |
278 | closesocket(s); | |
279 | perror("keepalive"); | |
280 | return (0); | |
281 | } | |
282 | } | |
283 | # endif | |
d02b48c6 | 284 | |
0f113f3e MC |
285 | if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) { |
286 | closesocket(s); | |
287 | perror("connect"); | |
288 | return (0); | |
289 | } | |
290 | *sock = s; | |
291 | return (1); | |
292 | } | |
d02b48c6 | 293 | |
0f113f3e | 294 | # ifndef NO_SYS_UN_H |
a9351320 | 295 | int init_client_unix(int *sock, const char *server) |
0f113f3e MC |
296 | { |
297 | struct sockaddr_un them; | |
298 | int s; | |
299 | ||
300 | if (strlen(server) > (UNIX_PATH_MAX + 1)) | |
301 | return (0); | |
302 | if (!ssl_sock_init()) | |
303 | return (0); | |
304 | ||
305 | s = socket(AF_UNIX, SOCK_STREAM, 0); | |
b13fdc48 | 306 | if (s == (int)INVALID_SOCKET) { |
0f113f3e MC |
307 | perror("socket"); |
308 | return (0); | |
309 | } | |
310 | ||
16f8d4eb | 311 | memset(&them, 0, sizeof(them)); |
0f113f3e MC |
312 | them.sun_family = AF_UNIX; |
313 | strcpy(them.sun_path, server); | |
314 | ||
315 | if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) { | |
316 | closesocket(s); | |
317 | perror("connect"); | |
318 | return (0); | |
319 | } | |
320 | *sock = s; | |
321 | return (1); | |
322 | } | |
323 | # endif | |
a9351320 GT |
324 | |
325 | int do_server(int port, int type, int *ret, | |
0f113f3e MC |
326 | int (*cb) (char *hostname, int s, int stype, |
327 | unsigned char *context), unsigned char *context, | |
328 | int naccept) | |
329 | { | |
330 | int sock; | |
331 | char *name = NULL; | |
332 | int accept_socket = 0; | |
333 | int i; | |
334 | ||
335 | if (!init_server(&accept_socket, port, type)) | |
336 | return (0); | |
337 | ||
338 | if (ret != NULL) { | |
339 | *ret = accept_socket; | |
340 | /* return(1); */ | |
341 | } | |
342 | for (;;) { | |
343 | if (type == SOCK_STREAM) { | |
344 | # ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL | |
345 | if (do_accept(accept_socket, &sock, NULL) == 0) | |
346 | # else | |
347 | if (do_accept(accept_socket, &sock, &name) == 0) | |
348 | # endif | |
349 | { | |
350 | SHUTDOWN(accept_socket); | |
351 | return (0); | |
352 | } | |
353 | } else | |
354 | sock = accept_socket; | |
355 | i = (*cb) (name, sock, type, context); | |
b548a1f1 | 356 | OPENSSL_free(name); |
0f113f3e MC |
357 | if (type == SOCK_STREAM) |
358 | SHUTDOWN2(sock); | |
359 | if (naccept != -1) | |
360 | naccept--; | |
361 | if (i < 0 || naccept == 0) { | |
362 | SHUTDOWN2(accept_socket); | |
363 | return (i); | |
364 | } | |
365 | } | |
366 | } | |
367 | ||
368 | # ifndef NO_SYS_UN_H | |
a9351320 | 369 | int do_server_unix(const char *path, int *ret, |
0f113f3e MC |
370 | int (*cb) (char *hostname, int s, int stype, |
371 | unsigned char *context), unsigned char *context, | |
372 | int naccept) | |
373 | { | |
374 | int sock; | |
375 | int accept_socket = 0; | |
376 | int i; | |
377 | ||
378 | if (!init_server_unix(&accept_socket, path)) | |
379 | return (0); | |
380 | ||
381 | if (ret != NULL) | |
382 | *ret = accept_socket; | |
383 | for (;;) { | |
384 | if (do_accept_unix(accept_socket, &sock) == 0) { | |
385 | SHUTDOWN(accept_socket); | |
386 | i = 0; | |
387 | goto out; | |
388 | } | |
389 | i = (*cb) (NULL, sock, 0, context); | |
390 | SHUTDOWN2(sock); | |
391 | if (naccept != -1) | |
392 | naccept--; | |
393 | if (i < 0 || naccept == 0) { | |
394 | SHUTDOWN2(accept_socket); | |
395 | goto out; | |
396 | } | |
397 | } | |
398 | out: | |
399 | unlink(path); | |
400 | return (i); | |
401 | } | |
402 | # endif | |
a9351320 | 403 | |
36d16f8e | 404 | static int init_server_long(int *sock, int port, char *ip, int type) |
0f113f3e MC |
405 | { |
406 | int ret = 0; | |
407 | struct sockaddr_in server; | |
408 | int s = -1; | |
409 | ||
410 | if (!ssl_sock_init()) | |
411 | return (0); | |
412 | ||
16f8d4eb | 413 | memset(&server, 0, sizeof(server)); |
0f113f3e MC |
414 | server.sin_family = AF_INET; |
415 | server.sin_port = htons((unsigned short)port); | |
416 | if (ip == NULL) | |
417 | server.sin_addr.s_addr = INADDR_ANY; | |
418 | else | |
13e91dd3 | 419 | /* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */ |
0f113f3e MC |
420 | # ifndef BIT_FIELD_LIMITS |
421 | memcpy(&server.sin_addr.s_addr, ip, 4); | |
422 | # else | |
423 | memcpy(&server.sin_addr, ip, 4); | |
424 | # endif | |
a9351320 | 425 | |
0f113f3e MC |
426 | if (type == SOCK_STREAM) |
427 | s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
428 | else /* type == SOCK_DGRAM */ | |
429 | s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
a9351320 | 430 | |
b13fdc48 | 431 | if (s == (int)INVALID_SOCKET) |
0f113f3e MC |
432 | goto err; |
433 | # if defined SOL_SOCKET && defined SO_REUSEADDR | |
434 | { | |
435 | int j = 1; | |
436 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&j, sizeof j); | |
437 | } | |
438 | # endif | |
439 | if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) { | |
440 | # ifndef OPENSSL_SYS_WINDOWS | |
441 | perror("bind"); | |
442 | # endif | |
443 | goto err; | |
444 | } | |
445 | /* Make it 128 for linux */ | |
446 | if (type == SOCK_STREAM && listen(s, 128) == -1) | |
447 | goto err; | |
448 | *sock = s; | |
449 | ret = 1; | |
450 | err: | |
451 | if ((ret == 0) && (s != -1)) { | |
452 | SHUTDOWN(s); | |
453 | } | |
454 | return (ret); | |
455 | } | |
a9351320 | 456 | |
0f113f3e MC |
457 | static int init_server(int *sock, int port, int type) |
458 | { | |
459 | return (init_server_long(sock, port, NULL, type)); | |
460 | } | |
a9351320 | 461 | |
0f113f3e MC |
462 | # ifndef NO_SYS_UN_H |
463 | static int init_server_unix(int *sock, const char *path) | |
464 | { | |
465 | int ret = 0; | |
466 | struct sockaddr_un server; | |
467 | int s = -1; | |
468 | ||
469 | if (strlen(path) > (UNIX_PATH_MAX + 1)) | |
470 | return (0); | |
471 | if (!ssl_sock_init()) | |
472 | return (0); | |
473 | ||
474 | s = socket(AF_UNIX, SOCK_STREAM, 0); | |
b13fdc48 | 475 | if (s == (int)INVALID_SOCKET) |
0f113f3e MC |
476 | goto err; |
477 | ||
16f8d4eb | 478 | memset(&server, 0, sizeof(server)); |
0f113f3e MC |
479 | server.sun_family = AF_UNIX; |
480 | strcpy(server.sun_path, path); | |
481 | ||
482 | if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) { | |
483 | # ifndef OPENSSL_SYS_WINDOWS | |
484 | perror("bind"); | |
485 | # endif | |
486 | goto err; | |
487 | } | |
488 | /* Make it 128 for linux */ | |
489 | if (listen(s, 128) == -1) { | |
490 | # ifndef OPENSSL_SYS_WINDOWS | |
491 | perror("listen"); | |
492 | # endif | |
493 | unlink(path); | |
494 | goto err; | |
495 | } | |
496 | *sock = s; | |
497 | ret = 1; | |
498 | err: | |
499 | if ((ret == 0) && (s != -1)) { | |
500 | SHUTDOWN(s); | |
501 | } | |
502 | return (ret); | |
503 | } | |
504 | # endif | |
a9351320 | 505 | |
863fe2ec | 506 | static int do_accept(int acc_sock, int *sock, char **host) |
0f113f3e MC |
507 | { |
508 | int ret; | |
509 | struct hostent *h1, *h2; | |
510 | static struct sockaddr_in from; | |
511 | int len; | |
512 | /* struct linger ling; */ | |
513 | ||
514 | if (!ssl_sock_init()) | |
515 | return (0); | |
516 | ||
517 | # ifndef OPENSSL_SYS_WINDOWS | |
518 | redoit: | |
519 | # endif | |
d02b48c6 | 520 | |
16f8d4eb | 521 | memset(&from, 0, sizeof(from)); |
0f113f3e MC |
522 | len = sizeof(from); |
523 | /* | |
524 | * Note: under VMS with SOCKETSHR the fourth parameter is currently of | |
525 | * type (int *) whereas under other systems it is (void *) if you don't | |
526 | * have a cast it will choke the compiler: if you do have a cast then you | |
527 | * can either go for (int *) or (void *). | |
528 | */ | |
529 | ret = accept(acc_sock, (struct sockaddr *)&from, (void *)&len); | |
b13fdc48 | 530 | if (ret == (int)INVALID_SOCKET) { |
0f113f3e MC |
531 | # if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) |
532 | int i; | |
533 | i = WSAGetLastError(); | |
534 | BIO_printf(bio_err, "accept error %d\n", i); | |
535 | # else | |
536 | if (errno == EINTR) { | |
537 | /* | |
538 | * check_timeout(); | |
539 | */ | |
540 | goto redoit; | |
541 | } | |
7768e116 | 542 | BIO_printf(bio_err, "accept errno=%d, %s\n", errno, strerror(errno)); |
0f113f3e MC |
543 | # endif |
544 | return (0); | |
545 | } | |
d02b48c6 | 546 | |
0f113f3e MC |
547 | if (host == NULL) |
548 | goto end; | |
549 | # ifndef BIT_FIELD_LIMITS | |
550 | /* I should use WSAAsyncGetHostByName() under windows */ | |
551 | h1 = gethostbyaddr((char *)&from.sin_addr.s_addr, | |
552 | sizeof(from.sin_addr.s_addr), AF_INET); | |
553 | # else | |
554 | h1 = gethostbyaddr((char *)&from.sin_addr, | |
555 | sizeof(struct in_addr), AF_INET); | |
556 | # endif | |
557 | if (h1 == NULL) { | |
558 | BIO_printf(bio_err, "bad gethostbyaddr\n"); | |
559 | *host = NULL; | |
560 | /* return(0); */ | |
561 | } else { | |
68dc6824 | 562 | *host = app_malloc(strlen(h1->h_name) + 1, "copy hostname"); |
7644a9ae | 563 | OPENSSL_strlcpy(*host, h1->h_name, strlen(h1->h_name) + 1); |
0f113f3e | 564 | |
ff660b93 | 565 | h2 = gethostbyname(*host); |
0f113f3e MC |
566 | if (h2 == NULL) { |
567 | BIO_printf(bio_err, "gethostbyname failure\n"); | |
568 | closesocket(ret); | |
569 | return (0); | |
570 | } | |
571 | if (h2->h_addrtype != AF_INET) { | |
572 | BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n"); | |
573 | closesocket(ret); | |
574 | return (0); | |
575 | } | |
576 | } | |
577 | end: | |
578 | *sock = ret; | |
579 | return (1); | |
580 | } | |
581 | ||
582 | # ifndef NO_SYS_UN_H | |
a9351320 | 583 | static int do_accept_unix(int acc_sock, int *sock) |
0f113f3e MC |
584 | { |
585 | int ret; | |
586 | ||
587 | if (!ssl_sock_init()) | |
588 | return (0); | |
589 | ||
590 | redoit: | |
591 | ret = accept(acc_sock, NULL, NULL); | |
b13fdc48 | 592 | if (ret == (int)INVALID_SOCKET) { |
0f113f3e MC |
593 | if (errno == EINTR) { |
594 | /* | |
595 | * check_timeout(); | |
596 | */ | |
597 | goto redoit; | |
598 | } | |
7768e116 | 599 | BIO_printf(bio_err, "accept errno=%d, %s\n", errno, strerror(errno)); |
0f113f3e MC |
600 | return (0); |
601 | } | |
602 | ||
603 | *sock = ret; | |
604 | return (1); | |
605 | } | |
606 | # endif | |
a9351320 | 607 | |
6b691a5c | 608 | int extract_host_port(char *str, char **host_ptr, unsigned char *ip, |
7e1b7485 | 609 | unsigned short *port_ptr) |
0f113f3e MC |
610 | { |
611 | char *h, *p; | |
612 | ||
613 | h = str; | |
614 | p = strchr(str, ':'); | |
615 | if (p == NULL) { | |
616 | BIO_printf(bio_err, "no port defined\n"); | |
617 | return (0); | |
618 | } | |
619 | *(p++) = '\0'; | |
620 | ||
621 | if ((ip != NULL) && !host_ip(str, ip)) | |
622 | goto err; | |
623 | if (host_ptr != NULL) | |
624 | *host_ptr = h; | |
625 | ||
626 | if (!extract_port(p, port_ptr)) | |
627 | goto err; | |
628 | return (1); | |
629 | err: | |
630 | return (0); | |
631 | } | |
d02b48c6 | 632 | |
76c3ff69 | 633 | static int host_ip(const char *str, unsigned char ip[4]) |
0f113f3e MC |
634 | { |
635 | unsigned int in[4]; | |
636 | int i; | |
637 | ||
638 | if (sscanf(str, "%u.%u.%u.%u", &(in[0]), &(in[1]), &(in[2]), &(in[3])) == | |
639 | 4) { | |
640 | for (i = 0; i < 4; i++) | |
641 | if (in[i] > 255) { | |
642 | BIO_printf(bio_err, "invalid IP address\n"); | |
643 | goto err; | |
644 | } | |
645 | ip[0] = in[0]; | |
646 | ip[1] = in[1]; | |
647 | ip[2] = in[2]; | |
648 | ip[3] = in[3]; | |
649 | } else { /* do a gethostbyname */ | |
650 | struct hostent *he; | |
651 | ||
652 | if (!ssl_sock_init()) | |
653 | return (0); | |
654 | ||
ff660b93 | 655 | he = gethostbyname(str); |
0f113f3e MC |
656 | if (he == NULL) { |
657 | BIO_printf(bio_err, "gethostbyname failure\n"); | |
658 | goto err; | |
659 | } | |
660 | if (he->h_addrtype != AF_INET) { | |
661 | BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n"); | |
662 | return (0); | |
663 | } | |
664 | ip[0] = he->h_addr_list[0][0]; | |
665 | ip[1] = he->h_addr_list[0][1]; | |
666 | ip[2] = he->h_addr_list[0][2]; | |
667 | ip[3] = he->h_addr_list[0][3]; | |
668 | } | |
669 | return (1); | |
670 | err: | |
671 | return (0); | |
672 | } | |
d02b48c6 | 673 | |
7e1b7485 | 674 | int extract_port(const char *str, unsigned short *port_ptr) |
0f113f3e MC |
675 | { |
676 | int i; | |
677 | struct servent *s; | |
678 | ||
679 | i = atoi(str); | |
680 | if (i != 0) | |
681 | *port_ptr = (unsigned short)i; | |
682 | else { | |
683 | s = getservbyname(str, "tcp"); | |
684 | if (s == NULL) { | |
685 | BIO_printf(bio_err, "getservbyname failure for %s\n", str); | |
686 | return (0); | |
687 | } | |
688 | *port_ptr = ntohs((unsigned short)s->s_port); | |
689 | } | |
690 | return (1); | |
691 | } | |
692 | ||
19aa3705 | 693 | #endif |