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