xref: /openssl/crypto/bio/bio_sock.c (revision 38e8392b)
1 /*
2  * Copyright 1995-2024 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) != 0
176                     || len_out != sizeof(bio_WSARecvMsg))
177                     bio_WSARecvMsg = NULL;
178 
179                 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
180                              &id_WSASendMsg, sizeof(id_WSASendMsg),
181                              &bio_WSASendMsg, sizeof(bio_WSASendMsg),
182                              &len_out, NULL, NULL) != 0
183                     || len_out != sizeof(bio_WSASendMsg))
184                     bio_WSASendMsg = NULL;
185 
186                 closesocket(s);
187             }
188         }
189 #  endif
190     }
191 # endif                         /* OPENSSL_SYS_WINDOWS */
192 # ifdef WATT32
193     extern int _watt_do_exit;
194     _watt_do_exit = 0;          /* don't make sock_init() call exit() */
195     if (sock_init())
196         return -1;
197 # endif
198 
199     return 1;
200 }
201 
bio_sock_cleanup_int(void)202 void bio_sock_cleanup_int(void)
203 {
204 # ifdef OPENSSL_SYS_WINDOWS
205     if (wsa_init_done) {
206         wsa_init_done = 0;
207         WSACleanup();
208     }
209 # endif
210 }
211 
BIO_socket_ioctl(int fd,long type,void * arg)212 int BIO_socket_ioctl(int fd, long type, void *arg)
213 {
214     int i;
215 
216 #  ifdef __DJGPP__
217     i = ioctlsocket(fd, type, (char *)arg);
218 #  else
219 #   if defined(OPENSSL_SYS_VMS)
220     /*-
221      * 2011-02-18 SMS.
222      * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
223      * observe that all the consumers pass in an "unsigned long *",
224      * so we arrange a local copy with a short pointer, and use
225      * that, instead.
226      */
227 #    if __INITIAL_POINTER_SIZE == 64
228 #     define ARG arg_32p
229 #     pragma pointer_size save
230 #     pragma pointer_size 32
231     unsigned long arg_32;
232     unsigned long *arg_32p;
233 #     pragma pointer_size restore
234     arg_32p = &arg_32;
235     arg_32 = *((unsigned long *)arg);
236 #    else                       /* __INITIAL_POINTER_SIZE == 64 */
237 #     define ARG arg
238 #    endif                      /* __INITIAL_POINTER_SIZE == 64 [else] */
239 #   else                        /* defined(OPENSSL_SYS_VMS) */
240 #    define ARG arg
241 #   endif                       /* defined(OPENSSL_SYS_VMS) [else] */
242 
243     i = ioctlsocket(fd, type, ARG);
244 #  endif                        /* __DJGPP__ */
245     if (i < 0)
246         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
247                        "calling ioctlsocket()");
248     return i;
249 }
250 
251 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_get_accept_socket(char * host,int bind_mode)252 int BIO_get_accept_socket(char *host, int bind_mode)
253 {
254     int s = INVALID_SOCKET;
255     char *h = NULL, *p = NULL;
256     BIO_ADDRINFO *res = NULL;
257 
258     if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
259         return INVALID_SOCKET;
260 
261     if (BIO_sock_init() != 1)
262         return INVALID_SOCKET;
263 
264     if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
265         goto err;
266 
267     if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
268                         BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
269         s = INVALID_SOCKET;
270         goto err;
271     }
272 
273     if (!BIO_listen(s, BIO_ADDRINFO_address(res),
274                     bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
275         BIO_closesocket(s);
276         s = INVALID_SOCKET;
277     }
278 
279  err:
280     BIO_ADDRINFO_free(res);
281     OPENSSL_free(h);
282     OPENSSL_free(p);
283 
284     return s;
285 }
286 
BIO_accept(int sock,char ** ip_port)287 int BIO_accept(int sock, char **ip_port)
288 {
289     BIO_ADDR res;
290     int ret = -1;
291 
292     ret = BIO_accept_ex(sock, &res, 0);
293     if (ret == (int)INVALID_SOCKET) {
294         if (BIO_sock_should_retry(ret)) {
295             ret = -2;
296             goto end;
297         }
298         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
299                        "calling accept()");
300         ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
301         goto end;
302     }
303 
304     if (ip_port != NULL) {
305         char *host = BIO_ADDR_hostname_string(&res, 1);
306         char *port = BIO_ADDR_service_string(&res, 1);
307         if (host != NULL && port != NULL) {
308             *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
309         } else {
310             *ip_port = NULL;
311             ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
312         }
313 
314         if (*ip_port == NULL) {
315             BIO_closesocket(ret);
316             ret = (int)INVALID_SOCKET;
317         } else {
318             strcpy(*ip_port, host);
319             strcat(*ip_port, ":");
320             strcat(*ip_port, port);
321         }
322         OPENSSL_free(host);
323         OPENSSL_free(port);
324     }
325 
326  end:
327     return ret;
328 }
329 # endif
330 
BIO_set_tcp_ndelay(int s,int on)331 int BIO_set_tcp_ndelay(int s, int on)
332 {
333     int ret = 0;
334 # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
335     int opt;
336 
337 #  ifdef SOL_TCP
338     opt = SOL_TCP;
339 #  else
340 #   ifdef IPPROTO_TCP
341     opt = IPPROTO_TCP;
342 #   endif
343 #  endif
344 
345     ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
346 # endif
347     return (ret == 0);
348 }
349 
BIO_socket_nbio(int s,int mode)350 int BIO_socket_nbio(int s, int mode)
351 {
352     int ret = -1;
353     int l;
354 
355     l = mode;
356 # ifdef FIONBIO
357     l = mode;
358 
359     ret = BIO_socket_ioctl(s, FIONBIO, &l);
360 # elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
361     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
362 
363     l = fcntl(s, F_GETFL, 0);
364     if (l == -1) {
365         ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
366                        "calling fcntl()");
367         ret = -1;
368     } else {
369 #  if defined(O_NONBLOCK)
370         l &= ~O_NONBLOCK;
371 #  else
372         l &= ~FNDELAY; /* BSD4.x */
373 #  endif
374         if (mode) {
375 #  if defined(O_NONBLOCK)
376             l |= O_NONBLOCK;
377 #  else
378             l |= FNDELAY; /* BSD4.x */
379 #  endif
380         }
381         ret = fcntl(s, F_SETFL, l);
382 
383         if (ret < 0) {
384             ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
385                            "calling fcntl()");
386         }
387     }
388 # else
389     /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
390     ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
391 # endif
392 
393     return (ret == 0);
394 }
395 
BIO_sock_info(int sock,enum BIO_sock_info_type type,union BIO_sock_info_u * info)396 int BIO_sock_info(int sock,
397                   enum BIO_sock_info_type type, union BIO_sock_info_u *info)
398 {
399     switch (type) {
400     case BIO_SOCK_INFO_ADDRESS:
401         {
402             socklen_t addr_len;
403             int ret = 0;
404             addr_len = sizeof(*info->addr);
405             ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
406                               &addr_len);
407             if (ret == -1) {
408                 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
409                                "calling getsockname()");
410                 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR);
411                 return 0;
412             }
413             if ((size_t)addr_len > sizeof(*info->addr)) {
414                 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
415                 return 0;
416             }
417         }
418         break;
419     default:
420         ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE);
421         return 0;
422     }
423     return 1;
424 }
425 
426 /*
427  * Wait on fd at most until max_time; succeed immediately if max_time == 0.
428  * If for_read == 0 then assume to wait for writing, else wait for reading.
429  * Returns -1 on error, 0 on timeout, and 1 on success.
430  */
BIO_socket_wait(int fd,int for_read,time_t max_time)431 int BIO_socket_wait(int fd, int for_read, time_t max_time)
432 {
433 # if defined(OPENSSL_SYS_WINDOWS) || !defined(POLLIN)
434     fd_set confds;
435     struct timeval tv;
436     time_t now;
437 
438 #  ifdef _WIN32
439     if ((SOCKET)fd == INVALID_SOCKET)
440 #  else
441     if (fd < 0 || fd >= FD_SETSIZE)
442 #  endif
443         return -1;
444     if (max_time == 0)
445         return 1;
446 
447     now = time(NULL);
448     if (max_time < now)
449         return 0;
450 
451     FD_ZERO(&confds);
452     openssl_fdset(fd, &confds);
453     tv.tv_usec = 0;
454     tv.tv_sec = (long)(max_time - now); /* might overflow */
455     return select(fd + 1, for_read ? &confds : NULL,
456                   for_read ? NULL : &confds, NULL, &tv);
457 # else
458     struct pollfd confds;
459     time_t now;
460 
461     if (fd < 0)
462         return -1;
463     if (max_time == 0)
464         return 1;
465 
466     now = time(NULL);
467     if (max_time < now)
468         return 0;
469 
470     confds.fd = fd;
471     confds.events = for_read ? POLLIN : POLLOUT;
472     return poll(&confds, 1, (int)(max_time - now) * 1000);
473 # endif
474 }
475 #endif /* !defined(OPENSSL_NO_SOCK) */
476