blob: 360839350c240a36c45e2501d49aa3eb28f49b25 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/cert_verifier/cert_verifier_service_factory.h"
#include <memory>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/stl_util.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_verifier.h"
#include "net/net_buildflags.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/cert_verifier/cert_verifier_creation.h"
#include "services/cert_verifier/cert_verifier_service.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
#include "mojo/public/cpp/base/big_buffer.h"
#include "net/cert/internal/trust_store_chrome.h"
#include "net/cert/root_store_proto_lite/root_store.pb.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#endif
namespace net {
class ChromeRootStoreData;
}
namespace cert_verifier {
namespace {
internal::CertVerifierServiceImpl* GetNewCertVerifierImpl(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojom::CertVerifierCreationParamsPtr creation_params,
const net::ChromeRootStoreData* root_store_data,
scoped_refptr<CertNetFetcherURLLoader>* out_cert_net_fetcher) {
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher;
// Sometimes the cert_net_fetcher isn't used by CreateCertVerifier.
// But losing the last ref without calling Shutdown() will cause a CHECK
// failure, so keep a ref.
if (IsUsingCertNetFetcher()) {
cert_net_fetcher = base::MakeRefCounted<CertNetFetcherURLLoader>();
}
std::unique_ptr<net::CertVerifierWithUpdatableProc> cert_verifier =
CreateCertVerifier(creation_params.get(), cert_net_fetcher,
root_store_data);
// As an optimization, if the CertNetFetcher isn't used by the CertVerifier,
// shut it down immediately.
if (cert_net_fetcher && cert_net_fetcher->HasOneRef()) {
cert_net_fetcher->Shutdown();
cert_net_fetcher.reset();
}
// Return reference to cert_net_fetcher for testing purposes.
if (out_cert_net_fetcher)
*out_cert_net_fetcher = cert_net_fetcher;
// The service will delete itself upon disconnection.
return new internal::CertVerifierServiceImpl(std::move(cert_verifier),
std::move(receiver),
std::move(cert_net_fetcher));
}
} // namespace
CertVerifierServiceFactoryImpl::CertVerifierServiceFactoryImpl(
mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver)
: receiver_(this, std::move(receiver)) {}
CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojom::CertVerifierCreationParamsPtr creation_params) {
net::ChromeRootStoreData* root_store_data = nullptr;
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
root_store_data = base::OptionalOrNullptr(root_store_data_);
#endif
internal::CertVerifierServiceImpl* service_impl = GetNewCertVerifierImpl(
std::move(receiver), std::move(creation_params), root_store_data,
/*out_cert_net_fetcher=*/nullptr);
verifier_services_.insert(service_impl);
service_impl->SetCertVerifierServiceFactory(weak_factory_.GetWeakPtr());
}
void CertVerifierServiceFactoryImpl::GetNewCertVerifierForTesting(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
mojom::CertVerifierCreationParamsPtr creation_params,
scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
GetNewCertVerifierImpl(std::move(receiver), std::move(creation_params),
/*root_store_data=*/nullptr, cert_net_fetcher_ptr);
}
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
void CertVerifierServiceFactoryImpl::UpdateChromeRootStore(
mojom::ChromeRootStorePtr new_root_store) {
if (new_root_store->serialized_proto_root_store.size() == 0) {
LOG(ERROR) << "Empty serialized RootStore proto";
return;
}
chrome_root_store::RootStore proto;
if (!proto.ParseFromArray(
new_root_store->serialized_proto_root_store.data(),
new_root_store->serialized_proto_root_store.size())) {
LOG(ERROR) << "error parsing proto for Chrome Root Store";
return;
}
// We only check against the compiled version to allow for us to to use
// Component Updater to revert to older versions. Check is left in
// to guard against Component updater being stuck on older versions due
// to daily updates of the PKI Metadata component being broken.
if (proto.version_major() <= net::CompiledChromeRootStoreVersion()) {
return;
}
absl::optional<net::ChromeRootStoreData> root_store_data =
net::ChromeRootStoreData::CreateChromeRootStoreData(proto);
if (!root_store_data) {
LOG(ERROR) << "error interpreting proto for Chrome Root Store";
return;
}
if (root_store_data->anchors().empty()) {
LOG(ERROR) << "parsed root store contained no anchors";
return;
}
for (internal::CertVerifierServiceImpl* service : verifier_services_) {
service->UpdateChromeRootStoreData(&root_store_data.value());
}
// Update the stored Chrome Root Store so that new CertVerifierService
// instances will start with the updated store.
root_store_data_ = std::move(root_store_data);
}
#endif
void CertVerifierServiceFactoryImpl::RemoveService(
internal::CertVerifierServiceImpl* service_impl) {
verifier_services_.erase(service_impl);
}
} // namespace cert_verifier