From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Wed, 8 May 2019 17:25:55 -0700 Subject: network_service_allow_remote_certificate_verification_logic.patch This adds a callback from the network service that's used to implement session.setCertificateVerifyCallback. diff --git a/services/network/network_context.cc b/services/network/network_context.cc index db667e13f2e4d9e96e9ac28f17c61412d6279ec7..258fc7463f81e58bdeb22c6eea465c9e97242fb0 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc @@ -118,6 +118,11 @@ #include "services/network/url_loader.h" #include "services/network/url_request_context_builder_mojo.h" +// Electron +#include "net/cert/caching_cert_verifier.h" +#include "net/cert/cert_verify_proc.h" +#include "net/cert/multi_threaded_cert_verifier.h" + #if BUILDFLAG(IS_CT_SUPPORTED) #include "components/certificate_transparency/chrome_ct_policy_enforcer.h" #include "components/certificate_transparency/chrome_require_ct_delegate.h" @@ -376,6 +381,79 @@ bool SCTAuditingDelegate::IsSCTAuditingEnabled() { } // namespace +class RemoteCertVerifier : public net::CertVerifier { + public: + RemoteCertVerifier(std::unique_ptr upstream): upstream_(std::move(upstream)) { + } + ~RemoteCertVerifier() override = default; + + void Bind( + mojo::PendingRemote client_info) { + client_.reset(); + if (client_info.is_valid()) { + client_.Bind(std::move(client_info)); + } + } + + // CertVerifier implementation + int Verify(const RequestParams& params, + net::CertVerifyResult* verify_result, + net::CompletionOnceCallback callback, + std::unique_ptr* out_req, + const net::NetLogWithSource& net_log) override { + out_req->reset(); + + net::CompletionOnceCallback callback2 = base::BindOnce( + &RemoteCertVerifier::OnRequestFinished, base::Unretained(this), + params, std::move(callback), verify_result); + int result = upstream_->Verify(params, verify_result, + std::move(callback2), out_req, net_log); + if (result != net::ERR_IO_PENDING) { + // Synchronous completion + } + + return result; + } + + + void SetConfig(const Config& config) override { + upstream_->SetConfig(config); + } + + void OnRequestFinished(const RequestParams& params, net::CompletionOnceCallback callback, net::CertVerifyResult* verify_result, int error) { + if (client_.is_bound()) { + client_->Verify(error, *verify_result, params.certificate(), + params.hostname(), params.flags(), params.ocsp_response(), + base::BindOnce(&RemoteCertVerifier::OnRemoteResponse, + base::Unretained(this), params, verify_result, error, + std::move(callback))); + } else { + std::move(callback).Run(error); + } + } + + void OnRemoteResponse( + const RequestParams& params, + net::CertVerifyResult* verify_result, + int error, + net::CompletionOnceCallback callback, + int error2, + const net::CertVerifyResult& verify_result2) { + if (error2 == net::ERR_ABORTED) { + // use the default + std::move(callback).Run(error); + } else { + // use the override + verify_result->Reset(); + verify_result->verified_cert = verify_result2.verified_cert; + std::move(callback).Run(error2); + } + } + private: + std::unique_ptr upstream_; + mojo::Remote client_; +}; + constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess; NetworkContext::PendingCertVerify::PendingCertVerify() = default; @@ -575,6 +653,13 @@ void NetworkContext::SetClient( client_.Bind(std::move(client)); } +void NetworkContext::SetCertVerifierClient( + mojo::PendingRemote client) { + if (remote_cert_verifier_) { + remote_cert_verifier_->Bind(std::move(client)); + } +} + void NetworkContext::CreateURLLoaderFactory( mojo::PendingReceiver receiver, mojom::URLLoaderFactoryParamsPtr params) { @@ -1929,6 +2014,10 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( } #endif // BUILDFLAG(IS_CT_SUPPORTED) + auto remote_cert_verifier = std::make_unique(std::move(cert_verifier)); + remote_cert_verifier_ = remote_cert_verifier.get(); + cert_verifier = std::move(remote_cert_verifier); + // Whether the cert verifier is remote or in-process, we should wrap it in // caching and coalescing layers to avoid extra verifications and IPCs. cert_verifier = std::make_unique( diff --git a/services/network/network_context.h b/services/network/network_context.h index 707cf9a7db7b81da9affef0c9ab4a934f5fd69c9..494d68d7f399152a08dd74ee4aa2d17baec81dd8 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h @@ -90,6 +90,7 @@ class DomainReliabilityMonitor; namespace network { class CertVerifierWithTrustAnchors; +class RemoteCertVerifier; class CookieManager; class ExpectCTReporter; class HostResolver; @@ -194,6 +195,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext void CreateURLLoaderFactory( mojo::PendingReceiver receiver, mojom::URLLoaderFactoryParamsPtr params) override; + void SetCertVerifierClient( + mojo::PendingRemote client) override; void ResetURLLoaderFactories() override; void GetCookieManager( mojo::PendingReceiver receiver) override; @@ -692,6 +695,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext CertVerifierWithTrustAnchors* cert_verifier_with_trust_anchors_ = nullptr; #endif + RemoteCertVerifier* remote_cert_verifier_ = nullptr; + // CertNetFetcher used by the context's CertVerifier. May be nullptr if // CertNetFetcher is not used by the current platform, or if the actual // net::CertVerifier is instantiated outside of the network service. diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 8ac73cae153047e16f37a7ca1941c7fc43def52e..17695b6b6a50f6d8f3b81d5e57b2bbeb667b83c7 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom @@ -228,6 +228,17 @@ struct CTPolicy { array excluded_legacy_spkis; }; +interface CertVerifierClient { + Verify( + int32 default_error, + CertVerifyResult default_result, + X509Certificate certificate, + string hostname, + int32 flags, + string? ocsp_response + ) => (int32 error_code, CertVerifyResult result); +}; + // Parameters for constructing a network context. struct NetworkContextParams { // Name used by memory tools to identify the context. @@ -889,6 +900,9 @@ interface NetworkContext { // Sets a client for this network context. SetClient(pending_remote client); + // Sets a certificate verifier client for this network context. + SetCertVerifierClient(pending_remote? client); + // Creates a new URLLoaderFactory with the given |params|. CreateURLLoaderFactory(pending_receiver url_loader_factory, URLLoaderFactoryParams params);