root/opal/mca/event/libevent2022/libevent/test/regress_ssl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getkey
  2. getcert
  3. get_ssl_ctx
  4. init_ssl
  5. respond_to_number
  6. done_writing_cb
  7. eventcb
  8. open_ssl_bufevs
  9. regress_bufferevent_openssl
  10. acceptcb
  11. regress_bufferevent_openssl_connect

   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 };

/* [<][>][^][v][top][bottom][index][help] */