| Index: net/quic/quic_stream_factory.cc
|
| diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
|
| index c011f6a9d5e6d1af82acbfd5bdb85ada4da14778..bca22e2cdb4d9fc71b5530381b46f23cdf95d3b4 100644
|
| --- a/net/quic/quic_stream_factory.cc
|
| +++ b/net/quic/quic_stream_factory.cc
|
| @@ -34,6 +34,7 @@
|
| #include "net/http/bidirectional_stream_impl.h"
|
| #include "net/quic/bidirectional_stream_quic_impl.h"
|
| #include "net/quic/crypto/channel_id_chromium.h"
|
| +#include "net/quic/crypto/proof_verifier.h"
|
| #include "net/quic/crypto/proof_verifier_chromium.h"
|
| #include "net/quic/crypto/properties_based_quic_server_info.h"
|
| #include "net/quic/crypto/quic_random.h"
|
| @@ -167,6 +168,84 @@ QuicConfig InitializeQuicConfig(const QuicTagVector& connection_options,
|
|
|
| } // namespace
|
|
|
| +class QuicStreamFactory::CertVerifierJob {
|
| + public:
|
| + class IgnoreProofVerifierCallback : public ProofVerifierCallback {
|
| + public:
|
| + explicit IgnoreProofVerifierCallback(CertVerifierJob* job) : job_(job) {}
|
| +
|
| + ~IgnoreProofVerifierCallback() override {}
|
| +
|
| + void Run(bool ok,
|
| + const std::string& error_details,
|
| + std::unique_ptr<ProofVerifyDetails>* details) override {
|
| + LOG(ERROR) << __FUNCTION__;
|
| + if (job_ == nullptr)
|
| + return;
|
| + job_->verify_callback_ = nullptr;
|
| + job_->OnComplete();
|
| + }
|
| +
|
| + void Cancel() { job_ = nullptr; }
|
| +
|
| + private:
|
| + CertVerifierJob* job_;
|
| + };
|
| +
|
| + CertVerifierJob(const QuicServerId& server_id,
|
| + int cert_verify_flags,
|
| + QuicCryptoClientConfig* crypto_config,
|
| + const BoundNetLog& net_log)
|
| + : server_id_(server_id),
|
| + crypto_config_(crypto_config),
|
| + verify_callback_(new IgnoreProofVerifierCallback(this)),
|
| + verify_context_(
|
| + new ProofVerifyContextChromium(cert_verify_flags, net_log)),
|
| + net_log_(net_log),
|
| + weak_factory_(this) {}
|
| +
|
| + ~CertVerifierJob() {
|
| + if (verify_callback_)
|
| + verify_callback_->Cancel();
|
| + }
|
| +
|
| + QuicAsyncStatus Run(const CompletionCallback& callback) {
|
| + QuicCryptoClientConfig::CachedState* cached =
|
| + crypto_config_->LookupOrCreate(server_id_);
|
| + LOG(ERROR) << __FUNCTION__;
|
| + // Pass empty chlo_hash, signature and cert_sct so that only certificate is
|
| + // verified.
|
| + QuicAsyncStatus status = crypto_config_->proof_verifier()->VerifyProof(
|
| + server_id_.host(), server_id_.port(), cached->server_config(),
|
| + QUIC_VERSION_25, /*chlo_hash=*/"", cached->certs(),
|
| + /*cert_sct=*/"", /*signature=*/"", verify_context_.get(),
|
| + &verify_error_details_, &verify_details_, verify_callback_);
|
| + if (status != QUIC_FAILURE)
|
| + callback_ = callback;
|
| + return status;
|
| + }
|
| +
|
| + void OnComplete() {
|
| + if (!callback_.is_null())
|
| + callback_.Run(OK);
|
| + }
|
| +
|
| + const QuicServerId& server_id() const { return server_id_; }
|
| +
|
| + private:
|
| + QuicServerId server_id_;
|
| + QuicCryptoClientConfig* crypto_config_;
|
| + IgnoreProofVerifierCallback* verify_callback_;
|
| + std::unique_ptr<ProofVerifyContext> verify_context_;
|
| + std::unique_ptr<ProofVerifyDetails> verify_details_;
|
| + std::string verify_error_details_;
|
| + const BoundNetLog net_log_;
|
| + CompletionCallback callback_;
|
| + base::WeakPtrFactory<CertVerifierJob> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CertVerifierJob);
|
| +};
|
| +
|
| // Responsible for creating a new QUIC session to the specified server, and
|
| // for notifying any associated requests when complete.
|
| class QuicStreamFactory::Job {
|
| @@ -631,6 +710,7 @@ QuicStreamFactory::QuicStreamFactory(
|
| int idle_connection_timeout_seconds,
|
| bool migrate_sessions_on_network_change,
|
| bool migrate_sessions_early,
|
| + bool race_cert_verification,
|
| const QuicTagVector& connection_options,
|
| bool enable_token_binding)
|
| : require_confirmation_(true),
|
| @@ -684,6 +764,7 @@ QuicStreamFactory::QuicStreamFactory(
|
| NetworkChangeNotifier::AreNetworkHandlesSupported()),
|
| migrate_sessions_early_(migrate_sessions_early &&
|
| migrate_sessions_on_network_change_),
|
| + race_cert_verification_(race_cert_verification),
|
| port_seed_(random_generator_->RandUint64()),
|
| check_persisted_supports_quic_(true),
|
| has_initialized_data_(false),
|
| @@ -748,6 +829,10 @@ QuicStreamFactory::~QuicStreamFactory() {
|
| STLDeleteElements(&(active_jobs_[server_id]));
|
| active_jobs_.erase(server_id);
|
| }
|
| + while (!active_cert_verifier_jobs_.empty()) {
|
| + delete active_cert_verifier_jobs_.begin()->second;
|
| + active_cert_verifier_jobs_.erase(active_cert_verifier_jobs_.begin());
|
| + }
|
| if (migrate_sessions_on_network_change_) {
|
| NetworkChangeNotifier::RemoveNetworkObserver(this);
|
| } else if (close_sessions_on_ip_change_) {
|
| @@ -882,6 +967,8 @@ int QuicStreamFactory::Create(const QuicServerId& server_id,
|
| }
|
| }
|
|
|
| + StartCertVerifyJob(server_id, cert_verify_flags, net_log);
|
| +
|
| QuicSessionKey key(destination, server_id);
|
| std::unique_ptr<Job> job(
|
| new Job(this, host_resolver_, key, WasQuicRecentlyBroken(server_id),
|
| @@ -1014,6 +1101,11 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
|
| job_requests_map_.erase(server_id);
|
| }
|
|
|
| +void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) {
|
| + LOG(ERROR) << __FUNCTION__;
|
| + active_cert_verifier_jobs_.erase(job->server_id());
|
| +}
|
| +
|
| std::unique_ptr<QuicHttpStream> QuicStreamFactory::CreateFromSession(
|
| QuicChromiumClientSession* session) {
|
| return std::unique_ptr<QuicHttpStream>(
|
| @@ -1542,6 +1634,11 @@ bool QuicStreamFactory::HasActiveJob(const QuicServerId& server_id) const {
|
| return ContainsKey(active_jobs_, server_id);
|
| }
|
|
|
| +bool QuicStreamFactory::HasActiveCertVerifierJob(
|
| + const QuicServerId& server_id) const {
|
| + return ContainsKey(active_cert_verifier_jobs_, server_id);
|
| +}
|
| +
|
| int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket,
|
| IPEndPoint addr,
|
| NetworkHandle network) {
|
| @@ -1749,6 +1846,28 @@ bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
|
| return cached->IsEmpty();
|
| }
|
|
|
| +void QuicStreamFactory::StartCertVerifyJob(const QuicServerId& server_id,
|
| + int cert_verify_flags,
|
| + const BoundNetLog& net_log) {
|
| + LOG(ERROR) << __FUNCTION__ << " " << race_cert_verification_;
|
| + if (!race_cert_verification_)
|
| + return;
|
| + QuicCryptoClientConfig::CachedState* cached =
|
| + crypto_config_.LookupOrCreate(server_id);
|
| + if (!cached || cached->certs().empty() || cached->proof_valid() ||
|
| + HasActiveCertVerifierJob(server_id)) {
|
| + LOG(ERROR) << __FUNCTION__ << " " << __LINE__;
|
| + return;
|
| + }
|
| + std::unique_ptr<CertVerifierJob> cert_verifier_job(new CertVerifierJob(
|
| + server_id, cert_verify_flags, &crypto_config_, net_log));
|
| + QuicAsyncStatus status = cert_verifier_job->Run(
|
| + base::Bind(&QuicStreamFactory::OnCertVerifyJobComplete,
|
| + base::Unretained(this), cert_verifier_job.get()));
|
| + if (status != QUIC_FAILURE)
|
| + active_cert_verifier_jobs_[server_id] = cert_verifier_job.release();
|
| +}
|
| +
|
| void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
|
| const QuicServerId& server_id,
|
| const std::unique_ptr<QuicServerInfo>& server_info,
|
|
|