Make QuicDispatcher reject packets with invalid short connection IDs
This CLs enforces a MUST in the IETF spec that dictates that clients cannot send initial connection IDs under 8 bytes. The QuicDispatcher will reject (and close the connection of) any packet whose connection ID is shorter than 8 (or what it was configured for). The behavior is disabled by quartc. This only impacts v99 because connection IDs of any length other than 8 are already currently dropped when using versions < 99.
gfe-relnote: v99 only, not flag protected
PiperOrigin-RevId: 239629063
Change-Id: I85cee11d84566073e8cbb3569ba3e88e91192f2a
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 7ef2869..d1200a9 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -296,7 +296,8 @@
expected_connection_id_length),
last_error_(QUIC_NO_ERROR),
new_sessions_allowed_per_event_loop_(0u),
- accept_new_connections_(true) {
+ accept_new_connections_(true),
+ allow_short_initial_connection_ids_(false) {
framer_.set_visitor(this);
}
@@ -371,6 +372,26 @@
}
QuicConnectionId connection_id = header.destination_connection_id;
+ // The IETF spec requires the client to generate an initial server
+ // connection ID that is at least 64 bits long. After that initial
+ // connection ID, the dispatcher picks a new one of its expected length.
+ // Therefore we should never receive a connection ID that is smaller
+ // than 64 bits and smaller than what we expect.
+ if (connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
+ connection_id.length() < framer_.GetExpectedConnectionIdLength() &&
+ !allow_short_initial_connection_ids_) {
+ DCHECK(header.version_flag);
+ DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ header.version.transport_version));
+ QUIC_DLOG(INFO) << "Packet with short destination connection ID "
+ << connection_id << " expected "
+ << static_cast<int>(
+ framer_.GetExpectedConnectionIdLength());
+ ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, header.form,
+ header.version);
+ return false;
+ }
+
// Packets with connection IDs for active connections are processed
// immediately.
auto it = session_map_.find(connection_id);