xref: /netbsd-src/external/bsd/ntp/dist/sntp/libevent/bufferevent_openssl.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: bufferevent_openssl.c,v 1.7 2024/08/18 20:47:21 christos Exp $	*/
28585484eSchristos 
38585484eSchristos /*
48585484eSchristos  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
58585484eSchristos  *
68585484eSchristos  * Redistribution and use in source and binary forms, with or without
78585484eSchristos  * modification, are permitted provided that the following conditions
88585484eSchristos  * are met:
98585484eSchristos  * 1. Redistributions of source code must retain the above copyright
108585484eSchristos  *    notice, this list of conditions and the following disclaimer.
118585484eSchristos  * 2. Redistributions in binary form must reproduce the above copyright
128585484eSchristos  *    notice, this list of conditions and the following disclaimer in the
138585484eSchristos  *    documentation and/or other materials provided with the distribution.
148585484eSchristos  * 3. The name of the author may not be used to endorse or promote products
158585484eSchristos  *    derived from this software without specific prior written permission.
168585484eSchristos  *
178585484eSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
188585484eSchristos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
198585484eSchristos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
208585484eSchristos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
218585484eSchristos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
228585484eSchristos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
238585484eSchristos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
248585484eSchristos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258585484eSchristos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268585484eSchristos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278585484eSchristos  */
288585484eSchristos 
29b8ecfcfeSchristos // Get rid of OSX 10.7 and greater deprecation warnings.
30b8ecfcfeSchristos #if defined(__APPLE__) && defined(__clang__)
31b8ecfcfeSchristos #pragma clang diagnostic ignored "-Wdeprecated-declarations"
32b8ecfcfeSchristos #endif
33b8ecfcfeSchristos 
348585484eSchristos #include "event2/event-config.h"
358585484eSchristos #include "evconfig-private.h"
368585484eSchristos 
378585484eSchristos #include <sys/types.h>
388585484eSchristos 
398585484eSchristos #ifdef EVENT__HAVE_SYS_TIME_H
408585484eSchristos #include <sys/time.h>
418585484eSchristos #endif
428585484eSchristos 
438585484eSchristos #include <errno.h>
448585484eSchristos #include <stdio.h>
458585484eSchristos #include <stdlib.h>
468585484eSchristos #include <string.h>
478585484eSchristos #ifdef EVENT__HAVE_STDARG_H
488585484eSchristos #include <stdarg.h>
498585484eSchristos #endif
508585484eSchristos #ifdef EVENT__HAVE_UNISTD_H
518585484eSchristos #include <unistd.h>
528585484eSchristos #endif
538585484eSchristos 
548585484eSchristos #ifdef _WIN32
558585484eSchristos #include <winsock2.h>
568585484eSchristos #endif
578585484eSchristos 
588585484eSchristos #include "event2/bufferevent.h"
598585484eSchristos #include "event2/bufferevent_struct.h"
608585484eSchristos #include "event2/bufferevent_ssl.h"
618585484eSchristos #include "event2/buffer.h"
628585484eSchristos #include "event2/event.h"
638585484eSchristos 
648585484eSchristos #include "mm-internal.h"
658585484eSchristos #include "bufferevent-internal.h"
668585484eSchristos #include "log-internal.h"
678585484eSchristos 
688585484eSchristos #include <openssl/ssl.h>
698585484eSchristos #include <openssl/err.h>
70*eabc0478Schristos #include "openssl-compat.h"
718585484eSchristos 
728585484eSchristos /*
738585484eSchristos  * Define an OpenSSL bio that targets a bufferevent.
748585484eSchristos  */
758585484eSchristos 
768585484eSchristos /* --------------------
778585484eSchristos    A BIO is an OpenSSL abstraction that handles reading and writing data.  The
788585484eSchristos    library will happily speak SSL over anything that implements a BIO
798585484eSchristos    interface.
808585484eSchristos 
818585484eSchristos    Here we define a BIO implementation that directs its output to a
828585484eSchristos    bufferevent.  We'll want to use this only when none of OpenSSL's built-in
838585484eSchristos    IO mechanisms work for us.
848585484eSchristos    -------------------- */
858585484eSchristos 
868585484eSchristos /* every BIO type needs its own integer type value. */
878585484eSchristos #define BIO_TYPE_LIBEVENT 57
888585484eSchristos /* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on
898585484eSchristos  * this. */
908585484eSchristos 
918585484eSchristos #if 0
928585484eSchristos static void
938585484eSchristos print_err(int val)
948585484eSchristos {
958585484eSchristos 	int err;
968585484eSchristos 	printf("Error was %d\n", val);
978585484eSchristos 
988585484eSchristos 	while ((err = ERR_get_error())) {
998585484eSchristos 		const char *msg = (const char*)ERR_reason_error_string(err);
1008585484eSchristos 		const char *lib = (const char*)ERR_lib_error_string(err);
1018585484eSchristos 		const char *func = (const char*)ERR_func_error_string(err);
1028585484eSchristos 
1038585484eSchristos 		printf("%s in %s %s\n", msg, lib, func);
1048585484eSchristos 	}
1058585484eSchristos }
1068585484eSchristos #else
1078585484eSchristos #define print_err(v) ((void)0)
1088585484eSchristos #endif
1098585484eSchristos 
1108585484eSchristos /* Called to initialize a new BIO */
1118585484eSchristos static int
1128585484eSchristos bio_bufferevent_new(BIO *b)
1138585484eSchristos {
114*eabc0478Schristos 	BIO_set_init(b, 0);
115*eabc0478Schristos 	BIO_set_data(b, NULL); /* We'll be putting the bufferevent in this field.*/
1168585484eSchristos 	return 1;
1178585484eSchristos }
1188585484eSchristos 
1198585484eSchristos /* Called to uninitialize the BIO. */
1208585484eSchristos static int
1218585484eSchristos bio_bufferevent_free(BIO *b)
1228585484eSchristos {
1238585484eSchristos 	if (!b)
1248585484eSchristos 		return 0;
125*eabc0478Schristos 	if (BIO_get_shutdown(b)) {
126*eabc0478Schristos 		if (BIO_get_init(b) && BIO_get_data(b))
127*eabc0478Schristos 			bufferevent_free(BIO_get_data(b));
128*eabc0478Schristos 		BIO_free(b);
1298585484eSchristos 	}
1308585484eSchristos 	return 1;
1318585484eSchristos }
1328585484eSchristos 
1338585484eSchristos /* Called to extract data from the BIO. */
1348585484eSchristos static int
1358585484eSchristos bio_bufferevent_read(BIO *b, char *out, int outlen)
1368585484eSchristos {
1378585484eSchristos 	int r = 0;
1388585484eSchristos 	struct evbuffer *input;
1398585484eSchristos 
1408585484eSchristos 	BIO_clear_retry_flags(b);
1418585484eSchristos 
1428585484eSchristos 	if (!out)
1438585484eSchristos 		return 0;
144*eabc0478Schristos 	if (!BIO_get_data(b))
1458585484eSchristos 		return -1;
1468585484eSchristos 
147*eabc0478Schristos 	input = bufferevent_get_input(BIO_get_data(b));
1488585484eSchristos 	if (evbuffer_get_length(input) == 0) {
1498585484eSchristos 		/* If there's no data to read, say so. */
1508585484eSchristos 		BIO_set_retry_read(b);
1518585484eSchristos 		return -1;
1528585484eSchristos 	} else {
1538585484eSchristos 		r = evbuffer_remove(input, out, outlen);
1548585484eSchristos 	}
1558585484eSchristos 
1568585484eSchristos 	return r;
1578585484eSchristos }
1588585484eSchristos 
159*eabc0478Schristos /* Called to write data into the BIO */
1608585484eSchristos static int
1618585484eSchristos bio_bufferevent_write(BIO *b, const char *in, int inlen)
1628585484eSchristos {
163*eabc0478Schristos 	struct bufferevent *bufev = BIO_get_data(b);
1648585484eSchristos 	struct evbuffer *output;
1658585484eSchristos 	size_t outlen;
1668585484eSchristos 
1678585484eSchristos 	BIO_clear_retry_flags(b);
1688585484eSchristos 
169*eabc0478Schristos 	if (!BIO_get_data(b))
1708585484eSchristos 		return -1;
1718585484eSchristos 
1728585484eSchristos 	output = bufferevent_get_output(bufev);
1738585484eSchristos 	outlen = evbuffer_get_length(output);
1748585484eSchristos 
1758585484eSchristos 	/* Copy only as much data onto the output buffer as can fit under the
1768585484eSchristos 	 * high-water mark. */
1778585484eSchristos 	if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {
1788585484eSchristos 		if (bufev->wm_write.high <= outlen) {
1798585484eSchristos 			/* If no data can fit, we'll need to retry later. */
1808585484eSchristos 			BIO_set_retry_write(b);
1818585484eSchristos 			return -1;
1828585484eSchristos 		}
1838585484eSchristos 		inlen = bufev->wm_write.high - outlen;
1848585484eSchristos 	}
1858585484eSchristos 
1868585484eSchristos 	EVUTIL_ASSERT(inlen > 0);
1878585484eSchristos 	evbuffer_add(output, in, inlen);
1888585484eSchristos 	return inlen;
1898585484eSchristos }
1908585484eSchristos 
1918585484eSchristos /* Called to handle various requests */
1928585484eSchristos static long
1938585484eSchristos bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)
1948585484eSchristos {
195*eabc0478Schristos 	struct bufferevent *bufev = BIO_get_data(b);
1968585484eSchristos 	long ret = 1;
1978585484eSchristos 
1988585484eSchristos 	switch (cmd) {
1998585484eSchristos 	case BIO_CTRL_GET_CLOSE:
200*eabc0478Schristos 		ret = BIO_get_shutdown(b);
2018585484eSchristos 		break;
2028585484eSchristos 	case BIO_CTRL_SET_CLOSE:
203*eabc0478Schristos 		BIO_set_shutdown(b, (int)num);
2048585484eSchristos 		break;
2058585484eSchristos 	case BIO_CTRL_PENDING:
2068585484eSchristos 		ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;
2078585484eSchristos 		break;
2088585484eSchristos 	case BIO_CTRL_WPENDING:
2098585484eSchristos 		ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0;
2108585484eSchristos 		break;
2118585484eSchristos 	/* XXXX These two are given a special-case treatment because
2128585484eSchristos 	 * of cargo-cultism.  I should come up with a better reason. */
2138585484eSchristos 	case BIO_CTRL_DUP:
2148585484eSchristos 	case BIO_CTRL_FLUSH:
2158585484eSchristos 		ret = 1;
2168585484eSchristos 		break;
2178585484eSchristos 	default:
2188585484eSchristos 		ret = 0;
2198585484eSchristos 		break;
2208585484eSchristos 	}
2218585484eSchristos 	return ret;
2228585484eSchristos }
2238585484eSchristos 
2248585484eSchristos /* Called to write a string to the BIO */
2258585484eSchristos static int
2268585484eSchristos bio_bufferevent_puts(BIO *b, const char *s)
2278585484eSchristos {
2288585484eSchristos 	return bio_bufferevent_write(b, s, strlen(s));
2298585484eSchristos }
2308585484eSchristos 
2318585484eSchristos /* Method table for the bufferevent BIO */
232*eabc0478Schristos static BIO_METHOD *methods_bufferevent;
2338585484eSchristos 
2348585484eSchristos /* Return the method table for the bufferevents BIO */
2358585484eSchristos static BIO_METHOD *
2368585484eSchristos BIO_s_bufferevent(void)
2378585484eSchristos {
238*eabc0478Schristos 	if (methods_bufferevent == NULL) {
239*eabc0478Schristos 		methods_bufferevent = BIO_meth_new(BIO_TYPE_LIBEVENT, "bufferevent");
240*eabc0478Schristos 		if (methods_bufferevent == NULL)
241*eabc0478Schristos 			return NULL;
242*eabc0478Schristos 		BIO_meth_set_write(methods_bufferevent, bio_bufferevent_write);
243*eabc0478Schristos 		BIO_meth_set_read(methods_bufferevent, bio_bufferevent_read);
244*eabc0478Schristos 		BIO_meth_set_puts(methods_bufferevent, bio_bufferevent_puts);
245*eabc0478Schristos 		BIO_meth_set_ctrl(methods_bufferevent, bio_bufferevent_ctrl);
246*eabc0478Schristos 		BIO_meth_set_create(methods_bufferevent, bio_bufferevent_new);
247*eabc0478Schristos 		BIO_meth_set_destroy(methods_bufferevent, bio_bufferevent_free);
248*eabc0478Schristos 	}
249*eabc0478Schristos 	return methods_bufferevent;
2508585484eSchristos }
2518585484eSchristos 
2528585484eSchristos /* Create a new BIO to wrap communication around a bufferevent.  If close_flag
2538585484eSchristos  * is true, the bufferevent will be freed when the BIO is closed. */
2548585484eSchristos static BIO *
255*eabc0478Schristos BIO_new_bufferevent(struct bufferevent *bufferevent)
2568585484eSchristos {
2578585484eSchristos 	BIO *result;
2588585484eSchristos 	if (!bufferevent)
2598585484eSchristos 		return NULL;
2608585484eSchristos 	if (!(result = BIO_new(BIO_s_bufferevent())))
2618585484eSchristos 		return NULL;
262*eabc0478Schristos 	BIO_set_init(result, 1);
263*eabc0478Schristos 	BIO_set_data(result, bufferevent);
264*eabc0478Schristos 	/* We don't tell the BIO to close the bufferevent; we do it ourselves on
265*eabc0478Schristos 	 * be_openssl_destruct() */
266*eabc0478Schristos 	BIO_set_shutdown(result, 0);
2678585484eSchristos 	return result;
2688585484eSchristos }
2698585484eSchristos 
2708585484eSchristos /* --------------------
2718585484eSchristos    Now, here's the OpenSSL-based implementation of bufferevent.
2728585484eSchristos 
2738585484eSchristos    The implementation comes in two flavors: one that connects its SSL object
2748585484eSchristos    to an underlying bufferevent using a BIO_bufferevent, and one that has the
2758585484eSchristos    SSL object connect to a socket directly.  The latter should generally be
2768585484eSchristos    faster, except on Windows, where your best bet is using a
2778585484eSchristos    bufferevent_async.
2788585484eSchristos 
2798585484eSchristos    (OpenSSL supports many other BIO types, too.  But we can't use any unless
2808585484eSchristos    we have a good way to get notified when they become readable/writable.)
2818585484eSchristos    -------------------- */
2828585484eSchristos 
2838585484eSchristos struct bio_data_counts {
2848585484eSchristos 	unsigned long n_written;
2858585484eSchristos 	unsigned long n_read;
2868585484eSchristos };
2878585484eSchristos 
2888585484eSchristos struct bufferevent_openssl {
2898585484eSchristos 	/* Shared fields with common bufferevent implementation code.
2908585484eSchristos 	   If we were set up with an underlying bufferevent, we use the
2918585484eSchristos 	   events here as timers only.  If we have an SSL, then we use
2928585484eSchristos 	   the events as socket events.
2938585484eSchristos 	 */
2948585484eSchristos 	struct bufferevent_private bev;
2958585484eSchristos 	/* An underlying bufferevent that we're directing our output to.
2968585484eSchristos 	   If it's NULL, then we're connected to an fd, not an evbuffer. */
2978585484eSchristos 	struct bufferevent *underlying;
2988585484eSchristos 	/* The SSL object doing our encryption. */
2998585484eSchristos 	SSL *ssl;
3008585484eSchristos 
3018585484eSchristos 	/* A callback that's invoked when data arrives on our outbuf so we
3028585484eSchristos 	   know to write data to the SSL. */
3038585484eSchristos 	struct evbuffer_cb_entry *outbuf_cb;
3048585484eSchristos 
3058585484eSchristos 	/* A count of how much data the bios have read/written total.  Used
3068585484eSchristos 	   for rate-limiting. */
3078585484eSchristos 	struct bio_data_counts counts;
3088585484eSchristos 
3098585484eSchristos 	/* If this value is greater than 0, then the last SSL_write blocked,
3108585484eSchristos 	 * and we need to try it again with this many bytes. */
3118585484eSchristos 	ev_ssize_t last_write;
3128585484eSchristos 
3138585484eSchristos #define NUM_ERRORS 3
3148585484eSchristos 	ev_uint32_t errors[NUM_ERRORS];
3158585484eSchristos 
3168585484eSchristos 	/* When we next get available space, we should say "read" instead of
3178585484eSchristos 	   "write". This can happen if there's a renegotiation during a read
3188585484eSchristos 	   operation. */
3198585484eSchristos 	unsigned read_blocked_on_write : 1;
3208585484eSchristos 	/* When we next get data, we should say "write" instead of "read". */
3218585484eSchristos 	unsigned write_blocked_on_read : 1;
3228585484eSchristos 	/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
3238585484eSchristos 	unsigned allow_dirty_shutdown : 1;
3248585484eSchristos 	/* XXX */
3258585484eSchristos 	unsigned n_errors : 2;
3268585484eSchristos 
3278585484eSchristos 	/* Are we currently connecting, accepting, or doing IO? */
3288585484eSchristos 	unsigned state : 2;
329*eabc0478Schristos 	/* If we reset fd, we sould reset state too */
330*eabc0478Schristos 	unsigned old_state : 2;
3318585484eSchristos };
3328585484eSchristos 
3338585484eSchristos static int be_openssl_enable(struct bufferevent *, short);
3348585484eSchristos static int be_openssl_disable(struct bufferevent *, short);
335b8ecfcfeSchristos static void be_openssl_unlink(struct bufferevent *);
3368585484eSchristos static void be_openssl_destruct(struct bufferevent *);
3378585484eSchristos static int be_openssl_adj_timeouts(struct bufferevent *);
3388585484eSchristos static int be_openssl_flush(struct bufferevent *bufev,
3398585484eSchristos     short iotype, enum bufferevent_flush_mode mode);
3408585484eSchristos static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
3418585484eSchristos 
3428585484eSchristos const struct bufferevent_ops bufferevent_ops_openssl = {
3438585484eSchristos 	"ssl",
3448585484eSchristos 	evutil_offsetof(struct bufferevent_openssl, bev.bev),
3458585484eSchristos 	be_openssl_enable,
3468585484eSchristos 	be_openssl_disable,
347b8ecfcfeSchristos 	be_openssl_unlink,
3488585484eSchristos 	be_openssl_destruct,
3498585484eSchristos 	be_openssl_adj_timeouts,
3508585484eSchristos 	be_openssl_flush,
3518585484eSchristos 	be_openssl_ctrl,
3528585484eSchristos };
3538585484eSchristos 
3548585484eSchristos /* Given a bufferevent, return a pointer to the bufferevent_openssl that
3558585484eSchristos  * contains it, if any. */
3568585484eSchristos static inline struct bufferevent_openssl *
3578585484eSchristos upcast(struct bufferevent *bev)
3588585484eSchristos {
3598585484eSchristos 	struct bufferevent_openssl *bev_o;
360*eabc0478Schristos 	if (!BEV_IS_OPENSSL(bev))
3618585484eSchristos 		return NULL;
3628585484eSchristos 	bev_o = (void*)( ((char*)bev) -
3638585484eSchristos 			 evutil_offsetof(struct bufferevent_openssl, bev.bev));
364*eabc0478Schristos 	EVUTIL_ASSERT(BEV_IS_OPENSSL(&bev_o->bev.bev));
3658585484eSchristos 	return bev_o;
3668585484eSchristos }
3678585484eSchristos 
3688585484eSchristos static inline void
3698585484eSchristos put_error(struct bufferevent_openssl *bev_ssl, unsigned long err)
3708585484eSchristos {
3718585484eSchristos 	if (bev_ssl->n_errors == NUM_ERRORS)
3728585484eSchristos 		return;
3738585484eSchristos 	/* The error type according to openssl is "unsigned long", but
3748585484eSchristos 	   openssl never uses more than 32 bits of it.  It _can't_ use more
3758585484eSchristos 	   than 32 bits of it, since it needs to report errors on systems
3768585484eSchristos 	   where long is only 32 bits.
3778585484eSchristos 	 */
3788585484eSchristos 	bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err;
3798585484eSchristos }
3808585484eSchristos 
3818585484eSchristos /* Have the base communications channel (either the underlying bufferevent or
3828585484eSchristos  * ev_read and ev_write) start reading.  Take the read-blocked-on-write flag
3838585484eSchristos  * into account. */
3848585484eSchristos static int
3858585484eSchristos start_reading(struct bufferevent_openssl *bev_ssl)
3868585484eSchristos {
3878585484eSchristos 	if (bev_ssl->underlying) {
3888585484eSchristos 		bufferevent_unsuspend_read_(bev_ssl->underlying,
3898585484eSchristos 		    BEV_SUSPEND_FILT_READ);
3908585484eSchristos 		return 0;
3918585484eSchristos 	} else {
3928585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
3938585484eSchristos 		int r;
3948585484eSchristos 		r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
3958585484eSchristos 		if (r == 0 && bev_ssl->read_blocked_on_write)
3968585484eSchristos 			r = bufferevent_add_event_(&bev->ev_write,
3978585484eSchristos 			    &bev->timeout_write);
3988585484eSchristos 		return r;
3998585484eSchristos 	}
4008585484eSchristos }
4018585484eSchristos 
4028585484eSchristos /* Have the base communications channel (either the underlying bufferevent or
4038585484eSchristos  * ev_read and ev_write) start writing.  Take the write-blocked-on-read flag
4048585484eSchristos  * into account. */
4058585484eSchristos static int
4068585484eSchristos start_writing(struct bufferevent_openssl *bev_ssl)
4078585484eSchristos {
4088585484eSchristos 	int r = 0;
4098585484eSchristos 	if (bev_ssl->underlying) {
410*eabc0478Schristos 		if (bev_ssl->write_blocked_on_read) {
411*eabc0478Schristos 			bufferevent_unsuspend_read_(bev_ssl->underlying,
412*eabc0478Schristos 			    BEV_SUSPEND_FILT_READ);
413*eabc0478Schristos 		}
4148585484eSchristos 	} else {
4158585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
4168585484eSchristos 		r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
4178585484eSchristos 		if (!r && bev_ssl->write_blocked_on_read)
4188585484eSchristos 			r = bufferevent_add_event_(&bev->ev_read,
4198585484eSchristos 			    &bev->timeout_read);
4208585484eSchristos 	}
4218585484eSchristos 	return r;
4228585484eSchristos }
4238585484eSchristos 
4248585484eSchristos static void
4258585484eSchristos stop_reading(struct bufferevent_openssl *bev_ssl)
4268585484eSchristos {
4278585484eSchristos 	if (bev_ssl->write_blocked_on_read)
4288585484eSchristos 		return;
4298585484eSchristos 	if (bev_ssl->underlying) {
4308585484eSchristos 		bufferevent_suspend_read_(bev_ssl->underlying,
4318585484eSchristos 		    BEV_SUSPEND_FILT_READ);
4328585484eSchristos 	} else {
4338585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
4348585484eSchristos 		event_del(&bev->ev_read);
4358585484eSchristos 	}
4368585484eSchristos }
4378585484eSchristos 
4388585484eSchristos static void
4398585484eSchristos stop_writing(struct bufferevent_openssl *bev_ssl)
4408585484eSchristos {
4418585484eSchristos 	if (bev_ssl->read_blocked_on_write)
4428585484eSchristos 		return;
4438585484eSchristos 	if (bev_ssl->underlying) {
444*eabc0478Schristos 		bufferevent_unsuspend_read_(bev_ssl->underlying,
445*eabc0478Schristos 		    BEV_SUSPEND_FILT_READ);
4468585484eSchristos 	} else {
4478585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
4488585484eSchristos 		event_del(&bev->ev_write);
4498585484eSchristos 	}
4508585484eSchristos }
4518585484eSchristos 
4528585484eSchristos static int
4538585484eSchristos set_rbow(struct bufferevent_openssl *bev_ssl)
4548585484eSchristos {
4558585484eSchristos 	if (!bev_ssl->underlying)
4568585484eSchristos 		stop_reading(bev_ssl);
4578585484eSchristos 	bev_ssl->read_blocked_on_write = 1;
4588585484eSchristos 	return start_writing(bev_ssl);
4598585484eSchristos }
4608585484eSchristos 
4618585484eSchristos static int
4628585484eSchristos set_wbor(struct bufferevent_openssl *bev_ssl)
4638585484eSchristos {
4648585484eSchristos 	if (!bev_ssl->underlying)
4658585484eSchristos 		stop_writing(bev_ssl);
4668585484eSchristos 	bev_ssl->write_blocked_on_read = 1;
4678585484eSchristos 	return start_reading(bev_ssl);
4688585484eSchristos }
4698585484eSchristos 
4708585484eSchristos static int
4718585484eSchristos clear_rbow(struct bufferevent_openssl *bev_ssl)
4728585484eSchristos {
4738585484eSchristos 	struct bufferevent *bev = &bev_ssl->bev.bev;
4748585484eSchristos 	int r = 0;
4758585484eSchristos 	bev_ssl->read_blocked_on_write = 0;
4768585484eSchristos 	if (!(bev->enabled & EV_WRITE))
4778585484eSchristos 		stop_writing(bev_ssl);
4788585484eSchristos 	if (bev->enabled & EV_READ)
4798585484eSchristos 		r = start_reading(bev_ssl);
4808585484eSchristos 	return r;
4818585484eSchristos }
4828585484eSchristos 
4838585484eSchristos 
4848585484eSchristos static int
4858585484eSchristos clear_wbor(struct bufferevent_openssl *bev_ssl)
4868585484eSchristos {
4878585484eSchristos 	struct bufferevent *bev = &bev_ssl->bev.bev;
4888585484eSchristos 	int r = 0;
4898585484eSchristos 	bev_ssl->write_blocked_on_read = 0;
4908585484eSchristos 	if (!(bev->enabled & EV_READ))
4918585484eSchristos 		stop_reading(bev_ssl);
4928585484eSchristos 	if (bev->enabled & EV_WRITE)
4938585484eSchristos 		r = start_writing(bev_ssl);
4948585484eSchristos 	return r;
4958585484eSchristos }
4968585484eSchristos 
4978585484eSchristos static void
4988585484eSchristos conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret)
4998585484eSchristos {
5008585484eSchristos 	int event = BEV_EVENT_ERROR;
5018585484eSchristos 	int dirty_shutdown = 0;
5028585484eSchristos 	unsigned long err;
5038585484eSchristos 
5048585484eSchristos 	switch (errcode) {
5058585484eSchristos 	case SSL_ERROR_ZERO_RETURN:
5068585484eSchristos 		/* Possibly a clean shutdown. */
5078585484eSchristos 		if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)
5088585484eSchristos 			event = BEV_EVENT_EOF;
5098585484eSchristos 		else
5108585484eSchristos 			dirty_shutdown = 1;
5118585484eSchristos 		break;
5128585484eSchristos 	case SSL_ERROR_SYSCALL:
5138585484eSchristos 		/* IO error; possibly a dirty shutdown. */
514*eabc0478Schristos 		if ((ret == 0 || ret == -1) && ERR_peek_error() == 0)
5158585484eSchristos 			dirty_shutdown = 1;
516*eabc0478Schristos 		put_error(bev_ssl, errcode);
5178585484eSchristos 		break;
5188585484eSchristos 	case SSL_ERROR_SSL:
5198585484eSchristos 		/* Protocol error. */
520*eabc0478Schristos 		put_error(bev_ssl, errcode);
5218585484eSchristos 		break;
5228585484eSchristos 	case SSL_ERROR_WANT_X509_LOOKUP:
5238585484eSchristos 		/* XXXX handle this. */
524*eabc0478Schristos 		put_error(bev_ssl, errcode);
5258585484eSchristos 		break;
5268585484eSchristos 	case SSL_ERROR_NONE:
5278585484eSchristos 	case SSL_ERROR_WANT_READ:
5288585484eSchristos 	case SSL_ERROR_WANT_WRITE:
5298585484eSchristos 	case SSL_ERROR_WANT_CONNECT:
5308585484eSchristos 	case SSL_ERROR_WANT_ACCEPT:
5318585484eSchristos 	default:
5328585484eSchristos 		/* should be impossible; treat as normal error. */
5338585484eSchristos 		event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);
5348585484eSchristos 		break;
5358585484eSchristos 	}
5368585484eSchristos 
5378585484eSchristos 	while ((err = ERR_get_error())) {
5388585484eSchristos 		put_error(bev_ssl, err);
5398585484eSchristos 	}
5408585484eSchristos 
5418585484eSchristos 	if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)
5428585484eSchristos 		event = BEV_EVENT_EOF;
5438585484eSchristos 
5448585484eSchristos 	stop_reading(bev_ssl);
5458585484eSchristos 	stop_writing(bev_ssl);
5468585484eSchristos 
5478585484eSchristos 	/* when is BEV_EVENT_{READING|WRITING} */
5488585484eSchristos 	event = when | event;
549b8ecfcfeSchristos 	bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
5508585484eSchristos }
5518585484eSchristos 
5528585484eSchristos static void
5538585484eSchristos init_bio_counts(struct bufferevent_openssl *bev_ssl)
5548585484eSchristos {
555*eabc0478Schristos 	BIO *rbio, *wbio;
556*eabc0478Schristos 
557*eabc0478Schristos 	wbio = SSL_get_wbio(bev_ssl->ssl);
558*eabc0478Schristos 	bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0;
559*eabc0478Schristos 	rbio = SSL_get_rbio(bev_ssl->ssl);
560*eabc0478Schristos 	bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0;
5618585484eSchristos }
5628585484eSchristos 
5638585484eSchristos static inline void
5648585484eSchristos decrement_buckets(struct bufferevent_openssl *bev_ssl)
5658585484eSchristos {
5668585484eSchristos 	unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
5678585484eSchristos 	unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
5688585484eSchristos 	/* These next two subtractions can wrap around. That's okay. */
5698585484eSchristos 	unsigned long w = num_w - bev_ssl->counts.n_written;
5708585484eSchristos 	unsigned long r = num_r - bev_ssl->counts.n_read;
5718585484eSchristos 	if (w)
5728585484eSchristos 		bufferevent_decrement_write_buckets_(&bev_ssl->bev, w);
5738585484eSchristos 	if (r)
5748585484eSchristos 		bufferevent_decrement_read_buckets_(&bev_ssl->bev, r);
5758585484eSchristos 	bev_ssl->counts.n_written = num_w;
5768585484eSchristos 	bev_ssl->counts.n_read = num_r;
5778585484eSchristos }
5788585484eSchristos 
5798585484eSchristos #define OP_MADE_PROGRESS 1
5808585484eSchristos #define OP_BLOCKED 2
5818585484eSchristos #define OP_ERR 4
5828585484eSchristos 
5838585484eSchristos /* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if
5848585484eSchristos    we're now blocked); and OP_ERR (if an error occurred). */
5858585484eSchristos static int
5868585484eSchristos do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {
5878585484eSchristos 	/* Requires lock */
5888585484eSchristos 	struct bufferevent *bev = &bev_ssl->bev.bev;
5898585484eSchristos 	struct evbuffer *input = bev->input;
5908585484eSchristos 	int r, n, i, n_used = 0, atmost;
5918585484eSchristos 	struct evbuffer_iovec space[2];
5928585484eSchristos 	int result = 0;
5938585484eSchristos 
5948585484eSchristos 	if (bev_ssl->bev.read_suspended)
5958585484eSchristos 		return 0;
5968585484eSchristos 
5978585484eSchristos 	atmost = bufferevent_get_read_max_(&bev_ssl->bev);
5988585484eSchristos 	if (n_to_read > atmost)
5998585484eSchristos 		n_to_read = atmost;
6008585484eSchristos 
6018585484eSchristos 	n = evbuffer_reserve_space(input, n_to_read, space, 2);
6028585484eSchristos 	if (n < 0)
6038585484eSchristos 		return OP_ERR;
6048585484eSchristos 
6058585484eSchristos 	for (i=0; i<n; ++i) {
6068585484eSchristos 		if (bev_ssl->bev.read_suspended)
6078585484eSchristos 			break;
608*eabc0478Schristos 		ERR_clear_error();
6098585484eSchristos 		r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
6108585484eSchristos 		if (r>0) {
6118585484eSchristos 			result |= OP_MADE_PROGRESS;
6128585484eSchristos 			if (bev_ssl->read_blocked_on_write)
6138585484eSchristos 				if (clear_rbow(bev_ssl) < 0)
6148585484eSchristos 					return OP_ERR | result;
6158585484eSchristos 			++n_used;
6168585484eSchristos 			space[i].iov_len = r;
6178585484eSchristos 			decrement_buckets(bev_ssl);
6188585484eSchristos 		} else {
6198585484eSchristos 			int err = SSL_get_error(bev_ssl->ssl, r);
6208585484eSchristos 			print_err(err);
6218585484eSchristos 			switch (err) {
6228585484eSchristos 			case SSL_ERROR_WANT_READ:
6238585484eSchristos 				/* Can't read until underlying has more data. */
6248585484eSchristos 				if (bev_ssl->read_blocked_on_write)
6258585484eSchristos 					if (clear_rbow(bev_ssl) < 0)
6268585484eSchristos 						return OP_ERR | result;
6278585484eSchristos 				break;
6288585484eSchristos 			case SSL_ERROR_WANT_WRITE:
6298585484eSchristos 				/* This read operation requires a write, and the
6308585484eSchristos 				 * underlying is full */
6318585484eSchristos 				if (!bev_ssl->read_blocked_on_write)
6328585484eSchristos 					if (set_rbow(bev_ssl) < 0)
6338585484eSchristos 						return OP_ERR | result;
6348585484eSchristos 				break;
6358585484eSchristos 			default:
6368585484eSchristos 				conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
6378585484eSchristos 				break;
6388585484eSchristos 			}
6398585484eSchristos 			result |= OP_BLOCKED;
6408585484eSchristos 			break; /* out of the loop */
6418585484eSchristos 		}
6428585484eSchristos 	}
6438585484eSchristos 
6448585484eSchristos 	if (n_used) {
6458585484eSchristos 		evbuffer_commit_space(input, space, n_used);
6468585484eSchristos 		if (bev_ssl->underlying)
6478585484eSchristos 			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
6488585484eSchristos 	}
6498585484eSchristos 
6508585484eSchristos 	return result;
6518585484eSchristos }
6528585484eSchristos 
6538585484eSchristos /* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if
6548585484eSchristos    we're now blocked); and OP_ERR (if an error occurred). */
6558585484eSchristos static int
6568585484eSchristos do_write(struct bufferevent_openssl *bev_ssl, int atmost)
6578585484eSchristos {
6588585484eSchristos 	int i, r, n, n_written = 0;
6598585484eSchristos 	struct bufferevent *bev = &bev_ssl->bev.bev;
6608585484eSchristos 	struct evbuffer *output = bev->output;
6618585484eSchristos 	struct evbuffer_iovec space[8];
6628585484eSchristos 	int result = 0;
6638585484eSchristos 
6648585484eSchristos 	if (bev_ssl->last_write > 0)
6658585484eSchristos 		atmost = bev_ssl->last_write;
6668585484eSchristos 	else
6678585484eSchristos 		atmost = bufferevent_get_write_max_(&bev_ssl->bev);
6688585484eSchristos 
6698585484eSchristos 	n = evbuffer_peek(output, atmost, NULL, space, 8);
6708585484eSchristos 	if (n < 0)
6718585484eSchristos 		return OP_ERR | result;
6728585484eSchristos 
6738585484eSchristos 	if (n > 8)
6748585484eSchristos 		n = 8;
6758585484eSchristos 	for (i=0; i < n; ++i) {
6768585484eSchristos 		if (bev_ssl->bev.write_suspended)
6778585484eSchristos 			break;
6788585484eSchristos 
6798585484eSchristos 		/* SSL_write will (reasonably) return 0 if we tell it to
6808585484eSchristos 		   send 0 data.  Skip this case so we don't interpret the
6818585484eSchristos 		   result as an error */
6828585484eSchristos 		if (space[i].iov_len == 0)
6838585484eSchristos 			continue;
6848585484eSchristos 
685*eabc0478Schristos 		ERR_clear_error();
6868585484eSchristos 		r = SSL_write(bev_ssl->ssl, space[i].iov_base,
6878585484eSchristos 		    space[i].iov_len);
6888585484eSchristos 		if (r > 0) {
6898585484eSchristos 			result |= OP_MADE_PROGRESS;
6908585484eSchristos 			if (bev_ssl->write_blocked_on_read)
6918585484eSchristos 				if (clear_wbor(bev_ssl) < 0)
6928585484eSchristos 					return OP_ERR | result;
6938585484eSchristos 			n_written += r;
6948585484eSchristos 			bev_ssl->last_write = -1;
6958585484eSchristos 			decrement_buckets(bev_ssl);
6968585484eSchristos 		} else {
6978585484eSchristos 			int err = SSL_get_error(bev_ssl->ssl, r);
6988585484eSchristos 			print_err(err);
6998585484eSchristos 			switch (err) {
7008585484eSchristos 			case SSL_ERROR_WANT_WRITE:
7018585484eSchristos 				/* Can't read until underlying has more data. */
7028585484eSchristos 				if (bev_ssl->write_blocked_on_read)
7038585484eSchristos 					if (clear_wbor(bev_ssl) < 0)
7048585484eSchristos 						return OP_ERR | result;
7058585484eSchristos 				bev_ssl->last_write = space[i].iov_len;
7068585484eSchristos 				break;
7078585484eSchristos 			case SSL_ERROR_WANT_READ:
7088585484eSchristos 				/* This read operation requires a write, and the
7098585484eSchristos 				 * underlying is full */
7108585484eSchristos 				if (!bev_ssl->write_blocked_on_read)
7118585484eSchristos 					if (set_wbor(bev_ssl) < 0)
7128585484eSchristos 						return OP_ERR | result;
7138585484eSchristos 				bev_ssl->last_write = space[i].iov_len;
7148585484eSchristos 				break;
7158585484eSchristos 			default:
7168585484eSchristos 				conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r);
7178585484eSchristos 				bev_ssl->last_write = -1;
7188585484eSchristos 				break;
7198585484eSchristos 			}
7208585484eSchristos 			result |= OP_BLOCKED;
7218585484eSchristos 			break;
7228585484eSchristos 		}
7238585484eSchristos 	}
7248585484eSchristos 	if (n_written) {
7258585484eSchristos 		evbuffer_drain(output, n_written);
7268585484eSchristos 		if (bev_ssl->underlying)
7278585484eSchristos 			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
7288585484eSchristos 
729*eabc0478Schristos 		bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);
7308585484eSchristos 	}
7318585484eSchristos 	return result;
7328585484eSchristos }
7338585484eSchristos 
7348585484eSchristos #define WRITE_FRAME 15000
7358585484eSchristos 
7368585484eSchristos #define READ_DEFAULT 4096
7378585484eSchristos 
7388585484eSchristos /* Try to figure out how many bytes to read; return 0 if we shouldn't be
7398585484eSchristos  * reading. */
7408585484eSchristos static int
7418585484eSchristos bytes_to_read(struct bufferevent_openssl *bev)
7428585484eSchristos {
7438585484eSchristos 	struct evbuffer *input = bev->bev.bev.input;
7448585484eSchristos 	struct event_watermark *wm = &bev->bev.bev.wm_read;
7458585484eSchristos 	int result = READ_DEFAULT;
7468585484eSchristos 	ev_ssize_t limit;
7478585484eSchristos 	/* XXX 99% of this is generic code that nearly all bufferevents will
7488585484eSchristos 	 * want. */
7498585484eSchristos 
7508585484eSchristos 	if (bev->write_blocked_on_read) {
7518585484eSchristos 		return 0;
7528585484eSchristos 	}
7538585484eSchristos 
7548585484eSchristos 	if (! (bev->bev.bev.enabled & EV_READ)) {
7558585484eSchristos 		return 0;
7568585484eSchristos 	}
7578585484eSchristos 
7588585484eSchristos 	if (bev->bev.read_suspended) {
7598585484eSchristos 		return 0;
7608585484eSchristos 	}
7618585484eSchristos 
7628585484eSchristos 	if (wm->high) {
7638585484eSchristos 		if (evbuffer_get_length(input) >= wm->high) {
7648585484eSchristos 			return 0;
7658585484eSchristos 		}
7668585484eSchristos 
7678585484eSchristos 		result = wm->high - evbuffer_get_length(input);
7688585484eSchristos 	} else {
7698585484eSchristos 		result = READ_DEFAULT;
7708585484eSchristos 	}
7718585484eSchristos 
7728585484eSchristos 	/* Respect the rate limit */
7738585484eSchristos 	limit = bufferevent_get_read_max_(&bev->bev);
7748585484eSchristos 	if (result > limit) {
7758585484eSchristos 		result = limit;
7768585484eSchristos 	}
7778585484eSchristos 
7788585484eSchristos 	return result;
7798585484eSchristos }
7808585484eSchristos 
7818585484eSchristos 
7828585484eSchristos /* Things look readable.  If write is blocked on read, write till it isn't.
7838585484eSchristos  * Read from the underlying buffer until we block or we hit our high-water
7848585484eSchristos  * mark.
7858585484eSchristos  */
7868585484eSchristos static void
7878585484eSchristos consider_reading(struct bufferevent_openssl *bev_ssl)
7888585484eSchristos {
7898585484eSchristos 	int r;
7908585484eSchristos 	int n_to_read;
7918585484eSchristos 	int all_result_flags = 0;
7928585484eSchristos 
7938585484eSchristos 	while (bev_ssl->write_blocked_on_read) {
7948585484eSchristos 		r = do_write(bev_ssl, WRITE_FRAME);
7958585484eSchristos 		if (r & (OP_BLOCKED|OP_ERR))
7968585484eSchristos 			break;
7978585484eSchristos 	}
7988585484eSchristos 	if (bev_ssl->write_blocked_on_read)
7998585484eSchristos 		return;
8008585484eSchristos 
8018585484eSchristos 	n_to_read = bytes_to_read(bev_ssl);
8028585484eSchristos 
8038585484eSchristos 	while (n_to_read) {
8048585484eSchristos 		r = do_read(bev_ssl, n_to_read);
8058585484eSchristos 		all_result_flags |= r;
8068585484eSchristos 
8078585484eSchristos 		if (r & (OP_BLOCKED|OP_ERR))
8088585484eSchristos 			break;
8098585484eSchristos 
8108585484eSchristos 		if (bev_ssl->bev.read_suspended)
8118585484eSchristos 			break;
8128585484eSchristos 
8138585484eSchristos 		/* Read all pending data.  This won't hit the network
8148585484eSchristos 		 * again, and will (most importantly) put us in a state
8158585484eSchristos 		 * where we don't need to read anything else until the
8168585484eSchristos 		 * socket is readable again.  It'll potentially make us
8178585484eSchristos 		 * overrun our read high-watermark (somewhat
8188585484eSchristos 		 * regrettable).  The damage to the rate-limit has
8198585484eSchristos 		 * already been done, since OpenSSL went and read a
8208585484eSchristos 		 * whole SSL record anyway. */
8218585484eSchristos 		n_to_read = SSL_pending(bev_ssl->ssl);
8228585484eSchristos 
8238585484eSchristos 		/* XXX This if statement is actually a bad bug, added to avoid
8248585484eSchristos 		 * XXX a worse bug.
8258585484eSchristos 		 *
8268585484eSchristos 		 * The bad bug: It can potentially cause resource unfairness
8278585484eSchristos 		 * by reading too much data from the underlying bufferevent;
8288585484eSchristos 		 * it can potentially cause read looping if the underlying
8298585484eSchristos 		 * bufferevent is a bufferevent_pair and deferred callbacks
8308585484eSchristos 		 * aren't used.
8318585484eSchristos 		 *
8328585484eSchristos 		 * The worse bug: If we didn't do this, then we would
8338585484eSchristos 		 * potentially not read any more from bev_ssl->underlying
8348585484eSchristos 		 * until more data arrived there, which could lead to us
8358585484eSchristos 		 * waiting forever.
8368585484eSchristos 		 */
8378585484eSchristos 		if (!n_to_read && bev_ssl->underlying)
8388585484eSchristos 			n_to_read = bytes_to_read(bev_ssl);
8398585484eSchristos 	}
8408585484eSchristos 
8418585484eSchristos 	if (all_result_flags & OP_MADE_PROGRESS) {
8428585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
8438585484eSchristos 
844b8ecfcfeSchristos 		bufferevent_trigger_nolock_(bev, EV_READ, 0);
8458585484eSchristos 	}
8468585484eSchristos 
8478585484eSchristos 	if (!bev_ssl->underlying) {
8488585484eSchristos 		/* Should be redundant, but let's avoid busy-looping */
8498585484eSchristos 		if (bev_ssl->bev.read_suspended ||
8508585484eSchristos 		    !(bev_ssl->bev.bev.enabled & EV_READ)) {
8518585484eSchristos 			event_del(&bev_ssl->bev.bev.ev_read);
8528585484eSchristos 		}
8538585484eSchristos 	}
8548585484eSchristos }
8558585484eSchristos 
8568585484eSchristos static void
8578585484eSchristos consider_writing(struct bufferevent_openssl *bev_ssl)
8588585484eSchristos {
8598585484eSchristos 	int r;
8608585484eSchristos 	struct evbuffer *output = bev_ssl->bev.bev.output;
8618585484eSchristos 	struct evbuffer *target = NULL;
8628585484eSchristos 	struct event_watermark *wm = NULL;
8638585484eSchristos 
8648585484eSchristos 	while (bev_ssl->read_blocked_on_write) {
8658585484eSchristos 		r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */
8668585484eSchristos 		if (r & OP_MADE_PROGRESS) {
8678585484eSchristos 			struct bufferevent *bev = &bev_ssl->bev.bev;
8688585484eSchristos 
869b8ecfcfeSchristos 			bufferevent_trigger_nolock_(bev, EV_READ, 0);
8708585484eSchristos 		}
8718585484eSchristos 		if (r & (OP_ERR|OP_BLOCKED))
8728585484eSchristos 			break;
8738585484eSchristos 	}
8748585484eSchristos 	if (bev_ssl->read_blocked_on_write)
8758585484eSchristos 		return;
8768585484eSchristos 	if (bev_ssl->underlying) {
8778585484eSchristos 		target = bev_ssl->underlying->output;
8788585484eSchristos 		wm = &bev_ssl->underlying->wm_write;
8798585484eSchristos 	}
8808585484eSchristos 	while ((bev_ssl->bev.bev.enabled & EV_WRITE) &&
8818585484eSchristos 	    (! bev_ssl->bev.write_suspended) &&
8828585484eSchristos 	    evbuffer_get_length(output) &&
8838585484eSchristos 	    (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) {
8848585484eSchristos 		int n_to_write;
8858585484eSchristos 		if (wm && wm->high)
8868585484eSchristos 			n_to_write = wm->high - evbuffer_get_length(target);
8878585484eSchristos 		else
8888585484eSchristos 			n_to_write = WRITE_FRAME;
8898585484eSchristos 		r = do_write(bev_ssl, n_to_write);
8908585484eSchristos 		if (r & (OP_BLOCKED|OP_ERR))
8918585484eSchristos 			break;
8928585484eSchristos 	}
8938585484eSchristos 
8948585484eSchristos 	if (!bev_ssl->underlying) {
8958585484eSchristos 		if (evbuffer_get_length(output) == 0) {
8968585484eSchristos 			event_del(&bev_ssl->bev.bev.ev_write);
8978585484eSchristos 		} else if (bev_ssl->bev.write_suspended ||
8988585484eSchristos 		    !(bev_ssl->bev.bev.enabled & EV_WRITE)) {
8998585484eSchristos 			/* Should be redundant, but let's avoid busy-looping */
9008585484eSchristos 			event_del(&bev_ssl->bev.bev.ev_write);
9018585484eSchristos 		}
9028585484eSchristos 	}
9038585484eSchristos }
9048585484eSchristos 
9058585484eSchristos static void
9068585484eSchristos be_openssl_readcb(struct bufferevent *bev_base, void *ctx)
9078585484eSchristos {
9088585484eSchristos 	struct bufferevent_openssl *bev_ssl = ctx;
9098585484eSchristos 	consider_reading(bev_ssl);
9108585484eSchristos }
9118585484eSchristos 
9128585484eSchristos static void
9138585484eSchristos be_openssl_writecb(struct bufferevent *bev_base, void *ctx)
9148585484eSchristos {
9158585484eSchristos 	struct bufferevent_openssl *bev_ssl = ctx;
9168585484eSchristos 	consider_writing(bev_ssl);
9178585484eSchristos }
9188585484eSchristos 
9198585484eSchristos static void
9208585484eSchristos be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)
9218585484eSchristos {
9228585484eSchristos 	struct bufferevent_openssl *bev_ssl = ctx;
9238585484eSchristos 	int event = 0;
9248585484eSchristos 
9258585484eSchristos 	if (what & BEV_EVENT_EOF) {
9268585484eSchristos 		if (bev_ssl->allow_dirty_shutdown)
9278585484eSchristos 			event = BEV_EVENT_EOF;
9288585484eSchristos 		else
9298585484eSchristos 			event = BEV_EVENT_ERROR;
9308585484eSchristos 	} else if (what & BEV_EVENT_TIMEOUT) {
9318585484eSchristos 		/* We sure didn't set this.  Propagate it to the user. */
9328585484eSchristos 		event = what;
9338585484eSchristos 	} else if (what & BEV_EVENT_ERROR) {
9348585484eSchristos 		/* An error occurred on the connection.  Propagate it to the user. */
9358585484eSchristos 		event = what;
9368585484eSchristos 	} else if (what & BEV_EVENT_CONNECTED) {
9378585484eSchristos 		/* Ignore it.  We're saying SSL_connect() already, which will
9388585484eSchristos 		   eat it. */
9398585484eSchristos 	}
9408585484eSchristos 	if (event)
941b8ecfcfeSchristos 		bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
9428585484eSchristos }
9438585484eSchristos 
9448585484eSchristos static void
9458585484eSchristos be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr)
9468585484eSchristos {
9478585484eSchristos 	struct bufferevent_openssl *bev_ssl = ptr;
9488585484eSchristos 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
9498585484eSchristos 	if (what == EV_TIMEOUT) {
9508585484eSchristos 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
951b8ecfcfeSchristos 		    BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0);
9528585484eSchristos 	} else {
9538585484eSchristos 		consider_reading(bev_ssl);
9548585484eSchristos 	}
9558585484eSchristos 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
9568585484eSchristos }
9578585484eSchristos 
9588585484eSchristos static void
9598585484eSchristos be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
9608585484eSchristos {
9618585484eSchristos 	struct bufferevent_openssl *bev_ssl = ptr;
9628585484eSchristos 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
9638585484eSchristos 	if (what == EV_TIMEOUT) {
9648585484eSchristos 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
965b8ecfcfeSchristos 		    BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0);
9668585484eSchristos 	} else {
9678585484eSchristos 		consider_writing(bev_ssl);
9688585484eSchristos 	}
9698585484eSchristos 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
9708585484eSchristos }
9718585484eSchristos 
972*eabc0478Schristos static evutil_socket_t
973*eabc0478Schristos be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
974*eabc0478Schristos {
975*eabc0478Schristos 	if (!bev_ssl->underlying) {
976*eabc0478Schristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
977*eabc0478Schristos 		if (event_initialized(&bev->ev_read) && fd < 0) {
978*eabc0478Schristos 			fd = event_get_fd(&bev->ev_read);
979*eabc0478Schristos 		}
980*eabc0478Schristos 	}
981*eabc0478Schristos 	return fd;
982*eabc0478Schristos }
983*eabc0478Schristos 
9848585484eSchristos static int
9858585484eSchristos set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
9868585484eSchristos {
9878585484eSchristos 	if (bev_ssl->underlying) {
9888585484eSchristos 		bufferevent_setcb(bev_ssl->underlying,
9898585484eSchristos 		    be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
9908585484eSchristos 		    bev_ssl);
9918585484eSchristos 		return 0;
9928585484eSchristos 	} else {
9938585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
9948585484eSchristos 		int rpending=0, wpending=0, r1=0, r2=0;
995*eabc0478Schristos 
996*eabc0478Schristos 		if (event_initialized(&bev->ev_read)) {
9978585484eSchristos 			rpending = event_pending(&bev->ev_read, EV_READ, NULL);
9988585484eSchristos 			wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
999*eabc0478Schristos 
10008585484eSchristos 			event_del(&bev->ev_read);
10018585484eSchristos 			event_del(&bev->ev_write);
10028585484eSchristos 		}
1003*eabc0478Schristos 
10048585484eSchristos 		event_assign(&bev->ev_read, bev->ev_base, fd,
1005b8ecfcfeSchristos 		    EV_READ|EV_PERSIST|EV_FINALIZE,
1006b8ecfcfeSchristos 		    be_openssl_readeventcb, bev_ssl);
10078585484eSchristos 		event_assign(&bev->ev_write, bev->ev_base, fd,
1008b8ecfcfeSchristos 		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
1009b8ecfcfeSchristos 		    be_openssl_writeeventcb, bev_ssl);
1010*eabc0478Schristos 
10118585484eSchristos 		if (rpending)
10128585484eSchristos 			r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
10138585484eSchristos 		if (wpending)
10148585484eSchristos 			r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
1015*eabc0478Schristos 
10168585484eSchristos 		return (r1<0 || r2<0) ? -1 : 0;
10178585484eSchristos 	}
10188585484eSchristos }
10198585484eSchristos 
10208585484eSchristos static int
10218585484eSchristos do_handshake(struct bufferevent_openssl *bev_ssl)
10228585484eSchristos {
10238585484eSchristos 	int r;
10248585484eSchristos 
10258585484eSchristos 	switch (bev_ssl->state) {
10268585484eSchristos 	default:
10278585484eSchristos 	case BUFFEREVENT_SSL_OPEN:
10288585484eSchristos 		EVUTIL_ASSERT(0);
10298585484eSchristos 		return -1;
10308585484eSchristos 	case BUFFEREVENT_SSL_CONNECTING:
10318585484eSchristos 	case BUFFEREVENT_SSL_ACCEPTING:
1032*eabc0478Schristos 		ERR_clear_error();
10338585484eSchristos 		r = SSL_do_handshake(bev_ssl->ssl);
10348585484eSchristos 		break;
10358585484eSchristos 	}
10368585484eSchristos 	decrement_buckets(bev_ssl);
10378585484eSchristos 
10388585484eSchristos 	if (r==1) {
1039*eabc0478Schristos 		evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
10408585484eSchristos 		/* We're done! */
10418585484eSchristos 		bev_ssl->state = BUFFEREVENT_SSL_OPEN;
1042*eabc0478Schristos 		set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */
10438585484eSchristos 		/* Call do_read and do_write as needed */
10448585484eSchristos 		bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
10458585484eSchristos 		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
1046b8ecfcfeSchristos 		    BEV_EVENT_CONNECTED, 0);
10478585484eSchristos 		return 1;
10488585484eSchristos 	} else {
10498585484eSchristos 		int err = SSL_get_error(bev_ssl->ssl, r);
10508585484eSchristos 		print_err(err);
10518585484eSchristos 		switch (err) {
10528585484eSchristos 		case SSL_ERROR_WANT_WRITE:
10538585484eSchristos 			stop_reading(bev_ssl);
10548585484eSchristos 			return start_writing(bev_ssl);
10558585484eSchristos 		case SSL_ERROR_WANT_READ:
10568585484eSchristos 			stop_writing(bev_ssl);
10578585484eSchristos 			return start_reading(bev_ssl);
10588585484eSchristos 		default:
10598585484eSchristos 			conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
10608585484eSchristos 			return -1;
10618585484eSchristos 		}
10628585484eSchristos 	}
10638585484eSchristos }
10648585484eSchristos 
10658585484eSchristos static void
10668585484eSchristos be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
10678585484eSchristos {
10688585484eSchristos 	struct bufferevent_openssl *bev_ssl = ctx;
10698585484eSchristos 	do_handshake(bev_ssl);/* XXX handle failure */
10708585484eSchristos }
10718585484eSchristos 
10728585484eSchristos static void
10738585484eSchristos be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
10748585484eSchristos {
10758585484eSchristos 	struct bufferevent_openssl *bev_ssl = ptr;
10768585484eSchristos 
10778585484eSchristos 	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
10788585484eSchristos 	if (what & EV_TIMEOUT) {
1079b8ecfcfeSchristos 		bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0);
10808585484eSchristos 	} else
10818585484eSchristos 		do_handshake(bev_ssl);/* XXX handle failure */
10828585484eSchristos 	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
10838585484eSchristos }
10848585484eSchristos 
10858585484eSchristos static int
10868585484eSchristos set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
10878585484eSchristos {
10888585484eSchristos 	if (bev_ssl->underlying) {
10898585484eSchristos 		bufferevent_setcb(bev_ssl->underlying,
10908585484eSchristos 		    be_openssl_handshakecb, be_openssl_handshakecb,
10918585484eSchristos 		    be_openssl_eventcb,
10928585484eSchristos 		    bev_ssl);
1093*eabc0478Schristos 
1094*eabc0478Schristos 		if (fd < 0)
1095*eabc0478Schristos 			return 0;
1096*eabc0478Schristos 
1097*eabc0478Schristos 		if (bufferevent_setfd(bev_ssl->underlying, fd))
1098*eabc0478Schristos 			return 1;
1099*eabc0478Schristos 
11008585484eSchristos 		return do_handshake(bev_ssl);
11018585484eSchristos 	} else {
11028585484eSchristos 		struct bufferevent *bev = &bev_ssl->bev.bev;
1103*eabc0478Schristos 
1104*eabc0478Schristos 		if (event_initialized(&bev->ev_read)) {
11058585484eSchristos 			event_del(&bev->ev_read);
11068585484eSchristos 			event_del(&bev->ev_write);
11078585484eSchristos 		}
1108*eabc0478Schristos 
11098585484eSchristos 		event_assign(&bev->ev_read, bev->ev_base, fd,
1110b8ecfcfeSchristos 		    EV_READ|EV_PERSIST|EV_FINALIZE,
1111b8ecfcfeSchristos 		    be_openssl_handshakeeventcb, bev_ssl);
11128585484eSchristos 		event_assign(&bev->ev_write, bev->ev_base, fd,
1113b8ecfcfeSchristos 		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
1114b8ecfcfeSchristos 		    be_openssl_handshakeeventcb, bev_ssl);
1115*eabc0478Schristos 		if (fd >= 0)
1116*eabc0478Schristos 			bufferevent_enable(bev, bev->enabled);
1117*eabc0478Schristos 		return 0;
11188585484eSchristos 	}
11198585484eSchristos }
11208585484eSchristos 
11218585484eSchristos int
11228585484eSchristos bufferevent_ssl_renegotiate(struct bufferevent *bev)
11238585484eSchristos {
11248585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11258585484eSchristos 	if (!bev_ssl)
11268585484eSchristos 		return -1;
11278585484eSchristos 	if (SSL_renegotiate(bev_ssl->ssl) < 0)
11288585484eSchristos 		return -1;
11298585484eSchristos 	bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
1130*eabc0478Schristos 	if (set_handshake_callbacks(bev_ssl, be_openssl_auto_fd(bev_ssl, -1)) < 0)
11318585484eSchristos 		return -1;
11328585484eSchristos 	if (!bev_ssl->underlying)
11338585484eSchristos 		return do_handshake(bev_ssl);
11348585484eSchristos 	return 0;
11358585484eSchristos }
11368585484eSchristos 
11378585484eSchristos static void
11388585484eSchristos be_openssl_outbuf_cb(struct evbuffer *buf,
11398585484eSchristos     const struct evbuffer_cb_info *cbinfo, void *arg)
11408585484eSchristos {
11418585484eSchristos 	struct bufferevent_openssl *bev_ssl = arg;
11428585484eSchristos 	int r = 0;
11438585484eSchristos 	/* XXX need to hold a reference here. */
11448585484eSchristos 
11458585484eSchristos 	if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
11468585484eSchristos 		if (cbinfo->orig_size == 0)
11478585484eSchristos 			r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
11488585484eSchristos 			    &bev_ssl->bev.bev.timeout_write);
1149*eabc0478Schristos 
1150*eabc0478Schristos 		if (bev_ssl->underlying)
11518585484eSchristos 			consider_writing(bev_ssl);
11528585484eSchristos 	}
11538585484eSchristos 	/* XXX Handle r < 0 */
11548585484eSchristos 	(void)r;
11558585484eSchristos }
11568585484eSchristos 
11578585484eSchristos 
11588585484eSchristos static int
11598585484eSchristos be_openssl_enable(struct bufferevent *bev, short events)
11608585484eSchristos {
11618585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11628585484eSchristos 	int r1 = 0, r2 = 0;
11638585484eSchristos 
11648585484eSchristos 	if (events & EV_READ)
11658585484eSchristos 		r1 = start_reading(bev_ssl);
11668585484eSchristos 	if (events & EV_WRITE)
11678585484eSchristos 		r2 = start_writing(bev_ssl);
11688585484eSchristos 
11698585484eSchristos 	if (bev_ssl->underlying) {
11708585484eSchristos 		if (events & EV_READ)
11718585484eSchristos 			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
11728585484eSchristos 		if (events & EV_WRITE)
11738585484eSchristos 			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
11748585484eSchristos 
11758585484eSchristos 		if (events & EV_READ)
11768585484eSchristos 			consider_reading(bev_ssl);
11778585484eSchristos 		if (events & EV_WRITE)
11788585484eSchristos 			consider_writing(bev_ssl);
11798585484eSchristos 	}
11808585484eSchristos 	return (r1 < 0 || r2 < 0) ? -1 : 0;
11818585484eSchristos }
11828585484eSchristos 
11838585484eSchristos static int
11848585484eSchristos be_openssl_disable(struct bufferevent *bev, short events)
11858585484eSchristos {
11868585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
11878585484eSchristos 
11888585484eSchristos 	if (events & EV_READ)
11898585484eSchristos 		stop_reading(bev_ssl);
11908585484eSchristos 	if (events & EV_WRITE)
11918585484eSchristos 		stop_writing(bev_ssl);
11928585484eSchristos 
11938585484eSchristos 	if (bev_ssl->underlying) {
11948585484eSchristos 		if (events & EV_READ)
11958585484eSchristos 			BEV_DEL_GENERIC_READ_TIMEOUT(bev);
11968585484eSchristos 		if (events & EV_WRITE)
11978585484eSchristos 			BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
11988585484eSchristos 	}
11998585484eSchristos 	return 0;
12008585484eSchristos }
12018585484eSchristos 
12028585484eSchristos static void
1203b8ecfcfeSchristos be_openssl_unlink(struct bufferevent *bev)
12048585484eSchristos {
12058585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
12068585484eSchristos 
12078585484eSchristos 	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
12088585484eSchristos 		if (bev_ssl->underlying) {
12098585484eSchristos 			if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) {
12108585484eSchristos 				event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "
12118585484eSchristos 				    "bufferevent with too few references");
12128585484eSchristos 			} else {
12138585484eSchristos 				bufferevent_free(bev_ssl->underlying);
1214b8ecfcfeSchristos 				/* We still have a reference to it, via our
1215b8ecfcfeSchristos 				 * BIO. So we don't drop this. */
1216b8ecfcfeSchristos 				// bev_ssl->underlying = NULL;
12178585484eSchristos 			}
12188585484eSchristos 		}
12198585484eSchristos 	} else {
12208585484eSchristos 		if (bev_ssl->underlying) {
12218585484eSchristos 			if (bev_ssl->underlying->errorcb == be_openssl_eventcb)
12228585484eSchristos 				bufferevent_setcb(bev_ssl->underlying,
12238585484eSchristos 				    NULL,NULL,NULL,NULL);
12248585484eSchristos 			bufferevent_unsuspend_read_(bev_ssl->underlying,
12258585484eSchristos 			    BEV_SUSPEND_FILT_READ);
12268585484eSchristos 		}
12278585484eSchristos 	}
12288585484eSchristos }
12298585484eSchristos 
1230b8ecfcfeSchristos static void
1231b8ecfcfeSchristos be_openssl_destruct(struct bufferevent *bev)
1232b8ecfcfeSchristos {
1233b8ecfcfeSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
1234b8ecfcfeSchristos 
1235b8ecfcfeSchristos 	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
1236b8ecfcfeSchristos 		if (! bev_ssl->underlying) {
1237*eabc0478Schristos 			evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
1238b8ecfcfeSchristos 			BIO *bio = SSL_get_wbio(bev_ssl->ssl);
1239b8ecfcfeSchristos 			if (bio)
1240b8ecfcfeSchristos 				fd = BIO_get_fd(bio, NULL);
1241b8ecfcfeSchristos 			if (fd >= 0)
1242b8ecfcfeSchristos 				evutil_closesocket(fd);
1243b8ecfcfeSchristos 		}
1244b8ecfcfeSchristos 		SSL_free(bev_ssl->ssl);
1245b8ecfcfeSchristos 	}
1246b8ecfcfeSchristos }
1247b8ecfcfeSchristos 
12488585484eSchristos static int
12498585484eSchristos be_openssl_adj_timeouts(struct bufferevent *bev)
12508585484eSchristos {
12518585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
12528585484eSchristos 
12538585484eSchristos 	if (bev_ssl->underlying) {
12548585484eSchristos 		return bufferevent_generic_adj_timeouts_(bev);
12558585484eSchristos 	} else {
1256*eabc0478Schristos 		return bufferevent_generic_adj_existing_timeouts_(bev);
12578585484eSchristos 	}
12588585484eSchristos }
12598585484eSchristos 
12608585484eSchristos static int
12618585484eSchristos be_openssl_flush(struct bufferevent *bufev,
12628585484eSchristos     short iotype, enum bufferevent_flush_mode mode)
12638585484eSchristos {
12648585484eSchristos 	/* XXXX Implement this. */
12658585484eSchristos 	return 0;
12668585484eSchristos }
12678585484eSchristos 
12688585484eSchristos static int
1269*eabc0478Schristos be_openssl_set_fd(struct bufferevent_openssl *bev_ssl,
1270*eabc0478Schristos     enum bufferevent_ssl_state state, evutil_socket_t fd)
1271*eabc0478Schristos {
1272*eabc0478Schristos 	bev_ssl->state = state;
1273*eabc0478Schristos 
1274*eabc0478Schristos 	switch (state) {
1275*eabc0478Schristos 	case BUFFEREVENT_SSL_ACCEPTING:
1276*eabc0478Schristos 		if (!SSL_clear(bev_ssl->ssl))
1277*eabc0478Schristos 			return -1;
1278*eabc0478Schristos 		SSL_set_accept_state(bev_ssl->ssl);
1279*eabc0478Schristos 		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1280*eabc0478Schristos 			return -1;
1281*eabc0478Schristos 		break;
1282*eabc0478Schristos 	case BUFFEREVENT_SSL_CONNECTING:
1283*eabc0478Schristos 		if (!SSL_clear(bev_ssl->ssl))
1284*eabc0478Schristos 			return -1;
1285*eabc0478Schristos 		SSL_set_connect_state(bev_ssl->ssl);
1286*eabc0478Schristos 		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1287*eabc0478Schristos 			return -1;
1288*eabc0478Schristos 		break;
1289*eabc0478Schristos 	case BUFFEREVENT_SSL_OPEN:
1290*eabc0478Schristos 		if (set_open_callbacks(bev_ssl, fd) < 0)
1291*eabc0478Schristos 			return -1;
1292*eabc0478Schristos 		break;
1293*eabc0478Schristos 	default:
1294*eabc0478Schristos 		return -1;
1295*eabc0478Schristos 	}
1296*eabc0478Schristos 
1297*eabc0478Schristos 	return 0;
1298*eabc0478Schristos }
1299*eabc0478Schristos 
1300*eabc0478Schristos static int
13018585484eSchristos be_openssl_ctrl(struct bufferevent *bev,
13028585484eSchristos     enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data)
13038585484eSchristos {
13048585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bev);
13058585484eSchristos 	switch (op) {
13068585484eSchristos 	case BEV_CTRL_SET_FD:
1307*eabc0478Schristos 		if (!bev_ssl->underlying) {
13088585484eSchristos 			BIO *bio;
1309*eabc0478Schristos 			bio = BIO_new_socket((int)data->fd, 0);
13108585484eSchristos 			SSL_set_bio(bev_ssl->ssl, bio, bio);
1311*eabc0478Schristos 		} else {
1312*eabc0478Schristos 			BIO *bio;
1313*eabc0478Schristos 			if (!(bio = BIO_new_bufferevent(bev_ssl->underlying)))
1314*eabc0478Schristos 				return -1;
1315*eabc0478Schristos 			SSL_set_bio(bev_ssl->ssl, bio, bio);
13168585484eSchristos 		}
1317*eabc0478Schristos 
1318*eabc0478Schristos 		return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);
13198585484eSchristos 	case BEV_CTRL_GET_FD:
1320*eabc0478Schristos 		if (bev_ssl->underlying) {
1321*eabc0478Schristos 			data->fd = event_get_fd(&bev_ssl->underlying->ev_read);
1322*eabc0478Schristos 		} else {
13238585484eSchristos 			data->fd = event_get_fd(&bev->ev_read);
1324*eabc0478Schristos 		}
13258585484eSchristos 		return 0;
13268585484eSchristos 	case BEV_CTRL_GET_UNDERLYING:
13278585484eSchristos 		data->ptr = bev_ssl->underlying;
13288585484eSchristos 		return 0;
13298585484eSchristos 	case BEV_CTRL_CANCEL_ALL:
13308585484eSchristos 	default:
13318585484eSchristos 		return -1;
13328585484eSchristos 	}
13338585484eSchristos }
13348585484eSchristos 
13358585484eSchristos SSL *
13368585484eSchristos bufferevent_openssl_get_ssl(struct bufferevent *bufev)
13378585484eSchristos {
13388585484eSchristos 	struct bufferevent_openssl *bev_ssl = upcast(bufev);
13398585484eSchristos 	if (!bev_ssl)
13408585484eSchristos 		return NULL;
13418585484eSchristos 	return bev_ssl->ssl;
13428585484eSchristos }
13438585484eSchristos 
13448585484eSchristos static struct bufferevent *
13458585484eSchristos bufferevent_openssl_new_impl(struct event_base *base,
13468585484eSchristos     struct bufferevent *underlying,
13478585484eSchristos     evutil_socket_t fd,
13488585484eSchristos     SSL *ssl,
13498585484eSchristos     enum bufferevent_ssl_state state,
13508585484eSchristos     int options)
13518585484eSchristos {
13528585484eSchristos 	struct bufferevent_openssl *bev_ssl = NULL;
13538585484eSchristos 	struct bufferevent_private *bev_p = NULL;
13548585484eSchristos 	int tmp_options = options & ~BEV_OPT_THREADSAFE;
13558585484eSchristos 
1356*eabc0478Schristos 	/* Only one can be set. */
13578585484eSchristos 	if (underlying != NULL && fd >= 0)
1358*eabc0478Schristos 		goto err;
13598585484eSchristos 
13608585484eSchristos 	if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))
13618585484eSchristos 		goto err;
13628585484eSchristos 
13638585484eSchristos 	bev_p = &bev_ssl->bev;
13648585484eSchristos 
13658585484eSchristos 	if (bufferevent_init_common_(bev_p, base,
13668585484eSchristos 		&bufferevent_ops_openssl, tmp_options) < 0)
13678585484eSchristos 		goto err;
13688585484eSchristos 
13698585484eSchristos 	/* Don't explode if we decide to realloc a chunk we're writing from in
13708585484eSchristos 	 * the output buffer. */
13718585484eSchristos 	SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
13728585484eSchristos 
13738585484eSchristos 	bev_ssl->underlying = underlying;
13748585484eSchristos 	bev_ssl->ssl = ssl;
13758585484eSchristos 
13768585484eSchristos 	bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output,
13778585484eSchristos 	    be_openssl_outbuf_cb, bev_ssl);
13788585484eSchristos 
13798585484eSchristos 	if (options & BEV_OPT_THREADSAFE)
13808585484eSchristos 		bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL);
13818585484eSchristos 
13828585484eSchristos 	if (underlying) {
13838585484eSchristos 		bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev);
13848585484eSchristos 		bufferevent_incref_(underlying);
13858585484eSchristos 	}
13868585484eSchristos 
1387*eabc0478Schristos 	bev_ssl->old_state = state;
13888585484eSchristos 	bev_ssl->last_write = -1;
13898585484eSchristos 
13908585484eSchristos 	init_bio_counts(bev_ssl);
13918585484eSchristos 
1392*eabc0478Schristos 	fd = be_openssl_auto_fd(bev_ssl, fd);
1393*eabc0478Schristos 	if (be_openssl_set_fd(bev_ssl, state, fd))
13948585484eSchristos 		goto err;
13958585484eSchristos 
13968585484eSchristos 	if (underlying) {
13978585484eSchristos 		bufferevent_setwatermark(underlying, EV_READ, 0, 0);
13988585484eSchristos 		bufferevent_enable(underlying, EV_READ|EV_WRITE);
13998585484eSchristos 		if (state == BUFFEREVENT_SSL_OPEN)
14008585484eSchristos 			bufferevent_suspend_read_(underlying,
14018585484eSchristos 			    BEV_SUSPEND_FILT_READ);
14028585484eSchristos 	}
14038585484eSchristos 
14048585484eSchristos 	return &bev_ssl->bev.bev;
14058585484eSchristos err:
1406*eabc0478Schristos 	if (options & BEV_OPT_CLOSE_ON_FREE)
1407*eabc0478Schristos 		SSL_free(ssl);
1408*eabc0478Schristos 	if (bev_ssl) {
1409*eabc0478Schristos 		bev_ssl->ssl = NULL;
14108585484eSchristos 		bufferevent_free(&bev_ssl->bev.bev);
1411*eabc0478Schristos 	}
14128585484eSchristos 	return NULL;
14138585484eSchristos }
14148585484eSchristos 
14158585484eSchristos struct bufferevent *
14168585484eSchristos bufferevent_openssl_filter_new(struct event_base *base,
14178585484eSchristos     struct bufferevent *underlying,
14188585484eSchristos     SSL *ssl,
14198585484eSchristos     enum bufferevent_ssl_state state,
14208585484eSchristos     int options)
14218585484eSchristos {
14228585484eSchristos 	BIO *bio;
1423*eabc0478Schristos 	struct bufferevent *bev;
1424*eabc0478Schristos 
14258585484eSchristos 	if (!underlying)
1426*eabc0478Schristos 		goto err;
1427*eabc0478Schristos 	if (!(bio = BIO_new_bufferevent(underlying)))
1428*eabc0478Schristos 		goto err;
14298585484eSchristos 
14308585484eSchristos 	SSL_set_bio(ssl, bio, bio);
14318585484eSchristos 
1432*eabc0478Schristos 	bev = bufferevent_openssl_new_impl(
14338585484eSchristos 		base, underlying, -1, ssl, state, options);
1434*eabc0478Schristos 	return bev;
1435*eabc0478Schristos 
1436*eabc0478Schristos err:
1437*eabc0478Schristos 	if (options & BEV_OPT_CLOSE_ON_FREE)
1438*eabc0478Schristos 		SSL_free(ssl);
1439*eabc0478Schristos 	return NULL;
14408585484eSchristos }
14418585484eSchristos 
14428585484eSchristos struct bufferevent *
14438585484eSchristos bufferevent_openssl_socket_new(struct event_base *base,
14448585484eSchristos     evutil_socket_t fd,
14458585484eSchristos     SSL *ssl,
14468585484eSchristos     enum bufferevent_ssl_state state,
14478585484eSchristos     int options)
14488585484eSchristos {
14498585484eSchristos 	/* Does the SSL already have an fd? */
14508585484eSchristos 	BIO *bio = SSL_get_wbio(ssl);
14518585484eSchristos 	long have_fd = -1;
14528585484eSchristos 
14538585484eSchristos 	if (bio)
14548585484eSchristos 		have_fd = BIO_get_fd(bio, NULL);
14558585484eSchristos 
14568585484eSchristos 	if (have_fd >= 0) {
14578585484eSchristos 		/* The SSL is already configured with an fd. */
14588585484eSchristos 		if (fd < 0) {
14598585484eSchristos 			/* We should learn the fd from the SSL. */
14608585484eSchristos 			fd = (evutil_socket_t) have_fd;
14618585484eSchristos 		} else if (have_fd == (long)fd) {
14628585484eSchristos 			/* We already know the fd from the SSL; do nothing */
14638585484eSchristos 		} else {
14648585484eSchristos 			/* We specified an fd different from that of the SSL.
14658585484eSchristos 			   This is probably an error on our part.  Fail. */
1466*eabc0478Schristos 			goto err;
14678585484eSchristos 		}
1468*eabc0478Schristos 		BIO_set_close(bio, 0);
14698585484eSchristos 	} else {
14708585484eSchristos 		/* The SSL isn't configured with a BIO with an fd. */
14718585484eSchristos 		if (fd >= 0) {
14728585484eSchristos 			/* ... and we have an fd we want to use. */
1473*eabc0478Schristos 			bio = BIO_new_socket((int)fd, 0);
14748585484eSchristos 			SSL_set_bio(ssl, bio, bio);
14758585484eSchristos 		} else {
14768585484eSchristos 			/* Leave the fd unset. */
14778585484eSchristos 		}
14788585484eSchristos 	}
14798585484eSchristos 
14808585484eSchristos 	return bufferevent_openssl_new_impl(
14818585484eSchristos 		base, NULL, fd, ssl, state, options);
1482*eabc0478Schristos 
1483*eabc0478Schristos err:
1484*eabc0478Schristos 	if (options & BEV_OPT_CLOSE_ON_FREE)
1485*eabc0478Schristos 		SSL_free(ssl);
1486*eabc0478Schristos 	return NULL;
14878585484eSchristos }
14888585484eSchristos 
14898585484eSchristos int
14908585484eSchristos bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev)
14918585484eSchristos {
14928585484eSchristos 	int allow_dirty_shutdown = -1;
14938585484eSchristos 	struct bufferevent_openssl *bev_ssl;
14948585484eSchristos 	BEV_LOCK(bev);
14958585484eSchristos 	bev_ssl = upcast(bev);
14968585484eSchristos 	if (bev_ssl)
14978585484eSchristos 		allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown;
14988585484eSchristos 	BEV_UNLOCK(bev);
14998585484eSchristos 	return allow_dirty_shutdown;
15008585484eSchristos }
15018585484eSchristos 
15028585484eSchristos void
15038585484eSchristos bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
15048585484eSchristos     int allow_dirty_shutdown)
15058585484eSchristos {
15068585484eSchristos 	struct bufferevent_openssl *bev_ssl;
15078585484eSchristos 	BEV_LOCK(bev);
15088585484eSchristos 	bev_ssl = upcast(bev);
15098585484eSchristos 	if (bev_ssl)
15108585484eSchristos 		bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown;
15118585484eSchristos 	BEV_UNLOCK(bev);
15128585484eSchristos }
15138585484eSchristos 
15148585484eSchristos unsigned long
15158585484eSchristos bufferevent_get_openssl_error(struct bufferevent *bev)
15168585484eSchristos {
15178585484eSchristos 	unsigned long err = 0;
15188585484eSchristos 	struct bufferevent_openssl *bev_ssl;
15198585484eSchristos 	BEV_LOCK(bev);
15208585484eSchristos 	bev_ssl = upcast(bev);
15218585484eSchristos 	if (bev_ssl && bev_ssl->n_errors) {
15228585484eSchristos 		err = bev_ssl->errors[--bev_ssl->n_errors];
15238585484eSchristos 	}
15248585484eSchristos 	BEV_UNLOCK(bev);
15258585484eSchristos 	return err;
15268585484eSchristos }
1527