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(),