1290001Sglebius/* 2290001Sglebius * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 3290001Sglebius * 4290001Sglebius * Redistribution and use in source and binary forms, with or without 5290001Sglebius * modification, are permitted provided that the following conditions 6290001Sglebius * are met: 7290001Sglebius * 1. Redistributions of source code must retain the above copyright 8290001Sglebius * notice, this list of conditions and the following disclaimer. 9290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer in the 11290001Sglebius * documentation and/or other materials provided with the distribution. 12290001Sglebius * 3. The name of the author may not be used to endorse or promote products 13290001Sglebius * derived from this software without specific prior written permission. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25290001Sglebius */ 26290001Sglebius 27290001Sglebius// Get rid of OSX 10.7 and greater deprecation warnings. 28290001Sglebius#if defined(__APPLE__) && defined(__clang__) 29290001Sglebius#pragma clang diagnostic ignored "-Wdeprecated-declarations" 30290001Sglebius#endif 31290001Sglebius 32290001Sglebius#include "event2/event-config.h" 33290001Sglebius#include "evconfig-private.h" 34290001Sglebius 35290001Sglebius#include <sys/types.h> 36290001Sglebius 37290001Sglebius#ifdef EVENT__HAVE_SYS_TIME_H 38290001Sglebius#include <sys/time.h> 39290001Sglebius#endif 40290001Sglebius 41290001Sglebius#include <errno.h> 42290001Sglebius#include <stdio.h> 43290001Sglebius#include <stdlib.h> 44290001Sglebius#include <string.h> 45290001Sglebius#ifdef EVENT__HAVE_STDARG_H 46290001Sglebius#include <stdarg.h> 47290001Sglebius#endif 48290001Sglebius#ifdef EVENT__HAVE_UNISTD_H 49290001Sglebius#include <unistd.h> 50290001Sglebius#endif 51290001Sglebius 52290001Sglebius#ifdef _WIN32 53290001Sglebius#include <winsock2.h> 54290001Sglebius#endif 55290001Sglebius 56290001Sglebius#include "event2/bufferevent.h" 57290001Sglebius#include "event2/bufferevent_struct.h" 58290001Sglebius#include "event2/bufferevent_ssl.h" 59290001Sglebius#include "event2/buffer.h" 60290001Sglebius#include "event2/event.h" 61290001Sglebius 62290001Sglebius#include "mm-internal.h" 63290001Sglebius#include "bufferevent-internal.h" 64290001Sglebius#include "log-internal.h" 65290001Sglebius 66290001Sglebius#include <openssl/bio.h> 67290001Sglebius#include <openssl/ssl.h> 68290001Sglebius#include <openssl/err.h> 69290001Sglebius 70290001Sglebius/* 71290001Sglebius * Define an OpenSSL bio that targets a bufferevent. 72290001Sglebius */ 73290001Sglebius 74290001Sglebius/* -------------------- 75290001Sglebius A BIO is an OpenSSL abstraction that handles reading and writing data. The 76290001Sglebius library will happily speak SSL over anything that implements a BIO 77290001Sglebius interface. 78290001Sglebius 79290001Sglebius Here we define a BIO implementation that directs its output to a 80290001Sglebius bufferevent. We'll want to use this only when none of OpenSSL's built-in 81290001Sglebius IO mechanisms work for us. 82290001Sglebius -------------------- */ 83290001Sglebius 84290001Sglebius/* every BIO type needs its own integer type value. */ 85290001Sglebius#define BIO_TYPE_LIBEVENT 57 86290001Sglebius/* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on 87290001Sglebius * this. */ 88290001Sglebius 89290001Sglebius#if 0 90290001Sglebiusstatic void 91290001Sglebiusprint_err(int val) 92290001Sglebius{ 93290001Sglebius int err; 94290001Sglebius printf("Error was %d\n", val); 95290001Sglebius 96290001Sglebius while ((err = ERR_get_error())) { 97290001Sglebius const char *msg = (const char*)ERR_reason_error_string(err); 98290001Sglebius const char *lib = (const char*)ERR_lib_error_string(err); 99290001Sglebius const char *func = (const char*)ERR_func_error_string(err); 100290001Sglebius 101290001Sglebius printf("%s in %s %s\n", msg, lib, func); 102290001Sglebius } 103290001Sglebius} 104290001Sglebius#else 105290001Sglebius#define print_err(v) ((void)0) 106290001Sglebius#endif 107290001Sglebius 108290001Sglebius/* Called to initialize a new BIO */ 109290001Sglebiusstatic int 110290001Sglebiusbio_bufferevent_new(BIO *b) 111290001Sglebius{ 112290001Sglebius b->init = 0; 113290001Sglebius b->num = -1; 114290001Sglebius b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/ 115290001Sglebius b->flags = 0; 116290001Sglebius return 1; 117290001Sglebius} 118290001Sglebius 119290001Sglebius/* Called to uninitialize the BIO. */ 120290001Sglebiusstatic int 121290001Sglebiusbio_bufferevent_free(BIO *b) 122290001Sglebius{ 123290001Sglebius if (!b) 124290001Sglebius return 0; 125290001Sglebius if (b->shutdown) { 126290001Sglebius if (b->init && b->ptr) 127290001Sglebius bufferevent_free(b->ptr); 128290001Sglebius b->init = 0; 129290001Sglebius b->flags = 0; 130290001Sglebius b->ptr = NULL; 131290001Sglebius } 132290001Sglebius return 1; 133290001Sglebius} 134290001Sglebius 135290001Sglebius/* Called to extract data from the BIO. */ 136290001Sglebiusstatic int 137290001Sglebiusbio_bufferevent_read(BIO *b, char *out, int outlen) 138290001Sglebius{ 139290001Sglebius int r = 0; 140290001Sglebius struct evbuffer *input; 141290001Sglebius 142290001Sglebius BIO_clear_retry_flags(b); 143290001Sglebius 144290001Sglebius if (!out) 145290001Sglebius return 0; 146290001Sglebius if (!b->ptr) 147290001Sglebius return -1; 148290001Sglebius 149290001Sglebius input = bufferevent_get_input(b->ptr); 150290001Sglebius if (evbuffer_get_length(input) == 0) { 151290001Sglebius /* If there's no data to read, say so. */ 152290001Sglebius BIO_set_retry_read(b); 153290001Sglebius return -1; 154290001Sglebius } else { 155290001Sglebius r = evbuffer_remove(input, out, outlen); 156290001Sglebius } 157290001Sglebius 158290001Sglebius return r; 159290001Sglebius} 160290001Sglebius 161290001Sglebius/* Called to write data info the BIO */ 162290001Sglebiusstatic int 163290001Sglebiusbio_bufferevent_write(BIO *b, const char *in, int inlen) 164290001Sglebius{ 165290001Sglebius struct bufferevent *bufev = b->ptr; 166290001Sglebius struct evbuffer *output; 167290001Sglebius size_t outlen; 168290001Sglebius 169290001Sglebius BIO_clear_retry_flags(b); 170290001Sglebius 171290001Sglebius if (!b->ptr) 172290001Sglebius return -1; 173290001Sglebius 174290001Sglebius output = bufferevent_get_output(bufev); 175290001Sglebius outlen = evbuffer_get_length(output); 176290001Sglebius 177290001Sglebius /* Copy only as much data onto the output buffer as can fit under the 178290001Sglebius * high-water mark. */ 179290001Sglebius if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) { 180290001Sglebius if (bufev->wm_write.high <= outlen) { 181290001Sglebius /* If no data can fit, we'll need to retry later. */ 182290001Sglebius BIO_set_retry_write(b); 183290001Sglebius return -1; 184290001Sglebius } 185290001Sglebius inlen = bufev->wm_write.high - outlen; 186290001Sglebius } 187290001Sglebius 188290001Sglebius EVUTIL_ASSERT(inlen > 0); 189290001Sglebius evbuffer_add(output, in, inlen); 190290001Sglebius return inlen; 191290001Sglebius} 192290001Sglebius 193290001Sglebius/* Called to handle various requests */ 194290001Sglebiusstatic long 195290001Sglebiusbio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr) 196290001Sglebius{ 197290001Sglebius struct bufferevent *bufev = b->ptr; 198290001Sglebius long ret = 1; 199290001Sglebius 200290001Sglebius switch (cmd) { 201290001Sglebius case BIO_CTRL_GET_CLOSE: 202290001Sglebius ret = b->shutdown; 203290001Sglebius break; 204290001Sglebius case BIO_CTRL_SET_CLOSE: 205290001Sglebius b->shutdown = (int)num; 206290001Sglebius break; 207290001Sglebius case BIO_CTRL_PENDING: 208290001Sglebius ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0; 209290001Sglebius break; 210290001Sglebius case BIO_CTRL_WPENDING: 211290001Sglebius ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0; 212290001Sglebius break; 213290001Sglebius /* XXXX These two are given a special-case treatment because 214290001Sglebius * of cargo-cultism. I should come up with a better reason. */ 215290001Sglebius case BIO_CTRL_DUP: 216290001Sglebius case BIO_CTRL_FLUSH: 217290001Sglebius ret = 1; 218290001Sglebius break; 219290001Sglebius default: 220290001Sglebius ret = 0; 221290001Sglebius break; 222290001Sglebius } 223290001Sglebius return ret; 224290001Sglebius} 225290001Sglebius 226290001Sglebius/* Called to write a string to the BIO */ 227290001Sglebiusstatic int 228290001Sglebiusbio_bufferevent_puts(BIO *b, const char *s) 229290001Sglebius{ 230290001Sglebius return bio_bufferevent_write(b, s, strlen(s)); 231290001Sglebius} 232290001Sglebius 233290001Sglebius/* Method table for the bufferevent BIO */ 234290001Sglebiusstatic BIO_METHOD methods_bufferevent = { 235290001Sglebius BIO_TYPE_LIBEVENT, "bufferevent", 236290001Sglebius bio_bufferevent_write, 237290001Sglebius bio_bufferevent_read, 238290001Sglebius bio_bufferevent_puts, 239290001Sglebius NULL /* bio_bufferevent_gets */, 240290001Sglebius bio_bufferevent_ctrl, 241290001Sglebius bio_bufferevent_new, 242290001Sglebius bio_bufferevent_free, 243290001Sglebius NULL /* callback_ctrl */, 244290001Sglebius}; 245290001Sglebius 246290001Sglebius/* Return the method table for the bufferevents BIO */ 247290001Sglebiusstatic BIO_METHOD * 248290001SglebiusBIO_s_bufferevent(void) 249290001Sglebius{ 250290001Sglebius return &methods_bufferevent; 251290001Sglebius} 252290001Sglebius 253290001Sglebius/* Create a new BIO to wrap communication around a bufferevent. If close_flag 254290001Sglebius * is true, the bufferevent will be freed when the BIO is closed. */ 255290001Sglebiusstatic BIO * 256290001SglebiusBIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag) 257290001Sglebius{ 258290001Sglebius BIO *result; 259290001Sglebius if (!bufferevent) 260290001Sglebius return NULL; 261290001Sglebius if (!(result = BIO_new(BIO_s_bufferevent()))) 262290001Sglebius return NULL; 263290001Sglebius result->init = 1; 264290001Sglebius result->ptr = bufferevent; 265290001Sglebius result->shutdown = close_flag ? 1 : 0; 266290001Sglebius return result; 267290001Sglebius} 268290001Sglebius 269290001Sglebius/* -------------------- 270290001Sglebius Now, here's the OpenSSL-based implementation of bufferevent. 271290001Sglebius 272290001Sglebius The implementation comes in two flavors: one that connects its SSL object 273290001Sglebius to an underlying bufferevent using a BIO_bufferevent, and one that has the 274290001Sglebius SSL object connect to a socket directly. The latter should generally be 275290001Sglebius faster, except on Windows, where your best bet is using a 276290001Sglebius bufferevent_async. 277290001Sglebius 278290001Sglebius (OpenSSL supports many other BIO types, too. But we can't use any unless 279290001Sglebius we have a good way to get notified when they become readable/writable.) 280290001Sglebius -------------------- */ 281290001Sglebius 282290001Sglebiusstruct bio_data_counts { 283290001Sglebius unsigned long n_written; 284290001Sglebius unsigned long n_read; 285290001Sglebius}; 286290001Sglebius 287290001Sglebiusstruct bufferevent_openssl { 288290001Sglebius /* Shared fields with common bufferevent implementation code. 289290001Sglebius If we were set up with an underlying bufferevent, we use the 290290001Sglebius events here as timers only. If we have an SSL, then we use 291290001Sglebius the events as socket events. 292290001Sglebius */ 293290001Sglebius struct bufferevent_private bev; 294290001Sglebius /* An underlying bufferevent that we're directing our output to. 295290001Sglebius If it's NULL, then we're connected to an fd, not an evbuffer. */ 296290001Sglebius struct bufferevent *underlying; 297290001Sglebius /* The SSL object doing our encryption. */ 298290001Sglebius SSL *ssl; 299290001Sglebius 300290001Sglebius /* A callback that's invoked when data arrives on our outbuf so we 301290001Sglebius know to write data to the SSL. */ 302290001Sglebius struct evbuffer_cb_entry *outbuf_cb; 303290001Sglebius 304290001Sglebius /* A count of how much data the bios have read/written total. Used 305290001Sglebius for rate-limiting. */ 306290001Sglebius struct bio_data_counts counts; 307290001Sglebius 308290001Sglebius /* If this value is greater than 0, then the last SSL_write blocked, 309290001Sglebius * and we need to try it again with this many bytes. */ 310290001Sglebius ev_ssize_t last_write; 311290001Sglebius 312290001Sglebius#define NUM_ERRORS 3 313290001Sglebius ev_uint32_t errors[NUM_ERRORS]; 314290001Sglebius 315290001Sglebius /* When we next get available space, we should say "read" instead of 316290001Sglebius "write". This can happen if there's a renegotiation during a read 317290001Sglebius operation. */ 318290001Sglebius unsigned read_blocked_on_write : 1; 319290001Sglebius /* When we next get data, we should say "write" instead of "read". */ 320290001Sglebius unsigned write_blocked_on_read : 1; 321290001Sglebius /* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */ 322290001Sglebius unsigned allow_dirty_shutdown : 1; 323290001Sglebius /* XXXX */ 324290001Sglebius unsigned fd_is_set : 1; 325290001Sglebius /* XXX */ 326290001Sglebius unsigned n_errors : 2; 327290001Sglebius 328290001Sglebius /* Are we currently connecting, accepting, or doing IO? */ 329290001Sglebius unsigned state : 2; 330290001Sglebius}; 331290001Sglebius 332290001Sglebiusstatic int be_openssl_enable(struct bufferevent *, short); 333290001Sglebiusstatic int be_openssl_disable(struct bufferevent *, short); 334290001Sglebiusstatic void be_openssl_unlink(struct bufferevent *); 335290001Sglebiusstatic void be_openssl_destruct(struct bufferevent *); 336290001Sglebiusstatic int be_openssl_adj_timeouts(struct bufferevent *); 337290001Sglebiusstatic int be_openssl_flush(struct bufferevent *bufev, 338290001Sglebius short iotype, enum bufferevent_flush_mode mode); 339290001Sglebiusstatic int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); 340290001Sglebius 341290001Sglebiusconst struct bufferevent_ops bufferevent_ops_openssl = { 342290001Sglebius "ssl", 343290001Sglebius evutil_offsetof(struct bufferevent_openssl, bev.bev), 344290001Sglebius be_openssl_enable, 345290001Sglebius be_openssl_disable, 346290001Sglebius be_openssl_unlink, 347290001Sglebius be_openssl_destruct, 348290001Sglebius be_openssl_adj_timeouts, 349290001Sglebius be_openssl_flush, 350290001Sglebius be_openssl_ctrl, 351290001Sglebius}; 352290001Sglebius 353290001Sglebius/* Given a bufferevent, return a pointer to the bufferevent_openssl that 354290001Sglebius * contains it, if any. */ 355290001Sglebiusstatic inline struct bufferevent_openssl * 356290001Sglebiusupcast(struct bufferevent *bev) 357290001Sglebius{ 358290001Sglebius struct bufferevent_openssl *bev_o; 359290001Sglebius if (bev->be_ops != &bufferevent_ops_openssl) 360290001Sglebius return NULL; 361290001Sglebius bev_o = (void*)( ((char*)bev) - 362290001Sglebius evutil_offsetof(struct bufferevent_openssl, bev.bev)); 363290001Sglebius EVUTIL_ASSERT(bev_o->bev.bev.be_ops == &bufferevent_ops_openssl); 364290001Sglebius return bev_o; 365290001Sglebius} 366290001Sglebius 367290001Sglebiusstatic inline void 368290001Sglebiusput_error(struct bufferevent_openssl *bev_ssl, unsigned long err) 369290001Sglebius{ 370290001Sglebius if (bev_ssl->n_errors == NUM_ERRORS) 371290001Sglebius return; 372290001Sglebius /* The error type according to openssl is "unsigned long", but 373290001Sglebius openssl never uses more than 32 bits of it. It _can't_ use more 374290001Sglebius than 32 bits of it, since it needs to report errors on systems 375290001Sglebius where long is only 32 bits. 376290001Sglebius */ 377290001Sglebius bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err; 378290001Sglebius} 379290001Sglebius 380290001Sglebius/* Have the base communications channel (either the underlying bufferevent or 381290001Sglebius * ev_read and ev_write) start reading. Take the read-blocked-on-write flag 382290001Sglebius * into account. */ 383290001Sglebiusstatic int 384290001Sglebiusstart_reading(struct bufferevent_openssl *bev_ssl) 385290001Sglebius{ 386290001Sglebius if (bev_ssl->underlying) { 387290001Sglebius bufferevent_unsuspend_read_(bev_ssl->underlying, 388290001Sglebius BEV_SUSPEND_FILT_READ); 389290001Sglebius return 0; 390290001Sglebius } else { 391290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 392290001Sglebius int r; 393290001Sglebius r = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); 394290001Sglebius if (r == 0 && bev_ssl->read_blocked_on_write) 395290001Sglebius r = bufferevent_add_event_(&bev->ev_write, 396290001Sglebius &bev->timeout_write); 397290001Sglebius return r; 398290001Sglebius } 399290001Sglebius} 400290001Sglebius 401290001Sglebius/* Have the base communications channel (either the underlying bufferevent or 402290001Sglebius * ev_read and ev_write) start writing. Take the write-blocked-on-read flag 403290001Sglebius * into account. */ 404290001Sglebiusstatic int 405290001Sglebiusstart_writing(struct bufferevent_openssl *bev_ssl) 406290001Sglebius{ 407290001Sglebius int r = 0; 408290001Sglebius if (bev_ssl->underlying) { 409290001Sglebius ; 410290001Sglebius } else { 411290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 412290001Sglebius r = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); 413290001Sglebius if (!r && bev_ssl->write_blocked_on_read) 414290001Sglebius r = bufferevent_add_event_(&bev->ev_read, 415290001Sglebius &bev->timeout_read); 416290001Sglebius } 417290001Sglebius return r; 418290001Sglebius} 419290001Sglebius 420290001Sglebiusstatic void 421290001Sglebiusstop_reading(struct bufferevent_openssl *bev_ssl) 422290001Sglebius{ 423290001Sglebius if (bev_ssl->write_blocked_on_read) 424290001Sglebius return; 425290001Sglebius if (bev_ssl->underlying) { 426290001Sglebius bufferevent_suspend_read_(bev_ssl->underlying, 427290001Sglebius BEV_SUSPEND_FILT_READ); 428290001Sglebius } else { 429290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 430290001Sglebius event_del(&bev->ev_read); 431290001Sglebius } 432290001Sglebius} 433290001Sglebius 434290001Sglebiusstatic void 435290001Sglebiusstop_writing(struct bufferevent_openssl *bev_ssl) 436290001Sglebius{ 437290001Sglebius if (bev_ssl->read_blocked_on_write) 438290001Sglebius return; 439290001Sglebius if (bev_ssl->underlying) { 440290001Sglebius ; 441290001Sglebius } else { 442290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 443290001Sglebius event_del(&bev->ev_write); 444290001Sglebius } 445290001Sglebius} 446290001Sglebius 447290001Sglebiusstatic int 448290001Sglebiusset_rbow(struct bufferevent_openssl *bev_ssl) 449290001Sglebius{ 450290001Sglebius if (!bev_ssl->underlying) 451290001Sglebius stop_reading(bev_ssl); 452290001Sglebius bev_ssl->read_blocked_on_write = 1; 453290001Sglebius return start_writing(bev_ssl); 454290001Sglebius} 455290001Sglebius 456290001Sglebiusstatic int 457290001Sglebiusset_wbor(struct bufferevent_openssl *bev_ssl) 458290001Sglebius{ 459290001Sglebius if (!bev_ssl->underlying) 460290001Sglebius stop_writing(bev_ssl); 461290001Sglebius bev_ssl->write_blocked_on_read = 1; 462290001Sglebius return start_reading(bev_ssl); 463290001Sglebius} 464290001Sglebius 465290001Sglebiusstatic int 466290001Sglebiusclear_rbow(struct bufferevent_openssl *bev_ssl) 467290001Sglebius{ 468290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 469290001Sglebius int r = 0; 470290001Sglebius bev_ssl->read_blocked_on_write = 0; 471290001Sglebius if (!(bev->enabled & EV_WRITE)) 472290001Sglebius stop_writing(bev_ssl); 473290001Sglebius if (bev->enabled & EV_READ) 474290001Sglebius r = start_reading(bev_ssl); 475290001Sglebius return r; 476290001Sglebius} 477290001Sglebius 478290001Sglebius 479290001Sglebiusstatic int 480290001Sglebiusclear_wbor(struct bufferevent_openssl *bev_ssl) 481290001Sglebius{ 482290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 483290001Sglebius int r = 0; 484290001Sglebius bev_ssl->write_blocked_on_read = 0; 485290001Sglebius if (!(bev->enabled & EV_READ)) 486290001Sglebius stop_reading(bev_ssl); 487290001Sglebius if (bev->enabled & EV_WRITE) 488290001Sglebius r = start_writing(bev_ssl); 489290001Sglebius return r; 490290001Sglebius} 491290001Sglebius 492290001Sglebiusstatic void 493290001Sglebiusconn_closed(struct bufferevent_openssl *bev_ssl, int when, int errcode, int ret) 494290001Sglebius{ 495290001Sglebius int event = BEV_EVENT_ERROR; 496290001Sglebius int dirty_shutdown = 0; 497290001Sglebius unsigned long err; 498290001Sglebius 499290001Sglebius switch (errcode) { 500290001Sglebius case SSL_ERROR_ZERO_RETURN: 501290001Sglebius /* Possibly a clean shutdown. */ 502290001Sglebius if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN) 503290001Sglebius event = BEV_EVENT_EOF; 504290001Sglebius else 505290001Sglebius dirty_shutdown = 1; 506290001Sglebius break; 507290001Sglebius case SSL_ERROR_SYSCALL: 508290001Sglebius /* IO error; possibly a dirty shutdown. */ 509290001Sglebius if (ret == 0 && ERR_peek_error() == 0) 510290001Sglebius dirty_shutdown = 1; 511290001Sglebius break; 512290001Sglebius case SSL_ERROR_SSL: 513290001Sglebius /* Protocol error. */ 514290001Sglebius break; 515290001Sglebius case SSL_ERROR_WANT_X509_LOOKUP: 516290001Sglebius /* XXXX handle this. */ 517290001Sglebius break; 518290001Sglebius case SSL_ERROR_NONE: 519290001Sglebius case SSL_ERROR_WANT_READ: 520290001Sglebius case SSL_ERROR_WANT_WRITE: 521290001Sglebius case SSL_ERROR_WANT_CONNECT: 522290001Sglebius case SSL_ERROR_WANT_ACCEPT: 523290001Sglebius default: 524290001Sglebius /* should be impossible; treat as normal error. */ 525290001Sglebius event_warnx("BUG: Unexpected OpenSSL error code %d", errcode); 526290001Sglebius break; 527290001Sglebius } 528290001Sglebius 529290001Sglebius while ((err = ERR_get_error())) { 530290001Sglebius put_error(bev_ssl, err); 531290001Sglebius } 532290001Sglebius 533290001Sglebius if (dirty_shutdown && bev_ssl->allow_dirty_shutdown) 534290001Sglebius event = BEV_EVENT_EOF; 535290001Sglebius 536290001Sglebius stop_reading(bev_ssl); 537290001Sglebius stop_writing(bev_ssl); 538290001Sglebius 539290001Sglebius /* when is BEV_EVENT_{READING|WRITING} */ 540290001Sglebius event = when | event; 541290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0); 542290001Sglebius} 543290001Sglebius 544290001Sglebiusstatic void 545290001Sglebiusinit_bio_counts(struct bufferevent_openssl *bev_ssl) 546290001Sglebius{ 547290001Sglebius bev_ssl->counts.n_written = 548290001Sglebius BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); 549290001Sglebius bev_ssl->counts.n_read = 550290001Sglebius BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); 551290001Sglebius} 552290001Sglebius 553290001Sglebiusstatic inline void 554290001Sglebiusdecrement_buckets(struct bufferevent_openssl *bev_ssl) 555290001Sglebius{ 556290001Sglebius unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl)); 557290001Sglebius unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl)); 558290001Sglebius /* These next two subtractions can wrap around. That's okay. */ 559290001Sglebius unsigned long w = num_w - bev_ssl->counts.n_written; 560290001Sglebius unsigned long r = num_r - bev_ssl->counts.n_read; 561290001Sglebius if (w) 562290001Sglebius bufferevent_decrement_write_buckets_(&bev_ssl->bev, w); 563290001Sglebius if (r) 564290001Sglebius bufferevent_decrement_read_buckets_(&bev_ssl->bev, r); 565290001Sglebius bev_ssl->counts.n_written = num_w; 566290001Sglebius bev_ssl->counts.n_read = num_r; 567290001Sglebius} 568290001Sglebius 569290001Sglebius#define OP_MADE_PROGRESS 1 570290001Sglebius#define OP_BLOCKED 2 571290001Sglebius#define OP_ERR 4 572290001Sglebius 573290001Sglebius/* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if 574290001Sglebius we're now blocked); and OP_ERR (if an error occurred). */ 575290001Sglebiusstatic int 576290001Sglebiusdo_read(struct bufferevent_openssl *bev_ssl, int n_to_read) { 577290001Sglebius /* Requires lock */ 578290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 579290001Sglebius struct evbuffer *input = bev->input; 580290001Sglebius int r, n, i, n_used = 0, atmost; 581290001Sglebius struct evbuffer_iovec space[2]; 582290001Sglebius int result = 0; 583290001Sglebius 584290001Sglebius if (bev_ssl->bev.read_suspended) 585290001Sglebius return 0; 586290001Sglebius 587290001Sglebius atmost = bufferevent_get_read_max_(&bev_ssl->bev); 588290001Sglebius if (n_to_read > atmost) 589290001Sglebius n_to_read = atmost; 590290001Sglebius 591290001Sglebius n = evbuffer_reserve_space(input, n_to_read, space, 2); 592290001Sglebius if (n < 0) 593290001Sglebius return OP_ERR; 594290001Sglebius 595290001Sglebius for (i=0; i<n; ++i) { 596290001Sglebius if (bev_ssl->bev.read_suspended) 597290001Sglebius break; 598290001Sglebius r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); 599290001Sglebius if (r>0) { 600290001Sglebius result |= OP_MADE_PROGRESS; 601290001Sglebius if (bev_ssl->read_blocked_on_write) 602290001Sglebius if (clear_rbow(bev_ssl) < 0) 603290001Sglebius return OP_ERR | result; 604290001Sglebius ++n_used; 605290001Sglebius space[i].iov_len = r; 606290001Sglebius decrement_buckets(bev_ssl); 607290001Sglebius } else { 608290001Sglebius int err = SSL_get_error(bev_ssl->ssl, r); 609290001Sglebius print_err(err); 610290001Sglebius switch (err) { 611290001Sglebius case SSL_ERROR_WANT_READ: 612290001Sglebius /* Can't read until underlying has more data. */ 613290001Sglebius if (bev_ssl->read_blocked_on_write) 614290001Sglebius if (clear_rbow(bev_ssl) < 0) 615290001Sglebius return OP_ERR | result; 616290001Sglebius break; 617290001Sglebius case SSL_ERROR_WANT_WRITE: 618290001Sglebius /* This read operation requires a write, and the 619290001Sglebius * underlying is full */ 620290001Sglebius if (!bev_ssl->read_blocked_on_write) 621290001Sglebius if (set_rbow(bev_ssl) < 0) 622290001Sglebius return OP_ERR | result; 623290001Sglebius break; 624290001Sglebius default: 625290001Sglebius conn_closed(bev_ssl, BEV_EVENT_READING, err, r); 626290001Sglebius break; 627290001Sglebius } 628290001Sglebius result |= OP_BLOCKED; 629290001Sglebius break; /* out of the loop */ 630290001Sglebius } 631290001Sglebius } 632290001Sglebius 633290001Sglebius if (n_used) { 634290001Sglebius evbuffer_commit_space(input, space, n_used); 635290001Sglebius if (bev_ssl->underlying) 636290001Sglebius BEV_RESET_GENERIC_READ_TIMEOUT(bev); 637290001Sglebius } 638290001Sglebius 639290001Sglebius return result; 640290001Sglebius} 641290001Sglebius 642290001Sglebius/* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if 643290001Sglebius we're now blocked); and OP_ERR (if an error occurred). */ 644290001Sglebiusstatic int 645290001Sglebiusdo_write(struct bufferevent_openssl *bev_ssl, int atmost) 646290001Sglebius{ 647290001Sglebius int i, r, n, n_written = 0; 648290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 649290001Sglebius struct evbuffer *output = bev->output; 650290001Sglebius struct evbuffer_iovec space[8]; 651290001Sglebius int result = 0; 652290001Sglebius 653290001Sglebius if (bev_ssl->last_write > 0) 654290001Sglebius atmost = bev_ssl->last_write; 655290001Sglebius else 656290001Sglebius atmost = bufferevent_get_write_max_(&bev_ssl->bev); 657290001Sglebius 658290001Sglebius n = evbuffer_peek(output, atmost, NULL, space, 8); 659290001Sglebius if (n < 0) 660290001Sglebius return OP_ERR | result; 661290001Sglebius 662290001Sglebius if (n > 8) 663290001Sglebius n = 8; 664290001Sglebius for (i=0; i < n; ++i) { 665290001Sglebius if (bev_ssl->bev.write_suspended) 666290001Sglebius break; 667290001Sglebius 668290001Sglebius /* SSL_write will (reasonably) return 0 if we tell it to 669290001Sglebius send 0 data. Skip this case so we don't interpret the 670290001Sglebius result as an error */ 671290001Sglebius if (space[i].iov_len == 0) 672290001Sglebius continue; 673290001Sglebius 674290001Sglebius r = SSL_write(bev_ssl->ssl, space[i].iov_base, 675290001Sglebius space[i].iov_len); 676290001Sglebius if (r > 0) { 677290001Sglebius result |= OP_MADE_PROGRESS; 678290001Sglebius if (bev_ssl->write_blocked_on_read) 679290001Sglebius if (clear_wbor(bev_ssl) < 0) 680290001Sglebius return OP_ERR | result; 681290001Sglebius n_written += r; 682290001Sglebius bev_ssl->last_write = -1; 683290001Sglebius decrement_buckets(bev_ssl); 684290001Sglebius } else { 685290001Sglebius int err = SSL_get_error(bev_ssl->ssl, r); 686290001Sglebius print_err(err); 687290001Sglebius switch (err) { 688290001Sglebius case SSL_ERROR_WANT_WRITE: 689290001Sglebius /* Can't read until underlying has more data. */ 690290001Sglebius if (bev_ssl->write_blocked_on_read) 691290001Sglebius if (clear_wbor(bev_ssl) < 0) 692290001Sglebius return OP_ERR | result; 693290001Sglebius bev_ssl->last_write = space[i].iov_len; 694290001Sglebius break; 695290001Sglebius case SSL_ERROR_WANT_READ: 696290001Sglebius /* This read operation requires a write, and the 697290001Sglebius * underlying is full */ 698290001Sglebius if (!bev_ssl->write_blocked_on_read) 699290001Sglebius if (set_wbor(bev_ssl) < 0) 700290001Sglebius return OP_ERR | result; 701290001Sglebius bev_ssl->last_write = space[i].iov_len; 702290001Sglebius break; 703290001Sglebius default: 704290001Sglebius conn_closed(bev_ssl, BEV_EVENT_WRITING, err, r); 705290001Sglebius bev_ssl->last_write = -1; 706290001Sglebius break; 707290001Sglebius } 708290001Sglebius result |= OP_BLOCKED; 709290001Sglebius break; 710290001Sglebius } 711290001Sglebius } 712290001Sglebius if (n_written) { 713290001Sglebius evbuffer_drain(output, n_written); 714290001Sglebius if (bev_ssl->underlying) 715290001Sglebius BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); 716290001Sglebius 717290001Sglebius bufferevent_trigger_nolock_(bev, EV_WRITE, 0); 718290001Sglebius } 719290001Sglebius return result; 720290001Sglebius} 721290001Sglebius 722290001Sglebius#define WRITE_FRAME 15000 723290001Sglebius 724290001Sglebius#define READ_DEFAULT 4096 725290001Sglebius 726290001Sglebius/* Try to figure out how many bytes to read; return 0 if we shouldn't be 727290001Sglebius * reading. */ 728290001Sglebiusstatic int 729290001Sglebiusbytes_to_read(struct bufferevent_openssl *bev) 730290001Sglebius{ 731290001Sglebius struct evbuffer *input = bev->bev.bev.input; 732290001Sglebius struct event_watermark *wm = &bev->bev.bev.wm_read; 733290001Sglebius int result = READ_DEFAULT; 734290001Sglebius ev_ssize_t limit; 735290001Sglebius /* XXX 99% of this is generic code that nearly all bufferevents will 736290001Sglebius * want. */ 737290001Sglebius 738290001Sglebius if (bev->write_blocked_on_read) { 739290001Sglebius return 0; 740290001Sglebius } 741290001Sglebius 742290001Sglebius if (! (bev->bev.bev.enabled & EV_READ)) { 743290001Sglebius return 0; 744290001Sglebius } 745290001Sglebius 746290001Sglebius if (bev->bev.read_suspended) { 747290001Sglebius return 0; 748290001Sglebius } 749290001Sglebius 750290001Sglebius if (wm->high) { 751290001Sglebius if (evbuffer_get_length(input) >= wm->high) { 752290001Sglebius return 0; 753290001Sglebius } 754290001Sglebius 755290001Sglebius result = wm->high - evbuffer_get_length(input); 756290001Sglebius } else { 757290001Sglebius result = READ_DEFAULT; 758290001Sglebius } 759290001Sglebius 760290001Sglebius /* Respect the rate limit */ 761290001Sglebius limit = bufferevent_get_read_max_(&bev->bev); 762290001Sglebius if (result > limit) { 763290001Sglebius result = limit; 764290001Sglebius } 765290001Sglebius 766290001Sglebius return result; 767290001Sglebius} 768290001Sglebius 769290001Sglebius 770290001Sglebius/* Things look readable. If write is blocked on read, write till it isn't. 771290001Sglebius * Read from the underlying buffer until we block or we hit our high-water 772290001Sglebius * mark. 773290001Sglebius */ 774290001Sglebiusstatic void 775290001Sglebiusconsider_reading(struct bufferevent_openssl *bev_ssl) 776290001Sglebius{ 777290001Sglebius int r; 778290001Sglebius int n_to_read; 779290001Sglebius int all_result_flags = 0; 780290001Sglebius 781290001Sglebius while (bev_ssl->write_blocked_on_read) { 782290001Sglebius r = do_write(bev_ssl, WRITE_FRAME); 783290001Sglebius if (r & (OP_BLOCKED|OP_ERR)) 784290001Sglebius break; 785290001Sglebius } 786290001Sglebius if (bev_ssl->write_blocked_on_read) 787290001Sglebius return; 788290001Sglebius 789290001Sglebius n_to_read = bytes_to_read(bev_ssl); 790290001Sglebius 791290001Sglebius while (n_to_read) { 792290001Sglebius r = do_read(bev_ssl, n_to_read); 793290001Sglebius all_result_flags |= r; 794290001Sglebius 795290001Sglebius if (r & (OP_BLOCKED|OP_ERR)) 796290001Sglebius break; 797290001Sglebius 798290001Sglebius if (bev_ssl->bev.read_suspended) 799290001Sglebius break; 800290001Sglebius 801290001Sglebius /* Read all pending data. This won't hit the network 802290001Sglebius * again, and will (most importantly) put us in a state 803290001Sglebius * where we don't need to read anything else until the 804290001Sglebius * socket is readable again. It'll potentially make us 805290001Sglebius * overrun our read high-watermark (somewhat 806290001Sglebius * regrettable). The damage to the rate-limit has 807290001Sglebius * already been done, since OpenSSL went and read a 808290001Sglebius * whole SSL record anyway. */ 809290001Sglebius n_to_read = SSL_pending(bev_ssl->ssl); 810290001Sglebius 811290001Sglebius /* XXX This if statement is actually a bad bug, added to avoid 812290001Sglebius * XXX a worse bug. 813290001Sglebius * 814290001Sglebius * The bad bug: It can potentially cause resource unfairness 815290001Sglebius * by reading too much data from the underlying bufferevent; 816290001Sglebius * it can potentially cause read looping if the underlying 817290001Sglebius * bufferevent is a bufferevent_pair and deferred callbacks 818290001Sglebius * aren't used. 819290001Sglebius * 820290001Sglebius * The worse bug: If we didn't do this, then we would 821290001Sglebius * potentially not read any more from bev_ssl->underlying 822290001Sglebius * until more data arrived there, which could lead to us 823290001Sglebius * waiting forever. 824290001Sglebius */ 825290001Sglebius if (!n_to_read && bev_ssl->underlying) 826290001Sglebius n_to_read = bytes_to_read(bev_ssl); 827290001Sglebius } 828290001Sglebius 829290001Sglebius if (all_result_flags & OP_MADE_PROGRESS) { 830290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 831290001Sglebius 832290001Sglebius bufferevent_trigger_nolock_(bev, EV_READ, 0); 833290001Sglebius } 834290001Sglebius 835290001Sglebius if (!bev_ssl->underlying) { 836290001Sglebius /* Should be redundant, but let's avoid busy-looping */ 837290001Sglebius if (bev_ssl->bev.read_suspended || 838290001Sglebius !(bev_ssl->bev.bev.enabled & EV_READ)) { 839290001Sglebius event_del(&bev_ssl->bev.bev.ev_read); 840290001Sglebius } 841290001Sglebius } 842290001Sglebius} 843290001Sglebius 844290001Sglebiusstatic void 845290001Sglebiusconsider_writing(struct bufferevent_openssl *bev_ssl) 846290001Sglebius{ 847290001Sglebius int r; 848290001Sglebius struct evbuffer *output = bev_ssl->bev.bev.output; 849290001Sglebius struct evbuffer *target = NULL; 850290001Sglebius struct event_watermark *wm = NULL; 851290001Sglebius 852290001Sglebius while (bev_ssl->read_blocked_on_write) { 853290001Sglebius r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */ 854290001Sglebius if (r & OP_MADE_PROGRESS) { 855290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 856290001Sglebius 857290001Sglebius bufferevent_trigger_nolock_(bev, EV_READ, 0); 858290001Sglebius } 859290001Sglebius if (r & (OP_ERR|OP_BLOCKED)) 860290001Sglebius break; 861290001Sglebius } 862290001Sglebius if (bev_ssl->read_blocked_on_write) 863290001Sglebius return; 864290001Sglebius if (bev_ssl->underlying) { 865290001Sglebius target = bev_ssl->underlying->output; 866290001Sglebius wm = &bev_ssl->underlying->wm_write; 867290001Sglebius } 868290001Sglebius while ((bev_ssl->bev.bev.enabled & EV_WRITE) && 869290001Sglebius (! bev_ssl->bev.write_suspended) && 870290001Sglebius evbuffer_get_length(output) && 871290001Sglebius (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) { 872290001Sglebius int n_to_write; 873290001Sglebius if (wm && wm->high) 874290001Sglebius n_to_write = wm->high - evbuffer_get_length(target); 875290001Sglebius else 876290001Sglebius n_to_write = WRITE_FRAME; 877290001Sglebius r = do_write(bev_ssl, n_to_write); 878290001Sglebius if (r & (OP_BLOCKED|OP_ERR)) 879290001Sglebius break; 880290001Sglebius } 881290001Sglebius 882290001Sglebius if (!bev_ssl->underlying) { 883290001Sglebius if (evbuffer_get_length(output) == 0) { 884290001Sglebius event_del(&bev_ssl->bev.bev.ev_write); 885290001Sglebius } else if (bev_ssl->bev.write_suspended || 886290001Sglebius !(bev_ssl->bev.bev.enabled & EV_WRITE)) { 887290001Sglebius /* Should be redundant, but let's avoid busy-looping */ 888290001Sglebius event_del(&bev_ssl->bev.bev.ev_write); 889290001Sglebius } 890290001Sglebius } 891290001Sglebius} 892290001Sglebius 893290001Sglebiusstatic void 894290001Sglebiusbe_openssl_readcb(struct bufferevent *bev_base, void *ctx) 895290001Sglebius{ 896290001Sglebius struct bufferevent_openssl *bev_ssl = ctx; 897290001Sglebius consider_reading(bev_ssl); 898290001Sglebius} 899290001Sglebius 900290001Sglebiusstatic void 901290001Sglebiusbe_openssl_writecb(struct bufferevent *bev_base, void *ctx) 902290001Sglebius{ 903290001Sglebius struct bufferevent_openssl *bev_ssl = ctx; 904290001Sglebius consider_writing(bev_ssl); 905290001Sglebius} 906290001Sglebius 907290001Sglebiusstatic void 908290001Sglebiusbe_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx) 909290001Sglebius{ 910290001Sglebius struct bufferevent_openssl *bev_ssl = ctx; 911290001Sglebius int event = 0; 912290001Sglebius 913290001Sglebius if (what & BEV_EVENT_EOF) { 914290001Sglebius if (bev_ssl->allow_dirty_shutdown) 915290001Sglebius event = BEV_EVENT_EOF; 916290001Sglebius else 917290001Sglebius event = BEV_EVENT_ERROR; 918290001Sglebius } else if (what & BEV_EVENT_TIMEOUT) { 919290001Sglebius /* We sure didn't set this. Propagate it to the user. */ 920290001Sglebius event = what; 921290001Sglebius } else if (what & BEV_EVENT_ERROR) { 922290001Sglebius /* An error occurred on the connection. Propagate it to the user. */ 923290001Sglebius event = what; 924290001Sglebius } else if (what & BEV_EVENT_CONNECTED) { 925290001Sglebius /* Ignore it. We're saying SSL_connect() already, which will 926290001Sglebius eat it. */ 927290001Sglebius } 928290001Sglebius if (event) 929290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, event, 0); 930290001Sglebius} 931290001Sglebius 932290001Sglebiusstatic void 933290001Sglebiusbe_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr) 934290001Sglebius{ 935290001Sglebius struct bufferevent_openssl *bev_ssl = ptr; 936290001Sglebius bufferevent_incref_and_lock_(&bev_ssl->bev.bev); 937290001Sglebius if (what == EV_TIMEOUT) { 938290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, 939290001Sglebius BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0); 940290001Sglebius } else { 941290001Sglebius consider_reading(bev_ssl); 942290001Sglebius } 943290001Sglebius bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); 944290001Sglebius} 945290001Sglebius 946290001Sglebiusstatic void 947290001Sglebiusbe_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr) 948290001Sglebius{ 949290001Sglebius struct bufferevent_openssl *bev_ssl = ptr; 950290001Sglebius bufferevent_incref_and_lock_(&bev_ssl->bev.bev); 951290001Sglebius if (what == EV_TIMEOUT) { 952290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, 953290001Sglebius BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING, 0); 954290001Sglebius } else { 955290001Sglebius consider_writing(bev_ssl); 956290001Sglebius } 957290001Sglebius bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); 958290001Sglebius} 959290001Sglebius 960290001Sglebiusstatic int 961290001Sglebiusset_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) 962290001Sglebius{ 963290001Sglebius if (bev_ssl->underlying) { 964290001Sglebius bufferevent_setcb(bev_ssl->underlying, 965290001Sglebius be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb, 966290001Sglebius bev_ssl); 967290001Sglebius return 0; 968290001Sglebius } else { 969290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 970290001Sglebius int rpending=0, wpending=0, r1=0, r2=0; 971290001Sglebius if (fd < 0 && bev_ssl->fd_is_set) 972290001Sglebius fd = event_get_fd(&bev->ev_read); 973290001Sglebius if (bev_ssl->fd_is_set) { 974290001Sglebius rpending = event_pending(&bev->ev_read, EV_READ, NULL); 975290001Sglebius wpending = event_pending(&bev->ev_write, EV_WRITE, NULL); 976290001Sglebius event_del(&bev->ev_read); 977290001Sglebius event_del(&bev->ev_write); 978290001Sglebius } 979290001Sglebius event_assign(&bev->ev_read, bev->ev_base, fd, 980290001Sglebius EV_READ|EV_PERSIST|EV_FINALIZE, 981290001Sglebius be_openssl_readeventcb, bev_ssl); 982290001Sglebius event_assign(&bev->ev_write, bev->ev_base, fd, 983290001Sglebius EV_WRITE|EV_PERSIST|EV_FINALIZE, 984290001Sglebius be_openssl_writeeventcb, bev_ssl); 985290001Sglebius if (rpending) 986290001Sglebius r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); 987290001Sglebius if (wpending) 988290001Sglebius r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); 989290001Sglebius if (fd >= 0) { 990290001Sglebius bev_ssl->fd_is_set = 1; 991290001Sglebius } 992290001Sglebius return (r1<0 || r2<0) ? -1 : 0; 993290001Sglebius } 994290001Sglebius} 995290001Sglebius 996290001Sglebiusstatic int 997290001Sglebiusdo_handshake(struct bufferevent_openssl *bev_ssl) 998290001Sglebius{ 999290001Sglebius int r; 1000290001Sglebius 1001290001Sglebius switch (bev_ssl->state) { 1002290001Sglebius default: 1003290001Sglebius case BUFFEREVENT_SSL_OPEN: 1004290001Sglebius EVUTIL_ASSERT(0); 1005290001Sglebius return -1; 1006290001Sglebius case BUFFEREVENT_SSL_CONNECTING: 1007290001Sglebius case BUFFEREVENT_SSL_ACCEPTING: 1008290001Sglebius r = SSL_do_handshake(bev_ssl->ssl); 1009290001Sglebius break; 1010290001Sglebius } 1011290001Sglebius decrement_buckets(bev_ssl); 1012290001Sglebius 1013290001Sglebius if (r==1) { 1014290001Sglebius /* We're done! */ 1015290001Sglebius bev_ssl->state = BUFFEREVENT_SSL_OPEN; 1016290001Sglebius set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */ 1017290001Sglebius /* Call do_read and do_write as needed */ 1018290001Sglebius bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled); 1019290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, 1020290001Sglebius BEV_EVENT_CONNECTED, 0); 1021290001Sglebius return 1; 1022290001Sglebius } else { 1023290001Sglebius int err = SSL_get_error(bev_ssl->ssl, r); 1024290001Sglebius print_err(err); 1025290001Sglebius switch (err) { 1026290001Sglebius case SSL_ERROR_WANT_WRITE: 1027290001Sglebius if (!bev_ssl->underlying) { 1028290001Sglebius stop_reading(bev_ssl); 1029290001Sglebius return start_writing(bev_ssl); 1030290001Sglebius } 1031290001Sglebius return 0; 1032290001Sglebius case SSL_ERROR_WANT_READ: 1033290001Sglebius if (!bev_ssl->underlying) { 1034290001Sglebius stop_writing(bev_ssl); 1035290001Sglebius return start_reading(bev_ssl); 1036290001Sglebius } 1037290001Sglebius return 0; 1038290001Sglebius default: 1039290001Sglebius conn_closed(bev_ssl, BEV_EVENT_READING, err, r); 1040290001Sglebius return -1; 1041290001Sglebius } 1042290001Sglebius } 1043290001Sglebius} 1044290001Sglebius 1045290001Sglebiusstatic void 1046290001Sglebiusbe_openssl_handshakecb(struct bufferevent *bev_base, void *ctx) 1047290001Sglebius{ 1048290001Sglebius struct bufferevent_openssl *bev_ssl = ctx; 1049290001Sglebius do_handshake(bev_ssl);/* XXX handle failure */ 1050290001Sglebius} 1051290001Sglebius 1052290001Sglebiusstatic void 1053290001Sglebiusbe_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr) 1054290001Sglebius{ 1055290001Sglebius struct bufferevent_openssl *bev_ssl = ptr; 1056290001Sglebius 1057290001Sglebius bufferevent_incref_and_lock_(&bev_ssl->bev.bev); 1058290001Sglebius if (what & EV_TIMEOUT) { 1059290001Sglebius bufferevent_run_eventcb_(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT, 0); 1060290001Sglebius } else 1061290001Sglebius do_handshake(bev_ssl);/* XXX handle failure */ 1062290001Sglebius bufferevent_decref_and_unlock_(&bev_ssl->bev.bev); 1063290001Sglebius} 1064290001Sglebius 1065290001Sglebiusstatic int 1066290001Sglebiusset_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) 1067290001Sglebius{ 1068290001Sglebius if (bev_ssl->underlying) { 1069290001Sglebius bufferevent_setcb(bev_ssl->underlying, 1070290001Sglebius be_openssl_handshakecb, be_openssl_handshakecb, 1071290001Sglebius be_openssl_eventcb, 1072290001Sglebius bev_ssl); 1073290001Sglebius return do_handshake(bev_ssl); 1074290001Sglebius } else { 1075290001Sglebius struct bufferevent *bev = &bev_ssl->bev.bev; 1076290001Sglebius int r1=0, r2=0; 1077290001Sglebius if (fd < 0 && bev_ssl->fd_is_set) 1078290001Sglebius fd = event_get_fd(&bev->ev_read); 1079290001Sglebius if (bev_ssl->fd_is_set) { 1080290001Sglebius event_del(&bev->ev_read); 1081290001Sglebius event_del(&bev->ev_write); 1082290001Sglebius } 1083290001Sglebius event_assign(&bev->ev_read, bev->ev_base, fd, 1084290001Sglebius EV_READ|EV_PERSIST|EV_FINALIZE, 1085290001Sglebius be_openssl_handshakeeventcb, bev_ssl); 1086290001Sglebius event_assign(&bev->ev_write, bev->ev_base, fd, 1087290001Sglebius EV_WRITE|EV_PERSIST|EV_FINALIZE, 1088290001Sglebius be_openssl_handshakeeventcb, bev_ssl); 1089290001Sglebius if (fd >= 0) { 1090290001Sglebius r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); 1091290001Sglebius r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); 1092290001Sglebius bev_ssl->fd_is_set = 1; 1093290001Sglebius } 1094290001Sglebius return (r1<0 || r2<0) ? -1 : 0; 1095290001Sglebius } 1096290001Sglebius} 1097290001Sglebius 1098290001Sglebiusint 1099290001Sglebiusbufferevent_ssl_renegotiate(struct bufferevent *bev) 1100290001Sglebius{ 1101290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1102290001Sglebius if (!bev_ssl) 1103290001Sglebius return -1; 1104290001Sglebius if (SSL_renegotiate(bev_ssl->ssl) < 0) 1105290001Sglebius return -1; 1106290001Sglebius bev_ssl->state = BUFFEREVENT_SSL_CONNECTING; 1107290001Sglebius if (set_handshake_callbacks(bev_ssl, -1) < 0) 1108290001Sglebius return -1; 1109290001Sglebius if (!bev_ssl->underlying) 1110290001Sglebius return do_handshake(bev_ssl); 1111290001Sglebius return 0; 1112290001Sglebius} 1113290001Sglebius 1114290001Sglebiusstatic void 1115290001Sglebiusbe_openssl_outbuf_cb(struct evbuffer *buf, 1116290001Sglebius const struct evbuffer_cb_info *cbinfo, void *arg) 1117290001Sglebius{ 1118290001Sglebius struct bufferevent_openssl *bev_ssl = arg; 1119290001Sglebius int r = 0; 1120290001Sglebius /* XXX need to hold a reference here. */ 1121290001Sglebius 1122290001Sglebius if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) { 1123290001Sglebius if (cbinfo->orig_size == 0) 1124290001Sglebius r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write, 1125290001Sglebius &bev_ssl->bev.bev.timeout_write); 1126290001Sglebius consider_writing(bev_ssl); 1127290001Sglebius } 1128290001Sglebius /* XXX Handle r < 0 */ 1129290001Sglebius (void)r; 1130290001Sglebius} 1131290001Sglebius 1132290001Sglebius 1133290001Sglebiusstatic int 1134290001Sglebiusbe_openssl_enable(struct bufferevent *bev, short events) 1135290001Sglebius{ 1136290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1137290001Sglebius int r1 = 0, r2 = 0; 1138290001Sglebius 1139290001Sglebius if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) 1140290001Sglebius return 0; 1141290001Sglebius 1142290001Sglebius if (events & EV_READ) 1143290001Sglebius r1 = start_reading(bev_ssl); 1144290001Sglebius if (events & EV_WRITE) 1145290001Sglebius r2 = start_writing(bev_ssl); 1146290001Sglebius 1147290001Sglebius if (bev_ssl->underlying) { 1148290001Sglebius if (events & EV_READ) 1149290001Sglebius BEV_RESET_GENERIC_READ_TIMEOUT(bev); 1150290001Sglebius if (events & EV_WRITE) 1151290001Sglebius BEV_RESET_GENERIC_WRITE_TIMEOUT(bev); 1152290001Sglebius 1153290001Sglebius if (events & EV_READ) 1154290001Sglebius consider_reading(bev_ssl); 1155290001Sglebius if (events & EV_WRITE) 1156290001Sglebius consider_writing(bev_ssl); 1157290001Sglebius } 1158290001Sglebius return (r1 < 0 || r2 < 0) ? -1 : 0; 1159290001Sglebius} 1160290001Sglebius 1161290001Sglebiusstatic int 1162290001Sglebiusbe_openssl_disable(struct bufferevent *bev, short events) 1163290001Sglebius{ 1164290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1165290001Sglebius if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) 1166290001Sglebius return 0; 1167290001Sglebius 1168290001Sglebius if (events & EV_READ) 1169290001Sglebius stop_reading(bev_ssl); 1170290001Sglebius if (events & EV_WRITE) 1171290001Sglebius stop_writing(bev_ssl); 1172290001Sglebius 1173290001Sglebius if (bev_ssl->underlying) { 1174290001Sglebius if (events & EV_READ) 1175290001Sglebius BEV_DEL_GENERIC_READ_TIMEOUT(bev); 1176290001Sglebius if (events & EV_WRITE) 1177290001Sglebius BEV_DEL_GENERIC_WRITE_TIMEOUT(bev); 1178290001Sglebius } 1179290001Sglebius return 0; 1180290001Sglebius} 1181290001Sglebius 1182290001Sglebiusstatic void 1183290001Sglebiusbe_openssl_unlink(struct bufferevent *bev) 1184290001Sglebius{ 1185290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1186290001Sglebius 1187290001Sglebius if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) { 1188290001Sglebius if (bev_ssl->underlying) { 1189290001Sglebius if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) { 1190290001Sglebius event_warnx("BEV_OPT_CLOSE_ON_FREE set on an " 1191290001Sglebius "bufferevent with too few references"); 1192290001Sglebius } else { 1193290001Sglebius bufferevent_free(bev_ssl->underlying); 1194290001Sglebius /* We still have a reference to it, via our 1195290001Sglebius * BIO. So we don't drop this. */ 1196290001Sglebius // bev_ssl->underlying = NULL; 1197290001Sglebius } 1198290001Sglebius } 1199290001Sglebius } else { 1200290001Sglebius if (bev_ssl->underlying) { 1201290001Sglebius if (bev_ssl->underlying->errorcb == be_openssl_eventcb) 1202290001Sglebius bufferevent_setcb(bev_ssl->underlying, 1203290001Sglebius NULL,NULL,NULL,NULL); 1204290001Sglebius bufferevent_unsuspend_read_(bev_ssl->underlying, 1205290001Sglebius BEV_SUSPEND_FILT_READ); 1206290001Sglebius } 1207290001Sglebius } 1208290001Sglebius} 1209290001Sglebius 1210290001Sglebiusstatic void 1211290001Sglebiusbe_openssl_destruct(struct bufferevent *bev) 1212290001Sglebius{ 1213290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1214290001Sglebius 1215290001Sglebius if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) { 1216290001Sglebius if (! bev_ssl->underlying) { 1217290001Sglebius evutil_socket_t fd = -1; 1218290001Sglebius BIO *bio = SSL_get_wbio(bev_ssl->ssl); 1219290001Sglebius if (bio) 1220290001Sglebius fd = BIO_get_fd(bio, NULL); 1221290001Sglebius if (fd >= 0) 1222290001Sglebius evutil_closesocket(fd); 1223290001Sglebius } 1224290001Sglebius SSL_free(bev_ssl->ssl); 1225290001Sglebius } 1226290001Sglebius} 1227290001Sglebius 1228290001Sglebiusstatic int 1229290001Sglebiusbe_openssl_adj_timeouts(struct bufferevent *bev) 1230290001Sglebius{ 1231290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1232290001Sglebius 1233290001Sglebius if (bev_ssl->underlying) { 1234290001Sglebius return bufferevent_generic_adj_timeouts_(bev); 1235290001Sglebius } else { 1236290001Sglebius int r1=0, r2=0; 1237290001Sglebius if (event_pending(&bev->ev_read, EV_READ, NULL)) { 1238290001Sglebius if (evutil_timerisset(&bev->timeout_read)) { 1239290001Sglebius r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read); 1240290001Sglebius } else { 1241290001Sglebius event_remove_timer(&bev->ev_read); 1242290001Sglebius } 1243290001Sglebius } 1244290001Sglebius if (event_pending(&bev->ev_write, EV_WRITE, NULL)) { 1245290001Sglebius if (evutil_timerisset(&bev->timeout_write)) { 1246290001Sglebius r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write); 1247290001Sglebius } else { 1248290001Sglebius event_remove_timer(&bev->ev_write); 1249290001Sglebius } 1250290001Sglebius } 1251290001Sglebius 1252290001Sglebius return (r1<0 || r2<0) ? -1 : 0; 1253290001Sglebius } 1254290001Sglebius} 1255290001Sglebius 1256290001Sglebiusstatic int 1257290001Sglebiusbe_openssl_flush(struct bufferevent *bufev, 1258290001Sglebius short iotype, enum bufferevent_flush_mode mode) 1259290001Sglebius{ 1260290001Sglebius /* XXXX Implement this. */ 1261290001Sglebius return 0; 1262290001Sglebius} 1263290001Sglebius 1264290001Sglebiusstatic int 1265290001Sglebiusbe_openssl_ctrl(struct bufferevent *bev, 1266290001Sglebius enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data) 1267290001Sglebius{ 1268290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bev); 1269290001Sglebius switch (op) { 1270290001Sglebius case BEV_CTRL_SET_FD: 1271290001Sglebius if (bev_ssl->underlying) 1272290001Sglebius return -1; 1273290001Sglebius { 1274290001Sglebius BIO *bio; 1275290001Sglebius bio = BIO_new_socket(data->fd, 0); 1276290001Sglebius SSL_set_bio(bev_ssl->ssl, bio, bio); 1277290001Sglebius bev_ssl->fd_is_set = 1; 1278290001Sglebius } 1279290001Sglebius if (data->fd == -1) 1280290001Sglebius bev_ssl->fd_is_set = 0; 1281290001Sglebius if (bev_ssl->state == BUFFEREVENT_SSL_OPEN) 1282290001Sglebius return set_open_callbacks(bev_ssl, data->fd); 1283290001Sglebius else { 1284290001Sglebius return set_handshake_callbacks(bev_ssl, data->fd); 1285290001Sglebius } 1286290001Sglebius case BEV_CTRL_GET_FD: 1287290001Sglebius if (bev_ssl->underlying) 1288290001Sglebius return -1; 1289290001Sglebius if (!bev_ssl->fd_is_set) 1290290001Sglebius return -1; 1291290001Sglebius data->fd = event_get_fd(&bev->ev_read); 1292290001Sglebius return 0; 1293290001Sglebius case BEV_CTRL_GET_UNDERLYING: 1294290001Sglebius if (!bev_ssl->underlying) 1295290001Sglebius return -1; 1296290001Sglebius data->ptr = bev_ssl->underlying; 1297290001Sglebius return 0; 1298290001Sglebius case BEV_CTRL_CANCEL_ALL: 1299290001Sglebius default: 1300290001Sglebius return -1; 1301290001Sglebius } 1302290001Sglebius} 1303290001Sglebius 1304290001SglebiusSSL * 1305290001Sglebiusbufferevent_openssl_get_ssl(struct bufferevent *bufev) 1306290001Sglebius{ 1307290001Sglebius struct bufferevent_openssl *bev_ssl = upcast(bufev); 1308290001Sglebius if (!bev_ssl) 1309290001Sglebius return NULL; 1310290001Sglebius return bev_ssl->ssl; 1311290001Sglebius} 1312290001Sglebius 1313290001Sglebiusstatic struct bufferevent * 1314290001Sglebiusbufferevent_openssl_new_impl(struct event_base *base, 1315290001Sglebius struct bufferevent *underlying, 1316290001Sglebius evutil_socket_t fd, 1317290001Sglebius SSL *ssl, 1318290001Sglebius enum bufferevent_ssl_state state, 1319290001Sglebius int options) 1320290001Sglebius{ 1321290001Sglebius struct bufferevent_openssl *bev_ssl = NULL; 1322290001Sglebius struct bufferevent_private *bev_p = NULL; 1323290001Sglebius int tmp_options = options & ~BEV_OPT_THREADSAFE; 1324290001Sglebius 1325290001Sglebius if (underlying != NULL && fd >= 0) 1326290001Sglebius return NULL; /* Only one can be set. */ 1327290001Sglebius 1328290001Sglebius if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl)))) 1329290001Sglebius goto err; 1330290001Sglebius 1331290001Sglebius bev_p = &bev_ssl->bev; 1332290001Sglebius 1333290001Sglebius if (bufferevent_init_common_(bev_p, base, 1334290001Sglebius &bufferevent_ops_openssl, tmp_options) < 0) 1335290001Sglebius goto err; 1336290001Sglebius 1337290001Sglebius /* Don't explode if we decide to realloc a chunk we're writing from in 1338290001Sglebius * the output buffer. */ 1339290001Sglebius SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); 1340290001Sglebius 1341290001Sglebius bev_ssl->underlying = underlying; 1342290001Sglebius bev_ssl->ssl = ssl; 1343290001Sglebius 1344290001Sglebius bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output, 1345290001Sglebius be_openssl_outbuf_cb, bev_ssl); 1346290001Sglebius 1347290001Sglebius if (options & BEV_OPT_THREADSAFE) 1348290001Sglebius bufferevent_enable_locking_(&bev_ssl->bev.bev, NULL); 1349290001Sglebius 1350290001Sglebius if (underlying) { 1351290001Sglebius bufferevent_init_generic_timeout_cbs_(&bev_ssl->bev.bev); 1352290001Sglebius bufferevent_incref_(underlying); 1353290001Sglebius } 1354290001Sglebius 1355290001Sglebius bev_ssl->state = state; 1356290001Sglebius bev_ssl->last_write = -1; 1357290001Sglebius 1358290001Sglebius init_bio_counts(bev_ssl); 1359290001Sglebius 1360290001Sglebius switch (state) { 1361290001Sglebius case BUFFEREVENT_SSL_ACCEPTING: 1362290001Sglebius SSL_set_accept_state(bev_ssl->ssl); 1363290001Sglebius if (set_handshake_callbacks(bev_ssl, fd) < 0) 1364290001Sglebius goto err; 1365290001Sglebius break; 1366290001Sglebius case BUFFEREVENT_SSL_CONNECTING: 1367290001Sglebius SSL_set_connect_state(bev_ssl->ssl); 1368290001Sglebius if (set_handshake_callbacks(bev_ssl, fd) < 0) 1369290001Sglebius goto err; 1370290001Sglebius break; 1371290001Sglebius case BUFFEREVENT_SSL_OPEN: 1372290001Sglebius if (set_open_callbacks(bev_ssl, fd) < 0) 1373290001Sglebius goto err; 1374290001Sglebius break; 1375290001Sglebius default: 1376290001Sglebius goto err; 1377290001Sglebius } 1378290001Sglebius 1379290001Sglebius if (underlying) { 1380290001Sglebius bufferevent_setwatermark(underlying, EV_READ, 0, 0); 1381290001Sglebius bufferevent_enable(underlying, EV_READ|EV_WRITE); 1382290001Sglebius if (state == BUFFEREVENT_SSL_OPEN) 1383290001Sglebius bufferevent_suspend_read_(underlying, 1384290001Sglebius BEV_SUSPEND_FILT_READ); 1385290001Sglebius } else { 1386290001Sglebius bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE; 1387290001Sglebius if (bev_ssl->fd_is_set) { 1388290001Sglebius if (state != BUFFEREVENT_SSL_OPEN) 1389290001Sglebius if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0) 1390290001Sglebius goto err; 1391290001Sglebius if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0) 1392290001Sglebius goto err; 1393290001Sglebius } 1394290001Sglebius } 1395290001Sglebius 1396290001Sglebius return &bev_ssl->bev.bev; 1397290001Sglebiuserr: 1398290001Sglebius if (bev_ssl) 1399290001Sglebius bufferevent_free(&bev_ssl->bev.bev); 1400290001Sglebius return NULL; 1401290001Sglebius} 1402290001Sglebius 1403290001Sglebiusstruct bufferevent * 1404290001Sglebiusbufferevent_openssl_filter_new(struct event_base *base, 1405290001Sglebius struct bufferevent *underlying, 1406290001Sglebius SSL *ssl, 1407290001Sglebius enum bufferevent_ssl_state state, 1408290001Sglebius int options) 1409290001Sglebius{ 1410290001Sglebius /* We don't tell the BIO to close the bufferevent; we do it ourselves 1411290001Sglebius * on be_openssl_destruct */ 1412290001Sglebius int close_flag = 0; /* options & BEV_OPT_CLOSE_ON_FREE; */ 1413290001Sglebius BIO *bio; 1414290001Sglebius if (!underlying) 1415290001Sglebius return NULL; 1416290001Sglebius if (!(bio = BIO_new_bufferevent(underlying, close_flag))) 1417290001Sglebius return NULL; 1418290001Sglebius 1419290001Sglebius SSL_set_bio(ssl, bio, bio); 1420290001Sglebius 1421290001Sglebius return bufferevent_openssl_new_impl( 1422290001Sglebius base, underlying, -1, ssl, state, options); 1423290001Sglebius} 1424290001Sglebius 1425290001Sglebiusstruct bufferevent * 1426290001Sglebiusbufferevent_openssl_socket_new(struct event_base *base, 1427290001Sglebius evutil_socket_t fd, 1428290001Sglebius SSL *ssl, 1429290001Sglebius enum bufferevent_ssl_state state, 1430290001Sglebius int options) 1431290001Sglebius{ 1432290001Sglebius /* Does the SSL already have an fd? */ 1433290001Sglebius BIO *bio = SSL_get_wbio(ssl); 1434290001Sglebius long have_fd = -1; 1435290001Sglebius 1436290001Sglebius if (bio) 1437290001Sglebius have_fd = BIO_get_fd(bio, NULL); 1438290001Sglebius 1439290001Sglebius if (have_fd >= 0) { 1440290001Sglebius /* The SSL is already configured with an fd. */ 1441290001Sglebius if (fd < 0) { 1442290001Sglebius /* We should learn the fd from the SSL. */ 1443290001Sglebius fd = (evutil_socket_t) have_fd; 1444290001Sglebius } else if (have_fd == (long)fd) { 1445290001Sglebius /* We already know the fd from the SSL; do nothing */ 1446290001Sglebius } else { 1447290001Sglebius /* We specified an fd different from that of the SSL. 1448290001Sglebius This is probably an error on our part. Fail. */ 1449290001Sglebius return NULL; 1450290001Sglebius } 1451290001Sglebius (void) BIO_set_close(bio, 0); 1452290001Sglebius } else { 1453290001Sglebius /* The SSL isn't configured with a BIO with an fd. */ 1454290001Sglebius if (fd >= 0) { 1455290001Sglebius /* ... and we have an fd we want to use. */ 1456290001Sglebius bio = BIO_new_socket(fd, 0); 1457290001Sglebius SSL_set_bio(ssl, bio, bio); 1458290001Sglebius } else { 1459290001Sglebius /* Leave the fd unset. */ 1460290001Sglebius } 1461290001Sglebius } 1462290001Sglebius 1463290001Sglebius return bufferevent_openssl_new_impl( 1464290001Sglebius base, NULL, fd, ssl, state, options); 1465290001Sglebius} 1466290001Sglebius 1467290001Sglebiusint 1468290001Sglebiusbufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev) 1469290001Sglebius{ 1470290001Sglebius int allow_dirty_shutdown = -1; 1471290001Sglebius struct bufferevent_openssl *bev_ssl; 1472290001Sglebius BEV_LOCK(bev); 1473290001Sglebius bev_ssl = upcast(bev); 1474290001Sglebius if (bev_ssl) 1475290001Sglebius allow_dirty_shutdown = bev_ssl->allow_dirty_shutdown; 1476290001Sglebius BEV_UNLOCK(bev); 1477290001Sglebius return allow_dirty_shutdown; 1478290001Sglebius} 1479290001Sglebius 1480290001Sglebiusvoid 1481290001Sglebiusbufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev, 1482290001Sglebius int allow_dirty_shutdown) 1483290001Sglebius{ 1484290001Sglebius struct bufferevent_openssl *bev_ssl; 1485290001Sglebius BEV_LOCK(bev); 1486290001Sglebius bev_ssl = upcast(bev); 1487290001Sglebius if (bev_ssl) 1488290001Sglebius bev_ssl->allow_dirty_shutdown = !!allow_dirty_shutdown; 1489290001Sglebius BEV_UNLOCK(bev); 1490290001Sglebius} 1491290001Sglebius 1492290001Sglebiusunsigned long 1493290001Sglebiusbufferevent_get_openssl_error(struct bufferevent *bev) 1494290001Sglebius{ 1495290001Sglebius unsigned long err = 0; 1496290001Sglebius struct bufferevent_openssl *bev_ssl; 1497290001Sglebius BEV_LOCK(bev); 1498290001Sglebius bev_ssl = upcast(bev); 1499290001Sglebius if (bev_ssl && bev_ssl->n_errors) { 1500290001Sglebius err = bev_ssl->errors[--bev_ssl->n_errors]; 1501290001Sglebius } 1502290001Sglebius BEV_UNLOCK(bev); 1503290001Sglebius return err; 1504290001Sglebius} 1505