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