xref: /openbsd-src/lib/libssl/bio_ssl.c (revision 82821a618568f0edc5dd97e8c920c69266b62eca)
1*82821a61Stb /* $OpenBSD: bio_ssl.c,v 1.40 2023/07/19 13:34:33 tb Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
585b37fcf3Sryker 
59c5899dbcSjsing #include <errno.h>
605b37fcf3Sryker #include <stdio.h>
615b37fcf3Sryker #include <stdlib.h>
625b37fcf3Sryker #include <string.h>
63c5899dbcSjsing 
64913ec974Sbeck #include <openssl/bio.h>
65c5899dbcSjsing #include <openssl/crypto.h>
66913ec974Sbeck #include <openssl/err.h>
67913ec974Sbeck #include <openssl/ssl.h>
685b37fcf3Sryker 
69a366758fStb #include "bio_local.h"
70c9675a23Stb #include "ssl_local.h"
71ff236217Sbeck 
72c109e398Sbeck static int ssl_write(BIO *h, const char *buf, int num);
735b37fcf3Sryker static int ssl_read(BIO *h, char *buf, int size);
74c109e398Sbeck static int ssl_puts(BIO *h, const char *str);
75c109e398Sbeck static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
765b37fcf3Sryker static int ssl_new(BIO *h);
775b37fcf3Sryker static int ssl_free(BIO *data);
78c929ff6cStb static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
797c408a08Sjsing typedef struct bio_ssl_st {
805b37fcf3Sryker 	SSL *ssl; /* The ssl handle :-) */
815b37fcf3Sryker 	/* re-negotiate every time the total number of bytes is this size */
825b37fcf3Sryker 	int num_renegotiates;
835b37fcf3Sryker 	unsigned long renegotiate_count;
845b37fcf3Sryker 	unsigned long byte_count;
855b37fcf3Sryker 	unsigned long renegotiate_timeout;
8635dedd17Sderaadt 	time_t last_time;
875b37fcf3Sryker } BIO_SSL;
885b37fcf3Sryker 
89daf0add4Stb static const BIO_METHOD methods_sslp = {
904f2520b6Sjsing 	.type = BIO_TYPE_SSL,
914f2520b6Sjsing 	.name = "ssl",
924f2520b6Sjsing 	.bwrite = ssl_write,
934f2520b6Sjsing 	.bread = ssl_read,
944f2520b6Sjsing 	.bputs = ssl_puts,
954f2520b6Sjsing 	.ctrl = ssl_ctrl,
964f2520b6Sjsing 	.create = ssl_new,
974f2520b6Sjsing 	.destroy = ssl_free,
984f2520b6Sjsing 	.callback_ctrl = ssl_callback_ctrl,
995b37fcf3Sryker };
1005b37fcf3Sryker 
101daf0add4Stb const BIO_METHOD *
BIO_f_ssl(void)10252ada5cbSjsing BIO_f_ssl(void)
1035b37fcf3Sryker {
1045b37fcf3Sryker 	return (&methods_sslp);
1055b37fcf3Sryker }
106cedac418Stb LSSL_ALIAS(BIO_f_ssl);
1075b37fcf3Sryker 
1087c408a08Sjsing static int
ssl_new(BIO * bi)1097c408a08Sjsing ssl_new(BIO *bi)
1105b37fcf3Sryker {
1115b37fcf3Sryker 	BIO_SSL *bs;
1125b37fcf3Sryker 
1137c5c1828Sderaadt 	bs = calloc(1, sizeof(BIO_SSL));
1147c408a08Sjsing 	if (bs == NULL) {
115c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
1165b37fcf3Sryker 		return (0);
1175b37fcf3Sryker 	}
1185b37fcf3Sryker 	bi->init = 0;
1195b37fcf3Sryker 	bi->ptr = (char *)bs;
1205b37fcf3Sryker 	bi->flags = 0;
1215b37fcf3Sryker 	return (1);
1225b37fcf3Sryker }
12371e04849Sbeck LSSL_ALIAS(BIO_f_ssl);
1245b37fcf3Sryker 
1257c408a08Sjsing static int
ssl_free(BIO * a)1267c408a08Sjsing ssl_free(BIO *a)
1275b37fcf3Sryker {
1285b37fcf3Sryker 	BIO_SSL *bs;
1295b37fcf3Sryker 
1307c408a08Sjsing 	if (a == NULL)
1317c408a08Sjsing 		return (0);
1325b37fcf3Sryker 	bs = (BIO_SSL *)a->ptr;
1337c408a08Sjsing 	if (bs->ssl != NULL)
1347c408a08Sjsing 		SSL_shutdown(bs->ssl);
1357c408a08Sjsing 	if (a->shutdown) {
1365b37fcf3Sryker 		if (a->init && (bs->ssl != NULL))
1375b37fcf3Sryker 			SSL_free(bs->ssl);
1385b37fcf3Sryker 		a->init = 0;
1395b37fcf3Sryker 		a->flags = 0;
1405b37fcf3Sryker 	}
1416f3a6cb1Sbeck 	free(a->ptr);
1425b37fcf3Sryker 	return (1);
1435b37fcf3Sryker }
1445b37fcf3Sryker 
1457c408a08Sjsing static int
ssl_read(BIO * b,char * out,int outl)1467c408a08Sjsing ssl_read(BIO *b, char *out, int outl)
1475b37fcf3Sryker {
1485b37fcf3Sryker 	int ret = 1;
1495b37fcf3Sryker 	BIO_SSL *sb;
1505b37fcf3Sryker 	SSL *ssl;
1515b37fcf3Sryker 	int retry_reason = 0;
1525b37fcf3Sryker 	int r = 0;
1535b37fcf3Sryker 
1547c408a08Sjsing 	if (out == NULL)
1557c408a08Sjsing 		return (0);
1565b37fcf3Sryker 	sb = (BIO_SSL *)b->ptr;
1575b37fcf3Sryker 	ssl = sb->ssl;
1585b37fcf3Sryker 
1595b37fcf3Sryker 	BIO_clear_retry_flags(b);
1605b37fcf3Sryker 
1615b37fcf3Sryker 	ret = SSL_read(ssl, out, outl);
1625b37fcf3Sryker 
1637c408a08Sjsing 	switch (SSL_get_error(ssl, ret)) {
1645b37fcf3Sryker 	case SSL_ERROR_NONE:
1657c408a08Sjsing 		if (ret <= 0)
1667c408a08Sjsing 			break;
1677c408a08Sjsing 		if (sb->renegotiate_count > 0) {
1685b37fcf3Sryker 			sb->byte_count += ret;
1697c408a08Sjsing 			if (sb->byte_count > sb->renegotiate_count) {
1705b37fcf3Sryker 				sb->byte_count = 0;
1715b37fcf3Sryker 				sb->num_renegotiates++;
1725b37fcf3Sryker 				SSL_renegotiate(ssl);
1735b37fcf3Sryker 				r = 1;
1745b37fcf3Sryker 			}
1755b37fcf3Sryker 		}
1767c408a08Sjsing 		if ((sb->renegotiate_timeout > 0) && (!r)) {
17735dedd17Sderaadt 			time_t tm;
1785b37fcf3Sryker 
17935dedd17Sderaadt 			tm = time(NULL);
1807c408a08Sjsing 			if (tm > sb->last_time + sb->renegotiate_timeout) {
1815b37fcf3Sryker 				sb->last_time = tm;
1825b37fcf3Sryker 				sb->num_renegotiates++;
1835b37fcf3Sryker 				SSL_renegotiate(ssl);
1845b37fcf3Sryker 			}
1855b37fcf3Sryker 		}
1865b37fcf3Sryker 
1875b37fcf3Sryker 		break;
1885b37fcf3Sryker 	case SSL_ERROR_WANT_READ:
1895b37fcf3Sryker 		BIO_set_retry_read(b);
1905b37fcf3Sryker 		break;
1915b37fcf3Sryker 	case SSL_ERROR_WANT_WRITE:
1925b37fcf3Sryker 		BIO_set_retry_write(b);
1935b37fcf3Sryker 		break;
1945b37fcf3Sryker 	case SSL_ERROR_WANT_X509_LOOKUP:
1955b37fcf3Sryker 		BIO_set_retry_special(b);
1965b37fcf3Sryker 		retry_reason = BIO_RR_SSL_X509_LOOKUP;
1975b37fcf3Sryker 		break;
198da347917Sbeck 	case SSL_ERROR_WANT_ACCEPT:
199da347917Sbeck 		BIO_set_retry_special(b);
200da347917Sbeck 		retry_reason = BIO_RR_ACCEPT;
201da347917Sbeck 		break;
2025b37fcf3Sryker 	case SSL_ERROR_WANT_CONNECT:
2035b37fcf3Sryker 		BIO_set_retry_special(b);
2045b37fcf3Sryker 		retry_reason = BIO_RR_CONNECT;
2055b37fcf3Sryker 		break;
2065b37fcf3Sryker 	case SSL_ERROR_SYSCALL:
2075b37fcf3Sryker 	case SSL_ERROR_SSL:
2085b37fcf3Sryker 	case SSL_ERROR_ZERO_RETURN:
2095b37fcf3Sryker 	default:
2105b37fcf3Sryker 		break;
2115b37fcf3Sryker 	}
2125b37fcf3Sryker 
2135b37fcf3Sryker 	b->retry_reason = retry_reason;
2145b37fcf3Sryker 	return (ret);
2155b37fcf3Sryker }
2165b37fcf3Sryker 
2177c408a08Sjsing static int
ssl_write(BIO * b,const char * out,int outl)2187c408a08Sjsing ssl_write(BIO *b, const char *out, int outl)
2195b37fcf3Sryker {
2205b37fcf3Sryker 	int ret, r = 0;
2215b37fcf3Sryker 	int retry_reason = 0;
2225b37fcf3Sryker 	SSL *ssl;
2235b37fcf3Sryker 	BIO_SSL *bs;
2245b37fcf3Sryker 
2257c408a08Sjsing 	if (out == NULL)
2267c408a08Sjsing 		return (0);
2275b37fcf3Sryker 	bs = (BIO_SSL *)b->ptr;
2285b37fcf3Sryker 	ssl = bs->ssl;
2295b37fcf3Sryker 
2305b37fcf3Sryker 	BIO_clear_retry_flags(b);
2315b37fcf3Sryker 
2325b37fcf3Sryker /*	ret=SSL_do_handshake(ssl);
2335b37fcf3Sryker 	if (ret > 0) */
2345b37fcf3Sryker 		ret = SSL_write(ssl, out, outl);
2355b37fcf3Sryker 
2367c408a08Sjsing 	switch (SSL_get_error(ssl, ret)) {
2375b37fcf3Sryker 	case SSL_ERROR_NONE:
2387c408a08Sjsing 		if (ret <= 0)
2397c408a08Sjsing 			break;
2407c408a08Sjsing 		if (bs->renegotiate_count > 0) {
2415b37fcf3Sryker 			bs->byte_count += ret;
2427c408a08Sjsing 			if (bs->byte_count > bs->renegotiate_count) {
2435b37fcf3Sryker 				bs->byte_count = 0;
2445b37fcf3Sryker 				bs->num_renegotiates++;
2455b37fcf3Sryker 				SSL_renegotiate(ssl);
2465b37fcf3Sryker 				r = 1;
2475b37fcf3Sryker 			}
2485b37fcf3Sryker 		}
2497c408a08Sjsing 		if ((bs->renegotiate_timeout > 0) && (!r)) {
25035dedd17Sderaadt 			time_t tm;
2515b37fcf3Sryker 
25235dedd17Sderaadt 			tm = time(NULL);
2537c408a08Sjsing 			if (tm > bs->last_time + bs->renegotiate_timeout) {
2545b37fcf3Sryker 				bs->last_time = tm;
2555b37fcf3Sryker 				bs->num_renegotiates++;
2565b37fcf3Sryker 				SSL_renegotiate(ssl);
2575b37fcf3Sryker 			}
2585b37fcf3Sryker 		}
2595b37fcf3Sryker 		break;
2605b37fcf3Sryker 	case SSL_ERROR_WANT_WRITE:
2615b37fcf3Sryker 		BIO_set_retry_write(b);
2625b37fcf3Sryker 		break;
2635b37fcf3Sryker 	case SSL_ERROR_WANT_READ:
2645b37fcf3Sryker 		BIO_set_retry_read(b);
2655b37fcf3Sryker 		break;
2665b37fcf3Sryker 	case SSL_ERROR_WANT_X509_LOOKUP:
2675b37fcf3Sryker 		BIO_set_retry_special(b);
2685b37fcf3Sryker 		retry_reason = BIO_RR_SSL_X509_LOOKUP;
2695b37fcf3Sryker 		break;
2705b37fcf3Sryker 	case SSL_ERROR_WANT_CONNECT:
2715b37fcf3Sryker 		BIO_set_retry_special(b);
2725b37fcf3Sryker 		retry_reason = BIO_RR_CONNECT;
2735b37fcf3Sryker 	case SSL_ERROR_SYSCALL:
2745b37fcf3Sryker 	case SSL_ERROR_SSL:
2755b37fcf3Sryker 	default:
2765b37fcf3Sryker 		break;
2775b37fcf3Sryker 	}
2785b37fcf3Sryker 
2795b37fcf3Sryker 	b->retry_reason = retry_reason;
2805b37fcf3Sryker 	return (ret);
2815b37fcf3Sryker }
2825b37fcf3Sryker 
2837c408a08Sjsing static long
ssl_ctrl(BIO * b,int cmd,long num,void * ptr)2847c408a08Sjsing ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
2855b37fcf3Sryker {
2865b37fcf3Sryker 	SSL **sslp, *ssl;
2875b37fcf3Sryker 	BIO_SSL *bs;
2885b37fcf3Sryker 	BIO *dbio, *bio;
2895b37fcf3Sryker 	long ret = 1;
2905b37fcf3Sryker 
2915b37fcf3Sryker 	bs = (BIO_SSL *)b->ptr;
2925b37fcf3Sryker 	ssl = bs->ssl;
2935b37fcf3Sryker 	if ((ssl == NULL)  && (cmd != BIO_C_SET_SSL))
2945b37fcf3Sryker 		return (0);
2957c408a08Sjsing 	switch (cmd) {
2965b37fcf3Sryker 	case BIO_CTRL_RESET:
2975b37fcf3Sryker 		SSL_shutdown(ssl);
2985b37fcf3Sryker 
299e481eacfStb 		if (ssl->handshake_func == ssl->method->ssl_connect)
3005b37fcf3Sryker 			SSL_set_connect_state(ssl);
301e481eacfStb 		else if (ssl->handshake_func == ssl->method->ssl_accept)
3025b37fcf3Sryker 			SSL_set_accept_state(ssl);
3035b37fcf3Sryker 
3045b37fcf3Sryker 		SSL_clear(ssl);
3055b37fcf3Sryker 
3065b37fcf3Sryker 		if (b->next_bio != NULL)
3075b37fcf3Sryker 			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
3085b37fcf3Sryker 		else if (ssl->rbio != NULL)
3095b37fcf3Sryker 			ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
3105b37fcf3Sryker 		else
3115b37fcf3Sryker 			ret = 1;
3125b37fcf3Sryker 		break;
3135b37fcf3Sryker 	case BIO_CTRL_INFO:
3145b37fcf3Sryker 		ret = 0;
3155b37fcf3Sryker 		break;
3165b37fcf3Sryker 	case BIO_C_SSL_MODE:
3175b37fcf3Sryker 		if (num) /* client mode */
3185b37fcf3Sryker 			SSL_set_connect_state(ssl);
3195b37fcf3Sryker 		else
3205b37fcf3Sryker 			SSL_set_accept_state(ssl);
3215b37fcf3Sryker 		break;
3225b37fcf3Sryker 	case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
3235b37fcf3Sryker 		ret = bs->renegotiate_timeout;
3247c408a08Sjsing 		if (num < 60)
3257c408a08Sjsing 			num = 5;
3265b37fcf3Sryker 		bs->renegotiate_timeout = (unsigned long)num;
32735dedd17Sderaadt 		bs->last_time = time(NULL);
3285b37fcf3Sryker 		break;
3295b37fcf3Sryker 	case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
3305b37fcf3Sryker 		ret = bs->renegotiate_count;
3315b37fcf3Sryker 		if ((long)num >=512)
3325b37fcf3Sryker 			bs->renegotiate_count = (unsigned long)num;
3335b37fcf3Sryker 		break;
3345b37fcf3Sryker 	case BIO_C_GET_SSL_NUM_RENEGOTIATES:
3355b37fcf3Sryker 		ret = bs->num_renegotiates;
3365b37fcf3Sryker 		break;
3375b37fcf3Sryker 	case BIO_C_SET_SSL:
3387c408a08Sjsing 		if (ssl != NULL) {
3395b37fcf3Sryker 			ssl_free(b);
340c32db552Sdjm 			if (!ssl_new(b))
341c32db552Sdjm 				return 0;
342c32db552Sdjm 		}
3435b37fcf3Sryker 		b->shutdown = (int)num;
3445b37fcf3Sryker 		ssl = (SSL *)ptr;
3455b37fcf3Sryker 		((BIO_SSL *)b->ptr)->ssl = ssl;
3465b37fcf3Sryker 		bio = SSL_get_rbio(ssl);
3477c408a08Sjsing 		if (bio != NULL) {
3485b37fcf3Sryker 			if (b->next_bio != NULL)
3495b37fcf3Sryker 				BIO_push(bio, b->next_bio);
3505b37fcf3Sryker 			b->next_bio = bio;
3515b37fcf3Sryker 			CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
3525b37fcf3Sryker 		}
3535b37fcf3Sryker 		b->init = 1;
3545b37fcf3Sryker 		break;
3555b37fcf3Sryker 	case BIO_C_GET_SSL:
3567c408a08Sjsing 		if (ptr != NULL) {
3575b37fcf3Sryker 			sslp = (SSL **)ptr;
3585b37fcf3Sryker 			*sslp = ssl;
3597c408a08Sjsing 		} else
3605b37fcf3Sryker 			ret = 0;
3615b37fcf3Sryker 		break;
3625b37fcf3Sryker 	case BIO_CTRL_GET_CLOSE:
3635b37fcf3Sryker 		ret = b->shutdown;
3645b37fcf3Sryker 		break;
3655b37fcf3Sryker 	case BIO_CTRL_SET_CLOSE:
3665b37fcf3Sryker 		b->shutdown = (int)num;
3675b37fcf3Sryker 		break;
3685b37fcf3Sryker 	case BIO_CTRL_WPENDING:
3695b37fcf3Sryker 		ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
3705b37fcf3Sryker 		break;
3715b37fcf3Sryker 	case BIO_CTRL_PENDING:
3725b37fcf3Sryker 		ret = SSL_pending(ssl);
3735b37fcf3Sryker 		if (ret == 0)
3745b37fcf3Sryker 			ret = BIO_pending(ssl->rbio);
3755b37fcf3Sryker 		break;
3765b37fcf3Sryker 	case BIO_CTRL_FLUSH:
3775b37fcf3Sryker 		BIO_clear_retry_flags(b);
3785b37fcf3Sryker 		ret = BIO_ctrl(ssl->wbio, cmd, num, ptr);
3795b37fcf3Sryker 		BIO_copy_next_retry(b);
3805b37fcf3Sryker 		break;
3815b37fcf3Sryker 	case BIO_CTRL_PUSH:
3827c408a08Sjsing 		if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) {
3835b37fcf3Sryker 			SSL_set_bio(ssl, b->next_bio, b->next_bio);
384f3742667Sbeck 			CRYPTO_add(&b->next_bio->references, 1,
385f3742667Sbeck 			    CRYPTO_LOCK_BIO);
3865b37fcf3Sryker 		}
3875b37fcf3Sryker 		break;
3885b37fcf3Sryker 	case BIO_CTRL_POP:
3890a5d6edeSdjm 		/* Only detach if we are the BIO explicitly being popped */
3907c408a08Sjsing 		if (b == ptr) {
3910a5d6edeSdjm 			/* Shouldn't happen in practice because the
3920a5d6edeSdjm 			 * rbio and wbio are the same when pushed.
3930a5d6edeSdjm 			 */
3940a5d6edeSdjm 			if (ssl->rbio != ssl->wbio)
3955b37fcf3Sryker 				BIO_free_all(ssl->wbio);
396767fe2ffSmarkus 			if (b->next_bio != NULL)
3970a5d6edeSdjm 				CRYPTO_add(&b->next_bio->references, -1, CRYPTO_LOCK_BIO);
3985b37fcf3Sryker 			ssl->wbio = NULL;
3995b37fcf3Sryker 			ssl->rbio = NULL;
4000a5d6edeSdjm 		}
4015b37fcf3Sryker 		break;
4025b37fcf3Sryker 	case BIO_C_DO_STATE_MACHINE:
4035b37fcf3Sryker 		BIO_clear_retry_flags(b);
4045b37fcf3Sryker 
4055b37fcf3Sryker 		b->retry_reason = 0;
4065b37fcf3Sryker 		ret = (int)SSL_do_handshake(ssl);
4075b37fcf3Sryker 
4087c408a08Sjsing 		switch (SSL_get_error(ssl, (int)ret)) {
4095b37fcf3Sryker 		case SSL_ERROR_WANT_READ:
4105b37fcf3Sryker 			BIO_set_flags(b,
4115b37fcf3Sryker 			    BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY);
4125b37fcf3Sryker 			break;
4135b37fcf3Sryker 		case SSL_ERROR_WANT_WRITE:
4145b37fcf3Sryker 			BIO_set_flags(b,
4155b37fcf3Sryker 			    BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY);
4165b37fcf3Sryker 			break;
4175b37fcf3Sryker 		case SSL_ERROR_WANT_CONNECT:
4185b37fcf3Sryker 			BIO_set_flags(b,
4195b37fcf3Sryker 			    BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY);
4205b37fcf3Sryker 			b->retry_reason = b->next_bio->retry_reason;
4215b37fcf3Sryker 			break;
4225b37fcf3Sryker 		default:
4235b37fcf3Sryker 			break;
4245b37fcf3Sryker 		}
4255b37fcf3Sryker 		break;
4265b37fcf3Sryker 	case BIO_CTRL_DUP:
4275b37fcf3Sryker 		dbio = (BIO *)ptr;
4285b37fcf3Sryker 		if (((BIO_SSL *)dbio->ptr)->ssl != NULL)
4295b37fcf3Sryker 			SSL_free(((BIO_SSL *)dbio->ptr)->ssl);
4305b37fcf3Sryker 		((BIO_SSL *)dbio->ptr)->ssl = SSL_dup(ssl);
4315b37fcf3Sryker 		((BIO_SSL *)dbio->ptr)->renegotiate_count =
4325b37fcf3Sryker 		    ((BIO_SSL *)b->ptr)->renegotiate_count;
4335b37fcf3Sryker 		((BIO_SSL *)dbio->ptr)->byte_count =
4345b37fcf3Sryker 		    ((BIO_SSL *)b->ptr)->byte_count;
4355b37fcf3Sryker 		((BIO_SSL *)dbio->ptr)->renegotiate_timeout =
4365b37fcf3Sryker 		    ((BIO_SSL *)b->ptr)->renegotiate_timeout;
4375b37fcf3Sryker 		((BIO_SSL *)dbio->ptr)->last_time =
4385b37fcf3Sryker 		    ((BIO_SSL *)b->ptr)->last_time;
4395b37fcf3Sryker 		ret = (((BIO_SSL *)dbio->ptr)->ssl != NULL);
4405b37fcf3Sryker 		break;
4415b37fcf3Sryker 	case BIO_C_GET_FD:
4425b37fcf3Sryker 		ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
4435b37fcf3Sryker 		break;
4445b37fcf3Sryker 	case BIO_CTRL_SET_CALLBACK:
445ba5406e9Sbeck 		{
446ba5406e9Sbeck 			ret = 0;
447ba5406e9Sbeck 		}
4485b37fcf3Sryker 		break;
4495b37fcf3Sryker 	case BIO_CTRL_GET_CALLBACK:
4505b37fcf3Sryker 		{
4514fcf65c5Sdjm 			void (**fptr)(const SSL *xssl, int type, int val);
4525b37fcf3Sryker 
453f3742667Sbeck 			fptr = (void (**)(const SSL *xssl, int type, int val))
454f3742667Sbeck 			    ptr;
4555b37fcf3Sryker 			*fptr = SSL_get_info_callback(ssl);
4565b37fcf3Sryker 		}
4575b37fcf3Sryker 		break;
4585b37fcf3Sryker 	default:
4595b37fcf3Sryker 		ret = BIO_ctrl(ssl->rbio, cmd, num, ptr);
4605b37fcf3Sryker 		break;
4615b37fcf3Sryker 	}
4625b37fcf3Sryker 	return (ret);
4635b37fcf3Sryker }
4645b37fcf3Sryker 
4657c408a08Sjsing static long
ssl_callback_ctrl(BIO * b,int cmd,BIO_info_cb * fp)466c929ff6cStb ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
467ba5406e9Sbeck {
468ba5406e9Sbeck 	SSL *ssl;
469ba5406e9Sbeck 	BIO_SSL *bs;
470ba5406e9Sbeck 	long ret = 1;
471ba5406e9Sbeck 
472ba5406e9Sbeck 	bs = (BIO_SSL *)b->ptr;
473ba5406e9Sbeck 	ssl = bs->ssl;
4747c408a08Sjsing 	switch (cmd) {
475ba5406e9Sbeck 	case BIO_CTRL_SET_CALLBACK:
476ba5406e9Sbeck 		{
477da347917Sbeck 		/* FIXME: setting this via a completely different prototype
478da347917Sbeck 		   seems like a crap idea */
479f3742667Sbeck 			SSL_set_info_callback(ssl,
480f3742667Sbeck 			    (void (*)(const SSL *, int, int))fp);
481ba5406e9Sbeck 		}
482ba5406e9Sbeck 		break;
483ba5406e9Sbeck 	default:
484ba5406e9Sbeck 		ret = BIO_callback_ctrl(ssl->rbio, cmd, fp);
485ba5406e9Sbeck 		break;
486ba5406e9Sbeck 	}
487ba5406e9Sbeck 	return (ret);
488ba5406e9Sbeck }
489ba5406e9Sbeck 
4907c408a08Sjsing static int
ssl_puts(BIO * bp,const char * str)4917c408a08Sjsing ssl_puts(BIO *bp, const char *str)
4925b37fcf3Sryker {
4935b37fcf3Sryker 	int n, ret;
4945b37fcf3Sryker 
4955b37fcf3Sryker 	n = strlen(str);
4965b37fcf3Sryker 	ret = BIO_write(bp, str, n);
4975b37fcf3Sryker 	return (ret);
4985b37fcf3Sryker }
4995b37fcf3Sryker 
50052ada5cbSjsing BIO *
BIO_new_buffer_ssl_connect(SSL_CTX * ctx)50152ada5cbSjsing BIO_new_buffer_ssl_connect(SSL_CTX *ctx)
5025b37fcf3Sryker {
5035b37fcf3Sryker 	BIO *ret = NULL, *buf = NULL, *ssl = NULL;
5045b37fcf3Sryker 
5055b37fcf3Sryker 	if ((buf = BIO_new(BIO_f_buffer())) == NULL)
50607ae8dc8Sjsing 		goto err;
5075b37fcf3Sryker 	if ((ssl = BIO_new_ssl_connect(ctx)) == NULL)
5085b37fcf3Sryker 		goto err;
5095b37fcf3Sryker 	if ((ret = BIO_push(buf, ssl)) == NULL)
5105b37fcf3Sryker 		goto err;
5115b37fcf3Sryker 	return (ret);
51207ae8dc8Sjsing 
5135b37fcf3Sryker  err:
5147c408a08Sjsing 	BIO_free(buf);
5157c408a08Sjsing 	BIO_free(ssl);
5165b37fcf3Sryker 	return (NULL);
5175b37fcf3Sryker }
51871e04849Sbeck LSSL_ALIAS(BIO_new_buffer_ssl_connect);
5195b37fcf3Sryker 
52052ada5cbSjsing BIO *
BIO_new_ssl_connect(SSL_CTX * ctx)52152ada5cbSjsing BIO_new_ssl_connect(SSL_CTX *ctx)
5225b37fcf3Sryker {
5235b37fcf3Sryker 	BIO *ret = NULL, *con = NULL, *ssl = NULL;
5245b37fcf3Sryker 
5255b37fcf3Sryker 	if ((con = BIO_new(BIO_s_connect())) == NULL)
52607ae8dc8Sjsing 		goto err;
5275b37fcf3Sryker 	if ((ssl = BIO_new_ssl(ctx, 1)) == NULL)
5285b37fcf3Sryker 		goto err;
5295b37fcf3Sryker 	if ((ret = BIO_push(ssl, con)) == NULL)
5305b37fcf3Sryker 		goto err;
5315b37fcf3Sryker 	return (ret);
53207ae8dc8Sjsing 
5335b37fcf3Sryker  err:
5347c408a08Sjsing 	BIO_free(con);
53507ae8dc8Sjsing 	BIO_free(ssl);
5365b37fcf3Sryker 	return (NULL);
5375b37fcf3Sryker }
538cedac418Stb LSSL_ALIAS(BIO_new_ssl_connect);
5395b37fcf3Sryker 
54052ada5cbSjsing BIO *
BIO_new_ssl(SSL_CTX * ctx,int client)54152ada5cbSjsing BIO_new_ssl(SSL_CTX *ctx, int client)
5425b37fcf3Sryker {
5435b37fcf3Sryker 	BIO *ret;
5445b37fcf3Sryker 	SSL *ssl;
5455b37fcf3Sryker 
5465b37fcf3Sryker 	if ((ret = BIO_new(BIO_f_ssl())) == NULL)
54707ae8dc8Sjsing 		goto err;
54807ae8dc8Sjsing 	if ((ssl = SSL_new(ctx)) == NULL)
54907ae8dc8Sjsing 		goto err;
55007ae8dc8Sjsing 
5515b37fcf3Sryker 	if (client)
5525b37fcf3Sryker 		SSL_set_connect_state(ssl);
5535b37fcf3Sryker 	else
5545b37fcf3Sryker 		SSL_set_accept_state(ssl);
5555b37fcf3Sryker 
5565b37fcf3Sryker 	BIO_set_ssl(ret, ssl, BIO_CLOSE);
5575b37fcf3Sryker 	return (ret);
55807ae8dc8Sjsing 
55907ae8dc8Sjsing  err:
56007ae8dc8Sjsing 	BIO_free(ret);
56107ae8dc8Sjsing 	return (NULL);
5625b37fcf3Sryker }
563cedac418Stb LSSL_ALIAS(BIO_new_ssl);
5645b37fcf3Sryker 
5657c408a08Sjsing int
BIO_ssl_copy_session_id(BIO * t,BIO * f)5667c408a08Sjsing BIO_ssl_copy_session_id(BIO *t, BIO *f)
5675b37fcf3Sryker {
5685b37fcf3Sryker 	t = BIO_find_type(t, BIO_TYPE_SSL);
5695b37fcf3Sryker 	f = BIO_find_type(f, BIO_TYPE_SSL);
5705b37fcf3Sryker 	if ((t == NULL) || (f == NULL))
5715b37fcf3Sryker 		return (0);
5725b37fcf3Sryker 	if ((((BIO_SSL *)t->ptr)->ssl == NULL) ||
5735b37fcf3Sryker 	    (((BIO_SSL *)f->ptr)->ssl == NULL))
5745b37fcf3Sryker 		return (0);
5751e7a28f3Stb 	if (!SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,
5761e7a28f3Stb 	    ((BIO_SSL *)f->ptr)->ssl))
5771e7a28f3Stb 		return (0);
5785b37fcf3Sryker 	return (1);
5795b37fcf3Sryker }
580*82821a61Stb LSSL_ALIAS(BIO_ssl_copy_session_id);
5815b37fcf3Sryker 
5827c408a08Sjsing void
BIO_ssl_shutdown(BIO * b)5837c408a08Sjsing BIO_ssl_shutdown(BIO *b)
5845b37fcf3Sryker {
5855b37fcf3Sryker 	SSL *s;
5865b37fcf3Sryker 
5877c408a08Sjsing 	while (b != NULL) {
5887c408a08Sjsing 		if (b->method->type == BIO_TYPE_SSL) {
5895b37fcf3Sryker 			s = ((BIO_SSL *)b->ptr)->ssl;
5905b37fcf3Sryker 			SSL_shutdown(s);
5915b37fcf3Sryker 			break;
5925b37fcf3Sryker 		}
5935b37fcf3Sryker 		b = b->next_bio;
5945b37fcf3Sryker 	}
5955b37fcf3Sryker }
59671e04849Sbeck LSSL_ALIAS(BIO_ssl_shutdown);
597