xref: /freebsd/contrib/ntp/sntp/libevent/bufferevent_openssl.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
32b15cb3dSCy Schubert  *
42b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
52b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
62b15cb3dSCy Schubert  * are met:
72b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
82b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
92b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
102b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
112b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
122b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
132b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
142b15cb3dSCy Schubert  *
152b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
172b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
182b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
192b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
212b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
242b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252b15cb3dSCy Schubert  */
262b15cb3dSCy Schubert 
272b15cb3dSCy Schubert // Get rid of OSX 10.7 and greater deprecation warnings.
282b15cb3dSCy Schubert #if defined(__APPLE__) && defined(__clang__)
292b15cb3dSCy Schubert #pragma clang diagnostic ignored "-Wdeprecated-declarations"
302b15cb3dSCy Schubert #endif
312b15cb3dSCy Schubert 
322b15cb3dSCy Schubert #include "event2/event-config.h"
332b15cb3dSCy Schubert #include "evconfig-private.h"
342b15cb3dSCy Schubert 
352b15cb3dSCy Schubert #include <sys/types.h>
362b15cb3dSCy Schubert 
372b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H
382b15cb3dSCy Schubert #include <sys/time.h>
392b15cb3dSCy Schubert #endif
402b15cb3dSCy Schubert 
412b15cb3dSCy Schubert #include <errno.h>
422b15cb3dSCy Schubert #include <stdio.h>
432b15cb3dSCy Schubert #include <stdlib.h>
442b15cb3dSCy Schubert #include <string.h>
452b15cb3dSCy Schubert #ifdef EVENT__HAVE_STDARG_H
462b15cb3dSCy Schubert #include <stdarg.h>
472b15cb3dSCy Schubert #endif
482b15cb3dSCy Schubert #ifdef EVENT__HAVE_UNISTD_H
492b15cb3dSCy Schubert #include <unistd.h>
502b15cb3dSCy Schubert #endif
512b15cb3dSCy Schubert 
522b15cb3dSCy Schubert #ifdef _WIN32
532b15cb3dSCy Schubert #include <winsock2.h>
542b15cb3dSCy Schubert #endif
552b15cb3dSCy Schubert 
562b15cb3dSCy Schubert #include "event2/bufferevent.h"
572b15cb3dSCy Schubert #include "event2/bufferevent_struct.h"
582b15cb3dSCy Schubert #include "event2/bufferevent_ssl.h"
592b15cb3dSCy Schubert #include "event2/buffer.h"
602b15cb3dSCy Schubert #include "event2/event.h"
612b15cb3dSCy Schubert 
622b15cb3dSCy Schubert #include "mm-internal.h"
632b15cb3dSCy Schubert #include "bufferevent-internal.h"
642b15cb3dSCy Schubert #include "log-internal.h"
652b15cb3dSCy Schubert 
662b15cb3dSCy Schubert #include <openssl/ssl.h>
672b15cb3dSCy Schubert #include <openssl/err.h>
68*a466cc55SCy Schubert #include "openssl-compat.h"
692b15cb3dSCy Schubert 
702b15cb3dSCy Schubert /*
712b15cb3dSCy Schubert  * Define an OpenSSL bio that targets a bufferevent.
722b15cb3dSCy Schubert  */
732b15cb3dSCy Schubert 
742b15cb3dSCy Schubert /* --------------------
752b15cb3dSCy Schubert    A BIO is an OpenSSL abstraction that handles reading and writing data.  The
762b15cb3dSCy Schubert    library will happily speak SSL over anything that implements a BIO
772b15cb3dSCy Schubert    interface.
782b15cb3dSCy Schubert 
792b15cb3dSCy Schubert    Here we define a BIO implementation that directs its output to a
802b15cb3dSCy Schubert    bufferevent.  We'll want to use this only when none of OpenSSL's built-in
812b15cb3dSCy Schubert    IO mechanisms work for us.
822b15cb3dSCy Schubert    -------------------- */
832b15cb3dSCy Schubert 
842b15cb3dSCy Schubert /* every BIO type needs its own integer type value. */
852b15cb3dSCy Schubert #define BIO_TYPE_LIBEVENT 57
862b15cb3dSCy Schubert /* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on
872b15cb3dSCy Schubert  * this. */
882b15cb3dSCy Schubert 
892b15cb3dSCy Schubert #if 0
902b15cb3dSCy Schubert static void
912b15cb3dSCy Schubert print_err(int val)
922b15cb3dSCy Schubert {
932b15cb3dSCy Schubert 	int err;
942b15cb3dSCy Schubert 	printf("Error was %d\n", val);
952b15cb3dSCy Schubert 
962b15cb3dSCy Schubert 	while ((err = ERR_get_error())) {
972b15cb3dSCy Schubert 		const char *msg = (const char*)ERR_reason_error_string(err);
982b15cb3dSCy Schubert 		const char *lib = (const char*)ERR_lib_error_string(err);
992b15cb3dSCy Schubert 		const char *func = (const char*)ERR_func_error_string(err);
1002b15cb3dSCy Schubert 
1012b15cb3dSCy Schubert 		printf("%s in %s %s\n", msg, lib, func);
1022b15cb3dSCy Schubert 	}
1032b15cb3dSCy Schubert }
1042b15cb3dSCy Schubert #else
1052b15cb3dSCy Schubert #define print_err(v) ((void)0)
1062b15cb3dSCy Schubert #endif
1072b15cb3dSCy Schubert 
1082b15cb3dSCy Schubert /* Called to initialize a new BIO */
1092b15cb3dSCy Schubert static int
bio_bufferevent_new(BIO * b)1102b15cb3dSCy Schubert bio_bufferevent_new(BIO *b)
1112b15cb3dSCy Schubert {
112*a466cc55SCy Schubert 	BIO_set_init(b, 0);
113*a466cc55SCy Schubert 	BIO_set_data(b, NULL); /* We'll be putting the bufferevent in this field.*/
1142b15cb3dSCy Schubert 	return 1;
1152b15cb3dSCy Schubert }
1162b15cb3dSCy Schubert 
1172b15cb3dSCy Schubert /* Called to uninitialize the BIO. */
1182b15cb3dSCy Schubert static int
bio_bufferevent_free(BIO * b)1192b15cb3dSCy Schubert bio_bufferevent_free(BIO *b)
1202b15cb3dSCy Schubert {
1212b15cb3dSCy Schubert 	if (!b)
1222b15cb3dSCy Schubert 		return 0;
123*a466cc55SCy Schubert 	if (BIO_get_shutdown(b)) {
124*a466cc55SCy Schubert 		if (BIO_get_init(b) && BIO_get_data(b))
125*a466cc55SCy Schubert 			bufferevent_free(BIO_get_data(b));
126*a466cc55SCy Schubert 		BIO_free(b);
1272b15cb3dSCy Schubert 	}
1282b15cb3dSCy Schubert 	return 1;
1292b15cb3dSCy Schubert }
1302b15cb3dSCy Schubert 
1312b15cb3dSCy Schubert /* Called to extract data from the BIO. */
1322b15cb3dSCy Schubert static int
bio_bufferevent_read(BIO * b,char * out,int outlen)1332b15cb3dSCy Schubert bio_bufferevent_read(BIO *b, char *out, int outlen)
1342b15cb3dSCy Schubert {
1352b15cb3dSCy Schubert 	int r = 0;
1362b15cb3dSCy Schubert 	struct evbuffer *input;
1372b15cb3dSCy Schubert 
1382b15cb3dSCy Schubert 	BIO_clear_retry_flags(b);
1392b15cb3dSCy Schubert 
1402b15cb3dSCy Schubert 	if (!out)
1412b15cb3dSCy Schubert 		return 0;
142*a466cc55SCy Schubert 	if (!BIO_get_data(b))
1432b15cb3dSCy Schubert 		return -1;
1442b15cb3dSCy Schubert 
145*a466cc55SCy Schubert 	input = bufferevent_get_input(BIO_get_data(b));
1462b15cb3dSCy Schubert 	if (evbuffer_get_length(input) == 0) {
1472b15cb3dSCy Schubert 		/* If there's no data to read, say so. */
1482b15cb3dSCy Schubert 		BIO_set_retry_read(b);
1492b15cb3dSCy Schubert 		return -1;
1502b15cb3dSCy Schubert 	} else {
1512b15cb3dSCy Schubert 		r = evbuffer_remove(input, out, outlen);
1522b15cb3dSCy Schubert 	}
1532b15cb3dSCy Schubert 
1542b15cb3dSCy Schubert 	return r;
1552b15cb3dSCy Schubert }
1562b15cb3dSCy Schubert 
157*a466cc55SCy Schubert /* Called to write data into the BIO */
1582b15cb3dSCy Schubert static int
bio_bufferevent_write(BIO * b,const char * in,int inlen)1592b15cb3dSCy Schubert bio_bufferevent_write(BIO *b, const char *in, int inlen)
1602b15cb3dSCy Schubert {
161*a466cc55SCy Schubert 	struct bufferevent *bufev = BIO_get_data(b);
1622b15cb3dSCy Schubert 	struct evbuffer *output;
1632b15cb3dSCy Schubert 	size_t outlen;
1642b15cb3dSCy Schubert 
1652b15cb3dSCy Schubert 	BIO_clear_retry_flags(b);
1662b15cb3dSCy Schubert 
167*a466cc55SCy Schubert 	if (!BIO_get_data(b))
1682b15cb3dSCy Schubert 		return -1;
1692b15cb3dSCy Schubert 
1702b15cb3dSCy Schubert 	output = bufferevent_get_output(bufev);
1712b15cb3dSCy Schubert 	outlen = evbuffer_get_length(output);
1722b15cb3dSCy Schubert 
1732b15cb3dSCy Schubert 	/* Copy only as much data onto the output buffer as can fit under the
1742b15cb3dSCy Schubert 	 * high-water mark. */
1752b15cb3dSCy Schubert 	if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {
1762b15cb3dSCy Schubert 		if (bufev->wm_write.high <= outlen) {
1772b15cb3dSCy Schubert 			/* If no data can fit, we'll need to retry later. */
1782b15cb3dSCy Schubert 			BIO_set_retry_write(b);
1792b15cb3dSCy Schubert 			return -1;
1802b15cb3dSCy Schubert 		}
1812b15cb3dSCy Schubert 		inlen = bufev->wm_write.high - outlen;
1822b15cb3dSCy Schubert 	}
1832b15cb3dSCy Schubert 
1842b15cb3dSCy Schubert 	EVUTIL_ASSERT(inlen > 0);
1852b15cb3dSCy Schubert 	evbuffer_add(output, in, inlen);
1862b15cb3dSCy Schubert 	return inlen;
1872b15cb3dSCy Schubert }
1882b15cb3dSCy Schubert 
1892b15cb3dSCy Schubert /* Called to handle various requests */
1902b15cb3dSCy Schubert static long
bio_bufferevent_ctrl(BIO * b,int cmd,long num,void * ptr)1912b15cb3dSCy Schubert bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)
1922b15cb3dSCy Schubert {
193*a466cc55SCy Schubert 	struct bufferevent *bufev = BIO_get_data(b);
1942b15cb3dSCy Schubert 	long ret = 1;
1952b15cb3dSCy Schubert 
1962b15cb3dSCy Schubert 	switch (cmd) {
1972b15cb3dSCy Schubert 	case BIO_CTRL_GET_CLOSE:
198*a466cc55SCy Schubert 		ret = BIO_get_shutdown(b);
1992b15cb3dSCy Schubert 		break;
2002b15cb3dSCy Schubert 	case BIO_CTRL_SET_CLOSE:
201*a466cc55SCy Schubert 		BIO_set_shutdown(b, (int)num);
2022b15cb3dSCy Schubert 		break;
2032b15cb3dSCy Schubert 	case BIO_CTRL_PENDING:
2042b15cb3dSCy Schubert 		ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;
2052b15cb3dSCy Schubert 		break;
2062b15cb3dSCy Schubert 	case BIO_CTRL_WPENDING:
2072b15cb3dSCy Schubert 		ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0;
2082b15cb3dSCy Schubert 		break;
2092b15cb3dSCy Schubert 	/* XXXX These two are given a special-case treatment because
2102b15cb3dSCy Schubert 	 * of cargo-cultism.  I should come up with a better reason. */
2112b15cb3dSCy Schubert 	case BIO_CTRL_DUP:
2122b15cb3dSCy Schubert 	case BIO_CTRL_FLUSH:
2132b15cb3dSCy Schubert 		ret = 1;
2142b15cb3dSCy Schubert 		break;
2152b15cb3dSCy Schubert 	default:
2162b15cb3dSCy Schubert 		ret = 0;
2172b15cb3dSCy Schubert 		break;
2182b15cb3dSCy Schubert 	}
2192b15cb3dSCy Schubert 	return ret;
2202b15cb3dSCy Schubert }
2212b15cb3dSCy Schubert 
2222b15cb3dSCy Schubert /* Called to write a string to the BIO */
2232b15cb3dSCy Schubert static int
bio_bufferevent_puts(BIO * b,const char * s)2242b15cb3dSCy Schubert bio_bufferevent_puts(BIO *b, const char *s)
2252b15cb3dSCy Schubert {
2262b15cb3dSCy Schubert 	return bio_bufferevent_write(b, s, strlen(s));
2272b15cb3dSCy Schubert }
2282b15cb3dSCy Schubert 
2292b15cb3dSCy Schubert /* Method table for the bufferevent BIO */
230*a466cc55SCy Schubert static BIO_METHOD *methods_bufferevent;
2312b15cb3dSCy Schubert 
2322b15cb3dSCy Schubert /* Return the method table for the bufferevents BIO */
2332b15cb3dSCy Schubert static BIO_METHOD *
BIO_s_bufferevent(void)2342b15cb3dSCy Schubert BIO_s_bufferevent(void)
2352b15cb3dSCy Schubert {
236*a466cc55SCy Schubert 	if (methods_bufferevent == NULL) {
237*a466cc55SCy Schubert 		methods_bufferevent = BIO_meth_new(BIO_TYPE_LIBEVENT, "bufferevent");
238*a466cc55SCy Schubert 		if (methods_bufferevent == NULL)
239*a466cc55SCy Schubert 			return NULL;
240*a466cc55SCy Schubert 		BIO_meth_set_write(methods_bufferevent, bio_bufferevent_write);
241*a466cc55SCy Schubert 		BIO_meth_set_read(methods_bufferevent, bio_bufferevent_read);
242*a466cc55SCy Schubert 		BIO_meth_set_puts(methods_bufferevent, bio_bufferevent_puts);
243*a466cc55SCy Schubert 		BIO_meth_set_ctrl(methods_bufferevent, bio_bufferevent_ctrl);
244*a466cc55SCy Schubert 		BIO_meth_set_create(methods_bufferevent, bio_bufferevent_new);
245*a466cc55SCy Schubert 		BIO_meth_set_destroy(methods_bufferevent, bio_bufferevent_free);
246*a466cc55SCy Schubert 	}
247*a466cc55SCy Schubert 	return methods_bufferevent;
2482b15cb3dSCy Schubert }
2492b15cb3dSCy Schubert 
2502b15cb3dSCy Schubert /* Create a new BIO to wrap communication around a bufferevent.  If close_flag
2512b15cb3dSCy Schubert  * is true, the bufferevent will be freed when the BIO is closed. */
2522b15cb3dSCy Schubert static BIO *
BIO_new_bufferevent(struct bufferevent * bufferevent)253*a466cc55SCy Schubert BIO_new_bufferevent(struct bufferevent *bufferevent)
2542b15cb3dSCy Schubert {
2552b15cb3dSCy Schubert 	BIO *result;
2562b15cb3dSCy Schubert 	if (!bufferevent)
2572b15cb3dSCy Schubert 		return NULL;
2582b15cb3dSCy Schubert 	if (!(result = BIO_new(BIO_s_bufferevent())))
2592b15cb3dSCy Schubert 		return NULL;
260*a466cc55SCy Schubert 	BIO_set_init(result, 1);
261*a466cc55SCy Schubert 	BIO_set_data(result, bufferevent);
262*a466cc55SCy Schubert 	/* We don't tell the BIO to close the bufferevent; we do it ourselves on
263*a466cc55SCy Schubert 	 * be_openssl_destruct() */
264*a466cc55SCy Schubert 	BIO_set_shutdown(result, 0);
2652b15cb3dSCy Schubert 	return result;
2662b15cb3dSCy Schubert }
2672b15cb3dSCy Schubert 
2682b15cb3dSCy Schubert /* --------------------
2692b15cb3dSCy Schubert    Now, here's the OpenSSL-based implementation of bufferevent.
2702b15cb3dSCy Schubert 
2712b15cb3dSCy Schubert    The implementation comes in two flavors: one that connects its SSL object
2722b15cb3dSCy Schubert    to an underlying bufferevent using a BIO_bufferevent, and one that has the
2732b15cb3dSCy Schubert    SSL object connect to a socket directly.  The latter should generally be
2742b15cb3dSCy Schubert    faster, except on Windows, where your best bet is using a
2752b15cb3dSCy Schubert    bufferevent_async.
2762b15cb3dSCy Schubert 
2772b15cb3dSCy Schubert    (OpenSSL supports many other BIO types, too.  But we can't use any unless
2782b15cb3dSCy Schubert    we have a good way to get notified when they become readable/writable.)
2792b15cb3dSCy Schubert    -------------------- */
2802b15cb3dSCy Schubert 
2812b15cb3dSCy Schubert struct bio_data_counts {
2822b15cb3dSCy Schubert 	unsigned long n_written;
2832b15cb3dSCy Schubert 	unsigned long n_read;
2842b15cb3dSCy Schubert };
2852b15cb3dSCy Schubert 
2862b15cb3dSCy Schubert struct bufferevent_openssl {
2872b15cb3dSCy Schubert 	/* Shared fields with common bufferevent implementation code.
2882b15cb3dSCy Schubert 	   If we were set up with an underlying bufferevent, we use the
2892b15cb3dSCy Schubert 	   events here as timers only.  If we have an SSL, then we use
2902b15cb3dSCy Schubert 	   the events as socket events.
2912b15cb3dSCy Schubert 	 */
2922b15cb3dSCy Schubert 	struct bufferevent_private bev;
2932b15cb3dSCy Schubert 	/* An underlying bufferevent that we're directing our output to.
2942b15cb3dSCy Schubert 	   If it's NULL, then we're connected to an fd, not an evbuffer. */
2952b15cb3dSCy Schubert 	struct bufferevent *underlying;
2962b15cb3dSCy Schubert 	/* The SSL object doing our encryption. */
2972b15cb3dSCy Schubert 	SSL *ssl;
2982b15cb3dSCy Schubert 
2992b15cb3dSCy Schubert 	/* A callback that's invoked when data arrives on our outbuf so we
3002b15cb3dSCy Schubert 	   know to write data to the SSL. */
3012b15cb3dSCy Schubert 	struct evbuffer_cb_entry *outbuf_cb;
3022b15cb3dSCy Schubert 
3032b15cb3dSCy Schubert 	/* A count of how much data the bios have read/written total.  Used
3042b15cb3dSCy Schubert 	   for rate-limiting. */
3052b15cb3dSCy Schubert 	struct bio_data_counts counts;
3062b15cb3dSCy Schubert 
3072b15cb3dSCy Schubert 	/* If this value is greater than 0, then the last SSL_write blocked,
3082b15cb3dSCy Schubert 	 * and we need to try it again with this many bytes. */
3092b15cb3dSCy Schubert 	ev_ssize_t last_write;
3102b15cb3dSCy Schubert 
3112b15cb3dSCy Schubert #define NUM_ERRORS 3
3122b15cb3dSCy Schubert 	ev_uint32_t errors[NUM_ERRORS];
3132b15cb3dSCy Schubert 
3142b15cb3dSCy Schubert 	/* When we next get available space, we should say "read" instead of
3152b15cb3dSCy Schubert 	   "write". This can happen if there's a renegotiation during a read
3162b15cb3dSCy Schubert 	   operation. */
3172b15cb3dSCy Schubert 	unsigned read_blocked_on_write : 1;
3182b15cb3dSCy Schubert 	/* When we next get data, we should say "write" instead of "read". */
3192b15cb3dSCy Schubert 	unsigned write_blocked_on_read : 1;
3202b15cb3dSCy Schubert 	/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
3212b15cb3dSCy Schubert 	unsigned allow_dirty_shutdown : 1;
3222b15cb3dSCy Schubert 	/* XXX */
3232b15cb3dSCy Schubert 	unsigned n_errors : 2;
3242b15cb3dSCy Schubert 
3252b15cb3dSCy Schubert 	/* Are we currently connecting, accepting, or doing IO? */
3262b15cb3dSCy Schubert 	unsigned state : 2;
327*a466cc55SCy Schubert 	/* If we reset fd, we sould reset state too */
328*a466cc55SCy Schubert 	unsigned old_state : 2;
3292b15cb3dSCy Schubert };
3302b15cb3dSCy Schubert 
3312b15cb3dSCy Schubert static int be_openssl_enable(struct bufferevent *, short);
3322b15cb3dSCy Schubert static int be_openssl_disable(struct bufferevent *, short);
3332b15cb3dSCy Schubert static void be_openssl_unlink(struct bufferevent *);
3342b15cb3dSCy Schubert static void be_openssl_destruct(struct bufferevent *);
3352b15cb3dSCy Schubert static int be_openssl_adj_timeouts(struct bufferevent *);
3362b15cb3dSCy Schubert static int be_openssl_flush(struct bufferevent *bufev,
3372b15cb3dSCy Schubert     short iotype, enum bufferevent_flush_mode mode);
3382b15cb3dSCy Schubert static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
3392b15cb3dSCy Schubert 
3402b15cb3dSCy Schubert const struct bufferevent_ops bufferevent_ops_openssl = {
3412b15cb3dSCy Schubert 	"ssl",
3422b15cb3dSCy Schubert 	evutil_offsetof(struct bufferevent_openssl, bev.bev),
3432b15cb3dSCy Schubert 	be_openssl_enable,
3442b15cb3dSCy Schubert 	be_openssl_disable,
3452b15cb3dSCy Schubert 	be_openssl_unlink,
3462b15cb3dSCy Schubert 	be_openssl_destruct,
3472b15cb3dSCy Schubert 	be_openssl_adj_timeouts,
3482b15cb3dSCy Schubert 	be_openssl_flush,
3492b15cb3dSCy Schubert 	be_openssl_ctrl,
3502b15cb3dSCy Schubert };
3512b15cb3dSCy Schubert 
3522b15cb3dSCy Schubert /* Given a bufferevent, return a pointer to the bufferevent_openssl that
3532b15cb3dSCy Schubert  * contains it, if any. */
3542b15cb3dSCy Schubert static inline struct bufferevent_openssl *
upcast(struct bufferevent * bev)3552b15cb3dSCy Schubert upcast(struct bufferevent *bev)
3562b15cb3dSCy Schubert {
3572b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_o;
358*a466cc55SCy Schubert 	if (!BEV_IS_OPENSSL(bev))
3592b15cb3dSCy Schubert 		return NULL;
3602b15cb3dSCy Schubert 	bev_o = (void*)( ((char*)bev) -
3612b15cb3dSCy Schubert 			 evutil_offsetof(struct bufferevent_openssl, bev.bev));
362*a466cc55SCy Schubert 	EVUTIL_ASSERT(BEV_IS_OPENSSL(&bev_o->bev.bev));
3632b15cb3dSCy Schubert 	return bev_o;
3642b15cb3dSCy Schubert }
3652b15cb3dSCy Schubert 
3662b15cb3dSCy Schubert static inline void
put_error(struct bufferevent_openssl * bev_ssl,unsigned long err)3672b15cb3dSCy Schubert put_error(struct bufferevent_openssl *bev_ssl, unsigned long err)
3682b15cb3dSCy Schubert {
3692b15cb3dSCy Schubert 	if (bev_ssl->n_errors == NUM_ERRORS)
3702b15cb3dSCy Schubert 		return;
3712b15cb3dSCy Schubert 	/* The error type according to openssl is "unsigned long", but
3722b15cb3dSCy Schubert 	   openssl never uses more than 32 bits of it.  It _can't_ use more
3732b15cb3dSCy Schubert 	   than 32 bits of it, since it needs to report errors on systems
3742b15cb3dSCy Schubert 	   where long is only 32 bits.
3752b15cb3dSCy Schubert 	 */
3762b15cb3dSCy Schubert 	bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err;
3772b15cb3dSCy Schubert }
3782b15cb3dSCy Schubert 
3792b15cb3dSCy Schubert /* Have the base communications channel (either the underlying bufferevent or
3802b15cb3dSCy Schubert  * ev_read and ev_write) start reading.  Take the read-blocked-on-write flag
3812b15cb3dSCy Schubert  * into account. */
3822b15cb3dSCy Schubert static int
start_reading(struct bufferevent_openssl * bev_ssl)3832b15cb3dSCy Schubert start_reading(struct bufferevent_openssl *bev_ssl)
3842b15cb3dSCy Schubert {
3852b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
3862b15cb3dSCy Schubert 		bufferevent_unsuspend_read_(bev_ssl->underlying,
3872b15cb3dSCy Schubert 		    BEV_SUSPEND_FILT_READ);
3882b15cb3dSCy Schubert 		return 0;
3892b15cb3dSCy Schubert 	} else {
3902b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
3912b15cb3dSCy Schubert 		int r;
3922b15cb3dSCy Schubert 		r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
3932b15cb3dSCy Schubert 		if (r == 0 && bev_ssl->read_blocked_on_write)
3942b15cb3dSCy Schubert 			r = bufferevent_add_event_(&bev->ev_write,
3952b15cb3dSCy Schubert 			    &bev->timeout_write);
3962b15cb3dSCy Schubert 		return r;
3972b15cb3dSCy Schubert 	}
3982b15cb3dSCy Schubert }
3992b15cb3dSCy Schubert 
4002b15cb3dSCy Schubert /* Have the base communications channel (either the underlying bufferevent or
4012b15cb3dSCy Schubert  * ev_read and ev_write) start writing.  Take the write-blocked-on-read flag
4022b15cb3dSCy Schubert  * into account. */
4032b15cb3dSCy Schubert static int
start_writing(struct bufferevent_openssl * bev_ssl)4042b15cb3dSCy Schubert start_writing(struct bufferevent_openssl *bev_ssl)
4052b15cb3dSCy Schubert {
4062b15cb3dSCy Schubert 	int r = 0;
4072b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
408*a466cc55SCy Schubert 		if (bev_ssl->write_blocked_on_read) {
409*a466cc55SCy Schubert 			bufferevent_unsuspend_read_(bev_ssl->underlying,
410*a466cc55SCy Schubert 			    BEV_SUSPEND_FILT_READ);
411*a466cc55SCy Schubert 		}
4122b15cb3dSCy Schubert 	} else {
4132b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
4142b15cb3dSCy Schubert 		r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
4152b15cb3dSCy Schubert 		if (!r && bev_ssl->write_blocked_on_read)
4162b15cb3dSCy Schubert 			r = bufferevent_add_event_(&bev->ev_read,
4172b15cb3dSCy Schubert 			    &bev->timeout_read);
4182b15cb3dSCy Schubert 	}
4192b15cb3dSCy Schubert 	return r;
4202b15cb3dSCy Schubert }
4212b15cb3dSCy Schubert 
4222b15cb3dSCy Schubert static void
stop_reading(struct bufferevent_openssl * bev_ssl)4232b15cb3dSCy Schubert stop_reading(struct bufferevent_openssl *bev_ssl)
4242b15cb3dSCy Schubert {
4252b15cb3dSCy Schubert 	if (bev_ssl->write_blocked_on_read)
4262b15cb3dSCy Schubert 		return;
4272b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
4282b15cb3dSCy Schubert 		bufferevent_suspend_read_(bev_ssl->underlying,
4292b15cb3dSCy Schubert 		    BEV_SUSPEND_FILT_READ);
4302b15cb3dSCy Schubert 	} else {
4312b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
4322b15cb3dSCy Schubert 		event_del(&bev->ev_read);
4332b15cb3dSCy Schubert 	}
4342b15cb3dSCy Schubert }
4352b15cb3dSCy Schubert 
4362b15cb3dSCy Schubert static void
stop_writing(struct bufferevent_openssl * bev_ssl)4372b15cb3dSCy Schubert stop_writing(struct bufferevent_openssl *bev_ssl)
4382b15cb3dSCy Schubert {
4392b15cb3dSCy Schubert 	if (bev_ssl->read_blocked_on_write)
4402b15cb3dSCy Schubert 		return;
4412b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
442*a466cc55SCy Schubert 		bufferevent_unsuspend_read_(bev_ssl->underlying,
443*a466cc55SCy Schubert 		    BEV_SUSPEND_FILT_READ);
4442b15cb3dSCy Schubert 	} else {
4452b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
4462b15cb3dSCy Schubert 		event_del(&bev->ev_write);
4472b15cb3dSCy Schubert 	}
4482b15cb3dSCy Schubert }
4492b15cb3dSCy Schubert 
4502b15cb3dSCy Schubert static int
set_rbow(struct bufferevent_openssl * bev_ssl)4512b15cb3dSCy Schubert set_rbow(struct bufferevent_openssl *bev_ssl)
4522b15cb3dSCy Schubert {
4532b15cb3dSCy Schubert 	if (!bev_ssl->underlying)
4542b15cb3dSCy Schubert 		stop_reading(bev_ssl);
4552b15cb3dSCy Schubert 	bev_ssl->read_blocked_on_write = 1;
4562b15cb3dSCy Schubert 	return start_writing(bev_ssl);
4572b15cb3dSCy Schubert }
4582b15cb3dSCy Schubert 
4592b15cb3dSCy Schubert static int
set_wbor(struct bufferevent_openssl * bev_ssl)4602b15cb3dSCy Schubert set_wbor(struct bufferevent_openssl *bev_ssl)
4612b15cb3dSCy Schubert {
4622b15cb3dSCy Schubert 	if (!bev_ssl->underlying)
4632b15cb3dSCy Schubert 		stop_writing(bev_ssl);
4642b15cb3dSCy Schubert 	bev_ssl->write_blocked_on_read = 1;
4652b15cb3dSCy Schubert 	return start_reading(bev_ssl);
4662b15cb3dSCy Schubert }
4672b15cb3dSCy Schubert 
4682b15cb3dSCy Schubert static int
clear_rbow(struct bufferevent_openssl * bev_ssl)4692b15cb3dSCy Schubert clear_rbow(struct bufferevent_openssl *bev_ssl)
4702b15cb3dSCy Schubert {
4712b15cb3dSCy Schubert 	struct bufferevent *bev = &bev_ssl->bev.bev;
4722b15cb3dSCy Schubert 	int r = 0;
4732b15cb3dSCy Schubert 	bev_ssl->read_blocked_on_write = 0;
4742b15cb3dSCy Schubert 	if (!(bev->enabled & EV_WRITE))
4752b15cb3dSCy Schubert 		stop_writing(bev_ssl);
4762b15cb3dSCy Schubert 	if (bev->enabled & EV_READ)
4772b15cb3dSCy Schubert 		r = start_reading(bev_ssl);
4782b15cb3dSCy Schubert 	return r;
4792b15cb3dSCy Schubert }
4802b15cb3dSCy Schubert 
4812b15cb3dSCy Schubert 
4822b15cb3dSCy Schubert static int
clear_wbor(struct bufferevent_openssl * bev_ssl)4832b15cb3dSCy Schubert clear_wbor(struct bufferevent_openssl *bev_ssl)
4842b15cb3dSCy Schubert {
4852b15cb3dSCy Schubert 	struct bufferevent *bev = &bev_ssl->bev.bev;
4862b15cb3dSCy Schubert 	int r = 0;
4872b15cb3dSCy Schubert 	bev_ssl->write_blocked_on_read = 0;
4882b15cb3dSCy Schubert 	if (!(bev->enabled & EV_READ))
4892b15cb3dSCy Schubert 		stop_reading(bev_ssl);
4902b15cb3dSCy Schubert 	if (bev->enabled & EV_WRITE)
4912b15cb3dSCy Schubert 		r = start_writing(bev_ssl);
4922b15cb3dSCy Schubert 	return r;
4932b15cb3dSCy Schubert }
4942b15cb3dSCy Schubert 
4952b15cb3dSCy Schubert static void
conn_closed(struct bufferevent_openssl * bev_ssl,int when,int errcode,int ret)4962b15cb3dSCy Schubert conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret)
4972b15cb3dSCy Schubert {
4982b15cb3dSCy Schubert 	int event = BEV_EVENT_ERROR;
4992b15cb3dSCy Schubert 	int dirty_shutdown = 0;
5002b15cb3dSCy Schubert 	unsigned long err;
5012b15cb3dSCy Schubert 
5022b15cb3dSCy Schubert 	switch (errcode) {
5032b15cb3dSCy Schubert 	case SSL_ERROR_ZERO_RETURN:
5042b15cb3dSCy Schubert 		/* Possibly a clean shutdown. */
5052b15cb3dSCy Schubert 		if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)
5062b15cb3dSCy Schubert 			event = BEV_EVENT_EOF;
5072b15cb3dSCy Schubert 		else
5082b15cb3dSCy Schubert 			dirty_shutdown = 1;
5092b15cb3dSCy Schubert 		break;
5102b15cb3dSCy Schubert 	case SSL_ERROR_SYSCALL:
5112b15cb3dSCy Schubert 		/* IO error; possibly a dirty shutdown. */
512*a466cc55SCy Schubert 		if ((ret == 0 || ret == -1) && ERR_peek_error() == 0)
5132b15cb3dSCy Schubert 			dirty_shutdown = 1;
514*a466cc55SCy Schubert 		put_error(bev_ssl, errcode);
5152b15cb3dSCy Schubert 		break;
5162b15cb3dSCy Schubert 	case SSL_ERROR_SSL:
5172b15cb3dSCy Schubert 		/* Protocol error. */
518*a466cc55SCy Schubert 		put_error(bev_ssl, errcode);
5192b15cb3dSCy Schubert 		break;
5202b15cb3dSCy Schubert 	case SSL_ERROR_WANT_X509_LOOKUP:
5212b15cb3dSCy Schubert 		/* XXXX handle this. */
522*a466cc55SCy Schubert 		put_error(bev_ssl, errcode);
5232b15cb3dSCy Schubert 		break;
5242b15cb3dSCy Schubert 	case SSL_ERROR_NONE:
5252b15cb3dSCy Schubert 	case SSL_ERROR_WANT_READ:
5262b15cb3dSCy Schubert 	case SSL_ERROR_WANT_WRITE:
5272b15cb3dSCy Schubert 	case SSL_ERROR_WANT_CONNECT:
5282b15cb3dSCy Schubert 	case SSL_ERROR_WANT_ACCEPT:
5292b15cb3dSCy Schubert 	default:
5302b15cb3dSCy Schubert 		/* should be impossible; treat as normal error. */
5312b15cb3dSCy Schubert 		event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);
5322b15cb3dSCy Schubert 		break;
5332b15cb3dSCy Schubert 	}
5342b15cb3dSCy Schubert 
5352b15cb3dSCy Schubert 	while ((err = ERR_get_error())) {
5362b15cb3dSCy Schubert 		put_error(bev_ssl, err);
5372b15cb3dSCy Schubert 	}
5382b15cb3dSCy Schubert 
5392b15cb3dSCy Schubert 	if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)
5402b15cb3dSCy Schubert 		event = BEV_EVENT_EOF;
5412b15cb3dSCy Schubert 
5422b15cb3dSCy Schubert 	stop_reading(bev_ssl);
5432b15cb3dSCy Schubert 	stop_writing(bev_ssl);
5442b15cb3dSCy Schubert 
5452b15cb3dSCy Schubert 	/* when is BEV_EVENT_{READING|WRITING} */
5462b15cb3dSCy Schubert 	event = when | event;
5472b15cb3dSCy Schubert 	bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
5482b15cb3dSCy Schubert }
5492b15cb3dSCy Schubert 
5502b15cb3dSCy Schubert static void
init_bio_counts(struct bufferevent_openssl * bev_ssl)5512b15cb3dSCy Schubert init_bio_counts(struct bufferevent_openssl *bev_ssl)
5522b15cb3dSCy Schubert {
553*a466cc55SCy Schubert 	BIO *rbio, *wbio;
554*a466cc55SCy Schubert 
555*a466cc55SCy Schubert 	wbio = SSL_get_wbio(bev_ssl->ssl);
556*a466cc55SCy Schubert 	bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0;
557*a466cc55SCy Schubert 	rbio = SSL_get_rbio(bev_ssl->ssl);
558*a466cc55SCy Schubert 	bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0;
5592b15cb3dSCy Schubert }
5602b15cb3dSCy Schubert 
5612b15cb3dSCy Schubert static inline void
decrement_buckets(struct bufferevent_openssl * bev_ssl)5622b15cb3dSCy Schubert decrement_buckets(struct bufferevent_openssl *bev_ssl)
5632b15cb3dSCy Schubert {
5642b15cb3dSCy Schubert 	unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
5652b15cb3dSCy Schubert 	unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
5662b15cb3dSCy Schubert 	/* These next two subtractions can wrap around. That's okay. */
5672b15cb3dSCy Schubert 	unsigned long w = num_w - bev_ssl->counts.n_written;
5682b15cb3dSCy Schubert 	unsigned long r = num_r - bev_ssl->counts.n_read;
5692b15cb3dSCy Schubert 	if (w)
5702b15cb3dSCy Schubert 		bufferevent_decrement_write_buckets_(&bev_ssl->bev, w);
5712b15cb3dSCy Schubert 	if (r)
5722b15cb3dSCy Schubert 		bufferevent_decrement_read_buckets_(&bev_ssl->bev, r);
5732b15cb3dSCy Schubert 	bev_ssl->counts.n_written = num_w;
5742b15cb3dSCy Schubert 	bev_ssl->counts.n_read = num_r;
5752b15cb3dSCy Schubert }
5762b15cb3dSCy Schubert 
5772b15cb3dSCy Schubert #define OP_MADE_PROGRESS 1
5782b15cb3dSCy Schubert #define OP_BLOCKED 2
5792b15cb3dSCy Schubert #define OP_ERR 4
5802b15cb3dSCy Schubert 
5812b15cb3dSCy Schubert /* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if
5822b15cb3dSCy Schubert    we're now blocked); and OP_ERR (if an error occurred). */
5832b15cb3dSCy Schubert static int
do_read(struct bufferevent_openssl * bev_ssl,int n_to_read)5842b15cb3dSCy Schubert do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {
5852b15cb3dSCy Schubert 	/* Requires lock */
5862b15cb3dSCy Schubert 	struct bufferevent *bev = &bev_ssl->bev.bev;
5872b15cb3dSCy Schubert 	struct evbuffer *input = bev->input;
5882b15cb3dSCy Schubert 	int r, n, i, n_used = 0, atmost;
5892b15cb3dSCy Schubert 	struct evbuffer_iovec space[2];
5902b15cb3dSCy Schubert 	int result = 0;
5912b15cb3dSCy Schubert 
5922b15cb3dSCy Schubert 	if (bev_ssl->bev.read_suspended)
5932b15cb3dSCy Schubert 		return 0;
5942b15cb3dSCy Schubert 
5952b15cb3dSCy Schubert 	atmost = bufferevent_get_read_max_(&bev_ssl->bev);
5962b15cb3dSCy Schubert 	if (n_to_read > atmost)
5972b15cb3dSCy Schubert 		n_to_read = atmost;
5982b15cb3dSCy Schubert 
5992b15cb3dSCy Schubert 	n = evbuffer_reserve_space(input, n_to_read, space, 2);
6002b15cb3dSCy Schubert 	if (n < 0)
6012b15cb3dSCy Schubert 		return OP_ERR;
6022b15cb3dSCy Schubert 
6032b15cb3dSCy Schubert 	for (i=0; i<n; ++i) {
6042b15cb3dSCy Schubert 		if (bev_ssl->bev.read_suspended)
6052b15cb3dSCy Schubert 			break;
606*a466cc55SCy Schubert 		ERR_clear_error();
6072b15cb3dSCy Schubert 		r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
6082b15cb3dSCy Schubert 		if (r>0) {
6092b15cb3dSCy Schubert 			result |= OP_MADE_PROGRESS;
6102b15cb3dSCy Schubert 			if (bev_ssl->read_blocked_on_write)
6112b15cb3dSCy Schubert 				if (clear_rbow(bev_ssl) < 0)
6122b15cb3dSCy Schubert 					return OP_ERR | result;
6132b15cb3dSCy Schubert 			++n_used;
6142b15cb3dSCy Schubert 			space[i].iov_len = r;
6152b15cb3dSCy Schubert 			decrement_buckets(bev_ssl);
6162b15cb3dSCy Schubert 		} else {
6172b15cb3dSCy Schubert 			int err = SSL_get_error(bev_ssl->ssl, r);
6182b15cb3dSCy Schubert 			print_err(err);
6192b15cb3dSCy Schubert 			switch (err) {
6202b15cb3dSCy Schubert 			case SSL_ERROR_WANT_READ:
6212b15cb3dSCy Schubert 				/* Can't read until underlying has more data. */
6222b15cb3dSCy Schubert 				if (bev_ssl->read_blocked_on_write)
6232b15cb3dSCy Schubert 					if (clear_rbow(bev_ssl) < 0)
6242b15cb3dSCy Schubert 						return OP_ERR | result;
6252b15cb3dSCy Schubert 				break;
6262b15cb3dSCy Schubert 			case SSL_ERROR_WANT_WRITE:
6272b15cb3dSCy Schubert 				/* This read operation requires a write, and the
6282b15cb3dSCy Schubert 				 * underlying is full */
6292b15cb3dSCy Schubert 				if (!bev_ssl->read_blocked_on_write)
6302b15cb3dSCy Schubert 					if (set_rbow(bev_ssl) < 0)
6312b15cb3dSCy Schubert 						return OP_ERR | result;
6322b15cb3dSCy Schubert 				break;
6332b15cb3dSCy Schubert 			default:
6342b15cb3dSCy Schubert 				conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
6352b15cb3dSCy Schubert 				break;
6362b15cb3dSCy Schubert 			}
6372b15cb3dSCy Schubert 			result |= OP_BLOCKED;
6382b15cb3dSCy Schubert 			break; /* out of the loop */
6392b15cb3dSCy Schubert 		}
6402b15cb3dSCy Schubert 	}
6412b15cb3dSCy Schubert 
6422b15cb3dSCy Schubert 	if (n_used) {
6432b15cb3dSCy Schubert 		evbuffer_commit_space(input, space, n_used);
6442b15cb3dSCy Schubert 		if (bev_ssl->underlying)
6452b15cb3dSCy Schubert 			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
6462b15cb3dSCy Schubert 	}
6472b15cb3dSCy Schubert 
6482b15cb3dSCy Schubert 	return result;
6492b15cb3dSCy Schubert }
6502b15cb3dSCy Schubert 
6512b15cb3dSCy Schubert /* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if
6522b15cb3dSCy Schubert    we're now blocked); and OP_ERR (if an error occurred). */
6532b15cb3dSCy Schubert static int
do_write(struct bufferevent_openssl * bev_ssl,int atmost)6542b15cb3dSCy Schubert do_write(struct bufferevent_openssl *bev_ssl, int atmost)
6552b15cb3dSCy Schubert {
6562b15cb3dSCy Schubert 	int i, r, n, n_written = 0;
6572b15cb3dSCy Schubert 	struct bufferevent *bev = &bev_ssl->bev.bev;
6582b15cb3dSCy Schubert 	struct evbuffer *output = bev->output;
6592b15cb3dSCy Schubert 	struct evbuffer_iovec space[8];
6602b15cb3dSCy Schubert 	int result = 0;
6612b15cb3dSCy Schubert 
6622b15cb3dSCy Schubert 	if (bev_ssl->last_write > 0)
6632b15cb3dSCy Schubert 		atmost = bev_ssl->last_write;
6642b15cb3dSCy Schubert 	else
6652b15cb3dSCy Schubert 		atmost = bufferevent_get_write_max_(&bev_ssl->bev);
6662b15cb3dSCy Schubert 
6672b15cb3dSCy Schubert 	n = evbuffer_peek(output, atmost, NULL, space, 8);
6682b15cb3dSCy Schubert 	if (n < 0)
6692b15cb3dSCy Schubert 		return OP_ERR | result;
6702b15cb3dSCy Schubert 
6712b15cb3dSCy Schubert 	if (n > 8)
6722b15cb3dSCy Schubert 		n = 8;
6732b15cb3dSCy Schubert 	for (i=0; i < n; ++i) {
6742b15cb3dSCy Schubert 		if (bev_ssl->bev.write_suspended)
6752b15cb3dSCy Schubert 			break;
6762b15cb3dSCy Schubert 
6772b15cb3dSCy Schubert 		/* SSL_write will (reasonably) return 0 if we tell it to
6782b15cb3dSCy Schubert 		   send 0 data.  Skip this case so we don't interpret the
6792b15cb3dSCy Schubert 		   result as an error */
6802b15cb3dSCy Schubert 		if (space[i].iov_len == 0)
6812b15cb3dSCy Schubert 			continue;
6822b15cb3dSCy Schubert 
683*a466cc55SCy Schubert 		ERR_clear_error();
6842b15cb3dSCy Schubert 		r = SSL_write(bev_ssl->ssl, space[i].iov_base,
6852b15cb3dSCy Schubert 		    space[i].iov_len);
6862b15cb3dSCy Schubert 		if (r > 0) {
6872b15cb3dSCy Schubert 			result |= OP_MADE_PROGRESS;
6882b15cb3dSCy Schubert 			if (bev_ssl->write_blocked_on_read)
6892b15cb3dSCy Schubert 				if (clear_wbor(bev_ssl) < 0)
6902b15cb3dSCy Schubert 					return OP_ERR | result;
6912b15cb3dSCy Schubert 			n_written += r;
6922b15cb3dSCy Schubert 			bev_ssl->last_write = -1;
6932b15cb3dSCy Schubert 			decrement_buckets(bev_ssl);
6942b15cb3dSCy Schubert 		} else {
6952b15cb3dSCy Schubert 			int err = SSL_get_error(bev_ssl->ssl, r);
6962b15cb3dSCy Schubert 			print_err(err);
6972b15cb3dSCy Schubert 			switch (err) {
6982b15cb3dSCy Schubert 			case SSL_ERROR_WANT_WRITE:
6992b15cb3dSCy Schubert 				/* Can't read until underlying has more data. */
7002b15cb3dSCy Schubert 				if (bev_ssl->write_blocked_on_read)
7012b15cb3dSCy Schubert 					if (clear_wbor(bev_ssl) < 0)
7022b15cb3dSCy Schubert 						return OP_ERR | result;
7032b15cb3dSCy Schubert 				bev_ssl->last_write = space[i].iov_len;
7042b15cb3dSCy Schubert 				break;
7052b15cb3dSCy Schubert 			case SSL_ERROR_WANT_READ:
7062b15cb3dSCy Schubert 				/* This read operation requires a write, and the
7072b15cb3dSCy Schubert 				 * underlying is full */
7082b15cb3dSCy Schubert 				if (!bev_ssl->write_blocked_on_read)
7092b15cb3dSCy Schubert 					if (set_wbor(bev_ssl) < 0)
7102b15cb3dSCy Schubert 						return OP_ERR | result;
7112b15cb3dSCy Schubert 				bev_ssl->last_write = space[i].iov_len;
7122b15cb3dSCy Schubert 				break;
7132b15cb3dSCy Schubert 			default:
7142b15cb3dSCy Schubert 				conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r);
7152b15cb3dSCy Schubert 				bev_ssl->last_write = -1;
7162b15cb3dSCy Schubert 				break;
7172b15cb3dSCy Schubert 			}
7182b15cb3dSCy Schubert 			result |= OP_BLOCKED;
7192b15cb3dSCy Schubert 			break;
7202b15cb3dSCy Schubert 		}
7212b15cb3dSCy Schubert 	}
7222b15cb3dSCy Schubert 	if (n_written) {
7232b15cb3dSCy Schubert 		evbuffer_drain(output, n_written);
7242b15cb3dSCy Schubert 		if (bev_ssl->underlying)
7252b15cb3dSCy Schubert 			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
7262b15cb3dSCy Schubert 
727*a466cc55SCy Schubert 		bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);
7282b15cb3dSCy Schubert 	}
7292b15cb3dSCy Schubert 	return result;
7302b15cb3dSCy Schubert }
7312b15cb3dSCy Schubert 
7322b15cb3dSCy Schubert #define WRITE_FRAME 15000
7332b15cb3dSCy Schubert 
7342b15cb3dSCy Schubert #define READ_DEFAULT 4096
7352b15cb3dSCy Schubert 
7362b15cb3dSCy Schubert /* Try to figure out how many bytes to read; return 0 if we shouldn't be
7372b15cb3dSCy Schubert  * reading. */
7382b15cb3dSCy Schubert static int
bytes_to_read(struct bufferevent_openssl * bev)7392b15cb3dSCy Schubert bytes_to_read(struct bufferevent_openssl *bev)
7402b15cb3dSCy Schubert {
7412b15cb3dSCy Schubert 	struct evbuffer *input = bev->bev.bev.input;
7422b15cb3dSCy Schubert 	struct event_watermark *wm = &bev->bev.bev.wm_read;
7432b15cb3dSCy Schubert 	int result = READ_DEFAULT;
7442b15cb3dSCy Schubert 	ev_ssize_t limit;
7452b15cb3dSCy Schubert 	/* XXX 99% of this is generic code that nearly all bufferevents will
7462b15cb3dSCy Schubert 	 * want. */
7472b15cb3dSCy Schubert 
7482b15cb3dSCy Schubert 	if (bev->write_blocked_on_read) {
7492b15cb3dSCy Schubert 		return 0;
7502b15cb3dSCy Schubert 	}
7512b15cb3dSCy Schubert 
7522b15cb3dSCy Schubert 	if (! (bev->bev.bev.enabled & EV_READ)) {
7532b15cb3dSCy Schubert 		return 0;
7542b15cb3dSCy Schubert 	}
7552b15cb3dSCy Schubert 
7562b15cb3dSCy Schubert 	if (bev->bev.read_suspended) {
7572b15cb3dSCy Schubert 		return 0;
7582b15cb3dSCy Schubert 	}
7592b15cb3dSCy Schubert 
7602b15cb3dSCy Schubert 	if (wm->high) {
7612b15cb3dSCy Schubert 		if (evbuffer_get_length(input) >= wm->high) {
7622b15cb3dSCy Schubert 			return 0;
7632b15cb3dSCy Schubert 		}
7642b15cb3dSCy Schubert 
7652b15cb3dSCy Schubert 		result = wm->high - evbuffer_get_length(input);
7662b15cb3dSCy Schubert 	} else {
7672b15cb3dSCy Schubert 		result = READ_DEFAULT;
7682b15cb3dSCy Schubert 	}
7692b15cb3dSCy Schubert 
7702b15cb3dSCy Schubert 	/* Respect the rate limit */
7712b15cb3dSCy Schubert 	limit = bufferevent_get_read_max_(&bev->bev);
7722b15cb3dSCy Schubert 	if (result > limit) {
7732b15cb3dSCy Schubert 		result = limit;
7742b15cb3dSCy Schubert 	}
7752b15cb3dSCy Schubert 
7762b15cb3dSCy Schubert 	return result;
7772b15cb3dSCy Schubert }
7782b15cb3dSCy Schubert 
7792b15cb3dSCy Schubert 
7802b15cb3dSCy Schubert /* Things look readable.  If write is blocked on read, write till it isn't.
7812b15cb3dSCy Schubert  * Read from the underlying buffer until we block or we hit our high-water
7822b15cb3dSCy Schubert  * mark.
7832b15cb3dSCy Schubert  */
7842b15cb3dSCy Schubert static void
consider_reading(struct bufferevent_openssl * bev_ssl)7852b15cb3dSCy Schubert consider_reading(struct bufferevent_openssl *bev_ssl)
7862b15cb3dSCy Schubert {
7872b15cb3dSCy Schubert 	int r;
7882b15cb3dSCy Schubert 	int n_to_read;
7892b15cb3dSCy Schubert 	int all_result_flags = 0;
7902b15cb3dSCy Schubert 
7912b15cb3dSCy Schubert 	while (bev_ssl->write_blocked_on_read) {
7922b15cb3dSCy Schubert 		r = do_write(bev_ssl, WRITE_FRAME);
7932b15cb3dSCy Schubert 		if (r & (OP_BLOCKED|OP_ERR))
7942b15cb3dSCy Schubert 			break;
7952b15cb3dSCy Schubert 	}
7962b15cb3dSCy Schubert 	if (bev_ssl->write_blocked_on_read)
7972b15cb3dSCy Schubert 		return;
7982b15cb3dSCy Schubert 
7992b15cb3dSCy Schubert 	n_to_read = bytes_to_read(bev_ssl);
8002b15cb3dSCy Schubert 
8012b15cb3dSCy Schubert 	while (n_to_read) {
8022b15cb3dSCy Schubert 		r = do_read(bev_ssl, n_to_read);
8032b15cb3dSCy Schubert 		all_result_flags |= r;
8042b15cb3dSCy Schubert 
8052b15cb3dSCy Schubert 		if (r & (OP_BLOCKED|OP_ERR))
8062b15cb3dSCy Schubert 			break;
8072b15cb3dSCy Schubert 
8082b15cb3dSCy Schubert 		if (bev_ssl->bev.read_suspended)
8092b15cb3dSCy Schubert 			break;
8102b15cb3dSCy Schubert 
8112b15cb3dSCy Schubert 		/* Read all pending data.  This won't hit the network
8122b15cb3dSCy Schubert 		 * again, and will (most importantly) put us in a state
8132b15cb3dSCy Schubert 		 * where we don't need to read anything else until the
8142b15cb3dSCy Schubert 		 * socket is readable again.  It'll potentially make us
8152b15cb3dSCy Schubert 		 * overrun our read high-watermark (somewhat
8162b15cb3dSCy Schubert 		 * regrettable).  The damage to the rate-limit has
8172b15cb3dSCy Schubert 		 * already been done, since OpenSSL went and read a
8182b15cb3dSCy Schubert 		 * whole SSL record anyway. */
8192b15cb3dSCy Schubert 		n_to_read = SSL_pending(bev_ssl->ssl);
8202b15cb3dSCy Schubert 
8212b15cb3dSCy Schubert 		/* XXX This if statement is actually a bad bug, added to avoid
8222b15cb3dSCy Schubert 		 * XXX a worse bug.
8232b15cb3dSCy Schubert 		 *
8242b15cb3dSCy Schubert 		 * The bad bug: It can potentially cause resource unfairness
8252b15cb3dSCy Schubert 		 * by reading too much data from the underlying bufferevent;
8262b15cb3dSCy Schubert 		 * it can potentially cause read looping if the underlying
8272b15cb3dSCy Schubert 		 * bufferevent is a bufferevent_pair and deferred callbacks
8282b15cb3dSCy Schubert 		 * aren't used.
8292b15cb3dSCy Schubert 		 *
8302b15cb3dSCy Schubert 		 * The worse bug: If we didn't do this, then we would
8312b15cb3dSCy Schubert 		 * potentially not read any more from bev_ssl->underlying
8322b15cb3dSCy Schubert 		 * until more data arrived there, which could lead to us
8332b15cb3dSCy Schubert 		 * waiting forever.
8342b15cb3dSCy Schubert 		 */
8352b15cb3dSCy Schubert 		if (!n_to_read && bev_ssl->underlying)
8362b15cb3dSCy Schubert 			n_to_read = bytes_to_read(bev_ssl);
8372b15cb3dSCy Schubert 	}
8382b15cb3dSCy Schubert 
8392b15cb3dSCy Schubert 	if (all_result_flags & OP_MADE_PROGRESS) {
8402b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
8412b15cb3dSCy Schubert 
8422b15cb3dSCy Schubert 		bufferevent_trigger_nolock_(bev, EV_READ, 0);
8432b15cb3dSCy Schubert 	}
8442b15cb3dSCy Schubert 
8452b15cb3dSCy Schubert 	if (!bev_ssl->underlying) {
8462b15cb3dSCy Schubert 		/* Should be redundant, but let's avoid busy-looping */
8472b15cb3dSCy Schubert 		if (bev_ssl->bev.read_suspended ||
8482b15cb3dSCy Schubert 		    !(bev_ssl->bev.bev.enabled & EV_READ)) {
8492b15cb3dSCy Schubert 			event_del(&bev_ssl->bev.bev.ev_read);
8502b15cb3dSCy Schubert 		}
8512b15cb3dSCy Schubert 	}
8522b15cb3dSCy Schubert }
8532b15cb3dSCy Schubert 
8542b15cb3dSCy Schubert static void
consider_writing(struct bufferevent_openssl * bev_ssl)8552b15cb3dSCy Schubert consider_writing(struct bufferevent_openssl *bev_ssl)
8562b15cb3dSCy Schubert {
8572b15cb3dSCy Schubert 	int r;
8582b15cb3dSCy Schubert 	struct evbuffer *output = bev_ssl->bev.bev.output;
8592b15cb3dSCy Schubert 	struct evbuffer *target = NULL;
8602b15cb3dSCy Schubert 	struct event_watermark *wm = NULL;
8612b15cb3dSCy Schubert 
8622b15cb3dSCy Schubert 	while (bev_ssl->read_blocked_on_write) {
8632b15cb3dSCy Schubert 		r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */
8642b15cb3dSCy Schubert 		if (r & OP_MADE_PROGRESS) {
8652b15cb3dSCy Schubert 			struct bufferevent *bev = &bev_ssl->bev.bev;
8662b15cb3dSCy Schubert 
8672b15cb3dSCy Schubert 			bufferevent_trigger_nolock_(bev, EV_READ, 0);
8682b15cb3dSCy Schubert 		}
8692b15cb3dSCy Schubert 		if (r & (OP_ERR|OP_BLOCKED))
8702b15cb3dSCy Schubert 			break;
8712b15cb3dSCy Schubert 	}
8722b15cb3dSCy Schubert 	if (bev_ssl->read_blocked_on_write)
8732b15cb3dSCy Schubert 		return;
8742b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
8752b15cb3dSCy Schubert 		target = bev_ssl->underlying->output;
8762b15cb3dSCy Schubert 		wm = &bev_ssl->underlying->wm_write;
8772b15cb3dSCy Schubert 	}
8782b15cb3dSCy Schubert 	while ((bev_ssl->bev.bev.enabled & EV_WRITE) &&
8792b15cb3dSCy Schubert 	    (! bev_ssl->bev.write_suspended) &&
8802b15cb3dSCy Schubert 	    evbuffer_get_length(output) &&
8812b15cb3dSCy Schubert 	    (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) {
8822b15cb3dSCy Schubert 		int n_to_write;
8832b15cb3dSCy Schubert 		if (wm && wm->high)
8842b15cb3dSCy Schubert 			n_to_write = wm->high - evbuffer_get_length(target);
8852b15cb3dSCy Schubert 		else
8862b15cb3dSCy Schubert 			n_to_write = WRITE_FRAME;
8872b15cb3dSCy Schubert 		r = do_write(bev_ssl, n_to_write);
8882b15cb3dSCy Schubert 		if (r & (OP_BLOCKED|OP_ERR))
8892b15cb3dSCy Schubert 			break;
8902b15cb3dSCy Schubert 	}
8912b15cb3dSCy Schubert 
8922b15cb3dSCy Schubert 	if (!bev_ssl->underlying) {
8932b15cb3dSCy Schubert 		if (evbuffer_get_length(output) == 0) {
8942b15cb3dSCy Schubert 			event_del(&bev_ssl->bev.bev.ev_write);
8952b15cb3dSCy Schubert 		} else if (bev_ssl->bev.write_suspended ||
8962b15cb3dSCy Schubert 		    !(bev_ssl->bev.bev.enabled & EV_WRITE)) {
8972b15cb3dSCy Schubert 			/* Should be redundant, but let's avoid busy-looping */
8982b15cb3dSCy Schubert 			event_del(&bev_ssl->bev.bev.ev_write);
8992b15cb3dSCy Schubert 		}
9002b15cb3dSCy Schubert 	}
9012b15cb3dSCy Schubert }
9022b15cb3dSCy Schubert 
9032b15cb3dSCy Schubert static void
be_openssl_readcb(struct bufferevent * bev_base,void * ctx)9042b15cb3dSCy Schubert be_openssl_readcb(struct bufferevent *bev_base, void *ctx)
9052b15cb3dSCy Schubert {
9062b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ctx;
9072b15cb3dSCy Schubert 	consider_reading(bev_ssl);
9082b15cb3dSCy Schubert }
9092b15cb3dSCy Schubert 
9102b15cb3dSCy Schubert static void
be_openssl_writecb(struct bufferevent * bev_base,void * ctx)9112b15cb3dSCy Schubert be_openssl_writecb(struct bufferevent *bev_base, void *ctx)
9122b15cb3dSCy Schubert {
9132b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ctx;
9142b15cb3dSCy Schubert 	consider_writing(bev_ssl);
9152b15cb3dSCy Schubert }
9162b15cb3dSCy Schubert 
9172b15cb3dSCy Schubert static void
be_openssl_eventcb(struct bufferevent * bev_base,short what,void * ctx)9182b15cb3dSCy Schubert be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)
9192b15cb3dSCy Schubert {
9202b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ctx;
9212b15cb3dSCy Schubert 	int event = 0;
9222b15cb3dSCy Schubert 
9232b15cb3dSCy Schubert 	if (what & BEV_EVENT_EOF) {
9242b15cb3dSCy Schubert 		if (bev_ssl->allow_dirty_shutdown)
9252b15cb3dSCy Schubert 			event = BEV_EVENT_EOF;
9262b15cb3dSCy Schubert 		else
9272b15cb3dSCy Schubert 			event = BEV_EVENT_ERROR;
9282b15cb3dSCy Schubert 	} else if (what & BEV_EVENT_TIMEOUT) {
9292b15cb3dSCy Schubert 		/* We sure didn't set this.  Propagate it to the user. */
9302b15cb3dSCy Schubert 		event = what;
9312b15cb3dSCy Schubert 	} else if (what & BEV_EVENT_ERROR) {
9322b15cb3dSCy Schubert 		/* An error occurred on the connection.  Propagate it to the user. */
9332b15cb3dSCy Schubert 		event = what;
9342b15cb3dSCy Schubert 	} else if (what & BEV_EVENT_CONNECTED) {
9352b15cb3dSCy Schubert 		/* Ignore it.  We're saying SSL_connect() already, which will
9362b15cb3dSCy Schubert 		   eat it. */
9372b15cb3dSCy Schubert 	}
9382b15cb3dSCy Schubert 	if (event)
9392b15cb3dSCy Schubert 		bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
9402b15cb3dSCy Schubert }
9412b15cb3dSCy Schubert 
9422b15cb3dSCy Schubert static void
be_openssl_readeventcb(evutil_socket_t fd,short what,void * ptr)9432b15cb3dSCy Schubert be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr)
9442b15cb3dSCy Schubert {
9452b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ptr;
9462b15cb3dSCy Schubert 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
9472b15cb3dSCy Schubert 	if (what == EV_TIMEOUT) {
9482b15cb3dSCy Schubert 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
9492b15cb3dSCy Schubert 		    BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0);
9502b15cb3dSCy Schubert 	} else {
9512b15cb3dSCy Schubert 		consider_reading(bev_ssl);
9522b15cb3dSCy Schubert 	}
9532b15cb3dSCy Schubert 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
9542b15cb3dSCy Schubert }
9552b15cb3dSCy Schubert 
9562b15cb3dSCy Schubert static void
be_openssl_writeeventcb(evutil_socket_t fd,short what,void * ptr)9572b15cb3dSCy Schubert be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
9582b15cb3dSCy Schubert {
9592b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ptr;
9602b15cb3dSCy Schubert 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
9612b15cb3dSCy Schubert 	if (what == EV_TIMEOUT) {
9622b15cb3dSCy Schubert 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
9632b15cb3dSCy Schubert 		    BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0);
9642b15cb3dSCy Schubert 	} else {
9652b15cb3dSCy Schubert 		consider_writing(bev_ssl);
9662b15cb3dSCy Schubert 	}
9672b15cb3dSCy Schubert 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
9682b15cb3dSCy Schubert }
9692b15cb3dSCy Schubert 
970*a466cc55SCy Schubert static evutil_socket_t
be_openssl_auto_fd(struct bufferevent_openssl * bev_ssl,evutil_socket_t fd)971*a466cc55SCy Schubert be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
972*a466cc55SCy Schubert {
973*a466cc55SCy Schubert 	if (!bev_ssl->underlying) {
974*a466cc55SCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
975*a466cc55SCy Schubert 		if (event_initialized(&bev->ev_read) && fd < 0) {
976*a466cc55SCy Schubert 			fd = event_get_fd(&bev->ev_read);
977*a466cc55SCy Schubert 		}
978*a466cc55SCy Schubert 	}
979*a466cc55SCy Schubert 	return fd;
980*a466cc55SCy Schubert }
981*a466cc55SCy Schubert 
9822b15cb3dSCy Schubert static int
set_open_callbacks(struct bufferevent_openssl * bev_ssl,evutil_socket_t fd)9832b15cb3dSCy Schubert set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
9842b15cb3dSCy Schubert {
9852b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
9862b15cb3dSCy Schubert 		bufferevent_setcb(bev_ssl->underlying,
9872b15cb3dSCy Schubert 		    be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
9882b15cb3dSCy Schubert 		    bev_ssl);
9892b15cb3dSCy Schubert 		return 0;
9902b15cb3dSCy Schubert 	} else {
9912b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
9922b15cb3dSCy Schubert 		int rpending=0, wpending=0, r1=0, r2=0;
993*a466cc55SCy Schubert 
994*a466cc55SCy Schubert 		if (event_initialized(&bev->ev_read)) {
9952b15cb3dSCy Schubert 			rpending = event_pending(&bev->ev_read, EV_READ, NULL);
9962b15cb3dSCy Schubert 			wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
997*a466cc55SCy Schubert 
9982b15cb3dSCy Schubert 			event_del(&bev->ev_read);
9992b15cb3dSCy Schubert 			event_del(&bev->ev_write);
10002b15cb3dSCy Schubert 		}
1001*a466cc55SCy Schubert 
10022b15cb3dSCy Schubert 		event_assign(&bev->ev_read, bev->ev_base, fd,
10032b15cb3dSCy Schubert 		    EV_READ|EV_PERSIST|EV_FINALIZE,
10042b15cb3dSCy Schubert 		    be_openssl_readeventcb, bev_ssl);
10052b15cb3dSCy Schubert 		event_assign(&bev->ev_write, bev->ev_base, fd,
10062b15cb3dSCy Schubert 		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
10072b15cb3dSCy Schubert 		    be_openssl_writeeventcb, bev_ssl);
1008*a466cc55SCy Schubert 
10092b15cb3dSCy Schubert 		if (rpending)
10102b15cb3dSCy Schubert 			r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
10112b15cb3dSCy Schubert 		if (wpending)
10122b15cb3dSCy Schubert 			r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
1013*a466cc55SCy Schubert 
10142b15cb3dSCy Schubert 		return (r1<0 || r2<0) ? -1 : 0;
10152b15cb3dSCy Schubert 	}
10162b15cb3dSCy Schubert }
10172b15cb3dSCy Schubert 
10182b15cb3dSCy Schubert static int
do_handshake(struct bufferevent_openssl * bev_ssl)10192b15cb3dSCy Schubert do_handshake(struct bufferevent_openssl *bev_ssl)
10202b15cb3dSCy Schubert {
10212b15cb3dSCy Schubert 	int r;
10222b15cb3dSCy Schubert 
10232b15cb3dSCy Schubert 	switch (bev_ssl->state) {
10242b15cb3dSCy Schubert 	default:
10252b15cb3dSCy Schubert 	case BUFFEREVENT_SSL_OPEN:
10262b15cb3dSCy Schubert 		EVUTIL_ASSERT(0);
10272b15cb3dSCy Schubert 		return -1;
10282b15cb3dSCy Schubert 	case BUFFEREVENT_SSL_CONNECTING:
10292b15cb3dSCy Schubert 	case BUFFEREVENT_SSL_ACCEPTING:
1030*a466cc55SCy Schubert 		ERR_clear_error();
10312b15cb3dSCy Schubert 		r = SSL_do_handshake(bev_ssl->ssl);
10322b15cb3dSCy Schubert 		break;
10332b15cb3dSCy Schubert 	}
10342b15cb3dSCy Schubert 	decrement_buckets(bev_ssl);
10352b15cb3dSCy Schubert 
10362b15cb3dSCy Schubert 	if (r==1) {
1037*a466cc55SCy Schubert 		evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
10382b15cb3dSCy Schubert 		/* We're done! */
10392b15cb3dSCy Schubert 		bev_ssl->state = BUFFEREVENT_SSL_OPEN;
1040*a466cc55SCy Schubert 		set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */
10412b15cb3dSCy Schubert 		/* Call do_read and do_write as needed */
10422b15cb3dSCy Schubert 		bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
10432b15cb3dSCy Schubert 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
10442b15cb3dSCy Schubert 		    BEV_EVENT_CONNECTED, 0);
10452b15cb3dSCy Schubert 		return 1;
10462b15cb3dSCy Schubert 	} else {
10472b15cb3dSCy Schubert 		int err = SSL_get_error(bev_ssl->ssl, r);
10482b15cb3dSCy Schubert 		print_err(err);
10492b15cb3dSCy Schubert 		switch (err) {
10502b15cb3dSCy Schubert 		case SSL_ERROR_WANT_WRITE:
10512b15cb3dSCy Schubert 			stop_reading(bev_ssl);
10522b15cb3dSCy Schubert 			return start_writing(bev_ssl);
10532b15cb3dSCy Schubert 		case SSL_ERROR_WANT_READ:
10542b15cb3dSCy Schubert 			stop_writing(bev_ssl);
10552b15cb3dSCy Schubert 			return start_reading(bev_ssl);
10562b15cb3dSCy Schubert 		default:
10572b15cb3dSCy Schubert 			conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
10582b15cb3dSCy Schubert 			return -1;
10592b15cb3dSCy Schubert 		}
10602b15cb3dSCy Schubert 	}
10612b15cb3dSCy Schubert }
10622b15cb3dSCy Schubert 
10632b15cb3dSCy Schubert static void
be_openssl_handshakecb(struct bufferevent * bev_base,void * ctx)10642b15cb3dSCy Schubert be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
10652b15cb3dSCy Schubert {
10662b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ctx;
10672b15cb3dSCy Schubert 	do_handshake(bev_ssl);/* XXX handle failure */
10682b15cb3dSCy Schubert }
10692b15cb3dSCy Schubert 
10702b15cb3dSCy Schubert static void
be_openssl_handshakeeventcb(evutil_socket_t fd,short what,void * ptr)10712b15cb3dSCy Schubert be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
10722b15cb3dSCy Schubert {
10732b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = ptr;
10742b15cb3dSCy Schubert 
10752b15cb3dSCy Schubert 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
10762b15cb3dSCy Schubert 	if (what & EV_TIMEOUT) {
10772b15cb3dSCy Schubert 		bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0);
10782b15cb3dSCy Schubert 	} else
10792b15cb3dSCy Schubert 		do_handshake(bev_ssl);/* XXX handle failure */
10802b15cb3dSCy Schubert 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
10812b15cb3dSCy Schubert }
10822b15cb3dSCy Schubert 
10832b15cb3dSCy Schubert static int
set_handshake_callbacks(struct bufferevent_openssl * bev_ssl,evutil_socket_t fd)10842b15cb3dSCy Schubert set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
10852b15cb3dSCy Schubert {
10862b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
10872b15cb3dSCy Schubert 		bufferevent_setcb(bev_ssl->underlying,
10882b15cb3dSCy Schubert 		    be_openssl_handshakecb, be_openssl_handshakecb,
10892b15cb3dSCy Schubert 		    be_openssl_eventcb,
10902b15cb3dSCy Schubert 		    bev_ssl);
1091*a466cc55SCy Schubert 
1092*a466cc55SCy Schubert 		if (fd < 0)
1093*a466cc55SCy Schubert 			return 0;
1094*a466cc55SCy Schubert 
1095*a466cc55SCy Schubert 		if (bufferevent_setfd(bev_ssl->underlying, fd))
1096*a466cc55SCy Schubert 			return 1;
1097*a466cc55SCy Schubert 
10982b15cb3dSCy Schubert 		return do_handshake(bev_ssl);
10992b15cb3dSCy Schubert 	} else {
11002b15cb3dSCy Schubert 		struct bufferevent *bev = &bev_ssl->bev.bev;
1101*a466cc55SCy Schubert 
1102*a466cc55SCy Schubert 		if (event_initialized(&bev->ev_read)) {
11032b15cb3dSCy Schubert 			event_del(&bev->ev_read);
11042b15cb3dSCy Schubert 			event_del(&bev->ev_write);
11052b15cb3dSCy Schubert 		}
1106*a466cc55SCy Schubert 
11072b15cb3dSCy Schubert 		event_assign(&bev->ev_read, bev->ev_base, fd,
11082b15cb3dSCy Schubert 		    EV_READ|EV_PERSIST|EV_FINALIZE,
11092b15cb3dSCy Schubert 		    be_openssl_handshakeeventcb, bev_ssl);
11102b15cb3dSCy Schubert 		event_assign(&bev->ev_write, bev->ev_base, fd,
11112b15cb3dSCy Schubert 		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
11122b15cb3dSCy Schubert 		    be_openssl_handshakeeventcb, bev_ssl);
1113*a466cc55SCy Schubert 		if (fd >= 0)
1114*a466cc55SCy Schubert 			bufferevent_enable(bev, bev->enabled);
1115*a466cc55SCy Schubert 		return 0;
11162b15cb3dSCy Schubert 	}
11172b15cb3dSCy Schubert }
11182b15cb3dSCy Schubert 
11192b15cb3dSCy Schubert int
bufferevent_ssl_renegotiate(struct bufferevent * bev)11202b15cb3dSCy Schubert bufferevent_ssl_renegotiate(struct bufferevent *bev)
11212b15cb3dSCy Schubert {
11222b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11232b15cb3dSCy Schubert 	if (!bev_ssl)
11242b15cb3dSCy Schubert 		return -1;
11252b15cb3dSCy Schubert 	if (SSL_renegotiate(bev_ssl->ssl) < 0)
11262b15cb3dSCy Schubert 		return -1;
11272b15cb3dSCy Schubert 	bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
1128*a466cc55SCy Schubert 	if (set_handshake_callbacks(bev_ssl, be_openssl_auto_fd(bev_ssl, -1)) < 0)
11292b15cb3dSCy Schubert 		return -1;
11302b15cb3dSCy Schubert 	if (!bev_ssl->underlying)
11312b15cb3dSCy Schubert 		return do_handshake(bev_ssl);
11322b15cb3dSCy Schubert 	return 0;
11332b15cb3dSCy Schubert }
11342b15cb3dSCy Schubert 
11352b15cb3dSCy Schubert static void
be_openssl_outbuf_cb(struct evbuffer * buf,const struct evbuffer_cb_info * cbinfo,void * arg)11362b15cb3dSCy Schubert be_openssl_outbuf_cb(struct evbuffer *buf,
11372b15cb3dSCy Schubert     const struct evbuffer_cb_info *cbinfo, void *arg)
11382b15cb3dSCy Schubert {
11392b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = arg;
11402b15cb3dSCy Schubert 	int r = 0;
11412b15cb3dSCy Schubert 	/* XXX need to hold a reference here. */
11422b15cb3dSCy Schubert 
11432b15cb3dSCy Schubert 	if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
11442b15cb3dSCy Schubert 		if (cbinfo->orig_size == 0)
11452b15cb3dSCy Schubert 			r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
11462b15cb3dSCy Schubert 			    &bev_ssl->bev.bev.timeout_write);
1147*a466cc55SCy Schubert 
1148*a466cc55SCy Schubert 		if (bev_ssl->underlying)
11492b15cb3dSCy Schubert 			consider_writing(bev_ssl);
11502b15cb3dSCy Schubert 	}
11512b15cb3dSCy Schubert 	/* XXX Handle r < 0 */
11522b15cb3dSCy Schubert 	(void)r;
11532b15cb3dSCy Schubert }
11542b15cb3dSCy Schubert 
11552b15cb3dSCy Schubert 
11562b15cb3dSCy Schubert static int
be_openssl_enable(struct bufferevent * bev,short events)11572b15cb3dSCy Schubert be_openssl_enable(struct bufferevent *bev, short events)
11582b15cb3dSCy Schubert {
11592b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11602b15cb3dSCy Schubert 	int r1 = 0, r2 = 0;
11612b15cb3dSCy Schubert 
11622b15cb3dSCy Schubert 	if (events & EV_READ)
11632b15cb3dSCy Schubert 		r1 = start_reading(bev_ssl);
11642b15cb3dSCy Schubert 	if (events & EV_WRITE)
11652b15cb3dSCy Schubert 		r2 = start_writing(bev_ssl);
11662b15cb3dSCy Schubert 
11672b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
11682b15cb3dSCy Schubert 		if (events & EV_READ)
11692b15cb3dSCy Schubert 			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
11702b15cb3dSCy Schubert 		if (events & EV_WRITE)
11712b15cb3dSCy Schubert 			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
11722b15cb3dSCy Schubert 
11732b15cb3dSCy Schubert 		if (events & EV_READ)
11742b15cb3dSCy Schubert 			consider_reading(bev_ssl);
11752b15cb3dSCy Schubert 		if (events & EV_WRITE)
11762b15cb3dSCy Schubert 			consider_writing(bev_ssl);
11772b15cb3dSCy Schubert 	}
11782b15cb3dSCy Schubert 	return (r1 < 0 || r2 < 0) ? -1 : 0;
11792b15cb3dSCy Schubert }
11802b15cb3dSCy Schubert 
11812b15cb3dSCy Schubert static int
be_openssl_disable(struct bufferevent * bev,short events)11822b15cb3dSCy Schubert be_openssl_disable(struct bufferevent *bev, short events)
11832b15cb3dSCy Schubert {
11842b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11852b15cb3dSCy Schubert 
11862b15cb3dSCy Schubert 	if (events & EV_READ)
11872b15cb3dSCy Schubert 		stop_reading(bev_ssl);
11882b15cb3dSCy Schubert 	if (events & EV_WRITE)
11892b15cb3dSCy Schubert 		stop_writing(bev_ssl);
11902b15cb3dSCy Schubert 
11912b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
11922b15cb3dSCy Schubert 		if (events & EV_READ)
11932b15cb3dSCy Schubert 			BEV_DEL_GENERIC_READ_TIMEOUT(bev);
11942b15cb3dSCy Schubert 		if (events & EV_WRITE)
11952b15cb3dSCy Schubert 			BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
11962b15cb3dSCy Schubert 	}
11972b15cb3dSCy Schubert 	return 0;
11982b15cb3dSCy Schubert }
11992b15cb3dSCy Schubert 
12002b15cb3dSCy Schubert static void
be_openssl_unlink(struct bufferevent * bev)12012b15cb3dSCy Schubert be_openssl_unlink(struct bufferevent *bev)
12022b15cb3dSCy Schubert {
12032b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
12042b15cb3dSCy Schubert 
12052b15cb3dSCy Schubert 	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
12062b15cb3dSCy Schubert 		if (bev_ssl->underlying) {
12072b15cb3dSCy Schubert 			if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) {
12082b15cb3dSCy Schubert 				event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "
12092b15cb3dSCy Schubert 				    "bufferevent with too few references");
12102b15cb3dSCy Schubert 			} else {
12112b15cb3dSCy Schubert 				bufferevent_free(bev_ssl->underlying);
12122b15cb3dSCy Schubert 				/* We still have a reference to it, via our
12132b15cb3dSCy Schubert 				 * BIO. So we don't drop this. */
12142b15cb3dSCy Schubert 				// bev_ssl->underlying = NULL;
12152b15cb3dSCy Schubert 			}
12162b15cb3dSCy Schubert 		}
12172b15cb3dSCy Schubert 	} else {
12182b15cb3dSCy Schubert 		if (bev_ssl->underlying) {
12192b15cb3dSCy Schubert 			if (bev_ssl->underlying->errorcb == be_openssl_eventcb)
12202b15cb3dSCy Schubert 				bufferevent_setcb(bev_ssl->underlying,
12212b15cb3dSCy Schubert 				    NULL,NULL,NULL,NULL);
12222b15cb3dSCy Schubert 			bufferevent_unsuspend_read_(bev_ssl->underlying,
12232b15cb3dSCy Schubert 			    BEV_SUSPEND_FILT_READ);
12242b15cb3dSCy Schubert 		}
12252b15cb3dSCy Schubert 	}
12262b15cb3dSCy Schubert }
12272b15cb3dSCy Schubert 
12282b15cb3dSCy Schubert static void
be_openssl_destruct(struct bufferevent * bev)12292b15cb3dSCy Schubert be_openssl_destruct(struct bufferevent *bev)
12302b15cb3dSCy Schubert {
12312b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
12322b15cb3dSCy Schubert 
12332b15cb3dSCy Schubert 	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
12342b15cb3dSCy Schubert 		if (! bev_ssl->underlying) {
1235*a466cc55SCy Schubert 			evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
12362b15cb3dSCy Schubert 			BIO *bio = SSL_get_wbio(bev_ssl->ssl);
12372b15cb3dSCy Schubert 			if (bio)
12382b15cb3dSCy Schubert 				fd = BIO_get_fd(bio, NULL);
12392b15cb3dSCy Schubert 			if (fd >= 0)
12402b15cb3dSCy Schubert 				evutil_closesocket(fd);
12412b15cb3dSCy Schubert 		}
12422b15cb3dSCy Schubert 		SSL_free(bev_ssl->ssl);
12432b15cb3dSCy Schubert 	}
12442b15cb3dSCy Schubert }
12452b15cb3dSCy Schubert 
12462b15cb3dSCy Schubert static int
be_openssl_adj_timeouts(struct bufferevent * bev)12472b15cb3dSCy Schubert be_openssl_adj_timeouts(struct bufferevent *bev)
12482b15cb3dSCy Schubert {
12492b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
12502b15cb3dSCy Schubert 
12512b15cb3dSCy Schubert 	if (bev_ssl->underlying) {
12522b15cb3dSCy Schubert 		return bufferevent_generic_adj_timeouts_(bev);
12532b15cb3dSCy Schubert 	} else {
1254*a466cc55SCy Schubert 		return bufferevent_generic_adj_existing_timeouts_(bev);
12552b15cb3dSCy Schubert 	}
12562b15cb3dSCy Schubert }
12572b15cb3dSCy Schubert 
12582b15cb3dSCy Schubert static int
be_openssl_flush(struct bufferevent * bufev,short iotype,enum bufferevent_flush_mode mode)12592b15cb3dSCy Schubert be_openssl_flush(struct bufferevent *bufev,
12602b15cb3dSCy Schubert     short iotype, enum bufferevent_flush_mode mode)
12612b15cb3dSCy Schubert {
12622b15cb3dSCy Schubert 	/* XXXX Implement this. */
12632b15cb3dSCy Schubert 	return 0;
12642b15cb3dSCy Schubert }
12652b15cb3dSCy Schubert 
12662b15cb3dSCy Schubert static int
be_openssl_set_fd(struct bufferevent_openssl * bev_ssl,enum bufferevent_ssl_state state,evutil_socket_t fd)1267*a466cc55SCy Schubert be_openssl_set_fd(struct bufferevent_openssl *bev_ssl,
1268*a466cc55SCy Schubert     enum bufferevent_ssl_state state, evutil_socket_t fd)
1269*a466cc55SCy Schubert {
1270*a466cc55SCy Schubert 	bev_ssl->state = state;
1271*a466cc55SCy Schubert 
1272*a466cc55SCy Schubert 	switch (state) {
1273*a466cc55SCy Schubert 	case BUFFEREVENT_SSL_ACCEPTING:
1274*a466cc55SCy Schubert 		if (!SSL_clear(bev_ssl->ssl))
1275*a466cc55SCy Schubert 			return -1;
1276*a466cc55SCy Schubert 		SSL_set_accept_state(bev_ssl->ssl);
1277*a466cc55SCy Schubert 		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1278*a466cc55SCy Schubert 			return -1;
1279*a466cc55SCy Schubert 		break;
1280*a466cc55SCy Schubert 	case BUFFEREVENT_SSL_CONNECTING:
1281*a466cc55SCy Schubert 		if (!SSL_clear(bev_ssl->ssl))
1282*a466cc55SCy Schubert 			return -1;
1283*a466cc55SCy Schubert 		SSL_set_connect_state(bev_ssl->ssl);
1284*a466cc55SCy Schubert 		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1285*a466cc55SCy Schubert 			return -1;
1286*a466cc55SCy Schubert 		break;
1287*a466cc55SCy Schubert 	case BUFFEREVENT_SSL_OPEN:
1288*a466cc55SCy Schubert 		if (set_open_callbacks(bev_ssl, fd) < 0)
1289*a466cc55SCy Schubert 			return -1;
1290*a466cc55SCy Schubert 		break;
1291*a466cc55SCy Schubert 	default:
1292*a466cc55SCy Schubert 		return -1;
1293*a466cc55SCy Schubert 	}
1294*a466cc55SCy Schubert 
1295*a466cc55SCy Schubert 	return 0;
1296*a466cc55SCy Schubert }
1297*a466cc55SCy Schubert 
1298*a466cc55SCy Schubert static int
be_openssl_ctrl(struct bufferevent * bev,enum bufferevent_ctrl_op op,union bufferevent_ctrl_data * data)12992b15cb3dSCy Schubert be_openssl_ctrl(struct bufferevent *bev,
13002b15cb3dSCy Schubert     enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data)
13012b15cb3dSCy Schubert {
13022b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bev);
13032b15cb3dSCy Schubert 	switch (op) {
13042b15cb3dSCy Schubert 	case BEV_CTRL_SET_FD:
1305*a466cc55SCy Schubert 		if (!bev_ssl->underlying) {
13062b15cb3dSCy Schubert 			BIO *bio;
1307*a466cc55SCy Schubert 			bio = BIO_new_socket((int)data->fd, 0);
13082b15cb3dSCy Schubert 			SSL_set_bio(bev_ssl->ssl, bio, bio);
1309*a466cc55SCy Schubert 		} else {
1310*a466cc55SCy Schubert 			BIO *bio;
1311*a466cc55SCy Schubert 			if (!(bio = BIO_new_bufferevent(bev_ssl->underlying)))
1312*a466cc55SCy Schubert 				return -1;
1313*a466cc55SCy Schubert 			SSL_set_bio(bev_ssl->ssl, bio, bio);
13142b15cb3dSCy Schubert 		}
1315*a466cc55SCy Schubert 
1316*a466cc55SCy Schubert 		return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);
13172b15cb3dSCy Schubert 	case BEV_CTRL_GET_FD:
1318*a466cc55SCy Schubert 		if (bev_ssl->underlying) {
1319*a466cc55SCy Schubert 			data->fd = event_get_fd(&bev_ssl->underlying->ev_read);
1320*a466cc55SCy Schubert 		} else {
13212b15cb3dSCy Schubert 			data->fd = event_get_fd(&bev->ev_read);
1322*a466cc55SCy Schubert 		}
13232b15cb3dSCy Schubert 		return 0;
13242b15cb3dSCy Schubert 	case BEV_CTRL_GET_UNDERLYING:
13252b15cb3dSCy Schubert 		data->ptr = bev_ssl->underlying;
13262b15cb3dSCy Schubert 		return 0;
13272b15cb3dSCy Schubert 	case BEV_CTRL_CANCEL_ALL:
13282b15cb3dSCy Schubert 	default:
13292b15cb3dSCy Schubert 		return -1;
13302b15cb3dSCy Schubert 	}
13312b15cb3dSCy Schubert }
13322b15cb3dSCy Schubert 
13332b15cb3dSCy Schubert SSL *
bufferevent_openssl_get_ssl(struct bufferevent * bufev)13342b15cb3dSCy Schubert bufferevent_openssl_get_ssl(struct bufferevent *bufev)
13352b15cb3dSCy Schubert {
13362b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = upcast(bufev);
13372b15cb3dSCy Schubert 	if (!bev_ssl)
13382b15cb3dSCy Schubert 		return NULL;
13392b15cb3dSCy Schubert 	return bev_ssl->ssl;
13402b15cb3dSCy Schubert }
13412b15cb3dSCy Schubert 
13422b15cb3dSCy Schubert static struct bufferevent *
bufferevent_openssl_new_impl(struct event_base * base,struct bufferevent * underlying,evutil_socket_t fd,SSL * ssl,enum bufferevent_ssl_state state,int options)13432b15cb3dSCy Schubert bufferevent_openssl_new_impl(struct event_base *base,
13442b15cb3dSCy Schubert     struct bufferevent *underlying,
13452b15cb3dSCy Schubert     evutil_socket_t fd,
13462b15cb3dSCy Schubert     SSL *ssl,
13472b15cb3dSCy Schubert     enum bufferevent_ssl_state state,
13482b15cb3dSCy Schubert     int options)
13492b15cb3dSCy Schubert {
13502b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl = NULL;
13512b15cb3dSCy Schubert 	struct bufferevent_private *bev_p = NULL;
13522b15cb3dSCy Schubert 	int tmp_options = options & ~BEV_OPT_THREADSAFE;
13532b15cb3dSCy Schubert 
1354*a466cc55SCy Schubert 	/* Only one can be set. */
13552b15cb3dSCy Schubert 	if (underlying != NULL && fd >= 0)
1356*a466cc55SCy Schubert 		goto err;
13572b15cb3dSCy Schubert 
13582b15cb3dSCy Schubert 	if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))
13592b15cb3dSCy Schubert 		goto err;
13602b15cb3dSCy Schubert 
13612b15cb3dSCy Schubert 	bev_p = &bev_ssl->bev;
13622b15cb3dSCy Schubert 
13632b15cb3dSCy Schubert 	if (bufferevent_init_common_(bev_p, base,
13642b15cb3dSCy Schubert 		&bufferevent_ops_openssl, tmp_options) < 0)
13652b15cb3dSCy Schubert 		goto err;
13662b15cb3dSCy Schubert 
13672b15cb3dSCy Schubert 	/* Don't explode if we decide to realloc a chunk we're writing from in
13682b15cb3dSCy Schubert 	 * the output buffer. */
13692b15cb3dSCy Schubert 	SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
13702b15cb3dSCy Schubert 
13712b15cb3dSCy Schubert 	bev_ssl->underlying = underlying;
13722b15cb3dSCy Schubert 	bev_ssl->ssl = ssl;
13732b15cb3dSCy Schubert 
13742b15cb3dSCy Schubert 	bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output,
13752b15cb3dSCy Schubert 	    be_openssl_outbuf_cb, bev_ssl);
13762b15cb3dSCy Schubert 
13772b15cb3dSCy Schubert 	if (options & BEV_OPT_THREADSAFE)
13782b15cb3dSCy Schubert 		bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL);
13792b15cb3dSCy Schubert 
13802b15cb3dSCy Schubert 	if (underlying) {
13812b15cb3dSCy Schubert 		bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev);
13822b15cb3dSCy Schubert 		bufferevent_incref_(underlying);
13832b15cb3dSCy Schubert 	}
13842b15cb3dSCy Schubert 
1385*a466cc55SCy Schubert 	bev_ssl->old_state = state;
13862b15cb3dSCy Schubert 	bev_ssl->last_write = -1;
13872b15cb3dSCy Schubert 
13882b15cb3dSCy Schubert 	init_bio_counts(bev_ssl);
13892b15cb3dSCy Schubert 
1390*a466cc55SCy Schubert 	fd = be_openssl_auto_fd(bev_ssl, fd);
1391*a466cc55SCy Schubert 	if (be_openssl_set_fd(bev_ssl, state, fd))
13922b15cb3dSCy Schubert 		goto err;
13932b15cb3dSCy Schubert 
13942b15cb3dSCy Schubert 	if (underlying) {
13952b15cb3dSCy Schubert 		bufferevent_setwatermark(underlying, EV_READ, 0, 0);
13962b15cb3dSCy Schubert 		bufferevent_enable(underlying, EV_READ|EV_WRITE);
13972b15cb3dSCy Schubert 		if (state == BUFFEREVENT_SSL_OPEN)
13982b15cb3dSCy Schubert 			bufferevent_suspend_read_(underlying,
13992b15cb3dSCy Schubert 			    BEV_SUSPEND_FILT_READ);
14002b15cb3dSCy Schubert 	}
14012b15cb3dSCy Schubert 
14022b15cb3dSCy Schubert 	return &bev_ssl->bev.bev;
14032b15cb3dSCy Schubert err:
1404*a466cc55SCy Schubert 	if (options & BEV_OPT_CLOSE_ON_FREE)
1405*a466cc55SCy Schubert 		SSL_free(ssl);
1406*a466cc55SCy Schubert 	if (bev_ssl) {
1407*a466cc55SCy Schubert 		bev_ssl->ssl = NULL;
14082b15cb3dSCy Schubert 		bufferevent_free(&bev_ssl->bev.bev);
1409*a466cc55SCy Schubert 	}
14102b15cb3dSCy Schubert 	return NULL;
14112b15cb3dSCy Schubert }
14122b15cb3dSCy Schubert 
14132b15cb3dSCy Schubert struct bufferevent *
bufferevent_openssl_filter_new(struct event_base * base,struct bufferevent * underlying,SSL * ssl,enum bufferevent_ssl_state state,int options)14142b15cb3dSCy Schubert bufferevent_openssl_filter_new(struct event_base *base,
14152b15cb3dSCy Schubert     struct bufferevent *underlying,
14162b15cb3dSCy Schubert     SSL *ssl,
14172b15cb3dSCy Schubert     enum bufferevent_ssl_state state,
14182b15cb3dSCy Schubert     int options)
14192b15cb3dSCy Schubert {
14202b15cb3dSCy Schubert 	BIO *bio;
1421*a466cc55SCy Schubert 	struct bufferevent *bev;
1422*a466cc55SCy Schubert 
14232b15cb3dSCy Schubert 	if (!underlying)
1424*a466cc55SCy Schubert 		goto err;
1425*a466cc55SCy Schubert 	if (!(bio = BIO_new_bufferevent(underlying)))
1426*a466cc55SCy Schubert 		goto err;
14272b15cb3dSCy Schubert 
14282b15cb3dSCy Schubert 	SSL_set_bio(ssl, bio, bio);
14292b15cb3dSCy Schubert 
1430*a466cc55SCy Schubert 	bev = bufferevent_openssl_new_impl(
14312b15cb3dSCy Schubert 		base, underlying, -1, ssl, state, options);
1432*a466cc55SCy Schubert 	return bev;
1433*a466cc55SCy Schubert 
1434*a466cc55SCy Schubert err:
1435*a466cc55SCy Schubert 	if (options & BEV_OPT_CLOSE_ON_FREE)
1436*a466cc55SCy Schubert 		SSL_free(ssl);
1437*a466cc55SCy Schubert 	return NULL;
14382b15cb3dSCy Schubert }
14392b15cb3dSCy Schubert 
14402b15cb3dSCy Schubert struct bufferevent *
bufferevent_openssl_socket_new(struct event_base * base,evutil_socket_t fd,SSL * ssl,enum bufferevent_ssl_state state,int options)14412b15cb3dSCy Schubert bufferevent_openssl_socket_new(struct event_base *base,
14422b15cb3dSCy Schubert     evutil_socket_t fd,
14432b15cb3dSCy Schubert     SSL *ssl,
14442b15cb3dSCy Schubert     enum bufferevent_ssl_state state,
14452b15cb3dSCy Schubert     int options)
14462b15cb3dSCy Schubert {
14472b15cb3dSCy Schubert 	/* Does the SSL already have an fd? */
14482b15cb3dSCy Schubert 	BIO *bio = SSL_get_wbio(ssl);
14492b15cb3dSCy Schubert 	long have_fd = -1;
14502b15cb3dSCy Schubert 
14512b15cb3dSCy Schubert 	if (bio)
14522b15cb3dSCy Schubert 		have_fd = BIO_get_fd(bio, NULL);
14532b15cb3dSCy Schubert 
14542b15cb3dSCy Schubert 	if (have_fd >= 0) {
14552b15cb3dSCy Schubert 		/* The SSL is already configured with an fd. */
14562b15cb3dSCy Schubert 		if (fd < 0) {
14572b15cb3dSCy Schubert 			/* We should learn the fd from the SSL. */
14582b15cb3dSCy Schubert 			fd = (evutil_socket_t) have_fd;
14592b15cb3dSCy Schubert 		} else if (have_fd == (long)fd) {
14602b15cb3dSCy Schubert 			/* We already know the fd from the SSL; do nothing */
14612b15cb3dSCy Schubert 		} else {
14622b15cb3dSCy Schubert 			/* We specified an fd different from that of the SSL.
14632b15cb3dSCy Schubert 			   This is probably an error on our part.  Fail. */
1464*a466cc55SCy Schubert 			goto err;
14652b15cb3dSCy Schubert 		}
1466*a466cc55SCy Schubert 		BIO_set_close(bio, 0);
14672b15cb3dSCy Schubert 	} else {
14682b15cb3dSCy Schubert 		/* The SSL isn't configured with a BIO with an fd. */
14692b15cb3dSCy Schubert 		if (fd >= 0) {
14702b15cb3dSCy Schubert 			/* ... and we have an fd we want to use. */
1471*a466cc55SCy Schubert 			bio = BIO_new_socket((int)fd, 0);
14722b15cb3dSCy Schubert 			SSL_set_bio(ssl, bio, bio);
14732b15cb3dSCy Schubert 		} else {
14742b15cb3dSCy Schubert 			/* Leave the fd unset. */
14752b15cb3dSCy Schubert 		}
14762b15cb3dSCy Schubert 	}
14772b15cb3dSCy Schubert 
14782b15cb3dSCy Schubert 	return bufferevent_openssl_new_impl(
14792b15cb3dSCy Schubert 		base, NULL, fd, ssl, state, options);
1480*a466cc55SCy Schubert 
1481*a466cc55SCy Schubert err:
1482*a466cc55SCy Schubert 	if (options & BEV_OPT_CLOSE_ON_FREE)
1483*a466cc55SCy Schubert 		SSL_free(ssl);
1484*a466cc55SCy Schubert 	return NULL;
14852b15cb3dSCy Schubert }
14862b15cb3dSCy Schubert 
14872b15cb3dSCy Schubert int
bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent * bev)14882b15cb3dSCy Schubert bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev)
14892b15cb3dSCy Schubert {
14902b15cb3dSCy Schubert 	int allow_dirty_shutdown = -1;
14912b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl;
14922b15cb3dSCy Schubert 	BEV_LOCK(bev);
14932b15cb3dSCy Schubert 	bev_ssl = upcast(bev);
14942b15cb3dSCy Schubert 	if (bev_ssl)
14952b15cb3dSCy Schubert 		allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown;
14962b15cb3dSCy Schubert 	BEV_UNLOCK(bev);
14972b15cb3dSCy Schubert 	return allow_dirty_shutdown;
14982b15cb3dSCy Schubert }
14992b15cb3dSCy Schubert 
15002b15cb3dSCy Schubert void
bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent * bev,int allow_dirty_shutdown)15012b15cb3dSCy Schubert bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
15022b15cb3dSCy Schubert     int allow_dirty_shutdown)
15032b15cb3dSCy Schubert {
15042b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl;
15052b15cb3dSCy Schubert 	BEV_LOCK(bev);
15062b15cb3dSCy Schubert 	bev_ssl = upcast(bev);
15072b15cb3dSCy Schubert 	if (bev_ssl)
15082b15cb3dSCy Schubert 		bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown;
15092b15cb3dSCy Schubert 	BEV_UNLOCK(bev);
15102b15cb3dSCy Schubert }
15112b15cb3dSCy Schubert 
15122b15cb3dSCy Schubert unsigned long
bufferevent_get_openssl_error(struct bufferevent * bev)15132b15cb3dSCy Schubert bufferevent_get_openssl_error(struct bufferevent *bev)
15142b15cb3dSCy Schubert {
15152b15cb3dSCy Schubert 	unsigned long err = 0;
15162b15cb3dSCy Schubert 	struct bufferevent_openssl *bev_ssl;
15172b15cb3dSCy Schubert 	BEV_LOCK(bev);
15182b15cb3dSCy Schubert 	bev_ssl = upcast(bev);
15192b15cb3dSCy Schubert 	if (bev_ssl && bev_ssl->n_errors) {
15202b15cb3dSCy Schubert 		err = bev_ssl->errors[--bev_ssl->n_errors];
15212b15cb3dSCy Schubert 	}
15222b15cb3dSCy Schubert 	BEV_UNLOCK(bev);
15232b15cb3dSCy Schubert 	return err;
15242b15cb3dSCy Schubert }
1525