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