X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fbio%2Fb_sock.c;h=3c8a10b8fdffcb9c659576f73ed84d8ac728c7ca;hp=eece85bb51f0491ed3f898f23d566fbb3f8eb1c3;hb=e8d0819d52b2741fcb4ddb79ced4d824c3056918;hpb=59d9bb591c950062ef3721f6b58fddbaae910f2a diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index eece85bb51..3c8a10b8fd 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -1,68 +1,15 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/* + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include #include -#include -#include "bio_lcl.h" -#if defined(NETWARE_CLIB) -# include -NETDB_DEFINE_CONTEXT -#endif +#include "bio_local.h" #ifndef OPENSSL_NO_SOCK # define SOCKET_PROTOCOL IPPROTO_TCP # ifdef SO_MAXCONN @@ -72,11 +19,18 @@ NETDB_DEFINE_CONTEXT # else # define MAX_LISTEN 32 # endif -# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) +# if defined(OPENSSL_SYS_WINDOWS) static int wsa_init_done = 0; # endif -# if OPENSSL_API_COMPAT < 0x10100000L +# ifndef _WIN32 +# include +# include +# else +# include /* for type fd_set */ +# endif + +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 int BIO_get_host_ip(const char *str, unsigned char *ip) { BIO_ADDRINFO *res = NULL; @@ -91,14 +45,13 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) if (BIO_ADDRINFO_family(res) != AF_INET) { BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); - } else { - BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l); - /* Because only AF_INET addresses will reach this far, - we can assert that l should be 4 */ - OPENSSL_assert(l == 4); - - BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); - ret = 1; + } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { + /* + * Because only AF_INET addresses will reach this far, we can assert + * that l should be 4 + */ + if (ossl_assert(l == 4)) + ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); } BIO_ADDRINFO_free(res); } else { @@ -115,7 +68,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) if (str == NULL) { BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); - return (0); + return 0; } if (BIO_sock_init() != 1) @@ -141,7 +94,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) int BIO_sock_error(int sock) { int j = 0, i; - socklen_t size = 0; + socklen_t size = sizeof(j); /* * Note: under Windows the third parameter is of type (char *) whereas @@ -151,23 +104,19 @@ int BIO_sock_error(int sock) */ i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); if (i < 0) - return (1); + return get_last_socket_error(); else - return (j); + return j; } -# if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 struct hostent *BIO_gethostbyname(const char *name) { /* * Caching gethostbyname() results forever is wrong, so we have to let * the true gethostbyname() worry about this */ -# if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__)) - return gethostbyname((char *)name); -# else return gethostbyname(name); -# endif } # endif @@ -177,8 +126,6 @@ int BIO_sock_init(void) static struct WSAData wsa_state; if (!wsa_init_done) { - int err; - wsa_init_done = 1; memset(&wsa_state, 0, sizeof(wsa_state)); /* @@ -188,10 +135,10 @@ int BIO_sock_init(void) * probed at run-time with DSO_global_lookup. */ if (WSAStartup(0x0202, &wsa_state) != 0) { - err = WSAGetLastError(); - SYSerr(SYS_F_WSASTARTUP, err); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling wsastartup()"); BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); - return (-1); + return -1; } } # endif /* OPENSSL_SYS_WINDOWS */ @@ -199,46 +146,22 @@ int BIO_sock_init(void) extern int _watt_do_exit; _watt_do_exit = 0; /* don't make sock_init() call exit() */ if (sock_init()) - return (-1); + return -1; # endif -# if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) - WORD wVerReq; - WSADATA wsaData; - int err; - - if (!wsa_init_done) { - wsa_init_done = 1; - wVerReq = MAKEWORD(2, 0); - err = WSAStartup(wVerReq, &wsaData); - if (err != 0) { - SYSerr(SYS_F_WSASTARTUP, err); - BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); - return (-1); - } - } -# endif - - return (1); + return 1; } -void BIO_sock_cleanup(void) +void bio_sock_cleanup_int(void) { # ifdef OPENSSL_SYS_WINDOWS if (wsa_init_done) { wsa_init_done = 0; WSACleanup(); } -# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) - if (wsa_init_done) { - wsa_init_done = 0; - WSACleanup(); - } # endif } -# if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 - int BIO_socket_ioctl(int fd, long type, void *arg) { int i; @@ -273,12 +196,12 @@ int BIO_socket_ioctl(int fd, long type, void *arg) i = ioctlsocket(fd, type, ARG); # endif /* __DJGPP__ */ if (i < 0) - SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); - return (i); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling ioctlsocket()"); + return i; } -# endif /* __VMS_VER */ -# if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 int BIO_get_accept_socket(char *host, int bind_mode) { int s = INVALID_SOCKET; @@ -316,39 +239,43 @@ int BIO_get_accept_socket(char *host, int bind_mode) int BIO_accept(int sock, char **ip_port) { - BIO_ADDR *res = BIO_ADDR_new(); + BIO_ADDR res; int ret = -1; - if (res == NULL) { - BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); - return ret; - } - - ret = BIO_accept_ex(sock, res, 0); - + ret = BIO_accept_ex(sock, &res, 0); if (ret == (int)INVALID_SOCKET) { if (BIO_sock_should_retry(ret)) { ret = -2; goto end; } - SYSerr(SYS_F_ACCEPT, get_last_socket_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling accept()"); BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); goto end; } if (ip_port != NULL) { - char *host = BIO_ADDR_hostname_string(res, 1); - char *port = BIO_ADDR_service_string(res, 1); - *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); - strcpy(*ip_port, host); - strcat(*ip_port, ":"); - strcat(*ip_port, port); + char *host = BIO_ADDR_hostname_string(&res, 1); + char *port = BIO_ADDR_service_string(&res, 1); + if (host != NULL && port != NULL) + *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); + else + *ip_port = NULL; + + if (*ip_port == NULL) { + BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); + BIO_closesocket(ret); + ret = (int)INVALID_SOCKET; + } else { + strcpy(*ip_port, host); + strcat(*ip_port, ":"); + strcat(*ip_port, port); + } OPENSSL_free(host); OPENSSL_free(port); } end: - BIO_ADDR_free(res); return ret; } # endif @@ -387,7 +314,8 @@ int BIO_socket_nbio(int s, int mode) l = fcntl(s, F_GETFL, 0); if (l == -1) { - SYSerr(SYS_F_FCNTL, get_last_rtl_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); ret = -1; } else { # if defined(O_NONBLOCK) @@ -405,7 +333,8 @@ int BIO_socket_nbio(int s, int mode) ret = fcntl(s, F_SETFL, l); if (ret < 0) { - SYSerr(SYS_F_FCNTL, get_last_rtl_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); } } # else @@ -428,7 +357,8 @@ int BIO_sock_info(int sock, ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), &addr_len); if (ret == -1) { - SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockname()"); BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); return 0; } @@ -445,4 +375,30 @@ int BIO_sock_info(int sock, return 1; } -#endif +/* TODO simplify by BIO_socket_wait() further other uses of select() in apps/ */ +/* + * Wait on fd at most until max_time; succeed immediately if max_time == 0. + * If for_read == 0 then assume to wait for writing, else wait for reading. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_socket_wait(int fd, int for_read, time_t max_time) +{ + fd_set confds; + struct timeval tv; + time_t now; + + if (max_time == 0) + return 1; + + now = time(NULL); + if (max_time <= now) + return 0; + + FD_ZERO(&confds); + openssl_fdset(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = (long)(max_time - now); /* might overflow */ + return select(fd + 1, for_read ? &confds : NULL, + for_read ? NULL : &confds, NULL, &tv); +} +#endif /* !defined(OPENSSL_NO_SOCK) */