xref: /freebsd/crypto/openssl/crypto/bio/bio_sock.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
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
8  */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include "bio_local.h"
13 
14 #ifndef OPENSSL_NO_SOCK
15 #define SOCKET_PROTOCOL IPPROTO_TCP
16 #ifdef SO_MAXCONN
17 #define MAX_LISTEN SO_MAXCONN
18 #elif defined(SOMAXCONN)
19 #define MAX_LISTEN SOMAXCONN
20 #else
21 #define MAX_LISTEN 32
22 #endif
23 #if defined(OPENSSL_SYS_WINDOWS)
24 static int wsa_init_done = 0;
25 #endif
26 
27 #if defined __TANDEM
28 #include <unistd.h>
29 #include <sys/time.h> /* select */
30 #elif defined _WIN32
31 #include <winsock.h> /* for type fd_set */
32 #else
33 #include <unistd.h>
34 #if defined __VMS
35 #include <sys/socket.h>
36 #elif defined _HPUX_SOURCE
37 #include <sys/time.h>
38 #else
39 #include <sys/select.h>
40 #endif
41 #endif
42 #include "internal/sockets.h" /* for openssl_fdset() */
43 
44 #ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_get_host_ip(const char * str,unsigned char * ip)45 int BIO_get_host_ip(const char *str, unsigned char *ip)
46 {
47     BIO_ADDRINFO *res = NULL;
48     int ret = 0;
49 
50     if (BIO_sock_init() != 1)
51         return 0; /* don't generate another error code here */
52 
53     if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
54         size_t l;
55 
56         if (BIO_ADDRINFO_family(res) != AF_INET) {
57             ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
58         } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
59             /*
60              * Because only AF_INET addresses will reach this far, we can assert
61              * that l should be 4
62              */
63             if (ossl_assert(l == 4))
64                 ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
65         }
66         BIO_ADDRINFO_free(res);
67     } else {
68         ERR_add_error_data(2, "host=", str);
69     }
70 
71     return ret;
72 }
73 
BIO_get_port(const char * str,unsigned short * port_ptr)74 int BIO_get_port(const char *str, unsigned short *port_ptr)
75 {
76     BIO_ADDRINFO *res = NULL;
77     int ret = 0;
78 
79     if (str == NULL) {
80         ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED);
81         return 0;
82     }
83 
84     if (BIO_sock_init() != 1)
85         return 0; /* don't generate another error code here */
86 
87     if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
88         if (BIO_ADDRINFO_family(res) != AF_INET) {
89             ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
90         } else {
91             *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
92             ret = 1;
93         }
94         BIO_ADDRINFO_free(res);
95     } else {
96         ERR_add_error_data(2, "host=", str);
97     }
98 
99     return ret;
100 }
101 #endif
102 
BIO_sock_error(int sock)103 int BIO_sock_error(int sock)
104 {
105     int j = 0, i;
106     socklen_t size = sizeof(j);
107 
108     /*
109      * Note: under Windows the third parameter is of type (char *) whereas
110      * under other systems it is (void *) if you don't have a cast it will
111      * choke the compiler: if you do have a cast then you can either go for
112      * (char *) or (void *).
113      */
114     i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
115     if (i < 0)
116         return get_last_socket_error();
117     else
118         return j;
119 }
120 
121 #ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_gethostbyname(const char * name)122 struct hostent *BIO_gethostbyname(const char *name)
123 {
124     /*
125      * Caching gethostbyname() results forever is wrong, so we have to let
126      * the true gethostbyname() worry about this
127      */
128     return gethostbyname(name);
129 }
130 #endif
131 
132 #ifdef BIO_HAVE_WSAMSG
133 LPFN_WSARECVMSG bio_WSARecvMsg;
134 LPFN_WSASENDMSG bio_WSASendMsg;
135 #endif
136 
BIO_sock_init(void)137 int BIO_sock_init(void)
138 {
139 #ifdef OPENSSL_SYS_WINDOWS
140     static struct WSAData wsa_state;
141 
142     if (!wsa_init_done) {
143         wsa_init_done = 1;
144         memset(&wsa_state, 0, sizeof(wsa_state));
145         /*
146          * Not making wsa_state available to the rest of the code is formally
147          * wrong. But the structures we use are [believed to be] invariable
148          * among Winsock DLLs, while API availability is [expected to be]
149          * probed at run-time with DSO_global_lookup.
150          */
151         if (WSAStartup(0x0202, &wsa_state) != 0) {
152             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
153                 "calling wsastartup()");
154             ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP);
155             return -1;
156         }
157 
158         /*
159          * On Windows, some socket functions are not exposed as a prototype.
160          * Instead, their function pointers must be loaded via this elaborate
161          * process...
162          */
163 #ifdef BIO_HAVE_WSAMSG
164         {
165             GUID id_WSARecvMsg = WSAID_WSARECVMSG;
166             GUID id_WSASendMsg = WSAID_WSASENDMSG;
167             DWORD len_out = 0;
168             SOCKET s;
169 
170             s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
171             if (s != INVALID_SOCKET) {
172                 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
173                         &id_WSARecvMsg, sizeof(id_WSARecvMsg),
174                         &bio_WSARecvMsg, sizeof(bio_WSARecvMsg),
175                         &len_out, NULL, NULL)
176                         != 0
177                     || len_out != sizeof(bio_WSARecvMsg))
178                     bio_WSARecvMsg = NULL;
179 
180                 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
181                         &id_WSASendMsg, sizeof(id_WSASendMsg),
182                         &bio_WSASendMsg, sizeof(bio_WSASendMsg),
183                         &len_out, NULL, NULL)
184                         != 0
185                     || len_out != sizeof(bio_WSASendMsg))
186                     bio_WSASendMsg = NULL;
187 
188                 closesocket(s);
189             }
190         }
191 #endif
192     }
193 #endif /* OPENSSL_SYS_WINDOWS */
194 #ifdef WATT32
195     extern int _watt_do_exit;
196     _watt_do_exit = 0; /* don't make sock_init() call exit() */
197     if (sock_init())
198         return -1;
199 #endif
200 
201     return 1;
202 }
203 
bio_sock_cleanup_int(void)204 void bio_sock_cleanup_int(void)
205 {
206 #ifdef OPENSSL_SYS_WINDOWS
207     if (wsa_init_done) {
208         wsa_init_done = 0;
209         WSACleanup();
210     }
211 #endif
212 }
213 
BIO_socket_ioctl(int fd,long type,void * arg)214 int BIO_socket_ioctl(int fd, long type, void *arg)
215 {
216     int i;
217 
218 #ifdef __DJGPP__
219     i = ioctlsocket(fd, type, (char *)arg);
220 #else
221 #if defined(OPENSSL_SYS_VMS)
222     /*-
223      * 2011-02-18 SMS.
224      * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
225      * observe that all the consumers pass in an "unsigned long *",
226      * so we arrange a local copy with a short pointer, and use
227      * that, instead.
228      */
229 #if __INITIAL_POINTER_SIZE == 64
230 #define ARG arg_32p
231 #pragma pointer_size save
232 #pragma pointer_size 32
233     unsigned long arg_32;
234     unsigned long *arg_32p;
235 #pragma pointer_size restore
236     arg_32p = &arg_32;
237     arg_32 = *((unsigned long *)arg);
238 #else /* __INITIAL_POINTER_SIZE == 64 */
239 #define ARG arg
240 #endif /* __INITIAL_POINTER_SIZE == 64 [else] */
241 #else /* defined(OPENSSL_SYS_VMS) */
242 #define ARG arg
243 #endif /* defined(OPENSSL_SYS_VMS) [else] */
244 
245     i = ioctlsocket(fd, type, ARG);
246 #endif /* __DJGPP__ */
247     if (i < 0)
248         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
249             "calling ioctlsocket()");
250     return i;
251 }
252 
253 #ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_get_accept_socket(char * host,int bind_mode)254 int BIO_get_accept_socket(char *host, int bind_mode)
255 {
256     int s = INVALID_SOCKET;
257     char *h = NULL, *p = NULL;
258     BIO_ADDRINFO *res = NULL;
259 
260     if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
261         return INVALID_SOCKET;
262 
263     if (BIO_sock_init() != 1)
264         goto err;
265 
266     if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) == 0)
267         goto err;
268 
269     if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
270              BIO_ADDRINFO_protocol(res), 0))
271         == INVALID_SOCKET) {
272         s = INVALID_SOCKET;
273         goto err;
274     }
275 
276     if (!BIO_listen(s, BIO_ADDRINFO_address(res),
277             bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
278         BIO_closesocket(s);
279         s = INVALID_SOCKET;
280     }
281 
282 err:
283     BIO_ADDRINFO_free(res);
284     OPENSSL_free(h);
285     OPENSSL_free(p);
286 
287     return s;
288 }
289 
BIO_accept(int sock,char ** ip_port)290 int BIO_accept(int sock, char **ip_port)
291 {
292     BIO_ADDR res;
293     int ret = -1;
294 
295     ret = BIO_accept_ex(sock, &res, 0);
296     if (ret == (int)INVALID_SOCKET) {
297         if (BIO_sock_should_retry(ret)) {
298             ret = -2;
299             goto end;
300         }
301         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
302             "calling accept()");
303         ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
304         goto end;
305     }
306 
307     if (ip_port != NULL) {
308         char *host = BIO_ADDR_hostname_string(&res, 1);
309         char *port = BIO_ADDR_service_string(&res, 1);
310         if (host != NULL && port != NULL) {
311             *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
312         } else {
313             *ip_port = NULL;
314             ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
315         }
316 
317         if (*ip_port == NULL) {
318             BIO_closesocket(ret);
319             ret = (int)INVALID_SOCKET;
320         } else {
321             strcpy(*ip_port, host);
322             strcat(*ip_port, ":");
323             strcat(*ip_port, port);
324         }
325         OPENSSL_free(host);
326         OPENSSL_free(port);
327     }
328 
329 end:
330     return ret;
331 }
332 #endif
333 
BIO_set_tcp_ndelay(int s,int on)334 int BIO_set_tcp_ndelay(int s, int on)
335 {
336     int ret = 0;
337 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
338     int opt;
339 
340 #ifdef SOL_TCP
341     opt = SOL_TCP;
342 #else
343 #ifdef IPPROTO_TCP
344     opt = IPPROTO_TCP;
345 #endif
346 #endif
347 
348     ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
349 #endif
350     return (ret == 0);
351 }
352 
BIO_socket_nbio(int s,int mode)353 int BIO_socket_nbio(int s, int mode)
354 {
355     int ret = -1;
356     int l;
357 
358     l = mode;
359 #ifdef FIONBIO
360     l = mode;
361 
362     ret = BIO_socket_ioctl(s, FIONBIO, &l);
363 #elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
364     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
365 
366     l = fcntl(s, F_GETFL, 0);
367     if (l == -1) {
368         ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
369             "calling fcntl()");
370         ret = -1;
371     } else {
372 #if defined(O_NONBLOCK)
373         l &= ~O_NONBLOCK;
374 #else
375         l &= ~FNDELAY; /* BSD4.x */
376 #endif
377         if (mode) {
378 #if defined(O_NONBLOCK)
379             l |= O_NONBLOCK;
380 #else
381             l |= FNDELAY; /* BSD4.x */
382 #endif
383         }
384         ret = fcntl(s, F_SETFL, l);
385 
386         if (ret < 0) {
387             ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
388                 "calling fcntl()");
389         }
390     }
391 #else
392     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
393     ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
394 #endif
395 
396     return (ret == 0);
397 }
398 
BIO_sock_info(int sock,enum BIO_sock_info_type type,union BIO_sock_info_u * info)399 int BIO_sock_info(int sock,
400     enum BIO_sock_info_type type, union BIO_sock_info_u *info)
401 {
402     switch (type) {
403     case BIO_SOCK_INFO_ADDRESS: {
404         socklen_t addr_len;
405         int ret = 0;
406         addr_len = sizeof(*info->addr);
407         ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
408             &addr_len);
409         if (ret == -1) {
410             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
411                 "calling getsockname()");
412             ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR);
413             return 0;
414         }
415         if ((size_t)addr_len > sizeof(*info->addr)) {
416             ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
417             return 0;
418         }
419     } break;
420     default:
421         ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE);
422         return 0;
423     }
424     return 1;
425 }
426 
427 /*
428  * Wait on fd at most until max_time; succeed immediately if max_time == 0.
429  * If for_read == 0 then assume to wait for writing, else wait for reading.
430  * Returns -1 on error, 0 on timeout, and 1 on success.
431  */
BIO_socket_wait(int fd,int for_read,time_t max_time)432 int BIO_socket_wait(int fd, int for_read, time_t max_time)
433 {
434 #if defined(OPENSSL_SYS_WINDOWS) || !defined(POLLIN)
435     fd_set confds;
436     struct timeval tv;
437     time_t now;
438 
439 #ifdef _WIN32
440     if ((SOCKET)fd == INVALID_SOCKET)
441 #else
442     if (fd < 0 || fd >= FD_SETSIZE)
443 #endif
444         return -1;
445     if (max_time == 0)
446         return 1;
447 
448     now = time(NULL);
449     if (max_time < now)
450         return 0;
451 
452     FD_ZERO(&confds);
453     openssl_fdset(fd, &confds);
454     tv.tv_usec = 0;
455     tv.tv_sec = (long)(max_time - now); /* might overflow */
456     return select(fd + 1, for_read ? &confds : NULL,
457         for_read ? NULL : &confds, NULL, &tv);
458 #else
459     struct pollfd confds;
460     time_t now;
461 
462     if (fd < 0)
463         return -1;
464     if (max_time == 0)
465         return 1;
466 
467     now = time(NULL);
468     if (max_time < now)
469         return 0;
470 
471     confds.fd = fd;
472     confds.events = for_read ? POLLIN : POLLOUT;
473     return poll(&confds, 1, (int)(max_time - now) * 1000);
474 #endif
475 }
476 #endif /* !defined(OPENSSL_NO_SOCK) */
477