xref: /freebsd/crypto/openssl/crypto/bio/bio_sock2.c (revision b077aed3)
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 
17 #include <openssl/err.h>
18 
19 #ifndef OPENSSL_NO_SOCK
20 # ifdef SO_MAXCONN
21 #  define MAX_LISTEN  SO_MAXCONN
22 # elif defined(SOMAXCONN)
23 #  define MAX_LISTEN  SOMAXCONN
24 # else
25 #  define MAX_LISTEN  32
26 # endif
27 
28 /*-
29  * BIO_socket - create a socket
30  * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
31  * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
32  * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
33  * @options: BIO socket options (currently unused)
34  *
35  * Creates a socket.  This should be called before calling any
36  * of BIO_connect and BIO_listen.
37  *
38  * Returns the file descriptor on success or INVALID_SOCKET on failure.  On
39  * failure errno is set, and a status is added to the OpenSSL error stack.
40  */
BIO_socket(int domain,int socktype,int protocol,int options)41 int BIO_socket(int domain, int socktype, int protocol, int options)
42 {
43     int sock = -1;
44 
45     if (BIO_sock_init() != 1)
46         return INVALID_SOCKET;
47 
48     sock = socket(domain, socktype, protocol);
49     if (sock == -1) {
50         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
51                        "calling socket()");
52         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
53         return INVALID_SOCKET;
54     }
55 # ifndef OPENSSL_NO_KTLS
56     {
57         /*
58          * The new socket is created successfully regardless of ktls_enable.
59          * ktls_enable doesn't change any functionality of the socket, except
60          * changing the setsockopt to enable the processing of ktls_start.
61          * Thus, it is not a problem to call it for non-TLS sockets.
62          */
63         ktls_enable(sock);
64     }
65 # endif
66 
67     return sock;
68 }
69 
70 /*-
71  * BIO_connect - connect to an address
72  * @sock: the socket to connect with
73  * @addr: the address to connect to
74  * @options: BIO socket options
75  *
76  * Connects to the address using the given socket and options.
77  *
78  * Options can be a combination of the following:
79  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
80  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
81  * - BIO_SOCK_NODELAY: don't delay small messages.
82  *
83  * options holds BIO socket options that can be used
84  * You should call this for every address returned by BIO_lookup
85  * until the connection is successful.
86  *
87  * Returns 1 on success or 0 on failure.  On failure errno is set
88  * and an error status is added to the OpenSSL error stack.
89  */
BIO_connect(int sock,const BIO_ADDR * addr,int options)90 int BIO_connect(int sock, const BIO_ADDR *addr, int options)
91 {
92     const int on = 1;
93 
94     if (sock == -1) {
95         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
96         return 0;
97     }
98 
99     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
100         return 0;
101 
102     if (options & BIO_SOCK_KEEPALIVE) {
103         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
104                        (const void *)&on, sizeof(on)) != 0) {
105             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
106                            "calling setsockopt()");
107             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
108             return 0;
109         }
110     }
111 
112     if (options & BIO_SOCK_NODELAY) {
113         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
114                        (const void *)&on, sizeof(on)) != 0) {
115             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
116                            "calling setsockopt()");
117             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
118             return 0;
119         }
120     }
121 
122     if (connect(sock, BIO_ADDR_sockaddr(addr),
123                 BIO_ADDR_sockaddr_size(addr)) == -1) {
124         if (!BIO_sock_should_retry(-1)) {
125             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
126                            "calling connect()");
127             ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
128         }
129         return 0;
130     }
131 # ifndef OPENSSL_NO_KTLS
132     /*
133      * The new socket is created successfully regardless of ktls_enable.
134      * ktls_enable doesn't change any functionality of the socket, except
135      * changing the setsockopt to enable the processing of ktls_start.
136      * Thus, it is not a problem to call it for non-TLS sockets.
137      */
138     ktls_enable(sock);
139 # endif
140     return 1;
141 }
142 
143 /*-
144  * BIO_bind - bind socket to address
145  * @sock: the socket to set
146  * @addr: local address to bind to
147  * @options: BIO socket options
148  *
149  * Binds to the address using the given socket and options.
150  *
151  * Options can be a combination of the following:
152  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
153  *   for a recently closed port.
154  *
155  * When restarting the program it could be that the port is still in use.  If
156  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
157  * It's recommended that you use this.
158  */
BIO_bind(int sock,const BIO_ADDR * addr,int options)159 int BIO_bind(int sock, const BIO_ADDR *addr, int options)
160 {
161 # ifndef OPENSSL_SYS_WINDOWS
162     int on = 1;
163 # endif
164 
165     if (sock == -1) {
166         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
167         return 0;
168     }
169 
170 # ifndef OPENSSL_SYS_WINDOWS
171     /*
172      * SO_REUSEADDR has different behavior on Windows than on
173      * other operating systems, don't set it there.
174      */
175     if (options & BIO_SOCK_REUSEADDR) {
176         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
177                        (const void *)&on, sizeof(on)) != 0) {
178             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
179                            "calling setsockopt()");
180             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR);
181             return 0;
182         }
183     }
184 # endif
185 
186     if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
187         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */,
188                        "calling bind()");
189         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET);
190         return 0;
191     }
192 
193     return 1;
194 }
195 
196 /*-
197  * BIO_listen - Creates a listen socket
198  * @sock: the socket to listen with
199  * @addr: local address to bind to
200  * @options: BIO socket options
201  *
202  * Binds to the address using the given socket and options, then
203  * starts listening for incoming connections.
204  *
205  * Options can be a combination of the following:
206  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
207  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
208  * - BIO_SOCK_NODELAY: don't delay small messages.
209  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
210  *   for a recently closed port.
211  * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
212  *   for IPv6 addresses and not IPv4 addresses mapped to IPv6.
213  *
214  * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
215  * then check both for new clients that connect to it.  You want to set up
216  * the socket as non-blocking in that case since else it could hang.
217  *
218  * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
219  * others it's an option.  If you pass the BIO_LISTEN_V6_ONLY it will try to
220  * create the IPv6 sockets to only listen for IPv6 connection.
221  *
222  * It could be that the first BIO_listen() call will listen to all the IPv6
223  * and IPv4 addresses and that then trying to bind to the IPv4 address will
224  * fail.  We can't tell the difference between already listening ourself to
225  * it and someone else listening to it when failing and errno is EADDRINUSE, so
226  * it's recommended to not give an error in that case if the first call was
227  * successful.
228  *
229  * When restarting the program it could be that the port is still in use.  If
230  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
231  * It's recommended that you use this.
232  */
BIO_listen(int sock,const BIO_ADDR * addr,int options)233 int BIO_listen(int sock, const BIO_ADDR *addr, int options)
234 {
235     int on = 1;
236     int socktype;
237     socklen_t socktype_len = sizeof(socktype);
238 
239     if (sock == -1) {
240         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
241         return 0;
242     }
243 
244     if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
245                    (void *)&socktype, &socktype_len) != 0
246         || socktype_len != sizeof(socktype)) {
247         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
248                        "calling getsockopt()");
249         ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE);
250         return 0;
251     }
252 
253     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
254         return 0;
255 
256     if (options & BIO_SOCK_KEEPALIVE) {
257         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
258                        (const void *)&on, sizeof(on)) != 0) {
259             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
260                            "calling setsockopt()");
261             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
262             return 0;
263         }
264     }
265 
266     if (options & BIO_SOCK_NODELAY) {
267         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
268                        (const void *)&on, sizeof(on)) != 0) {
269             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
270                            "calling setsockopt()");
271             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
272             return 0;
273         }
274     }
275 
276   /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */
277 # if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
278     if (BIO_ADDR_family(addr) == AF_INET6) {
279         /*
280          * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
281          * Therefore we always have to use setsockopt here.
282          */
283         on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
284         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
285                        (const void *)&on, sizeof(on)) != 0) {
286             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
287                            "calling setsockopt()");
288             ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY);
289             return 0;
290         }
291     }
292 # endif
293 
294     if (!BIO_bind(sock, addr, options))
295         return 0;
296 
297     if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
298         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
299                        "calling listen()");
300         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET);
301         return 0;
302     }
303 
304     return 1;
305 }
306 
307 /*-
308  * BIO_accept_ex - Accept new incoming connections
309  * @sock: the listening socket
310  * @addr: the BIO_ADDR to store the peer address in
311  * @options: BIO socket options, applied on the accepted socket.
312  *
313  */
BIO_accept_ex(int accept_sock,BIO_ADDR * addr_,int options)314 int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
315 {
316     socklen_t len;
317     int accepted_sock;
318     BIO_ADDR locaddr;
319     BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
320 
321     len = sizeof(*addr);
322     accepted_sock = accept(accept_sock,
323                            BIO_ADDR_sockaddr_noconst(addr), &len);
324     if (accepted_sock == -1) {
325         if (!BIO_sock_should_retry(accepted_sock)) {
326             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
327                            "calling accept()");
328             ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
329         }
330         return INVALID_SOCKET;
331     }
332 
333     if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
334         closesocket(accepted_sock);
335         return INVALID_SOCKET;
336     }
337 
338     return accepted_sock;
339 }
340 
341 /*-
342  * BIO_closesocket - Close a socket
343  * @sock: the socket to close
344  */
BIO_closesocket(int sock)345 int BIO_closesocket(int sock)
346 {
347     if (sock < 0 || closesocket(sock) < 0)
348         return 0;
349     return 1;
350 }
351 #endif
352