Add big red button to disable QUIC TLS resumption.
Protected by FLAGS_quic_disable_server_tls_resumption.
PiperOrigin-RevId: 341128029
Change-Id: Id6d81e63d8c5f58595565144c6af99525a5f25a6
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 91af8c6..91e3dd1 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -5086,6 +5086,108 @@
server_thread_->Resume();
}
+TEST_P(EndToEndTest, TlsResumptionEnabledOnTheFly) {
+ SetQuicFlag(FLAGS_quic_disable_server_tls_resumption, true);
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesTls()) {
+ // This test is TLS specific.
+ return;
+ }
+
+ // Send the first request. Client should not have a resumption ticket.
+ SendSynchronousFooRequestAndCheckResponse();
+ QuicSpdyClientSession* client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(),
+ ssl_early_data_no_session_offered);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ client_->Disconnect();
+
+ SetQuicFlag(FLAGS_quic_disable_server_tls_resumption, false);
+
+ // Send the second request. Client should still have no resumption ticket, but
+ // it will receive one which can be used by the next request.
+ client_->Connect();
+ SendSynchronousFooRequestAndCheckResponse();
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(),
+ ssl_early_data_no_session_offered);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ client_->Disconnect();
+
+ // Send the third request in 0RTT.
+ client_->Connect();
+ SendSynchronousFooRequestAndCheckResponse();
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_TRUE(client_session->EarlyDataAccepted());
+ client_->Disconnect();
+}
+
+TEST_P(EndToEndTest, TlsResumptionDisabledOnTheFly) {
+ SetQuicFlag(FLAGS_quic_disable_server_tls_resumption, false);
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesTls()) {
+ // This test is TLS specific.
+ return;
+ }
+
+ // Send the first request and then disconnect.
+ SendSynchronousFooRequestAndCheckResponse();
+ QuicSpdyClientSession* client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ client_->Disconnect();
+
+ // Send the second request in 0RTT.
+ client_->Connect();
+ SendSynchronousFooRequestAndCheckResponse();
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_TRUE(client_session->EarlyDataAccepted());
+ client_->Disconnect();
+
+ SetQuicFlag(FLAGS_quic_disable_server_tls_resumption, true);
+
+ // Send the third request. The client should try resumption but server should
+ // decline it.
+ client_->Connect();
+ SendSynchronousFooRequestAndCheckResponse();
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ EXPECT_EQ(client_session->GetCryptoStream()->EarlyDataReason(),
+ ssl_early_data_session_not_resumed);
+ client_->Disconnect();
+
+ // Keep sending until the client runs out of resumption tickets.
+ for (int i = 0; i < 10; ++i) {
+ client_->Connect();
+ SendSynchronousFooRequestAndCheckResponse();
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ const auto early_data_reason =
+ client_session->GetCryptoStream()->EarlyDataReason();
+ client_->Disconnect();
+
+ if (early_data_reason != ssl_early_data_session_not_resumed) {
+ EXPECT_EQ(early_data_reason, ssl_early_data_no_session_offered);
+ return;
+ }
+ }
+
+ ADD_FAILURE() << "Client should not have 10 resumption tickets.";
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_protocol_flags_list.h b/quic/core/quic_protocol_flags_list.h
index c39d1e0..9484a23 100644
--- a/quic/core/quic_protocol_flags_list.h
+++ b/quic/core/quic_protocol_flags_list.h
@@ -237,4 +237,10 @@
false,
"If true, QUIC client with TLS will not try 0-RTT.")
+QUIC_PROTOCOL_FLAG(bool,
+ quic_disable_server_tls_resumption,
+ false,
+ "If true, QUIC server will disable TLS resumption by not "
+ "issuing or processing session tickets.")
+
#endif
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index a935741..aa49597 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -98,6 +98,10 @@
// Configure the SSL to be a server.
SSL_set_accept_state(ssl());
+
+ if (GetQuicFlag(FLAGS_quic_disable_server_tls_resumption)) {
+ SSL_set_options(ssl(), SSL_OP_NO_TICKET);
+ }
}
TlsServerHandshaker::~TlsServerHandshaker() {
diff --git a/quic/core/tls_server_handshaker_test.cc b/quic/core/tls_server_handshaker_test.cc
index f890684..7411ba2 100644
--- a/quic/core/tls_server_handshaker_test.cc
+++ b/quic/core/tls_server_handshaker_test.cc
@@ -42,14 +42,39 @@
const char kServerHostname[] = "test.example.com";
const uint16_t kServerPort = 443;
-class TlsServerHandshakerTest : public QuicTestWithParam<ParsedQuicVersion> {
+struct TestParams {
+ ParsedQuicVersion version;
+ bool disable_resumption;
+};
+
+// Used by ::testing::PrintToStringParamName().
+std::string PrintToString(const TestParams& p) {
+ return quiche::QuicheStrCat(
+ ParsedQuicVersionToString(p.version), "_",
+ (p.disable_resumption ? "ResumptionDisabled" : "ResumptionEnabled"));
+}
+
+// Constructs test permutations.
+std::vector<TestParams> GetTestParams() {
+ std::vector<TestParams> params;
+ for (const auto& version : AllSupportedVersionsWithTls()) {
+ for (bool disable_resumption : {false, true}) {
+ params.push_back(TestParams{version, disable_resumption});
+ }
+ }
+ return params;
+}
+
+class TlsServerHandshakerTest : public QuicTestWithParam<TestParams> {
public:
TlsServerHandshakerTest()
: server_compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, false),
- supported_versions_({GetParam()}) {
+ supported_versions_({GetParam().version}) {
SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
+ SetQuicFlag(FLAGS_quic_disable_server_tls_resumption,
+ GetParam().disable_resumption);
client_crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
crypto_test_utils::ProofVerifierForTesting(),
std::make_unique<test::SimpleSessionCache>());
@@ -228,7 +253,7 @@
INSTANTIATE_TEST_SUITE_P(TlsServerHandshakerTests,
TlsServerHandshakerTest,
- ::testing::ValuesIn(AllSupportedVersionsWithTls()),
+ ::testing::ValuesIn(GetTestParams()),
::testing::PrintToStringParamName());
TEST_P(TlsServerHandshakerTest, NotInitiallyConected) {
@@ -369,9 +394,10 @@
InitializeFakeClient();
CompleteCryptoHandshake();
ExpectHandshakeSuccessful();
- EXPECT_TRUE(client_stream()->IsResumption());
- EXPECT_TRUE(server_stream()->IsResumption());
- EXPECT_TRUE(server_stream()->ResumptionAttempted());
+ EXPECT_NE(client_stream()->IsResumption(), GetParam().disable_resumption);
+ EXPECT_NE(server_stream()->IsResumption(), GetParam().disable_resumption);
+ EXPECT_NE(server_stream()->ResumptionAttempted(),
+ GetParam().disable_resumption);
}
TEST_P(TlsServerHandshakerTest, ResumptionWithAsyncDecryptCallback) {
@@ -386,6 +412,10 @@
InitializeFakeClient();
AdvanceHandshakeWithFakeClient();
+ if (GetParam().disable_resumption) {
+ ASSERT_EQ(ticket_crypter_->NumPendingCallbacks(), 0u);
+ return;
+ }
// Test that the DecryptCallback will be run asynchronously, and then run it.
ASSERT_EQ(ticket_crypter_->NumPendingCallbacks(), 1u);
ticket_crypter_->RunPendingCallback(0);
@@ -398,6 +428,10 @@
}
TEST_P(TlsServerHandshakerTest, ResumptionWithFailingDecryptCallback) {
+ if (GetParam().disable_resumption) {
+ return;
+ }
+
// Do the first handshake
InitializeFakeClient();
CompleteCryptoHandshake();
@@ -415,6 +449,10 @@
}
TEST_P(TlsServerHandshakerTest, ResumptionWithFailingAsyncDecryptCallback) {
+ if (GetParam().disable_resumption) {
+ return;
+ }
+
// Do the first handshake
InitializeFakeClient();
CompleteCryptoHandshake();
@@ -469,8 +507,8 @@
InitializeFakeClient();
CompleteCryptoHandshake();
ExpectHandshakeSuccessful();
- EXPECT_TRUE(client_stream()->IsResumption());
- EXPECT_TRUE(server_stream()->IsZeroRtt());
+ EXPECT_NE(client_stream()->IsResumption(), GetParam().disable_resumption);
+ EXPECT_NE(server_stream()->IsZeroRtt(), GetParam().disable_resumption);
}
TEST_P(TlsServerHandshakerTest, ZeroRttRejectOnApplicationStateChange) {
@@ -493,7 +531,7 @@
InitializeFakeClient();
CompleteCryptoHandshake();
ExpectHandshakeSuccessful();
- EXPECT_TRUE(client_stream()->IsResumption());
+ EXPECT_NE(client_stream()->IsResumption(), GetParam().disable_resumption);
EXPECT_FALSE(server_stream()->IsZeroRtt());
}