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