diff options
Diffstat (limited to 'test/sslapitest.c')
-rw-r--r-- | test/sslapitest.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/test/sslapitest.c b/test/sslapitest.c index 61619a3..d998e10 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -4972,6 +4972,128 @@ static int test_ticket_callbacks(int tst) return testresult; } +/* + * Test bi-directional shutdown. + * Test 0: TLSv1.2 + * Test 1: TLSv1.2, server continues to read/write after client shutdown + * Test 2: TLSv1.3, no pending NewSessionTicket messages + * Test 3: TLSv1.3, pending NewSessionTicket messages + * Test 4: TLSv1.3, server continues to read/write after client shutdown, client + * reads it + * Test 5: TLSv1.3, server continues to read/write after client shutdown, client + * doesn't read it + */ +static int test_shutdown(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + char msg[] = "A test message"; + char buf[80]; + size_t written, readbytes; + +#ifdef OPENSSL_NO_TLS1_2 + if (tst == 0) + return 1; +#endif +#ifdef OPENSSL_NO_TLS1_3 + if (tst != 0) + return 1; +#endif + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, + (tst <= 1) ? TLS1_2_VERSION + : TLS1_3_VERSION, + &sctx, &cctx, cert, privkey)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (tst == 3) { + if (!TEST_true(create_bare_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + } else if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) { + goto end; + } + + if (!TEST_int_eq(SSL_shutdown(clientssl), 0)) + goto end; + + if (tst >= 4) { + /* + * Reading on the server after the client has sent close_notify should + * fail and provide SSL_ERROR_ZERO_RETURN + */ + if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)) + || !TEST_int_eq(SSL_get_error(serverssl, 0), + SSL_ERROR_ZERO_RETURN) + || !TEST_int_eq(SSL_get_shutdown(serverssl), + SSL_RECEIVED_SHUTDOWN) + /* + * Even though we're shutdown on receive we should still be + * able to write. + */ + || !TEST_true(SSL_write(serverssl, msg, sizeof(msg))) + || !TEST_int_eq(SSL_shutdown(serverssl), 1)) + goto end; + if (tst == 4) { + /* Should still be able to read data from server */ + if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), + &readbytes)) + || !TEST_size_t_eq(readbytes, sizeof(msg)) + || !TEST_int_eq(memcmp(msg, buf, readbytes), 0)) + goto end; + } + } + + /* Writing on the client after sending close_notify shouldn't be possible */ + if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written)) + /* + * Writing on the server after sending close_notify shouldn't be + * possible. + */ + || !TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written))) + goto end; + + if (tst < 4) { + /* + * For these tests the client has sent close_notify but it has not yet + * been received by the server. The server has not sent close_notify + * yet. + */ + if (!TEST_int_eq(SSL_shutdown(serverssl), 0) + || !TEST_int_eq(SSL_shutdown(clientssl), 1) + || !TEST_int_eq(SSL_shutdown(serverssl), 1)) + goto end; + } else { + /* + * In this test the client has sent close_notify and it has been + * received by the server which has responded with a close_notify. The + * client needs to read the close_notify sent by the server. When + * tst == 5, there is application data to be read first but this is + * discarded with a -1 return value. + */ + if (tst == 5 && !TEST_int_eq(SSL_shutdown(clientssl), -1)) + goto end; + if (!TEST_int_eq(SSL_shutdown(clientssl), 1)) + goto end; + } + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) @@ -5069,6 +5191,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_ssl_pending, 2); ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data)); ADD_ALL_TESTS(test_ticket_callbacks, 12); + ADD_ALL_TESTS(test_shutdown, 6); return 1; } |