1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Merge pull request #11708 from padelsbach/shutdown-loop

Fail wolfSSL_shutdown when the peer's record cannot be processed
This commit is contained in:
philljj
2026-10-23 11:24:09 -05:00
committed by GitHub
3 changed files with 105 additions and 4 deletions

View File

@@ -1023,11 +1023,10 @@ static int wolfssl_shutdown_recv_close_notify(WOLFSSL* ssl)
ssl->error = WOLFSSL_ERROR_NONE;
ret = WOLFSSL_SUCCESS;
}
else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
ret = WOLFSSL_FATAL_ERROR;
}
else if (ret == WC_NO_ERR_TRACE(WANT_READ)) {
else if ((ret < 0) && (ret != WC_NO_ERR_TRACE(APP_DATA_READY))) {
/* Retry would process the same bad record again, error out. */
ssl->error = ret;
WOLFSSL_ERROR(ret);
ret = WOLFSSL_FATAL_ERROR;
}
else if (ssl->error == WOLFSSL_ERROR_NONE) {

View File

@@ -1498,6 +1498,106 @@ int test_wolfSSL_shutdown_no_notify(void)
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_TLS) && \
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13))
/* Shut a connection down when the peer's next record cannot be processed.
*
* @param [in] method_c Client method.
* @param [in] method_s Server method.
* @param [in] peerAlert 0 to corrupt a record from the server, 1 to have the
* server send a fatal alert instead.
* @return TEST_SUCCESS on success.
*/
static int test_ssl_rw_shutdown_bad_record(method_provider method_c,
method_provider method_s, int peerAlert)
{
EXPECT_DECLS;
WOLFSSL_CTX* ctx_c = NULL;
WOLFSSL_CTX* ctx_s = NULL;
WOLFSSL* ssl_c = NULL;
WOLFSSL* ssl_s = NULL;
struct test_memio_ctx test_ctx;
char buf[16];
int sentLen = 0;
int retryRet = WOLFSSL_FATAL_ERROR;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
method_c, method_s), 0);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Read any session tickets so the next record is the bad one. */
ExpectIntEQ(wolfSSL_read(ssl_c, buf, (int)sizeof(buf)),
WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);
if (peerAlert) {
/* An unknown record type gets a fatal alert with any cipher. */
ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), 5);
ExpectIntEQ(test_ctx.s_buff[0], application_data);
if (EXPECT_SUCCESS()) {
test_ctx.s_buff[0] = no_type;
}
ExpectIntEQ(wolfSSL_read(ssl_s, buf, (int)sizeof(buf)),
WOLFSSL_FATAL_ERROR);
ExpectIntGT(test_ctx.c_len, 0);
}
else {
ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), 5);
if (EXPECT_SUCCESS()) {
test_ctx.c_buff[test_ctx.c_len - 1] ^= 0xff;
}
}
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
/* The record cannot be processed, so the shutdown fails. */
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_FATAL_ERROR);
ExpectIntLT(ssl_c->error, 0);
ExpectIntNE(ssl_c->error, WC_NO_ERR_TRACE(WANT_READ));
sentLen = test_ctx.s_len;
#ifdef WOLFSSL_SHUTDOWNONCE
if ((ssl_c != NULL) &&
(ssl_c->options.isClosed || ssl_c->options.connReset)) {
retryRet = WC_NO_ERR_TRACE(SSL_SHUTDOWN_ALREADY_DONE_E);
}
#endif
/* Trying again still fails and sends nothing more. */
ExpectIntEQ(wolfSSL_shutdown(ssl_c), retryRet);
ExpectIntLT(ssl_c->error, 0);
ExpectIntEQ(test_ctx.s_len, sentLen);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
return EXPECT_RESULT();
}
#endif
/* Test that a shutdown fails when the peer's next record is bad.
*
* @return TEST_SUCCESS on success.
*/
int test_wolfSSL_shutdown_bad_record(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_TLS)
#ifndef WOLFSSL_NO_TLS12
ExpectIntEQ(test_ssl_rw_shutdown_bad_record(wolfTLSv1_2_client_method,
wolfTLSv1_2_server_method, 0), TEST_SUCCESS);
ExpectIntEQ(test_ssl_rw_shutdown_bad_record(wolfTLSv1_2_client_method,
wolfTLSv1_2_server_method, 1), TEST_SUCCESS);
#endif
#ifdef WOLFSSL_TLS13
ExpectIntEQ(test_ssl_rw_shutdown_bad_record(wolfTLSv1_3_client_method,
wolfTLSv1_3_server_method, 0), TEST_SUCCESS);
ExpectIntEQ(test_ssl_rw_shutdown_bad_record(wolfTLSv1_3_client_method,
wolfTLSv1_3_server_method, 1), TEST_SUCCESS);
#endif
#endif
return EXPECT_RESULT();
}
/* Test the paths wolfSSL_SendUserCanceled() takes once the alert is sent.
*
* The NULL case is covered by test_wolfSSL_rw_bad_args(). This drives the

View File

@@ -39,6 +39,7 @@ int test_wolfSSL_rehandshake_app_data_pending(void);
int test_wolfSSL_rehandshake_app_data_partial_record(void);
int test_wolfSSL_accept_early_data_pending(void);
int test_wolfSSL_shutdown_no_notify(void);
int test_wolfSSL_shutdown_bad_record(void);
int test_wolfSSL_shutdown_repeat_after_done(void);
int test_wolfSSL_shutdown_flush_no_notify(void);
int test_wolfSSL_shutdown_quic_alert_refused(void);
@@ -69,6 +70,7 @@ int test_wolfSSL_write_dup_max_fragment(void);
test_wolfSSL_rehandshake_app_data_partial_record), \
TEST_DECL_GROUP("ssl_rw", test_wolfSSL_accept_early_data_pending), \
TEST_DECL_GROUP("ssl_rw", test_wolfSSL_shutdown_no_notify), \
TEST_DECL_GROUP("ssl_rw", test_wolfSSL_shutdown_bad_record), \
TEST_DECL_GROUP("ssl_rw", \
test_wolfSSL_shutdown_repeat_after_done), \
TEST_DECL_GROUP("ssl_rw", test_wolfSSL_shutdown_flush_no_notify), \