From f07e571ec67701e33199c27036175b1abfd178a5 Mon Sep 17 00:00:00 2001 From: Nico Greger Date: Sat, 25 Oct 2025 15:08:50 +0200 Subject: [PATCH] fix: Don't overwrite early address validation tokens --- .../core/crypto/quic_client_session_cache.cc | 36 ++++++++++++++----- .../core/crypto/quic_client_session_cache.h | 8 ++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/quiche/quic/core/crypto/quic_client_session_cache.cc b/quiche/quic/core/crypto/quic_client_session_cache.cc index 640ca1ecd..7a2a1c639 100644 --- a/quiche/quic/core/crypto/quic_client_session_cache.cc +++ b/quiche/quic/core/crypto/quic_client_session_cache.cc @@ -56,19 +56,27 @@ void QuicClientSessionCache::Insert(const QuicServerId& server_id, return; } - QUICHE_DCHECK(iter->second->params); // The states are both the same, so only need to insert sessions. - if (params == *iter->second->params && + if (iter->second->params && params == *iter->second->params && DoApplicationStatesMatch(application_state, iter->second->application_state.get())) { iter->second->PushSession(std::move(session)); return; } - // Erase the existing entry because this Insert call must come from a - // different QUIC session. - cache_.Erase(iter); - CreateAndInsertEntry(server_id, std::move(session), params, - application_state); + + // Copy potential address token received between the last sent Initial packet and now. + if (iter->second->token.empty()) { + // Erase the existing entry because this Insert call must come from a + // different QUIC session. + cache_.Erase(iter); + CreateAndInsertEntry(server_id, std::move(session), params, + application_state); + } else { + auto token = std::move(iter->second->token); + cache_.Erase(iter); + CreateAndInsertEntry(server_id, std::move(session), params, + application_state, std::move(token)); + } } std::unique_ptr QuicClientSessionCache::Lookup( @@ -118,6 +126,8 @@ void QuicClientSessionCache::OnNewTokenReceived(const QuicServerId& server_id, } auto iter = cache_.Lookup(server_id.cache_key()); if (iter == cache_.end()) { + // TODO: Create new Entry with zero values except for token + CreateAndInsertTokenDummy(server_id, token); return; } iter->second->token = std::string(token); @@ -136,13 +146,23 @@ void QuicClientSessionCache::RemoveExpiredEntries(QuicWallTime now) { void QuicClientSessionCache::Clear() { cache_.Clear(); } +void QuicClientSessionCache::CreateAndInsertTokenDummy( + const QuicServerId& server_id, + const absl::string_view& token) { + auto entry = std::make_unique(); + entry->token = std::string(token); + cache_.Insert(server_id.cache_key(), std::move(entry)); +} + void QuicClientSessionCache::CreateAndInsertEntry( const QuicServerId& server_id, bssl::UniquePtr session, const TransportParameters& params, - const ApplicationState* application_state) { + const ApplicationState* application_state, + const std::string &token){ auto entry = std::make_unique(); entry->PushSession(std::move(session)); entry->params = std::make_unique(params); + entry->token = token; if (application_state) { entry->application_state = std::make_unique(*application_state); diff --git a/quiche/quic/core/crypto/quic_client_session_cache.h b/quiche/quic/core/crypto/quic_client_session_cache.h index 37b7ef555..c28aa38f9 100644 --- a/quiche/quic/core/crypto/quic_client_session_cache.h +++ b/quiche/quic/core/crypto/quic_client_session_cache.h @@ -70,11 +70,17 @@ class QUICHE_EXPORT QuicClientSessionCache : public SessionCache { std::string token; // An opaque string received in NEW_TOKEN frame. }; + // Creates a dummy entry that only contains a token and inserts into |cache_| + void CreateAndInsertTokenDummy( + const QuicServerId& server_id, + const absl::string_view& token); + // Creates a new entry and insert into |cache_|. void CreateAndInsertEntry(const QuicServerId& server_id, bssl::UniquePtr session, const TransportParameters& params, - const ApplicationState* application_state); + const ApplicationState* application_state, + const std::string &token = std::string()); QuicLRUCache> cache_; };