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