ipc/chromium/src/third_party/libevent/bufferevent_openssl.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
michael@0 3 *
michael@0 4 * Redistribution and use in source and binary forms, with or without
michael@0 5 * modification, are permitted provided that the following conditions
michael@0 6 * are met:
michael@0 7 * 1. Redistributions of source code must retain the above copyright
michael@0 8 * notice, this list of conditions and the following disclaimer.
michael@0 9 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 10 * notice, this list of conditions and the following disclaimer in the
michael@0 11 * documentation and/or other materials provided with the distribution.
michael@0 12 * 3. The name of the author may not be used to endorse or promote products
michael@0 13 * derived from this software without specific prior written permission.
michael@0 14 *
michael@0 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
michael@0 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
michael@0 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@0 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
michael@0 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
michael@0 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
michael@0 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 25 */
michael@0 26
michael@0 27 #include <sys/types.h>
michael@0 28
michael@0 29 #include "event2/event-config.h"
michael@0 30
michael@0 31 #ifdef _EVENT_HAVE_SYS_TIME_H
michael@0 32 #include <sys/time.h>
michael@0 33 #endif
michael@0 34
michael@0 35 #include <errno.h>
michael@0 36 #include <stdio.h>
michael@0 37 #include <stdlib.h>
michael@0 38 #include <string.h>
michael@0 39 #ifdef _EVENT_HAVE_STDARG_H
michael@0 40 #include <stdarg.h>
michael@0 41 #endif
michael@0 42 #ifdef _EVENT_HAVE_UNISTD_H
michael@0 43 #include <unistd.h>
michael@0 44 #endif
michael@0 45
michael@0 46 #ifdef WIN32
michael@0 47 #include <winsock2.h>
michael@0 48 #endif
michael@0 49
michael@0 50 #include "event2/bufferevent.h"
michael@0 51 #include "event2/bufferevent_struct.h"
michael@0 52 #include "event2/bufferevent_ssl.h"
michael@0 53 #include "event2/buffer.h"
michael@0 54 #include "event2/event.h"
michael@0 55
michael@0 56 #include "mm-internal.h"
michael@0 57 #include "bufferevent-internal.h"
michael@0 58 #include "log-internal.h"
michael@0 59
michael@0 60 #include <openssl/bio.h>
michael@0 61 #include <openssl/ssl.h>
michael@0 62 #include <openssl/err.h>
michael@0 63
michael@0 64 /*
michael@0 65 * Define an OpenSSL bio that targets a bufferevent.
michael@0 66 */
michael@0 67
michael@0 68 /* --------------------
michael@0 69 A BIO is an OpenSSL abstraction that handles reading and writing data. The
michael@0 70 library will happily speak SSL over anything that implements a BIO
michael@0 71 interface.
michael@0 72
michael@0 73 Here we define a BIO implementation that directs its output to a
michael@0 74 bufferevent. We'll want to use this only when none of OpenSSL's built-in
michael@0 75 IO mechanisms work for us.
michael@0 76 -------------------- */
michael@0 77
michael@0 78 /* every BIO type needs its own integer type value. */
michael@0 79 #define BIO_TYPE_LIBEVENT 57
michael@0 80 /* ???? Arguably, we should set BIO_TYPE_FILTER or BIO_TYPE_SOURCE_SINK on
michael@0 81 * this. */
michael@0 82
michael@0 83 #if 0
michael@0 84 static void
michael@0 85 print_err(int val)
michael@0 86 {
michael@0 87 int err;
michael@0 88 printf("Error was %d\n", val);
michael@0 89
michael@0 90 while ((err = ERR_get_error())) {
michael@0 91 const char *msg = (const char*)ERR_reason_error_string(err);
michael@0 92 const char *lib = (const char*)ERR_lib_error_string(err);
michael@0 93 const char *func = (const char*)ERR_func_error_string(err);
michael@0 94
michael@0 95 printf("%s in %s %s\n", msg, lib, func);
michael@0 96 }
michael@0 97 }
michael@0 98 #else
michael@0 99 #define print_err(v) ((void)0)
michael@0 100 #endif
michael@0 101
michael@0 102 /* Called to initialize a new BIO */
michael@0 103 static int
michael@0 104 bio_bufferevent_new(BIO *b)
michael@0 105 {
michael@0 106 b->init = 0;
michael@0 107 b->num = -1;
michael@0 108 b->ptr = NULL; /* We'll be putting the bufferevent in this field.*/
michael@0 109 b->flags = 0;
michael@0 110 return 1;
michael@0 111 }
michael@0 112
michael@0 113 /* Called to uninitialize the BIO. */
michael@0 114 static int
michael@0 115 bio_bufferevent_free(BIO *b)
michael@0 116 {
michael@0 117 if (!b)
michael@0 118 return 0;
michael@0 119 if (b->shutdown) {
michael@0 120 if (b->init && b->ptr)
michael@0 121 bufferevent_free(b->ptr);
michael@0 122 b->init = 0;
michael@0 123 b->flags = 0;
michael@0 124 b->ptr = NULL;
michael@0 125 }
michael@0 126 return 1;
michael@0 127 }
michael@0 128
michael@0 129 /* Called to extract data from the BIO. */
michael@0 130 static int
michael@0 131 bio_bufferevent_read(BIO *b, char *out, int outlen)
michael@0 132 {
michael@0 133 int r = 0;
michael@0 134 struct evbuffer *input;
michael@0 135
michael@0 136 BIO_clear_retry_flags(b);
michael@0 137
michael@0 138 if (!out)
michael@0 139 return 0;
michael@0 140 if (!b->ptr)
michael@0 141 return -1;
michael@0 142
michael@0 143 input = bufferevent_get_input(b->ptr);
michael@0 144 if (evbuffer_get_length(input) == 0) {
michael@0 145 /* If there's no data to read, say so. */
michael@0 146 BIO_set_retry_read(b);
michael@0 147 return -1;
michael@0 148 } else {
michael@0 149 r = evbuffer_remove(input, out, outlen);
michael@0 150 }
michael@0 151
michael@0 152 return r;
michael@0 153 }
michael@0 154
michael@0 155 /* Called to write data info the BIO */
michael@0 156 static int
michael@0 157 bio_bufferevent_write(BIO *b, const char *in, int inlen)
michael@0 158 {
michael@0 159 struct bufferevent *bufev = b->ptr;
michael@0 160 struct evbuffer *output;
michael@0 161 size_t outlen;
michael@0 162
michael@0 163 BIO_clear_retry_flags(b);
michael@0 164
michael@0 165 if (!b->ptr)
michael@0 166 return -1;
michael@0 167
michael@0 168 output = bufferevent_get_output(bufev);
michael@0 169 outlen = evbuffer_get_length(output);
michael@0 170
michael@0 171 /* Copy only as much data onto the output buffer as can fit under the
michael@0 172 * high-water mark. */
michael@0 173 if (bufev->wm_write.high && bufev->wm_write.high <= (outlen+inlen)) {
michael@0 174 if (bufev->wm_write.high <= outlen) {
michael@0 175 /* If no data can fit, we'll need to retry later. */
michael@0 176 BIO_set_retry_write(b);
michael@0 177 return -1;
michael@0 178 }
michael@0 179 inlen = bufev->wm_write.high - outlen;
michael@0 180 }
michael@0 181
michael@0 182 EVUTIL_ASSERT(inlen > 0);
michael@0 183 evbuffer_add(output, in, inlen);
michael@0 184 return inlen;
michael@0 185 }
michael@0 186
michael@0 187 /* Called to handle various requests */
michael@0 188 static long
michael@0 189 bio_bufferevent_ctrl(BIO *b, int cmd, long num, void *ptr)
michael@0 190 {
michael@0 191 struct bufferevent *bufev = b->ptr;
michael@0 192 long ret = 1;
michael@0 193
michael@0 194 switch (cmd) {
michael@0 195 case BIO_CTRL_GET_CLOSE:
michael@0 196 ret = b->shutdown;
michael@0 197 break;
michael@0 198 case BIO_CTRL_SET_CLOSE:
michael@0 199 b->shutdown = (int)num;
michael@0 200 break;
michael@0 201 case BIO_CTRL_PENDING:
michael@0 202 ret = evbuffer_get_length(bufferevent_get_input(bufev)) != 0;
michael@0 203 break;
michael@0 204 case BIO_CTRL_WPENDING:
michael@0 205 ret = evbuffer_get_length(bufferevent_get_output(bufev)) != 0;
michael@0 206 break;
michael@0 207 /* XXXX These two are given a special-case treatment because
michael@0 208 * of cargo-cultism. I should come up with a better reason. */
michael@0 209 case BIO_CTRL_DUP:
michael@0 210 case BIO_CTRL_FLUSH:
michael@0 211 ret = 1;
michael@0 212 break;
michael@0 213 default:
michael@0 214 ret = 0;
michael@0 215 break;
michael@0 216 }
michael@0 217 return ret;
michael@0 218 }
michael@0 219
michael@0 220 /* Called to write a string to the BIO */
michael@0 221 static int
michael@0 222 bio_bufferevent_puts(BIO *b, const char *s)
michael@0 223 {
michael@0 224 return bio_bufferevent_write(b, s, strlen(s));
michael@0 225 }
michael@0 226
michael@0 227 /* Method table for the bufferevent BIO */
michael@0 228 static BIO_METHOD methods_bufferevent = {
michael@0 229 BIO_TYPE_LIBEVENT, "bufferevent",
michael@0 230 bio_bufferevent_write,
michael@0 231 bio_bufferevent_read,
michael@0 232 bio_bufferevent_puts,
michael@0 233 NULL /* bio_bufferevent_gets */,
michael@0 234 bio_bufferevent_ctrl,
michael@0 235 bio_bufferevent_new,
michael@0 236 bio_bufferevent_free,
michael@0 237 NULL /* callback_ctrl */,
michael@0 238 };
michael@0 239
michael@0 240 /* Return the method table for the bufferevents BIO */
michael@0 241 static BIO_METHOD *
michael@0 242 BIO_s_bufferevent(void)
michael@0 243 {
michael@0 244 return &methods_bufferevent;
michael@0 245 }
michael@0 246
michael@0 247 /* Create a new BIO to wrap communication around a bufferevent. If close_flag
michael@0 248 * is true, the bufferevent will be freed when the BIO is closed. */
michael@0 249 static BIO *
michael@0 250 BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag)
michael@0 251 {
michael@0 252 BIO *result;
michael@0 253 if (!bufferevent)
michael@0 254 return NULL;
michael@0 255 if (!(result = BIO_new(BIO_s_bufferevent())))
michael@0 256 return NULL;
michael@0 257 result->init = 1;
michael@0 258 result->ptr = bufferevent;
michael@0 259 result->shutdown = close_flag ? 1 : 0;
michael@0 260 return result;
michael@0 261 }
michael@0 262
michael@0 263 /* --------------------
michael@0 264 Now, here's the OpenSSL-based implementation of bufferevent.
michael@0 265
michael@0 266 The implementation comes in two flavors: one that connects its SSL object
michael@0 267 to an underlying bufferevent using a BIO_bufferevent, and one that has the
michael@0 268 SSL object connect to a socket directly. The latter should generally be
michael@0 269 faster, except on Windows, where your best bet is using a
michael@0 270 bufferevent_async.
michael@0 271
michael@0 272 (OpenSSL supports many other BIO types, too. But we can't use any unless
michael@0 273 we have a good way to get notified when they become readable/writable.)
michael@0 274 -------------------- */
michael@0 275
michael@0 276 struct bio_data_counts {
michael@0 277 unsigned long n_written;
michael@0 278 unsigned long n_read;
michael@0 279 };
michael@0 280
michael@0 281 struct bufferevent_openssl {
michael@0 282 /* Shared fields with common bufferevent implementation code.
michael@0 283 If we were set up with an underlying bufferevent, we use the
michael@0 284 events here as timers only. If we have an SSL, then we use
michael@0 285 the events as socket events.
michael@0 286 */
michael@0 287 struct bufferevent_private bev;
michael@0 288 /* An underlying bufferevent that we're directing our output to.
michael@0 289 If it's NULL, then we're connected to an fd, not an evbuffer. */
michael@0 290 struct bufferevent *underlying;
michael@0 291 /* The SSL object doing our encryption. */
michael@0 292 SSL *ssl;
michael@0 293
michael@0 294 /* A callback that's invoked when data arrives on our outbuf so we
michael@0 295 know to write data to the SSL. */
michael@0 296 struct evbuffer_cb_entry *outbuf_cb;
michael@0 297
michael@0 298 /* A count of how much data the bios have read/written total. Used
michael@0 299 for rate-limiting. */
michael@0 300 struct bio_data_counts counts;
michael@0 301
michael@0 302 /* If this value is greater than 0, then the last SSL_write blocked,
michael@0 303 * and we need to try it again with this many bytes. */
michael@0 304 ev_ssize_t last_write;
michael@0 305
michael@0 306 #define NUM_ERRORS 3
michael@0 307 ev_uint32_t errors[NUM_ERRORS];
michael@0 308
michael@0 309 /* When we next get available space, we should say "read" instead of
michael@0 310 "write". This can happen if there's a renegotiation during a read
michael@0 311 operation. */
michael@0 312 unsigned read_blocked_on_write : 1;
michael@0 313 /* When we next get data, we should say "write" instead of "read". */
michael@0 314 unsigned write_blocked_on_read : 1;
michael@0 315 /* XXX */
michael@0 316 unsigned allow_dirty_shutdown : 1;
michael@0 317 /* XXXX */
michael@0 318 unsigned fd_is_set : 1;
michael@0 319 /* XXX */
michael@0 320 unsigned n_errors : 2;
michael@0 321
michael@0 322 /* Are we currently connecting, accepting, or doing IO? */
michael@0 323 unsigned state : 2;
michael@0 324 };
michael@0 325
michael@0 326 static int be_openssl_enable(struct bufferevent *, short);
michael@0 327 static int be_openssl_disable(struct bufferevent *, short);
michael@0 328 static void be_openssl_destruct(struct bufferevent *);
michael@0 329 static int be_openssl_adj_timeouts(struct bufferevent *);
michael@0 330 static int be_openssl_flush(struct bufferevent *bufev,
michael@0 331 short iotype, enum bufferevent_flush_mode mode);
michael@0 332 static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
michael@0 333
michael@0 334 const struct bufferevent_ops bufferevent_ops_openssl = {
michael@0 335 "ssl",
michael@0 336 evutil_offsetof(struct bufferevent_openssl, bev.bev),
michael@0 337 be_openssl_enable,
michael@0 338 be_openssl_disable,
michael@0 339 be_openssl_destruct,
michael@0 340 be_openssl_adj_timeouts,
michael@0 341 be_openssl_flush,
michael@0 342 be_openssl_ctrl,
michael@0 343 };
michael@0 344
michael@0 345 /* Given a bufferevent, return a pointer to the bufferevent_openssl that
michael@0 346 * contains it, if any. */
michael@0 347 static inline struct bufferevent_openssl *
michael@0 348 upcast(struct bufferevent *bev)
michael@0 349 {
michael@0 350 struct bufferevent_openssl *bev_o;
michael@0 351 if (bev->be_ops != &bufferevent_ops_openssl)
michael@0 352 return NULL;
michael@0 353 bev_o = (void*)( ((char*)bev) -
michael@0 354 evutil_offsetof(struct bufferevent_openssl, bev.bev));
michael@0 355 EVUTIL_ASSERT(bev_o->bev.bev.be_ops == &bufferevent_ops_openssl);
michael@0 356 return bev_o;
michael@0 357 }
michael@0 358
michael@0 359 static inline void
michael@0 360 put_error(struct bufferevent_openssl *bev_ssl, unsigned long err)
michael@0 361 {
michael@0 362 if (bev_ssl->n_errors == NUM_ERRORS)
michael@0 363 return;
michael@0 364 /* The error type according to openssl is "unsigned long", but
michael@0 365 openssl never uses more than 32 bits of it. It _can't_ use more
michael@0 366 than 32 bits of it, since it needs to report errors on systems
michael@0 367 where long is only 32 bits.
michael@0 368 */
michael@0 369 bev_ssl->errors[bev_ssl->n_errors++] = (ev_uint32_t) err;
michael@0 370 }
michael@0 371
michael@0 372 /* Have the base communications channel (either the underlying bufferevent or
michael@0 373 * ev_read and ev_write) start reading. Take the read-blocked-on-write flag
michael@0 374 * into account. */
michael@0 375 static int
michael@0 376 start_reading(struct bufferevent_openssl *bev_ssl)
michael@0 377 {
michael@0 378 if (bev_ssl->underlying) {
michael@0 379 bufferevent_unsuspend_read(bev_ssl->underlying,
michael@0 380 BEV_SUSPEND_FILT_READ);
michael@0 381 return 0;
michael@0 382 } else {
michael@0 383 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 384 int r;
michael@0 385 r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
michael@0 386 if (r == 0 && bev_ssl->read_blocked_on_write)
michael@0 387 r = _bufferevent_add_event(&bev->ev_write,
michael@0 388 &bev->timeout_write);
michael@0 389 return r;
michael@0 390 }
michael@0 391 }
michael@0 392
michael@0 393 /* Have the base communications channel (either the underlying bufferevent or
michael@0 394 * ev_read and ev_write) start writing. Take the write-blocked-on-read flag
michael@0 395 * into account. */
michael@0 396 static int
michael@0 397 start_writing(struct bufferevent_openssl *bev_ssl)
michael@0 398 {
michael@0 399 int r = 0;
michael@0 400 if (bev_ssl->underlying) {
michael@0 401 ;
michael@0 402 } else {
michael@0 403 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 404 r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
michael@0 405 if (!r && bev_ssl->write_blocked_on_read)
michael@0 406 r = _bufferevent_add_event(&bev->ev_read,
michael@0 407 &bev->timeout_read);
michael@0 408 }
michael@0 409 return r;
michael@0 410 }
michael@0 411
michael@0 412 static void
michael@0 413 stop_reading(struct bufferevent_openssl *bev_ssl)
michael@0 414 {
michael@0 415 if (bev_ssl->write_blocked_on_read)
michael@0 416 return;
michael@0 417 if (bev_ssl->underlying) {
michael@0 418 bufferevent_suspend_read(bev_ssl->underlying,
michael@0 419 BEV_SUSPEND_FILT_READ);
michael@0 420 } else {
michael@0 421 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 422 event_del(&bev->ev_read);
michael@0 423 }
michael@0 424 }
michael@0 425
michael@0 426 static void
michael@0 427 stop_writing(struct bufferevent_openssl *bev_ssl)
michael@0 428 {
michael@0 429 if (bev_ssl->read_blocked_on_write)
michael@0 430 return;
michael@0 431 if (bev_ssl->underlying) {
michael@0 432 ;
michael@0 433 } else {
michael@0 434 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 435 event_del(&bev->ev_write);
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 static int
michael@0 440 set_rbow(struct bufferevent_openssl *bev_ssl)
michael@0 441 {
michael@0 442 if (!bev_ssl->underlying)
michael@0 443 stop_reading(bev_ssl);
michael@0 444 bev_ssl->read_blocked_on_write = 1;
michael@0 445 return start_writing(bev_ssl);
michael@0 446 }
michael@0 447
michael@0 448 static int
michael@0 449 set_wbor(struct bufferevent_openssl *bev_ssl)
michael@0 450 {
michael@0 451 if (!bev_ssl->underlying)
michael@0 452 stop_writing(bev_ssl);
michael@0 453 bev_ssl->write_blocked_on_read = 1;
michael@0 454 return start_reading(bev_ssl);
michael@0 455 }
michael@0 456
michael@0 457 static int
michael@0 458 clear_rbow(struct bufferevent_openssl *bev_ssl)
michael@0 459 {
michael@0 460 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 461 int r = 0;
michael@0 462 bev_ssl->read_blocked_on_write = 0;
michael@0 463 if (!(bev->enabled & EV_WRITE))
michael@0 464 stop_writing(bev_ssl);
michael@0 465 if (bev->enabled & EV_READ)
michael@0 466 r = start_reading(bev_ssl);
michael@0 467 return r;
michael@0 468 }
michael@0 469
michael@0 470
michael@0 471 static int
michael@0 472 clear_wbor(struct bufferevent_openssl *bev_ssl)
michael@0 473 {
michael@0 474 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 475 int r = 0;
michael@0 476 bev_ssl->write_blocked_on_read = 0;
michael@0 477 if (!(bev->enabled & EV_READ))
michael@0 478 stop_reading(bev_ssl);
michael@0 479 if (bev->enabled & EV_WRITE)
michael@0 480 r = start_writing(bev_ssl);
michael@0 481 return r;
michael@0 482 }
michael@0 483
michael@0 484 static void
michael@0 485 conn_closed(struct bufferevent_openssl *bev_ssl, int errcode, int ret)
michael@0 486 {
michael@0 487 int event = BEV_EVENT_ERROR;
michael@0 488 int dirty_shutdown = 0;
michael@0 489 unsigned long err;
michael@0 490
michael@0 491 switch (errcode) {
michael@0 492 case SSL_ERROR_ZERO_RETURN:
michael@0 493 /* Possibly a clean shutdown. */
michael@0 494 if (SSL_get_shutdown(bev_ssl->ssl) & SSL_RECEIVED_SHUTDOWN)
michael@0 495 event = BEV_EVENT_EOF;
michael@0 496 else
michael@0 497 dirty_shutdown = 1;
michael@0 498 break;
michael@0 499 case SSL_ERROR_SYSCALL:
michael@0 500 /* IO error; possibly a dirty shutdown. */
michael@0 501 if (ret == 0 && ERR_peek_error() == 0)
michael@0 502 dirty_shutdown = 1;
michael@0 503 break;
michael@0 504 case SSL_ERROR_SSL:
michael@0 505 /* Protocol error. */
michael@0 506 break;
michael@0 507 case SSL_ERROR_WANT_X509_LOOKUP:
michael@0 508 /* XXXX handle this. */
michael@0 509 break;
michael@0 510 case SSL_ERROR_NONE:
michael@0 511 case SSL_ERROR_WANT_READ:
michael@0 512 case SSL_ERROR_WANT_WRITE:
michael@0 513 case SSL_ERROR_WANT_CONNECT:
michael@0 514 case SSL_ERROR_WANT_ACCEPT:
michael@0 515 default:
michael@0 516 /* should be impossible; treat as normal error. */
michael@0 517 event_warnx("BUG: Unexpected OpenSSL error code %d", errcode);
michael@0 518 break;
michael@0 519 }
michael@0 520
michael@0 521 while ((err = ERR_get_error())) {
michael@0 522 put_error(bev_ssl, err);
michael@0 523 }
michael@0 524
michael@0 525 if (dirty_shutdown && bev_ssl->allow_dirty_shutdown)
michael@0 526 event = BEV_EVENT_EOF;
michael@0 527
michael@0 528 stop_reading(bev_ssl);
michael@0 529 stop_writing(bev_ssl);
michael@0 530
michael@0 531 _bufferevent_run_eventcb(&bev_ssl->bev.bev, event);
michael@0 532 }
michael@0 533
michael@0 534 static void
michael@0 535 init_bio_counts(struct bufferevent_openssl *bev_ssl)
michael@0 536 {
michael@0 537 bev_ssl->counts.n_written =
michael@0 538 BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
michael@0 539 bev_ssl->counts.n_read =
michael@0 540 BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
michael@0 541 }
michael@0 542
michael@0 543 static inline void
michael@0 544 decrement_buckets(struct bufferevent_openssl *bev_ssl)
michael@0 545 {
michael@0 546 unsigned long num_w = BIO_number_written(SSL_get_wbio(bev_ssl->ssl));
michael@0 547 unsigned long num_r = BIO_number_read(SSL_get_rbio(bev_ssl->ssl));
michael@0 548 /* These next two subtractions can wrap around. That's okay. */
michael@0 549 unsigned long w = num_w - bev_ssl->counts.n_written;
michael@0 550 unsigned long r = num_r - bev_ssl->counts.n_read;
michael@0 551 if (w)
michael@0 552 _bufferevent_decrement_write_buckets(&bev_ssl->bev, w);
michael@0 553 if (r)
michael@0 554 _bufferevent_decrement_read_buckets(&bev_ssl->bev, r);
michael@0 555 bev_ssl->counts.n_written = num_w;
michael@0 556 bev_ssl->counts.n_read = num_r;
michael@0 557 }
michael@0 558
michael@0 559 #define OP_MADE_PROGRESS 1
michael@0 560 #define OP_BLOCKED 2
michael@0 561 #define OP_ERR 4
michael@0 562
michael@0 563 /* Return a bitmask of OP_MADE_PROGRESS (if we read anything); OP_BLOCKED (if
michael@0 564 we're now blocked); and OP_ERR (if an error occurred). */
michael@0 565 static int
michael@0 566 do_read(struct bufferevent_openssl *bev_ssl, int n_to_read) {
michael@0 567 /* Requires lock */
michael@0 568 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 569 struct evbuffer *input = bev->input;
michael@0 570 int r, n, i, n_used = 0, atmost;
michael@0 571 struct evbuffer_iovec space[2];
michael@0 572 int result = 0;
michael@0 573
michael@0 574 if (bev_ssl->bev.read_suspended)
michael@0 575 return 0;
michael@0 576
michael@0 577 atmost = _bufferevent_get_read_max(&bev_ssl->bev);
michael@0 578 if (n_to_read > atmost)
michael@0 579 n_to_read = atmost;
michael@0 580
michael@0 581 n = evbuffer_reserve_space(input, n_to_read, space, 2);
michael@0 582 if (n < 0)
michael@0 583 return OP_ERR;
michael@0 584
michael@0 585 for (i=0; i<n; ++i) {
michael@0 586 if (bev_ssl->bev.read_suspended)
michael@0 587 break;
michael@0 588 r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
michael@0 589 if (r>0) {
michael@0 590 result |= OP_MADE_PROGRESS;
michael@0 591 if (bev_ssl->read_blocked_on_write)
michael@0 592 if (clear_rbow(bev_ssl) < 0)
michael@0 593 return OP_ERR | result;
michael@0 594 ++n_used;
michael@0 595 space[i].iov_len = r;
michael@0 596 decrement_buckets(bev_ssl);
michael@0 597 } else {
michael@0 598 int err = SSL_get_error(bev_ssl->ssl, r);
michael@0 599 print_err(err);
michael@0 600 switch (err) {
michael@0 601 case SSL_ERROR_WANT_READ:
michael@0 602 /* Can't read until underlying has more data. */
michael@0 603 if (bev_ssl->read_blocked_on_write)
michael@0 604 if (clear_rbow(bev_ssl) < 0)
michael@0 605 return OP_ERR | result;
michael@0 606 break;
michael@0 607 case SSL_ERROR_WANT_WRITE:
michael@0 608 /* This read operation requires a write, and the
michael@0 609 * underlying is full */
michael@0 610 if (!bev_ssl->read_blocked_on_write)
michael@0 611 if (set_rbow(bev_ssl) < 0)
michael@0 612 return OP_ERR | result;
michael@0 613 break;
michael@0 614 default:
michael@0 615 conn_closed(bev_ssl, err, r);
michael@0 616 break;
michael@0 617 }
michael@0 618 result |= OP_BLOCKED;
michael@0 619 break; /* out of the loop */
michael@0 620 }
michael@0 621 }
michael@0 622
michael@0 623 if (n_used) {
michael@0 624 evbuffer_commit_space(input, space, n_used);
michael@0 625 if (bev_ssl->underlying)
michael@0 626 BEV_RESET_GENERIC_READ_TIMEOUT(bev);
michael@0 627 }
michael@0 628
michael@0 629 return result;
michael@0 630 }
michael@0 631
michael@0 632 /* Return a bitmask of OP_MADE_PROGRESS (if we wrote anything); OP_BLOCKED (if
michael@0 633 we're now blocked); and OP_ERR (if an error occurred). */
michael@0 634 static int
michael@0 635 do_write(struct bufferevent_openssl *bev_ssl, int atmost)
michael@0 636 {
michael@0 637 int i, r, n, n_written = 0;
michael@0 638 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 639 struct evbuffer *output = bev->output;
michael@0 640 struct evbuffer_iovec space[8];
michael@0 641 int result = 0;
michael@0 642
michael@0 643 if (bev_ssl->last_write > 0)
michael@0 644 atmost = bev_ssl->last_write;
michael@0 645 else
michael@0 646 atmost = _bufferevent_get_write_max(&bev_ssl->bev);
michael@0 647
michael@0 648 n = evbuffer_peek(output, atmost, NULL, space, 8);
michael@0 649 if (n < 0)
michael@0 650 return OP_ERR | result;
michael@0 651
michael@0 652 if (n > 8)
michael@0 653 n = 8;
michael@0 654 for (i=0; i < n; ++i) {
michael@0 655 if (bev_ssl->bev.write_suspended)
michael@0 656 break;
michael@0 657
michael@0 658 /* SSL_write will (reasonably) return 0 if we tell it to
michael@0 659 send 0 data. Skip this case so we don't interpret the
michael@0 660 result as an error */
michael@0 661 if (space[i].iov_len == 0)
michael@0 662 continue;
michael@0 663
michael@0 664 r = SSL_write(bev_ssl->ssl, space[i].iov_base,
michael@0 665 space[i].iov_len);
michael@0 666 if (r > 0) {
michael@0 667 result |= OP_MADE_PROGRESS;
michael@0 668 if (bev_ssl->write_blocked_on_read)
michael@0 669 if (clear_wbor(bev_ssl) < 0)
michael@0 670 return OP_ERR | result;
michael@0 671 n_written += r;
michael@0 672 bev_ssl->last_write = -1;
michael@0 673 decrement_buckets(bev_ssl);
michael@0 674 } else {
michael@0 675 int err = SSL_get_error(bev_ssl->ssl, r);
michael@0 676 print_err(err);
michael@0 677 switch (err) {
michael@0 678 case SSL_ERROR_WANT_WRITE:
michael@0 679 /* Can't read until underlying has more data. */
michael@0 680 if (bev_ssl->write_blocked_on_read)
michael@0 681 if (clear_wbor(bev_ssl) < 0)
michael@0 682 return OP_ERR | result;
michael@0 683 bev_ssl->last_write = space[i].iov_len;
michael@0 684 break;
michael@0 685 case SSL_ERROR_WANT_READ:
michael@0 686 /* This read operation requires a write, and the
michael@0 687 * underlying is full */
michael@0 688 if (!bev_ssl->write_blocked_on_read)
michael@0 689 if (set_wbor(bev_ssl) < 0)
michael@0 690 return OP_ERR | result;
michael@0 691 bev_ssl->last_write = space[i].iov_len;
michael@0 692 break;
michael@0 693 default:
michael@0 694 conn_closed(bev_ssl, err, r);
michael@0 695 bev_ssl->last_write = -1;
michael@0 696 break;
michael@0 697 }
michael@0 698 result |= OP_BLOCKED;
michael@0 699 break;
michael@0 700 }
michael@0 701 }
michael@0 702 if (n_written) {
michael@0 703 evbuffer_drain(output, n_written);
michael@0 704 if (bev_ssl->underlying)
michael@0 705 BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
michael@0 706
michael@0 707 if (evbuffer_get_length(output) <= bev->wm_write.low)
michael@0 708 _bufferevent_run_writecb(bev);
michael@0 709 }
michael@0 710 return result;
michael@0 711 }
michael@0 712
michael@0 713 #define WRITE_FRAME 15000
michael@0 714
michael@0 715 #define READ_DEFAULT 4096
michael@0 716
michael@0 717 /* Try to figure out how many bytes to read; return 0 if we shouldn't be
michael@0 718 * reading. */
michael@0 719 static int
michael@0 720 bytes_to_read(struct bufferevent_openssl *bev)
michael@0 721 {
michael@0 722 struct evbuffer *input = bev->bev.bev.input;
michael@0 723 struct event_watermark *wm = &bev->bev.bev.wm_read;
michael@0 724 int result = READ_DEFAULT;
michael@0 725 ev_ssize_t limit;
michael@0 726 /* XXX 99% of this is generic code that nearly all bufferevents will
michael@0 727 * want. */
michael@0 728
michael@0 729 if (bev->write_blocked_on_read) {
michael@0 730 return 0;
michael@0 731 }
michael@0 732
michael@0 733 if (! (bev->bev.bev.enabled & EV_READ)) {
michael@0 734 return 0;
michael@0 735 }
michael@0 736
michael@0 737 if (bev->bev.read_suspended) {
michael@0 738 return 0;
michael@0 739 }
michael@0 740
michael@0 741 if (wm->high) {
michael@0 742 if (evbuffer_get_length(input) >= wm->high) {
michael@0 743 return 0;
michael@0 744 }
michael@0 745
michael@0 746 result = wm->high - evbuffer_get_length(input);
michael@0 747 } else {
michael@0 748 result = READ_DEFAULT;
michael@0 749 }
michael@0 750
michael@0 751 /* Respect the rate limit */
michael@0 752 limit = _bufferevent_get_read_max(&bev->bev);
michael@0 753 if (result > limit) {
michael@0 754 result = limit;
michael@0 755 }
michael@0 756
michael@0 757 return result;
michael@0 758 }
michael@0 759
michael@0 760
michael@0 761 /* Things look readable. If write is blocked on read, write till it isn't.
michael@0 762 * Read from the underlying buffer until we block or we hit our high-water
michael@0 763 * mark.
michael@0 764 */
michael@0 765 static void
michael@0 766 consider_reading(struct bufferevent_openssl *bev_ssl)
michael@0 767 {
michael@0 768 int r;
michael@0 769 int n_to_read;
michael@0 770 int all_result_flags = 0;
michael@0 771
michael@0 772 while (bev_ssl->write_blocked_on_read) {
michael@0 773 r = do_write(bev_ssl, WRITE_FRAME);
michael@0 774 if (r & (OP_BLOCKED|OP_ERR))
michael@0 775 break;
michael@0 776 }
michael@0 777 if (bev_ssl->write_blocked_on_read)
michael@0 778 return;
michael@0 779
michael@0 780 n_to_read = bytes_to_read(bev_ssl);
michael@0 781
michael@0 782 while (n_to_read) {
michael@0 783 r = do_read(bev_ssl, n_to_read);
michael@0 784 all_result_flags |= r;
michael@0 785
michael@0 786 if (r & (OP_BLOCKED|OP_ERR))
michael@0 787 break;
michael@0 788
michael@0 789 if (bev_ssl->bev.read_suspended)
michael@0 790 break;
michael@0 791
michael@0 792 /* Read all pending data. This won't hit the network
michael@0 793 * again, and will (most importantly) put us in a state
michael@0 794 * where we don't need to read anything else until the
michael@0 795 * socket is readable again. It'll potentially make us
michael@0 796 * overrun our read high-watermark (somewhat
michael@0 797 * regrettable). The damage to the rate-limit has
michael@0 798 * already been done, since OpenSSL went and read a
michael@0 799 * whole SSL record anyway. */
michael@0 800 n_to_read = SSL_pending(bev_ssl->ssl);
michael@0 801
michael@0 802 /* XXX This if statement is actually a bad bug, added to avoid
michael@0 803 * XXX a worse bug.
michael@0 804 *
michael@0 805 * The bad bug: It can potentially cause resource unfairness
michael@0 806 * by reading too much data from the underlying bufferevent;
michael@0 807 * it can potentially cause read looping if the underlying
michael@0 808 * bufferevent is a bufferevent_pair and deferred callbacks
michael@0 809 * aren't used.
michael@0 810 *
michael@0 811 * The worse bug: If we didn't do this, then we would
michael@0 812 * potentially not read any more from bev_ssl->underlying
michael@0 813 * until more data arrived there, which could lead to us
michael@0 814 * waiting forever.
michael@0 815 */
michael@0 816 if (!n_to_read && bev_ssl->underlying)
michael@0 817 n_to_read = bytes_to_read(bev_ssl);
michael@0 818 }
michael@0 819
michael@0 820 if (all_result_flags & OP_MADE_PROGRESS) {
michael@0 821 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 822 struct evbuffer *input = bev->input;
michael@0 823
michael@0 824 if (evbuffer_get_length(input) >= bev->wm_read.low) {
michael@0 825 _bufferevent_run_readcb(bev);
michael@0 826 }
michael@0 827 }
michael@0 828
michael@0 829 if (!bev_ssl->underlying) {
michael@0 830 /* Should be redundant, but let's avoid busy-looping */
michael@0 831 if (bev_ssl->bev.read_suspended ||
michael@0 832 !(bev_ssl->bev.bev.enabled & EV_READ)) {
michael@0 833 event_del(&bev_ssl->bev.bev.ev_read);
michael@0 834 }
michael@0 835 }
michael@0 836 }
michael@0 837
michael@0 838 static void
michael@0 839 consider_writing(struct bufferevent_openssl *bev_ssl)
michael@0 840 {
michael@0 841 int r;
michael@0 842 struct evbuffer *output = bev_ssl->bev.bev.output;
michael@0 843 struct evbuffer *target = NULL;
michael@0 844 struct event_watermark *wm = NULL;
michael@0 845
michael@0 846 while (bev_ssl->read_blocked_on_write) {
michael@0 847 r = do_read(bev_ssl, 1024); /* XXXX 1024 is a hack */
michael@0 848 if (r & OP_MADE_PROGRESS) {
michael@0 849 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 850 struct evbuffer *input = bev->input;
michael@0 851
michael@0 852 if (evbuffer_get_length(input) >= bev->wm_read.low) {
michael@0 853 _bufferevent_run_readcb(bev);
michael@0 854 }
michael@0 855 }
michael@0 856 if (r & (OP_ERR|OP_BLOCKED))
michael@0 857 break;
michael@0 858 }
michael@0 859 if (bev_ssl->read_blocked_on_write)
michael@0 860 return;
michael@0 861 if (bev_ssl->underlying) {
michael@0 862 target = bev_ssl->underlying->output;
michael@0 863 wm = &bev_ssl->underlying->wm_write;
michael@0 864 }
michael@0 865 while ((bev_ssl->bev.bev.enabled & EV_WRITE) &&
michael@0 866 (! bev_ssl->bev.write_suspended) &&
michael@0 867 evbuffer_get_length(output) &&
michael@0 868 (!target || (! wm->high || evbuffer_get_length(target) < wm->high))) {
michael@0 869 int n_to_write;
michael@0 870 if (wm && wm->high)
michael@0 871 n_to_write = wm->high - evbuffer_get_length(target);
michael@0 872 else
michael@0 873 n_to_write = WRITE_FRAME;
michael@0 874 r = do_write(bev_ssl, n_to_write);
michael@0 875 if (r & (OP_BLOCKED|OP_ERR))
michael@0 876 break;
michael@0 877 }
michael@0 878
michael@0 879 if (!bev_ssl->underlying) {
michael@0 880 if (evbuffer_get_length(output) == 0) {
michael@0 881 event_del(&bev_ssl->bev.bev.ev_write);
michael@0 882 } else if (bev_ssl->bev.write_suspended ||
michael@0 883 !(bev_ssl->bev.bev.enabled & EV_WRITE)) {
michael@0 884 /* Should be redundant, but let's avoid busy-looping */
michael@0 885 event_del(&bev_ssl->bev.bev.ev_write);
michael@0 886 }
michael@0 887 }
michael@0 888 }
michael@0 889
michael@0 890 static void
michael@0 891 be_openssl_readcb(struct bufferevent *bev_base, void *ctx)
michael@0 892 {
michael@0 893 struct bufferevent_openssl *bev_ssl = ctx;
michael@0 894 consider_reading(bev_ssl);
michael@0 895 }
michael@0 896
michael@0 897 static void
michael@0 898 be_openssl_writecb(struct bufferevent *bev_base, void *ctx)
michael@0 899 {
michael@0 900 struct bufferevent_openssl *bev_ssl = ctx;
michael@0 901 consider_writing(bev_ssl);
michael@0 902 }
michael@0 903
michael@0 904 static void
michael@0 905 be_openssl_eventcb(struct bufferevent *bev_base, short what, void *ctx)
michael@0 906 {
michael@0 907 struct bufferevent_openssl *bev_ssl = ctx;
michael@0 908 int event = 0;
michael@0 909
michael@0 910 if (what & BEV_EVENT_EOF) {
michael@0 911 if (bev_ssl->allow_dirty_shutdown)
michael@0 912 event = BEV_EVENT_EOF;
michael@0 913 else
michael@0 914 event = BEV_EVENT_ERROR;
michael@0 915 } else if (what & BEV_EVENT_TIMEOUT) {
michael@0 916 /* We sure didn't set this. Propagate it to the user. */
michael@0 917 event = what;
michael@0 918 } else if (what & BEV_EVENT_ERROR) {
michael@0 919 /* An error occurred on the connection. Propagate it to the user. */
michael@0 920 event = what;
michael@0 921 } else if (what & BEV_EVENT_CONNECTED) {
michael@0 922 /* Ignore it. We're saying SSL_connect() already, which will
michael@0 923 eat it. */
michael@0 924 }
michael@0 925 if (event)
michael@0 926 _bufferevent_run_eventcb(&bev_ssl->bev.bev, event);
michael@0 927 }
michael@0 928
michael@0 929 static void
michael@0 930 be_openssl_readeventcb(evutil_socket_t fd, short what, void *ptr)
michael@0 931 {
michael@0 932 struct bufferevent_openssl *bev_ssl = ptr;
michael@0 933 _bufferevent_incref_and_lock(&bev_ssl->bev.bev);
michael@0 934 if (what == EV_TIMEOUT) {
michael@0 935 _bufferevent_run_eventcb(&bev_ssl->bev.bev,
michael@0 936 BEV_EVENT_TIMEOUT|BEV_EVENT_READING);
michael@0 937 } else {
michael@0 938 consider_reading(bev_ssl);
michael@0 939 }
michael@0 940 _bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
michael@0 941 }
michael@0 942
michael@0 943 static void
michael@0 944 be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
michael@0 945 {
michael@0 946 struct bufferevent_openssl *bev_ssl = ptr;
michael@0 947 _bufferevent_incref_and_lock(&bev_ssl->bev.bev);
michael@0 948 if (what == EV_TIMEOUT) {
michael@0 949 _bufferevent_run_eventcb(&bev_ssl->bev.bev,
michael@0 950 BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING);
michael@0 951 } else {
michael@0 952 consider_writing(bev_ssl);
michael@0 953 }
michael@0 954 _bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
michael@0 955 }
michael@0 956
michael@0 957 static int
michael@0 958 set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
michael@0 959 {
michael@0 960 if (bev_ssl->underlying) {
michael@0 961 bufferevent_setcb(bev_ssl->underlying,
michael@0 962 be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
michael@0 963 bev_ssl);
michael@0 964 return 0;
michael@0 965 } else {
michael@0 966 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 967 int rpending=0, wpending=0, r1=0, r2=0;
michael@0 968 if (fd < 0 && bev_ssl->fd_is_set)
michael@0 969 fd = event_get_fd(&bev->ev_read);
michael@0 970 if (bev_ssl->fd_is_set) {
michael@0 971 rpending = event_pending(&bev->ev_read, EV_READ, NULL);
michael@0 972 wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
michael@0 973 event_del(&bev->ev_read);
michael@0 974 event_del(&bev->ev_write);
michael@0 975 }
michael@0 976 event_assign(&bev->ev_read, bev->ev_base, fd,
michael@0 977 EV_READ|EV_PERSIST, be_openssl_readeventcb, bev_ssl);
michael@0 978 event_assign(&bev->ev_write, bev->ev_base, fd,
michael@0 979 EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl);
michael@0 980 if (rpending)
michael@0 981 r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
michael@0 982 if (wpending)
michael@0 983 r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
michael@0 984 if (fd >= 0) {
michael@0 985 bev_ssl->fd_is_set = 1;
michael@0 986 }
michael@0 987 return (r1<0 || r2<0) ? -1 : 0;
michael@0 988 }
michael@0 989 }
michael@0 990
michael@0 991 static int
michael@0 992 do_handshake(struct bufferevent_openssl *bev_ssl)
michael@0 993 {
michael@0 994 int r;
michael@0 995
michael@0 996 switch (bev_ssl->state) {
michael@0 997 default:
michael@0 998 case BUFFEREVENT_SSL_OPEN:
michael@0 999 EVUTIL_ASSERT(0);
michael@0 1000 return -1;
michael@0 1001 case BUFFEREVENT_SSL_CONNECTING:
michael@0 1002 case BUFFEREVENT_SSL_ACCEPTING:
michael@0 1003 r = SSL_do_handshake(bev_ssl->ssl);
michael@0 1004 break;
michael@0 1005 }
michael@0 1006 decrement_buckets(bev_ssl);
michael@0 1007
michael@0 1008 if (r==1) {
michael@0 1009 /* We're done! */
michael@0 1010 bev_ssl->state = BUFFEREVENT_SSL_OPEN;
michael@0 1011 set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */
michael@0 1012 /* Call do_read and do_write as needed */
michael@0 1013 bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
michael@0 1014 _bufferevent_run_eventcb(&bev_ssl->bev.bev,
michael@0 1015 BEV_EVENT_CONNECTED);
michael@0 1016 return 1;
michael@0 1017 } else {
michael@0 1018 int err = SSL_get_error(bev_ssl->ssl, r);
michael@0 1019 print_err(err);
michael@0 1020 switch (err) {
michael@0 1021 case SSL_ERROR_WANT_WRITE:
michael@0 1022 if (!bev_ssl->underlying) {
michael@0 1023 stop_reading(bev_ssl);
michael@0 1024 return start_writing(bev_ssl);
michael@0 1025 }
michael@0 1026 return 0;
michael@0 1027 case SSL_ERROR_WANT_READ:
michael@0 1028 if (!bev_ssl->underlying) {
michael@0 1029 stop_writing(bev_ssl);
michael@0 1030 return start_reading(bev_ssl);
michael@0 1031 }
michael@0 1032 return 0;
michael@0 1033 default:
michael@0 1034 conn_closed(bev_ssl, err, r);
michael@0 1035 return -1;
michael@0 1036 }
michael@0 1037 }
michael@0 1038 }
michael@0 1039
michael@0 1040 static void
michael@0 1041 be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
michael@0 1042 {
michael@0 1043 struct bufferevent_openssl *bev_ssl = ctx;
michael@0 1044 do_handshake(bev_ssl);/* XXX handle failure */
michael@0 1045 }
michael@0 1046
michael@0 1047 static void
michael@0 1048 be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
michael@0 1049 {
michael@0 1050 struct bufferevent_openssl *bev_ssl = ptr;
michael@0 1051
michael@0 1052 _bufferevent_incref_and_lock(&bev_ssl->bev.bev);
michael@0 1053 if (what & EV_TIMEOUT) {
michael@0 1054 _bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT);
michael@0 1055 } else
michael@0 1056 do_handshake(bev_ssl);/* XXX handle failure */
michael@0 1057 _bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
michael@0 1058 }
michael@0 1059
michael@0 1060 static int
michael@0 1061 set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
michael@0 1062 {
michael@0 1063 if (bev_ssl->underlying) {
michael@0 1064 bufferevent_setcb(bev_ssl->underlying,
michael@0 1065 be_openssl_handshakecb, be_openssl_handshakecb,
michael@0 1066 be_openssl_eventcb,
michael@0 1067 bev_ssl);
michael@0 1068 return do_handshake(bev_ssl);
michael@0 1069 } else {
michael@0 1070 struct bufferevent *bev = &bev_ssl->bev.bev;
michael@0 1071 int r1=0, r2=0;
michael@0 1072 if (fd < 0 && bev_ssl->fd_is_set)
michael@0 1073 fd = event_get_fd(&bev->ev_read);
michael@0 1074 if (bev_ssl->fd_is_set) {
michael@0 1075 event_del(&bev->ev_read);
michael@0 1076 event_del(&bev->ev_write);
michael@0 1077 }
michael@0 1078 event_assign(&bev->ev_read, bev->ev_base, fd,
michael@0 1079 EV_READ|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);
michael@0 1080 event_assign(&bev->ev_write, bev->ev_base, fd,
michael@0 1081 EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);
michael@0 1082 if (fd >= 0) {
michael@0 1083 r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
michael@0 1084 r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
michael@0 1085 bev_ssl->fd_is_set = 1;
michael@0 1086 }
michael@0 1087 return (r1<0 || r2<0) ? -1 : 0;
michael@0 1088 }
michael@0 1089 }
michael@0 1090
michael@0 1091 int
michael@0 1092 bufferevent_ssl_renegotiate(struct bufferevent *bev)
michael@0 1093 {
michael@0 1094 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1095 if (!bev_ssl)
michael@0 1096 return -1;
michael@0 1097 if (SSL_renegotiate(bev_ssl->ssl) < 0)
michael@0 1098 return -1;
michael@0 1099 bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
michael@0 1100 if (set_handshake_callbacks(bev_ssl, -1) < 0)
michael@0 1101 return -1;
michael@0 1102 if (!bev_ssl->underlying)
michael@0 1103 return do_handshake(bev_ssl);
michael@0 1104 return 0;
michael@0 1105 }
michael@0 1106
michael@0 1107 static void
michael@0 1108 be_openssl_outbuf_cb(struct evbuffer *buf,
michael@0 1109 const struct evbuffer_cb_info *cbinfo, void *arg)
michael@0 1110 {
michael@0 1111 struct bufferevent_openssl *bev_ssl = arg;
michael@0 1112 int r = 0;
michael@0 1113 /* XXX need to hold a reference here. */
michael@0 1114
michael@0 1115 if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
michael@0 1116 if (cbinfo->orig_size == 0)
michael@0 1117 r = _bufferevent_add_event(&bev_ssl->bev.bev.ev_write,
michael@0 1118 &bev_ssl->bev.bev.timeout_write);
michael@0 1119 consider_writing(bev_ssl);
michael@0 1120 }
michael@0 1121 /* XXX Handle r < 0 */
michael@0 1122 (void)r;
michael@0 1123 }
michael@0 1124
michael@0 1125
michael@0 1126 static int
michael@0 1127 be_openssl_enable(struct bufferevent *bev, short events)
michael@0 1128 {
michael@0 1129 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1130 int r1 = 0, r2 = 0;
michael@0 1131
michael@0 1132 if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
michael@0 1133 return 0;
michael@0 1134
michael@0 1135 if (events & EV_READ)
michael@0 1136 r1 = start_reading(bev_ssl);
michael@0 1137 if (events & EV_WRITE)
michael@0 1138 r2 = start_writing(bev_ssl);
michael@0 1139
michael@0 1140 if (bev_ssl->underlying) {
michael@0 1141 if (events & EV_READ)
michael@0 1142 BEV_RESET_GENERIC_READ_TIMEOUT(bev);
michael@0 1143 if (events & EV_WRITE)
michael@0 1144 BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
michael@0 1145
michael@0 1146 if (events & EV_READ)
michael@0 1147 consider_reading(bev_ssl);
michael@0 1148 if (events & EV_WRITE)
michael@0 1149 consider_writing(bev_ssl);
michael@0 1150 }
michael@0 1151 return (r1 < 0 || r2 < 0) ? -1 : 0;
michael@0 1152 }
michael@0 1153
michael@0 1154 static int
michael@0 1155 be_openssl_disable(struct bufferevent *bev, short events)
michael@0 1156 {
michael@0 1157 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1158 if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
michael@0 1159 return 0;
michael@0 1160
michael@0 1161 if (events & EV_READ)
michael@0 1162 stop_reading(bev_ssl);
michael@0 1163 if (events & EV_WRITE)
michael@0 1164 stop_writing(bev_ssl);
michael@0 1165
michael@0 1166 if (bev_ssl->underlying) {
michael@0 1167 if (events & EV_READ)
michael@0 1168 BEV_DEL_GENERIC_READ_TIMEOUT(bev);
michael@0 1169 if (events & EV_WRITE)
michael@0 1170 BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
michael@0 1171 }
michael@0 1172 return 0;
michael@0 1173 }
michael@0 1174
michael@0 1175 static void
michael@0 1176 be_openssl_destruct(struct bufferevent *bev)
michael@0 1177 {
michael@0 1178 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1179
michael@0 1180 if (bev_ssl->underlying) {
michael@0 1181 _bufferevent_del_generic_timeout_cbs(bev);
michael@0 1182 } else {
michael@0 1183 event_del(&bev->ev_read);
michael@0 1184 event_del(&bev->ev_write);
michael@0 1185 }
michael@0 1186
michael@0 1187 if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
michael@0 1188 if (bev_ssl->underlying) {
michael@0 1189 if (BEV_UPCAST(bev_ssl->underlying)->refcnt < 2) {
michael@0 1190 event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "
michael@0 1191 "bufferevent with too few references");
michael@0 1192 } else {
michael@0 1193 bufferevent_free(bev_ssl->underlying);
michael@0 1194 bev_ssl->underlying = NULL;
michael@0 1195 }
michael@0 1196 } else {
michael@0 1197 evutil_socket_t fd = -1;
michael@0 1198 BIO *bio = SSL_get_wbio(bev_ssl->ssl);
michael@0 1199 if (bio)
michael@0 1200 fd = BIO_get_fd(bio, NULL);
michael@0 1201 if (fd >= 0)
michael@0 1202 evutil_closesocket(fd);
michael@0 1203 }
michael@0 1204 SSL_free(bev_ssl->ssl);
michael@0 1205 } else {
michael@0 1206 if (bev_ssl->underlying) {
michael@0 1207 if (bev_ssl->underlying->errorcb == be_openssl_eventcb)
michael@0 1208 bufferevent_setcb(bev_ssl->underlying,
michael@0 1209 NULL,NULL,NULL,NULL);
michael@0 1210 bufferevent_unsuspend_read(bev_ssl->underlying,
michael@0 1211 BEV_SUSPEND_FILT_READ);
michael@0 1212 }
michael@0 1213 }
michael@0 1214 }
michael@0 1215
michael@0 1216 static int
michael@0 1217 be_openssl_adj_timeouts(struct bufferevent *bev)
michael@0 1218 {
michael@0 1219 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1220
michael@0 1221 if (bev_ssl->underlying)
michael@0 1222 return _bufferevent_generic_adj_timeouts(bev);
michael@0 1223 else {
michael@0 1224 int r1=0, r2=0;
michael@0 1225 if (event_pending(&bev->ev_read, EV_READ, NULL))
michael@0 1226 r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
michael@0 1227 if (event_pending(&bev->ev_write, EV_WRITE, NULL))
michael@0 1228 r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
michael@0 1229 return (r1<0 || r2<0) ? -1 : 0;
michael@0 1230 }
michael@0 1231 }
michael@0 1232
michael@0 1233 static int
michael@0 1234 be_openssl_flush(struct bufferevent *bufev,
michael@0 1235 short iotype, enum bufferevent_flush_mode mode)
michael@0 1236 {
michael@0 1237 /* XXXX Implement this. */
michael@0 1238 return 0;
michael@0 1239 }
michael@0 1240
michael@0 1241 static int
michael@0 1242 be_openssl_ctrl(struct bufferevent *bev,
michael@0 1243 enum bufferevent_ctrl_op op, union bufferevent_ctrl_data *data)
michael@0 1244 {
michael@0 1245 struct bufferevent_openssl *bev_ssl = upcast(bev);
michael@0 1246 switch (op) {
michael@0 1247 case BEV_CTRL_SET_FD:
michael@0 1248 if (bev_ssl->underlying)
michael@0 1249 return -1;
michael@0 1250 {
michael@0 1251 BIO *bio;
michael@0 1252 bio = BIO_new_socket(data->fd, 0);
michael@0 1253 SSL_set_bio(bev_ssl->ssl, bio, bio);
michael@0 1254 bev_ssl->fd_is_set = 1;
michael@0 1255 }
michael@0 1256 if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
michael@0 1257 return set_open_callbacks(bev_ssl, data->fd);
michael@0 1258 else {
michael@0 1259 return set_handshake_callbacks(bev_ssl, data->fd);
michael@0 1260 }
michael@0 1261 case BEV_CTRL_GET_FD:
michael@0 1262 if (bev_ssl->underlying)
michael@0 1263 return -1;
michael@0 1264 if (!bev_ssl->fd_is_set)
michael@0 1265 return -1;
michael@0 1266 data->fd = event_get_fd(&bev->ev_read);
michael@0 1267 return 0;
michael@0 1268 case BEV_CTRL_GET_UNDERLYING:
michael@0 1269 if (!bev_ssl->underlying)
michael@0 1270 return -1;
michael@0 1271 data->ptr = bev_ssl->underlying;
michael@0 1272 return 0;
michael@0 1273 case BEV_CTRL_CANCEL_ALL:
michael@0 1274 default:
michael@0 1275 return -1;
michael@0 1276 }
michael@0 1277 }
michael@0 1278
michael@0 1279 SSL *
michael@0 1280 bufferevent_openssl_get_ssl(struct bufferevent *bufev)
michael@0 1281 {
michael@0 1282 struct bufferevent_openssl *bev_ssl = upcast(bufev);
michael@0 1283 if (!bev_ssl)
michael@0 1284 return NULL;
michael@0 1285 return bev_ssl->ssl;
michael@0 1286 }
michael@0 1287
michael@0 1288 static struct bufferevent *
michael@0 1289 bufferevent_openssl_new_impl(struct event_base *base,
michael@0 1290 struct bufferevent *underlying,
michael@0 1291 evutil_socket_t fd,
michael@0 1292 SSL *ssl,
michael@0 1293 enum bufferevent_ssl_state state,
michael@0 1294 int options)
michael@0 1295 {
michael@0 1296 struct bufferevent_openssl *bev_ssl = NULL;
michael@0 1297 struct bufferevent_private *bev_p = NULL;
michael@0 1298 int tmp_options = options & ~BEV_OPT_THREADSAFE;
michael@0 1299
michael@0 1300 if (underlying != NULL && fd >= 0)
michael@0 1301 return NULL; /* Only one can be set. */
michael@0 1302
michael@0 1303 if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))
michael@0 1304 goto err;
michael@0 1305
michael@0 1306 bev_p = &bev_ssl->bev;
michael@0 1307
michael@0 1308 if (bufferevent_init_common(bev_p, base,
michael@0 1309 &bufferevent_ops_openssl, tmp_options) < 0)
michael@0 1310 goto err;
michael@0 1311
michael@0 1312 /* Don't explode if we decide to realloc a chunk we're writing from in
michael@0 1313 * the output buffer. */
michael@0 1314 SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
michael@0 1315
michael@0 1316 bev_ssl->underlying = underlying;
michael@0 1317 bev_ssl->ssl = ssl;
michael@0 1318
michael@0 1319 bev_ssl->outbuf_cb = evbuffer_add_cb(bev_p->bev.output,
michael@0 1320 be_openssl_outbuf_cb, bev_ssl);
michael@0 1321
michael@0 1322 if (options & BEV_OPT_THREADSAFE)
michael@0 1323 bufferevent_enable_locking(&bev_ssl->bev.bev, NULL);
michael@0 1324
michael@0 1325 if (underlying) {
michael@0 1326 _bufferevent_init_generic_timeout_cbs(&bev_ssl->bev.bev);
michael@0 1327 bufferevent_incref(underlying);
michael@0 1328 }
michael@0 1329
michael@0 1330 bev_ssl->state = state;
michael@0 1331 bev_ssl->last_write = -1;
michael@0 1332
michael@0 1333 init_bio_counts(bev_ssl);
michael@0 1334
michael@0 1335 switch (state) {
michael@0 1336 case BUFFEREVENT_SSL_ACCEPTING:
michael@0 1337 SSL_set_accept_state(bev_ssl->ssl);
michael@0 1338 if (set_handshake_callbacks(bev_ssl, fd) < 0)
michael@0 1339 goto err;
michael@0 1340 break;
michael@0 1341 case BUFFEREVENT_SSL_CONNECTING:
michael@0 1342 SSL_set_connect_state(bev_ssl->ssl);
michael@0 1343 if (set_handshake_callbacks(bev_ssl, fd) < 0)
michael@0 1344 goto err;
michael@0 1345 break;
michael@0 1346 case BUFFEREVENT_SSL_OPEN:
michael@0 1347 if (set_open_callbacks(bev_ssl, fd) < 0)
michael@0 1348 goto err;
michael@0 1349 break;
michael@0 1350 default:
michael@0 1351 goto err;
michael@0 1352 }
michael@0 1353
michael@0 1354 if (underlying) {
michael@0 1355 bufferevent_setwatermark(underlying, EV_READ, 0, 0);
michael@0 1356 bufferevent_enable(underlying, EV_READ|EV_WRITE);
michael@0 1357 if (state == BUFFEREVENT_SSL_OPEN)
michael@0 1358 bufferevent_suspend_read(underlying,
michael@0 1359 BEV_SUSPEND_FILT_READ);
michael@0 1360 } else {
michael@0 1361 bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
michael@0 1362 if (bev_ssl->fd_is_set) {
michael@0 1363 if (state != BUFFEREVENT_SSL_OPEN)
michael@0 1364 if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
michael@0 1365 goto err;
michael@0 1366 if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
michael@0 1367 goto err;
michael@0 1368 }
michael@0 1369 }
michael@0 1370
michael@0 1371 return &bev_ssl->bev.bev;
michael@0 1372 err:
michael@0 1373 if (bev_ssl)
michael@0 1374 bufferevent_free(&bev_ssl->bev.bev);
michael@0 1375 return NULL;
michael@0 1376 }
michael@0 1377
michael@0 1378 struct bufferevent *
michael@0 1379 bufferevent_openssl_filter_new(struct event_base *base,
michael@0 1380 struct bufferevent *underlying,
michael@0 1381 SSL *ssl,
michael@0 1382 enum bufferevent_ssl_state state,
michael@0 1383 int options)
michael@0 1384 {
michael@0 1385 /* We don't tell the BIO to close the bufferevent; we do it ourselves
michael@0 1386 * on be_openssl_destruct */
michael@0 1387 int close_flag = 0; /* options & BEV_OPT_CLOSE_ON_FREE; */
michael@0 1388 BIO *bio;
michael@0 1389 if (!underlying)
michael@0 1390 return NULL;
michael@0 1391 if (!(bio = BIO_new_bufferevent(underlying, close_flag)))
michael@0 1392 return NULL;
michael@0 1393
michael@0 1394 SSL_set_bio(ssl, bio, bio);
michael@0 1395
michael@0 1396 return bufferevent_openssl_new_impl(
michael@0 1397 base, underlying, -1, ssl, state, options);
michael@0 1398 }
michael@0 1399
michael@0 1400 struct bufferevent *
michael@0 1401 bufferevent_openssl_socket_new(struct event_base *base,
michael@0 1402 evutil_socket_t fd,
michael@0 1403 SSL *ssl,
michael@0 1404 enum bufferevent_ssl_state state,
michael@0 1405 int options)
michael@0 1406 {
michael@0 1407 /* Does the SSL already have an fd? */
michael@0 1408 BIO *bio = SSL_get_wbio(ssl);
michael@0 1409 long have_fd = -1;
michael@0 1410
michael@0 1411 if (bio)
michael@0 1412 have_fd = BIO_get_fd(bio, NULL);
michael@0 1413
michael@0 1414 if (have_fd >= 0) {
michael@0 1415 /* The SSL is already configured with an fd. */
michael@0 1416 if (fd < 0) {
michael@0 1417 /* We should learn the fd from the SSL. */
michael@0 1418 fd = (evutil_socket_t) have_fd;
michael@0 1419 } else if (have_fd == (long)fd) {
michael@0 1420 /* We already know the fd from the SSL; do nothing */
michael@0 1421 } else {
michael@0 1422 /* We specified an fd different from that of the SSL.
michael@0 1423 This is probably an error on our part. Fail. */
michael@0 1424 return NULL;
michael@0 1425 }
michael@0 1426 (void) BIO_set_close(bio, 0);
michael@0 1427 } else {
michael@0 1428 /* The SSL isn't configured with a BIO with an fd. */
michael@0 1429 if (fd >= 0) {
michael@0 1430 /* ... and we have an fd we want to use. */
michael@0 1431 bio = BIO_new_socket(fd, 0);
michael@0 1432 SSL_set_bio(ssl, bio, bio);
michael@0 1433 } else {
michael@0 1434 /* Leave the fd unset. */
michael@0 1435 }
michael@0 1436 }
michael@0 1437
michael@0 1438 return bufferevent_openssl_new_impl(
michael@0 1439 base, NULL, fd, ssl, state, options);
michael@0 1440 }
michael@0 1441
michael@0 1442 unsigned long
michael@0 1443 bufferevent_get_openssl_error(struct bufferevent *bev)
michael@0 1444 {
michael@0 1445 unsigned long err = 0;
michael@0 1446 struct bufferevent_openssl *bev_ssl;
michael@0 1447 BEV_LOCK(bev);
michael@0 1448 bev_ssl = upcast(bev);
michael@0 1449 if (bev_ssl && bev_ssl->n_errors) {
michael@0 1450 err = bev_ssl->errors[--bev_ssl->n_errors];
michael@0 1451 }
michael@0 1452 BEV_UNLOCK(bev);
michael@0 1453 return err;
michael@0 1454 }

mercurial