xref: /openssl/crypto/bio/bio_sock2.c (revision c7340583)
1 /*
2  * Copyright 2016-2022 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 <errno.h>
13 
14 #include "bio_local.h"
15 #include "internal/ktls.h"
16 #include "internal/bio_tfo.h"
17 
18 #include <openssl/err.h>
19 
20 #ifndef OPENSSL_NO_SOCK
21 # ifdef SO_MAXCONN
22 #  define MAX_LISTEN  SO_MAXCONN
23 # elif defined(SOMAXCONN)
24 #  define MAX_LISTEN  SOMAXCONN
25 # else
26 #  define MAX_LISTEN  32
27 # endif
28 
29 /*-
30  * BIO_socket - create a socket
31  * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
32  * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
33  * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
34  * @options: BIO socket options (currently unused)
35  *
36  * Creates a socket.  This should be called before calling any
37  * of BIO_connect and BIO_listen.
38  *
39  * Returns the file descriptor on success or INVALID_SOCKET on failure.  On
40  * failure errno is set, and a status is added to the OpenSSL error stack.
41  */
BIO_socket(int domain,int socktype,int protocol,int options)42 int BIO_socket(int domain, int socktype, int protocol, int options)
43 {
44     int sock = -1;
45 
46     if (BIO_sock_init() != 1)
47         return INVALID_SOCKET;
48 
49     sock = socket(domain, socktype, protocol);
50     if (sock == -1) {
51         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
52                        "calling socket()");
53         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
54         return INVALID_SOCKET;
55     }
56 
57     return sock;
58 }
59 
60 /*-
61  * BIO_connect - connect to an address
62  * @sock: the socket to connect with
63  * @addr: the address to connect to
64  * @options: BIO socket options
65  *
66  * Connects to the address using the given socket and options.
67  *
68  * Options can be a combination of the following:
69  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
70  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
71  * - BIO_SOCK_NODELAY: don't delay small messages.
72  * - BIO_SOCK_TFO: use TCP Fast Open
73  *
74  * options holds BIO socket options that can be used
75  * You should call this for every address returned by BIO_lookup
76  * until the connection is successful.
77  *
78  * Returns 1 on success or 0 on failure.  On failure errno is set
79  * and an error status is added to the OpenSSL error stack.
80  */
BIO_connect(int sock,const BIO_ADDR * addr,int options)81 int BIO_connect(int sock, const BIO_ADDR *addr, int options)
82 {
83     const int on = 1;
84 
85     if (sock == -1) {
86         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
87         return 0;
88     }
89 
90     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
91         return 0;
92 
93     if (options & BIO_SOCK_KEEPALIVE) {
94         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
95                        (const void *)&on, sizeof(on)) != 0) {
96             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
97                            "calling setsockopt()");
98             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
99             return 0;
100         }
101     }
102 
103     if (options & BIO_SOCK_NODELAY) {
104         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
105                        (const void *)&on, sizeof(on)) != 0) {
106             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
107                            "calling setsockopt()");
108             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
109             return 0;
110         }
111     }
112     if (options & BIO_SOCK_TFO) {
113 # if defined(OSSL_TFO_CLIENT_FLAG)
114 #  if defined(OSSL_TFO_SYSCTL_CLIENT)
115         int enabled = 0;
116         size_t enabledlen = sizeof(enabled);
117 
118         /* Later FreeBSD */
119         if (sysctlbyname(OSSL_TFO_SYSCTL_CLIENT, &enabled, &enabledlen, NULL, 0) < 0) {
120             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT);
121             return 0;
122         }
123         /* Need to check for client flag */
124         if (!(enabled & OSSL_TFO_CLIENT_FLAG)) {
125             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED);
126             return 0;
127         }
128 #  elif defined(OSSL_TFO_SYSCTL)
129         int enabled = 0;
130         size_t enabledlen = sizeof(enabled);
131 
132         /* macOS */
133         if (sysctlbyname(OSSL_TFO_SYSCTL, &enabled, &enabledlen, NULL, 0) < 0) {
134             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT);
135             return 0;
136         }
137         /* Need to check for client flag */
138         if (!(enabled & OSSL_TFO_CLIENT_FLAG)) {
139             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED);
140             return 0;
141         }
142 #  endif
143 # endif
144 # if defined(OSSL_TFO_CONNECTX)
145         sa_endpoints_t sae;
146 
147         memset(&sae, 0, sizeof(sae));
148         sae.sae_dstaddr = BIO_ADDR_sockaddr(addr);
149         sae.sae_dstaddrlen = BIO_ADDR_sockaddr_size(addr);
150         if (connectx(sock, &sae, SAE_ASSOCID_ANY,
151                      CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
152                      NULL, 0, NULL, NULL) == -1) {
153             if (!BIO_sock_should_retry(-1)) {
154                 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
155                                "calling connectx()");
156                 ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
157             }
158             return 0;
159         }
160 # endif
161 # if defined(OSSL_TFO_CLIENT_SOCKOPT)
162         if (setsockopt(sock, IPPROTO_TCP, OSSL_TFO_CLIENT_SOCKOPT,
163                        (const void *)&on, sizeof(on)) != 0) {
164             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
165                            "calling setsockopt()");
166             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO);
167             return 0;
168         }
169 # endif
170 # if defined(OSSL_TFO_DO_NOT_CONNECT)
171         return 1;
172 # endif
173     }
174 
175     if (connect(sock, BIO_ADDR_sockaddr(addr),
176                 BIO_ADDR_sockaddr_size(addr)) == -1) {
177         if (!BIO_sock_should_retry(-1)) {
178             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
179                            "calling connect()");
180             ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
181         }
182         return 0;
183     }
184 # ifndef OPENSSL_NO_KTLS
185     /*
186      * The new socket is created successfully regardless of ktls_enable.
187      * ktls_enable doesn't change any functionality of the socket, except
188      * changing the setsockopt to enable the processing of ktls_start.
189      * Thus, it is not a problem to call it for non-TLS sockets.
190      */
191     ktls_enable(sock);
192 # endif
193     return 1;
194 }
195 
196 /*-
197  * BIO_bind - bind socket to address
198  * @sock: the socket to set
199  * @addr: local address to bind to
200  * @options: BIO socket options
201  *
202  * Binds to the address using the given socket and options.
203  *
204  * Options can be a combination of the following:
205  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
206  *   for a recently closed port.
207  *
208  * When restarting the program it could be that the port is still in use.  If
209  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
210  * It's recommended that you use this.
211  */
BIO_bind(int sock,const BIO_ADDR * addr,int options)212 int BIO_bind(int sock, const BIO_ADDR *addr, int options)
213 {
214 # ifndef OPENSSL_SYS_WINDOWS
215     int on = 1;
216 # endif
217 
218     if (sock == -1) {
219         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
220         return 0;
221     }
222 
223 # ifndef OPENSSL_SYS_WINDOWS
224     /*
225      * SO_REUSEADDR has different behavior on Windows than on
226      * other operating systems, don't set it there.
227      */
228     if (options & BIO_SOCK_REUSEADDR) {
229         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
230                        (const void *)&on, sizeof(on)) != 0) {
231             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
232                            "calling setsockopt()");
233             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR);
234             return 0;
235         }
236     }
237 # endif
238 
239     if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
240         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */,
241                        "calling bind()");
242         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET);
243         return 0;
244     }
245 
246     return 1;
247 }
248 
249 /*-
250  * BIO_listen - Creates a listen socket
251  * @sock: the socket to listen with
252  * @addr: local address to bind to
253  * @options: BIO socket options
254  *
255  * Binds to the address using the given socket and options, then
256  * starts listening for incoming connections.
257  *
258  * Options can be a combination of the following:
259  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
260  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
261  * - BIO_SOCK_NODELAY: don't delay small messages.
262  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
263  *   for a recently closed port.
264  * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
265  *   for IPv6 addresses and not IPv4 addresses mapped to IPv6.
266  * - BIO_SOCK_TFO: accept TCP fast open (set TCP_FASTOPEN)
267  *
268  * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
269  * then check both for new clients that connect to it.  You want to set up
270  * the socket as non-blocking in that case since else it could hang.
271  *
272  * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
273  * others it's an option.  If you pass the BIO_LISTEN_V6_ONLY it will try to
274  * create the IPv6 sockets to only listen for IPv6 connection.
275  *
276  * It could be that the first BIO_listen() call will listen to all the IPv6
277  * and IPv4 addresses and that then trying to bind to the IPv4 address will
278  * fail.  We can't tell the difference between already listening ourself to
279  * it and someone else listening to it when failing and errno is EADDRINUSE, so
280  * it's recommended to not give an error in that case if the first call was
281  * successful.
282  *
283  * When restarting the program it could be that the port is still in use.  If
284  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
285  * It's recommended that you use this.
286  */
BIO_listen(int sock,const BIO_ADDR * addr,int options)287 int BIO_listen(int sock, const BIO_ADDR *addr, int options)
288 {
289     int on = 1;
290     int socktype;
291     socklen_t socktype_len = sizeof(socktype);
292 
293     if (sock == -1) {
294         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
295         return 0;
296     }
297 
298     if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
299                    (void *)&socktype, &socktype_len) != 0
300         || socktype_len != sizeof(socktype)) {
301         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
302                        "calling getsockopt()");
303         ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE);
304         return 0;
305     }
306 
307     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
308         return 0;
309 
310     if (options & BIO_SOCK_KEEPALIVE) {
311         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
312                        (const void *)&on, sizeof(on)) != 0) {
313             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
314                            "calling setsockopt()");
315             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
316             return 0;
317         }
318     }
319 
320     if (options & BIO_SOCK_NODELAY) {
321         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
322                        (const void *)&on, sizeof(on)) != 0) {
323             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
324                            "calling setsockopt()");
325             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
326             return 0;
327         }
328     }
329 
330   /* On OpenBSD it is always IPv6 only with IPv6 sockets thus read-only */
331 # if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
332     if (BIO_ADDR_family(addr) == AF_INET6) {
333         /*
334          * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
335          * Therefore we always have to use setsockopt here.
336          */
337         on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
338         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
339                        (const void *)&on, sizeof(on)) != 0) {
340             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
341                            "calling setsockopt()");
342             ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY);
343             return 0;
344         }
345     }
346 # endif
347 
348     if (!BIO_bind(sock, addr, options))
349         return 0;
350 
351     if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
352         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
353                        "calling listen()");
354         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET);
355         return 0;
356     }
357 
358 # if defined(OSSL_TFO_SERVER_SOCKOPT)
359     /*
360      * Must do it explicitly after listen() for macOS, still
361      * works fine on other OS's
362      */
363     if ((options & BIO_SOCK_TFO) && socktype != SOCK_DGRAM) {
364         int q = OSSL_TFO_SERVER_SOCKOPT_VALUE;
365 #  if defined(OSSL_TFO_CLIENT_FLAG)
366 #   if defined(OSSL_TFO_SYSCTL_SERVER)
367         int enabled = 0;
368         size_t enabledlen = sizeof(enabled);
369 
370         /* Later FreeBSD */
371         if (sysctlbyname(OSSL_TFO_SYSCTL_SERVER, &enabled, &enabledlen, NULL, 0) < 0) {
372             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT);
373             return 0;
374         }
375         /* Need to check for server flag */
376         if (!(enabled & OSSL_TFO_SERVER_FLAG)) {
377             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED);
378             return 0;
379         }
380 #   elif defined(OSSL_TFO_SYSCTL)
381         int enabled = 0;
382         size_t enabledlen = sizeof(enabled);
383 
384         /* Early FreeBSD, macOS */
385         if (sysctlbyname(OSSL_TFO_SYSCTL, &enabled, &enabledlen, NULL, 0) < 0) {
386             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT);
387             return 0;
388         }
389         /* Need to check for server flag */
390         if (!(enabled & OSSL_TFO_SERVER_FLAG)) {
391             ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED);
392             return 0;
393         }
394 #   endif
395 #  endif
396         if (setsockopt(sock, IPPROTO_TCP, OSSL_TFO_SERVER_SOCKOPT,
397                        (void *)&q, sizeof(q)) < 0) {
398             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
399                            "calling setsockopt()");
400             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO);
401             return 0;
402         }
403     }
404 # endif
405 
406     return 1;
407 }
408 
409 /*-
410  * BIO_accept_ex - Accept new incoming connections
411  * @sock: the listening socket
412  * @addr: the BIO_ADDR to store the peer address in
413  * @options: BIO socket options, applied on the accepted socket.
414  *
415  */
BIO_accept_ex(int accept_sock,BIO_ADDR * addr_,int options)416 int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
417 {
418     socklen_t len;
419     int accepted_sock;
420     BIO_ADDR locaddr;
421     BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
422 
423     len = sizeof(*addr);
424     accepted_sock = accept(accept_sock,
425                            BIO_ADDR_sockaddr_noconst(addr), &len);
426     if (accepted_sock == -1) {
427         if (!BIO_sock_should_retry(accepted_sock)) {
428             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
429                            "calling accept()");
430             ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
431         }
432         return INVALID_SOCKET;
433     }
434 
435     if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
436         closesocket(accepted_sock);
437         return INVALID_SOCKET;
438     }
439 
440     return accepted_sock;
441 }
442 
443 /*-
444  * BIO_closesocket - Close a socket
445  * @sock: the socket to close
446  */
BIO_closesocket(int sock)447 int BIO_closesocket(int sock)
448 {
449     if (sock < 0 || closesocket(sock) < 0)
450         return 0;
451     return 1;
452 }
453 #endif
454