1275970Scy/*
2275970Scy * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
3275970Scy *
4275970Scy * Redistribution and use in source and binary forms, with or without
5275970Scy * modification, are permitted provided that the following conditions
6275970Scy * are met:
7275970Scy * 1. Redistributions of source code must retain the above copyright
8275970Scy *    notice, this list of conditions and the following disclaimer.
9275970Scy * 2. Redistributions in binary form must reproduce the above copyright
10275970Scy *    notice, this list of conditions and the following disclaimer in the
11275970Scy *    documentation and/or other materials provided with the distribution.
12275970Scy * 3. The name of the author may not be used to endorse or promote products
13275970Scy *    derived from this software without specific prior written permission.
14275970Scy *
15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25275970Scy */
26275970Scy
27275970Scy// Get rid of OSX 10.7 and greater deprecation warnings.
28275970Scy#if defined(__APPLE__) && defined(__clang__)
29275970Scy#pragma clang diagnostic ignored "-Wdeprecated-declarations"
30275970Scy#endif
31275970Scy
32275970Scy#include "event2/event-config.h"
33275970Scy#include "evconfig-private.h"
34275970Scy
35275970Scy#include <sys/types.h>
36275970Scy
37275970Scy#ifdef EVENT__HAVE_SYS_TIME_H
38275970Scy#include <sys/time.h>
39275970Scy#endif
40275970Scy
41275970Scy#include <errno.h>
42275970Scy#include <stdio.h>
43275970Scy#include <stdlib.h>
44275970Scy#include <string.h>
45275970Scy#ifdef EVENT__HAVE_STDARG_H
46275970Scy#include <stdarg.h>
47275970Scy#endif
48275970Scy#ifdef EVENT__HAVE_UNISTD_H
49275970Scy#include <unistd.h>
50275970Scy#endif
51275970Scy
52275970Scy#ifdef _WIN32
53275970Scy#include <winsock2.h>
54275970Scy#endif
55275970Scy
56275970Scy#include "event2/bufferevent.h"
57275970Scy#include "event2/bufferevent_struct.h"
58275970Scy#include "event2/bufferevent_ssl.h"
59275970Scy#include "event2/buffer.h"
60275970Scy#include "event2/event.h"
61275970Scy
62275970Scy#include "mm-internal.h"
63275970Scy#include "bufferevent-internal.h"
64275970Scy#include "log-internal.h"
65275970Scy
66275970Scy#include <openssl/bio.h>
67275970Scy#include <openssl/ssl.h>
68275970Scy#include <openssl/err.h>
69275970Scy
70275970Scy/*
71275970Scy * Define an OpenSSL bio that targets a bufferevent.
72275970Scy */
73275970Scy
74275970Scy/* --------------------
75275970Scy   A BIO is an OpenSSL abstraction that handles reading and writing data.  The
76275970Scy   library will happily speak SSL over anything that implements a BIO
77275970Scy   interface.
78275970Scy
79275970Scy   Here we define a BIO implementation that directs its output to a
80275970Scy   bufferevent.  We'll want to use this only when none of OpenSSL's built-in
81275970Scy   IO mechanisms work for us.
82275970Scy   -------------------- */
83275970Scy
84275970Scy/* every BIO type needs its own integer type value. */
85275970Scy#define BIO_TYPE_LIBEVENT 57
86275970Scy/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on
87275970Scy * this. */
88275970Scy
89275970Scy#if 0
90275970Scystatic void
91275970Scyprint_err(int val)
92275970Scy{
93275970Scy	int err;
94275970Scy	printf("Error was %d\n", val);
95275970Scy
96275970Scy	while ((err = ERR_get_error())) {
97275970Scy		const char *msg = (const char*)ERR_reason_error_string(err);
98275970Scy		const char *lib = (const char*)ERR_lib_error_string(err);
99275970Scy		const char *func = (const char*)ERR_func_error_string(err);
100275970Scy
101275970Scy		printf("%s in %s %s\n", msg, lib, func);
102275970Scy	}
103275970Scy}
104275970Scy#else
105275970Scy#define print_err(v) ((void)0)
106275970Scy#endif
107275970Scy
108275970Scy/* Called to initialize a new BIO */
109275970Scystatic int
110275970Scybio_bufferevent_new(BIO *b)
111275970Scy{
112275970Scy	b->init = 0;
113275970Scy	b->num = -1;
114275970Scy	b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/
115275970Scy	b->flags = 0;
116275970Scy	return 1;
117275970Scy}
118275970Scy
119275970Scy/* Called to uninitialize the BIO. */
120275970Scystatic int
121275970Scybio_bufferevent_free(BIO *b)
122275970Scy{
123275970Scy	if (!b)
124275970Scy		return 0;
125275970Scy	if (b->shutdown) {
126275970Scy		if (b->init && b->ptr)
127275970Scy			bufferevent_free(b->ptr);
128275970Scy		b->init = 0;
129275970Scy		b->flags = 0;
130275970Scy		b->ptr = NULL;
131275970Scy	}
132275970Scy	return 1;
133275970Scy}
134275970Scy
135275970Scy/* Called to extract data from the BIO. */
136275970Scystatic int
137275970Scybio_bufferevent_read(BIO *b, char *out, int outlen)
138275970Scy{
139275970Scy	int r = 0;
140275970Scy	struct evbuffer *input;
141275970Scy
142275970Scy	BIO_clear_retry_flags(b);
143275970Scy
144275970Scy	if (!out)
145275970Scy		return 0;
146275970Scy	if (!b->ptr)
147275970Scy		return -1;
148275970Scy
149275970Scy	input = bufferevent_get_input(b->ptr);
150275970Scy	if (evbuffer_get_length(input) == 0) {
151275970Scy		/* If there's no data to read, say so. */
152275970Scy		BIO_set_retry_read(b);
153275970Scy		return -1;
154275970Scy	} else {
155275970Scy		r = evbuffer_remove(input, out, outlen);
156275970Scy	}
157275970Scy
158275970Scy	return r;
159275970Scy}
160275970Scy
161275970Scy/* Called to write data info the BIO */
162275970Scystatic int
163275970Scybio_bufferevent_write(BIO *b, const char *in, int inlen)
164275970Scy{
165275970Scy	struct bufferevent *bufev = b->ptr;
166275970Scy	struct evbuffer *output;
167275970Scy	size_t outlen;
168275970Scy
169275970Scy	BIO_clear_retry_flags(b);
170275970Scy
171275970Scy	if (!b->ptr)
172275970Scy		return -1;
173275970Scy
174275970Scy	output = bufferevent_get_output(bufev);
175275970Scy	outlen = evbuffer_get_length(output);
176275970Scy
177275970Scy	/* Copy only as much data onto the output buffer as can fit under the
178275970Scy	 * high-water mark. */
179275970Scy	if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {
180275970Scy		if (bufev->wm_write.high <= outlen) {
181275970Scy			/* If no data can fit, we'll need to retry later. */
182275970Scy			BIO_set_retry_write(b);
183275970Scy			return -1;
184275970Scy		}
185275970Scy		inlen = bufev->wm_write.high - outlen;
186275970Scy	}
187275970Scy
188275970Scy	EVUTIL_ASSERT(inlen > 0);
189275970Scy	evbuffer_add(output, in, inlen);
190275970Scy	return inlen;
191275970Scy}
192275970Scy
193275970Scy/* Called to handle various requests */
194275970Scystatic long
195275970Scybio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)
196275970Scy{
197275970Scy	struct bufferevent *bufev = b->ptr;
198275970Scy	long ret = 1;
199275970Scy
200275970Scy	switch (cmd) {
201275970Scy	case BIO_CTRL_GET_CLOSE:
202275970Scy		ret = b->shutdown;
203275970Scy		break;
204275970Scy	case BIO_CTRL_SET_CLOSE:
205275970Scy		b->shutdown = (int)num;
206275970Scy		break;
207275970Scy	case BIO_CTRL_PENDING:
208275970Scy		ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;
209275970Scy		break;
210275970Scy	case BIO_CTRL_WPENDING:
211275970Scy		ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0;
212275970Scy		break;
213275970Scy	/* XXXX These two are given a special-case treatment because
214275970Scy	 * of cargo-cultism.  I should come up with a better reason. */
215275970Scy	case BIO_CTRL_DUP:
216275970Scy	case BIO_CTRL_FLUSH:
217275970Scy		ret = 1;
218275970Scy		break;
219275970Scy	default:
220275970Scy		ret = 0;
221275970Scy		break;
222275970Scy	}
223275970Scy	return ret;
224275970Scy}
225275970Scy
226275970Scy/* Called to write a string to the BIO */
227275970Scystatic int
228275970Scybio_bufferevent_puts(BIO *b, const char *s)
229275970Scy{
230275970Scy	return bio_bufferevent_write(b, s, strlen(s));
231275970Scy}
232275970Scy
233275970Scy/* Method table for the bufferevent BIO */
234275970Scystatic BIO_METHOD methods_bufferevent = {
235275970Scy	BIO_TYPE_LIBEVENT, "bufferevent",
236275970Scy	bio_bufferevent_write,
237275970Scy	bio_bufferevent_read,
238275970Scy	bio_bufferevent_puts,
239275970Scy	NULL /* bio_bufferevent_gets */,
240275970Scy	bio_bufferevent_ctrl,
241275970Scy	bio_bufferevent_new,
242275970Scy	bio_bufferevent_free,
243275970Scy	NULL /* callback_ctrl */,
244275970Scy};
245275970Scy
246275970Scy/* Return the method table for the bufferevents BIO */
247275970Scystatic BIO_METHOD *
248275970ScyBIO_s_bufferevent(void)
249275970Scy{
250275970Scy	return &methods_bufferevent;
251275970Scy}
252275970Scy
253275970Scy/* Create a new BIO to wrap communication around a bufferevent.  If close_flag
254275970Scy * is true, the bufferevent will be freed when the BIO is closed. */
255275970Scystatic BIO *
256275970ScyBIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag)
257275970Scy{
258275970Scy	BIO *result;
259275970Scy	if (!bufferevent)
260275970Scy		return NULL;
261275970Scy	if (!(result = BIO_new(BIO_s_bufferevent())))
262275970Scy		return NULL;
263275970Scy	result->init = 1;
264275970Scy	result->ptr = bufferevent;
265275970Scy	result->shutdown = close_flag ? 1 : 0;
266275970Scy	return result;
267275970Scy}
268275970Scy
269275970Scy/* --------------------
270275970Scy   Now, here's the OpenSSL-based implementation of bufferevent.
271275970Scy
272275970Scy   The implementation comes in two flavors: one that connects its SSL object
273275970Scy   to an underlying bufferevent using a BIO_bufferevent, and one that has the
274275970Scy   SSL object connect to a socket directly.  The latter should generally be
275275970Scy   faster, except on Windows, where your best bet is using a
276275970Scy   bufferevent_async.
277275970Scy
278275970Scy   (OpenSSL supports many other BIO types, too.  But we can't use any unless
279275970Scy   we have a good way to get notified when they become readable/writable.)
280275970Scy   -------------------- */
281275970Scy
282275970Scystruct bio_data_counts {
283275970Scy	unsigned long n_written;
284275970Scy	unsigned long n_read;
285275970Scy};
286275970Scy
287275970Scystruct bufferevent_openssl {
288275970Scy	/* Shared fields with common bufferevent implementation code.
289275970Scy	   If we were set up with an underlying bufferevent, we use the
290275970Scy	   events here as timers only.  If we have an SSL, then we use
291275970Scy	   the events as socket events.
292275970Scy	 */
293275970Scy	struct bufferevent_private bev;
294275970Scy	/* An underlying bufferevent that we're directing our output to.
295275970Scy	   If it's NULL, then we're connected to an fd, not an evbuffer. */
296275970Scy	struct bufferevent *underlying;
297275970Scy	/* The SSL object doing our encryption. */
298275970Scy	SSL *ssl;
299275970Scy
300275970Scy	/* A callback that's invoked when data arrives on our outbuf so we
301275970Scy	   know to write data to the SSL. */
302275970Scy	struct evbuffer_cb_entry *outbuf_cb;
303275970Scy
304275970Scy	/* A count of how much data the bios have read/written total.  Used
305275970Scy	   for rate-limiting. */
306275970Scy	struct bio_data_counts counts;
307275970Scy
308275970Scy	/* If this value is greater than 0, then the last SSL_write blocked,
309275970Scy	 * and we need to try it again with this many bytes. */
310275970Scy	ev_ssize_t last_write;
311275970Scy
312275970Scy#define NUM_ERRORS 3
313275970Scy	ev_uint32_t errors[NUM_ERRORS];
314275970Scy
315275970Scy	/* When we next get available space, we should say "read" instead of
316275970Scy	   "write". This can happen if there's a renegotiation during a read
317275970Scy	   operation. */
318275970Scy	unsigned read_blocked_on_write : 1;
319275970Scy	/* When we next get data, we should say "write" instead of "read". */
320275970Scy	unsigned write_blocked_on_read : 1;
321275970Scy	/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
322275970Scy	unsigned allow_dirty_shutdown : 1;
323275970Scy	/* XXXX */
324275970Scy	unsigned fd_is_set : 1;
325275970Scy	/* XXX */
326275970Scy	unsigned n_errors : 2;
327275970Scy
328275970Scy	/* Are we currently connecting, accepting, or doing IO? */
329275970Scy	unsigned state : 2;
330275970Scy};
331275970Scy
332275970Scystatic int be_openssl_enable(struct bufferevent *, short);
333275970Scystatic int be_openssl_disable(struct bufferevent *, short);
334275970Scystatic void be_openssl_unlink(struct bufferevent *);
335275970Scystatic void be_openssl_destruct(struct bufferevent *);
336275970Scystatic int be_openssl_adj_timeouts(struct bufferevent *);
337275970Scystatic int be_openssl_flush(struct bufferevent *bufev,
338275970Scy    short iotype, enum bufferevent_flush_mode mode);
339275970Scystatic int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
340275970Scy
341275970Scyconst struct bufferevent_ops bufferevent_ops_openssl = {
342275970Scy	"ssl",
343275970Scy	evutil_offsetof(struct bufferevent_openssl, bev.bev),
344275970Scy	be_openssl_enable,
345275970Scy	be_openssl_disable,
346275970Scy	be_openssl_unlink,
347275970Scy	be_openssl_destruct,
348275970Scy	be_openssl_adj_timeouts,
349275970Scy	be_openssl_flush,
350275970Scy	be_openssl_ctrl,
351275970Scy};
352275970Scy
353275970Scy/* Given a bufferevent, return a pointer to the bufferevent_openssl that
354275970Scy * contains it, if any. */
355275970Scystatic inline struct bufferevent_openssl *
356275970Scyupcast(struct bufferevent *bev)
357275970Scy{
358275970Scy	struct bufferevent_openssl *bev_o;
359275970Scy	if (bev->be_ops != &bufferevent_ops_openssl)
360275970Scy		return NULL;
361275970Scy	bev_o = (void*)( ((char*)bev) -
362275970Scy			 evutil_offsetof(struct bufferevent_openssl, bev.bev));
363275970Scy	EVUTIL_ASSERT(bev_o->bev.bev.be_ops == &bufferevent_ops_openssl);
364275970Scy	return bev_o;
365275970Scy}
366275970Scy
367275970Scystatic inline void
368275970Scyput_error(struct bufferevent_openssl *bev_ssl, unsigned long err)
369275970Scy{
370275970Scy	if (bev_ssl->n_errors == NUM_ERRORS)
371275970Scy		return;
372275970Scy	/* The error type according to openssl is "unsigned long", but
373275970Scy	   openssl never uses more than 32 bits of it.  It _can't_ use more
374275970Scy	   than 32 bits of it, since it needs to report errors on systems
375275970Scy	   where long is only 32 bits.
376275970Scy	 */
377275970Scy	bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err;
378275970Scy}
379275970Scy
380275970Scy/* Have the base communications channel (either the underlying bufferevent or
381275970Scy * ev_read and ev_write) start reading.  Take the read-blocked-on-write flag
382275970Scy * into account. */
383275970Scystatic int
384275970Scystart_reading(struct bufferevent_openssl *bev_ssl)
385275970Scy{
386275970Scy	if (bev_ssl->underlying) {
387275970Scy		bufferevent_unsuspend_read_(bev_ssl->underlying,
388275970Scy		    BEV_SUSPEND_FILT_READ);
389275970Scy		return 0;
390275970Scy	} else {
391275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
392275970Scy		int r;
393275970Scy		r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
394275970Scy		if (r == 0 && bev_ssl->read_blocked_on_write)
395275970Scy			r = bufferevent_add_event_(&bev->ev_write,
396275970Scy			    &bev->timeout_write);
397275970Scy		return r;
398275970Scy	}
399275970Scy}
400275970Scy
401275970Scy/* Have the base communications channel (either the underlying bufferevent or
402275970Scy * ev_read and ev_write) start writing.  Take the write-blocked-on-read flag
403275970Scy * into account. */
404275970Scystatic int
405275970Scystart_writing(struct bufferevent_openssl *bev_ssl)
406275970Scy{
407275970Scy	int r = 0;
408275970Scy	if (bev_ssl->underlying) {
409275970Scy		;
410275970Scy	} else {
411275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
412275970Scy		r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
413275970Scy		if (!r && bev_ssl->write_blocked_on_read)
414275970Scy			r = bufferevent_add_event_(&bev->ev_read,
415275970Scy			    &bev->timeout_read);
416275970Scy	}
417275970Scy	return r;
418275970Scy}
419275970Scy
420275970Scystatic void
421275970Scystop_reading(struct bufferevent_openssl *bev_ssl)
422275970Scy{
423275970Scy	if (bev_ssl->write_blocked_on_read)
424275970Scy		return;
425275970Scy	if (bev_ssl->underlying) {
426275970Scy		bufferevent_suspend_read_(bev_ssl->underlying,
427275970Scy		    BEV_SUSPEND_FILT_READ);
428275970Scy	} else {
429275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
430275970Scy		event_del(&bev->ev_read);
431275970Scy	}
432275970Scy}
433275970Scy
434275970Scystatic void
435275970Scystop_writing(struct bufferevent_openssl *bev_ssl)
436275970Scy{
437275970Scy	if (bev_ssl->read_blocked_on_write)
438275970Scy		return;
439275970Scy	if (bev_ssl->underlying) {
440275970Scy		;
441275970Scy	} else {
442275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
443275970Scy		event_del(&bev->ev_write);
444275970Scy	}
445275970Scy}
446275970Scy
447275970Scystatic int
448275970Scyset_rbow(struct bufferevent_openssl *bev_ssl)
449275970Scy{
450275970Scy	if (!bev_ssl->underlying)
451275970Scy		stop_reading(bev_ssl);
452275970Scy	bev_ssl->read_blocked_on_write = 1;
453275970Scy	return start_writing(bev_ssl);
454275970Scy}
455275970Scy
456275970Scystatic int
457275970Scyset_wbor(struct bufferevent_openssl *bev_ssl)
458275970Scy{
459275970Scy	if (!bev_ssl->underlying)
460275970Scy		stop_writing(bev_ssl);
461275970Scy	bev_ssl->write_blocked_on_read = 1;
462275970Scy	return start_reading(bev_ssl);
463275970Scy}
464275970Scy
465275970Scystatic int
466275970Scyclear_rbow(struct bufferevent_openssl *bev_ssl)
467275970Scy{
468275970Scy	struct bufferevent *bev = &bev_ssl->bev.bev;
469275970Scy	int r = 0;
470275970Scy	bev_ssl->read_blocked_on_write = 0;
471275970Scy	if (!(bev->enabled & EV_WRITE))
472275970Scy		stop_writing(bev_ssl);
473275970Scy	if (bev->enabled & EV_READ)
474275970Scy		r = start_reading(bev_ssl);
475275970Scy	return r;
476275970Scy}
477275970Scy
478275970Scy
479275970Scystatic int
480275970Scyclear_wbor(struct bufferevent_openssl *bev_ssl)
481275970Scy{
482275970Scy	struct bufferevent *bev = &bev_ssl->bev.bev;
483275970Scy	int r = 0;
484275970Scy	bev_ssl->write_blocked_on_read = 0;
485275970Scy	if (!(bev->enabled & EV_READ))
486275970Scy		stop_reading(bev_ssl);
487275970Scy	if (bev->enabled & EV_WRITE)
488275970Scy		r = start_writing(bev_ssl);
489275970Scy	return r;
490275970Scy}
491275970Scy
492275970Scystatic void
493275970Scyconn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret)
494275970Scy{
495275970Scy	int event = BEV_EVENT_ERROR;
496275970Scy	int dirty_shutdown = 0;
497275970Scy	unsigned long err;
498275970Scy
499275970Scy	switch (errcode) {
500275970Scy	case SSL_ERROR_ZERO_RETURN:
501275970Scy		/* Possibly a clean shutdown. */
502275970Scy		if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)
503275970Scy			event = BEV_EVENT_EOF;
504275970Scy		else
505275970Scy			dirty_shutdown = 1;
506275970Scy		break;
507275970Scy	case SSL_ERROR_SYSCALL:
508275970Scy		/* IO error; possibly a dirty shutdown. */
509275970Scy		if (ret == 0 && ERR_peek_error() == 0)
510275970Scy			dirty_shutdown = 1;
511275970Scy		break;
512275970Scy	case SSL_ERROR_SSL:
513275970Scy		/* Protocol error. */
514275970Scy		break;
515275970Scy	case SSL_ERROR_WANT_X509_LOOKUP:
516275970Scy		/* XXXX handle this. */
517275970Scy		break;
518275970Scy	case SSL_ERROR_NONE:
519275970Scy	case SSL_ERROR_WANT_READ:
520275970Scy	case SSL_ERROR_WANT_WRITE:
521275970Scy	case SSL_ERROR_WANT_CONNECT:
522275970Scy	case SSL_ERROR_WANT_ACCEPT:
523275970Scy	default:
524275970Scy		/* should be impossible; treat as normal error. */
525275970Scy		event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);
526275970Scy		break;
527275970Scy	}
528275970Scy
529275970Scy	while ((err = ERR_get_error())) {
530275970Scy		put_error(bev_ssl, err);
531275970Scy	}
532275970Scy
533275970Scy	if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)
534275970Scy		event = BEV_EVENT_EOF;
535275970Scy
536275970Scy	stop_reading(bev_ssl);
537275970Scy	stop_writing(bev_ssl);
538275970Scy
539275970Scy	/* when is BEV_EVENT_{READING|WRITING} */
540275970Scy	event = when | event;
541275970Scy	bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
542275970Scy}
543275970Scy
544275970Scystatic void
545275970Scyinit_bio_counts(struct bufferevent_openssl *bev_ssl)
546275970Scy{
547275970Scy	bev_ssl->counts.n_written =
548275970Scy	    BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
549275970Scy	bev_ssl->counts.n_read =
550275970Scy	    BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
551275970Scy}
552275970Scy
553275970Scystatic inline void
554275970Scydecrement_buckets(struct bufferevent_openssl *bev_ssl)
555275970Scy{
556275970Scy	unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
557275970Scy	unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
558275970Scy	/* These next two subtractions can wrap around. That's okay. */
559275970Scy	unsigned long w = num_w - bev_ssl->counts.n_written;
560275970Scy	unsigned long r = num_r - bev_ssl->counts.n_read;
561275970Scy	if (w)
562275970Scy		bufferevent_decrement_write_buckets_(&bev_ssl->bev, w);
563275970Scy	if (r)
564275970Scy		bufferevent_decrement_read_buckets_(&bev_ssl->bev, r);
565275970Scy	bev_ssl->counts.n_written = num_w;
566275970Scy	bev_ssl->counts.n_read = num_r;
567275970Scy}
568275970Scy
569275970Scy#define OP_MADE_PROGRESS 1
570275970Scy#define OP_BLOCKED 2
571275970Scy#define OP_ERR 4
572275970Scy
573275970Scy/* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if
574275970Scy   we're now blocked); and OP_ERR (if an error occurred). */
575275970Scystatic int
576275970Scydo_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {
577275970Scy	/* Requires lock */
578275970Scy	struct bufferevent *bev = &bev_ssl->bev.bev;
579275970Scy	struct evbuffer *input = bev->input;
580275970Scy	int r, n, i, n_used = 0, atmost;
581275970Scy	struct evbuffer_iovec space[2];
582275970Scy	int result = 0;
583275970Scy
584275970Scy	if (bev_ssl->bev.read_suspended)
585275970Scy		return 0;
586275970Scy
587275970Scy	atmost = bufferevent_get_read_max_(&bev_ssl->bev);
588275970Scy	if (n_to_read > atmost)
589275970Scy		n_to_read = atmost;
590275970Scy
591275970Scy	n = evbuffer_reserve_space(input, n_to_read, space, 2);
592275970Scy	if (n < 0)
593275970Scy		return OP_ERR;
594275970Scy
595275970Scy	for (i=0; i<n; ++i) {
596275970Scy		if (bev_ssl->bev.read_suspended)
597275970Scy			break;
598275970Scy		r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
599275970Scy		if (r>0) {
600275970Scy			result |= OP_MADE_PROGRESS;
601275970Scy			if (bev_ssl->read_blocked_on_write)
602275970Scy				if (clear_rbow(bev_ssl) < 0)
603275970Scy					return OP_ERR | result;
604275970Scy			++n_used;
605275970Scy			space[i].iov_len = r;
606275970Scy			decrement_buckets(bev_ssl);
607275970Scy		} else {
608275970Scy			int err = SSL_get_error(bev_ssl->ssl, r);
609275970Scy			print_err(err);
610275970Scy			switch (err) {
611275970Scy			case SSL_ERROR_WANT_READ:
612275970Scy				/* Can't read until underlying has more data. */
613275970Scy				if (bev_ssl->read_blocked_on_write)
614275970Scy					if (clear_rbow(bev_ssl) < 0)
615275970Scy						return OP_ERR | result;
616275970Scy				break;
617275970Scy			case SSL_ERROR_WANT_WRITE:
618275970Scy				/* This read operation requires a write, and the
619275970Scy				 * underlying is full */
620275970Scy				if (!bev_ssl->read_blocked_on_write)
621275970Scy					if (set_rbow(bev_ssl) < 0)
622275970Scy						return OP_ERR | result;
623275970Scy				break;
624275970Scy			default:
625275970Scy				conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
626275970Scy				break;
627275970Scy			}
628275970Scy			result |= OP_BLOCKED;
629275970Scy			break; /* out of the loop */
630275970Scy		}
631275970Scy	}
632275970Scy
633275970Scy	if (n_used) {
634275970Scy		evbuffer_commit_space(input, space, n_used);
635275970Scy		if (bev_ssl->underlying)
636275970Scy			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
637275970Scy	}
638275970Scy
639275970Scy	return result;
640275970Scy}
641275970Scy
642275970Scy/* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if
643275970Scy   we're now blocked); and OP_ERR (if an error occurred). */
644275970Scystatic int
645275970Scydo_write(struct bufferevent_openssl *bev_ssl, int atmost)
646275970Scy{
647275970Scy	int i, r, n, n_written = 0;
648275970Scy	struct bufferevent *bev = &bev_ssl->bev.bev;
649275970Scy	struct evbuffer *output = bev->output;
650275970Scy	struct evbuffer_iovec space[8];
651275970Scy	int result = 0;
652275970Scy
653275970Scy	if (bev_ssl->last_write > 0)
654275970Scy		atmost = bev_ssl->last_write;
655275970Scy	else
656275970Scy		atmost = bufferevent_get_write_max_(&bev_ssl->bev);
657275970Scy
658275970Scy	n = evbuffer_peek(output, atmost, NULL, space, 8);
659275970Scy	if (n < 0)
660275970Scy		return OP_ERR | result;
661275970Scy
662275970Scy	if (n > 8)
663275970Scy		n = 8;
664275970Scy	for (i=0; i < n; ++i) {
665275970Scy		if (bev_ssl->bev.write_suspended)
666275970Scy			break;
667275970Scy
668275970Scy		/* SSL_write will (reasonably) return 0 if we tell it to
669275970Scy		   send 0 data.  Skip this case so we don't interpret the
670275970Scy		   result as an error */
671275970Scy		if (space[i].iov_len == 0)
672275970Scy			continue;
673275970Scy
674275970Scy		r = SSL_write(bev_ssl->ssl, space[i].iov_base,
675275970Scy		    space[i].iov_len);
676275970Scy		if (r > 0) {
677275970Scy			result |= OP_MADE_PROGRESS;
678275970Scy			if (bev_ssl->write_blocked_on_read)
679275970Scy				if (clear_wbor(bev_ssl) < 0)
680275970Scy					return OP_ERR | result;
681275970Scy			n_written += r;
682275970Scy			bev_ssl->last_write = -1;
683275970Scy			decrement_buckets(bev_ssl);
684275970Scy		} else {
685275970Scy			int err = SSL_get_error(bev_ssl->ssl, r);
686275970Scy			print_err(err);
687275970Scy			switch (err) {
688275970Scy			case SSL_ERROR_WANT_WRITE:
689275970Scy				/* Can't read until underlying has more data. */
690275970Scy				if (bev_ssl->write_blocked_on_read)
691275970Scy					if (clear_wbor(bev_ssl) < 0)
692275970Scy						return OP_ERR | result;
693275970Scy				bev_ssl->last_write = space[i].iov_len;
694275970Scy				break;
695275970Scy			case SSL_ERROR_WANT_READ:
696275970Scy				/* This read operation requires a write, and the
697275970Scy				 * underlying is full */
698275970Scy				if (!bev_ssl->write_blocked_on_read)
699275970Scy					if (set_wbor(bev_ssl) < 0)
700275970Scy						return OP_ERR | result;
701275970Scy				bev_ssl->last_write = space[i].iov_len;
702275970Scy				break;
703275970Scy			default:
704275970Scy				conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r);
705275970Scy				bev_ssl->last_write = -1;
706275970Scy				break;
707275970Scy			}
708275970Scy			result |= OP_BLOCKED;
709275970Scy			break;
710275970Scy		}
711275970Scy	}
712275970Scy	if (n_written) {
713275970Scy		evbuffer_drain(output, n_written);
714275970Scy		if (bev_ssl->underlying)
715275970Scy			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
716275970Scy
717275970Scy		bufferevent_trigger_nolock_(bev, EV_WRITE, 0);
718275970Scy	}
719275970Scy	return result;
720275970Scy}
721275970Scy
722275970Scy#define WRITE_FRAME 15000
723275970Scy
724275970Scy#define READ_DEFAULT 4096
725275970Scy
726275970Scy/* Try to figure out how many bytes to read; return 0 if we shouldn't be
727275970Scy * reading. */
728275970Scystatic int
729275970Scybytes_to_read(struct bufferevent_openssl *bev)
730275970Scy{
731275970Scy	struct evbuffer *input = bev->bev.bev.input;
732275970Scy	struct event_watermark *wm = &bev->bev.bev.wm_read;
733275970Scy	int result = READ_DEFAULT;
734275970Scy	ev_ssize_t limit;
735275970Scy	/* XXX 99% of this is generic code that nearly all bufferevents will
736275970Scy	 * want. */
737275970Scy
738275970Scy	if (bev->write_blocked_on_read) {
739275970Scy		return 0;
740275970Scy	}
741275970Scy
742275970Scy	if (! (bev->bev.bev.enabled & EV_READ)) {
743275970Scy		return 0;
744275970Scy	}
745275970Scy
746275970Scy	if (bev->bev.read_suspended) {
747275970Scy		return 0;
748275970Scy	}
749275970Scy
750275970Scy	if (wm->high) {
751275970Scy		if (evbuffer_get_length(input) >= wm->high) {
752275970Scy			return 0;
753275970Scy		}
754275970Scy
755275970Scy		result = wm->high - evbuffer_get_length(input);
756275970Scy	} else {
757275970Scy		result = READ_DEFAULT;
758275970Scy	}
759275970Scy
760275970Scy	/* Respect the rate limit */
761275970Scy	limit = bufferevent_get_read_max_(&bev->bev);
762275970Scy	if (result > limit) {
763275970Scy		result = limit;
764275970Scy	}
765275970Scy
766275970Scy	return result;
767275970Scy}
768275970Scy
769275970Scy
770275970Scy/* Things look readable.  If write is blocked on read, write till it isn't.
771275970Scy * Read from the underlying buffer until we block or we hit our high-water
772275970Scy * mark.
773275970Scy */
774275970Scystatic void
775275970Scyconsider_reading(struct bufferevent_openssl *bev_ssl)
776275970Scy{
777275970Scy	int r;
778275970Scy	int n_to_read;
779275970Scy	int all_result_flags = 0;
780275970Scy
781275970Scy	while (bev_ssl->write_blocked_on_read) {
782275970Scy		r = do_write(bev_ssl, WRITE_FRAME);
783275970Scy		if (r & (OP_BLOCKED|OP_ERR))
784275970Scy			break;
785275970Scy	}
786275970Scy	if (bev_ssl->write_blocked_on_read)
787275970Scy		return;
788275970Scy
789275970Scy	n_to_read = bytes_to_read(bev_ssl);
790275970Scy
791275970Scy	while (n_to_read) {
792275970Scy		r = do_read(bev_ssl, n_to_read);
793275970Scy		all_result_flags |= r;
794275970Scy
795275970Scy		if (r & (OP_BLOCKED|OP_ERR))
796275970Scy			break;
797275970Scy
798275970Scy		if (bev_ssl->bev.read_suspended)
799275970Scy			break;
800275970Scy
801275970Scy		/* Read all pending data.  This won't hit the network
802275970Scy		 * again, and will (most importantly) put us in a state
803275970Scy		 * where we don't need to read anything else until the
804275970Scy		 * socket is readable again.  It'll potentially make us
805275970Scy		 * overrun our read high-watermark (somewhat
806275970Scy		 * regrettable).  The damage to the rate-limit has
807275970Scy		 * already been done, since OpenSSL went and read a
808275970Scy		 * whole SSL record anyway. */
809275970Scy		n_to_read = SSL_pending(bev_ssl->ssl);
810275970Scy
811275970Scy		/* XXX This if statement is actually a bad bug, added to avoid
812275970Scy		 * XXX a worse bug.
813275970Scy		 *
814275970Scy		 * The bad bug: It can potentially cause resource unfairness
815275970Scy		 * by reading too much data from the underlying bufferevent;
816275970Scy		 * it can potentially cause read looping if the underlying
817275970Scy		 * bufferevent is a bufferevent_pair and deferred callbacks
818275970Scy		 * aren't used.
819275970Scy		 *
820275970Scy		 * The worse bug: If we didn't do this, then we would
821275970Scy		 * potentially not read any more from bev_ssl->underlying
822275970Scy		 * until more data arrived there, which could lead to us
823275970Scy		 * waiting forever.
824275970Scy		 */
825275970Scy		if (!n_to_read && bev_ssl->underlying)
826275970Scy			n_to_read = bytes_to_read(bev_ssl);
827275970Scy	}
828275970Scy
829275970Scy	if (all_result_flags & OP_MADE_PROGRESS) {
830275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
831275970Scy
832275970Scy		bufferevent_trigger_nolock_(bev, EV_READ, 0);
833275970Scy	}
834275970Scy
835275970Scy	if (!bev_ssl->underlying) {
836275970Scy		/* Should be redundant, but let's avoid busy-looping */
837275970Scy		if (bev_ssl->bev.read_suspended ||
838275970Scy		    !(bev_ssl->bev.bev.enabled & EV_READ)) {
839275970Scy			event_del(&bev_ssl->bev.bev.ev_read);
840275970Scy		}
841275970Scy	}
842275970Scy}
843275970Scy
844275970Scystatic void
845275970Scyconsider_writing(struct bufferevent_openssl *bev_ssl)
846275970Scy{
847275970Scy	int r;
848275970Scy	struct evbuffer *output = bev_ssl->bev.bev.output;
849275970Scy	struct evbuffer *target = NULL;
850275970Scy	struct event_watermark *wm = NULL;
851275970Scy
852275970Scy	while (bev_ssl->read_blocked_on_write) {
853275970Scy		r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */
854275970Scy		if (r & OP_MADE_PROGRESS) {
855275970Scy			struct bufferevent *bev = &bev_ssl->bev.bev;
856275970Scy
857275970Scy			bufferevent_trigger_nolock_(bev, EV_READ, 0);
858275970Scy		}
859275970Scy		if (r & (OP_ERR|OP_BLOCKED))
860275970Scy			break;
861275970Scy	}
862275970Scy	if (bev_ssl->read_blocked_on_write)
863275970Scy		return;
864275970Scy	if (bev_ssl->underlying) {
865275970Scy		target = bev_ssl->underlying->output;
866275970Scy		wm = &bev_ssl->underlying->wm_write;
867275970Scy	}
868275970Scy	while ((bev_ssl->bev.bev.enabled & EV_WRITE) &&
869275970Scy	    (! bev_ssl->bev.write_suspended) &&
870275970Scy	    evbuffer_get_length(output) &&
871275970Scy	    (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) {
872275970Scy		int n_to_write;
873275970Scy		if (wm && wm->high)
874275970Scy			n_to_write = wm->high - evbuffer_get_length(target);
875275970Scy		else
876275970Scy			n_to_write = WRITE_FRAME;
877275970Scy		r = do_write(bev_ssl, n_to_write);
878275970Scy		if (r & (OP_BLOCKED|OP_ERR))
879275970Scy			break;
880275970Scy	}
881275970Scy
882275970Scy	if (!bev_ssl->underlying) {
883275970Scy		if (evbuffer_get_length(output) == 0) {
884275970Scy			event_del(&bev_ssl->bev.bev.ev_write);
885275970Scy		} else if (bev_ssl->bev.write_suspended ||
886275970Scy		    !(bev_ssl->bev.bev.enabled & EV_WRITE)) {
887275970Scy			/* Should be redundant, but let's avoid busy-looping */
888275970Scy			event_del(&bev_ssl->bev.bev.ev_write);
889275970Scy		}
890275970Scy	}
891275970Scy}
892275970Scy
893275970Scystatic void
894275970Scybe_openssl_readcb(struct bufferevent *bev_base, void *ctx)
895275970Scy{
896275970Scy	struct bufferevent_openssl *bev_ssl = ctx;
897275970Scy	consider_reading(bev_ssl);
898275970Scy}
899275970Scy
900275970Scystatic void
901275970Scybe_openssl_writecb(struct bufferevent *bev_base, void *ctx)
902275970Scy{
903275970Scy	struct bufferevent_openssl *bev_ssl = ctx;
904275970Scy	consider_writing(bev_ssl);
905275970Scy}
906275970Scy
907275970Scystatic void
908275970Scybe_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)
909275970Scy{
910275970Scy	struct bufferevent_openssl *bev_ssl = ctx;
911275970Scy	int event = 0;
912275970Scy
913275970Scy	if (what & BEV_EVENT_EOF) {
914275970Scy		if (bev_ssl->allow_dirty_shutdown)
915275970Scy			event = BEV_EVENT_EOF;
916275970Scy		else
917275970Scy			event = BEV_EVENT_ERROR;
918275970Scy	} else if (what & BEV_EVENT_TIMEOUT) {
919275970Scy		/* We sure didn't set this.  Propagate it to the user. */
920275970Scy		event = what;
921275970Scy	} else if (what & BEV_EVENT_ERROR) {
922275970Scy		/* An error occurred on the connection.  Propagate it to the user. */
923275970Scy		event = what;
924275970Scy	} else if (what & BEV_EVENT_CONNECTED) {
925275970Scy		/* Ignore it.  We're saying SSL_connect() already, which will
926275970Scy		   eat it. */
927275970Scy	}
928275970Scy	if (event)
929275970Scy		bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);
930275970Scy}
931275970Scy
932275970Scystatic void
933275970Scybe_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr)
934275970Scy{
935275970Scy	struct bufferevent_openssl *bev_ssl = ptr;
936275970Scy	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
937275970Scy	if (what == EV_TIMEOUT) {
938275970Scy		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
939275970Scy		    BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0);
940275970Scy	} else {
941275970Scy		consider_reading(bev_ssl);
942275970Scy	}
943275970Scy	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
944275970Scy}
945275970Scy
946275970Scystatic void
947275970Scybe_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
948275970Scy{
949275970Scy	struct bufferevent_openssl *bev_ssl = ptr;
950275970Scy	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
951275970Scy	if (what == EV_TIMEOUT) {
952275970Scy		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
953275970Scy		    BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0);
954275970Scy	} else {
955275970Scy		consider_writing(bev_ssl);
956275970Scy	}
957275970Scy	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
958275970Scy}
959275970Scy
960275970Scystatic int
961275970Scyset_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
962275970Scy{
963275970Scy	if (bev_ssl->underlying) {
964275970Scy		bufferevent_setcb(bev_ssl->underlying,
965275970Scy		    be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
966275970Scy		    bev_ssl);
967275970Scy		return 0;
968275970Scy	} else {
969275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
970275970Scy		int rpending=0, wpending=0, r1=0, r2=0;
971275970Scy		if (fd < 0 && bev_ssl->fd_is_set)
972275970Scy			fd = event_get_fd(&bev->ev_read);
973275970Scy		if (bev_ssl->fd_is_set) {
974275970Scy			rpending = event_pending(&bev->ev_read, EV_READ, NULL);
975275970Scy			wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
976275970Scy			event_del(&bev->ev_read);
977275970Scy			event_del(&bev->ev_write);
978275970Scy		}
979275970Scy		event_assign(&bev->ev_read, bev->ev_base, fd,
980275970Scy		    EV_READ|EV_PERSIST|EV_FINALIZE,
981275970Scy		    be_openssl_readeventcb, bev_ssl);
982275970Scy		event_assign(&bev->ev_write, bev->ev_base, fd,
983275970Scy		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
984275970Scy		    be_openssl_writeeventcb, bev_ssl);
985275970Scy		if (rpending)
986275970Scy			r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
987275970Scy		if (wpending)
988275970Scy			r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
989275970Scy		if (fd >= 0) {
990275970Scy			bev_ssl->fd_is_set = 1;
991275970Scy		}
992275970Scy		return (r1<0 || r2<0) ? -1 : 0;
993275970Scy	}
994275970Scy}
995275970Scy
996275970Scystatic int
997275970Scydo_handshake(struct bufferevent_openssl *bev_ssl)
998275970Scy{
999275970Scy	int r;
1000275970Scy
1001275970Scy	switch (bev_ssl->state) {
1002275970Scy	default:
1003275970Scy	case BUFFEREVENT_SSL_OPEN:
1004275970Scy		EVUTIL_ASSERT(0);
1005275970Scy		return -1;
1006275970Scy	case BUFFEREVENT_SSL_CONNECTING:
1007275970Scy	case BUFFEREVENT_SSL_ACCEPTING:
1008275970Scy		r = SSL_do_handshake(bev_ssl->ssl);
1009275970Scy		break;
1010275970Scy	}
1011275970Scy	decrement_buckets(bev_ssl);
1012275970Scy
1013275970Scy	if (r==1) {
1014275970Scy		/* We're done! */
1015275970Scy		bev_ssl->state = BUFFEREVENT_SSL_OPEN;
1016275970Scy		set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */
1017275970Scy		/* Call do_read and do_write as needed */
1018275970Scy		bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
1019275970Scy		bufferevent_run_eventcb_(&bev_ssl->bev.bev,
1020275970Scy		    BEV_EVENT_CONNECTED, 0);
1021275970Scy		return 1;
1022275970Scy	} else {
1023275970Scy		int err = SSL_get_error(bev_ssl->ssl, r);
1024275970Scy		print_err(err);
1025275970Scy		switch (err) {
1026275970Scy		case SSL_ERROR_WANT_WRITE:
1027275970Scy			if (!bev_ssl->underlying) {
1028275970Scy				stop_reading(bev_ssl);
1029275970Scy				return start_writing(bev_ssl);
1030275970Scy			}
1031275970Scy			return 0;
1032275970Scy		case SSL_ERROR_WANT_READ:
1033275970Scy			if (!bev_ssl->underlying) {
1034275970Scy				stop_writing(bev_ssl);
1035275970Scy				return start_reading(bev_ssl);
1036275970Scy			}
1037275970Scy			return 0;
1038275970Scy		default:
1039275970Scy			conn_closed(bev_ssl, BEV_EVENT_READING, err, r);
1040275970Scy			return -1;
1041275970Scy		}
1042275970Scy	}
1043275970Scy}
1044275970Scy
1045275970Scystatic void
1046275970Scybe_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
1047275970Scy{
1048275970Scy	struct bufferevent_openssl *bev_ssl = ctx;
1049275970Scy	do_handshake(bev_ssl);/* XXX handle failure */
1050275970Scy}
1051275970Scy
1052275970Scystatic void
1053275970Scybe_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
1054275970Scy{
1055275970Scy	struct bufferevent_openssl *bev_ssl = ptr;
1056275970Scy
1057275970Scy	bufferevent_incref_and_lock_(&bev_ssl->bev.bev);
1058275970Scy	if (what & EV_TIMEOUT) {
1059275970Scy		bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0);
1060275970Scy	} else
1061275970Scy		do_handshake(bev_ssl);/* XXX handle failure */
1062275970Scy	bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
1063275970Scy}
1064275970Scy
1065275970Scystatic int
1066275970Scyset_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
1067275970Scy{
1068275970Scy	if (bev_ssl->underlying) {
1069275970Scy		bufferevent_setcb(bev_ssl->underlying,
1070275970Scy		    be_openssl_handshakecb, be_openssl_handshakecb,
1071275970Scy		    be_openssl_eventcb,
1072275970Scy		    bev_ssl);
1073275970Scy		return do_handshake(bev_ssl);
1074275970Scy	} else {
1075275970Scy		struct bufferevent *bev = &bev_ssl->bev.bev;
1076275970Scy		int r1=0, r2=0;
1077275970Scy		if (fd < 0 && bev_ssl->fd_is_set)
1078275970Scy			fd = event_get_fd(&bev->ev_read);
1079275970Scy		if (bev_ssl->fd_is_set) {
1080275970Scy			event_del(&bev->ev_read);
1081275970Scy			event_del(&bev->ev_write);
1082275970Scy		}
1083275970Scy		event_assign(&bev->ev_read, bev->ev_base, fd,
1084275970Scy		    EV_READ|EV_PERSIST|EV_FINALIZE,
1085275970Scy		    be_openssl_handshakeeventcb, bev_ssl);
1086275970Scy		event_assign(&bev->ev_write, bev->ev_base, fd,
1087275970Scy		    EV_WRITE|EV_PERSIST|EV_FINALIZE,
1088275970Scy		    be_openssl_handshakeeventcb, bev_ssl);
1089275970Scy		if (fd >= 0) {
1090275970Scy			r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
1091275970Scy			r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
1092275970Scy			bev_ssl->fd_is_set = 1;
1093275970Scy		}
1094275970Scy		return (r1<0 || r2<0) ? -1 : 0;
1095275970Scy	}
1096275970Scy}
1097275970Scy
1098275970Scyint
1099275970Scybufferevent_ssl_renegotiate(struct bufferevent *bev)
1100275970Scy{
1101275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1102275970Scy	if (!bev_ssl)
1103275970Scy		return -1;
1104275970Scy	if (SSL_renegotiate(bev_ssl->ssl) < 0)
1105275970Scy		return -1;
1106275970Scy	bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
1107275970Scy	if (set_handshake_callbacks(bev_ssl, -1) < 0)
1108275970Scy		return -1;
1109275970Scy	if (!bev_ssl->underlying)
1110275970Scy		return do_handshake(bev_ssl);
1111275970Scy	return 0;
1112275970Scy}
1113275970Scy
1114275970Scystatic void
1115275970Scybe_openssl_outbuf_cb(struct evbuffer *buf,
1116275970Scy    const struct evbuffer_cb_info *cbinfo, void *arg)
1117275970Scy{
1118275970Scy	struct bufferevent_openssl *bev_ssl = arg;
1119275970Scy	int r = 0;
1120275970Scy	/* XXX need to hold a reference here. */
1121275970Scy
1122275970Scy	if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
1123275970Scy		if (cbinfo->orig_size == 0)
1124275970Scy			r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
1125275970Scy			    &bev_ssl->bev.bev.timeout_write);
1126275970Scy		consider_writing(bev_ssl);
1127275970Scy	}
1128275970Scy	/* XXX Handle r < 0 */
1129275970Scy        (void)r;
1130275970Scy}
1131275970Scy
1132275970Scy
1133275970Scystatic int
1134275970Scybe_openssl_enable(struct bufferevent *bev, short events)
1135275970Scy{
1136275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1137275970Scy	int r1 = 0, r2 = 0;
1138275970Scy
1139275970Scy	if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
1140275970Scy		return 0;
1141275970Scy
1142275970Scy	if (events & EV_READ)
1143275970Scy		r1 = start_reading(bev_ssl);
1144275970Scy	if (events & EV_WRITE)
1145275970Scy		r2 = start_writing(bev_ssl);
1146275970Scy
1147275970Scy	if (bev_ssl->underlying) {
1148275970Scy		if (events & EV_READ)
1149275970Scy			BEV_RESET_GENERIC_READ_TIMEOUT(bev);
1150275970Scy		if (events & EV_WRITE)
1151275970Scy			BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
1152275970Scy
1153275970Scy		if (events & EV_READ)
1154275970Scy			consider_reading(bev_ssl);
1155275970Scy		if (events & EV_WRITE)
1156275970Scy			consider_writing(bev_ssl);
1157275970Scy	}
1158275970Scy	return (r1 < 0 || r2 < 0) ? -1 : 0;
1159275970Scy}
1160275970Scy
1161275970Scystatic int
1162275970Scybe_openssl_disable(struct bufferevent *bev, short events)
1163275970Scy{
1164275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1165275970Scy	if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
1166275970Scy		return 0;
1167275970Scy
1168275970Scy	if (events & EV_READ)
1169275970Scy		stop_reading(bev_ssl);
1170275970Scy	if (events & EV_WRITE)
1171275970Scy		stop_writing(bev_ssl);
1172275970Scy
1173275970Scy	if (bev_ssl->underlying) {
1174275970Scy		if (events & EV_READ)
1175275970Scy			BEV_DEL_GENERIC_READ_TIMEOUT(bev);
1176275970Scy		if (events & EV_WRITE)
1177275970Scy			BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
1178275970Scy	}
1179275970Scy	return 0;
1180275970Scy}
1181275970Scy
1182275970Scystatic void
1183275970Scybe_openssl_unlink(struct bufferevent *bev)
1184275970Scy{
1185275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1186275970Scy
1187275970Scy	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
1188275970Scy		if (bev_ssl->underlying) {
1189275970Scy			if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) {
1190275970Scy				event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "
1191275970Scy				    "bufferevent with too few references");
1192275970Scy			} else {
1193275970Scy				bufferevent_free(bev_ssl->underlying);
1194275970Scy				/* We still have a reference to it, via our
1195275970Scy				 * BIO. So we don't drop this. */
1196275970Scy				// bev_ssl->underlying = NULL;
1197275970Scy			}
1198275970Scy		}
1199275970Scy	} else {
1200275970Scy		if (bev_ssl->underlying) {
1201275970Scy			if (bev_ssl->underlying->errorcb == be_openssl_eventcb)
1202275970Scy				bufferevent_setcb(bev_ssl->underlying,
1203275970Scy				    NULL,NULL,NULL,NULL);
1204275970Scy			bufferevent_unsuspend_read_(bev_ssl->underlying,
1205275970Scy			    BEV_SUSPEND_FILT_READ);
1206275970Scy		}
1207275970Scy	}
1208275970Scy}
1209275970Scy
1210275970Scystatic void
1211275970Scybe_openssl_destruct(struct bufferevent *bev)
1212275970Scy{
1213275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1214275970Scy
1215275970Scy	if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
1216275970Scy		if (! bev_ssl->underlying) {
1217275970Scy			evutil_socket_t fd = -1;
1218275970Scy			BIO *bio = SSL_get_wbio(bev_ssl->ssl);
1219275970Scy			if (bio)
1220275970Scy				fd = BIO_get_fd(bio, NULL);
1221275970Scy			if (fd >= 0)
1222275970Scy				evutil_closesocket(fd);
1223275970Scy		}
1224275970Scy		SSL_free(bev_ssl->ssl);
1225275970Scy	}
1226275970Scy}
1227275970Scy
1228275970Scystatic int
1229275970Scybe_openssl_adj_timeouts(struct bufferevent *bev)
1230275970Scy{
1231275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1232275970Scy
1233275970Scy	if (bev_ssl->underlying) {
1234275970Scy		return bufferevent_generic_adj_timeouts_(bev);
1235275970Scy	} else {
1236275970Scy		int r1=0, r2=0;
1237275970Scy		if (event_pending(&bev->ev_read, EV_READ, NULL)) {
1238275970Scy			if (evutil_timerisset(&bev->timeout_read)) {
1239275970Scy				r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
1240275970Scy			} else {
1241275970Scy				event_remove_timer(&bev->ev_read);
1242275970Scy			}
1243275970Scy		}
1244275970Scy		if (event_pending(&bev->ev_write, EV_WRITE, NULL)) {
1245275970Scy			if (evutil_timerisset(&bev->timeout_write)) {
1246275970Scy				r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
1247275970Scy			} else {
1248275970Scy				event_remove_timer(&bev->ev_write);
1249275970Scy			}
1250275970Scy		}
1251275970Scy
1252275970Scy		return (r1<0 || r2<0) ? -1 : 0;
1253275970Scy	}
1254275970Scy}
1255275970Scy
1256275970Scystatic int
1257275970Scybe_openssl_flush(struct bufferevent *bufev,
1258275970Scy    short iotype, enum bufferevent_flush_mode mode)
1259275970Scy{
1260275970Scy	/* XXXX Implement this. */
1261275970Scy	return 0;
1262275970Scy}
1263275970Scy
1264275970Scystatic int
1265275970Scybe_openssl_ctrl(struct bufferevent *bev,
1266275970Scy    enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data)
1267275970Scy{
1268275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bev);
1269275970Scy	switch (op) {
1270275970Scy	case BEV_CTRL_SET_FD:
1271275970Scy		if (bev_ssl->underlying)
1272275970Scy			return -1;
1273275970Scy		{
1274275970Scy			BIO *bio;
1275275970Scy			bio = BIO_new_socket(data->fd, 0);
1276275970Scy			SSL_set_bio(bev_ssl->ssl, bio, bio);
1277275970Scy			bev_ssl->fd_is_set = 1;
1278275970Scy		}
1279290000Sglebius		if (data->fd == -1)
1280290000Sglebius			bev_ssl->fd_is_set = 0;
1281275970Scy		if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
1282275970Scy			return set_open_callbacks(bev_ssl, data->fd);
1283275970Scy		else {
1284275970Scy			return set_handshake_callbacks(bev_ssl, data->fd);
1285275970Scy		}
1286275970Scy	case BEV_CTRL_GET_FD:
1287275970Scy		if (bev_ssl->underlying)
1288275970Scy			return -1;
1289275970Scy		if (!bev_ssl->fd_is_set)
1290275970Scy			return -1;
1291275970Scy		data->fd = event_get_fd(&bev->ev_read);
1292275970Scy		return 0;
1293275970Scy	case BEV_CTRL_GET_UNDERLYING:
1294275970Scy		if (!bev_ssl->underlying)
1295275970Scy			return -1;
1296275970Scy		data->ptr = bev_ssl->underlying;
1297275970Scy		return 0;
1298275970Scy	case BEV_CTRL_CANCEL_ALL:
1299275970Scy	default:
1300275970Scy		return -1;
1301275970Scy	}
1302275970Scy}
1303275970Scy
1304275970ScySSL *
1305275970Scybufferevent_openssl_get_ssl(struct bufferevent *bufev)
1306275970Scy{
1307275970Scy	struct bufferevent_openssl *bev_ssl = upcast(bufev);
1308275970Scy	if (!bev_ssl)
1309275970Scy		return NULL;
1310275970Scy	return bev_ssl->ssl;
1311275970Scy}
1312275970Scy
1313275970Scystatic struct bufferevent *
1314275970Scybufferevent_openssl_new_impl(struct event_base *base,
1315275970Scy    struct bufferevent *underlying,
1316275970Scy    evutil_socket_t fd,
1317275970Scy    SSL *ssl,
1318275970Scy    enum bufferevent_ssl_state state,
1319275970Scy    int options)
1320275970Scy{
1321275970Scy	struct bufferevent_openssl *bev_ssl = NULL;
1322275970Scy	struct bufferevent_private *bev_p = NULL;
1323275970Scy	int tmp_options = options & ~BEV_OPT_THREADSAFE;
1324275970Scy
1325275970Scy	if (underlying != NULL && fd >= 0)
1326275970Scy		return NULL; /* Only one can be set. */
1327275970Scy
1328275970Scy	if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))
1329275970Scy		goto err;
1330275970Scy
1331275970Scy	bev_p = &bev_ssl->bev;
1332275970Scy
1333275970Scy	if (bufferevent_init_common_(bev_p, base,
1334275970Scy		&bufferevent_ops_openssl, tmp_options) < 0)
1335275970Scy		goto err;
1336275970Scy
1337275970Scy	/* Don't explode if we decide to realloc a chunk we're writing from in
1338275970Scy	 * the output buffer. */
1339275970Scy	SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
1340275970Scy
1341275970Scy	bev_ssl->underlying = underlying;
1342275970Scy	bev_ssl->ssl = ssl;
1343275970Scy
1344275970Scy	bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output,
1345275970Scy	    be_openssl_outbuf_cb, bev_ssl);
1346275970Scy
1347275970Scy	if (options & BEV_OPT_THREADSAFE)
1348275970Scy		bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL);
1349275970Scy
1350275970Scy	if (underlying) {
1351275970Scy		bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev);
1352275970Scy		bufferevent_incref_(underlying);
1353275970Scy	}
1354275970Scy
1355275970Scy	bev_ssl->state = state;
1356275970Scy	bev_ssl->last_write = -1;
1357275970Scy
1358275970Scy	init_bio_counts(bev_ssl);
1359275970Scy
1360275970Scy	switch (state) {
1361275970Scy	case BUFFEREVENT_SSL_ACCEPTING:
1362275970Scy		SSL_set_accept_state(bev_ssl->ssl);
1363275970Scy		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1364275970Scy			goto err;
1365275970Scy		break;
1366275970Scy	case BUFFEREVENT_SSL_CONNECTING:
1367275970Scy		SSL_set_connect_state(bev_ssl->ssl);
1368275970Scy		if (set_handshake_callbacks(bev_ssl, fd) < 0)
1369275970Scy			goto err;
1370275970Scy		break;
1371275970Scy	case BUFFEREVENT_SSL_OPEN:
1372275970Scy		if (set_open_callbacks(bev_ssl, fd) < 0)
1373275970Scy			goto err;
1374275970Scy		break;
1375275970Scy	default:
1376275970Scy		goto err;
1377275970Scy	}
1378275970Scy
1379275970Scy	if (underlying) {
1380275970Scy		bufferevent_setwatermark(underlying, EV_READ, 0, 0);
1381275970Scy		bufferevent_enable(underlying, EV_READ|EV_WRITE);
1382275970Scy		if (state == BUFFEREVENT_SSL_OPEN)
1383275970Scy			bufferevent_suspend_read_(underlying,
1384275970Scy			    BEV_SUSPEND_FILT_READ);
1385275970Scy	} else {
1386275970Scy		bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
1387275970Scy		if (bev_ssl->fd_is_set) {
1388275970Scy			if (state != BUFFEREVENT_SSL_OPEN)
1389275970Scy				if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
1390275970Scy					goto err;
1391275970Scy			if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
1392275970Scy				goto err;
1393275970Scy		}
1394275970Scy	}
1395275970Scy
1396275970Scy	return &bev_ssl->bev.bev;
1397275970Scyerr:
1398275970Scy	if (bev_ssl)
1399275970Scy		bufferevent_free(&bev_ssl->bev.bev);
1400275970Scy	return NULL;
1401275970Scy}
1402275970Scy
1403275970Scystruct bufferevent *
1404275970Scybufferevent_openssl_filter_new(struct event_base *base,
1405275970Scy    struct bufferevent *underlying,
1406275970Scy    SSL *ssl,
1407275970Scy    enum bufferevent_ssl_state state,
1408275970Scy    int options)
1409275970Scy{
1410275970Scy	/* We don't tell the BIO to close the bufferevent; we do it ourselves
1411275970Scy	 * on be_openssl_destruct */
1412275970Scy	int close_flag = 0; /* options & BEV_OPT_CLOSE_ON_FREE; */
1413275970Scy	BIO *bio;
1414275970Scy	if (!underlying)
1415275970Scy		return NULL;
1416275970Scy	if (!(bio = BIO_new_bufferevent(underlying, close_flag)))
1417275970Scy		return NULL;
1418275970Scy
1419275970Scy	SSL_set_bio(ssl, bio, bio);
1420275970Scy
1421275970Scy	return bufferevent_openssl_new_impl(
1422275970Scy		base, underlying, -1, ssl, state, options);
1423275970Scy}
1424275970Scy
1425275970Scystruct bufferevent *
1426275970Scybufferevent_openssl_socket_new(struct event_base *base,
1427275970Scy    evutil_socket_t fd,
1428275970Scy    SSL *ssl,
1429275970Scy    enum bufferevent_ssl_state state,
1430275970Scy    int options)
1431275970Scy{
1432275970Scy	/* Does the SSL already have an fd? */
1433275970Scy	BIO *bio = SSL_get_wbio(ssl);
1434275970Scy	long have_fd = -1;
1435275970Scy
1436275970Scy	if (bio)
1437275970Scy		have_fd = BIO_get_fd(bio, NULL);
1438275970Scy
1439275970Scy	if (have_fd >= 0) {
1440275970Scy		/* The SSL is already configured with an fd. */
1441275970Scy		if (fd < 0) {
1442275970Scy			/* We should learn the fd from the SSL. */
1443275970Scy			fd = (evutil_socket_t) have_fd;
1444275970Scy		} else if (have_fd == (long)fd) {
1445275970Scy			/* We already know the fd from the SSL; do nothing */
1446275970Scy		} else {
1447275970Scy			/* We specified an fd different from that of the SSL.
1448275970Scy			   This is probably an error on our part.  Fail. */
1449275970Scy			return NULL;
1450275970Scy		}
1451275970Scy		(void) BIO_set_close(bio, 0);
1452275970Scy	} else {
1453275970Scy		/* The SSL isn't configured with a BIO with an fd. */
1454275970Scy		if (fd >= 0) {
1455275970Scy			/* ... and we have an fd we want to use. */
1456275970Scy			bio = BIO_new_socket(fd, 0);
1457275970Scy			SSL_set_bio(ssl, bio, bio);
1458275970Scy		} else {
1459275970Scy			/* Leave the fd unset. */
1460275970Scy		}
1461275970Scy	}
1462275970Scy
1463275970Scy	return bufferevent_openssl_new_impl(
1464275970Scy		base, NULL, fd, ssl, state, options);
1465275970Scy}
1466275970Scy
1467275970Scyint
1468275970Scybufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev)
1469275970Scy{
1470275970Scy	int allow_dirty_shutdown = -1;
1471275970Scy	struct bufferevent_openssl *bev_ssl;
1472275970Scy	BEV_LOCK(bev);
1473275970Scy	bev_ssl = upcast(bev);
1474275970Scy	if (bev_ssl)
1475275970Scy		allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown;
1476275970Scy	BEV_UNLOCK(bev);
1477275970Scy	return allow_dirty_shutdown;
1478275970Scy}
1479275970Scy
1480275970Scyvoid
1481275970Scybufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
1482275970Scy    int allow_dirty_shutdown)
1483275970Scy{
1484275970Scy	struct bufferevent_openssl *bev_ssl;
1485275970Scy	BEV_LOCK(bev);
1486275970Scy	bev_ssl = upcast(bev);
1487275970Scy	if (bev_ssl)
1488275970Scy		bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown;
1489275970Scy	BEV_UNLOCK(bev);
1490275970Scy}
1491275970Scy
1492275970Scyunsigned long
1493275970Scybufferevent_get_openssl_error(struct bufferevent *bev)
1494275970Scy{
1495275970Scy	unsigned long err = 0;
1496275970Scy	struct bufferevent_openssl *bev_ssl;
1497275970Scy	BEV_LOCK(bev);
1498275970Scy	bev_ssl = upcast(bev);
1499275970Scy	if (bev_ssl && bev_ssl->n_errors) {
1500275970Scy		err = bev_ssl->errors[--bev_ssl->n_errors];
1501275970Scy	}
1502275970Scy	BEV_UNLOCK(bev);
1503275970Scy	return err;
1504275970Scy}
1505