/src/openssl/crypto/bio/b_sock.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* crypto/bio/b_sock.c */ |
2 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | | * All rights reserved. |
4 | | * |
5 | | * This package is an SSL implementation written |
6 | | * by Eric Young (eay@cryptsoft.com). |
7 | | * The implementation was written so as to conform with Netscapes SSL. |
8 | | * |
9 | | * This library is free for commercial and non-commercial use as long as |
10 | | * the following conditions are aheared to. The following conditions |
11 | | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | | * included with this distribution is covered by the same copyright terms |
14 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | | * |
16 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | | * the code are not to be removed. |
18 | | * If this package is used in a product, Eric Young should be given attribution |
19 | | * as the author of the parts of the library used. |
20 | | * This can be in the form of a textual message at program startup or |
21 | | * in documentation (online or textual) provided with the package. |
22 | | * |
23 | | * Redistribution and use in source and binary forms, with or without |
24 | | * modification, are permitted provided that the following conditions |
25 | | * are met: |
26 | | * 1. Redistributions of source code must retain the copyright |
27 | | * notice, this list of conditions and the following disclaimer. |
28 | | * 2. Redistributions in binary form must reproduce the above copyright |
29 | | * notice, this list of conditions and the following disclaimer in the |
30 | | * documentation and/or other materials provided with the distribution. |
31 | | * 3. All advertising materials mentioning features or use of this software |
32 | | * must display the following acknowledgement: |
33 | | * "This product includes cryptographic software written by |
34 | | * Eric Young (eay@cryptsoft.com)" |
35 | | * The word 'cryptographic' can be left out if the rouines from the library |
36 | | * being used are not cryptographic related :-). |
37 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | | * the apps directory (application code) you must include an acknowledgement: |
39 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | | * |
41 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | | * SUCH DAMAGE. |
52 | | * |
53 | | * The licence and distribution terms for any publically available version or |
54 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | | * copied and put under another distribution licence |
56 | | * [including the GNU Public Licence.] |
57 | | */ |
58 | | |
59 | | #include <stdio.h> |
60 | | #include <stdlib.h> |
61 | | #include <errno.h> |
62 | | #define USE_SOCKETS |
63 | | #include "cryptlib.h" |
64 | | #include <openssl/bio.h> |
65 | | #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) |
66 | | # include <netdb.h> |
67 | | # if defined(NETWARE_CLIB) |
68 | | # include <sys/ioctl.h> |
69 | | NETDB_DEFINE_CONTEXT |
70 | | # endif |
71 | | #endif |
72 | | #ifndef OPENSSL_NO_SOCK |
73 | | # include <openssl/dso.h> |
74 | 0 | # define SOCKET_PROTOCOL IPPROTO_TCP |
75 | | # ifdef SO_MAXCONN |
76 | | # define MAX_LISTEN SO_MAXCONN |
77 | | # elif defined(SOMAXCONN) |
78 | 0 | # define MAX_LISTEN SOMAXCONN |
79 | | # else |
80 | | # define MAX_LISTEN 32 |
81 | | # endif |
82 | | # if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) |
83 | | static int wsa_init_done = 0; |
84 | | # endif |
85 | | |
86 | | /* |
87 | | * WSAAPI specifier is required to make indirect calls to run-time |
88 | | * linked WinSock 2 functions used in this module, to be specific |
89 | | * [get|free]addrinfo and getnameinfo. This is because WinSock uses |
90 | | * uses non-C calling convention, __stdcall vs. __cdecl, on x86 |
91 | | * Windows. On non-WinSock platforms WSAAPI needs to be void. |
92 | | */ |
93 | | # ifndef WSAAPI |
94 | | # define WSAAPI |
95 | | # endif |
96 | | |
97 | | # if 0 |
98 | | static unsigned long BIO_ghbn_hits = 0L; |
99 | | static unsigned long BIO_ghbn_miss = 0L; |
100 | | |
101 | | # define GHBN_NUM 4 |
102 | | static struct ghbn_cache_st { |
103 | | char name[129]; |
104 | | struct hostent *ent; |
105 | | unsigned long order; |
106 | | } ghbn_cache[GHBN_NUM]; |
107 | | # endif |
108 | | |
109 | | static int get_ip(const char *str, unsigned char *ip); |
110 | | # if 0 |
111 | | static void ghbn_free(struct hostent *a); |
112 | | static struct hostent *ghbn_dup(struct hostent *a); |
113 | | # endif |
114 | | int BIO_get_host_ip(const char *str, unsigned char *ip) |
115 | 0 | { |
116 | 0 | int i; |
117 | 0 | int err = 1; |
118 | 0 | int locked = 0; |
119 | 0 | struct hostent *he; |
120 | |
|
121 | 0 | i = get_ip(str, ip); |
122 | 0 | if (i < 0) { |
123 | 0 | BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_INVALID_IP_ADDRESS); |
124 | 0 | goto err; |
125 | 0 | } |
126 | | |
127 | | /* |
128 | | * At this point, we have something that is most probably correct in some |
129 | | * way, so let's init the socket. |
130 | | */ |
131 | 0 | if (BIO_sock_init() != 1) |
132 | 0 | return 0; /* don't generate another error code here */ |
133 | | |
134 | | /* |
135 | | * If the string actually contained an IP address, we need not do |
136 | | * anything more |
137 | | */ |
138 | 0 | if (i > 0) |
139 | 0 | return (1); |
140 | | |
141 | | /* do a gethostbyname */ |
142 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); |
143 | 0 | locked = 1; |
144 | 0 | he = BIO_gethostbyname(str); |
145 | 0 | if (he == NULL) { |
146 | 0 | BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP); |
147 | 0 | goto err; |
148 | 0 | } |
149 | | |
150 | | /* cast to short because of win16 winsock definition */ |
151 | 0 | if ((short)he->h_addrtype != AF_INET) { |
152 | 0 | BIOerr(BIO_F_BIO_GET_HOST_IP, |
153 | 0 | BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); |
154 | 0 | goto err; |
155 | 0 | } |
156 | 0 | for (i = 0; i < 4; i++) |
157 | 0 | ip[i] = he->h_addr_list[0][i]; |
158 | 0 | err = 0; |
159 | |
|
160 | 0 | err: |
161 | 0 | if (locked) |
162 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); |
163 | 0 | if (err) { |
164 | 0 | ERR_add_error_data(2, "host=", str); |
165 | 0 | return 0; |
166 | 0 | } else |
167 | 0 | return 1; |
168 | 0 | } |
169 | | |
170 | | int BIO_get_port(const char *str, unsigned short *port_ptr) |
171 | 0 | { |
172 | 0 | int i; |
173 | 0 | struct servent *s; |
174 | |
|
175 | 0 | if (str == NULL) { |
176 | 0 | BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); |
177 | 0 | return (0); |
178 | 0 | } |
179 | 0 | i = atoi(str); |
180 | 0 | if (i != 0) |
181 | 0 | *port_ptr = (unsigned short)i; |
182 | 0 | else { |
183 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); |
184 | | /* |
185 | | * Note: under VMS with SOCKETSHR, it seems like the first parameter |
186 | | * is 'char *', instead of 'const char *' |
187 | | */ |
188 | 0 | # ifndef CONST_STRICT |
189 | 0 | s = getservbyname((char *)str, "tcp"); |
190 | | # else |
191 | | s = getservbyname(str, "tcp"); |
192 | | # endif |
193 | 0 | if (s != NULL) |
194 | 0 | *port_ptr = ntohs((unsigned short)s->s_port); |
195 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); |
196 | 0 | if (s == NULL) { |
197 | 0 | if (strcmp(str, "http") == 0) |
198 | 0 | *port_ptr = 80; |
199 | 0 | else if (strcmp(str, "telnet") == 0) |
200 | 0 | *port_ptr = 23; |
201 | 0 | else if (strcmp(str, "socks") == 0) |
202 | 0 | *port_ptr = 1080; |
203 | 0 | else if (strcmp(str, "https") == 0) |
204 | 0 | *port_ptr = 443; |
205 | 0 | else if (strcmp(str, "ssl") == 0) |
206 | 0 | *port_ptr = 443; |
207 | 0 | else if (strcmp(str, "ftp") == 0) |
208 | 0 | *port_ptr = 21; |
209 | 0 | else if (strcmp(str, "gopher") == 0) |
210 | 0 | *port_ptr = 70; |
211 | | # if 0 |
212 | | else if (strcmp(str, "wais") == 0) |
213 | | *port_ptr = 21; |
214 | | # endif |
215 | 0 | else { |
216 | 0 | SYSerr(SYS_F_GETSERVBYNAME, get_last_socket_error()); |
217 | 0 | ERR_add_error_data(3, "service='", str, "'"); |
218 | 0 | return (0); |
219 | 0 | } |
220 | 0 | } |
221 | 0 | } |
222 | 0 | return (1); |
223 | 0 | } |
224 | | |
225 | | int BIO_sock_error(int sock) |
226 | 0 | { |
227 | 0 | int j, i; |
228 | 0 | union { |
229 | 0 | size_t s; |
230 | 0 | int i; |
231 | 0 | } size; |
232 | |
|
233 | | # if defined(OPENSSL_SYS_BEOS_R5) |
234 | | return 0; |
235 | | # endif |
236 | | |
237 | | /* heuristic way to adapt for platforms that expect 64-bit optlen */ |
238 | 0 | size.s = 0, size.i = sizeof(j); |
239 | | /* |
240 | | * Note: under Windows the third parameter is of type (char *) whereas |
241 | | * under other systems it is (void *) if you don't have a cast it will |
242 | | * choke the compiler: if you do have a cast then you can either go for |
243 | | * (char *) or (void *). |
244 | | */ |
245 | 0 | i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, (void *)&size); |
246 | 0 | if (i < 0) |
247 | 0 | return (1); |
248 | 0 | else |
249 | 0 | return (j); |
250 | 0 | } |
251 | | |
252 | | # if 0 |
253 | | long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) |
254 | | { |
255 | | int i; |
256 | | char **p; |
257 | | |
258 | | switch (cmd) { |
259 | | case BIO_GHBN_CTRL_HITS: |
260 | | return (BIO_ghbn_hits); |
261 | | /* break; */ |
262 | | case BIO_GHBN_CTRL_MISSES: |
263 | | return (BIO_ghbn_miss); |
264 | | /* break; */ |
265 | | case BIO_GHBN_CTRL_CACHE_SIZE: |
266 | | return (GHBN_NUM); |
267 | | /* break; */ |
268 | | case BIO_GHBN_CTRL_GET_ENTRY: |
269 | | if ((iarg >= 0) && (iarg < GHBN_NUM) && (ghbn_cache[iarg].order > 0)) { |
270 | | p = (char **)parg; |
271 | | if (p == NULL) |
272 | | return (0); |
273 | | *p = ghbn_cache[iarg].name; |
274 | | ghbn_cache[iarg].name[128] = '\0'; |
275 | | return (1); |
276 | | } |
277 | | return (0); |
278 | | /* break; */ |
279 | | case BIO_GHBN_CTRL_FLUSH: |
280 | | for (i = 0; i < GHBN_NUM; i++) |
281 | | ghbn_cache[i].order = 0; |
282 | | break; |
283 | | default: |
284 | | return (0); |
285 | | } |
286 | | return (1); |
287 | | } |
288 | | # endif |
289 | | |
290 | | # if 0 |
291 | | static struct hostent *ghbn_dup(struct hostent *a) |
292 | | { |
293 | | struct hostent *ret; |
294 | | int i, j; |
295 | | |
296 | | MemCheck_off(); |
297 | | ret = (struct hostent *)OPENSSL_malloc(sizeof(struct hostent)); |
298 | | if (ret == NULL) |
299 | | return (NULL); |
300 | | memset(ret, 0, sizeof(struct hostent)); |
301 | | |
302 | | for (i = 0; a->h_aliases[i] != NULL; i++) ; |
303 | | i++; |
304 | | ret->h_aliases = (char **)OPENSSL_malloc(i * sizeof(char *)); |
305 | | if (ret->h_aliases == NULL) |
306 | | goto err; |
307 | | memset(ret->h_aliases, 0, i * sizeof(char *)); |
308 | | |
309 | | for (i = 0; a->h_addr_list[i] != NULL; i++) ; |
310 | | i++; |
311 | | ret->h_addr_list = (char **)OPENSSL_malloc(i * sizeof(char *)); |
312 | | if (ret->h_addr_list == NULL) |
313 | | goto err; |
314 | | memset(ret->h_addr_list, 0, i * sizeof(char *)); |
315 | | |
316 | | j = strlen(a->h_name) + 1; |
317 | | if ((ret->h_name = OPENSSL_malloc(j)) == NULL) |
318 | | goto err; |
319 | | memcpy((char *)ret->h_name, a->h_name, j); |
320 | | for (i = 0; a->h_aliases[i] != NULL; i++) { |
321 | | j = strlen(a->h_aliases[i]) + 1; |
322 | | if ((ret->h_aliases[i] = OPENSSL_malloc(j)) == NULL) |
323 | | goto err; |
324 | | memcpy(ret->h_aliases[i], a->h_aliases[i], j); |
325 | | } |
326 | | ret->h_length = a->h_length; |
327 | | ret->h_addrtype = a->h_addrtype; |
328 | | for (i = 0; a->h_addr_list[i] != NULL; i++) { |
329 | | if ((ret->h_addr_list[i] = OPENSSL_malloc(a->h_length)) == NULL) |
330 | | goto err; |
331 | | memcpy(ret->h_addr_list[i], a->h_addr_list[i], a->h_length); |
332 | | } |
333 | | if (0) { |
334 | | err: |
335 | | if (ret != NULL) |
336 | | ghbn_free(ret); |
337 | | ret = NULL; |
338 | | } |
339 | | MemCheck_on(); |
340 | | return (ret); |
341 | | } |
342 | | |
343 | | static void ghbn_free(struct hostent *a) |
344 | | { |
345 | | int i; |
346 | | |
347 | | if (a == NULL) |
348 | | return; |
349 | | |
350 | | if (a->h_aliases != NULL) { |
351 | | for (i = 0; a->h_aliases[i] != NULL; i++) |
352 | | OPENSSL_free(a->h_aliases[i]); |
353 | | OPENSSL_free(a->h_aliases); |
354 | | } |
355 | | if (a->h_addr_list != NULL) { |
356 | | for (i = 0; a->h_addr_list[i] != NULL; i++) |
357 | | OPENSSL_free(a->h_addr_list[i]); |
358 | | OPENSSL_free(a->h_addr_list); |
359 | | } |
360 | | if (a->h_name != NULL) |
361 | | OPENSSL_free(a->h_name); |
362 | | OPENSSL_free(a); |
363 | | } |
364 | | |
365 | | # endif |
366 | | |
367 | | struct hostent *BIO_gethostbyname(const char *name) |
368 | 0 | { |
369 | 0 | # if 1 |
370 | | /* |
371 | | * Caching gethostbyname() results forever is wrong, so we have to let |
372 | | * the true gethostbyname() worry about this |
373 | | */ |
374 | | # if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__)) |
375 | | return gethostbyname((char *)name); |
376 | | # else |
377 | 0 | return gethostbyname(name); |
378 | 0 | # endif |
379 | | # else |
380 | | struct hostent *ret; |
381 | | int i, lowi = 0, j; |
382 | | unsigned long low = (unsigned long)-1; |
383 | | |
384 | | # if 0 |
385 | | /* |
386 | | * It doesn't make sense to use locking here: The function interface is |
387 | | * not thread-safe, because threads can never be sure when some other |
388 | | * thread destroys the data they were given a pointer to. |
389 | | */ |
390 | | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); |
391 | | # endif |
392 | | j = strlen(name); |
393 | | if (j < 128) { |
394 | | for (i = 0; i < GHBN_NUM; i++) { |
395 | | if (low > ghbn_cache[i].order) { |
396 | | low = ghbn_cache[i].order; |
397 | | lowi = i; |
398 | | } |
399 | | if (ghbn_cache[i].order > 0) { |
400 | | if (strncmp(name, ghbn_cache[i].name, 128) == 0) |
401 | | break; |
402 | | } |
403 | | } |
404 | | } else |
405 | | i = GHBN_NUM; |
406 | | |
407 | | if (i == GHBN_NUM) { /* no hit */ |
408 | | BIO_ghbn_miss++; |
409 | | /* |
410 | | * Note: under VMS with SOCKETSHR, it seems like the first parameter |
411 | | * is 'char *', instead of 'const char *' |
412 | | */ |
413 | | # ifndef CONST_STRICT |
414 | | ret = gethostbyname((char *)name); |
415 | | # else |
416 | | ret = gethostbyname(name); |
417 | | # endif |
418 | | |
419 | | if (ret == NULL) |
420 | | goto end; |
421 | | if (j > 128) { /* too big to cache */ |
422 | | # if 0 |
423 | | /* |
424 | | * If we were trying to make this function thread-safe (which is |
425 | | * bound to fail), we'd have to give up in this case (or allocate |
426 | | * more memory). |
427 | | */ |
428 | | ret = NULL; |
429 | | # endif |
430 | | goto end; |
431 | | } |
432 | | |
433 | | /* else add to cache */ |
434 | | if (ghbn_cache[lowi].ent != NULL) |
435 | | ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ |
436 | | ghbn_cache[lowi].name[0] = '\0'; |
437 | | |
438 | | if ((ret = ghbn_cache[lowi].ent = ghbn_dup(ret)) == NULL) { |
439 | | BIOerr(BIO_F_BIO_GETHOSTBYNAME, ERR_R_MALLOC_FAILURE); |
440 | | goto end; |
441 | | } |
442 | | strncpy(ghbn_cache[lowi].name, name, 128); |
443 | | ghbn_cache[lowi].order = BIO_ghbn_miss + BIO_ghbn_hits; |
444 | | } else { |
445 | | BIO_ghbn_hits++; |
446 | | ret = ghbn_cache[i].ent; |
447 | | ghbn_cache[i].order = BIO_ghbn_miss + BIO_ghbn_hits; |
448 | | } |
449 | | end: |
450 | | # if 0 |
451 | | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); |
452 | | # endif |
453 | | return (ret); |
454 | | # endif |
455 | 0 | } |
456 | | |
457 | | int BIO_sock_init(void) |
458 | 0 | { |
459 | | # ifdef OPENSSL_SYS_WINDOWS |
460 | | static struct WSAData wsa_state; |
461 | | |
462 | | if (!wsa_init_done) { |
463 | | int err; |
464 | | |
465 | | wsa_init_done = 1; |
466 | | memset(&wsa_state, 0, sizeof(wsa_state)); |
467 | | /* |
468 | | * Not making wsa_state available to the rest of the code is formally |
469 | | * wrong. But the structures we use are [beleived to be] invariable |
470 | | * among Winsock DLLs, while API availability is [expected to be] |
471 | | * probed at run-time with DSO_global_lookup. |
472 | | */ |
473 | | if (WSAStartup(0x0202, &wsa_state) != 0) { |
474 | | err = WSAGetLastError(); |
475 | | SYSerr(SYS_F_WSASTARTUP, err); |
476 | | BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); |
477 | | return (-1); |
478 | | } |
479 | | } |
480 | | # endif /* OPENSSL_SYS_WINDOWS */ |
481 | | # ifdef WATT32 |
482 | | extern int _watt_do_exit; |
483 | | _watt_do_exit = 0; /* don't make sock_init() call exit() */ |
484 | | if (sock_init()) |
485 | | return (-1); |
486 | | # endif |
487 | |
|
488 | | # if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) |
489 | | WORD wVerReq; |
490 | | WSADATA wsaData; |
491 | | int err; |
492 | | |
493 | | if (!wsa_init_done) { |
494 | | wsa_init_done = 1; |
495 | | wVerReq = MAKEWORD(2, 0); |
496 | | err = WSAStartup(wVerReq, &wsaData); |
497 | | if (err != 0) { |
498 | | SYSerr(SYS_F_WSASTARTUP, err); |
499 | | BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); |
500 | | return (-1); |
501 | | } |
502 | | } |
503 | | # endif |
504 | |
|
505 | 0 | return (1); |
506 | 0 | } |
507 | | |
508 | | void BIO_sock_cleanup(void) |
509 | 0 | { |
510 | | # ifdef OPENSSL_SYS_WINDOWS |
511 | | if (wsa_init_done) { |
512 | | wsa_init_done = 0; |
513 | | # if 0 /* this call is claimed to be non-present in |
514 | | * Winsock2 */ |
515 | | WSACancelBlockingCall(); |
516 | | # endif |
517 | | WSACleanup(); |
518 | | } |
519 | | # elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) |
520 | | if (wsa_init_done) { |
521 | | wsa_init_done = 0; |
522 | | WSACleanup(); |
523 | | } |
524 | | # endif |
525 | 0 | } |
526 | | |
527 | | # if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 |
528 | | |
529 | | int BIO_socket_ioctl(int fd, long type, void *arg) |
530 | 0 | { |
531 | 0 | int i; |
532 | |
|
533 | | # ifdef __DJGPP__ |
534 | | i = ioctlsocket(fd, type, (char *)arg); |
535 | | # else |
536 | | # if defined(OPENSSL_SYS_VMS) |
537 | | /*- |
538 | | * 2011-02-18 SMS. |
539 | | * VMS ioctl() can't tolerate a 64-bit "void *arg", but we |
540 | | * observe that all the consumers pass in an "unsigned long *", |
541 | | * so we arrange a local copy with a short pointer, and use |
542 | | * that, instead. |
543 | | */ |
544 | | # if __INITIAL_POINTER_SIZE == 64 |
545 | | # define ARG arg_32p |
546 | | # pragma pointer_size save |
547 | | # pragma pointer_size 32 |
548 | | unsigned long arg_32; |
549 | | unsigned long *arg_32p; |
550 | | # pragma pointer_size restore |
551 | | arg_32p = &arg_32; |
552 | | arg_32 = *((unsigned long *)arg); |
553 | | # else /* __INITIAL_POINTER_SIZE == 64 */ |
554 | | # define ARG arg |
555 | | # endif /* __INITIAL_POINTER_SIZE == 64 [else] */ |
556 | | # else /* defined(OPENSSL_SYS_VMS) */ |
557 | 0 | # define ARG arg |
558 | 0 | # endif /* defined(OPENSSL_SYS_VMS) [else] */ |
559 | |
|
560 | 0 | i = ioctlsocket(fd, type, ARG); |
561 | 0 | # endif /* __DJGPP__ */ |
562 | 0 | if (i < 0) |
563 | 0 | SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); |
564 | 0 | return (i); |
565 | 0 | } |
566 | | # endif /* __VMS_VER */ |
567 | | |
568 | | /* |
569 | | * The reason I have implemented this instead of using sscanf is because |
570 | | * Visual C 1.52c gives an unresolved external when linking a DLL :-( |
571 | | */ |
572 | | static int get_ip(const char *str, unsigned char ip[4]) |
573 | 0 | { |
574 | 0 | unsigned int tmp[4]; |
575 | 0 | int num = 0, c, ok = 0; |
576 | |
|
577 | 0 | tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; |
578 | |
|
579 | 0 | for (;;) { |
580 | 0 | c = *(str++); |
581 | 0 | if ((c >= '0') && (c <= '9')) { |
582 | 0 | ok = 1; |
583 | 0 | tmp[num] = tmp[num] * 10 + c - '0'; |
584 | 0 | if (tmp[num] > 255) |
585 | 0 | return (0); |
586 | 0 | } else if (c == '.') { |
587 | 0 | if (!ok) |
588 | 0 | return (-1); |
589 | 0 | if (num == 3) |
590 | 0 | return (0); |
591 | 0 | num++; |
592 | 0 | ok = 0; |
593 | 0 | } else if (c == '\0' && (num == 3) && ok) |
594 | 0 | break; |
595 | 0 | else |
596 | 0 | return (0); |
597 | 0 | } |
598 | 0 | ip[0] = tmp[0]; |
599 | 0 | ip[1] = tmp[1]; |
600 | 0 | ip[2] = tmp[2]; |
601 | 0 | ip[3] = tmp[3]; |
602 | 0 | return (1); |
603 | 0 | } |
604 | | |
605 | | int BIO_get_accept_socket(char *host, int bind_mode) |
606 | 0 | { |
607 | 0 | int ret = 0; |
608 | 0 | union { |
609 | 0 | struct sockaddr sa; |
610 | 0 | struct sockaddr_in sa_in; |
611 | 0 | # if OPENSSL_USE_IPV6 |
612 | 0 | struct sockaddr_in6 sa_in6; |
613 | 0 | # endif |
614 | 0 | } server, client; |
615 | 0 | int s = INVALID_SOCKET, cs, addrlen; |
616 | 0 | unsigned char ip[4]; |
617 | 0 | unsigned short port; |
618 | 0 | char *str = NULL, *e; |
619 | 0 | char *h, *p; |
620 | 0 | unsigned long l; |
621 | 0 | int err_num; |
622 | |
|
623 | 0 | if (BIO_sock_init() != 1) |
624 | 0 | return (INVALID_SOCKET); |
625 | | |
626 | 0 | if ((str = BUF_strdup(host)) == NULL) |
627 | 0 | return (INVALID_SOCKET); |
628 | | |
629 | 0 | h = p = NULL; |
630 | 0 | h = str; |
631 | 0 | for (e = str; *e; e++) { |
632 | 0 | if (*e == ':') { |
633 | 0 | p = e; |
634 | 0 | } else if (*e == '/') { |
635 | 0 | *e = '\0'; |
636 | 0 | break; |
637 | 0 | } |
638 | 0 | } |
639 | 0 | if (p) |
640 | 0 | *p++ = '\0'; /* points at last ':', '::port' is special |
641 | | * [see below] */ |
642 | 0 | else |
643 | 0 | p = h, h = NULL; |
644 | |
|
645 | 0 | # ifdef EAI_FAMILY |
646 | 0 | do { |
647 | 0 | static union { |
648 | 0 | void *p; |
649 | 0 | int (WSAAPI *f) (const char *, const char *, |
650 | 0 | const struct addrinfo *, struct addrinfo **); |
651 | 0 | } p_getaddrinfo = { |
652 | 0 | NULL |
653 | 0 | }; |
654 | 0 | static union { |
655 | 0 | void *p; |
656 | 0 | void (WSAAPI *f) (struct addrinfo *); |
657 | 0 | } p_freeaddrinfo = { |
658 | 0 | NULL |
659 | 0 | }; |
660 | 0 | struct addrinfo *res, hint; |
661 | |
|
662 | 0 | if (p_getaddrinfo.p == NULL) { |
663 | 0 | if ((p_getaddrinfo.p = DSO_global_lookup("getaddrinfo")) == NULL |
664 | 0 | || (p_freeaddrinfo.p = |
665 | 0 | DSO_global_lookup("freeaddrinfo")) == NULL) |
666 | 0 | p_getaddrinfo.p = (void *)-1; |
667 | 0 | } |
668 | 0 | if (p_getaddrinfo.p == (void *)-1) |
669 | 0 | break; |
670 | | |
671 | | /* |
672 | | * '::port' enforces IPv6 wildcard listener. Some OSes, e.g. Solaris, |
673 | | * default to IPv6 without any hint. Also note that commonly IPv6 |
674 | | * wildchard socket can service IPv4 connections just as well... |
675 | | */ |
676 | 0 | memset(&hint, 0, sizeof(hint)); |
677 | 0 | hint.ai_flags = AI_PASSIVE; |
678 | 0 | if (h) { |
679 | 0 | if (strchr(h, ':')) { |
680 | 0 | if (h[1] == '\0') |
681 | 0 | h = NULL; |
682 | 0 | # if OPENSSL_USE_IPV6 |
683 | 0 | hint.ai_family = AF_INET6; |
684 | | # else |
685 | | h = NULL; |
686 | | # endif |
687 | 0 | } else if (h[0] == '*' && h[1] == '\0') { |
688 | 0 | hint.ai_family = AF_INET; |
689 | 0 | h = NULL; |
690 | 0 | } |
691 | 0 | } |
692 | |
|
693 | 0 | if ((*p_getaddrinfo.f) (h, p, &hint, &res)) |
694 | 0 | break; |
695 | | |
696 | 0 | addrlen = res->ai_addrlen <= sizeof(server) ? |
697 | 0 | res->ai_addrlen : sizeof(server); |
698 | 0 | memcpy(&server, res->ai_addr, addrlen); |
699 | |
|
700 | 0 | (*p_freeaddrinfo.f) (res); |
701 | 0 | goto again; |
702 | 0 | } while (0); |
703 | 0 | # endif |
704 | | |
705 | 0 | if (!BIO_get_port(p, &port)) |
706 | 0 | goto err; |
707 | | |
708 | 0 | memset((char *)&server, 0, sizeof(server)); |
709 | 0 | server.sa_in.sin_family = AF_INET; |
710 | 0 | server.sa_in.sin_port = htons(port); |
711 | 0 | addrlen = sizeof(server.sa_in); |
712 | |
|
713 | 0 | if (h == NULL || strcmp(h, "*") == 0) |
714 | 0 | server.sa_in.sin_addr.s_addr = INADDR_ANY; |
715 | 0 | else { |
716 | 0 | if (!BIO_get_host_ip(h, &(ip[0]))) |
717 | 0 | goto err; |
718 | 0 | l = (unsigned long) |
719 | 0 | ((unsigned long)ip[0] << 24L) | |
720 | 0 | ((unsigned long)ip[1] << 16L) | |
721 | 0 | ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]); |
722 | 0 | server.sa_in.sin_addr.s_addr = htonl(l); |
723 | 0 | } |
724 | | |
725 | 0 | again: |
726 | 0 | s = socket(server.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL); |
727 | 0 | if (s == INVALID_SOCKET) { |
728 | 0 | SYSerr(SYS_F_SOCKET, get_last_socket_error()); |
729 | 0 | ERR_add_error_data(3, "port='", host, "'"); |
730 | 0 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); |
731 | 0 | goto err; |
732 | 0 | } |
733 | 0 | # ifdef SO_REUSEADDR |
734 | 0 | if (bind_mode == BIO_BIND_REUSEADDR) { |
735 | 0 | int i = 1; |
736 | |
|
737 | 0 | ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)); |
738 | 0 | bind_mode = BIO_BIND_NORMAL; |
739 | 0 | } |
740 | 0 | # endif |
741 | 0 | if (bind(s, &server.sa, addrlen) == -1) { |
742 | 0 | # ifdef SO_REUSEADDR |
743 | 0 | err_num = get_last_socket_error(); |
744 | 0 | if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && |
745 | | # ifdef OPENSSL_SYS_WINDOWS |
746 | | /* |
747 | | * Some versions of Windows define EADDRINUSE to a dummy value. |
748 | | */ |
749 | | (err_num == WSAEADDRINUSE)) |
750 | | # else |
751 | 0 | (err_num == EADDRINUSE)) |
752 | 0 | # endif |
753 | 0 | { |
754 | 0 | client = server; |
755 | 0 | if (h == NULL || strcmp(h, "*") == 0) { |
756 | 0 | # if OPENSSL_USE_IPV6 |
757 | 0 | if (client.sa.sa_family == AF_INET6) { |
758 | 0 | memset(&client.sa_in6.sin6_addr, 0, |
759 | 0 | sizeof(client.sa_in6.sin6_addr)); |
760 | 0 | client.sa_in6.sin6_addr.s6_addr[15] = 1; |
761 | 0 | } else |
762 | 0 | # endif |
763 | 0 | if (client.sa.sa_family == AF_INET) { |
764 | 0 | client.sa_in.sin_addr.s_addr = htonl(0x7F000001); |
765 | 0 | } else |
766 | 0 | goto err; |
767 | 0 | } |
768 | 0 | cs = socket(client.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL); |
769 | 0 | if (cs != INVALID_SOCKET) { |
770 | 0 | int ii; |
771 | 0 | ii = connect(cs, &client.sa, addrlen); |
772 | 0 | closesocket(cs); |
773 | 0 | if (ii == INVALID_SOCKET) { |
774 | 0 | bind_mode = BIO_BIND_REUSEADDR; |
775 | 0 | closesocket(s); |
776 | 0 | goto again; |
777 | 0 | } |
778 | | /* else error */ |
779 | 0 | } |
780 | | /* else error */ |
781 | 0 | } |
782 | 0 | # endif |
783 | 0 | SYSerr(SYS_F_BIND, err_num); |
784 | 0 | ERR_add_error_data(3, "port='", host, "'"); |
785 | 0 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_BIND_SOCKET); |
786 | 0 | goto err; |
787 | 0 | } |
788 | 0 | if (listen(s, MAX_LISTEN) == -1) { |
789 | 0 | SYSerr(SYS_F_BIND, get_last_socket_error()); |
790 | 0 | ERR_add_error_data(3, "port='", host, "'"); |
791 | 0 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_LISTEN_SOCKET); |
792 | 0 | goto err; |
793 | 0 | } |
794 | 0 | ret = 1; |
795 | 0 | err: |
796 | 0 | if (str != NULL) |
797 | 0 | OPENSSL_free(str); |
798 | 0 | if ((ret == 0) && (s != INVALID_SOCKET)) { |
799 | 0 | closesocket(s); |
800 | 0 | s = INVALID_SOCKET; |
801 | 0 | } |
802 | 0 | return (s); |
803 | 0 | } |
804 | | |
805 | | int BIO_accept(int sock, char **addr) |
806 | 0 | { |
807 | 0 | int ret = INVALID_SOCKET; |
808 | 0 | unsigned long l; |
809 | 0 | unsigned short port; |
810 | 0 | char *p; |
811 | |
|
812 | 0 | struct { |
813 | | /* |
814 | | * As for following union. Trouble is that there are platforms |
815 | | * that have socklen_t and there are platforms that don't, on |
816 | | * some platforms socklen_t is int and on some size_t. So what |
817 | | * one can do? One can cook #ifdef spaghetti, which is nothing |
818 | | * but masochistic. Or one can do union between int and size_t. |
819 | | * One naturally does it primarily for 64-bit platforms where |
820 | | * sizeof(int) != sizeof(size_t). But would it work? Note that |
821 | | * if size_t member is initialized to 0, then later int member |
822 | | * assignment naturally does the job on little-endian platforms |
823 | | * regardless accept's expectations! What about big-endians? |
824 | | * If accept expects int*, then it works, and if size_t*, then |
825 | | * length value would appear as unreasonably large. But this |
826 | | * won't prevent it from filling in the address structure. The |
827 | | * trouble of course would be if accept returns more data than |
828 | | * actual buffer can accomodate and overwrite stack... That's |
829 | | * where early OPENSSL_assert comes into picture. Besides, the |
830 | | * only 64-bit big-endian platform found so far that expects |
831 | | * size_t* is HP-UX, where stack grows towards higher address. |
832 | | * <appro> |
833 | | */ |
834 | 0 | union { |
835 | 0 | size_t s; |
836 | 0 | int i; |
837 | 0 | } len; |
838 | 0 | union { |
839 | 0 | struct sockaddr sa; |
840 | 0 | struct sockaddr_in sa_in; |
841 | 0 | # if OPENSSL_USE_IPV6 |
842 | 0 | struct sockaddr_in6 sa_in6; |
843 | 0 | # endif |
844 | 0 | } from; |
845 | 0 | } sa; |
846 | |
|
847 | 0 | sa.len.s = 0; |
848 | 0 | sa.len.i = sizeof(sa.from); |
849 | 0 | memset(&sa.from, 0, sizeof(sa.from)); |
850 | 0 | ret = accept(sock, &sa.from.sa, (void *)&sa.len); |
851 | 0 | if (sizeof(sa.len.i) != sizeof(sa.len.s) && sa.len.i == 0) { |
852 | 0 | OPENSSL_assert(sa.len.s <= sizeof(sa.from)); |
853 | 0 | sa.len.i = (int)sa.len.s; |
854 | | /* use sa.len.i from this point */ |
855 | 0 | } |
856 | 0 | if (ret == INVALID_SOCKET) { |
857 | 0 | if (BIO_sock_should_retry(ret)) |
858 | 0 | return -2; |
859 | 0 | SYSerr(SYS_F_ACCEPT, get_last_socket_error()); |
860 | 0 | BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); |
861 | 0 | goto end; |
862 | 0 | } |
863 | | |
864 | 0 | if (addr == NULL) |
865 | 0 | goto end; |
866 | | |
867 | 0 | # ifdef EAI_FAMILY |
868 | 0 | do { |
869 | 0 | char h[NI_MAXHOST], s[NI_MAXSERV]; |
870 | 0 | size_t nl; |
871 | 0 | static union { |
872 | 0 | void *p; |
873 | 0 | int (WSAAPI *f) (const struct sockaddr *, size_t /* socklen_t */ , |
874 | 0 | char *, size_t, char *, size_t, int); |
875 | 0 | } p_getnameinfo = { |
876 | 0 | NULL |
877 | 0 | }; |
878 | | /* |
879 | | * 2nd argument to getnameinfo is specified to be socklen_t. |
880 | | * Unfortunately there is a number of environments where socklen_t is |
881 | | * not defined. As it's passed by value, it's safe to pass it as |
882 | | * size_t... <appro> |
883 | | */ |
884 | |
|
885 | 0 | if (p_getnameinfo.p == NULL) { |
886 | 0 | if ((p_getnameinfo.p = DSO_global_lookup("getnameinfo")) == NULL) |
887 | 0 | p_getnameinfo.p = (void *)-1; |
888 | 0 | } |
889 | 0 | if (p_getnameinfo.p == (void *)-1) |
890 | 0 | break; |
891 | | |
892 | 0 | if ((*p_getnameinfo.f) (&sa.from.sa, sa.len.i, h, sizeof(h), s, |
893 | 0 | sizeof(s), NI_NUMERICHOST | NI_NUMERICSERV)) |
894 | 0 | break; |
895 | 0 | nl = strlen(h) + strlen(s) + 2; |
896 | 0 | p = *addr; |
897 | 0 | if (p) { |
898 | 0 | *p = '\0'; |
899 | 0 | p = OPENSSL_realloc(p, nl); |
900 | 0 | } else { |
901 | 0 | p = OPENSSL_malloc(nl); |
902 | 0 | } |
903 | 0 | if (p == NULL) { |
904 | 0 | BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); |
905 | 0 | goto end; |
906 | 0 | } |
907 | 0 | *addr = p; |
908 | 0 | BIO_snprintf(*addr, nl, "%s:%s", h, s); |
909 | 0 | goto end; |
910 | 0 | } while (0); |
911 | 0 | # endif |
912 | 0 | if (sa.from.sa.sa_family != AF_INET) |
913 | 0 | goto end; |
914 | 0 | l = ntohl(sa.from.sa_in.sin_addr.s_addr); |
915 | 0 | port = ntohs(sa.from.sa_in.sin_port); |
916 | 0 | if (*addr == NULL) { |
917 | 0 | if ((p = OPENSSL_malloc(24)) == NULL) { |
918 | 0 | BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); |
919 | 0 | goto end; |
920 | 0 | } |
921 | 0 | *addr = p; |
922 | 0 | } |
923 | 0 | BIO_snprintf(*addr, 24, "%d.%d.%d.%d:%d", |
924 | 0 | (unsigned char)(l >> 24L) & 0xff, |
925 | 0 | (unsigned char)(l >> 16L) & 0xff, |
926 | 0 | (unsigned char)(l >> 8L) & 0xff, |
927 | 0 | (unsigned char)(l) & 0xff, port); |
928 | 0 | end: |
929 | 0 | return (ret); |
930 | 0 | } |
931 | | |
932 | | int BIO_set_tcp_ndelay(int s, int on) |
933 | 0 | { |
934 | 0 | int ret = 0; |
935 | | # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) |
936 | | int opt; |
937 | | |
938 | | # ifdef SOL_TCP |
939 | | opt = SOL_TCP; |
940 | | # else |
941 | | # ifdef IPPROTO_TCP |
942 | | opt = IPPROTO_TCP; |
943 | | # endif |
944 | | # endif |
945 | | |
946 | | ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); |
947 | | # endif |
948 | 0 | return (ret == 0); |
949 | 0 | } |
950 | | |
951 | | int BIO_socket_nbio(int s, int mode) |
952 | 0 | { |
953 | 0 | int ret = -1; |
954 | 0 | int l; |
955 | |
|
956 | 0 | l = mode; |
957 | 0 | # ifdef FIONBIO |
958 | 0 | ret = BIO_socket_ioctl(s, FIONBIO, &l); |
959 | 0 | # endif |
960 | 0 | return (ret == 0); |
961 | 0 | } |
962 | | #endif |