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