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