From 2dffa364f081d1380dec0a9d14b61a504bc27b97 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sat, 19 Jun 2021 16:29:51 +0000 Subject: Add more complex DTLS tests for delay/reordering. These tests exercise the various queues and delayed processing that exists in the DTLS code. --- src/regress/lib/libssl/dtls/dtlstest.c | 177 +++++++++++++++++++++++++++++---- 1 file changed, 160 insertions(+), 17 deletions(-) diff --git a/src/regress/lib/libssl/dtls/dtlstest.c b/src/regress/lib/libssl/dtls/dtlstest.c index becc500c90..91b2599dda 100644 --- a/src/regress/lib/libssl/dtls/dtlstest.c +++ b/src/regress/lib/libssl/dtls/dtlstest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dtlstest.c,v 1.11 2021/06/19 15:52:41 jsing Exp $ */ +/* $OpenBSD: dtlstest.c,v 1.12 2021/06/19 16:29:51 jsing Exp $ */ /* * Copyright (c) 2020, 2021 Joel Sing * @@ -294,13 +294,11 @@ BIO_packet_monkey_delay(BIO *bio, int num, int count) return BIO_ctrl(bio, BIO_C_DELAY_PACKET, num, NULL); } -#if 0 static int BIO_packet_monkey_delay_flush(BIO *bio) { return BIO_ctrl(bio, BIO_C_DELAY_FLUSH, 0, NULL); } -#endif static int BIO_packet_monkey_drop(BIO *bio, int num) @@ -513,13 +511,60 @@ do_connect(SSL *ssl, const char *name, int *done, short *events) { int ssl_ret; - if ((ssl_ret = SSL_connect(ssl)) == 1) { - fprintf(stderr, "INFO: %s connect done\n", name); - *done = 1; - return 1; + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + return 1; +} + +static int +do_connect_read(SSL *ssl, const char *name, int *done, short *events) +{ + uint8_t buf[2048]; + int ssl_ret; + int i; + + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + for (i = 0; i < 3; i++) { + fprintf(stderr, "INFO: %s reading after connect\n", name); + if ((ssl_ret = SSL_read(ssl, buf, sizeof(buf))) != 3) { + fprintf(stderr, "ERROR: %s read failed\n", name); + return 0; + } } - return ssl_error(ssl, name, "connect", ssl_ret, events); + return 1; +} + +static int +do_connect_shutdown(SSL *ssl, const char *name, int *done, short *events) +{ + uint8_t buf[2048]; + int ssl_ret; + + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + ssl_ret = SSL_read(ssl, buf, sizeof(buf)); + if (SSL_get_error(ssl, ssl_ret) != SSL_ERROR_ZERO_RETURN) { + fprintf(stderr, "FAIL: %s did not receive close-notify\n", name); + return 0; + } + + fprintf(stderr, "INFO: %s received close-notify\n", name); + + return 1; } static int @@ -527,13 +572,66 @@ do_accept(SSL *ssl, const char *name, int *done, short *events) { int ssl_ret; - if ((ssl_ret = SSL_accept(ssl)) == 1) { - fprintf(stderr, "INFO: %s accept done\n", name); - *done = 1; - return 1; + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + *done = 1; + + return 1; +} + +static int +do_accept_write(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + BIO *bio; + int i; + + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + + for (i = 0; i < 3; i++) { + fprintf(stderr, "INFO: %s writing after accept\n", name); + if ((ssl_ret = SSL_write(ssl, "abc", 3)) != 3) { + fprintf(stderr, "ERROR: %s write failed\n", name); + return 0; + } } - return ssl_error(ssl, name, "accept", ssl_ret, events); + if ((bio = SSL_get_wbio(ssl)) == NULL) + errx(1, "SSL has NULL bio"); + + /* Flush any delayed packets. */ + BIO_packet_monkey_delay_flush(bio); + + *done = 1; + return 1; +} + +static int +do_accept_shutdown(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + BIO *bio; + + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + + SSL_shutdown(ssl); + + if ((bio = SSL_get_wbio(ssl)) == NULL) + errx(1, "SSL has NULL bio"); + + /* Flush any delayed packets. */ + BIO_packet_monkey_delay_flush(bio); + + *done = 1; + return 1; } static int @@ -582,11 +680,11 @@ do_shutdown(SSL *ssl, const char *name, int *done, short *events) return ssl_error(ssl, name, "shutdown", ssl_ret, events); } -typedef int (*ssl_func)(SSL *ssl, const char *name, int *done, short *events); +typedef int (ssl_func)(SSL *ssl, const char *name, int *done, short *events); static int -do_client_server_loop(SSL *client, ssl_func client_func, SSL *server, - ssl_func server_func, struct pollfd pfd[2]) +do_client_server_loop(SSL *client, ssl_func *client_func, SSL *server, + ssl_func *server_func, struct pollfd pfd[2]) { int client_done = 0, server_done = 0; int i = 0; @@ -642,6 +740,8 @@ struct dtls_test { long ssl_options; int client_bbio_off; int server_bbio_off; + int write_after_accept; + int shutdown_after_accept; struct dtls_delay client_delays[MAX_PACKET_DELAYS]; struct dtls_delay server_delays[MAX_PACKET_DELAYS]; uint8_t client_drops[MAX_PACKET_DROPS]; @@ -748,6 +848,33 @@ static const struct dtls_test dtls_tests[] = { .client_bbio_off = 1, .client_delays = { { 3, 2 } }, }, + { + /* + * Send CCS after server Finished - note app data will be + * dropped if we send the CCS after app data. + */ + .desc = "DTLS with delayed server CCS", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 5, 2 } }, + .write_after_accept = 1, + }, + { + /* Send Finished after app data - this is currently buffered. */ + .desc = "DTLS with delayed server Finished", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 6, 3 } }, + .write_after_accept = 1, + }, + { + /* Send CCS after server finished and close-notify. */ + .desc = "DTLS with delayed server CCS (close-notify)", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 5, 3 } }, + .shutdown_after_accept = 1, + }, }; #define N_DTLS_TESTS (sizeof(dtls_tests) / sizeof(*dtls_tests)) @@ -791,6 +918,7 @@ static int dtlstest(const struct dtls_test *dt) { SSL *client = NULL, *server = NULL; + ssl_func *connect_func, *accept_func; struct sockaddr_in server_sin; struct pollfd pfd[2]; int client_sock = -1; @@ -820,11 +948,25 @@ dtlstest(const struct dtls_test *dt) pfd[1].fd = server_sock; pfd[1].events = POLLIN; - if (!do_client_server_loop(client, do_connect, server, do_accept, pfd)) { + accept_func = do_accept; + connect_func = do_connect; + + if (dt->write_after_accept) { + accept_func = do_accept_write; + connect_func = do_connect_read; + } else if (dt->shutdown_after_accept) { + accept_func = do_accept_shutdown; + connect_func = do_connect_shutdown; + } + + if (!do_client_server_loop(client, connect_func, server, accept_func, pfd)) { fprintf(stderr, "FAIL: client and server handshake failed\n"); goto failure; } + if (dt->write_after_accept || dt->shutdown_after_accept) + goto done; + pfd[0].events = POLLIN; pfd[1].events = POLLOUT; @@ -849,6 +991,7 @@ dtlstest(const struct dtls_test *dt) goto failure; } + done: fprintf(stderr, "INFO: Done!\n"); failed = 0; -- cgit v1.2.3-55-g6feb