xref: /netbsd-src/external/bsd/ntp/dist/sntp/libevent/test/regress_ssl.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: regress_ssl.c,v 1.8 2024/08/18 20:47:23 christos Exp $	*/
28585484eSchristos 
38585484eSchristos /*
48585484eSchristos  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
58585484eSchristos  *
68585484eSchristos  * Redistribution and use in source and binary forms, with or without
78585484eSchristos  * modification, are permitted provided that the following conditions
88585484eSchristos  * are met:
98585484eSchristos  * 1. Redistributions of source code must retain the above copyright
108585484eSchristos  *    notice, this list of conditions and the following disclaimer.
118585484eSchristos  * 2. Redistributions in binary form must reproduce the above copyright
128585484eSchristos  *    notice, this list of conditions and the following disclaimer in the
138585484eSchristos  *    documentation and/or other materials provided with the distribution.
148585484eSchristos  * 3. The name of the author may not be used to endorse or promote products
158585484eSchristos  *    derived from this software without specific prior written permission.
168585484eSchristos  *
178585484eSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
188585484eSchristos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
198585484eSchristos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
208585484eSchristos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
218585484eSchristos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
228585484eSchristos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
238585484eSchristos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
248585484eSchristos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258585484eSchristos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268585484eSchristos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278585484eSchristos  */
288585484eSchristos 
29b8ecfcfeSchristos // Get rid of OSX 10.7 and greater deprecation warnings.
30b8ecfcfeSchristos #if defined(__APPLE__) && defined(__clang__)
31b8ecfcfeSchristos #pragma clang diagnostic ignored "-Wdeprecated-declarations"
32b8ecfcfeSchristos #endif
33b8ecfcfeSchristos 
348585484eSchristos #ifdef _WIN32
358585484eSchristos #include <winsock2.h>
368585484eSchristos #include <windows.h>
378585484eSchristos #endif
388585484eSchristos 
39*eabc0478Schristos #include "util-internal.h"
40*eabc0478Schristos 
418585484eSchristos #ifndef _WIN32
428585484eSchristos #include <sys/types.h>
438585484eSchristos #include <sys/socket.h>
448585484eSchristos #include <netinet/in.h>
458585484eSchristos #endif
468585484eSchristos 
478585484eSchristos #include "event2/util.h"
488585484eSchristos #include "event2/event.h"
498585484eSchristos #include "event2/bufferevent_ssl.h"
50*eabc0478Schristos #include "event2/bufferevent_struct.h"
518585484eSchristos #include "event2/buffer.h"
528585484eSchristos #include "event2/listener.h"
538585484eSchristos 
548585484eSchristos #include "regress.h"
558585484eSchristos #include "tinytest.h"
568585484eSchristos #include "tinytest_macros.h"
578585484eSchristos 
588585484eSchristos #include <openssl/err.h>
598585484eSchristos #include <openssl/pem.h>
60*eabc0478Schristos #include "openssl-compat.h"
618585484eSchristos 
628585484eSchristos #include <string.h>
63*eabc0478Schristos #ifdef _WIN32
64*eabc0478Schristos #include <io.h>
65*eabc0478Schristos #define read _read
66*eabc0478Schristos #define write _write
67*eabc0478Schristos #else
68*eabc0478Schristos #include <unistd.h>
69*eabc0478Schristos #endif
708585484eSchristos 
71*eabc0478Schristos /* A pre-generated key, to save the cost of doing an RSA key generation step
72*eabc0478Schristos  * during the unit tests. It is published in this file, so you would have to
73*eabc0478Schristos  * be very foolish to consider using it in your own code. */
748585484eSchristos static const char KEY[] =
758585484eSchristos     "-----BEGIN RSA PRIVATE KEY-----\n"
76*eabc0478Schristos     "MIIEogIBAAKCAQEAtK07Ili0dkJb79m/sFmHoVJTWyLoveXex2yX/BtUzzcvZEOu\n"
77*eabc0478Schristos     "QLon/++5YOA48kzZm5K9mIwZkZhui1ZgJ5Bjq0LGAWTZGIn+NXjLFshPYvTKpOCW\n"
78*eabc0478Schristos     "uzL0Ir0LXMsBLYJQ5A4FomLNxs4I3H/dhDSGy/rSiJB1B4w2xNiwPK08/VL3zZqk\n"
79*eabc0478Schristos     "V+GsSvGIIkzhTMbqPJy9K8pqyjwOU2pgORS794yXciTGxWYjTDzJPgQ35YMDATaG\n"
80*eabc0478Schristos     "jr4HHo1zxU/Lj0pndSUK5rKLYxYQ3Uc8B3AVYDl9CP/GbOoQ4LBzS68JjcAUyp6i\n"
81*eabc0478Schristos     "6NfXlc2D9S9XgqVqwI+JqgJs0eW/+zPY2UEDWwIDAQABAoIBAD2HzV66FOM9YDAD\n"
82*eabc0478Schristos     "2RtGskEHV2nvLpIVadRCsFPkPvK+2X3s6rgSbbLkwh4y3lHuSCGKTNVZyQ9jeSos\n"
83*eabc0478Schristos     "xVxT+Q2HFQW+gYyw2gj91TQyDY8mzKhv8AVaqff2p5r3a7RC8CdqexK9UVUGL9Bg\n"
84*eabc0478Schristos     "H2F5vfpTtkVZ5PEoGDLblNFlMiMW/t1SobUeBVx+Msco/xqk9lFv1A9nnepGy0Gi\n"
85*eabc0478Schristos     "D+i6YNGTBsX22YhoCZl/ICxCL8lgqPei4FvBr9dBVh/jQgjuUBm2jz55p2r7+7Aw\n"
86*eabc0478Schristos     "khmXHReejoVokQ2+htgSgZNKlKuDy710ZpBqnDi8ynQi82Y2qCpyg/p/xcER54B6\n"
87*eabc0478Schristos     "hSftaiECgYEA2RkSoxU+nWk+BClQEUZRi88QK5W/M8oo1DvUs36hvPFkw3Jk/gz0\n"
88*eabc0478Schristos     "fgd5bnA+MXj0Fc0QHvbddPjIkyoI/evq9GPV+JYIuH5zabrlI3Jvya8q9QpAcEDO\n"
89*eabc0478Schristos     "KkL/O09qXVEW52S6l05nh4PLejyI7aTyTIN5nbVLac/+M8MY/qOjZksCgYEA1Q1o\n"
90*eabc0478Schristos     "L8kjSavU2xhQmSgZb9W62Do60sa3e73ljrDPoiyvbExldpSdziFYxHBD/Rep0ePf\n"
91*eabc0478Schristos     "eVSGS3VSwevt9/jSGo2Oa83TYYns9agBm03oR/Go/DukESdI792NsEM+PRFypVNy\n"
92*eabc0478Schristos     "AohWRLj0UU6DV+zLKp0VBavtx0ATeLFX0eN17TECgYBI2O/3Bz7uhQ0JSm+SjFz6\n"
93*eabc0478Schristos     "o+2SInp5P2G57aWu4VQWWY3tQ2p+EQzNaWam10UXRrXoxtmc+ktPX9e2AgnoYoyB\n"
94*eabc0478Schristos     "myqGcpnUhqHlnZAb999o9r1cYidDQ4uqhLauSTSwwXAFDzjJYsa8o03Y440y6QFh\n"
95*eabc0478Schristos     "CVD6yYXXqLJs3g96CqDexwKBgAHxq1+0QCQt8zVElYewO/svQhMzBNJjic0RQIT6\n"
96*eabc0478Schristos     "zAo4yij80XgxhvcYiszQEW6/xobpw2JCCS+rFGQ8mOFIXfJsFD6blDAxp/3d2JXo\n"
97*eabc0478Schristos     "MhRl+hrDGI4ng5zcsqxHEMxR2m/zwPiQ8eiSn3gWdVBaEsiCwmxY00ScKxFQ3PJH\n"
98*eabc0478Schristos     "Vw4hAoGAdZLd8KfjjG6lg7hfpVqavstqVi9LOgkHeCfdjn7JP+76kYrgLk/XdkrP\n"
99*eabc0478Schristos     "N/BHhtFVFjOi/mTQfQ5YfZImkm/1ePBy7437DT8BDkOxspa50kK4HPggHnU64h1w\n"
100*eabc0478Schristos     "lhdEOj7mAgHwGwwVZWOgs9Lq6vfztnSuhqjha1daESY6kDscPIQ=\n"
1018585484eSchristos     "-----END RSA PRIVATE KEY-----\n";
1028585484eSchristos 
103*eabc0478Schristos EVP_PKEY *
104*eabc0478Schristos ssl_getkey(void)
1058585484eSchristos {
1068585484eSchristos 	EVP_PKEY *key;
1078585484eSchristos 	BIO *bio;
1088585484eSchristos 
1098585484eSchristos 	/* new read-only BIO backed by KEY. */
1108585484eSchristos 	bio = BIO_new_mem_buf((char*)KEY, -1);
1118585484eSchristos 	tt_assert(bio);
1128585484eSchristos 
1138585484eSchristos 	key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
1148585484eSchristos 	BIO_free(bio);
1158585484eSchristos 	tt_assert(key);
1168585484eSchristos 
1178585484eSchristos 	return key;
1188585484eSchristos end:
1198585484eSchristos 	return NULL;
1208585484eSchristos }
1218585484eSchristos 
122*eabc0478Schristos X509 *
123*eabc0478Schristos ssl_getcert(EVP_PKEY *key)
1248585484eSchristos {
1258585484eSchristos 	/* Dummy code to make a quick-and-dirty valid certificate with
1268585484eSchristos 	   OpenSSL.  Don't copy this code into your own program! It does a
1278585484eSchristos 	   number of things in a stupid and insecure way. */
1288585484eSchristos 	X509 *x509 = NULL;
1298585484eSchristos 	X509_NAME *name = NULL;
1308585484eSchristos 	int nid;
1318585484eSchristos 	time_t now = time(NULL);
1328585484eSchristos 
1338585484eSchristos 	tt_assert(key);
1348585484eSchristos 
1358585484eSchristos 	x509 = X509_new();
1368585484eSchristos 	tt_assert(x509);
1378585484eSchristos 	tt_assert(0 != X509_set_version(x509, 2));
1388585484eSchristos 	tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509),
1398585484eSchristos 		(long)now));
1408585484eSchristos 
1418585484eSchristos 	name = X509_NAME_new();
1428585484eSchristos 	tt_assert(name);
1438585484eSchristos 	nid = OBJ_txt2nid("commonName");
1448585484eSchristos 	tt_assert(NID_undef != nid);
1458585484eSchristos 	tt_assert(0 != X509_NAME_add_entry_by_NID(
1468585484eSchristos 		    name, nid, MBSTRING_ASC, (unsigned char*)"example.com",
1478585484eSchristos 		    -1, -1, 0));
1488585484eSchristos 
1498585484eSchristos 	X509_set_subject_name(x509, name);
1508585484eSchristos 	X509_set_issuer_name(x509, name);
151*eabc0478Schristos 	X509_NAME_free(name);
1528585484eSchristos 
153ccc794f0Schristos 	X509_time_adj(X509_getm_notBefore(x509), 0, &now);
154ccc794f0Schristos 	now += 3600;
155ccc794f0Schristos 	X509_time_adj(X509_getm_notAfter(x509), 0, &now);
1568585484eSchristos 	X509_set_pubkey(x509, key);
1578585484eSchristos 	tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
1588585484eSchristos 
1598585484eSchristos 	return x509;
1608585484eSchristos end:
1618585484eSchristos 	X509_free(x509);
162*eabc0478Schristos 	X509_NAME_free(name);
1638585484eSchristos 	return NULL;
1648585484eSchristos }
1658585484eSchristos 
1668585484eSchristos static int disable_tls_11_and_12 = 0;
1678585484eSchristos static SSL_CTX *the_ssl_ctx = NULL;
1688585484eSchristos 
169*eabc0478Schristos SSL_CTX *
1708585484eSchristos get_ssl_ctx(void)
1718585484eSchristos {
1728585484eSchristos 	if (the_ssl_ctx)
1738585484eSchristos 		return the_ssl_ctx;
1748585484eSchristos 	the_ssl_ctx = SSL_CTX_new(SSLv23_method());
1758585484eSchristos 	if (!the_ssl_ctx)
1768585484eSchristos 		return NULL;
1778585484eSchristos 	if (disable_tls_11_and_12) {
1788585484eSchristos #ifdef SSL_OP_NO_TLSv1_2
1798585484eSchristos 		SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
1808585484eSchristos #endif
1818585484eSchristos #ifdef SSL_OP_NO_TLSv1_1
1828585484eSchristos 		SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
1838585484eSchristos #endif
1848585484eSchristos 	}
1858585484eSchristos 	return the_ssl_ctx;
1868585484eSchristos }
1878585484eSchristos 
188*eabc0478Schristos static int test_is_done;
189*eabc0478Schristos static int n_connected;
190*eabc0478Schristos static int got_close;
191*eabc0478Schristos static int got_error;
192*eabc0478Schristos static int got_timeout;
193*eabc0478Schristos static int renegotiate_at = -1;
194*eabc0478Schristos static int stop_when_connected;
195*eabc0478Schristos static int pending_connect_events;
196*eabc0478Schristos static struct event_base *exit_base;
197*eabc0478Schristos static X509 *the_cert;
198*eabc0478Schristos EVP_PKEY *the_key;
199*eabc0478Schristos 
200*eabc0478Schristos void
2018585484eSchristos init_ssl(void)
2028585484eSchristos {
203*eabc0478Schristos #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
204*eabc0478Schristos 	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
2058585484eSchristos 	SSL_library_init();
2068585484eSchristos 	ERR_load_crypto_strings();
2078585484eSchristos 	SSL_load_error_strings();
2088585484eSchristos 	OpenSSL_add_all_algorithms();
209*eabc0478Schristos 	if (SSLeay() != OPENSSL_VERSION_NUMBER) {
210*eabc0478Schristos 		TT_DECLARE("WARN",
211*eabc0478Schristos 			("Version mismatch for openssl: compiled with %lx but running with %lx",
212*eabc0478Schristos 			(unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
2138585484eSchristos 	}
214*eabc0478Schristos #endif
2158585484eSchristos }
2168585484eSchristos 
217*eabc0478Schristos static void *
218*eabc0478Schristos ssl_test_setup(const struct testcase_t *testcase)
219*eabc0478Schristos {
220*eabc0478Schristos 	init_ssl();
221*eabc0478Schristos 
222*eabc0478Schristos 	the_key = ssl_getkey();
223*eabc0478Schristos 	EVUTIL_ASSERT(the_key);
224*eabc0478Schristos 
225*eabc0478Schristos 	the_cert = ssl_getcert(the_key);
226*eabc0478Schristos 	EVUTIL_ASSERT(the_cert);
227*eabc0478Schristos 
228*eabc0478Schristos 	disable_tls_11_and_12 = 0;
229*eabc0478Schristos 
230*eabc0478Schristos 	return basic_test_setup(testcase);
231*eabc0478Schristos }
232*eabc0478Schristos static int
233*eabc0478Schristos ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
234*eabc0478Schristos {
235*eabc0478Schristos 	int ret = basic_test_cleanup(testcase, ptr);
236*eabc0478Schristos 	if (!ret) {
237*eabc0478Schristos 		return ret;
238*eabc0478Schristos 	}
239*eabc0478Schristos 
240*eabc0478Schristos 	test_is_done = 0;
241*eabc0478Schristos 	n_connected = 0;
242*eabc0478Schristos 	got_close = 0;
243*eabc0478Schristos 	got_error = 0;
244*eabc0478Schristos 	got_timeout = 0;
245*eabc0478Schristos 	renegotiate_at = -1;
246*eabc0478Schristos 	stop_when_connected = 0;
247*eabc0478Schristos 	pending_connect_events = 0;
248*eabc0478Schristos 	exit_base = NULL;
249*eabc0478Schristos 
250*eabc0478Schristos 	X509_free(the_cert);
251*eabc0478Schristos 	EVP_PKEY_free(the_key);
252*eabc0478Schristos 
253*eabc0478Schristos 	SSL_CTX_free(the_ssl_ctx);
254*eabc0478Schristos 	the_ssl_ctx = NULL;
255*eabc0478Schristos 
256*eabc0478Schristos 	return 1;
257*eabc0478Schristos }
258*eabc0478Schristos const struct testcase_setup_t ssl_setup = {
259*eabc0478Schristos 	ssl_test_setup, ssl_test_cleanup
260*eabc0478Schristos };
261*eabc0478Schristos 
262*eabc0478Schristos 
2638585484eSchristos /* ====================
2648585484eSchristos    Here's a simple test: we read a number from the input, increment it, and
2658585484eSchristos    reply, until we get to 1001.
2668585484eSchristos */
2678585484eSchristos 
268*eabc0478Schristos enum regress_openssl_type
269*eabc0478Schristos {
270*eabc0478Schristos 	REGRESS_OPENSSL_SOCKETPAIR = 1,
271*eabc0478Schristos 	REGRESS_OPENSSL_FILTER = 2,
272*eabc0478Schristos 	REGRESS_OPENSSL_RENEGOTIATE = 4,
273*eabc0478Schristos 	REGRESS_OPENSSL_OPEN = 8,
274*eabc0478Schristos 	REGRESS_OPENSSL_DIRTY_SHUTDOWN = 16,
275*eabc0478Schristos 	REGRESS_OPENSSL_FD = 32,
276*eabc0478Schristos 
277*eabc0478Schristos 	REGRESS_OPENSSL_CLIENT = 64,
278*eabc0478Schristos 	REGRESS_OPENSSL_SERVER = 128,
279*eabc0478Schristos 
280*eabc0478Schristos 	REGRESS_OPENSSL_FREED = 256,
281*eabc0478Schristos 	REGRESS_OPENSSL_TIMEOUT = 512,
282*eabc0478Schristos 	REGRESS_OPENSSL_SLEEP = 1024,
283*eabc0478Schristos 
284*eabc0478Schristos 	REGRESS_OPENSSL_CLIENT_WRITE = 2048,
285*eabc0478Schristos 
286*eabc0478Schristos 	REGRESS_DEFERRED_CALLBACKS = 4096,
287*eabc0478Schristos };
288*eabc0478Schristos 
289*eabc0478Schristos static void
290*eabc0478Schristos bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
291*eabc0478Schristos {
292*eabc0478Schristos 	tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
293*eabc0478Schristos 	tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
294*eabc0478Schristos 	if (filter) {
295*eabc0478Schristos 		tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
296*eabc0478Schristos 	} else {
297*eabc0478Schristos 		tt_fd_op(bufferevent_getfd(bev), ==, EVUTIL_INVALID_SOCKET);
298*eabc0478Schristos 	}
299*eabc0478Schristos 
300*eabc0478Schristos end:
301*eabc0478Schristos 	;
302*eabc0478Schristos }
303*eabc0478Schristos static void
304*eabc0478Schristos bufferevent_openssl_check_freed(struct bufferevent *bev)
305*eabc0478Schristos {
306*eabc0478Schristos 	tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
307*eabc0478Schristos 	tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
308*eabc0478Schristos 
309*eabc0478Schristos end:
310*eabc0478Schristos 	;
311*eabc0478Schristos }
312*eabc0478Schristos 
313*eabc0478Schristos static void
314*eabc0478Schristos free_on_cb(struct bufferevent *bev, void *ctx)
315*eabc0478Schristos {
316*eabc0478Schristos 	TT_BLATHER(("free_on_cb: %p", bev));
317*eabc0478Schristos 	bufferevent_free(bev);
318*eabc0478Schristos }
3198585484eSchristos 
3208585484eSchristos static void
3218585484eSchristos respond_to_number(struct bufferevent *bev, void *ctx)
3228585484eSchristos {
3238585484eSchristos 	struct evbuffer *b = bufferevent_get_input(bev);
3248585484eSchristos 	char *line;
3258585484eSchristos 	int n;
326*eabc0478Schristos 
327*eabc0478Schristos 	enum regress_openssl_type type;
328*eabc0478Schristos 	type = (enum regress_openssl_type)ctx;
329*eabc0478Schristos 
3308585484eSchristos 	line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
3318585484eSchristos 	if (! line)
3328585484eSchristos 		return;
3338585484eSchristos 	n = atoi(line);
3348585484eSchristos 	if (n <= 0)
3358585484eSchristos 		TT_FAIL(("Bad number: %s", line));
3367476e6e4Schristos 	free(line);
3378585484eSchristos 	TT_BLATHER(("The number was %d", n));
3388585484eSchristos 	if (n == 1001) {
3398585484eSchristos 		++test_is_done;
3408585484eSchristos 		bufferevent_free(bev); /* Should trigger close on other side. */
3418585484eSchristos 		return;
3428585484eSchristos 	}
343*eabc0478Schristos 	if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
3448585484eSchristos 		SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
3458585484eSchristos 	}
3468585484eSchristos 	++n;
3478585484eSchristos 	evbuffer_add_printf(bufferevent_get_output(bev),
3488585484eSchristos 	    "%d\n", n);
3498585484eSchristos 	TT_BLATHER(("Done reading; now writing."));
3508585484eSchristos 	bufferevent_enable(bev, EV_WRITE);
3518585484eSchristos 	bufferevent_disable(bev, EV_READ);
3528585484eSchristos }
3538585484eSchristos 
3548585484eSchristos static void
3558585484eSchristos done_writing_cb(struct bufferevent *bev, void *ctx)
3568585484eSchristos {
3578585484eSchristos 	struct evbuffer *b = bufferevent_get_output(bev);
3588585484eSchristos 	if (evbuffer_get_length(b))
3598585484eSchristos 		return;
3608585484eSchristos 	TT_BLATHER(("Done writing."));
3618585484eSchristos 	bufferevent_disable(bev, EV_WRITE);
3628585484eSchristos 	bufferevent_enable(bev, EV_READ);
3638585484eSchristos }
3648585484eSchristos 
3658585484eSchristos static void
3668585484eSchristos eventcb(struct bufferevent *bev, short what, void *ctx)
3678585484eSchristos {
368*eabc0478Schristos 	X509 *peer_cert = NULL;
369*eabc0478Schristos 	enum regress_openssl_type type;
370*eabc0478Schristos 
371*eabc0478Schristos 	type = (enum regress_openssl_type)ctx;
372*eabc0478Schristos 
3738585484eSchristos 	TT_BLATHER(("Got event %d", (int)what));
3748585484eSchristos 	if (what & BEV_EVENT_CONNECTED) {
3758585484eSchristos 		SSL *ssl;
3768585484eSchristos 		++n_connected;
3778585484eSchristos 		ssl = bufferevent_openssl_get_ssl(bev);
3788585484eSchristos 		tt_assert(ssl);
3798585484eSchristos 		peer_cert = SSL_get_peer_certificate(ssl);
380*eabc0478Schristos 		if (type & REGRESS_OPENSSL_SERVER) {
3818585484eSchristos 			tt_assert(peer_cert == NULL);
3828585484eSchristos 		} else {
3838585484eSchristos 			tt_assert(peer_cert != NULL);
3848585484eSchristos 		}
3858585484eSchristos 		if (stop_when_connected) {
3868585484eSchristos 			if (--pending_connect_events == 0)
3878585484eSchristos 				event_base_loopexit(exit_base, NULL);
3888585484eSchristos 		}
389*eabc0478Schristos 
390*eabc0478Schristos 		if ((type & REGRESS_OPENSSL_CLIENT_WRITE) && (type & REGRESS_OPENSSL_CLIENT))
391*eabc0478Schristos 			evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
3928585484eSchristos 	} else if (what & BEV_EVENT_EOF) {
3938585484eSchristos 		TT_BLATHER(("Got a good EOF"));
3948585484eSchristos 		++got_close;
395*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FD) {
396*eabc0478Schristos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
397*eabc0478Schristos 		}
398*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FREED) {
399*eabc0478Schristos 			bufferevent_openssl_check_freed(bev);
400*eabc0478Schristos 		}
4018585484eSchristos 		bufferevent_free(bev);
4028585484eSchristos 	} else if (what & BEV_EVENT_ERROR) {
4038585484eSchristos 		TT_BLATHER(("Got an error."));
4048585484eSchristos 		++got_error;
405*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FD) {
406*eabc0478Schristos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
407*eabc0478Schristos 		}
408*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FREED) {
409*eabc0478Schristos 			bufferevent_openssl_check_freed(bev);
410*eabc0478Schristos 		}
411*eabc0478Schristos 		bufferevent_free(bev);
412*eabc0478Schristos 	} else if (what & BEV_EVENT_TIMEOUT) {
413*eabc0478Schristos 		TT_BLATHER(("Got timeout."));
414*eabc0478Schristos 		++got_timeout;
415*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FD) {
416*eabc0478Schristos 			bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
417*eabc0478Schristos 		}
418*eabc0478Schristos 		if (type & REGRESS_OPENSSL_FREED) {
419*eabc0478Schristos 			bufferevent_openssl_check_freed(bev);
420*eabc0478Schristos 		}
4218585484eSchristos 		bufferevent_free(bev);
4228585484eSchristos 	}
423*eabc0478Schristos 
4248585484eSchristos end:
425*eabc0478Schristos 	if (peer_cert)
426*eabc0478Schristos 		X509_free(peer_cert);
4278585484eSchristos }
4288585484eSchristos 
4298585484eSchristos static void
4308585484eSchristos open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
4318585484eSchristos     struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
432*eabc0478Schristos     evutil_socket_t *fd_pair, struct bufferevent **underlying_pair,
433*eabc0478Schristos     enum regress_openssl_type type)
4348585484eSchristos {
4358585484eSchristos 	int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
4368585484eSchristos 	int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
437*eabc0478Schristos 	int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
4388585484eSchristos 	if (fd_pair) {
4398585484eSchristos 		*bev1_out = bufferevent_openssl_socket_new(
4408585484eSchristos 			base, fd_pair[0], ssl1, state1, flags);
4418585484eSchristos 		*bev2_out = bufferevent_openssl_socket_new(
4428585484eSchristos 			base, fd_pair[1], ssl2, state2, flags);
4438585484eSchristos 	} else {
4448585484eSchristos 		*bev1_out = bufferevent_openssl_filter_new(
4458585484eSchristos 			base, underlying_pair[0], ssl1, state1, flags);
4468585484eSchristos 		*bev2_out = bufferevent_openssl_filter_new(
4478585484eSchristos 			base, underlying_pair[1], ssl2, state2, flags);
4488585484eSchristos 
4498585484eSchristos 	}
4508585484eSchristos 	bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
451*eabc0478Schristos 	    eventcb, (void*)(REGRESS_OPENSSL_CLIENT | (long)type));
4528585484eSchristos 	bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
453*eabc0478Schristos 	    eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
454*eabc0478Schristos 
455*eabc0478Schristos 	bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
456*eabc0478Schristos 	bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
4578585484eSchristos }
4588585484eSchristos 
4598585484eSchristos static void
4608585484eSchristos regress_bufferevent_openssl(void *arg)
4618585484eSchristos {
4628585484eSchristos 	struct basic_test_data *data = arg;
4638585484eSchristos 
4648585484eSchristos 	struct bufferevent *bev1, *bev2;
4658585484eSchristos 	SSL *ssl1, *ssl2;
4668585484eSchristos 	int flags = BEV_OPT_DEFER_CALLBACKS;
4678585484eSchristos 	struct bufferevent *bev_ll[2] = { NULL, NULL };
4688585484eSchristos 	evutil_socket_t *fd_pair = NULL;
4698585484eSchristos 
470*eabc0478Schristos 	enum regress_openssl_type type;
471*eabc0478Schristos 	type = (enum regress_openssl_type)data->setup_data;
4728585484eSchristos 
473*eabc0478Schristos 	if (type & REGRESS_OPENSSL_RENEGOTIATE) {
474*eabc0478Schristos 		if (OPENSSL_VERSION_NUMBER >= 0x10001000 &&
475*eabc0478Schristos 		    OPENSSL_VERSION_NUMBER <  0x1000104f) {
4768585484eSchristos 			/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
4778585484eSchristos 			 * can't renegotiate with themselves. Disable. */
4788585484eSchristos 			disable_tls_11_and_12 = 1;
4798585484eSchristos 		}
4808585484eSchristos 		renegotiate_at = 600;
4818585484eSchristos 	}
4828585484eSchristos 
4838585484eSchristos 	ssl1 = SSL_new(get_ssl_ctx());
4848585484eSchristos 	ssl2 = SSL_new(get_ssl_ctx());
4858585484eSchristos 
486*eabc0478Schristos 	SSL_use_certificate(ssl2, the_cert);
487*eabc0478Schristos 	SSL_use_PrivateKey(ssl2, the_key);
4888585484eSchristos 
489*eabc0478Schristos 	if (!(type & REGRESS_OPENSSL_OPEN))
4908585484eSchristos 		flags |= BEV_OPT_CLOSE_ON_FREE;
4918585484eSchristos 
492*eabc0478Schristos 	if (!(type & REGRESS_OPENSSL_FILTER)) {
493*eabc0478Schristos 		tt_assert(type & REGRESS_OPENSSL_SOCKETPAIR);
4948585484eSchristos 		fd_pair = data->pair;
4958585484eSchristos 	} else {
4968585484eSchristos 		bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
4978585484eSchristos 		    BEV_OPT_CLOSE_ON_FREE);
4988585484eSchristos 		bev_ll[1] = bufferevent_socket_new(data->base, data->pair[1],
4998585484eSchristos 		    BEV_OPT_CLOSE_ON_FREE);
5008585484eSchristos 	}
5018585484eSchristos 
5028585484eSchristos 	open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
503*eabc0478Schristos 	    fd_pair, bev_ll, type);
5048585484eSchristos 
505*eabc0478Schristos 	if (!(type & REGRESS_OPENSSL_FILTER)) {
506*eabc0478Schristos 		tt_fd_op(bufferevent_getfd(bev1), ==, data->pair[0]);
5078585484eSchristos 	} else {
5088585484eSchristos 		tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
5098585484eSchristos 	}
5108585484eSchristos 
511*eabc0478Schristos 	if (type & REGRESS_OPENSSL_OPEN) {
5128585484eSchristos 		pending_connect_events = 2;
5138585484eSchristos 		stop_when_connected = 1;
5148585484eSchristos 		exit_base = data->base;
5158585484eSchristos 		event_base_dispatch(data->base);
5168585484eSchristos 		/* Okay, now the renegotiation is done.  Make new
5178585484eSchristos 		 * bufferevents to test opening in BUFFEREVENT_SSL_OPEN */
5188585484eSchristos 		flags |= BEV_OPT_CLOSE_ON_FREE;
5198585484eSchristos 		bufferevent_free(bev1);
5208585484eSchristos 		bufferevent_free(bev2);
5218585484eSchristos 		bev1 = bev2 = NULL;
5228585484eSchristos 		open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
523*eabc0478Schristos 		    fd_pair, bev_ll, type);
5248585484eSchristos 	}
5258585484eSchristos 
526*eabc0478Schristos 	if (!(type & REGRESS_OPENSSL_TIMEOUT)) {
5278585484eSchristos 		bufferevent_enable(bev1, EV_READ|EV_WRITE);
5288585484eSchristos 		bufferevent_enable(bev2, EV_READ|EV_WRITE);
5298585484eSchristos 
530*eabc0478Schristos 		if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
5318585484eSchristos 			evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
5328585484eSchristos 
5338585484eSchristos 		event_base_dispatch(data->base);
5348585484eSchristos 
5358585484eSchristos 		tt_assert(test_is_done == 1);
5368585484eSchristos 		tt_assert(n_connected == 2);
5378585484eSchristos 
538*eabc0478Schristos 		/* We don't handle shutdown properly yet */
539*eabc0478Schristos 		if (type & REGRESS_OPENSSL_DIRTY_SHUTDOWN) {
5408585484eSchristos 			tt_int_op(got_close, ==, 1);
5418585484eSchristos 			tt_int_op(got_error, ==, 0);
542*eabc0478Schristos 		} else {
543*eabc0478Schristos 			tt_int_op(got_error, ==, 1);
544*eabc0478Schristos 		}
545*eabc0478Schristos 		tt_int_op(got_timeout, ==, 0);
546*eabc0478Schristos 	} else {
547*eabc0478Schristos 		struct timeval t = { 2, 0 };
548*eabc0478Schristos 
549*eabc0478Schristos 		bufferevent_enable(bev1, EV_READ|EV_WRITE);
550*eabc0478Schristos 		bufferevent_disable(bev2, EV_READ|EV_WRITE);
551*eabc0478Schristos 
552*eabc0478Schristos 		bufferevent_set_timeouts(bev1, &t, &t);
553*eabc0478Schristos 
554*eabc0478Schristos 		if (!(type & REGRESS_OPENSSL_CLIENT_WRITE))
555*eabc0478Schristos 			evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
556*eabc0478Schristos 
557*eabc0478Schristos 		event_base_dispatch(data->base);
558*eabc0478Schristos 
559*eabc0478Schristos 		tt_assert(test_is_done == 0);
560*eabc0478Schristos 		tt_assert(n_connected == 0);
561*eabc0478Schristos 
562*eabc0478Schristos 		tt_int_op(got_close, ==, 0);
563*eabc0478Schristos 		tt_int_op(got_error, ==, 0);
564*eabc0478Schristos 		tt_int_op(got_timeout, ==, 1);
565*eabc0478Schristos 
566*eabc0478Schristos 		bufferevent_free(bev2);
567*eabc0478Schristos 	}
568*eabc0478Schristos 
5698585484eSchristos end:
5708585484eSchristos 	return;
5718585484eSchristos }
5728585484eSchristos 
5738585484eSchristos static void
574*eabc0478Schristos acceptcb_deferred(evutil_socket_t fd, short events, void *arg)
575*eabc0478Schristos {
576*eabc0478Schristos 	struct bufferevent *bev = arg;
577*eabc0478Schristos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
578*eabc0478Schristos }
579*eabc0478Schristos static void
5808585484eSchristos acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
5818585484eSchristos     struct sockaddr *addr, int socklen, void *arg)
5828585484eSchristos {
5838585484eSchristos 	struct basic_test_data *data = arg;
5848585484eSchristos 	struct bufferevent *bev;
585*eabc0478Schristos 	enum regress_openssl_type type;
5868585484eSchristos 	SSL *ssl = SSL_new(get_ssl_ctx());
5878585484eSchristos 
588*eabc0478Schristos 	type = (enum regress_openssl_type)data->setup_data;
589*eabc0478Schristos 
590*eabc0478Schristos 	SSL_use_certificate(ssl, the_cert);
591*eabc0478Schristos 	SSL_use_PrivateKey(ssl, the_key);
5928585484eSchristos 
5938585484eSchristos 	bev = bufferevent_openssl_socket_new(
594*eabc0478Schristos 		data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
5958585484eSchristos 		BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
596*eabc0478Schristos 	tt_assert(bev);
5978585484eSchristos 
5988585484eSchristos 	bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
599*eabc0478Schristos 	    (void*)(REGRESS_OPENSSL_SERVER));
6008585484eSchristos 
601*eabc0478Schristos 	if (type & REGRESS_OPENSSL_SLEEP) {
602*eabc0478Schristos 		struct timeval when = { 1, 0 };
603*eabc0478Schristos 		event_base_once(data->base, -1, EV_TIMEOUT,
604*eabc0478Schristos 		    acceptcb_deferred, bev, &when);
605*eabc0478Schristos 		bufferevent_disable(bev, EV_READ|EV_WRITE);
606*eabc0478Schristos 	} else {
6078585484eSchristos 		bufferevent_enable(bev, EV_READ|EV_WRITE);
608*eabc0478Schristos 	}
6098585484eSchristos 
6108585484eSchristos 	/* Only accept once, then disable ourself. */
6118585484eSchristos 	evconnlistener_disable(listener);
612*eabc0478Schristos 
613*eabc0478Schristos end:
614*eabc0478Schristos 	;
615*eabc0478Schristos }
616*eabc0478Schristos 
617*eabc0478Schristos struct rwcount
618*eabc0478Schristos {
619*eabc0478Schristos 	evutil_socket_t fd;
620*eabc0478Schristos 	size_t read;
621*eabc0478Schristos 	size_t write;
622*eabc0478Schristos };
623*eabc0478Schristos static int
624*eabc0478Schristos bio_rwcount_new(BIO *b)
625*eabc0478Schristos {
626*eabc0478Schristos 	BIO_set_init(b, 0);
627*eabc0478Schristos 	BIO_set_data(b, NULL);
628*eabc0478Schristos 	return 1;
629*eabc0478Schristos }
630*eabc0478Schristos static int
631*eabc0478Schristos bio_rwcount_free(BIO *b)
632*eabc0478Schristos {
633*eabc0478Schristos 	TT_BLATHER(("bio_rwcount_free: %p", b));
634*eabc0478Schristos 	if (!b)
635*eabc0478Schristos 		return 0;
636*eabc0478Schristos 	if (BIO_get_shutdown(b)) {
637*eabc0478Schristos 		BIO_set_init(b, 0);
638*eabc0478Schristos 		BIO_set_data(b, NULL);
639*eabc0478Schristos 	}
640*eabc0478Schristos 	return 1;
641*eabc0478Schristos }
642*eabc0478Schristos static int
643*eabc0478Schristos bio_rwcount_read(BIO *b, char *out, int outlen)
644*eabc0478Schristos {
645*eabc0478Schristos 	struct rwcount *rw = BIO_get_data(b);
646*eabc0478Schristos 	ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
647*eabc0478Schristos 	++rw->read;
648*eabc0478Schristos 	if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
649*eabc0478Schristos 		BIO_set_retry_read(b);
650*eabc0478Schristos 	}
651*eabc0478Schristos 	return ret;
652*eabc0478Schristos }
653*eabc0478Schristos static int
654*eabc0478Schristos bio_rwcount_write(BIO *b, const char *in, int inlen)
655*eabc0478Schristos {
656*eabc0478Schristos 	struct rwcount *rw = BIO_get_data(b);
657*eabc0478Schristos 	ev_ssize_t ret = send(rw->fd, in, inlen, 0);
658*eabc0478Schristos 	++rw->write;
659*eabc0478Schristos 	if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
660*eabc0478Schristos 		BIO_set_retry_write(b);
661*eabc0478Schristos 	}
662*eabc0478Schristos 	return ret;
663*eabc0478Schristos }
664*eabc0478Schristos static long
665*eabc0478Schristos bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
666*eabc0478Schristos {
667*eabc0478Schristos 	struct rwcount *rw = BIO_get_data(b);
668*eabc0478Schristos 	long ret = 0;
669*eabc0478Schristos 	switch (cmd) {
670*eabc0478Schristos 	case BIO_C_GET_FD:
671*eabc0478Schristos 		ret = rw->fd;
672*eabc0478Schristos 		break;
673*eabc0478Schristos 	case BIO_CTRL_GET_CLOSE:
674*eabc0478Schristos 		ret = BIO_get_shutdown(b);
675*eabc0478Schristos 		break;
676*eabc0478Schristos 	case BIO_CTRL_SET_CLOSE:
677*eabc0478Schristos 		BIO_set_shutdown(b, (int)num);
678*eabc0478Schristos 		break;
679*eabc0478Schristos 	case BIO_CTRL_PENDING:
680*eabc0478Schristos 		ret = 0;
681*eabc0478Schristos 		break;
682*eabc0478Schristos 	case BIO_CTRL_WPENDING:
683*eabc0478Schristos 		ret = 0;
684*eabc0478Schristos 		break;
685*eabc0478Schristos 	case BIO_CTRL_DUP:
686*eabc0478Schristos 	case BIO_CTRL_FLUSH:
687*eabc0478Schristos 		ret = 1;
688*eabc0478Schristos 		break;
689*eabc0478Schristos 	}
690*eabc0478Schristos 	return ret;
691*eabc0478Schristos }
692*eabc0478Schristos static int
693*eabc0478Schristos bio_rwcount_puts(BIO *b, const char *s)
694*eabc0478Schristos {
695*eabc0478Schristos 	return bio_rwcount_write(b, s, strlen(s));
696*eabc0478Schristos }
697*eabc0478Schristos #define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
698*eabc0478Schristos static BIO_METHOD *methods_rwcount;
699*eabc0478Schristos 
700*eabc0478Schristos static BIO_METHOD *
701*eabc0478Schristos BIO_s_rwcount(void)
702*eabc0478Schristos {
703*eabc0478Schristos 	if (methods_rwcount == NULL) {
704*eabc0478Schristos 		methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount");
705*eabc0478Schristos 		if (methods_rwcount == NULL)
706*eabc0478Schristos 			return NULL;
707*eabc0478Schristos 		BIO_meth_set_write(methods_rwcount, bio_rwcount_write);
708*eabc0478Schristos 		BIO_meth_set_read(methods_rwcount, bio_rwcount_read);
709*eabc0478Schristos 		BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts);
710*eabc0478Schristos 		BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl);
711*eabc0478Schristos 		BIO_meth_set_create(methods_rwcount, bio_rwcount_new);
712*eabc0478Schristos 		BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free);
713*eabc0478Schristos 	}
714*eabc0478Schristos 	return methods_rwcount;
715*eabc0478Schristos }
716*eabc0478Schristos static BIO *
717*eabc0478Schristos BIO_new_rwcount(int close_flag)
718*eabc0478Schristos {
719*eabc0478Schristos 	BIO *result;
720*eabc0478Schristos 	if (!(result = BIO_new(BIO_s_rwcount())))
721*eabc0478Schristos 		return NULL;
722*eabc0478Schristos 	BIO_set_init(result, 1);
723*eabc0478Schristos 	BIO_set_data(result,  NULL);
724*eabc0478Schristos 	BIO_set_shutdown(result, !!close_flag);
725*eabc0478Schristos 	return result;
7268585484eSchristos }
7278585484eSchristos 
7288585484eSchristos static void
7298585484eSchristos regress_bufferevent_openssl_connect(void *arg)
7308585484eSchristos {
7318585484eSchristos 	struct basic_test_data *data = arg;
7328585484eSchristos 
7338585484eSchristos 	struct event_base *base = data->base;
7348585484eSchristos 
7358585484eSchristos 	struct evconnlistener *listener;
7368585484eSchristos 	struct bufferevent *bev;
7378585484eSchristos 	struct sockaddr_in sin;
7388585484eSchristos 	struct sockaddr_storage ss;
7398585484eSchristos 	ev_socklen_t slen;
740*eabc0478Schristos 	SSL *ssl;
741*eabc0478Schristos 	struct rwcount rw = { -1, 0, 0 };
742*eabc0478Schristos 	enum regress_openssl_type type;
7438585484eSchristos 
744*eabc0478Schristos 	type = (enum regress_openssl_type)data->setup_data;
7458585484eSchristos 
7468585484eSchristos 	memset(&sin, 0, sizeof(sin));
7478585484eSchristos 	sin.sin_family = AF_INET;
7488585484eSchristos 	sin.sin_addr.s_addr = htonl(0x7f000001);
7498585484eSchristos 
7508585484eSchristos 	memset(&ss, 0, sizeof(ss));
7518585484eSchristos 	slen = sizeof(ss);
7528585484eSchristos 
7538585484eSchristos 	listener = evconnlistener_new_bind(base, acceptcb, data,
7548585484eSchristos 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
7558585484eSchristos 	    -1, (struct sockaddr *)&sin, sizeof(sin));
7568585484eSchristos 
7578585484eSchristos 	tt_assert(listener);
7588585484eSchristos 	tt_assert(evconnlistener_get_fd(listener) >= 0);
7598585484eSchristos 
760*eabc0478Schristos 	ssl = SSL_new(get_ssl_ctx());
761*eabc0478Schristos 	tt_assert(ssl);
762*eabc0478Schristos 
7638585484eSchristos 	bev = bufferevent_openssl_socket_new(
764*eabc0478Schristos 		data->base, -1, ssl,
7658585484eSchristos 		BUFFEREVENT_SSL_CONNECTING,
7668585484eSchristos 		BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
7678585484eSchristos 	tt_assert(bev);
7688585484eSchristos 
769*eabc0478Schristos 	bufferevent_setcb(bev, respond_to_number, free_on_cb, eventcb,
770*eabc0478Schristos 	    (void*)(REGRESS_OPENSSL_CLIENT));
7718585484eSchristos 
7728585484eSchristos 	tt_assert(getsockname(evconnlistener_get_fd(listener),
7738585484eSchristos 		(struct sockaddr*)&ss, &slen) == 0);
7748585484eSchristos 	tt_assert(slen == sizeof(struct sockaddr_in));
7758585484eSchristos 	tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
7768585484eSchristos 
7778585484eSchristos 	tt_assert(0 ==
7788585484eSchristos 	    bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
779*eabc0478Schristos 	/* Possible only when we have fd, since be_openssl can and will overwrite
780*eabc0478Schristos 	 * bio otherwise before */
781*eabc0478Schristos 	if (type & REGRESS_OPENSSL_SLEEP) {
782*eabc0478Schristos 		BIO *bio;
783*eabc0478Schristos 
784*eabc0478Schristos 		rw.fd = bufferevent_getfd(bev);
785*eabc0478Schristos 		bio = BIO_new_rwcount(0);
786*eabc0478Schristos 		tt_assert(bio);
787*eabc0478Schristos 		BIO_set_data(bio, &rw);
788*eabc0478Schristos 		SSL_set_bio(ssl, bio, bio);
789*eabc0478Schristos 	}
7908585484eSchristos 	evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
7918585484eSchristos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
7928585484eSchristos 
7938585484eSchristos 	event_base_dispatch(base);
794*eabc0478Schristos 
795*eabc0478Schristos 	tt_int_op(rw.read, <=, 100);
796*eabc0478Schristos 	tt_int_op(rw.write, <=, 100);
7978585484eSchristos end:
798*eabc0478Schristos 	evconnlistener_free(listener);
799*eabc0478Schristos }
800*eabc0478Schristos 
801*eabc0478Schristos struct wm_context
802*eabc0478Schristos {
803*eabc0478Schristos 	int server;
804*eabc0478Schristos 	int flags;
805*eabc0478Schristos 	struct evbuffer *data;
806*eabc0478Schristos 	size_t to_read;
807*eabc0478Schristos 	size_t wm_high;
808*eabc0478Schristos 	size_t limit;
809*eabc0478Schristos 	size_t get;
810*eabc0478Schristos 	struct bufferevent *bev;
811*eabc0478Schristos 	struct wm_context *neighbour;
812*eabc0478Schristos };
813*eabc0478Schristos static void
814*eabc0478Schristos wm_transfer(struct bufferevent *bev, void *arg)
815*eabc0478Schristos {
816*eabc0478Schristos 	struct wm_context *ctx = arg;
817*eabc0478Schristos 	struct evbuffer *in  = bufferevent_get_input(bev);
818*eabc0478Schristos 	struct evbuffer *out = bufferevent_get_output(bev);
819*eabc0478Schristos 	size_t len = evbuffer_get_length(in);
820*eabc0478Schristos 	size_t drain = len < ctx->to_read ? len : ctx->to_read;
821*eabc0478Schristos 
822*eabc0478Schristos 	if (ctx->get >= ctx->limit) {
823*eabc0478Schristos 		TT_BLATHER(("wm_transfer-%s(%p): break",
824*eabc0478Schristos 			ctx->server ? "server" : "client", bev));
825*eabc0478Schristos 		bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
826*eabc0478Schristos 		bufferevent_disable(bev, EV_READ);
827*eabc0478Schristos 		if (ctx->neighbour->get >= ctx->neighbour->limit) {
828*eabc0478Schristos 			event_base_loopbreak(bufferevent_get_base(bev));
829*eabc0478Schristos 		}
830*eabc0478Schristos 	} else {
831*eabc0478Schristos 		ctx->get += drain;
832*eabc0478Schristos 		evbuffer_drain(in, drain);
833*eabc0478Schristos 	}
834*eabc0478Schristos 
835*eabc0478Schristos 	TT_BLATHER(("wm_transfer-%s(%p): "
836*eabc0478Schristos 		"in: " EV_SIZE_FMT ", "
837*eabc0478Schristos 		"out: " EV_SIZE_FMT ", "
838*eabc0478Schristos 		"got: " EV_SIZE_FMT "",
839*eabc0478Schristos 		ctx->server ? "server" : "client", bev,
840*eabc0478Schristos 		evbuffer_get_length(in),
841*eabc0478Schristos 		evbuffer_get_length(out),
842*eabc0478Schristos 		ctx->get));
843*eabc0478Schristos 
844*eabc0478Schristos 	evbuffer_add_buffer_reference(out, ctx->data);
845*eabc0478Schristos }
846*eabc0478Schristos static void
847*eabc0478Schristos wm_eventcb(struct bufferevent *bev, short what, void *arg)
848*eabc0478Schristos {
849*eabc0478Schristos 	struct wm_context *ctx = arg;
850*eabc0478Schristos 	TT_BLATHER(("wm_eventcb-%s(%p): %i",
851*eabc0478Schristos 		ctx->server ? "server" : "client", bev, what));
852*eabc0478Schristos 	if (what & BEV_EVENT_CONNECTED) {
853*eabc0478Schristos 	} else {
854*eabc0478Schristos 		ctx->get = 0;
855*eabc0478Schristos 	}
856*eabc0478Schristos }
857*eabc0478Schristos static void
858*eabc0478Schristos wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
859*eabc0478Schristos     struct sockaddr *addr, int socklen, void *arg)
860*eabc0478Schristos {
861*eabc0478Schristos 	struct wm_context *ctx = arg;
862*eabc0478Schristos 	struct bufferevent *bev;
863*eabc0478Schristos 	struct event_base *base = evconnlistener_get_base(listener);
864*eabc0478Schristos 	SSL *ssl = SSL_new(get_ssl_ctx());
865*eabc0478Schristos 
866*eabc0478Schristos 	SSL_use_certificate(ssl, the_cert);
867*eabc0478Schristos 	SSL_use_PrivateKey(ssl, the_key);
868*eabc0478Schristos 
869*eabc0478Schristos 	bev = bufferevent_openssl_socket_new(
870*eabc0478Schristos 		base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
871*eabc0478Schristos 
872*eabc0478Schristos 	TT_BLATHER(("wm_transfer-%s(%p): accept",
873*eabc0478Schristos 		ctx->server ? "server" : "client", bev));
874*eabc0478Schristos 
875*eabc0478Schristos 	bufferevent_setwatermark(bev, EV_READ, 0, ctx->wm_high);
876*eabc0478Schristos 	bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, ctx);
877*eabc0478Schristos 	bufferevent_enable(bev, EV_READ|EV_WRITE);
878*eabc0478Schristos 	ctx->bev = bev;
879*eabc0478Schristos 
880*eabc0478Schristos 	/* Only accept once, then disable ourself. */
881*eabc0478Schristos 	evconnlistener_disable(listener);
882*eabc0478Schristos }
883*eabc0478Schristos static void
884*eabc0478Schristos regress_bufferevent_openssl_wm(void *arg)
885*eabc0478Schristos {
886*eabc0478Schristos 	struct basic_test_data *data = arg;
887*eabc0478Schristos 	struct event_base *base = data->base;
888*eabc0478Schristos 
889*eabc0478Schristos 	struct evconnlistener *listener;
890*eabc0478Schristos 	struct bufferevent *bev;
891*eabc0478Schristos 	struct sockaddr_in sin;
892*eabc0478Schristos 	struct sockaddr_storage ss;
893*eabc0478Schristos 	enum regress_openssl_type type =
894*eabc0478Schristos 		(enum regress_openssl_type)data->setup_data;
895*eabc0478Schristos 	int bev_flags = BEV_OPT_CLOSE_ON_FREE;
896*eabc0478Schristos 	ev_socklen_t slen;
897*eabc0478Schristos 	SSL *ssl;
898*eabc0478Schristos 	struct wm_context client, server;
899*eabc0478Schristos 	char *payload;
900*eabc0478Schristos 	size_t payload_len = 1<<10;
901*eabc0478Schristos 	size_t wm_high = 5<<10;
902*eabc0478Schristos 
903*eabc0478Schristos 	memset(&sin, 0, sizeof(sin));
904*eabc0478Schristos 	sin.sin_family = AF_INET;
905*eabc0478Schristos 	sin.sin_addr.s_addr = htonl(0x7f000001);
906*eabc0478Schristos 
907*eabc0478Schristos 	memset(&ss, 0, sizeof(ss));
908*eabc0478Schristos 	slen = sizeof(ss);
909*eabc0478Schristos 
910*eabc0478Schristos 	if (type & REGRESS_DEFERRED_CALLBACKS)
911*eabc0478Schristos 		bev_flags |= BEV_OPT_DEFER_CALLBACKS;
912*eabc0478Schristos 
913*eabc0478Schristos 	memset(&client, 0, sizeof(client));
914*eabc0478Schristos 	memset(&server, 0, sizeof(server));
915*eabc0478Schristos 	client.server = 0;
916*eabc0478Schristos 	server.server = 1;
917*eabc0478Schristos 	client.flags = server.flags = bev_flags;
918*eabc0478Schristos 	client.data = evbuffer_new();
919*eabc0478Schristos 	server.data = evbuffer_new();
920*eabc0478Schristos 	payload = calloc(1, payload_len);
921*eabc0478Schristos 	memset(payload, 'A', payload_len);
922*eabc0478Schristos 	evbuffer_add(server.data, payload, payload_len);
923*eabc0478Schristos 	evbuffer_add(client.data, payload, payload_len);
924*eabc0478Schristos 	client.wm_high = server.wm_high = wm_high;
925*eabc0478Schristos 	client.limit = server.limit = wm_high<<3;
926*eabc0478Schristos 	client.to_read = server.to_read = payload_len>>1;
927*eabc0478Schristos 
928*eabc0478Schristos 	TT_BLATHER(("openssl_wm: "
929*eabc0478Schristos 		"payload_len = " EV_SIZE_FMT ", "
930*eabc0478Schristos 		"wm_high = " EV_SIZE_FMT ", "
931*eabc0478Schristos 		"limit = " EV_SIZE_FMT ", "
932*eabc0478Schristos 		"to_read: " EV_SIZE_FMT "",
933*eabc0478Schristos 		payload_len,
934*eabc0478Schristos 		wm_high,
935*eabc0478Schristos 		server.limit,
936*eabc0478Schristos 		server.to_read));
937*eabc0478Schristos 
938*eabc0478Schristos 	listener = evconnlistener_new_bind(base, wm_acceptcb, &server,
939*eabc0478Schristos 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
940*eabc0478Schristos 	    -1, (struct sockaddr *)&sin, sizeof(sin));
941*eabc0478Schristos 
942*eabc0478Schristos 	tt_assert(listener);
943*eabc0478Schristos 	tt_assert(evconnlistener_get_fd(listener) >= 0);
944*eabc0478Schristos 
945*eabc0478Schristos 	ssl = SSL_new(get_ssl_ctx());
946*eabc0478Schristos 	tt_assert(ssl);
947*eabc0478Schristos 
948*eabc0478Schristos 	if (type & REGRESS_OPENSSL_FILTER) {
949*eabc0478Schristos 		bev = bufferevent_socket_new(data->base, -1, client.flags);
950*eabc0478Schristos 		tt_assert(bev);
951*eabc0478Schristos 		bev = bufferevent_openssl_filter_new(
952*eabc0478Schristos 			base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
953*eabc0478Schristos 	} else {
954*eabc0478Schristos 		bev = bufferevent_openssl_socket_new(
955*eabc0478Schristos 			data->base, -1, ssl,
956*eabc0478Schristos 			BUFFEREVENT_SSL_CONNECTING,
957*eabc0478Schristos 			client.flags);
958*eabc0478Schristos 	}
959*eabc0478Schristos 	tt_assert(bev);
960*eabc0478Schristos 	client.bev = bev;
961*eabc0478Schristos 
962*eabc0478Schristos 	server.neighbour = &client;
963*eabc0478Schristos 	client.neighbour = &server;
964*eabc0478Schristos 
965*eabc0478Schristos 	bufferevent_setwatermark(bev, EV_READ, 0, client.wm_high);
966*eabc0478Schristos 	bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, &client);
967*eabc0478Schristos 
968*eabc0478Schristos 	tt_assert(getsockname(evconnlistener_get_fd(listener),
969*eabc0478Schristos 		(struct sockaddr*)&ss, &slen) == 0);
970*eabc0478Schristos 
971*eabc0478Schristos 	tt_assert(!bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
972*eabc0478Schristos 	tt_assert(!evbuffer_add_buffer_reference(bufferevent_get_output(bev), client.data));
973*eabc0478Schristos 	tt_assert(!bufferevent_enable(bev, EV_READ|EV_WRITE));
974*eabc0478Schristos 
975*eabc0478Schristos 	event_base_dispatch(base);
976*eabc0478Schristos 
977*eabc0478Schristos 	tt_int_op(client.get, ==, client.limit);
978*eabc0478Schristos 	tt_int_op(server.get, ==, server.limit);
979*eabc0478Schristos 
980*eabc0478Schristos end:
981*eabc0478Schristos 	free(payload);
982*eabc0478Schristos 	evbuffer_free(client.data);
983*eabc0478Schristos 	evbuffer_free(server.data);
984*eabc0478Schristos 	evconnlistener_free(listener);
985*eabc0478Schristos 	bufferevent_free(client.bev);
986*eabc0478Schristos 	bufferevent_free(server.bev);
987*eabc0478Schristos 
988*eabc0478Schristos 	/* XXX: by some reason otherise there is a leak */
989*eabc0478Schristos 	if (!(type & REGRESS_OPENSSL_FILTER))
990*eabc0478Schristos 		event_base_loop(base, EVLOOP_ONCE);
9918585484eSchristos }
9928585484eSchristos 
9938585484eSchristos struct testcase_t ssl_testcases[] = {
994*eabc0478Schristos #define T(a) ((void *)(a))
995*eabc0478Schristos 	{ "bufferevent_socketpair", regress_bufferevent_openssl,
996*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
997*eabc0478Schristos 	{ "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl,
998*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
999*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) },
10008585484eSchristos 	{ "bufferevent_filter", regress_bufferevent_openssl,
1001*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
1002*eabc0478Schristos 	{ "bufferevent_filter_write_after_connect", regress_bufferevent_openssl,
1003*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1004*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER|REGRESS_OPENSSL_CLIENT_WRITE) },
10058585484eSchristos 	{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
1006*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1007*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
10088585484eSchristos 	{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
1009*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1010*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
10118585484eSchristos 	{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
1012*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1013*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
10148585484eSchristos 	{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
1015*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1016*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
1017*eabc0478Schristos 
1018*eabc0478Schristos 	{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
1019*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1020*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1021*eabc0478Schristos 	{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
1022*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1023*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1024*eabc0478Schristos 	{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
1025*eabc0478Schristos 	  regress_bufferevent_openssl,
1026*eabc0478Schristos 	  TT_ISOLATED,
1027*eabc0478Schristos 	  &ssl_setup,
1028*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1029*eabc0478Schristos 	{ "bufferevent_renegotiate_filter_dirty_shutdown",
1030*eabc0478Schristos 	  regress_bufferevent_openssl,
1031*eabc0478Schristos 	  TT_ISOLATED,
1032*eabc0478Schristos 	  &ssl_setup,
1033*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1034*eabc0478Schristos 	{ "bufferevent_socketpair_startopen_dirty_shutdown",
1035*eabc0478Schristos 	  regress_bufferevent_openssl,
1036*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1037*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1038*eabc0478Schristos 	{ "bufferevent_filter_startopen_dirty_shutdown",
1039*eabc0478Schristos 	  regress_bufferevent_openssl,
1040*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1041*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
1042*eabc0478Schristos 
1043*eabc0478Schristos 	{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
1044*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1045*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
1046*eabc0478Schristos 	{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
1047*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1048*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
1049*eabc0478Schristos 	{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
1050*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1051*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
1052*eabc0478Schristos 	{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
1053*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1054*eabc0478Schristos 	  T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
1055*eabc0478Schristos 
1056*eabc0478Schristos 	{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
1057*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1058*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
1059*eabc0478Schristos 	{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
1060*eabc0478Schristos 	  TT_ISOLATED, &ssl_setup,
1061*eabc0478Schristos 	  T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
10628585484eSchristos 
10638585484eSchristos 	{ "bufferevent_connect", regress_bufferevent_openssl_connect,
1064*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
1065*eabc0478Schristos 	{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
1066*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
1067*eabc0478Schristos 
1068*eabc0478Schristos 	{ "bufferevent_wm", regress_bufferevent_openssl_wm,
1069*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
1070*eabc0478Schristos 	{ "bufferevent_wm_filter", regress_bufferevent_openssl_wm,
1071*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
1072*eabc0478Schristos 	{ "bufferevent_wm_defer", regress_bufferevent_openssl_wm,
1073*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_DEFERRED_CALLBACKS) },
1074*eabc0478Schristos 	{ "bufferevent_wm_filter_defer", regress_bufferevent_openssl_wm,
1075*eabc0478Schristos 	  TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER|REGRESS_DEFERRED_CALLBACKS) },
1076*eabc0478Schristos 
1077*eabc0478Schristos #undef T
10788585484eSchristos 
10798585484eSchristos 	END_OF_TESTCASES,
10808585484eSchristos };
1081