1 /* 2 * Copyright 1995-2024 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 { 48 BIO_ADDRINFO *res = NULL; 49 int ret = 0; 50 51 if (BIO_sock_init() != 1) 52 return 0; /* don't generate another error code here */ 53 54 if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { 55 size_t l; 56 57 if (BIO_ADDRINFO_family(res) != AF_INET) { 58 ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 59 } 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 if (ossl_assert(l == 4)) 65 ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); 66 } 67 BIO_ADDRINFO_free(res); 68 } else { 69 ERR_add_error_data(2, "host=", str); 70 } 71 72 return ret; 73 } 74 75 int BIO_get_port(const char *str, unsigned short *port_ptr) 76 { 77 BIO_ADDRINFO *res = NULL; 78 int ret = 0; 79 80 if (str == NULL) { 81 ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED); 82 return 0; 83 } 84 85 if (BIO_sock_init() != 1) 86 return 0; /* don't generate another error code here */ 87 88 if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { 89 if (BIO_ADDRINFO_family(res) != AF_INET) { 90 ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); 91 } else { 92 *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); 93 ret = 1; 94 } 95 BIO_ADDRINFO_free(res); 96 } else { 97 ERR_add_error_data(2, "host=", str); 98 } 99 100 return ret; 101 } 102 # endif 103 104 int BIO_sock_error(int sock) 105 { 106 int j = 0, i; 107 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 i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); 116 if (i < 0) 117 return get_last_socket_error(); 118 else 119 return j; 120 } 121 122 # ifndef OPENSSL_NO_DEPRECATED_1_1_0 123 struct hostent *BIO_gethostbyname(const char *name) 124 { 125 /* 126 * Caching gethostbyname() results forever is wrong, so we have to let 127 * the true gethostbyname() worry about this 128 */ 129 return gethostbyname(name); 130 } 131 # endif 132 133 int BIO_sock_init(void) 134 { 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 return 1; 163 } 164 165 void bio_sock_cleanup_int(void) 166 { 167 # ifdef OPENSSL_SYS_WINDOWS 168 if (wsa_init_done) { 169 wsa_init_done = 0; 170 WSACleanup(); 171 } 172 # endif 173 } 174 175 int BIO_socket_ioctl(int fd, long type, void *arg) 176 { 177 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 # define ARG arg 204 # endif /* defined(OPENSSL_SYS_VMS) [else] */ 205 206 i = ioctlsocket(fd, type, ARG); 207 # endif /* __DJGPP__ */ 208 if (i < 0) 209 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 210 "calling ioctlsocket()"); 211 return i; 212 } 213 214 # ifndef OPENSSL_NO_DEPRECATED_1_1_0 215 int BIO_get_accept_socket(char *host, int bind_mode) 216 { 217 int s = INVALID_SOCKET; 218 char *h = NULL, *p = NULL; 219 BIO_ADDRINFO *res = NULL; 220 221 if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) 222 return INVALID_SOCKET; 223 224 if (BIO_sock_init() != 1) 225 return INVALID_SOCKET; 226 227 if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) 228 goto err; 229 230 if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), 231 BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { 232 s = INVALID_SOCKET; 233 goto err; 234 } 235 236 if (!BIO_listen(s, BIO_ADDRINFO_address(res), 237 bind_mode ? BIO_SOCK_REUSEADDR : 0)) { 238 BIO_closesocket(s); 239 s = INVALID_SOCKET; 240 } 241 242 err: 243 BIO_ADDRINFO_free(res); 244 OPENSSL_free(h); 245 OPENSSL_free(p); 246 247 return s; 248 } 249 250 int BIO_accept(int sock, char **ip_port) 251 { 252 BIO_ADDR res; 253 int ret = -1; 254 255 ret = BIO_accept_ex(sock, &res, 0); 256 if (ret == (int)INVALID_SOCKET) { 257 if (BIO_sock_should_retry(ret)) { 258 ret = -2; 259 goto end; 260 } 261 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 262 "calling accept()"); 263 ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); 264 goto end; 265 } 266 267 if (ip_port != NULL) { 268 char *host = BIO_ADDR_hostname_string(&res, 1); 269 char *port = BIO_ADDR_service_string(&res, 1); 270 if (host != NULL && port != NULL) 271 *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); 272 else 273 *ip_port = NULL; 274 275 if (*ip_port == NULL) { 276 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 277 BIO_closesocket(ret); 278 ret = (int)INVALID_SOCKET; 279 } else { 280 strcpy(*ip_port, host); 281 strcat(*ip_port, ":"); 282 strcat(*ip_port, port); 283 } 284 OPENSSL_free(host); 285 OPENSSL_free(port); 286 } 287 288 end: 289 return ret; 290 } 291 # endif 292 293 int BIO_set_tcp_ndelay(int s, int on) 294 { 295 int ret = 0; 296 # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 297 int opt; 298 299 # ifdef SOL_TCP 300 opt = SOL_TCP; 301 # else 302 # ifdef IPPROTO_TCP 303 opt = IPPROTO_TCP; 304 # endif 305 # endif 306 307 ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); 308 # endif 309 return (ret == 0); 310 } 311 312 int BIO_socket_nbio(int s, int mode) 313 { 314 int ret = -1; 315 int l; 316 317 l = mode; 318 # ifdef FIONBIO 319 l = mode; 320 321 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 return (ret == 0); 356 } 357 358 int BIO_sock_info(int sock, 359 enum BIO_sock_info_type type, union BIO_sock_info_u *info) 360 { 361 switch (type) { 362 case BIO_SOCK_INFO_ADDRESS: 363 { 364 socklen_t addr_len; 365 int ret = 0; 366 addr_len = sizeof(*info->addr); 367 ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), 368 &addr_len); 369 if (ret == -1) { 370 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 371 "calling getsockname()"); 372 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR); 373 return 0; 374 } 375 if ((size_t)addr_len > sizeof(*info->addr)) { 376 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); 377 return 0; 378 } 379 } 380 break; 381 default: 382 ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE); 383 return 0; 384 } 385 return 1; 386 } 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 { 395 fd_set confds; 396 struct timeval tv; 397 time_t now; 398 399 #ifdef _WIN32 400 if ((SOCKET)fd == INVALID_SOCKET) 401 #else 402 if (fd < 0 || fd >= FD_SETSIZE) 403 #endif 404 return -1; 405 if (max_time == 0) 406 return 1; 407 408 now = time(NULL); 409 if (max_time < now) 410 return 0; 411 412 FD_ZERO(&confds); 413 openssl_fdset(fd, &confds); 414 tv.tv_usec = 0; 415 tv.tv_sec = (long)(max_time - now); /* might overflow */ 416 return select(fd + 1, for_read ? &confds : NULL, 417 for_read ? NULL : &confds, NULL, &tv); 418 } 419 #endif /* !defined(OPENSSL_NO_SOCK) */ 420