From 2e9b9681e60ff52d69a3a68b4c7be0bcbab9191b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Jan 2026 11:33:35 +0100 Subject: [PATCH] ssl_server2.c: DTLS: Attempt to read the response to the close notification Signed-off-by: Ronald Cron --- programs/ssl/ssl_server2.c | 50 ++++++++++++++++++- tests/compat.sh | 1 + tests/scripts/components-configuration-tls.sh | 1 + 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 0ae2f79303..f262542377 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -4133,7 +4133,55 @@ close_notify: } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; - mbedtls_printf(" done\n"); + /* + * In the DTLS case, attempt to read a possible response to the close + * notification. This avoids reconnecting to the same client when we + * reset and later receive its close-notification response during + * step 3 (waiting for a client to connect). + * + * Stop waiting for the response if the connection has already ended. + * + * The waiting loop below relies on mbedtls_ssl_read() returning regularly + * in order to keep the total waiting time approximately bounded to 1s. If + * no read timeout is configured (see the read_timeout option), or if the + * configured timeout is close to or larger than 1s, the total waiting time + * may exceed 1s by a significant margin. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_HAVE_TIME) + if (opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + mbedtls_ms_time_t start = mbedtls_ms_time(); + for (;;) { + ret = mbedtls_ssl_read(&ssl, buf, opt.buffer_size); + /* + * mbedtls_ssl_read() returned some data or timed out, loop if we + * have not spent already too much time, quite arbitrarily 1s. + */ + if ((ret > 0) || (ret == MBEDTLS_ERR_SSL_TIMEOUT)) { + if ((mbedtls_ms_time() - start) < 1000) { + continue; + } + } + + if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + mbedtls_printf(" done, received client close notification.\n"); + } else { + /* ret = 0, silent transport EOF or ret < 0 except + * MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY. Note that we do not + * handle specifically the non-fatal error codes like + * MBEDTLS_ERR_SSL_WANT_READ as we do not really expect them + * here. + */ + mbedtls_printf(" done\n"); + } + break; + } + ret = 0; + } else +#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_HAVE_TIME */ + { + mbedtls_printf(" done\n"); + } + fflush(stdout); #if defined(MBEDTLS_SSL_CACHE_C) if (opt.cache_remove > 0) { diff --git a/tests/compat.sh b/tests/compat.sh index 2b6f454127..3f44c984fb 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -557,6 +557,7 @@ setup_arguments() # with OpenSSL 1.0.1h, -www, -WWW and -HTTP break DTLS handshakes if is_dtls "$MODE"; then O_SERVER_ARGS="$O_SERVER_ARGS" + M_SERVER_ARGS="$M_SERVER_ARGS read_timeout=1000" else O_SERVER_ARGS="$O_SERVER_ARGS -www" fi diff --git a/tests/scripts/components-configuration-tls.sh b/tests/scripts/components-configuration-tls.sh index 5a77c4defc..d017eef182 100644 --- a/tests/scripts/components-configuration-tls.sh +++ b/tests/scripts/components-configuration-tls.sh @@ -165,6 +165,7 @@ component_test_tls1_2_ccm_psk_dtls () { msg "build: configs/config-ccm-psk-dtls1_2.h" MBEDTLS_CONFIG="configs/config-ccm-psk-dtls1_2.h" CRYPTO_CONFIG="configs/crypto-config-ccm-psk-tls1_2.h" + tf-psa-crypto/scripts/config.py -f "$CRYPTO_CONFIG" set MBEDTLS_HAVE_TIME CC=$ASAN_CC cmake -DMBEDTLS_CONFIG_FILE="$MBEDTLS_CONFIG" -DTF_PSA_CRYPTO_CONFIG_FILE="$CRYPTO_CONFIG" -D CMAKE_BUILD_TYPE:String=Asan . make