15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This package is an SSL implementation written 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * by Eric Young (eay@cryptsoft.com). 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The implementation was written so as to conform with Netscapes SSL. 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * This library is free for commercial and non-commercial use as long as 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions are aheared to. The following conditions 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * apply to all code found in this distribution, be it the RC4, RSA, 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * included with this distribution is covered by the same copyright terms 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright remains Eric Young's, and as such any Copyright notices in 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * the code are not to be removed. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If this package is used in a product, Eric Young should be given attribution 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as the author of the parts of the library used. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This can be in the form of a textual message at program startup or 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * in documentation (online or textual) provided with the package. 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * Redistribution and use in source and binary forms, with or without 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * modification, are permitted provided that the following conditions 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * are met: 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 1. Redistributions of source code must retain the copyright 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * notice, this list of conditions and the following disclaimer. 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * notice, this list of conditions and the following disclaimer in the 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * documentation and/or other materials provided with the distribution. 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * 3. All advertising materials mentioning features or use of this software 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * must display the following acknowledgement: 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * "This product includes cryptographic software written by 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Eric Young (eay@cryptsoft.com)" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The word 'cryptographic' can be left out if the rouines from the library 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * being used are not cryptographic related :-). 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 4. If you include any Windows specific code (or a derivative thereof) from 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the apps directory (application code) you must include an acknowledgement: 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * SUCH DAMAGE. 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * The licence and distribution terms for any publically available version or 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * derivative of this code cannot be changed. i.e. this code cannot simply be 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * copied and put under another distribution licence 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * [including the GNU Public Licence.] */ 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <openssl/bio.h> 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h> 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h> 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#if !defined(OPENSSL_WINDOWS) 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <sys/socket.h> 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <netinet/in.h> 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <arpa/inet.h> 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <unistd.h> 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/buf.h> 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/err.h> 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <openssl/mem.h> 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "internal.h" 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)enum { 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BIO_CONN_S_BEFORE, 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BIO_CONN_S_BLOCKED_CONNECT, 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BIO_CONN_S_OK, 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)typedef struct bio_connect_st { 841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int state; 85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch char *param_hostname; 871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) char *param_port; 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int nbio; 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint8_t ip[4]; 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned short port; 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch struct sockaddr_storage them; 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) socklen_t them_length; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch /* the file descriptor is kept in bio->num in order to match the socket 977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * BIO. */ 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* info_callback is called when the connection is initially made 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * callback(BIO,state,ret); The callback should return 'ret', state is for 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * compatibility with the SSL info_callback. */ 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int (*info_callback)(const BIO *bio, int state, int ret); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} BIO_CONNECT; 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* maybe_copy_ipv4_address sets |*ipv4| to the IPv4 address from |ss| (in 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * big-endian order), if |ss| contains an IPv4 socket address. */ 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void maybe_copy_ipv4_address(uint8_t *ipv4, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct sockaddr_storage *ss) { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct sockaddr_in *sin; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ss->ss_family != AF_INET) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sin = (const struct sockaddr_in*) ss; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(ipv4, &sin->sin_addr, 4); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int conn_state(BIO *bio, BIO_CONNECT *c) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ret = -1, i; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char *p, *q; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int (*cb)(const BIO *, int, int) = NULL; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (c->info_callback != NULL) { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb = c->info_callback; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (;;) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (c->state) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BIO_CONN_S_BEFORE: 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) p = c->param_hostname; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (p == NULL) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_HOSTNAME_SPECIFIED); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto exit_loop; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; *p != 0; p++) { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*p == ':' || *p == '/') { 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i = *p; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i == ':' || i == '/') { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(p++) = 0; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i == ':') { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (q = p; *q; q++) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (*q == '/') { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *q = 0; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (c->param_port != NULL) { 1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) OPENSSL_free(c->param_port); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c->param_port = BUF_strdup(p); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (c->param_port == NULL) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_PORT_SPECIFIED); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ERR_add_error_data(2, "host=", c->param_hostname); 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) goto exit_loop; 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bio_ip_and_port_to_socket_and_addr( 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bio->num, &c->them, &c->them_length, c->param_hostname, 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c->param_port)) { 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_UNABLE_TO_CREATE_SOCKET); 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch goto exit_loop; 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch memset(c->ip, 0, 4); 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch maybe_copy_ipv4_address(c->ip, &c->them); 1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (c->nbio) { 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!bio_socket_nbio(bio->num, 1)) { 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_ERROR_SETTING_NBIO); 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ERR_add_error_data(4, "host=", c->param_hostname, ":", 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch c->param_port); 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch goto exit_loop; 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch i = 1; 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sizeof(i)); 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ret < 0) { 1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OPENSSL_PUT_SYSTEM_ERROR(setsockopt); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_KEEPALIVE); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); 1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch goto exit_loop; 1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BIO_clear_retry_flags(bio); 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length); 1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ret < 0) { 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bio_fd_should_retry(ret)) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c->state = BIO_CONN_S_BLOCKED_CONNECT; 201 bio->retry_reason = BIO_RR_CONNECT; 202 } else { 203 OPENSSL_PUT_SYSTEM_ERROR(connect); 204 OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_CONNECT_ERROR); 205 ERR_add_error_data(4, "host=", c->param_hostname, ":", 206 c->param_port); 207 } 208 goto exit_loop; 209 } else { 210 c->state = BIO_CONN_S_OK; 211 } 212 break; 213 214 case BIO_CONN_S_BLOCKED_CONNECT: 215 i = bio_sock_error(bio->num); 216 if (i) { 217 if (bio_fd_should_retry(ret)) { 218 BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY)); 219 c->state = BIO_CONN_S_BLOCKED_CONNECT; 220 bio->retry_reason = BIO_RR_CONNECT; 221 ret = -1; 222 } else { 223 BIO_clear_retry_flags(bio); 224 OPENSSL_PUT_SYSTEM_ERROR(connect); 225 OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NBIO_CONNECT_ERROR); 226 ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port); 227 ret = 0; 228 } 229 goto exit_loop; 230 } else { 231 c->state = BIO_CONN_S_OK; 232 } 233 break; 234 235 case BIO_CONN_S_OK: 236 ret = 1; 237 goto exit_loop; 238 default: 239 assert(0); 240 goto exit_loop; 241 } 242 243 if (cb != NULL) { 244 ret = cb((BIO *)bio, c->state, ret); 245 if (ret == 0) { 246 goto end; 247 } 248 } 249 } 250 251exit_loop: 252 if (cb != NULL) { 253 ret = cb((BIO *)bio, c->state, ret); 254 } 255 256end: 257 return ret; 258} 259 260static BIO_CONNECT *BIO_CONNECT_new(void) { 261 BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT)); 262 263 if (ret == NULL) { 264 return NULL; 265 } 266 memset(ret, 0, sizeof(BIO_CONNECT)); 267 268 ret->state = BIO_CONN_S_BEFORE; 269 return ret; 270} 271 272static void BIO_CONNECT_free(BIO_CONNECT *c) { 273 if (c == NULL) { 274 return; 275 } 276 277 if (c->param_hostname != NULL) { 278 OPENSSL_free(c->param_hostname); 279 } 280 if (c->param_port != NULL) { 281 OPENSSL_free(c->param_port); 282 } 283 OPENSSL_free(c); 284} 285 286static int conn_new(BIO *bio) { 287 bio->init = 0; 288 bio->num = -1; 289 bio->flags = 0; 290 bio->ptr = (char *)BIO_CONNECT_new(); 291 return bio->ptr != NULL; 292} 293 294static void conn_close_socket(BIO *bio) { 295 BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr; 296 297 if (bio->num == -1) { 298 return; 299 } 300 301 /* Only do a shutdown if things were established */ 302 if (c->state == BIO_CONN_S_OK) { 303 shutdown(bio->num, 2); 304 } 305 close(bio->num); 306 bio->num = -1; 307} 308 309static int conn_free(BIO *bio) { 310 if (bio == NULL) { 311 return 0; 312 } 313 314 if (bio->shutdown) { 315 conn_close_socket(bio); 316 } 317 318 BIO_CONNECT_free((BIO_CONNECT*) bio->ptr); 319 320 return 1; 321} 322 323static int conn_read(BIO *bio, char *out, int out_len) { 324 int ret = 0; 325 BIO_CONNECT *data; 326 327 data = (BIO_CONNECT *)bio->ptr; 328 if (data->state != BIO_CONN_S_OK) { 329 ret = conn_state(bio, data); 330 if (ret <= 0) { 331 return ret; 332 } 333 } 334 335 bio_clear_socket_error(); 336 ret = recv(bio->num, out, out_len, 0); 337 BIO_clear_retry_flags(bio); 338 if (ret <= 0) { 339 if (bio_fd_should_retry(ret)) { 340 BIO_set_retry_read(bio); 341 } 342 } 343 344 return ret; 345} 346 347static int conn_write(BIO *bio, const char *in, int in_len) { 348 int ret; 349 BIO_CONNECT *data; 350 351 data = (BIO_CONNECT *)bio->ptr; 352 if (data->state != BIO_CONN_S_OK) { 353 ret = conn_state(bio, data); 354 if (ret <= 0) { 355 return ret; 356 } 357 } 358 359 bio_clear_socket_error(); 360 ret = send(bio->num, in, in_len, 0); 361 BIO_clear_retry_flags(bio); 362 if (ret <= 0) { 363 if (bio_fd_should_retry(ret)) { 364 BIO_set_retry_write(bio); 365 } 366 } 367 368 return ret; 369} 370 371static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) { 372 int *ip; 373 const char **pptr; 374 long ret = 1; 375 BIO_CONNECT *data; 376 377 data = (BIO_CONNECT *)bio->ptr; 378 379 switch (cmd) { 380 case BIO_CTRL_RESET: 381 ret = 0; 382 data->state = BIO_CONN_S_BEFORE; 383 conn_close_socket(bio); 384 bio->flags = 0; 385 break; 386 case BIO_C_DO_STATE_MACHINE: 387 /* use this one to start the connection */ 388 if (data->state != BIO_CONN_S_OK) 389 ret = (long)conn_state(bio, data); 390 else 391 ret = 1; 392 break; 393 case BIO_C_GET_CONNECT: 394 /* TODO(fork): can this be removed? (Or maybe this whole file). */ 395 if (ptr != NULL) { 396 pptr = (const char **)ptr; 397 if (num == 0) { 398 *pptr = data->param_hostname; 399 } else if (num == 1) { 400 *pptr = data->param_port; 401 } else if (num == 2) { 402 *pptr = (char *) &data->ip[0]; 403 } else if (num == 3) { 404 *((int *)ptr) = data->port; 405 } 406 if (!bio->init) { 407 *pptr = "not initialized"; 408 } 409 ret = 1; 410 } 411 break; 412 case BIO_C_SET_CONNECT: 413 if (ptr != NULL) { 414 bio->init = 1; 415 if (num == 0) { 416 if (data->param_hostname != NULL) { 417 OPENSSL_free(data->param_hostname); 418 } 419 data->param_hostname = BUF_strdup(ptr); 420 } else if (num == 1) { 421 if (data->param_port != NULL) { 422 OPENSSL_free(data->param_port); 423 } 424 data->param_port = BUF_strdup(ptr); 425 } else { 426 ret = 0; 427 } 428 } 429 break; 430 case BIO_C_SET_NBIO: 431 data->nbio = (int)num; 432 break; 433 case BIO_C_GET_FD: 434 if (bio->init) { 435 ip = (int *)ptr; 436 if (ip != NULL) { 437 *ip = bio->num; 438 } 439 ret = 1; 440 } else { 441 ret = 0; 442 } 443 break; 444 case BIO_CTRL_GET_CLOSE: 445 ret = bio->shutdown; 446 break; 447 case BIO_CTRL_SET_CLOSE: 448 bio->shutdown = (int)num; 449 break; 450 case BIO_CTRL_PENDING: 451 case BIO_CTRL_WPENDING: 452 ret = 0; 453 break; 454 case BIO_CTRL_FLUSH: 455 break; 456 case BIO_CTRL_SET_CALLBACK: { 457#if 0 /* FIXME: Should this be used? -- Richard Levitte */ 458 OPENSSL_PUT_ERROR(BIO, XXX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 459 ret = -1; 460#else 461 ret = 0; 462#endif 463 } break; 464 case BIO_CTRL_GET_CALLBACK: { 465 int (**fptr)(const BIO *bio, int state, int xret); 466 fptr = (int (**)(const BIO *bio, int state, int xret))ptr; 467 *fptr = data->info_callback; 468 } break; 469 default: 470 ret = 0; 471 break; 472 } 473 return (ret); 474} 475 476static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { 477 long ret = 1; 478 BIO_CONNECT *data; 479 480 data = (BIO_CONNECT *)bio->ptr; 481 482 switch (cmd) { 483 case BIO_CTRL_SET_CALLBACK: { 484 data->info_callback = (int (*)(const struct bio_st *, int, int))fp; 485 } break; 486 default: 487 ret = 0; 488 break; 489 } 490 return ret; 491} 492 493static int conn_puts(BIO *bp, const char *str) { 494 return conn_write(bp, str, strlen(str)); 495} 496 497BIO *BIO_new_connect(const char *hostname) { 498 BIO *ret; 499 500 ret = BIO_new(BIO_s_connect()); 501 if (ret == NULL) { 502 return NULL; 503 } 504 if (!BIO_set_conn_hostname(ret, hostname)) { 505 BIO_free(ret); 506 return NULL; 507 } 508 return ret; 509} 510 511static const BIO_METHOD methods_connectp = { 512 BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read, 513 conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new, 514 conn_free, conn_callback_ctrl, 515}; 516 517const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; } 518 519int BIO_set_conn_hostname(BIO *bio, const char *name) { 520 return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name); 521} 522 523int BIO_set_conn_port(BIO *bio, const char *port_str) { 524 return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str); 525} 526 527int BIO_set_nbio(BIO *bio, int on) { 528 return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL); 529} 530