blob: 5330c8111cd88faffd92bfa301f4e73fd81915da [file] [log] [blame]
// Copyright 2013 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/chromeos/policy/policy_cert_service.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/task/post_task.h"
#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/cert/x509_certificate.h"
#include "services/network/nss_temp_certs_cache_chromeos.h"
namespace policy {
PolicyCertService::~PolicyCertService() {}
PolicyCertService::PolicyCertService(
Profile* profile,
const std::string& user_id,
UserNetworkConfigurationUpdater* net_conf_updater,
user_manager::UserManager* user_manager)
: profile_(profile),
user_id_(user_id),
net_conf_updater_(net_conf_updater),
user_manager_(user_manager),
weak_ptr_factory_(this) {
DCHECK(net_conf_updater_);
DCHECK(user_manager_);
}
PolicyCertService::PolicyCertService(const std::string& user_id,
user_manager::UserManager* user_manager)
: user_id_(user_id),
net_conf_updater_(NULL),
user_manager_(user_manager),
weak_ptr_factory_(this) {}
void PolicyCertService::StartObservingPolicyCerts() {
// Don't notify the network service since it will get the initial list of
// trust anchors in NetworkContextParams::initial_trust_anchors.
StartObservingPolicyCertsInternal(false /* notify */);
}
void PolicyCertService::OnPolicyProvidedCertsChanged(
const net::CertificateList& all_server_and_authority_certs,
const net::CertificateList& trust_anchors) {
OnPolicyProvidedCertsChangedInternal(all_server_and_authority_certs,
trust_anchors, true /* notify */);
}
void PolicyCertService::StartObservingPolicyCertsInternal(bool notify) {
net_conf_updater_->AddPolicyProvidedCertsObserver(this);
// Set the current list of policy-provided server and authority certificates,
// and the current list of trust anchors.
net::CertificateList all_server_and_authority_certs =
net_conf_updater_->GetAllServerAndAuthorityCertificates();
net::CertificateList trust_anchors =
net_conf_updater_->GetWebTrustedCertificates();
OnPolicyProvidedCertsChangedInternal(all_server_and_authority_certs,
trust_anchors, notify);
}
void PolicyCertService::OnPolicyProvidedCertsChangedInternal(
const net::CertificateList& all_server_and_authority_certs,
const net::CertificateList& trust_anchors,
bool notify) {
// Make all policy-provided server and authority certificates available to NSS
// as temp certificates.
// Note that this is done on the UI thread because the assumption is that NSS
// has already been initialized by Chrome OS specific start-up code in chrome,
// expecting that the operation of creating in-memory NSS certs is cheap in
// that case.
temp_policy_provided_certs_ =
std::make_unique<network::NSSTempCertsCacheChromeOS>(
all_server_and_authority_certs);
all_server_and_authority_certs_ = all_server_and_authority_certs;
// Do not use certificates installed via ONC policy if the current session has
// multiple profiles. This is important to make sure that any possibly tainted
// data is absolutely confined to the managed profile and never, ever leaks to
// any other profile.
if (!trust_anchors.empty() && user_manager_->GetLoggedInUsers().size() > 1u) {
LOG(ERROR) << "Ignoring ONC-pushed certificates update because multiple "
<< "users are logged in.";
trust_anchors_.clear();
} else {
trust_anchors_ = trust_anchors;
}
if (!notify)
return;
auto* profile_network_context =
ProfileNetworkContextServiceFactory::GetForContext(profile_);
if (profile_network_context) { // null in unit tests.
profile_network_context->UpdateAdditionalCertificates(
all_server_and_authority_certs_, trust_anchors_);
}
}
bool PolicyCertService::UsedPolicyCertificates() const {
return PolicyCertServiceFactory::UsedPolicyCertificates(user_id_);
}
void PolicyCertService::Shutdown() {
weak_ptr_factory_.InvalidateWeakPtrs();
if (net_conf_updater_)
net_conf_updater_->RemovePolicyProvidedCertsObserver(this);
OnPolicyProvidedCertsChanged(
net::CertificateList() /* all_server_and_authority_certs */,
net::CertificateList() /* trust_anchors */);
net_conf_updater_ = NULL;
}
// static
std::unique_ptr<PolicyCertService> PolicyCertService::CreateForTesting(
const std::string& user_id,
user_manager::UserManager* user_manager) {
return base::WrapUnique(new PolicyCertService(user_id, user_manager));
}
} // namespace policy