Home | History | Annotate | Line # | Download | only in test
      1  1.7  christos /*	$NetBSD: regress_ssl.c,v 1.8 2024/08/18 20:47:23 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
      5  1.1  christos  *
      6  1.1  christos  * Redistribution and use in source and binary forms, with or without
      7  1.1  christos  * modification, are permitted provided that the following conditions
      8  1.1  christos  * are met:
      9  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     10  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     11  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  christos  *    documentation and/or other materials provided with the distribution.
     14  1.1  christos  * 3. The name of the author may not be used to endorse or promote products
     15  1.1  christos  *    derived from this software without specific prior written permission.
     16  1.1  christos  *
     17  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  1.1  christos  */
     28  1.1  christos 
     29  1.2  christos // Get rid of OSX 10.7 and greater deprecation warnings.
     30  1.2  christos #if defined(__APPLE__) && defined(__clang__)
     31  1.2  christos #pragma clang diagnostic ignored "-Wdeprecated-declarations"
     32  1.2  christos #endif
     33  1.2  christos 
     34  1.1  christos #ifdef _WIN32
     35  1.1  christos #include <winsock2.h>
     36  1.1  christos #include <windows.h>
     37  1.1  christos #endif
     38  1.1  christos 
     39  1.8  christos #include "util-internal.h"
     40  1.8  christos 
     41  1.1  christos #ifndef _WIN32
     42  1.1  christos #include <sys/types.h>
     43  1.1  christos #include <sys/socket.h>
     44  1.1  christos #include <netinet/in.h>
     45  1.1  christos #endif
     46  1.1  christos 
     47  1.1  christos #include "event2/util.h"
     48  1.1  christos #include "event2/event.h"
     49  1.1  christos #include "event2/bufferevent_ssl.h"
     50  1.8  christos #include "event2/bufferevent_struct.h"
     51  1.1  christos #include "event2/buffer.h"
     52  1.1  christos #include "event2/listener.h"
     53  1.1  christos 
     54  1.1  christos #include "regress.h"
     55  1.1  christos #include "tinytest.h"
     56  1.1  christos #include "tinytest_macros.h"
     57  1.1  christos 
     58  1.1  christos #include <openssl/err.h>
     59  1.1  christos #include <openssl/pem.h>
     60  1.8  christos #include "openssl-compat.h"
     61  1.1  christos 
     62  1.1  christos #include <string.h>
     63  1.8  christos #ifdef _WIN32
     64  1.8  christos #include <io.h>
     65  1.8  christos #define read _read
     66  1.8  christos #define write _write
     67  1.8  christos #else
     68  1.8  christos #include <unistd.h>
     69  1.8  christos #endif
     70  1.1  christos 
     71  1.8  christos /* A pre-generated key, to save the cost of doing an RSA key generation step
     72  1.8  christos  * during the unit tests. It is published in this file, so you would have to
     73  1.8  christos  * be very foolish to consider using it in your own code. */
     74  1.1  christos static const char KEY[] =
     75  1.1  christos     "-----BEGIN RSA PRIVATE KEY-----\n"
     76  1.8  christos     "MIIEogIBAAKCAQEAtK07Ili0dkJb79m/sFmHoVJTWyLoveXex2yX/BtUzzcvZEOu\n"
     77  1.8  christos     "QLon/++5YOA48kzZm5K9mIwZkZhui1ZgJ5Bjq0LGAWTZGIn+NXjLFshPYvTKpOCW\n"
     78  1.8  christos     "uzL0Ir0LXMsBLYJQ5A4FomLNxs4I3H/dhDSGy/rSiJB1B4w2xNiwPK08/VL3zZqk\n"
     79  1.8  christos     "V+GsSvGIIkzhTMbqPJy9K8pqyjwOU2pgORS794yXciTGxWYjTDzJPgQ35YMDATaG\n"
     80  1.8  christos     "jr4HHo1zxU/Lj0pndSUK5rKLYxYQ3Uc8B3AVYDl9CP/GbOoQ4LBzS68JjcAUyp6i\n"
     81  1.8  christos     "6NfXlc2D9S9XgqVqwI+JqgJs0eW/+zPY2UEDWwIDAQABAoIBAD2HzV66FOM9YDAD\n"
     82  1.8  christos     "2RtGskEHV2nvLpIVadRCsFPkPvK+2X3s6rgSbbLkwh4y3lHuSCGKTNVZyQ9jeSos\n"
     83  1.8  christos     "xVxT+Q2HFQW+gYyw2gj91TQyDY8mzKhv8AVaqff2p5r3a7RC8CdqexK9UVUGL9Bg\n"
     84  1.8  christos     "H2F5vfpTtkVZ5PEoGDLblNFlMiMW/t1SobUeBVx+Msco/xqk9lFv1A9nnepGy0Gi\n"
     85  1.8  christos     "D+i6YNGTBsX22YhoCZl/ICxCL8lgqPei4FvBr9dBVh/jQgjuUBm2jz55p2r7+7Aw\n"
     86  1.8  christos     "khmXHReejoVokQ2+htgSgZNKlKuDy710ZpBqnDi8ynQi82Y2qCpyg/p/xcER54B6\n"
     87  1.8  christos     "hSftaiECgYEA2RkSoxU+nWk+BClQEUZRi88QK5W/M8oo1DvUs36hvPFkw3Jk/gz0\n"
     88  1.8  christos     "fgd5bnA+MXj0Fc0QHvbddPjIkyoI/evq9GPV+JYIuH5zabrlI3Jvya8q9QpAcEDO\n"
     89  1.8  christos     "KkL/O09qXVEW52S6l05nh4PLejyI7aTyTIN5nbVLac/+M8MY/qOjZksCgYEA1Q1o\n"
     90  1.8  christos     "L8kjSavU2xhQmSgZb9W62Do60sa3e73ljrDPoiyvbExldpSdziFYxHBD/Rep0ePf\n"
     91  1.8  christos     "eVSGS3VSwevt9/jSGo2Oa83TYYns9agBm03oR/Go/DukESdI792NsEM+PRFypVNy\n"
     92  1.8  christos     "AohWRLj0UU6DV+zLKp0VBavtx0ATeLFX0eN17TECgYBI2O/3Bz7uhQ0JSm+SjFz6\n"
     93  1.8  christos     "o+2SInp5P2G57aWu4VQWWY3tQ2p+EQzNaWam10UXRrXoxtmc+ktPX9e2AgnoYoyB\n"
     94  1.8  christos     "myqGcpnUhqHlnZAb999o9r1cYidDQ4uqhLauSTSwwXAFDzjJYsa8o03Y440y6QFh\n"
     95  1.8  christos     "CVD6yYXXqLJs3g96CqDexwKBgAHxq1+0QCQt8zVElYewO/svQhMzBNJjic0RQIT6\n"
     96  1.8  christos     "zAo4yij80XgxhvcYiszQEW6/xobpw2JCCS+rFGQ8mOFIXfJsFD6blDAxp/3d2JXo\n"
     97  1.8  christos     "MhRl+hrDGI4ng5zcsqxHEMxR2m/zwPiQ8eiSn3gWdVBaEsiCwmxY00ScKxFQ3PJH\n"
     98  1.8  christos     "Vw4hAoGAdZLd8KfjjG6lg7hfpVqavstqVi9LOgkHeCfdjn7JP+76kYrgLk/XdkrP\n"
     99  1.8  christos     "N/BHhtFVFjOi/mTQfQ5YfZImkm/1ePBy7437DT8BDkOxspa50kK4HPggHnU64h1w\n"
    100  1.8  christos     "lhdEOj7mAgHwGwwVZWOgs9Lq6vfztnSuhqjha1daESY6kDscPIQ=\n"
    101  1.1  christos     "-----END RSA PRIVATE KEY-----\n";
    102  1.1  christos 
    103  1.8  christos EVP_PKEY *
    104  1.8  christos ssl_getkey(void)
    105  1.1  christos {
    106  1.1  christos 	EVP_PKEY *key;
    107  1.1  christos 	BIO *bio;
    108  1.1  christos 
    109  1.1  christos 	/* new read-only BIO backed by KEY. */
    110  1.1  christos 	bio = BIO_new_mem_buf((char*)KEY, -1);
    111  1.1  christos 	tt_assert(bio);
    112  1.1  christos 
    113  1.1  christos 	key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
    114  1.1  christos 	BIO_free(bio);
    115  1.1  christos 	tt_assert(key);
    116  1.1  christos 
    117  1.1  christos 	return key;
    118  1.1  christos end:
    119  1.1  christos 	return NULL;
    120  1.1  christos }
    121  1.1  christos 
    122  1.8  christos X509 *
    123  1.8  christos ssl_getcert(EVP_PKEY *key)
    124  1.1  christos {
    125  1.1  christos 	/* Dummy code to make a quick-and-dirty valid certificate with
    126  1.1  christos 	   OpenSSL.  Don't copy this code into your own program! It does a
    127  1.1  christos 	   number of things in a stupid and insecure way. */
    128  1.1  christos 	X509 *x509 = NULL;
    129  1.1  christos 	X509_NAME *name = NULL;
    130  1.1  christos 	int nid;
    131  1.1  christos 	time_t now = time(NULL);
    132  1.1  christos 
    133  1.1  christos 	tt_assert(key);
    134  1.1  christos 
    135  1.1  christos 	x509 = X509_new();
    136  1.1  christos 	tt_assert(x509);
    137  1.1  christos 	tt_assert(0 != X509_set_version(x509, 2));
    138  1.1  christos 	tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509),
    139  1.1  christos 		(long)now));
    140  1.1  christos 
    141  1.1  christos 	name = X509_NAME_new();
    142  1.1  christos 	tt_assert(name);
    143  1.1  christos 	nid = OBJ_txt2nid("commonName");
    144  1.1  christos 	tt_assert(NID_undef != nid);
    145  1.1  christos 	tt_assert(0 != X509_NAME_add_entry_by_NID(
    146  1.1  christos 		    name, nid, MBSTRING_ASC, (unsigned char*)"example.com",
    147  1.1  christos 		    -1, -1, 0));
    148  1.1  christos 
    149  1.1  christos 	X509_set_subject_name(x509, name);
    150  1.1  christos 	X509_set_issuer_name(x509, name);
    151  1.8  christos 	X509_NAME_free(name);
    152  1.1  christos 
    153  1.6  christos 	X509_time_adj(X509_getm_notBefore(x509), 0, &now);
    154  1.6  christos 	now += 3600;
    155  1.6  christos 	X509_time_adj(X509_getm_notAfter(x509), 0, &now);
    156  1.1  christos 	X509_set_pubkey(x509, key);
    157  1.1  christos 	tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
    158  1.1  christos 
    159  1.1  christos 	return x509;
    160  1.1  christos end:
    161  1.1  christos 	X509_free(x509);
    162  1.8  christos 	X509_NAME_free(name);
    163  1.1  christos 	return NULL;
    164  1.1  christos }
    165  1.1  christos 
    166  1.1  christos static int disable_tls_11_and_12 = 0;
    167  1.1  christos static SSL_CTX *the_ssl_ctx = NULL;
    168  1.1  christos 
    169  1.8  christos SSL_CTX *
    170  1.1  christos get_ssl_ctx(void)
    171  1.1  christos {
    172  1.1  christos 	if (the_ssl_ctx)
    173  1.1  christos 		return the_ssl_ctx;
    174  1.1  christos 	the_ssl_ctx = SSL_CTX_new(SSLv23_method());
    175  1.1  christos 	if (!the_ssl_ctx)
    176  1.1  christos 		return NULL;
    177  1.1  christos 	if (disable_tls_11_and_12) {
    178  1.1  christos #ifdef SSL_OP_NO_TLSv1_2
    179  1.1  christos 		SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
    180  1.1  christos #endif
    181  1.1  christos #ifdef SSL_OP_NO_TLSv1_1
    182  1.1  christos 		SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
    183  1.1  christos #endif
    184  1.1  christos 	}
    185  1.1  christos 	return the_ssl_ctx;
    186  1.1  christos }
    187  1.1  christos 
    188  1.8  christos static int test_is_done;
    189  1.8  christos static int n_connected;
    190  1.8  christos static int got_close;
    191  1.8  christos static int got_error;
    192  1.8  christos static int got_timeout;
    193  1.8  christos static int renegotiate_at = -1;
    194  1.8  christos static int stop_when_connected;
    195  1.8  christos static int pending_connect_events;
    196  1.8  christos static struct event_base *exit_base;
    197  1.8  christos static X509 *the_cert;
    198  1.8  christos EVP_PKEY *the_key;
    199  1.8  christos 
    200  1.8  christos void
    201  1.1  christos init_ssl(void)
    202  1.1  christos {
    203  1.8  christos #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
    204  1.8  christos 	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
    205  1.1  christos 	SSL_library_init();
    206  1.1  christos 	ERR_load_crypto_strings();
    207  1.1  christos 	SSL_load_error_strings();
    208  1.1  christos 	OpenSSL_add_all_algorithms();
    209  1.8  christos 	if (SSLeay() != OPENSSL_VERSION_NUMBER) {
    210  1.8  christos 		TT_DECLARE("WARN",
    211  1.8  christos 			("Version mismatch for openssl: compiled with %lx but running with %lx",
    212  1.8  christos 			(unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
    213  1.1  christos 	}
    214  1.8  christos #endif
    215  1.1  christos }
    216  1.1  christos 
    217  1.8  christos static void *
    218  1.8  christos ssl_test_setup(const struct testcase_t *testcase)
    219  1.8  christos {
    220  1.8  christos 	init_ssl();
    221  1.8  christos 
    222  1.8  christos 	the_key = ssl_getkey();
    223  1.8  christos 	EVUTIL_ASSERT(the_key);
    224  1.8  christos 
    225  1.8  christos 	the_cert = ssl_getcert(the_key);
    226  1.8  christos 	EVUTIL_ASSERT(the_cert);
    227  1.8  christos 
    228  1.8  christos 	disable_tls_11_and_12 = 0;
    229  1.8  christos 
    230  1.8  christos 	return basic_test_setup(testcase);
    231  1.8  christos }
    232  1.8  christos static int
    233  1.8  christos ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
    234  1.8  christos {
    235  1.8  christos 	int ret = basic_test_cleanup(testcase, ptr);
    236  1.8  christos 	if (!ret) {
    237  1.8  christos 		return ret;
    238  1.8  christos 	}
    239  1.8  christos 
    240  1.8  christos 	test_is_done = 0;
    241  1.8  christos 	n_connected = 0;
    242  1.8  christos 	got_close = 0;
    243  1.8  christos 	got_error = 0;
    244  1.8  christos 	got_timeout = 0;
    245  1.8  christos 	renegotiate_at = -1;
    246  1.8  christos 	stop_when_connected = 0;
    247  1.8  christos 	pending_connect_events = 0;
    248  1.8  christos 	exit_base = NULL;
    249  1.8  christos 
    250  1.8  christos 	X509_free(the_cert);
    251  1.8  christos 	EVP_PKEY_free(the_key);
    252  1.8  christos 
    253  1.8  christos 	SSL_CTX_free(the_ssl_ctx);
    254  1.8  christos 	the_ssl_ctx = NULL;
    255  1.8  christos 
    256  1.8  christos 	return 1;
    257  1.8  christos }
    258  1.8  christos const struct testcase_setup_t ssl_setup = {
    259  1.8  christos 	ssl_test_setup, ssl_test_cleanup
    260  1.8  christos };
    261  1.8  christos 
    262  1.8  christos 
    263  1.1  christos /* ====================
    264  1.1  christos    Here's a simple test: we read a number from the input, increment it, and
    265  1.1  christos    reply, until we get to 1001.
    266  1.1  christos */
    267  1.1  christos 
    268  1.8  christos enum regress_openssl_type
    269  1.8  christos {
    270  1.8  christos 	REGRESS_OPENSSL_SOCKETPAIR = 1,
    271  1.8  christos 	REGRESS_OPENSSL_FILTER = 2,
    272  1.8  christos 	REGRESS_OPENSSL_RENEGOTIATE = 4,
    273  1.8  christos 	REGRESS_OPENSSL_OPEN = 8,
    274  1.8  christos 	REGRESS_OPENSSL_DIRTY_SHUTDOWN = 16,
    275  1.8  christos 	REGRESS_OPENSSL_FD = 32,
    276  1.8  christos 
    277  1.8  christos 	REGRESS_OPENSSL_CLIENT = 64,
    278  1.8  christos 	REGRESS_OPENSSL_SERVER = 128,
    279  1.8  christos 
    280  1.8  christos 	REGRESS_OPENSSL_FREED = 256,
    281  1.8  christos 	REGRESS_OPENSSL_TIMEOUT = 512,
    282  1.8  christos 	REGRESS_OPENSSL_SLEEP = 1024,
    283  1.8  christos 
    284  1.8  christos 	REGRESS_OPENSSL_CLIENT_WRITE = 2048,
    285  1.8  christos 
    286  1.8  christos 	REGRESS_DEFERRED_CALLBACKS = 4096,
    287  1.8  christos };
    288  1.8  christos 
    289  1.8  christos static void
    290  1.8  christos bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
    291  1.8  christos {
    292  1.8  christos 	tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
    293  1.8  christos 	tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
    294  1.8  christos 	if (filter) {
    295  1.8  christos 		tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
    296  1.8  christos 	} else {
    297  1.8  christos 		tt_fd_op(bufferevent_getfd(bev), ==, EVUTIL_INVALID_SOCKET);
    298  1.8  christos 	}
    299  1.8  christos 
    300  1.8  christos end:
    301  1.8  christos 	;
    302  1.8  christos }
    303  1.8  christos static void
    304  1.8  christos bufferevent_openssl_check_freed(struct bufferevent *bev)
    305  1.8  christos {
    306  1.8  christos 	tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
    307  1.8  christos 	tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
    308  1.8  christos 
    309  1.8  christos end:
    310  1.8  christos 	;
    311  1.8  christos }
    312  1.8  christos 
    313  1.8  christos static void
    314  1.8  christos free_on_cb(struct bufferevent *bev, void *ctx)
    315  1.8  christos {
    316  1.8  christos 	TT_BLATHER(("free_on_cb: %p", bev));
    317  1.8  christos 	bufferevent_free(bev);
    318  1.8  christos }
    319  1.1  christos 
    320  1.1  christos static void
    321  1.1  christos respond_to_number(struct bufferevent *bev, void *ctx)
    322  1.1  christos {
    323  1.1  christos 	struct evbuffer *b = bufferevent_get_input(bev);
    324  1.1  christos 	char *line;
    325  1.1  christos 	int n;
    326  1.8  christos 
    327  1.8  christos 	enum regress_openssl_type type;
    328  1.8  christos 	type = (enum regress_openssl_type)ctx;
    329  1.8  christos 
    330  1.1  christos 	line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
    331  1.1  christos 	if (! line)
    332  1.1  christos 		return;
    333  1.1  christos 	n = atoi(line);
    334  1.1  christos 	if (n <= 0)
    335  1.1  christos 		TT_FAIL(("Bad number: %s", line));
    336  1.3  christos 	free(line);
    337  1.1  christos 	TT_BLATHER(("The number was %d", n));
    338  1.1  christos 	if (n == 1001) {
    339  1.1  christos 		++test_is_done;
    340  1.1  christos 		bufferevent_free(bev); /* Should trigger close on other side. */
    341  1.1  christos 		return;
    342  1.1  christos 	}
    343  1.8  christos 	if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
    344  1.1  christos 		SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
    345  1.1  christos 	}
    346  1.1  christos 	++n;
    347  1.1  christos 	evbuffer_add_printf(bufferevent_get_output(bev),
    348  1.1  christos 	    "%d\n", n);
    349  1.1  christos 	TT_BLATHER(("Done reading; now writing."));
    350  1.1  christos 	bufferevent_enable(bev, EV_WRITE);
    351  1.1  christos 	bufferevent_disable(bev, EV_READ);
    352  1.1  christos }
    353  1.1  christos 
    354  1.1  christos static void
    355  1.1  christos done_writing_cb(struct bufferevent *bev, void *ctx)
    356  1.1  christos {
    357  1.1  christos 	struct evbuffer *b = bufferevent_get_output(bev);
    358  1.1  christos 	if (evbuffer_get_length(b))
    359  1.1  christos 		return;
    360  1.1  christos 	TT_BLATHER(("Done writing."));
    361  1.1  christos 	bufferevent_disable(bev, EV_WRITE);
    362  1.1  christos 	bufferevent_enable(bev, EV_READ);
    363  1.1  christos }
    364  1.1  christos 
    365  1.1  christos static void
    366  1.1  christos eventcb(struct bufferevent *bev, short what, void *ctx)
    367  1.1  christos {
    368  1.8  christos 	X509 *peer_cert = NULL;
    369  1.8  christos 	enum regress_openssl_type type;
    370  1.8  christos 
    371  1.8  christos 	type = (enum regress_openssl_type)ctx;
    372  1.8  christos 
    373  1.1  christos 	TT_BLATHER(("Got event %d", (int)what));
    374  1.1  christos 	if (what & BEV_EVENT_CONNECTED) {
    375  1.1  christos 		SSL *ssl;
    376  1.1  christos 		++n_connected;
    377  1.1  christos 		ssl = bufferevent_openssl_get_ssl(bev);
    378  1.1  christos 		tt_assert(ssl);
    379  1.1  christos 		peer_cert = SSL_get_peer_certificate(ssl);
    380  1.8  christos 		if (type & REGRESS_OPENSSL_SERVER) {
    381  1.1  christos 			tt_assert(peer_cert == NULL);
    382  1.1  christos 		} else {
    383  1.1  christos 			tt_assert(peer_cert != NULL);
    384  1.1  christos 		}
    385  1.1  christos 		if (stop_when_connected) {
    386  1.1  christos 			if (--pending_connect_events == 0)
    387  1.1  christos 				event_base_loopexit(exit_base, NULL);
    388  1.1  christos 		}
    389  1.8  christos 
    390  1.8  christos 		if ((type & REGRESS_OPENSSL_CLIENT_WRITE) && (type & REGRESS_OPENSSL_CLIENT))
    391  1.8  christos 			evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
    392  1.1  christos 	} else if (what & BEV_EVENT_EOF) {
    393  1.1  christos 		TT_BLATHER(("Got a good EOF"));
    394  1.1  christos 		++got_close;
    395  1.8  christos 		if (type & REGRESS_OPENSSL_FD) {
    396  1.8  christos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
    397  1.8  christos 		}
    398  1.8  christos 		if (type & REGRESS_OPENSSL_FREED) {
    399  1.8  christos 			bufferevent_openssl_check_freed(bev);
    400  1.8  christos 		}
    401  1.1  christos 		bufferevent_free(bev);
    402  1.1  christos 	} else if (what & BEV_EVENT_ERROR) {
    403  1.1  christos 		TT_BLATHER(("Got an error."));
    404  1.1  christos 		++got_error;
    405  1.8  christos 		if (type & REGRESS_OPENSSL_FD) {
    406  1.8  christos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
    407  1.8  christos 		}
    408  1.8  christos 		if (type & REGRESS_OPENSSL_FREED) {
    409  1.8  christos 			bufferevent_openssl_check_freed(bev);
    410  1.8  christos 		}
    411  1.8  christos 		bufferevent_free(bev);
    412  1.8  christos 	} else if (what & BEV_EVENT_TIMEOUT) {
    413  1.8  christos 		TT_BLATHER(("Got timeout."));
    414  1.8  christos 		++got_timeout;
    415  1.8  christos 		if (type & REGRESS_OPENSSL_FD) {
    416  1.8  christos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
    417  1.8  christos 		}
    418  1.8  christos 		if (type & REGRESS_OPENSSL_FREED) {
    419  1.8  christos 			bufferevent_openssl_check_freed(bev);
    420  1.8  christos 		}
    421  1.1  christos 		bufferevent_free(bev);
    422  1.1  christos 	}
    423  1.8  christos 
    424  1.1  christos end:
    425  1.8  christos 	if (peer_cert)
    426  1.8  christos 		X509_free(peer_cert);
    427  1.1  christos }
    428  1.1  christos 
    429  1.1  christos static void
    430  1.1  christos open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
    431  1.1  christos     struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
    432  1.8  christos     evutil_socket_t *fd_pair, struct bufferevent **underlying_pair,
    433  1.8  christos     enum regress_openssl_type type)
    434  1.1  christos {
    435  1.1  christos 	int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
    436  1.1  christos 	int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
    437  1.8  christos 	int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
    438  1.1  christos 	if (fd_pair) {
    439  1.1  christos 		*bev1_out = bufferevent_openssl_socket_new(
    440  1.1  christos 			base, fd_pair[0], ssl1, state1, flags);
    441  1.1  christos 		*bev2_out = bufferevent_openssl_socket_new(
    442  1.1  christos 			base, fd_pair[1], ssl2, state2, flags);
    443  1.1  christos 	} else {
    444  1.1  christos 		*bev1_out = bufferevent_openssl_filter_new(
    445  1.1  christos 			base, underlying_pair[0], ssl1, state1, flags);
    446  1.1  christos 		*bev2_out = bufferevent_openssl_filter_new(
    447  1.1  christos 			base, underlying_pair[1], ssl2, state2, flags);
    448  1.1  christos 
    449  1.1  christos 	}
    450  1.1  christos 	bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
    451  1.8  christos 	    eventcb, (void*)(REGRESS_OPENSSL_CLIENT | (long)type));
    452  1.1  christos 	bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
    453  1.8  christos 	    eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
    454  1.8  christos 
    455  1.8  christos 	bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
    456  1.8  christos 	bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
    457  1.1  christos }
    458  1.1  christos 
    459  1.1  christos static void
    460  1.1  christos regress_bufferevent_openssl(void *arg)
    461  1.1  christos {
    462  1.1  christos 	struct basic_test_data *data = arg;
    463  1.1  christos 
    464  1.1  christos 	struct bufferevent *bev1, *bev2;
    465  1.1  christos 	SSL *ssl1, *ssl2;
    466  1.1  christos 	int flags = BEV_OPT_DEFER_CALLBACKS;
    467  1.1  christos 	struct bufferevent *bev_ll[2] = { NULL, NULL };
    468  1.1  christos 	evutil_socket_t *fd_pair = NULL;
    469  1.1  christos 
    470  1.8  christos 	enum regress_openssl_type type;
    471  1.8  christos 	type = (enum regress_openssl_type)data->setup_data;
    472  1.1  christos 
    473  1.8  christos 	if (type & REGRESS_OPENSSL_RENEGOTIATE) {
    474  1.8  christos 		if (OPENSSL_VERSION_NUMBER >= 0x10001000 &&
    475  1.8  christos 		    OPENSSL_VERSION_NUMBER <  0x1000104f) {
    476  1.1  christos 			/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
    477  1.1  christos 			 * can't renegotiate with themselves. Disable. */
    478  1.1  christos 			disable_tls_11_and_12 = 1;
    479  1.1  christos 		}
    480  1.1  christos 		renegotiate_at = 600;
    481  1.1  christos 	}
    482  1.1  christos 
    483  1.1  christos 	ssl1 = SSL_new(get_ssl_ctx());
    484  1.1  christos 	ssl2 = SSL_new(get_ssl_ctx());
    485  1.1  christos 
    486  1.8  christos 	SSL_use_certificate(ssl2, the_cert);
    487  1.8  christos 	SSL_use_PrivateKey(ssl2, the_key);
    488  1.1  christos 
    489  1.8  christos 	if (!(type & REGRESS_OPENSSL_OPEN))
    490  1.1  christos 		flags |= BEV_OPT_CLOSE_ON_FREE;
    491  1.1  christos 
    492  1.8  christos 	if (!(type & REGRESS_OPENSSL_FILTER)) {
    493  1.8  christos 		tt_assert(type & REGRESS_OPENSSL_SOCKETPAIR);
    494  1.1  christos 		fd_pair = data->pair;
    495  1.1  christos 	} else {
    496  1.1  christos 		bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
    497  1.1  christos 		    BEV_OPT_CLOSE_ON_FREE);
    498  1.1  christos 		bev_ll[1] = bufferevent_socket_new(data->base, data->pair[1],
    499  1.1  christos 		    BEV_OPT_CLOSE_ON_FREE);
    500  1.1  christos 	}
    501  1.1  christos 
    502  1.1  christos 	open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
    503  1.8  christos 	    fd_pair, bev_ll, type);
    504  1.1  christos 
    505  1.8  christos 	if (!(type & REGRESS_OPENSSL_FILTER)) {
    506  1.8  christos 		tt_fd_op(bufferevent_getfd(bev1), ==, data->pair[0]);
    507  1.1  christos 	} else {
    508  1.1  christos 		tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
    509  1.1  christos 	}
    510  1.1  christos 
    511  1.8  christos 	if (type & REGRESS_OPENSSL_OPEN) {
    512  1.1  christos 		pending_connect_events = 2;
    513  1.1  christos 		stop_when_connected = 1;
    514  1.1  christos 		exit_base = data->base;
    515  1.1  christos 		event_base_dispatch(data->base);
    516  1.1  christos 		/* Okay, now the renegotiation is done.  Make new
    517  1.1  christos 		 * bufferevents to test opening in BUFFEREVENT_SSL_OPEN */
    518  1.1  christos 		flags |= BEV_OPT_CLOSE_ON_FREE;
    519  1.1  christos 		bufferevent_free(bev1);
    520  1.1  christos 		bufferevent_free(bev2);
    521  1.1  christos 		bev1 = bev2 = NULL;
    522  1.1  christos 		open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
    523  1.8  christos 		    fd_pair, bev_ll, type);
    524  1.1  christos 	}
    525  1.1  christos 
    526  1.8  christos 	if (!(type & REGRESS_OPENSSL_TIMEOUT)) {
    527  1.8  christos 		bufferevent_enable(bev1, EV_READ|EV_WRITE);
    528  1.8  christos 		bufferevent_enable(bev2, EV_READ|EV_WRITE);
    529  1.8  christos 
    530  1.8  christos 		if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
    531  1.8  christos 			evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
    532  1.8  christos 
    533  1.8  christos 		event_base_dispatch(data->base);
    534  1.8  christos 
    535  1.8  christos 		tt_assert(test_is_done == 1);
    536  1.8  christos 		tt_assert(n_connected == 2);
    537  1.8  christos 
    538  1.8  christos 		/* We don't handle shutdown properly yet */
    539  1.8  christos 		if (type & REGRESS_OPENSSL_DIRTY_SHUTDOWN) {
    540  1.8  christos 			tt_int_op(got_close, ==, 1);
    541  1.8  christos 			tt_int_op(got_error, ==, 0);
    542  1.8  christos 		} else {
    543  1.8  christos 			tt_int_op(got_error, ==, 1);
    544  1.8  christos 		}
    545  1.8  christos 		tt_int_op(got_timeout, ==, 0);
    546  1.8  christos 	} else {
    547  1.8  christos 		struct timeval t = { 2, 0 };
    548  1.8  christos 
    549  1.8  christos 		bufferevent_enable(bev1, EV_READ|EV_WRITE);
    550  1.8  christos 		bufferevent_disable(bev2, EV_READ|EV_WRITE);
    551  1.8  christos 
    552  1.8  christos 		bufferevent_set_timeouts(bev1, &t, &t);
    553  1.8  christos 
    554  1.8  christos 		if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
    555  1.8  christos 			evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
    556  1.8  christos 
    557  1.8  christos 		event_base_dispatch(data->base);
    558  1.1  christos 
    559  1.8  christos 		tt_assert(test_is_done == 0);
    560  1.8  christos 		tt_assert(n_connected == 0);
    561  1.1  christos 
    562  1.8  christos 		tt_int_op(got_close, ==, 0);
    563  1.8  christos 		tt_int_op(got_error, ==, 0);
    564  1.8  christos 		tt_int_op(got_timeout, ==, 1);
    565  1.1  christos 
    566  1.8  christos 		bufferevent_free(bev2);
    567  1.8  christos 	}
    568  1.1  christos 
    569  1.1  christos end:
    570  1.1  christos 	return;
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos static void
    574  1.8  christos acceptcb_deferred(evutil_socket_t fd, short events, void *arg)
    575  1.8  christos {
    576  1.8  christos 	struct bufferevent *bev = arg;
    577  1.8  christos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
    578  1.8  christos }
    579  1.8  christos static void
    580  1.1  christos acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
    581  1.1  christos     struct sockaddr *addr, int socklen, void *arg)
    582  1.1  christos {
    583  1.1  christos 	struct basic_test_data *data = arg;
    584  1.1  christos 	struct bufferevent *bev;
    585  1.8  christos 	enum regress_openssl_type type;
    586  1.1  christos 	SSL *ssl = SSL_new(get_ssl_ctx());
    587  1.1  christos 
    588  1.8  christos 	type = (enum regress_openssl_type)data->setup_data;
    589  1.8  christos 
    590  1.8  christos 	SSL_use_certificate(ssl, the_cert);
    591  1.8  christos 	SSL_use_PrivateKey(ssl, the_key);
    592  1.1  christos 
    593  1.1  christos 	bev = bufferevent_openssl_socket_new(
    594  1.8  christos 		data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
    595  1.1  christos 		BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
    596  1.8  christos 	tt_assert(bev);
    597  1.1  christos 
    598  1.1  christos 	bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
    599  1.8  christos 	    (void*)(REGRESS_OPENSSL_SERVER));
    600  1.1  christos 
    601  1.8  christos 	if (type & REGRESS_OPENSSL_SLEEP) {
    602  1.8  christos 		struct timeval when = { 1, 0 };
    603  1.8  christos 		event_base_once(data->base, -1, EV_TIMEOUT,
    604  1.8  christos 		    acceptcb_deferred, bev, &when);
    605  1.8  christos 		bufferevent_disable(bev, EV_READ|EV_WRITE);
    606  1.8  christos 	} else {
    607  1.8  christos 		bufferevent_enable(bev, EV_READ|EV_WRITE);
    608  1.8  christos 	}
    609  1.1  christos 
    610  1.1  christos 	/* Only accept once, then disable ourself. */
    611  1.1  christos 	evconnlistener_disable(listener);
    612  1.8  christos 
    613  1.8  christos end:
    614  1.8  christos 	;
    615  1.8  christos }
    616  1.8  christos 
    617  1.8  christos struct rwcount
    618  1.8  christos {
    619  1.8  christos 	evutil_socket_t fd;
    620  1.8  christos 	size_t read;
    621  1.8  christos 	size_t write;
    622  1.8  christos };
    623  1.8  christos static int
    624  1.8  christos bio_rwcount_new(BIO *b)
    625  1.8  christos {
    626  1.8  christos 	BIO_set_init(b, 0);
    627  1.8  christos 	BIO_set_data(b, NULL);
    628  1.8  christos 	return 1;
    629  1.8  christos }
    630  1.8  christos static int
    631  1.8  christos bio_rwcount_free(BIO *b)
    632  1.8  christos {
    633  1.8  christos 	TT_BLATHER(("bio_rwcount_free: %p", b));
    634  1.8  christos 	if (!b)
    635  1.8  christos 		return 0;
    636  1.8  christos 	if (BIO_get_shutdown(b)) {
    637  1.8  christos 		BIO_set_init(b, 0);
    638  1.8  christos 		BIO_set_data(b, NULL);
    639  1.8  christos 	}
    640  1.8  christos 	return 1;
    641  1.8  christos }
    642  1.8  christos static int
    643  1.8  christos bio_rwcount_read(BIO *b, char *out, int outlen)
    644  1.8  christos {
    645  1.8  christos 	struct rwcount *rw = BIO_get_data(b);
    646  1.8  christos 	ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
    647  1.8  christos 	++rw->read;
    648  1.8  christos 	if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
    649  1.8  christos 		BIO_set_retry_read(b);
    650  1.8  christos 	}
    651  1.8  christos 	return ret;
    652  1.8  christos }
    653  1.8  christos static int
    654  1.8  christos bio_rwcount_write(BIO *b, const char *in, int inlen)
    655  1.8  christos {
    656  1.8  christos 	struct rwcount *rw = BIO_get_data(b);
    657  1.8  christos 	ev_ssize_t ret = send(rw->fd, in, inlen, 0);
    658  1.8  christos 	++rw->write;
    659  1.8  christos 	if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
    660  1.8  christos 		BIO_set_retry_write(b);
    661  1.8  christos 	}
    662  1.8  christos 	return ret;
    663  1.8  christos }
    664  1.8  christos static long
    665  1.8  christos bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
    666  1.8  christos {
    667  1.8  christos 	struct rwcount *rw = BIO_get_data(b);
    668  1.8  christos 	long ret = 0;
    669  1.8  christos 	switch (cmd) {
    670  1.8  christos 	case BIO_C_GET_FD:
    671  1.8  christos 		ret = rw->fd;
    672  1.8  christos 		break;
    673  1.8  christos 	case BIO_CTRL_GET_CLOSE:
    674  1.8  christos 		ret = BIO_get_shutdown(b);
    675  1.8  christos 		break;
    676  1.8  christos 	case BIO_CTRL_SET_CLOSE:
    677  1.8  christos 		BIO_set_shutdown(b, (int)num);
    678  1.8  christos 		break;
    679  1.8  christos 	case BIO_CTRL_PENDING:
    680  1.8  christos 		ret = 0;
    681  1.8  christos 		break;
    682  1.8  christos 	case BIO_CTRL_WPENDING:
    683  1.8  christos 		ret = 0;
    684  1.8  christos 		break;
    685  1.8  christos 	case BIO_CTRL_DUP:
    686  1.8  christos 	case BIO_CTRL_FLUSH:
    687  1.8  christos 		ret = 1;
    688  1.8  christos 		break;
    689  1.8  christos 	}
    690  1.8  christos 	return ret;
    691  1.8  christos }
    692  1.8  christos static int
    693  1.8  christos bio_rwcount_puts(BIO *b, const char *s)
    694  1.8  christos {
    695  1.8  christos 	return bio_rwcount_write(b, s, strlen(s));
    696  1.8  christos }
    697  1.8  christos #define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
    698  1.8  christos static BIO_METHOD *methods_rwcount;
    699  1.8  christos 
    700  1.8  christos static BIO_METHOD *
    701  1.8  christos BIO_s_rwcount(void)
    702  1.8  christos {
    703  1.8  christos 	if (methods_rwcount == NULL) {
    704  1.8  christos 		methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount");
    705  1.8  christos 		if (methods_rwcount == NULL)
    706  1.8  christos 			return NULL;
    707  1.8  christos 		BIO_meth_set_write(methods_rwcount, bio_rwcount_write);
    708  1.8  christos 		BIO_meth_set_read(methods_rwcount, bio_rwcount_read);
    709  1.8  christos 		BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts);
    710  1.8  christos 		BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl);
    711  1.8  christos 		BIO_meth_set_create(methods_rwcount, bio_rwcount_new);
    712  1.8  christos 		BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free);
    713  1.8  christos 	}
    714  1.8  christos 	return methods_rwcount;
    715  1.8  christos }
    716  1.8  christos static BIO *
    717  1.8  christos BIO_new_rwcount(int close_flag)
    718  1.8  christos {
    719  1.8  christos 	BIO *result;
    720  1.8  christos 	if (!(result = BIO_new(BIO_s_rwcount())))
    721  1.8  christos 		return NULL;
    722  1.8  christos 	BIO_set_init(result, 1);
    723  1.8  christos 	BIO_set_data(result,  NULL);
    724  1.8  christos 	BIO_set_shutdown(result, !!close_flag);
    725  1.8  christos 	return result;
    726  1.1  christos }
    727  1.1  christos 
    728  1.1  christos static void
    729  1.1  christos regress_bufferevent_openssl_connect(void *arg)
    730  1.1  christos {
    731  1.1  christos 	struct basic_test_data *data = arg;
    732  1.1  christos 
    733  1.1  christos 	struct event_base *base = data->base;
    734  1.1  christos 
    735  1.1  christos 	struct evconnlistener *listener;
    736  1.1  christos 	struct bufferevent *bev;
    737  1.1  christos 	struct sockaddr_in sin;
    738  1.1  christos 	struct sockaddr_storage ss;
    739  1.1  christos 	ev_socklen_t slen;
    740  1.8  christos 	SSL *ssl;
    741  1.8  christos 	struct rwcount rw = { -1, 0, 0 };
    742  1.8  christos 	enum regress_openssl_type type;
    743  1.1  christos 
    744  1.8  christos 	type = (enum regress_openssl_type)data->setup_data;
    745  1.1  christos 
    746  1.1  christos 	memset(&sin, 0, sizeof(sin));
    747  1.1  christos 	sin.sin_family = AF_INET;
    748  1.1  christos 	sin.sin_addr.s_addr = htonl(0x7f000001);
    749  1.1  christos 
    750  1.1  christos 	memset(&ss, 0, sizeof(ss));
    751  1.1  christos 	slen = sizeof(ss);
    752  1.1  christos 
    753  1.1  christos 	listener = evconnlistener_new_bind(base, acceptcb, data,
    754  1.1  christos 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
    755  1.1  christos 	    -1, (struct sockaddr *)&sin, sizeof(sin));
    756  1.1  christos 
    757  1.1  christos 	tt_assert(listener);
    758  1.1  christos 	tt_assert(evconnlistener_get_fd(listener) >= 0);
    759  1.1  christos 
    760  1.8  christos 	ssl = SSL_new(get_ssl_ctx());
    761  1.8  christos 	tt_assert(ssl);
    762  1.8  christos 
    763  1.1  christos 	bev = bufferevent_openssl_socket_new(
    764  1.8  christos 		data->base, -1, ssl,
    765  1.1  christos 		BUFFEREVENT_SSL_CONNECTING,
    766  1.1  christos 		BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
    767  1.1  christos 	tt_assert(bev);
    768  1.1  christos 
    769  1.8  christos 	bufferevent_setcb(bev, respond_to_number, free_on_cb, eventcb,
    770  1.8  christos 	    (void*)(REGRESS_OPENSSL_CLIENT));
    771  1.1  christos 
    772  1.1  christos 	tt_assert(getsockname(evconnlistener_get_fd(listener),
    773  1.1  christos 		(struct sockaddr*)&ss, &slen) == 0);
    774  1.1  christos 	tt_assert(slen == sizeof(struct sockaddr_in));
    775  1.1  christos 	tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
    776  1.1  christos 
    777  1.1  christos 	tt_assert(0 ==
    778  1.1  christos 	    bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
    779  1.8  christos 	/* Possible only when we have fd, since be_openssl can and will overwrite
    780  1.8  christos 	 * bio otherwise before */
    781  1.8  christos 	if (type & REGRESS_OPENSSL_SLEEP) {
    782  1.8  christos 		BIO *bio;
    783  1.8  christos 
    784  1.8  christos 		rw.fd = bufferevent_getfd(bev);
    785  1.8  christos 		bio = BIO_new_rwcount(0);
    786  1.8  christos 		tt_assert(bio);
    787  1.8  christos 		BIO_set_data(bio, &rw);
    788  1.8  christos 		SSL_set_bio(ssl, bio, bio);
    789  1.8  christos 	}
    790  1.1  christos 	evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
    791  1.1  christos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
    792  1.1  christos 
    793  1.1  christos 	event_base_dispatch(base);
    794  1.8  christos 
    795  1.8  christos 	tt_int_op(rw.read, <=, 100);
    796  1.8  christos 	tt_int_op(rw.write, <=, 100);
    797  1.8  christos end:
    798  1.8  christos 	evconnlistener_free(listener);
    799  1.8  christos }
    800  1.8  christos 
    801  1.8  christos struct wm_context
    802  1.8  christos {
    803  1.8  christos 	int server;
    804  1.8  christos 	int flags;
    805  1.8  christos 	struct evbuffer *data;
    806  1.8  christos 	size_t to_read;
    807  1.8  christos 	size_t wm_high;
    808  1.8  christos 	size_t limit;
    809  1.8  christos 	size_t get;
    810  1.8  christos 	struct bufferevent *bev;
    811  1.8  christos 	struct wm_context *neighbour;
    812  1.8  christos };
    813  1.8  christos static void
    814  1.8  christos wm_transfer(struct bufferevent *bev, void *arg)
    815  1.8  christos {
    816  1.8  christos 	struct wm_context *ctx = arg;
    817  1.8  christos 	struct evbuffer *in  = bufferevent_get_input(bev);
    818  1.8  christos 	struct evbuffer *out = bufferevent_get_output(bev);
    819  1.8  christos 	size_t len = evbuffer_get_length(in);
    820  1.8  christos 	size_t drain = len < ctx->to_read ? len : ctx->to_read;
    821  1.8  christos 
    822  1.8  christos 	if (ctx->get >= ctx->limit) {
    823  1.8  christos 		TT_BLATHER(("wm_transfer-%s(%p): break",
    824  1.8  christos 			ctx->server ? "server" : "client", bev));
    825  1.8  christos 		bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
    826  1.8  christos 		bufferevent_disable(bev, EV_READ);
    827  1.8  christos 		if (ctx->neighbour->get >= ctx->neighbour->limit) {
    828  1.8  christos 			event_base_loopbreak(bufferevent_get_base(bev));
    829  1.8  christos 		}
    830  1.8  christos 	} else {
    831  1.8  christos 		ctx->get += drain;
    832  1.8  christos 		evbuffer_drain(in, drain);
    833  1.8  christos 	}
    834  1.8  christos 
    835  1.8  christos 	TT_BLATHER(("wm_transfer-%s(%p): "
    836  1.8  christos 		"in: " EV_SIZE_FMT ", "
    837  1.8  christos 		"out: " EV_SIZE_FMT ", "
    838  1.8  christos 		"got: " EV_SIZE_FMT "",
    839  1.8  christos 		ctx->server ? "server" : "client", bev,
    840  1.8  christos 		evbuffer_get_length(in),
    841  1.8  christos 		evbuffer_get_length(out),
    842  1.8  christos 		ctx->get));
    843  1.8  christos 
    844  1.8  christos 	evbuffer_add_buffer_reference(out, ctx->data);
    845  1.8  christos }
    846  1.8  christos static void
    847  1.8  christos wm_eventcb(struct bufferevent *bev, short what, void *arg)
    848  1.8  christos {
    849  1.8  christos 	struct wm_context *ctx = arg;
    850  1.8  christos 	TT_BLATHER(("wm_eventcb-%s(%p): %i",
    851  1.8  christos 		ctx->server ? "server" : "client", bev, what));
    852  1.8  christos 	if (what & BEV_EVENT_CONNECTED) {
    853  1.8  christos 	} else {
    854  1.8  christos 		ctx->get = 0;
    855  1.8  christos 	}
    856  1.8  christos }
    857  1.8  christos static void
    858  1.8  christos wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
    859  1.8  christos     struct sockaddr *addr, int socklen, void *arg)
    860  1.8  christos {
    861  1.8  christos 	struct wm_context *ctx = arg;
    862  1.8  christos 	struct bufferevent *bev;
    863  1.8  christos 	struct event_base *base = evconnlistener_get_base(listener);
    864  1.8  christos 	SSL *ssl = SSL_new(get_ssl_ctx());
    865  1.8  christos 
    866  1.8  christos 	SSL_use_certificate(ssl, the_cert);
    867  1.8  christos 	SSL_use_PrivateKey(ssl, the_key);
    868  1.8  christos 
    869  1.8  christos 	bev = bufferevent_openssl_socket_new(
    870  1.8  christos 		base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
    871  1.8  christos 
    872  1.8  christos 	TT_BLATHER(("wm_transfer-%s(%p): accept",
    873  1.8  christos 		ctx->server ? "server" : "client", bev));
    874  1.8  christos 
    875  1.8  christos 	bufferevent_setwatermark(bev, EV_READ, 0, ctx->wm_high);
    876  1.8  christos 	bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, ctx);
    877  1.8  christos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
    878  1.8  christos 	ctx->bev = bev;
    879  1.8  christos 
    880  1.8  christos 	/* Only accept once, then disable ourself. */
    881  1.8  christos 	evconnlistener_disable(listener);
    882  1.8  christos }
    883  1.8  christos static void
    884  1.8  christos regress_bufferevent_openssl_wm(void *arg)
    885  1.8  christos {
    886  1.8  christos 	struct basic_test_data *data = arg;
    887  1.8  christos 	struct event_base *base = data->base;
    888  1.8  christos 
    889  1.8  christos 	struct evconnlistener *listener;
    890  1.8  christos 	struct bufferevent *bev;
    891  1.8  christos 	struct sockaddr_in sin;
    892  1.8  christos 	struct sockaddr_storage ss;
    893  1.8  christos 	enum regress_openssl_type type =
    894  1.8  christos 		(enum regress_openssl_type)data->setup_data;
    895  1.8  christos 	int bev_flags = BEV_OPT_CLOSE_ON_FREE;
    896  1.8  christos 	ev_socklen_t slen;
    897  1.8  christos 	SSL *ssl;
    898  1.8  christos 	struct wm_context client, server;
    899  1.8  christos 	char *payload;
    900  1.8  christos 	size_t payload_len = 1<<10;
    901  1.8  christos 	size_t wm_high = 5<<10;
    902  1.8  christos 
    903  1.8  christos 	memset(&sin, 0, sizeof(sin));
    904  1.8  christos 	sin.sin_family = AF_INET;
    905  1.8  christos 	sin.sin_addr.s_addr = htonl(0x7f000001);
    906  1.8  christos 
    907  1.8  christos 	memset(&ss, 0, sizeof(ss));
    908  1.8  christos 	slen = sizeof(ss);
    909  1.8  christos 
    910  1.8  christos 	if (type & REGRESS_DEFERRED_CALLBACKS)
    911  1.8  christos 		bev_flags |= BEV_OPT_DEFER_CALLBACKS;
    912  1.8  christos 
    913  1.8  christos 	memset(&client, 0, sizeof(client));
    914  1.8  christos 	memset(&server, 0, sizeof(server));
    915  1.8  christos 	client.server = 0;
    916  1.8  christos 	server.server = 1;
    917  1.8  christos 	client.flags = server.flags = bev_flags;
    918  1.8  christos 	client.data = evbuffer_new();
    919  1.8  christos 	server.data = evbuffer_new();
    920  1.8  christos 	payload = calloc(1, payload_len);
    921  1.8  christos 	memset(payload, 'A', payload_len);
    922  1.8  christos 	evbuffer_add(server.data, payload, payload_len);
    923  1.8  christos 	evbuffer_add(client.data, payload, payload_len);
    924  1.8  christos 	client.wm_high = server.wm_high = wm_high;
    925  1.8  christos 	client.limit = server.limit = wm_high<<3;
    926  1.8  christos 	client.to_read = server.to_read = payload_len>>1;
    927  1.8  christos 
    928  1.8  christos 	TT_BLATHER(("openssl_wm: "
    929  1.8  christos 		"payload_len = " EV_SIZE_FMT ", "
    930  1.8  christos 		"wm_high = " EV_SIZE_FMT ", "
    931  1.8  christos 		"limit = " EV_SIZE_FMT ", "
    932  1.8  christos 		"to_read: " EV_SIZE_FMT "",
    933  1.8  christos 		payload_len,
    934  1.8  christos 		wm_high,
    935  1.8  christos 		server.limit,
    936  1.8  christos 		server.to_read));
    937  1.8  christos 
    938  1.8  christos 	listener = evconnlistener_new_bind(base, wm_acceptcb, &server,
    939  1.8  christos 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
    940  1.8  christos 	    -1, (struct sockaddr *)&sin, sizeof(sin));
    941  1.8  christos 
    942  1.8  christos 	tt_assert(listener);
    943  1.8  christos 	tt_assert(evconnlistener_get_fd(listener) >= 0);
    944  1.8  christos 
    945  1.8  christos 	ssl = SSL_new(get_ssl_ctx());
    946  1.8  christos 	tt_assert(ssl);
    947  1.8  christos 
    948  1.8  christos 	if (type & REGRESS_OPENSSL_FILTER) {
    949  1.8  christos 		bev = bufferevent_socket_new(data->base, -1, client.flags);
    950  1.8  christos 		tt_assert(bev);
    951  1.8  christos 		bev = bufferevent_openssl_filter_new(
    952  1.8  christos 			base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
    953  1.8  christos 	} else {
    954  1.8  christos 		bev = bufferevent_openssl_socket_new(
    955  1.8  christos 			data->base, -1, ssl,
    956  1.8  christos 			BUFFEREVENT_SSL_CONNECTING,
    957  1.8  christos 			client.flags);
    958  1.8  christos 	}
    959  1.8  christos 	tt_assert(bev);
    960  1.8  christos 	client.bev = bev;
    961  1.8  christos 
    962  1.8  christos 	server.neighbour = &client;
    963  1.8  christos 	client.neighbour = &server;
    964  1.8  christos 
    965  1.8  christos 	bufferevent_setwatermark(bev, EV_READ, 0, client.wm_high);
    966  1.8  christos 	bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, &client);
    967  1.8  christos 
    968  1.8  christos 	tt_assert(getsockname(evconnlistener_get_fd(listener),
    969  1.8  christos 		(struct sockaddr*)&ss, &slen) == 0);
    970  1.8  christos 
    971  1.8  christos 	tt_assert(!bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
    972  1.8  christos 	tt_assert(!evbuffer_add_buffer_reference(bufferevent_get_output(bev), client.data));
    973  1.8  christos 	tt_assert(!bufferevent_enable(bev, EV_READ|EV_WRITE));
    974  1.8  christos 
    975  1.8  christos 	event_base_dispatch(base);
    976  1.8  christos 
    977  1.8  christos 	tt_int_op(client.get, ==, client.limit);
    978  1.8  christos 	tt_int_op(server.get, ==, server.limit);
    979  1.8  christos 
    980  1.1  christos end:
    981  1.8  christos 	free(payload);
    982  1.8  christos 	evbuffer_free(client.data);
    983  1.8  christos 	evbuffer_free(server.data);
    984  1.8  christos 	evconnlistener_free(listener);
    985  1.8  christos 	bufferevent_free(client.bev);
    986  1.8  christos 	bufferevent_free(server.bev);
    987  1.8  christos 
    988  1.8  christos 	/* XXX: by some reason otherise there is a leak */
    989  1.8  christos 	if (!(type & REGRESS_OPENSSL_FILTER))
    990  1.8  christos 		event_base_loop(base, EVLOOP_ONCE);
    991  1.1  christos }
    992  1.1  christos 
    993  1.1  christos struct testcase_t ssl_testcases[] = {
    994  1.8  christos #define T(a) ((void *)(a))
    995  1.8  christos 	{ "bufferevent_socketpair", regress_bufferevent_openssl,
    996  1.8  christos 	  TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
    997  1.8  christos 	{ "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl,
    998  1.8  christos 	  TT_ISOLATED, &ssl_setup,
    999  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) },
   1000  1.1  christos 	{ "bufferevent_filter", regress_bufferevent_openssl,
   1001  1.8  christos 	  TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
   1002  1.8  christos 	{ "bufferevent_filter_write_after_connect", regress_bufferevent_openssl,
   1003  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1004  1.8  christos 	  T(REGRESS_OPENSSL_FILTER|REGRESS_OPENSSL_CLIENT_WRITE) },
   1005  1.1  christos 	{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
   1006  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1007  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
   1008  1.1  christos 	{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
   1009  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1010  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
   1011  1.1  christos 	{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
   1012  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1013  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
   1014  1.1  christos 	{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
   1015  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1016  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
   1017  1.8  christos 
   1018  1.8  christos 	{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
   1019  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1020  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1021  1.8  christos 	{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
   1022  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1023  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1024  1.8  christos 	{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
   1025  1.8  christos 	  regress_bufferevent_openssl,
   1026  1.8  christos 	  TT_ISOLATED,
   1027  1.8  christos 	  &ssl_setup,
   1028  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1029  1.8  christos 	{ "bufferevent_renegotiate_filter_dirty_shutdown",
   1030  1.8  christos 	  regress_bufferevent_openssl,
   1031  1.8  christos 	  TT_ISOLATED,
   1032  1.8  christos 	  &ssl_setup,
   1033  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1034  1.8  christos 	{ "bufferevent_socketpair_startopen_dirty_shutdown",
   1035  1.8  christos 	  regress_bufferevent_openssl,
   1036  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1037  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1038  1.8  christos 	{ "bufferevent_filter_startopen_dirty_shutdown",
   1039  1.8  christos 	  regress_bufferevent_openssl,
   1040  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1041  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
   1042  1.8  christos 
   1043  1.8  christos 	{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
   1044  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1045  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
   1046  1.8  christos 	{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
   1047  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1048  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
   1049  1.8  christos 	{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
   1050  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1051  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
   1052  1.8  christos 	{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
   1053  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1054  1.8  christos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
   1055  1.8  christos 
   1056  1.8  christos 	{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
   1057  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1058  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
   1059  1.8  christos 	{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
   1060  1.8  christos 	  TT_ISOLATED, &ssl_setup,
   1061  1.8  christos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
   1062  1.1  christos 
   1063  1.1  christos 	{ "bufferevent_connect", regress_bufferevent_openssl_connect,
   1064  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
   1065  1.8  christos 	{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
   1066  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
   1067  1.8  christos 
   1068  1.8  christos 	{ "bufferevent_wm", regress_bufferevent_openssl_wm,
   1069  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
   1070  1.8  christos 	{ "bufferevent_wm_filter", regress_bufferevent_openssl_wm,
   1071  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
   1072  1.8  christos 	{ "bufferevent_wm_defer", regress_bufferevent_openssl_wm,
   1073  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_DEFERRED_CALLBACKS) },
   1074  1.8  christos 	{ "bufferevent_wm_filter_defer", regress_bufferevent_openssl_wm,
   1075  1.8  christos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER|REGRESS_DEFERRED_CALLBACKS) },
   1076  1.8  christos 
   1077  1.8  christos #undef T
   1078  1.1  christos 
   1079  1.1  christos 	END_OF_TESTCASES,
   1080  1.1  christos };
   1081