Path: blob/main/contrib/libevent/bufferevent_openssl.c
39475 views
/*1* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11* 3. The name of the author may not be used to endorse or promote products12* derived from this software without specific prior written permission.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.17* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526// Get rid of OSX 10.7 and greater deprecation warnings.27#if defined(__APPLE__) && defined(__clang__)28#pragma clang diagnostic ignored "-Wdeprecated-declarations"29#endif3031#include "event2/event-config.h"32#include "evconfig-private.h"3334#include <sys/types.h>3536#ifdef EVENT__HAVE_SYS_TIME_H37#include <sys/time.h>38#endif3940#include <errno.h>41#include <stdio.h>42#include <stdlib.h>43#include <string.h>44#ifdef EVENT__HAVE_STDARG_H45#include <stdarg.h>46#endif47#ifdef EVENT__HAVE_UNISTD_H48#include <unistd.h>49#endif5051#ifdef _WIN3252#include <winsock2.h>53#endif5455#include "event2/bufferevent.h"56#include "event2/bufferevent_struct.h"57#include "event2/bufferevent_ssl.h"58#include "event2/buffer.h"59#include "event2/event.h"6061#include "mm-internal.h"62#include "bufferevent-internal.h"63#include "log-internal.h"6465#include <openssl/ssl.h>66#include <openssl/err.h>67#include "openssl-compat.h"6869/*70* Define an OpenSSL bio that targets a bufferevent.71*/7273/* --------------------74A BIO is an OpenSSL abstraction that handles reading and writing data. The75library will happily speak SSL over anything that implements a BIO76interface.7778Here we define a BIO implementation that directs its output to a79bufferevent. We'll want to use this only when none of OpenSSL's built-in80IO mechanisms work for us.81-------------------- */8283/* every BIO type needs its own integer type value. */84#define BIO_TYPE_LIBEVENT 5785/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on86* this. */8788#if 089static void90print_err(int val)91{92int err;93printf("Error was %d\n", val);9495while ((err = ERR_get_error())) {96const char *msg = (const char*)ERR_reason_error_string(err);97const char *lib = (const char*)ERR_lib_error_string(err);98const char *func = (const char*)ERR_func_error_string(err);99100printf("%s in %s %s\n", msg, lib, func);101}102}103#else104#define print_err(v) ((void)0)105#endif106107/* Called to initialize a new BIO */108static int109bio_bufferevent_new(BIO *b)110{111BIO_set_init(b, 0);112BIO_set_data(b, NULL); /* We'll be putting the bufferevent in this field.*/113return 1;114}115116/* Called to uninitialize the BIO. */117static int118bio_bufferevent_free(BIO *b)119{120if (!b)121return 0;122if (BIO_get_shutdown(b)) {123if (BIO_get_init(b) && BIO_get_data(b))124bufferevent_free(BIO_get_data(b));125BIO_free(b);126}127return 1;128}129130/* Called to extract data from the BIO. */131static int132bio_bufferevent_read(BIO *b, char *out, int outlen)133{134int r = 0;135struct evbuffer *input;136137BIO_clear_retry_flags(b);138139if (!out)140return 0;141if (!BIO_get_data(b))142return -1;143144input = bufferevent_get_input(BIO_get_data(b));145if (evbuffer_get_length(input) == 0) {146/* If there's no data to read, say so. */147BIO_set_retry_read(b);148return -1;149} else {150r = evbuffer_remove(input, out, outlen);151}152153return r;154}155156/* Called to write data into the BIO */157static int158bio_bufferevent_write(BIO *b, const char *in, int inlen)159{160struct bufferevent *bufev = BIO_get_data(b);161struct evbuffer *output;162size_t outlen;163164BIO_clear_retry_flags(b);165166if (!BIO_get_data(b))167return -1;168169output = bufferevent_get_output(bufev);170outlen = evbuffer_get_length(output);171172/* Copy only as much data onto the output buffer as can fit under the173* high-water mark. */174if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {175if (bufev->wm_write.high <= outlen) {176/* If no data can fit, we'll need to retry later. */177BIO_set_retry_write(b);178return -1;179}180inlen = bufev->wm_write.high - outlen;181}182183EVUTIL_ASSERT(inlen > 0);184evbuffer_add(output, in, inlen);185return inlen;186}187188/* Called to handle various requests */189static long190bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)191{192struct bufferevent *bufev = BIO_get_data(b);193long ret = 1;194195switch (cmd) {196case BIO_CTRL_GET_CLOSE:197ret = BIO_get_shutdown(b);198break;199case BIO_CTRL_SET_CLOSE:200BIO_set_shutdown(b, (int)num);201break;202case BIO_CTRL_PENDING:203ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;204break;205case BIO_CTRL_WPENDING:206ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0;207break;208/* XXXX These two are given a special-case treatment because209* of cargo-cultism. I should come up with a better reason. */210case BIO_CTRL_DUP:211case BIO_CTRL_FLUSH:212ret = 1;213break;214default:215ret = 0;216break;217}218return ret;219}220221/* Called to write a string to the BIO */222static int223bio_bufferevent_puts(BIO *b, const char *s)224{225return bio_bufferevent_write(b, s, strlen(s));226}227228/* Method table for the bufferevent BIO */229static BIO_METHOD *methods_bufferevent;230231/* Return the method table for the bufferevents BIO */232static BIO_METHOD *233BIO_s_bufferevent(void)234{235if (methods_bufferevent == NULL) {236methods_bufferevent = BIO_meth_new(BIO_TYPE_LIBEVENT, "bufferevent");237if (methods_bufferevent == NULL)238return NULL;239BIO_meth_set_write(methods_bufferevent, bio_bufferevent_write);240BIO_meth_set_read(methods_bufferevent, bio_bufferevent_read);241BIO_meth_set_puts(methods_bufferevent, bio_bufferevent_puts);242BIO_meth_set_ctrl(methods_bufferevent, bio_bufferevent_ctrl);243BIO_meth_set_create(methods_bufferevent, bio_bufferevent_new);244BIO_meth_set_destroy(methods_bufferevent, bio_bufferevent_free);245}246return methods_bufferevent;247}248249/* Create a new BIO to wrap communication around a bufferevent. If close_flag250* is true, the bufferevent will be freed when the BIO is closed. */251static BIO *252BIO_new_bufferevent(struct bufferevent *bufferevent)253{254BIO *result;255if (!bufferevent)256return NULL;257if (!(result = BIO_new(BIO_s_bufferevent())))258return NULL;259BIO_set_init(result, 1);260BIO_set_data(result, bufferevent);261/* We don't tell the BIO to close the bufferevent; we do it ourselves on262* be_openssl_destruct() */263BIO_set_shutdown(result, 0);264return result;265}266267/* --------------------268Now, here's the OpenSSL-based implementation of bufferevent.269270The implementation comes in two flavors: one that connects its SSL object271to an underlying bufferevent using a BIO_bufferevent, and one that has the272SSL object connect to a socket directly. The latter should generally be273faster, except on Windows, where your best bet is using a274bufferevent_async.275276(OpenSSL supports many other BIO types, too. But we can't use any unless277we have a good way to get notified when they become readable/writable.)278-------------------- */279280struct bio_data_counts {281unsigned long n_written;282unsigned long n_read;283};284285struct bufferevent_openssl {286/* Shared fields with common bufferevent implementation code.287If we were set up with an underlying bufferevent, we use the288events here as timers only. If we have an SSL, then we use289the events as socket events.290*/291struct bufferevent_private bev;292/* An underlying bufferevent that we're directing our output to.293If it's NULL, then we're connected to an fd, not an evbuffer. */294struct bufferevent *underlying;295/* The SSL object doing our encryption. */296SSL *ssl;297298/* A callback that's invoked when data arrives on our outbuf so we299know to write data to the SSL. */300struct evbuffer_cb_entry *outbuf_cb;301302/* A count of how much data the bios have read/written total. Used303for rate-limiting. */304struct bio_data_counts counts;305306/* If this value is greater than 0, then the last SSL_write blocked,307* and we need to try it again with this many bytes. */308ev_ssize_t last_write;309310#define NUM_ERRORS 3311ev_uint32_t errors[NUM_ERRORS];312313/* When we next get available space, we should say "read" instead of314"write". This can happen if there's a renegotiation during a read315operation. */316unsigned read_blocked_on_write : 1;317/* When we next get data, we should say "write" instead of "read". */318unsigned write_blocked_on_read : 1;319/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */320unsigned allow_dirty_shutdown : 1;321/* XXX */322unsigned n_errors : 2;323324/* Are we currently connecting, accepting, or doing IO? */325unsigned state : 2;326/* If we reset fd, we sould reset state too */327unsigned old_state : 2;328};329330static int be_openssl_enable(struct bufferevent *, short);331static int be_openssl_disable(struct bufferevent *, short);332static void be_openssl_unlink(struct bufferevent *);333static void be_openssl_destruct(struct bufferevent *);334static int be_openssl_adj_timeouts(struct bufferevent *);335static int be_openssl_flush(struct bufferevent *bufev,336short iotype, enum bufferevent_flush_mode mode);337static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);338339const struct bufferevent_ops bufferevent_ops_openssl = {340"ssl",341evutil_offsetof(struct bufferevent_openssl, bev.bev),342be_openssl_enable,343be_openssl_disable,344be_openssl_unlink,345be_openssl_destruct,346be_openssl_adj_timeouts,347be_openssl_flush,348be_openssl_ctrl,349};350351/* Given a bufferevent, return a pointer to the bufferevent_openssl that352* contains it, if any. */353static inline struct bufferevent_openssl *354upcast(struct bufferevent *bev)355{356struct bufferevent_openssl *bev_o;357if (!BEV_IS_OPENSSL(bev))358return NULL;359bev_o = (void*)( ((char*)bev) -360evutil_offsetof(struct bufferevent_openssl, bev.bev));361EVUTIL_ASSERT(BEV_IS_OPENSSL(&bev_o->bev.bev));362return bev_o;363}364365static inline void366put_error(struct bufferevent_openssl *bev_ssl, unsigned long err)367{368if (bev_ssl->n_errors == NUM_ERRORS)369return;370/* The error type according to openssl is "unsigned long", but371openssl never uses more than 32 bits of it. It _can't_ use more372than 32 bits of it, since it needs to report errors on systems373where long is only 32 bits.374*/375bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err;376}377378/* Have the base communications channel (either the underlying bufferevent or379* ev_read and ev_write) start reading. Take the read-blocked-on-write flag380* into account. */381static int382start_reading(struct bufferevent_openssl *bev_ssl)383{384if (bev_ssl->underlying) {385bufferevent_unsuspend_read_(bev_ssl->underlying,386BEV_SUSPEND_FILT_READ);387return 0;388} else {389struct bufferevent *bev = &bev_ssl->bev.bev;390int r;391r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);392if (r == 0 && bev_ssl->read_blocked_on_write)393r = bufferevent_add_event_(&bev->ev_write,394&bev->timeout_write);395return r;396}397}398399/* Have the base communications channel (either the underlying bufferevent or400* ev_read and ev_write) start writing. Take the write-blocked-on-read flag401* into account. */402static int403start_writing(struct bufferevent_openssl *bev_ssl)404{405int r = 0;406if (bev_ssl->underlying) {407if (bev_ssl->write_blocked_on_read) {408bufferevent_unsuspend_read_(bev_ssl->underlying,409BEV_SUSPEND_FILT_READ);410}411} else {412struct bufferevent *bev = &bev_ssl->bev.bev;413r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);414if (!r && bev_ssl->write_blocked_on_read)415r = bufferevent_add_event_(&bev->ev_read,416&bev->timeout_read);417}418return r;419}420421static void422stop_reading(struct bufferevent_openssl *bev_ssl)423{424if (bev_ssl->write_blocked_on_read)425return;426if (bev_ssl->underlying) {427bufferevent_suspend_read_(bev_ssl->underlying,428BEV_SUSPEND_FILT_READ);429} else {430struct bufferevent *bev = &bev_ssl->bev.bev;431event_del(&bev->ev_read);432}433}434435static void436stop_writing(struct bufferevent_openssl *bev_ssl)437{438if (bev_ssl->read_blocked_on_write)439return;440if (bev_ssl->underlying) {441bufferevent_unsuspend_read_(bev_ssl->underlying,442BEV_SUSPEND_FILT_READ);443} else {444struct bufferevent *bev = &bev_ssl->bev.bev;445event_del(&bev->ev_write);446}447}448449static int450set_rbow(struct bufferevent_openssl *bev_ssl)451{452if (!bev_ssl->underlying)453stop_reading(bev_ssl);454bev_ssl->read_blocked_on_write = 1;455return start_writing(bev_ssl);456}457458static int459set_wbor(struct bufferevent_openssl *bev_ssl)460{461if (!bev_ssl->underlying)462stop_writing(bev_ssl);463bev_ssl->write_blocked_on_read = 1;464return start_reading(bev_ssl);465}466467static int468clear_rbow(struct bufferevent_openssl *bev_ssl)469{470struct bufferevent *bev = &bev_ssl->bev.bev;471int r = 0;472bev_ssl->read_blocked_on_write = 0;473if (!(bev->enabled & EV_WRITE))474stop_writing(bev_ssl);475if (bev->enabled & EV_READ)476r = start_reading(bev_ssl);477return r;478}479480481static int482clear_wbor(struct bufferevent_openssl *bev_ssl)483{484struct bufferevent *bev = &bev_ssl->bev.bev;485int r = 0;486bev_ssl->write_blocked_on_read = 0;487if (!(bev->enabled & EV_READ))488stop_reading(bev_ssl);489if (bev->enabled & EV_WRITE)490r = start_writing(bev_ssl);491return r;492}493494static void495conn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret)496{497int event = BEV_EVENT_ERROR;498int dirty_shutdown = 0;499unsigned long err;500501switch (errcode) {502case SSL_ERROR_ZERO_RETURN:503/* Possibly a clean shutdown. */504if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)505event = BEV_EVENT_EOF;506else507dirty_shutdown = 1;508break;509case SSL_ERROR_SYSCALL:510/* IO error; possibly a dirty shutdown. */511if ((ret == 0 || ret == -1) && ERR_peek_error() == 0)512dirty_shutdown = 1;513put_error(bev_ssl, errcode);514break;515case SSL_ERROR_SSL:516/* Protocol error. */517put_error(bev_ssl, errcode);518break;519case SSL_ERROR_WANT_X509_LOOKUP:520/* XXXX handle this. */521put_error(bev_ssl, errcode);522break;523case SSL_ERROR_NONE:524case SSL_ERROR_WANT_READ:525case SSL_ERROR_WANT_WRITE:526case SSL_ERROR_WANT_CONNECT:527case SSL_ERROR_WANT_ACCEPT:528default:529/* should be impossible; treat as normal error. */530event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);531break;532}533534while ((err = ERR_get_error())) {535put_error(bev_ssl, err);536}537538if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)539event = BEV_EVENT_EOF;540541stop_reading(bev_ssl);542stop_writing(bev_ssl);543544/* when is BEV_EVENT_{READING|WRITING} */545event = when | event;546bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);547}548549static void550init_bio_counts(struct bufferevent_openssl *bev_ssl)551{552BIO *rbio, *wbio;553554wbio = SSL_get_wbio(bev_ssl->ssl);555bev_ssl->counts.n_written = wbio ? BIO_number_written(wbio) : 0;556rbio = SSL_get_rbio(bev_ssl->ssl);557bev_ssl->counts.n_read = rbio ? BIO_number_read(rbio) : 0;558}559560static inline void561decrement_buckets(struct bufferevent_openssl *bev_ssl)562{563unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));564unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));565/* These next two subtractions can wrap around. That's okay. */566unsigned long w = num_w - bev_ssl->counts.n_written;567unsigned long r = num_r - bev_ssl->counts.n_read;568if (w)569bufferevent_decrement_write_buckets_(&bev_ssl->bev, w);570if (r)571bufferevent_decrement_read_buckets_(&bev_ssl->bev, r);572bev_ssl->counts.n_written = num_w;573bev_ssl->counts.n_read = num_r;574}575576#define OP_MADE_PROGRESS 1577#define OP_BLOCKED 2578#define OP_ERR 4579580/* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if581we're now blocked); and OP_ERR (if an error occurred). */582static int583do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {584/* Requires lock */585struct bufferevent *bev = &bev_ssl->bev.bev;586struct evbuffer *input = bev->input;587int r, n, i, n_used = 0, atmost;588struct evbuffer_iovec space[2];589int result = 0;590591if (bev_ssl->bev.read_suspended)592return 0;593594atmost = bufferevent_get_read_max_(&bev_ssl->bev);595if (n_to_read > atmost)596n_to_read = atmost;597598n = evbuffer_reserve_space(input, n_to_read, space, 2);599if (n < 0)600return OP_ERR;601602for (i=0; i<n; ++i) {603if (bev_ssl->bev.read_suspended)604break;605ERR_clear_error();606r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);607if (r>0) {608result |= OP_MADE_PROGRESS;609if (bev_ssl->read_blocked_on_write)610if (clear_rbow(bev_ssl) < 0)611return OP_ERR | result;612++n_used;613space[i].iov_len = r;614decrement_buckets(bev_ssl);615} else {616int err = SSL_get_error(bev_ssl->ssl, r);617print_err(err);618switch (err) {619case SSL_ERROR_WANT_READ:620/* Can't read until underlying has more data. */621if (bev_ssl->read_blocked_on_write)622if (clear_rbow(bev_ssl) < 0)623return OP_ERR | result;624break;625case SSL_ERROR_WANT_WRITE:626/* This read operation requires a write, and the627* underlying is full */628if (!bev_ssl->read_blocked_on_write)629if (set_rbow(bev_ssl) < 0)630return OP_ERR | result;631break;632default:633conn_closed(bev_ssl, BEV_EVENT_READING, err, r);634break;635}636result |= OP_BLOCKED;637break; /* out of the loop */638}639}640641if (n_used) {642evbuffer_commit_space(input, space, n_used);643if (bev_ssl->underlying)644BEV_RESET_GENERIC_READ_TIMEOUT(bev);645}646647return result;648}649650/* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if651we're now blocked); and OP_ERR (if an error occurred). */652static int653do_write(struct bufferevent_openssl *bev_ssl, int atmost)654{655int i, r, n, n_written = 0;656struct bufferevent *bev = &bev_ssl->bev.bev;657struct evbuffer *output = bev->output;658struct evbuffer_iovec space[8];659int result = 0;660661if (bev_ssl->last_write > 0)662atmost = bev_ssl->last_write;663else664atmost = bufferevent_get_write_max_(&bev_ssl->bev);665666n = evbuffer_peek(output, atmost, NULL, space, 8);667if (n < 0)668return OP_ERR | result;669670if (n > 8)671n = 8;672for (i=0; i < n; ++i) {673if (bev_ssl->bev.write_suspended)674break;675676/* SSL_write will (reasonably) return 0 if we tell it to677send 0 data. Skip this case so we don't interpret the678result as an error */679if (space[i].iov_len == 0)680continue;681682ERR_clear_error();683r = SSL_write(bev_ssl->ssl, space[i].iov_base,684space[i].iov_len);685if (r > 0) {686result |= OP_MADE_PROGRESS;687if (bev_ssl->write_blocked_on_read)688if (clear_wbor(bev_ssl) < 0)689return OP_ERR | result;690n_written += r;691bev_ssl->last_write = -1;692decrement_buckets(bev_ssl);693} else {694int err = SSL_get_error(bev_ssl->ssl, r);695print_err(err);696switch (err) {697case SSL_ERROR_WANT_WRITE:698/* Can't read until underlying has more data. */699if (bev_ssl->write_blocked_on_read)700if (clear_wbor(bev_ssl) < 0)701return OP_ERR | result;702bev_ssl->last_write = space[i].iov_len;703break;704case SSL_ERROR_WANT_READ:705/* This read operation requires a write, and the706* underlying is full */707if (!bev_ssl->write_blocked_on_read)708if (set_wbor(bev_ssl) < 0)709return OP_ERR | result;710bev_ssl->last_write = space[i].iov_len;711break;712default:713conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r);714bev_ssl->last_write = -1;715break;716}717result |= OP_BLOCKED;718break;719}720}721if (n_written) {722evbuffer_drain(output, n_written);723if (bev_ssl->underlying)724BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);725726bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS);727}728return result;729}730731#define WRITE_FRAME 15000732733#define READ_DEFAULT 4096734735/* Try to figure out how many bytes to read; return 0 if we shouldn't be736* reading. */737static int738bytes_to_read(struct bufferevent_openssl *bev)739{740struct evbuffer *input = bev->bev.bev.input;741struct event_watermark *wm = &bev->bev.bev.wm_read;742int result = READ_DEFAULT;743ev_ssize_t limit;744/* XXX 99% of this is generic code that nearly all bufferevents will745* want. */746747if (bev->write_blocked_on_read) {748return 0;749}750751if (! (bev->bev.bev.enabled & EV_READ)) {752return 0;753}754755if (bev->bev.read_suspended) {756return 0;757}758759if (wm->high) {760if (evbuffer_get_length(input) >= wm->high) {761return 0;762}763764result = wm->high - evbuffer_get_length(input);765} else {766result = READ_DEFAULT;767}768769/* Respect the rate limit */770limit = bufferevent_get_read_max_(&bev->bev);771if (result > limit) {772result = limit;773}774775return result;776}777778779/* Things look readable. If write is blocked on read, write till it isn't.780* Read from the underlying buffer until we block or we hit our high-water781* mark.782*/783static void784consider_reading(struct bufferevent_openssl *bev_ssl)785{786int r;787int n_to_read;788int all_result_flags = 0;789790while (bev_ssl->write_blocked_on_read) {791r = do_write(bev_ssl, WRITE_FRAME);792if (r & (OP_BLOCKED|OP_ERR))793break;794}795if (bev_ssl->write_blocked_on_read)796return;797798n_to_read = bytes_to_read(bev_ssl);799800while (n_to_read) {801r = do_read(bev_ssl, n_to_read);802all_result_flags |= r;803804if (r & (OP_BLOCKED|OP_ERR))805break;806807if (bev_ssl->bev.read_suspended)808break;809810/* Read all pending data. This won't hit the network811* again, and will (most importantly) put us in a state812* where we don't need to read anything else until the813* socket is readable again. It'll potentially make us814* overrun our read high-watermark (somewhat815* regrettable). The damage to the rate-limit has816* already been done, since OpenSSL went and read a817* whole SSL record anyway. */818n_to_read = SSL_pending(bev_ssl->ssl);819820/* XXX This if statement is actually a bad bug, added to avoid821* XXX a worse bug.822*823* The bad bug: It can potentially cause resource unfairness824* by reading too much data from the underlying bufferevent;825* it can potentially cause read looping if the underlying826* bufferevent is a bufferevent_pair and deferred callbacks827* aren't used.828*829* The worse bug: If we didn't do this, then we would830* potentially not read any more from bev_ssl->underlying831* until more data arrived there, which could lead to us832* waiting forever.833*/834if (!n_to_read && bev_ssl->underlying)835n_to_read = bytes_to_read(bev_ssl);836}837838if (all_result_flags & OP_MADE_PROGRESS) {839struct bufferevent *bev = &bev_ssl->bev.bev;840841bufferevent_trigger_nolock_(bev, EV_READ, 0);842}843844if (!bev_ssl->underlying) {845/* Should be redundant, but let's avoid busy-looping */846if (bev_ssl->bev.read_suspended ||847!(bev_ssl->bev.bev.enabled & EV_READ)) {848event_del(&bev_ssl->bev.bev.ev_read);849}850}851}852853static void854consider_writing(struct bufferevent_openssl *bev_ssl)855{856int r;857struct evbuffer *output = bev_ssl->bev.bev.output;858struct evbuffer *target = NULL;859struct event_watermark *wm = NULL;860861while (bev_ssl->read_blocked_on_write) {862r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */863if (r & OP_MADE_PROGRESS) {864struct bufferevent *bev = &bev_ssl->bev.bev;865866bufferevent_trigger_nolock_(bev, EV_READ, 0);867}868if (r & (OP_ERR|OP_BLOCKED))869break;870}871if (bev_ssl->read_blocked_on_write)872return;873if (bev_ssl->underlying) {874target = bev_ssl->underlying->output;875wm = &bev_ssl->underlying->wm_write;876}877while ((bev_ssl->bev.bev.enabled & EV_WRITE) &&878(! bev_ssl->bev.write_suspended) &&879evbuffer_get_length(output) &&880(!target || (! wm->high || evbuffer_get_length(target) < wm->high))) {881int n_to_write;882if (wm && wm->high)883n_to_write = wm->high - evbuffer_get_length(target);884else885n_to_write = WRITE_FRAME;886r = do_write(bev_ssl, n_to_write);887if (r & (OP_BLOCKED|OP_ERR))888break;889}890891if (!bev_ssl->underlying) {892if (evbuffer_get_length(output) == 0) {893event_del(&bev_ssl->bev.bev.ev_write);894} else if (bev_ssl->bev.write_suspended ||895!(bev_ssl->bev.bev.enabled & EV_WRITE)) {896/* Should be redundant, but let's avoid busy-looping */897event_del(&bev_ssl->bev.bev.ev_write);898}899}900}901902static void903be_openssl_readcb(struct bufferevent *bev_base, void *ctx)904{905struct bufferevent_openssl *bev_ssl = ctx;906consider_reading(bev_ssl);907}908909static void910be_openssl_writecb(struct bufferevent *bev_base, void *ctx)911{912struct bufferevent_openssl *bev_ssl = ctx;913consider_writing(bev_ssl);914}915916static void917be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)918{919struct bufferevent_openssl *bev_ssl = ctx;920int event = 0;921922if (what & BEV_EVENT_EOF) {923if (bev_ssl->allow_dirty_shutdown)924event = BEV_EVENT_EOF;925else926event = BEV_EVENT_ERROR;927} else if (what & BEV_EVENT_TIMEOUT) {928/* We sure didn't set this. Propagate it to the user. */929event = what;930} else if (what & BEV_EVENT_ERROR) {931/* An error occurred on the connection. Propagate it to the user. */932event = what;933} else if (what & BEV_EVENT_CONNECTED) {934/* Ignore it. We're saying SSL_connect() already, which will935eat it. */936}937if (event)938bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0);939}940941static void942be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr)943{944struct bufferevent_openssl *bev_ssl = ptr;945bufferevent_incref_and_lock_(&bev_ssl->bev.bev);946if (what == EV_TIMEOUT) {947bufferevent_run_eventcb_(&bev_ssl->bev.bev,948BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0);949} else {950consider_reading(bev_ssl);951}952bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);953}954955static void956be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)957{958struct bufferevent_openssl *bev_ssl = ptr;959bufferevent_incref_and_lock_(&bev_ssl->bev.bev);960if (what == EV_TIMEOUT) {961bufferevent_run_eventcb_(&bev_ssl->bev.bev,962BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0);963} else {964consider_writing(bev_ssl);965}966bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);967}968969static evutil_socket_t970be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)971{972if (!bev_ssl->underlying) {973struct bufferevent *bev = &bev_ssl->bev.bev;974if (event_initialized(&bev->ev_read) && fd < 0) {975fd = event_get_fd(&bev->ev_read);976}977}978return fd;979}980981static int982set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)983{984if (bev_ssl->underlying) {985bufferevent_setcb(bev_ssl->underlying,986be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,987bev_ssl);988return 0;989} else {990struct bufferevent *bev = &bev_ssl->bev.bev;991int rpending=0, wpending=0, r1=0, r2=0;992993if (event_initialized(&bev->ev_read)) {994rpending = event_pending(&bev->ev_read, EV_READ, NULL);995wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);996997event_del(&bev->ev_read);998event_del(&bev->ev_write);999}10001001event_assign(&bev->ev_read, bev->ev_base, fd,1002EV_READ|EV_PERSIST|EV_FINALIZE,1003be_openssl_readeventcb, bev_ssl);1004event_assign(&bev->ev_write, bev->ev_base, fd,1005EV_WRITE|EV_PERSIST|EV_FINALIZE,1006be_openssl_writeeventcb, bev_ssl);10071008if (rpending)1009r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);1010if (wpending)1011r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);10121013return (r1<0 || r2<0) ? -1 : 0;1014}1015}10161017static int1018do_handshake(struct bufferevent_openssl *bev_ssl)1019{1020int r;10211022switch (bev_ssl->state) {1023default:1024case BUFFEREVENT_SSL_OPEN:1025EVUTIL_ASSERT(0);1026return -1;1027case BUFFEREVENT_SSL_CONNECTING:1028case BUFFEREVENT_SSL_ACCEPTING:1029ERR_clear_error();1030r = SSL_do_handshake(bev_ssl->ssl);1031break;1032}1033decrement_buckets(bev_ssl);10341035if (r==1) {1036evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read);1037/* We're done! */1038bev_ssl->state = BUFFEREVENT_SSL_OPEN;1039set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */1040/* Call do_read and do_write as needed */1041bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);1042bufferevent_run_eventcb_(&bev_ssl->bev.bev,1043BEV_EVENT_CONNECTED, 0);1044return 1;1045} else {1046int err = SSL_get_error(bev_ssl->ssl, r);1047print_err(err);1048switch (err) {1049case SSL_ERROR_WANT_WRITE:1050stop_reading(bev_ssl);1051return start_writing(bev_ssl);1052case SSL_ERROR_WANT_READ:1053stop_writing(bev_ssl);1054return start_reading(bev_ssl);1055default:1056conn_closed(bev_ssl, BEV_EVENT_READING, err, r);1057return -1;1058}1059}1060}10611062static void1063be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)1064{1065struct bufferevent_openssl *bev_ssl = ctx;1066do_handshake(bev_ssl);/* XXX handle failure */1067}10681069static void1070be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)1071{1072struct bufferevent_openssl *bev_ssl = ptr;10731074bufferevent_incref_and_lock_(&bev_ssl->bev.bev);1075if (what & EV_TIMEOUT) {1076bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0);1077} else1078do_handshake(bev_ssl);/* XXX handle failure */1079bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);1080}10811082static int1083set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)1084{1085if (bev_ssl->underlying) {1086bufferevent_setcb(bev_ssl->underlying,1087be_openssl_handshakecb, be_openssl_handshakecb,1088be_openssl_eventcb,1089bev_ssl);10901091if (fd < 0)1092return 0;10931094if (bufferevent_setfd(bev_ssl->underlying, fd))1095return 1;10961097return do_handshake(bev_ssl);1098} else {1099struct bufferevent *bev = &bev_ssl->bev.bev;11001101if (event_initialized(&bev->ev_read)) {1102event_del(&bev->ev_read);1103event_del(&bev->ev_write);1104}11051106event_assign(&bev->ev_read, bev->ev_base, fd,1107EV_READ|EV_PERSIST|EV_FINALIZE,1108be_openssl_handshakeeventcb, bev_ssl);1109event_assign(&bev->ev_write, bev->ev_base, fd,1110EV_WRITE|EV_PERSIST|EV_FINALIZE,1111be_openssl_handshakeeventcb, bev_ssl);1112if (fd >= 0)1113bufferevent_enable(bev, bev->enabled);1114return 0;1115}1116}11171118int1119bufferevent_ssl_renegotiate(struct bufferevent *bev)1120{1121struct bufferevent_openssl *bev_ssl = upcast(bev);1122if (!bev_ssl)1123return -1;1124if (SSL_renegotiate(bev_ssl->ssl) < 0)1125return -1;1126bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;1127if (set_handshake_callbacks(bev_ssl, be_openssl_auto_fd(bev_ssl, -1)) < 0)1128return -1;1129if (!bev_ssl->underlying)1130return do_handshake(bev_ssl);1131return 0;1132}11331134static void1135be_openssl_outbuf_cb(struct evbuffer *buf,1136const struct evbuffer_cb_info *cbinfo, void *arg)1137{1138struct bufferevent_openssl *bev_ssl = arg;1139int r = 0;1140/* XXX need to hold a reference here. */11411142if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {1143if (cbinfo->orig_size == 0)1144r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,1145&bev_ssl->bev.bev.timeout_write);11461147if (bev_ssl->underlying)1148consider_writing(bev_ssl);1149}1150/* XXX Handle r < 0 */1151(void)r;1152}115311541155static int1156be_openssl_enable(struct bufferevent *bev, short events)1157{1158struct bufferevent_openssl *bev_ssl = upcast(bev);1159int r1 = 0, r2 = 0;11601161if (events & EV_READ)1162r1 = start_reading(bev_ssl);1163if (events & EV_WRITE)1164r2 = start_writing(bev_ssl);11651166if (bev_ssl->underlying) {1167if (events & EV_READ)1168BEV_RESET_GENERIC_READ_TIMEOUT(bev);1169if (events & EV_WRITE)1170BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);11711172if (events & EV_READ)1173consider_reading(bev_ssl);1174if (events & EV_WRITE)1175consider_writing(bev_ssl);1176}1177return (r1 < 0 || r2 < 0) ? -1 : 0;1178}11791180static int1181be_openssl_disable(struct bufferevent *bev, short events)1182{1183struct bufferevent_openssl *bev_ssl = upcast(bev);11841185if (events & EV_READ)1186stop_reading(bev_ssl);1187if (events & EV_WRITE)1188stop_writing(bev_ssl);11891190if (bev_ssl->underlying) {1191if (events & EV_READ)1192BEV_DEL_GENERIC_READ_TIMEOUT(bev);1193if (events & EV_WRITE)1194BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);1195}1196return 0;1197}11981199static void1200be_openssl_unlink(struct bufferevent *bev)1201{1202struct bufferevent_openssl *bev_ssl = upcast(bev);12031204if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {1205if (bev_ssl->underlying) {1206if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) {1207event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "1208"bufferevent with too few references");1209} else {1210bufferevent_free(bev_ssl->underlying);1211/* We still have a reference to it, via our1212* BIO. So we don't drop this. */1213// bev_ssl->underlying = NULL;1214}1215}1216} else {1217if (bev_ssl->underlying) {1218if (bev_ssl->underlying->errorcb == be_openssl_eventcb)1219bufferevent_setcb(bev_ssl->underlying,1220NULL,NULL,NULL,NULL);1221bufferevent_unsuspend_read_(bev_ssl->underlying,1222BEV_SUSPEND_FILT_READ);1223}1224}1225}12261227static void1228be_openssl_destruct(struct bufferevent *bev)1229{1230struct bufferevent_openssl *bev_ssl = upcast(bev);12311232if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {1233if (! bev_ssl->underlying) {1234evutil_socket_t fd = EVUTIL_INVALID_SOCKET;1235BIO *bio = SSL_get_wbio(bev_ssl->ssl);1236if (bio)1237fd = BIO_get_fd(bio, NULL);1238if (fd >= 0)1239evutil_closesocket(fd);1240}1241SSL_free(bev_ssl->ssl);1242}1243}12441245static int1246be_openssl_adj_timeouts(struct bufferevent *bev)1247{1248struct bufferevent_openssl *bev_ssl = upcast(bev);12491250if (bev_ssl->underlying) {1251return bufferevent_generic_adj_timeouts_(bev);1252} else {1253return bufferevent_generic_adj_existing_timeouts_(bev);1254}1255}12561257static int1258be_openssl_flush(struct bufferevent *bufev,1259short iotype, enum bufferevent_flush_mode mode)1260{1261/* XXXX Implement this. */1262return 0;1263}12641265static int1266be_openssl_set_fd(struct bufferevent_openssl *bev_ssl,1267enum bufferevent_ssl_state state, evutil_socket_t fd)1268{1269bev_ssl->state = state;12701271switch (state) {1272case BUFFEREVENT_SSL_ACCEPTING:1273if (!SSL_clear(bev_ssl->ssl))1274return -1;1275SSL_set_accept_state(bev_ssl->ssl);1276if (set_handshake_callbacks(bev_ssl, fd) < 0)1277return -1;1278break;1279case BUFFEREVENT_SSL_CONNECTING:1280if (!SSL_clear(bev_ssl->ssl))1281return -1;1282SSL_set_connect_state(bev_ssl->ssl);1283if (set_handshake_callbacks(bev_ssl, fd) < 0)1284return -1;1285break;1286case BUFFEREVENT_SSL_OPEN:1287if (set_open_callbacks(bev_ssl, fd) < 0)1288return -1;1289break;1290default:1291return -1;1292}12931294return 0;1295}12961297static int1298be_openssl_ctrl(struct bufferevent *bev,1299enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data)1300{1301struct bufferevent_openssl *bev_ssl = upcast(bev);1302switch (op) {1303case BEV_CTRL_SET_FD:1304if (!bev_ssl->underlying) {1305BIO *bio;1306bio = BIO_new_socket((int)data->fd, 0);1307SSL_set_bio(bev_ssl->ssl, bio, bio);1308} else {1309BIO *bio;1310if (!(bio = BIO_new_bufferevent(bev_ssl->underlying)))1311return -1;1312SSL_set_bio(bev_ssl->ssl, bio, bio);1313}13141315return be_openssl_set_fd(bev_ssl, bev_ssl->old_state, data->fd);1316case BEV_CTRL_GET_FD:1317if (bev_ssl->underlying) {1318data->fd = event_get_fd(&bev_ssl->underlying->ev_read);1319} else {1320data->fd = event_get_fd(&bev->ev_read);1321}1322return 0;1323case BEV_CTRL_GET_UNDERLYING:1324data->ptr = bev_ssl->underlying;1325return 0;1326case BEV_CTRL_CANCEL_ALL:1327default:1328return -1;1329}1330}13311332SSL *1333bufferevent_openssl_get_ssl(struct bufferevent *bufev)1334{1335struct bufferevent_openssl *bev_ssl = upcast(bufev);1336if (!bev_ssl)1337return NULL;1338return bev_ssl->ssl;1339}13401341static struct bufferevent *1342bufferevent_openssl_new_impl(struct event_base *base,1343struct bufferevent *underlying,1344evutil_socket_t fd,1345SSL *ssl,1346enum bufferevent_ssl_state state,1347int options)1348{1349struct bufferevent_openssl *bev_ssl = NULL;1350struct bufferevent_private *bev_p = NULL;1351int tmp_options = options & ~BEV_OPT_THREADSAFE;13521353/* Only one can be set. */1354if (underlying != NULL && fd >= 0)1355goto err;13561357if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))1358goto err;13591360bev_p = &bev_ssl->bev;13611362if (bufferevent_init_common_(bev_p, base,1363&bufferevent_ops_openssl, tmp_options) < 0)1364goto err;13651366/* Don't explode if we decide to realloc a chunk we're writing from in1367* the output buffer. */1368SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);13691370bev_ssl->underlying = underlying;1371bev_ssl->ssl = ssl;13721373bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output,1374be_openssl_outbuf_cb, bev_ssl);13751376if (options & BEV_OPT_THREADSAFE)1377bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL);13781379if (underlying) {1380bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev);1381bufferevent_incref_(underlying);1382}13831384bev_ssl->old_state = state;1385bev_ssl->last_write = -1;13861387init_bio_counts(bev_ssl);13881389fd = be_openssl_auto_fd(bev_ssl, fd);1390if (be_openssl_set_fd(bev_ssl, state, fd))1391goto err;13921393if (underlying) {1394bufferevent_setwatermark(underlying, EV_READ, 0, 0);1395bufferevent_enable(underlying, EV_READ|EV_WRITE);1396if (state == BUFFEREVENT_SSL_OPEN)1397bufferevent_suspend_read_(underlying,1398BEV_SUSPEND_FILT_READ);1399}14001401return &bev_ssl->bev.bev;1402err:1403if (options & BEV_OPT_CLOSE_ON_FREE)1404SSL_free(ssl);1405if (bev_ssl) {1406bev_ssl->ssl = NULL;1407bufferevent_free(&bev_ssl->bev.bev);1408}1409return NULL;1410}14111412struct bufferevent *1413bufferevent_openssl_filter_new(struct event_base *base,1414struct bufferevent *underlying,1415SSL *ssl,1416enum bufferevent_ssl_state state,1417int options)1418{1419BIO *bio;1420struct bufferevent *bev;14211422if (!underlying)1423goto err;1424if (!(bio = BIO_new_bufferevent(underlying)))1425goto err;14261427SSL_set_bio(ssl, bio, bio);14281429bev = bufferevent_openssl_new_impl(1430base, underlying, -1, ssl, state, options);1431return bev;14321433err:1434if (options & BEV_OPT_CLOSE_ON_FREE)1435SSL_free(ssl);1436return NULL;1437}14381439struct bufferevent *1440bufferevent_openssl_socket_new(struct event_base *base,1441evutil_socket_t fd,1442SSL *ssl,1443enum bufferevent_ssl_state state,1444int options)1445{1446/* Does the SSL already have an fd? */1447BIO *bio = SSL_get_wbio(ssl);1448long have_fd = -1;14491450if (bio)1451have_fd = BIO_get_fd(bio, NULL);14521453if (have_fd >= 0) {1454/* The SSL is already configured with an fd. */1455if (fd < 0) {1456/* We should learn the fd from the SSL. */1457fd = (evutil_socket_t) have_fd;1458} else if (have_fd == (long)fd) {1459/* We already know the fd from the SSL; do nothing */1460} else {1461/* We specified an fd different from that of the SSL.1462This is probably an error on our part. Fail. */1463goto err;1464}1465BIO_set_close(bio, 0);1466} else {1467/* The SSL isn't configured with a BIO with an fd. */1468if (fd >= 0) {1469/* ... and we have an fd we want to use. */1470bio = BIO_new_socket((int)fd, 0);1471SSL_set_bio(ssl, bio, bio);1472} else {1473/* Leave the fd unset. */1474}1475}14761477return bufferevent_openssl_new_impl(1478base, NULL, fd, ssl, state, options);14791480err:1481if (options & BEV_OPT_CLOSE_ON_FREE)1482SSL_free(ssl);1483return NULL;1484}14851486int1487bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev)1488{1489int allow_dirty_shutdown = -1;1490struct bufferevent_openssl *bev_ssl;1491BEV_LOCK(bev);1492bev_ssl = upcast(bev);1493if (bev_ssl)1494allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown;1495BEV_UNLOCK(bev);1496return allow_dirty_shutdown;1497}14981499void1500bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,1501int allow_dirty_shutdown)1502{1503struct bufferevent_openssl *bev_ssl;1504BEV_LOCK(bev);1505bev_ssl = upcast(bev);1506if (bev_ssl)1507bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown;1508BEV_UNLOCK(bev);1509}15101511unsigned long1512bufferevent_get_openssl_error(struct bufferevent *bev)1513{1514unsigned long err = 0;1515struct bufferevent_openssl *bev_ssl;1516BEV_LOCK(bev);1517bev_ssl = upcast(bev);1518if (bev_ssl && bev_ssl->n_errors) {1519err = bev_ssl->errors[--bev_ssl->n_errors];1520}1521BEV_UNLOCK(bev);1522return err;1523}152415251526