Fix gQUIC remote handshake by postpone certificate validation to after GetProof is done.

Also modify standalone_handshaker_end_to_end_test to verify the HTTP response content, instead of response_complete(), which is implemented incorrectly in quic client.

Protected by FLAGS_quic_reloadable_flag_quic_crypto_postpone_cert_validate_for_server.

PiperOrigin-RevId: 360229986
Change-Id: I1d7afa111daec727901c1e6a8c1c95ca4c76e731
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc
index da04f4f..1406829 100644
--- a/quic/core/crypto/quic_crypto_server_config.cc
+++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -743,6 +743,22 @@
       << context->connection_id() << " which is invalid with version "
       << context->version();
 
+  if (context->validate_chlo_result()->postpone_cert_validate_for_server &&
+      context->info().reject_reasons.empty()) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_crypto_postpone_cert_validate_for_server);
+    if (!context->signed_config() || !context->signed_config()->chain) {
+      // No chain.
+      context->validate_chlo_result()->info.reject_reasons.push_back(
+          SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
+    } else if (!ValidateExpectedLeafCertificate(
+                   context->client_hello(),
+                   context->signed_config()->chain->certs)) {
+      // Has chain but leaf is invalid.
+      context->validate_chlo_result()->info.reject_reasons.push_back(
+          INVALID_EXPECTED_LEAF_CERTIFICATE);
+    }
+  }
+
   if (found_error) {
     context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
     return;
@@ -1276,13 +1292,15 @@
     // No valid source address token.
   }
 
-  QuicReferenceCountedPointer<ProofSource::Chain> chain =
-      proof_source_->GetCertChain(server_address, client_address,
-                                  std::string(info->sni));
-  if (!chain) {
-    info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
-  } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
-    info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
+  if (!client_hello_state->postpone_cert_validate_for_server) {
+    QuicReferenceCountedPointer<ProofSource::Chain> chain =
+        proof_source_->GetCertChain(server_address, client_address,
+                                    std::string(info->sni));
+    if (!chain) {
+      info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
+    } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
+      info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
+    }
   }
 
   if (info->client_nonce.size() != kNonceSize) {
diff --git a/quic/core/crypto/quic_crypto_server_config.h b/quic/core/crypto/quic_crypto_server_config.h
index 4f3ad08..464f2bb 100644
--- a/quic/core/crypto/quic_crypto_server_config.h
+++ b/quic/core/crypto/quic_crypto_server_config.h
@@ -98,6 +98,9 @@
     // Populated if the CHLO STK contained a CachedNetworkParameters proto.
     CachedNetworkParameters cached_network_params;
 
+    const bool postpone_cert_validate_for_server =
+        GetQuicReloadableFlag(quic_crypto_postpone_cert_validate_for_server);
+
    protected:
     ~Result() override;
   };
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 92780bd..f37ccbc 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -20,6 +20,7 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_crypto_postpone_cert_validate_for_server, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc
index 4133950..d1c1272 100644
--- a/quic/test_tools/quic_test_client.cc
+++ b/quic/test_tools/quic_test_client.cc
@@ -796,7 +796,8 @@
   closed_stream_states_.insert(std::make_pair(
       id,
       PerStreamState(
-          client_stream->stream_error(), true,
+          // Set response_complete to true iff stream is closed while connected.
+          client_stream->stream_error(), connected(),
           client_stream->headers_decompressed(),
           client_stream->response_headers(),
           client_stream->preliminary_headers(),