1*e985b929SDavid van Moolenbroek /* $NetBSD: regress_ssl.c,v 1.2 2013/04/11 16:56:42 christos Exp $ */
2*e985b929SDavid van Moolenbroek /*
3*e985b929SDavid van Moolenbroek * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
4*e985b929SDavid van Moolenbroek *
5*e985b929SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*e985b929SDavid van Moolenbroek * modification, are permitted provided that the following conditions
7*e985b929SDavid van Moolenbroek * are met:
8*e985b929SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
9*e985b929SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
10*e985b929SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
11*e985b929SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
12*e985b929SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
13*e985b929SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
14*e985b929SDavid van Moolenbroek * derived from this software without specific prior written permission.
15*e985b929SDavid van Moolenbroek *
16*e985b929SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*e985b929SDavid van Moolenbroek * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*e985b929SDavid van Moolenbroek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*e985b929SDavid van Moolenbroek * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*e985b929SDavid van Moolenbroek * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*e985b929SDavid van Moolenbroek * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*e985b929SDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*e985b929SDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*e985b929SDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*e985b929SDavid van Moolenbroek * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*e985b929SDavid van Moolenbroek */
27*e985b929SDavid van Moolenbroek
28*e985b929SDavid van Moolenbroek #ifdef WIN32
29*e985b929SDavid van Moolenbroek #include <winsock2.h>
30*e985b929SDavid van Moolenbroek #include <windows.h>
31*e985b929SDavid van Moolenbroek #endif
32*e985b929SDavid van Moolenbroek
33*e985b929SDavid van Moolenbroek #ifndef WIN32
34*e985b929SDavid van Moolenbroek #include <sys/types.h>
35*e985b929SDavid van Moolenbroek #include <sys/socket.h>
36*e985b929SDavid van Moolenbroek #include <netinet/in.h>
37*e985b929SDavid van Moolenbroek #endif
38*e985b929SDavid van Moolenbroek
39*e985b929SDavid van Moolenbroek #include "event2/util.h"
40*e985b929SDavid van Moolenbroek #include "event2/event.h"
41*e985b929SDavid van Moolenbroek #include "event2/bufferevent_ssl.h"
42*e985b929SDavid van Moolenbroek #include "event2/buffer.h"
43*e985b929SDavid van Moolenbroek #include "event2/listener.h"
44*e985b929SDavid van Moolenbroek
45*e985b929SDavid van Moolenbroek #include "regress.h"
46*e985b929SDavid van Moolenbroek #include "tinytest.h"
47*e985b929SDavid van Moolenbroek #include "tinytest_macros.h"
48*e985b929SDavid van Moolenbroek
49*e985b929SDavid van Moolenbroek #include <openssl/ssl.h>
50*e985b929SDavid van Moolenbroek #include <openssl/bio.h>
51*e985b929SDavid van Moolenbroek #include <openssl/err.h>
52*e985b929SDavid van Moolenbroek #include <openssl/pem.h>
53*e985b929SDavid van Moolenbroek
54*e985b929SDavid van Moolenbroek #include <string.h>
55*e985b929SDavid van Moolenbroek
56*e985b929SDavid van Moolenbroek /* A short pre-generated key, to save the cost of doing an RSA key generation
57*e985b929SDavid van Moolenbroek * step during the unit tests. It's only 512 bits long, and it is published
58*e985b929SDavid van Moolenbroek * in this file, so you would have to be very foolish to consider using it in
59*e985b929SDavid van Moolenbroek * your own code. */
60*e985b929SDavid van Moolenbroek static const char KEY[] =
61*e985b929SDavid van Moolenbroek "-----BEGIN RSA PRIVATE KEY-----\n"
62*e985b929SDavid van Moolenbroek "MIIBOgIBAAJBAKibTEzXjj+sqpipePX1lEk5BNFuL/dDBbw8QCXgaJWikOiKHeJq\n"
63*e985b929SDavid van Moolenbroek "3FQ0OmCnmpkdsPFE4x3ojYmmdgE2i0dJwq0CAwEAAQJAZ08gpUS+qE1IClps/2gG\n"
64*e985b929SDavid van Moolenbroek "AAer6Bc31K2AaiIQvCSQcH440cp062QtWMC3V5sEoWmdLsbAHFH26/9ZHn5zAflp\n"
65*e985b929SDavid van Moolenbroek "gQIhANWOx/UYeR8HD0WREU5kcuSzgzNLwUErHLzxP7U6aojpAiEAyh2H35CjN/P7\n"
66*e985b929SDavid van Moolenbroek "NhcZ4QYw3PeUWpqgJnaE/4i80BSYkSUCIQDLHFhLYLJZ80HwHTADif/ISn9/Ow6b\n"
67*e985b929SDavid van Moolenbroek "p6BWh3DbMar/eQIgBPS6azH5vpp983KXkNv9AL4VZi9ac/b+BeINdzC6GP0CIDmB\n"
68*e985b929SDavid van Moolenbroek "U6GFEQTZ3IfuiVabG5pummdC4DNbcdI+WKrSFNmQ\n"
69*e985b929SDavid van Moolenbroek "-----END RSA PRIVATE KEY-----\n";
70*e985b929SDavid van Moolenbroek static void *xkey = __UNCONST(KEY);
71*e985b929SDavid van Moolenbroek
72*e985b929SDavid van Moolenbroek static EVP_PKEY *
getkey(void)73*e985b929SDavid van Moolenbroek getkey(void)
74*e985b929SDavid van Moolenbroek {
75*e985b929SDavid van Moolenbroek EVP_PKEY *key;
76*e985b929SDavid van Moolenbroek BIO *bio;
77*e985b929SDavid van Moolenbroek
78*e985b929SDavid van Moolenbroek /* new read-only BIO backed by KEY. */
79*e985b929SDavid van Moolenbroek bio = BIO_new_mem_buf(xkey, -1);
80*e985b929SDavid van Moolenbroek tt_assert(bio);
81*e985b929SDavid van Moolenbroek
82*e985b929SDavid van Moolenbroek key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
83*e985b929SDavid van Moolenbroek BIO_free(bio);
84*e985b929SDavid van Moolenbroek tt_assert(key);
85*e985b929SDavid van Moolenbroek
86*e985b929SDavid van Moolenbroek return key;
87*e985b929SDavid van Moolenbroek end:
88*e985b929SDavid van Moolenbroek return NULL;
89*e985b929SDavid van Moolenbroek }
90*e985b929SDavid van Moolenbroek
91*e985b929SDavid van Moolenbroek static X509 *
getcert(void)92*e985b929SDavid van Moolenbroek getcert(void)
93*e985b929SDavid van Moolenbroek {
94*e985b929SDavid van Moolenbroek /* Dummy code to make a quick-and-dirty valid certificate with
95*e985b929SDavid van Moolenbroek OpenSSL. Don't copy this code into your own program! It does a
96*e985b929SDavid van Moolenbroek number of things in a stupid and insecure way. */
97*e985b929SDavid van Moolenbroek X509 *x509 = NULL;
98*e985b929SDavid van Moolenbroek X509_NAME *name = NULL;
99*e985b929SDavid van Moolenbroek EVP_PKEY *key = getkey();
100*e985b929SDavid van Moolenbroek int nid;
101*e985b929SDavid van Moolenbroek time_t now = time(NULL);
102*e985b929SDavid van Moolenbroek
103*e985b929SDavid van Moolenbroek tt_assert(key);
104*e985b929SDavid van Moolenbroek
105*e985b929SDavid van Moolenbroek x509 = X509_new();
106*e985b929SDavid van Moolenbroek tt_assert(x509);
107*e985b929SDavid van Moolenbroek tt_assert(0 != X509_set_version(x509, 2));
108*e985b929SDavid van Moolenbroek tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509),
109*e985b929SDavid van Moolenbroek (long)now));
110*e985b929SDavid van Moolenbroek
111*e985b929SDavid van Moolenbroek name = X509_NAME_new();
112*e985b929SDavid van Moolenbroek tt_assert(name);
113*e985b929SDavid van Moolenbroek nid = OBJ_txt2nid("commonName");
114*e985b929SDavid van Moolenbroek tt_assert(NID_undef != nid);
115*e985b929SDavid van Moolenbroek tt_assert(0 != X509_NAME_add_entry_by_NID(
116*e985b929SDavid van Moolenbroek name, nid, MBSTRING_ASC, __UNCONST("example.com"),
117*e985b929SDavid van Moolenbroek -1, -1, 0));
118*e985b929SDavid van Moolenbroek
119*e985b929SDavid van Moolenbroek X509_set_subject_name(x509, name);
120*e985b929SDavid van Moolenbroek X509_set_issuer_name(x509, name);
121*e985b929SDavid van Moolenbroek
122*e985b929SDavid van Moolenbroek X509_time_adj(X509_get_notBefore(x509), 0, &now);
123*e985b929SDavid van Moolenbroek now += 3600;
124*e985b929SDavid van Moolenbroek X509_time_adj(X509_get_notAfter(x509), 0, &now);
125*e985b929SDavid van Moolenbroek X509_set_pubkey(x509, key);
126*e985b929SDavid van Moolenbroek tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
127*e985b929SDavid van Moolenbroek
128*e985b929SDavid van Moolenbroek return x509;
129*e985b929SDavid van Moolenbroek end:
130*e985b929SDavid van Moolenbroek X509_free(x509);
131*e985b929SDavid van Moolenbroek return NULL;
132*e985b929SDavid van Moolenbroek }
133*e985b929SDavid van Moolenbroek
134*e985b929SDavid van Moolenbroek static int disable_tls_11_and_12 = 0;
135*e985b929SDavid van Moolenbroek static SSL_CTX *the_ssl_ctx = NULL;
136*e985b929SDavid van Moolenbroek
137*e985b929SDavid van Moolenbroek static SSL_CTX *
get_ssl_ctx(void)138*e985b929SDavid van Moolenbroek get_ssl_ctx(void)
139*e985b929SDavid van Moolenbroek {
140*e985b929SDavid van Moolenbroek if (the_ssl_ctx)
141*e985b929SDavid van Moolenbroek return the_ssl_ctx;
142*e985b929SDavid van Moolenbroek the_ssl_ctx = SSL_CTX_new(SSLv23_method());
143*e985b929SDavid van Moolenbroek if (!the_ssl_ctx)
144*e985b929SDavid van Moolenbroek return NULL;
145*e985b929SDavid van Moolenbroek if (disable_tls_11_and_12) {
146*e985b929SDavid van Moolenbroek #ifdef SSL_OP_NO_TLSv1_2
147*e985b929SDavid van Moolenbroek SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
148*e985b929SDavid van Moolenbroek #endif
149*e985b929SDavid van Moolenbroek #ifdef SSL_OP_NO_TLSv1_1
150*e985b929SDavid van Moolenbroek SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
151*e985b929SDavid van Moolenbroek #endif
152*e985b929SDavid van Moolenbroek }
153*e985b929SDavid van Moolenbroek return the_ssl_ctx;
154*e985b929SDavid van Moolenbroek }
155*e985b929SDavid van Moolenbroek
156*e985b929SDavid van Moolenbroek static void
init_ssl(void)157*e985b929SDavid van Moolenbroek init_ssl(void)
158*e985b929SDavid van Moolenbroek {
159*e985b929SDavid van Moolenbroek SSL_library_init();
160*e985b929SDavid van Moolenbroek ERR_load_crypto_strings();
161*e985b929SDavid van Moolenbroek SSL_load_error_strings();
162*e985b929SDavid van Moolenbroek OpenSSL_add_all_algorithms();
163*e985b929SDavid van Moolenbroek if (SSLeay() != OPENSSL_VERSION_NUMBER) {
164*e985b929SDavid van Moolenbroek TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx but running with %lx", (unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
165*e985b929SDavid van Moolenbroek }
166*e985b929SDavid van Moolenbroek }
167*e985b929SDavid van Moolenbroek
168*e985b929SDavid van Moolenbroek /* ====================
169*e985b929SDavid van Moolenbroek Here's a simple test: we read a number from the input, increment it, and
170*e985b929SDavid van Moolenbroek reply, until we get to 1001.
171*e985b929SDavid van Moolenbroek */
172*e985b929SDavid van Moolenbroek
173*e985b929SDavid van Moolenbroek static int test_is_done = 0;
174*e985b929SDavid van Moolenbroek static int n_connected = 0;
175*e985b929SDavid van Moolenbroek static int got_close = 0;
176*e985b929SDavid van Moolenbroek static int got_error = 0;
177*e985b929SDavid van Moolenbroek static int renegotiate_at = -1;
178*e985b929SDavid van Moolenbroek static int stop_when_connected = 0;
179*e985b929SDavid van Moolenbroek static int pending_connect_events = 0;
180*e985b929SDavid van Moolenbroek static struct event_base *exit_base = NULL;
181*e985b929SDavid van Moolenbroek
182*e985b929SDavid van Moolenbroek static void
respond_to_number(struct bufferevent * bev,void * ctx)183*e985b929SDavid van Moolenbroek respond_to_number(struct bufferevent *bev, void *ctx)
184*e985b929SDavid van Moolenbroek {
185*e985b929SDavid van Moolenbroek struct evbuffer *b = bufferevent_get_input(bev);
186*e985b929SDavid van Moolenbroek char *line;
187*e985b929SDavid van Moolenbroek int n;
188*e985b929SDavid van Moolenbroek line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
189*e985b929SDavid van Moolenbroek if (! line)
190*e985b929SDavid van Moolenbroek return;
191*e985b929SDavid van Moolenbroek n = atoi(line);
192*e985b929SDavid van Moolenbroek if (n <= 0)
193*e985b929SDavid van Moolenbroek TT_FAIL(("Bad number: %s", line));
194*e985b929SDavid van Moolenbroek TT_BLATHER(("The number was %d", n));
195*e985b929SDavid van Moolenbroek if (n == 1001) {
196*e985b929SDavid van Moolenbroek ++test_is_done;
197*e985b929SDavid van Moolenbroek bufferevent_free(bev); /* Should trigger close on other side. */
198*e985b929SDavid van Moolenbroek return;
199*e985b929SDavid van Moolenbroek }
200*e985b929SDavid van Moolenbroek if (!strcmp(ctx, "client") && n == renegotiate_at) {
201*e985b929SDavid van Moolenbroek SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
202*e985b929SDavid van Moolenbroek }
203*e985b929SDavid van Moolenbroek ++n;
204*e985b929SDavid van Moolenbroek evbuffer_add_printf(bufferevent_get_output(bev),
205*e985b929SDavid van Moolenbroek "%d\n", n);
206*e985b929SDavid van Moolenbroek TT_BLATHER(("Done reading; now writing."));
207*e985b929SDavid van Moolenbroek bufferevent_enable(bev, EV_WRITE);
208*e985b929SDavid van Moolenbroek bufferevent_disable(bev, EV_READ);
209*e985b929SDavid van Moolenbroek }
210*e985b929SDavid van Moolenbroek
211*e985b929SDavid van Moolenbroek static void
done_writing_cb(struct bufferevent * bev,void * ctx)212*e985b929SDavid van Moolenbroek done_writing_cb(struct bufferevent *bev, void *ctx)
213*e985b929SDavid van Moolenbroek {
214*e985b929SDavid van Moolenbroek struct evbuffer *b = bufferevent_get_output(bev);
215*e985b929SDavid van Moolenbroek if (evbuffer_get_length(b))
216*e985b929SDavid van Moolenbroek return;
217*e985b929SDavid van Moolenbroek TT_BLATHER(("Done writing."));
218*e985b929SDavid van Moolenbroek bufferevent_disable(bev, EV_WRITE);
219*e985b929SDavid van Moolenbroek bufferevent_enable(bev, EV_READ);
220*e985b929SDavid van Moolenbroek }
221*e985b929SDavid van Moolenbroek
222*e985b929SDavid van Moolenbroek static void
eventcb(struct bufferevent * bev,short what,void * ctx)223*e985b929SDavid van Moolenbroek eventcb(struct bufferevent *bev, short what, void *ctx)
224*e985b929SDavid van Moolenbroek {
225*e985b929SDavid van Moolenbroek TT_BLATHER(("Got event %d", (int)what));
226*e985b929SDavid van Moolenbroek if (what & BEV_EVENT_CONNECTED) {
227*e985b929SDavid van Moolenbroek SSL *ssl;
228*e985b929SDavid van Moolenbroek X509 *peer_cert;
229*e985b929SDavid van Moolenbroek ++n_connected;
230*e985b929SDavid van Moolenbroek ssl = bufferevent_openssl_get_ssl(bev);
231*e985b929SDavid van Moolenbroek tt_assert(ssl);
232*e985b929SDavid van Moolenbroek peer_cert = SSL_get_peer_certificate(ssl);
233*e985b929SDavid van Moolenbroek if (0==strcmp(ctx, "server")) {
234*e985b929SDavid van Moolenbroek tt_assert(peer_cert == NULL);
235*e985b929SDavid van Moolenbroek } else {
236*e985b929SDavid van Moolenbroek tt_assert(peer_cert != NULL);
237*e985b929SDavid van Moolenbroek }
238*e985b929SDavid van Moolenbroek if (stop_when_connected) {
239*e985b929SDavid van Moolenbroek if (--pending_connect_events == 0)
240*e985b929SDavid van Moolenbroek event_base_loopexit(exit_base, NULL);
241*e985b929SDavid van Moolenbroek }
242*e985b929SDavid van Moolenbroek } else if (what & BEV_EVENT_EOF) {
243*e985b929SDavid van Moolenbroek TT_BLATHER(("Got a good EOF"));
244*e985b929SDavid van Moolenbroek ++got_close;
245*e985b929SDavid van Moolenbroek bufferevent_free(bev);
246*e985b929SDavid van Moolenbroek } else if (what & BEV_EVENT_ERROR) {
247*e985b929SDavid van Moolenbroek TT_BLATHER(("Got an error."));
248*e985b929SDavid van Moolenbroek ++got_error;
249*e985b929SDavid van Moolenbroek bufferevent_free(bev);
250*e985b929SDavid van Moolenbroek }
251*e985b929SDavid van Moolenbroek end:
252*e985b929SDavid van Moolenbroek ;
253*e985b929SDavid van Moolenbroek }
254*e985b929SDavid van Moolenbroek
255*e985b929SDavid van Moolenbroek static void
open_ssl_bufevs(struct bufferevent ** bev1_out,struct bufferevent ** bev2_out,struct event_base * base,int is_open,int flags,SSL * ssl1,SSL * ssl2,evutil_socket_t * fd_pair,struct bufferevent ** underlying_pair)256*e985b929SDavid van Moolenbroek open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
257*e985b929SDavid van Moolenbroek struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
258*e985b929SDavid van Moolenbroek evutil_socket_t *fd_pair, struct bufferevent **underlying_pair)
259*e985b929SDavid van Moolenbroek {
260*e985b929SDavid van Moolenbroek int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
261*e985b929SDavid van Moolenbroek int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
262*e985b929SDavid van Moolenbroek if (fd_pair) {
263*e985b929SDavid van Moolenbroek *bev1_out = bufferevent_openssl_socket_new(
264*e985b929SDavid van Moolenbroek base, fd_pair[0], ssl1, state1, flags);
265*e985b929SDavid van Moolenbroek *bev2_out = bufferevent_openssl_socket_new(
266*e985b929SDavid van Moolenbroek base, fd_pair[1], ssl2, state2, flags);
267*e985b929SDavid van Moolenbroek } else {
268*e985b929SDavid van Moolenbroek *bev1_out = bufferevent_openssl_filter_new(
269*e985b929SDavid van Moolenbroek base, underlying_pair[0], ssl1, state1, flags);
270*e985b929SDavid van Moolenbroek *bev2_out = bufferevent_openssl_filter_new(
271*e985b929SDavid van Moolenbroek base, underlying_pair[1], ssl2, state2, flags);
272*e985b929SDavid van Moolenbroek
273*e985b929SDavid van Moolenbroek }
274*e985b929SDavid van Moolenbroek bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
275*e985b929SDavid van Moolenbroek eventcb, __UNCONST("client"));
276*e985b929SDavid van Moolenbroek bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
277*e985b929SDavid van Moolenbroek eventcb, __UNCONST("server"));
278*e985b929SDavid van Moolenbroek }
279*e985b929SDavid van Moolenbroek
280*e985b929SDavid van Moolenbroek static void
regress_bufferevent_openssl(void * arg)281*e985b929SDavid van Moolenbroek regress_bufferevent_openssl(void *arg)
282*e985b929SDavid van Moolenbroek {
283*e985b929SDavid van Moolenbroek struct basic_test_data *data = arg;
284*e985b929SDavid van Moolenbroek
285*e985b929SDavid van Moolenbroek struct bufferevent *bev1, *bev2;
286*e985b929SDavid van Moolenbroek SSL *ssl1, *ssl2;
287*e985b929SDavid van Moolenbroek X509 *cert = getcert();
288*e985b929SDavid van Moolenbroek EVP_PKEY *key = getkey();
289*e985b929SDavid van Moolenbroek const int start_open = strstr((char*)data->setup_data, "open")!=NULL;
290*e985b929SDavid van Moolenbroek const int filter = strstr((char*)data->setup_data, "filter")!=NULL;
291*e985b929SDavid van Moolenbroek int flags = BEV_OPT_DEFER_CALLBACKS;
292*e985b929SDavid van Moolenbroek struct bufferevent *bev_ll[2] = { NULL, NULL };
293*e985b929SDavid van Moolenbroek evutil_socket_t *fd_pair = NULL;
294*e985b929SDavid van Moolenbroek
295*e985b929SDavid van Moolenbroek tt_assert(cert);
296*e985b929SDavid van Moolenbroek tt_assert(key);
297*e985b929SDavid van Moolenbroek
298*e985b929SDavid van Moolenbroek init_ssl();
299*e985b929SDavid van Moolenbroek
300*e985b929SDavid van Moolenbroek if (strstr((char*)data->setup_data, "renegotiate")) {
301*e985b929SDavid van Moolenbroek if (SSLeay() >= 0x10001000 &&
302*e985b929SDavid van Moolenbroek SSLeay() < 0x1000104f) {
303*e985b929SDavid van Moolenbroek /* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
304*e985b929SDavid van Moolenbroek * can't renegotiate with themselves. Disable. */
305*e985b929SDavid van Moolenbroek disable_tls_11_and_12 = 1;
306*e985b929SDavid van Moolenbroek }
307*e985b929SDavid van Moolenbroek renegotiate_at = 600;
308*e985b929SDavid van Moolenbroek }
309*e985b929SDavid van Moolenbroek
310*e985b929SDavid van Moolenbroek ssl1 = SSL_new(get_ssl_ctx());
311*e985b929SDavid van Moolenbroek ssl2 = SSL_new(get_ssl_ctx());
312*e985b929SDavid van Moolenbroek
313*e985b929SDavid van Moolenbroek SSL_use_certificate(ssl2, cert);
314*e985b929SDavid van Moolenbroek SSL_use_PrivateKey(ssl2, key);
315*e985b929SDavid van Moolenbroek
316*e985b929SDavid van Moolenbroek if (! start_open)
317*e985b929SDavid van Moolenbroek flags |= BEV_OPT_CLOSE_ON_FREE;
318*e985b929SDavid van Moolenbroek
319*e985b929SDavid van Moolenbroek if (!filter) {
320*e985b929SDavid van Moolenbroek tt_assert(strstr((char*)data->setup_data, "socketpair"));
321*e985b929SDavid van Moolenbroek fd_pair = data->pair;
322*e985b929SDavid van Moolenbroek } else {
323*e985b929SDavid van Moolenbroek bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
324*e985b929SDavid van Moolenbroek BEV_OPT_CLOSE_ON_FREE);
325*e985b929SDavid van Moolenbroek bev_ll[1] = bufferevent_socket_new(data->base, data->pair[1],
326*e985b929SDavid van Moolenbroek BEV_OPT_CLOSE_ON_FREE);
327*e985b929SDavid van Moolenbroek }
328*e985b929SDavid van Moolenbroek
329*e985b929SDavid van Moolenbroek open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
330*e985b929SDavid van Moolenbroek fd_pair, bev_ll);
331*e985b929SDavid van Moolenbroek
332*e985b929SDavid van Moolenbroek if (!filter) {
333*e985b929SDavid van Moolenbroek tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
334*e985b929SDavid van Moolenbroek } else {
335*e985b929SDavid van Moolenbroek tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
336*e985b929SDavid van Moolenbroek }
337*e985b929SDavid van Moolenbroek
338*e985b929SDavid van Moolenbroek if (start_open) {
339*e985b929SDavid van Moolenbroek pending_connect_events = 2;
340*e985b929SDavid van Moolenbroek stop_when_connected = 1;
341*e985b929SDavid van Moolenbroek exit_base = data->base;
342*e985b929SDavid van Moolenbroek event_base_dispatch(data->base);
343*e985b929SDavid van Moolenbroek /* Okay, now the renegotiation is done. Make new
344*e985b929SDavid van Moolenbroek * bufferevents to test opening in BUFFEREVENT_SSL_OPEN */
345*e985b929SDavid van Moolenbroek flags |= BEV_OPT_CLOSE_ON_FREE;
346*e985b929SDavid van Moolenbroek bufferevent_free(bev1);
347*e985b929SDavid van Moolenbroek bufferevent_free(bev2);
348*e985b929SDavid van Moolenbroek bev1 = bev2 = NULL;
349*e985b929SDavid van Moolenbroek open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
350*e985b929SDavid van Moolenbroek fd_pair, bev_ll);
351*e985b929SDavid van Moolenbroek }
352*e985b929SDavid van Moolenbroek
353*e985b929SDavid van Moolenbroek bufferevent_enable(bev1, EV_READ|EV_WRITE);
354*e985b929SDavid van Moolenbroek bufferevent_enable(bev2, EV_READ|EV_WRITE);
355*e985b929SDavid van Moolenbroek
356*e985b929SDavid van Moolenbroek evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
357*e985b929SDavid van Moolenbroek
358*e985b929SDavid van Moolenbroek event_base_dispatch(data->base);
359*e985b929SDavid van Moolenbroek
360*e985b929SDavid van Moolenbroek tt_assert(test_is_done == 1);
361*e985b929SDavid van Moolenbroek tt_assert(n_connected == 2);
362*e985b929SDavid van Moolenbroek
363*e985b929SDavid van Moolenbroek /* We don't handle shutdown properly yet.
364*e985b929SDavid van Moolenbroek tt_int_op(got_close, ==, 1);
365*e985b929SDavid van Moolenbroek tt_int_op(got_error, ==, 0);
366*e985b929SDavid van Moolenbroek */
367*e985b929SDavid van Moolenbroek end:
368*e985b929SDavid van Moolenbroek return;
369*e985b929SDavid van Moolenbroek }
370*e985b929SDavid van Moolenbroek
371*e985b929SDavid van Moolenbroek static void
acceptcb(struct evconnlistener * listener,evutil_socket_t fd,struct sockaddr * addr,int socklen,void * arg)372*e985b929SDavid van Moolenbroek acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
373*e985b929SDavid van Moolenbroek struct sockaddr *addr, int socklen, void *arg)
374*e985b929SDavid van Moolenbroek {
375*e985b929SDavid van Moolenbroek struct basic_test_data *data = arg;
376*e985b929SDavid van Moolenbroek struct bufferevent *bev;
377*e985b929SDavid van Moolenbroek SSL *ssl = SSL_new(get_ssl_ctx());
378*e985b929SDavid van Moolenbroek
379*e985b929SDavid van Moolenbroek SSL_use_certificate(ssl, getcert());
380*e985b929SDavid van Moolenbroek SSL_use_PrivateKey(ssl, getkey());
381*e985b929SDavid van Moolenbroek
382*e985b929SDavid van Moolenbroek bev = bufferevent_openssl_socket_new(
383*e985b929SDavid van Moolenbroek data->base,
384*e985b929SDavid van Moolenbroek fd,
385*e985b929SDavid van Moolenbroek ssl,
386*e985b929SDavid van Moolenbroek BUFFEREVENT_SSL_ACCEPTING,
387*e985b929SDavid van Moolenbroek BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
388*e985b929SDavid van Moolenbroek
389*e985b929SDavid van Moolenbroek bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
390*e985b929SDavid van Moolenbroek __UNCONST("server"));
391*e985b929SDavid van Moolenbroek
392*e985b929SDavid van Moolenbroek bufferevent_enable(bev, EV_READ|EV_WRITE);
393*e985b929SDavid van Moolenbroek
394*e985b929SDavid van Moolenbroek /* Only accept once, then disable ourself. */
395*e985b929SDavid van Moolenbroek evconnlistener_disable(listener);
396*e985b929SDavid van Moolenbroek }
397*e985b929SDavid van Moolenbroek
398*e985b929SDavid van Moolenbroek static void
regress_bufferevent_openssl_connect(void * arg)399*e985b929SDavid van Moolenbroek regress_bufferevent_openssl_connect(void *arg)
400*e985b929SDavid van Moolenbroek {
401*e985b929SDavid van Moolenbroek struct basic_test_data *data = arg;
402*e985b929SDavid van Moolenbroek
403*e985b929SDavid van Moolenbroek struct event_base *base = data->base;
404*e985b929SDavid van Moolenbroek
405*e985b929SDavid van Moolenbroek struct evconnlistener *listener;
406*e985b929SDavid van Moolenbroek struct bufferevent *bev;
407*e985b929SDavid van Moolenbroek struct sockaddr_in sin;
408*e985b929SDavid van Moolenbroek struct sockaddr_storage ss;
409*e985b929SDavid van Moolenbroek ev_socklen_t slen;
410*e985b929SDavid van Moolenbroek
411*e985b929SDavid van Moolenbroek init_ssl();
412*e985b929SDavid van Moolenbroek
413*e985b929SDavid van Moolenbroek memset(&sin, 0, sizeof(sin));
414*e985b929SDavid van Moolenbroek sin.sin_family = AF_INET;
415*e985b929SDavid van Moolenbroek sin.sin_addr.s_addr = htonl(0x7f000001);
416*e985b929SDavid van Moolenbroek
417*e985b929SDavid van Moolenbroek memset(&ss, 0, sizeof(ss));
418*e985b929SDavid van Moolenbroek slen = sizeof(ss);
419*e985b929SDavid van Moolenbroek
420*e985b929SDavid van Moolenbroek listener = evconnlistener_new_bind(base, acceptcb, data,
421*e985b929SDavid van Moolenbroek LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
422*e985b929SDavid van Moolenbroek -1, (struct sockaddr *)&sin, sizeof(sin));
423*e985b929SDavid van Moolenbroek
424*e985b929SDavid van Moolenbroek tt_assert(listener);
425*e985b929SDavid van Moolenbroek tt_assert(evconnlistener_get_fd(listener) >= 0);
426*e985b929SDavid van Moolenbroek
427*e985b929SDavid van Moolenbroek bev = bufferevent_openssl_socket_new(
428*e985b929SDavid van Moolenbroek data->base, -1, SSL_new(get_ssl_ctx()),
429*e985b929SDavid van Moolenbroek BUFFEREVENT_SSL_CONNECTING,
430*e985b929SDavid van Moolenbroek BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
431*e985b929SDavid van Moolenbroek tt_assert(bev);
432*e985b929SDavid van Moolenbroek
433*e985b929SDavid van Moolenbroek bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
434*e985b929SDavid van Moolenbroek __UNCONST("client"));
435*e985b929SDavid van Moolenbroek
436*e985b929SDavid van Moolenbroek tt_assert(getsockname(evconnlistener_get_fd(listener),
437*e985b929SDavid van Moolenbroek (struct sockaddr*)&ss, &slen) == 0);
438*e985b929SDavid van Moolenbroek tt_assert(slen == sizeof(struct sockaddr_in));
439*e985b929SDavid van Moolenbroek tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
440*e985b929SDavid van Moolenbroek tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
441*e985b929SDavid van Moolenbroek
442*e985b929SDavid van Moolenbroek tt_assert(0 ==
443*e985b929SDavid van Moolenbroek bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
444*e985b929SDavid van Moolenbroek evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
445*e985b929SDavid van Moolenbroek bufferevent_enable(bev, EV_READ|EV_WRITE);
446*e985b929SDavid van Moolenbroek
447*e985b929SDavid van Moolenbroek event_base_dispatch(base);
448*e985b929SDavid van Moolenbroek end:
449*e985b929SDavid van Moolenbroek ;
450*e985b929SDavid van Moolenbroek }
451*e985b929SDavid van Moolenbroek
452*e985b929SDavid van Moolenbroek struct testcase_t ssl_testcases[] = {
453*e985b929SDavid van Moolenbroek
454*e985b929SDavid van Moolenbroek { "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED,
455*e985b929SDavid van Moolenbroek &basic_setup, __UNCONST("socketpair") },
456*e985b929SDavid van Moolenbroek { "bufferevent_filter", regress_bufferevent_openssl,
457*e985b929SDavid van Moolenbroek TT_ISOLATED,
458*e985b929SDavid van Moolenbroek &basic_setup, __UNCONST("filter") },
459*e985b929SDavid van Moolenbroek { "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
460*e985b929SDavid van Moolenbroek TT_ISOLATED,
461*e985b929SDavid van Moolenbroek &basic_setup, __UNCONST("socketpair renegotiate") },
462*e985b929SDavid van Moolenbroek { "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
463*e985b929SDavid van Moolenbroek TT_ISOLATED,
464*e985b929SDavid van Moolenbroek &basic_setup, __UNCONST("filter renegotiate") },
465*e985b929SDavid van Moolenbroek { "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
466*e985b929SDavid van Moolenbroek TT_ISOLATED, &basic_setup, __UNCONST("socketpair open") },
467*e985b929SDavid van Moolenbroek { "bufferevent_filter_startopen", regress_bufferevent_openssl,
468*e985b929SDavid van Moolenbroek TT_ISOLATED, &basic_setup, __UNCONST("filter open") },
469*e985b929SDavid van Moolenbroek
470*e985b929SDavid van Moolenbroek { "bufferevent_connect", regress_bufferevent_openssl_connect,
471*e985b929SDavid van Moolenbroek TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
472*e985b929SDavid van Moolenbroek
473*e985b929SDavid van Moolenbroek END_OF_TESTCASES,
474*e985b929SDavid van Moolenbroek };
475