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);