blob: ad7fa4e88882d9a243f780e9c640c6f8ce1d9a60 [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/component_updater/crl_set_component_installer.h"
#include <memory>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "components/component_updater/component_installer.h"
#include "components/component_updater/component_updater_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "net/cert/crl_set.h"
#include "net/ssl/ssl_config_service.h"
#include "services/network/public/mojom/network_service.mojom.h"
namespace component_updater {
namespace {
// kCrlSetPublicKeySHA256 is the SHA256 hash of the SubjectPublicKeyInfo of the
// key that's used to sign generated CRL sets.
const uint8_t kCrlSetPublicKeySHA256[32] = {
0x75, 0xda, 0xf8, 0xcb, 0x77, 0x68, 0x40, 0x33, 0x65, 0x4c, 0x97,
0xe5, 0xc5, 0x1b, 0xcd, 0x81, 0x7b, 0x1e, 0xeb, 0x11, 0x2c, 0xe1,
0xa4, 0x33, 0x8c, 0xf5, 0x72, 0x5e, 0xed, 0xb8, 0x43, 0x97,
};
const base::FilePath::CharType kCRLSetFile[] = FILE_PATH_LITERAL("crl-set");
// Returns the contents of the file at |crl_path|.
std::string LoadCRLSet(const base::FilePath& crl_path) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::WILL_BLOCK);
std::string crl_set_bytes;
base::ReadFileToString(crl_path, &crl_set_bytes);
return crl_set_bytes;
}
// Singleton object used to configure Network Services and memoize the CRLSet
// configuration.
class CRLSetData {
public:
// Sets the latest CRLSet to |crl_set_path|. Call
// |ConfigureNetworkService()| to actually load that path.
void set_crl_set_path(const base::FilePath& crl_set_path) {
crl_set_path_ = crl_set_path;
}
// Configures updates to be sent to |network_service|, rather than
// content::GetNetworkService(). This should only be used for tests.
void set_network_service(network::mojom::NetworkService* network_service) {
network_service_ = network_service;
}
// Updates the currently configured network service (or
// content::GetNetworkService()) with the current CRLSet configuration.
void ConfigureNetworkService();
private:
void UpdateCRLSetOnUI(const std::string& crl_set_bytes);
network::mojom::NetworkService* network_service_ = nullptr;
base::FilePath crl_set_path_;
};
base::LazyInstance<CRLSetData>::Leaky g_crl_set_data =
LAZY_INSTANCE_INITIALIZER;
void CRLSetData::ConfigureNetworkService() {
if (crl_set_path_.empty())
return;
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
base::BindOnce(&LoadCRLSet, crl_set_path_),
base::BindOnce(&CRLSetData::UpdateCRLSetOnUI, base::Unretained(this)));
}
void CRLSetData::UpdateCRLSetOnUI(const std::string& crl_set_bytes) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
network::mojom::NetworkService* network_service =
network_service_ ? network_service_ : content::GetNetworkService();
network_service->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
base::DoNothing());
}
} // namespace
CRLSetPolicy::CRLSetPolicy() = default;
CRLSetPolicy::~CRLSetPolicy() = default;
// static
void CRLSetPolicy::SetNetworkServiceForTesting(
network::mojom::NetworkService* network_service) {
g_crl_set_data.Get().set_network_service(network_service);
}
// static
void CRLSetPolicy::ReconfigureAfterNetworkRestart() {
g_crl_set_data.Get().ConfigureNetworkService();
}
bool CRLSetPolicy::VerifyInstallation(const base::DictionaryValue& manifest,
const base::FilePath& install_dir) const {
return base::PathExists(install_dir.Append(kCRLSetFile));
}
bool CRLSetPolicy::SupportsGroupPolicyEnabledComponentUpdates() const {
return false;
}
bool CRLSetPolicy::RequiresNetworkEncryption() const {
return false;
}
update_client::CrxInstaller::Result CRLSetPolicy::OnCustomInstall(
const base::DictionaryValue& manifest,
const base::FilePath& install_dir) {
return update_client::CrxInstaller::Result(0); // Nothing custom here.
}
void CRLSetPolicy::OnCustomUninstall() {}
void CRLSetPolicy::ComponentReady(
const base::Version& version,
const base::FilePath& install_dir,
std::unique_ptr<base::DictionaryValue> manifest) {
g_crl_set_data.Get().set_crl_set_path(install_dir.Append(kCRLSetFile));
g_crl_set_data.Get().ConfigureNetworkService();
}
base::FilePath CRLSetPolicy::GetRelativeInstallDir() const {
return base::FilePath(FILE_PATH_LITERAL("CertificateRevocation"));
}
void CRLSetPolicy::GetHash(std::vector<uint8_t>* hash) const {
hash->assign(std::begin(kCrlSetPublicKeySHA256),
std::end(kCrlSetPublicKeySHA256));
}
std::string CRLSetPolicy::GetName() const {
return "CRLSet";
}
update_client::InstallerAttributes CRLSetPolicy::GetInstallerAttributes()
const {
return update_client::InstallerAttributes();
}
std::vector<std::string> CRLSetPolicy::GetMimeTypes() const {
return std::vector<std::string>();
}
void RegisterCRLSetComponent(ComponentUpdateService* cus,
const base::FilePath& user_data_dir) {
auto installer = base::MakeRefCounted<ComponentInstaller>(
std::make_unique<CRLSetPolicy>());
installer->Register(cus, base::OnceClosure());
}
} // namespace component_updater