From 9c83d9d99ed1b43c2d7ea5c78d9675865a78f724 Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Thu, 28 Apr 2022 19:01:28 +0200 Subject: [PATCH] DTLS: fail the connection if DTLSv1_handle_timeout returns an error which signals a permanent connection failure to the application BUG=webrtc:13999 Change-Id: I7ba25db4aa9035583558a613db97561c48796c76 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/260100 Reviewed-by: Jonas Oreland Reviewed-by: Harald Alvestrand Commit-Queue: Philipp Hancke Cr-Commit-Position: refs/heads/main@{#36700} --- rtc_base/openssl_stream_adapter.cc | 2 + rtc_base/ssl_stream_adapter_unittest.cc | 49 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc index 94b97d76fb..ee63c70a69 100644 --- a/rtc_base/openssl_stream_adapter.cc +++ b/rtc_base/openssl_stream_adapter.cc @@ -841,6 +841,8 @@ void OpenSSLStreamAdapter::SetTimeout(int delay_ms) { RTC_LOG(LS_INFO) << "DTLS retransmission"; } else if (res < 0) { RTC_LOG(LS_INFO) << "DTLSv1_handle_timeout() return -1"; + Error("DTLSv1_handle_timeout", res, -1, true); + return webrtc::TimeDelta::PlusInfinity(); } ContinueSSL(); } else { diff --git a/rtc_base/ssl_stream_adapter_unittest.cc b/rtc_base/ssl_stream_adapter_unittest.cc index f26166f086..2305bcea71 100644 --- a/rtc_base/ssl_stream_adapter_unittest.cc +++ b/rtc_base/ssl_stream_adapter_unittest.cc @@ -510,6 +510,49 @@ class SSLStreamAdapterTestBase : public ::testing::Test, } } + // This tests that we give up after 12 DTLS resends. + void TestHandshakeTimeout() { + rtc::ScopedFakeClock clock; + int64_t time_start = clock.TimeNanos(); + webrtc::TimeDelta time_increment = webrtc::TimeDelta::Millis(1000); + server_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); + client_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); + + if (!dtls_) { + // Make sure we simulate a reliable network for TLS. + // This is just a check to make sure that people don't write wrong + // tests. + RTC_CHECK_EQ(1460, mtu_); + RTC_CHECK(!loss_); + RTC_CHECK(!lose_first_packet_); + } + + if (!identities_set_) + SetPeerIdentitiesByDigest(true, true); + + // Start the handshake + int rv; + + server_ssl_->SetServerRole(); + rv = server_ssl_->StartSSL(); + ASSERT_EQ(0, rv); + + rv = client_ssl_->StartSSL(); + ASSERT_EQ(0, rv); + + // Now wait for the handshake to timeout (or fail after an hour of simulated + // time). + while (client_ssl_->GetState() == rtc::SS_OPENING && + (rtc::TimeDiff(clock.TimeNanos(), time_start) < + 3600 * rtc::kNumNanosecsPerSec)) { + EXPECT_TRUE_WAIT(!((client_ssl_->GetState() == rtc::SS_OPEN) && + (server_ssl_->GetState() == rtc::SS_OPEN)), + 1000); + clock.AdvanceTime(time_increment); + } + RTC_CHECK_EQ(client_ssl_->GetState(), rtc::SS_CLOSED); + } + // This tests that the handshake can complete before the identity is verified, // and the identity will be verified after the fact. It also verifies that // packets can't be read or written before the identity has been verified. @@ -1217,6 +1260,12 @@ TEST_P(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) { TestHandshake(); } +// Test a handshake with total loss and timing out. +TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnectTimeout) { + SetLoss(100); + TestHandshakeTimeout(); +} + // Test transfer -- trivial TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransfer) { TestHandshake();