1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/policy/networking/user_network_configuration_updater_ash.h"
#include <utility>
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/values.h"
#include "chrome/browser/ash/login/session/user_session_manager.h"
#include "chrome/browser/net/nss_service.h"
#include "chrome/browser/net/nss_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/network/managed_network_configuration_handler.h"
#include "chromeos/ash/components/network/network_cert_loader.h"
#include "chromeos/ash/components/network/onc/network_onc_utils.h"
#include "chromeos/ash/components/network/onc/onc_certificate_importer_impl.h"
#include "chromeos/components/onc/onc_parsed_certificates.h"
#include "chromeos/components/onc/onc_utils.h"
#include "components/policy/policy_constants.h"
#include "components/user_manager/user.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace policy {
namespace {
void GetNssCertDatabaseOnIOThread(
NssCertDatabaseGetter database_getter,
base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
auto split_callback = base::SplitOnceCallback(std::move(callback));
net::NSSCertDatabase* cert_db =
std::move(database_getter).Run(std::move(split_callback.first));
if (cert_db)
std::move(split_callback.second).Run(cert_db);
}
} // namespace
UserNetworkConfigurationUpdaterAsh::~UserNetworkConfigurationUpdaterAsh() {
// NetworkCertLoader may be not initialized in tests.
if (ash::NetworkCertLoader::IsInitialized()) {
ash::NetworkCertLoader::Get()->SetUserPolicyCertificateProvider(nullptr);
}
}
void UserNetworkConfigurationUpdaterAsh::Shutdown() {
profile_observation_.Reset();
UserNetworkConfigurationUpdater::Shutdown();
}
// static
std::unique_ptr<UserNetworkConfigurationUpdaterAsh>
UserNetworkConfigurationUpdaterAsh::CreateForUserPolicy(
Profile* profile,
const user_manager::User& user,
PolicyService* policy_service,
ash::ManagedNetworkConfigurationHandler* network_config_handler) {
std::unique_ptr<UserNetworkConfigurationUpdaterAsh> updater(
new UserNetworkConfigurationUpdaterAsh(profile, user, policy_service,
network_config_handler));
updater->Init();
return updater;
}
void UserNetworkConfigurationUpdaterAsh::SetClientCertificateImporterForTest(
std::unique_ptr<ash::onc::CertificateImporter>
client_certificate_importer) {
SetClientCertificateImporter(std::move(client_certificate_importer));
}
// static
bool UserNetworkConfigurationUpdaterAsh::
PolicyHasWebTrustedAuthorityCertificate(const PolicyMap& policy_map) {
const base::Value* policy_value = policy_map.GetValue(
key::kOpenNetworkConfiguration, base::Value::Type::STRING);
if (!policy_value)
return false;
base::Value::List certificates_value;
chromeos::onc::ParseAndValidateOncForImport(
policy_value->GetString(), onc::ONC_SOURCE_USER_POLICY,
/*network_configs=*/nullptr, /*global_network_config=*/nullptr,
&certificates_value);
chromeos::onc::OncParsedCertificates onc_parsed_certificates(
certificates_value);
for (const auto& server_or_authority_cert :
onc_parsed_certificates.server_or_authority_certificates()) {
if (server_or_authority_cert.type() ==
chromeos::onc::OncParsedCertificates::ServerOrAuthorityCertificate::
Type::kAuthority &&
server_or_authority_cert.web_trust_requested()) {
return true;
}
}
return false;
}
UserNetworkConfigurationUpdaterAsh::UserNetworkConfigurationUpdaterAsh(
Profile* profile,
const user_manager::User& user,
PolicyService* policy_service,
ash::ManagedNetworkConfigurationHandler* network_config_handler)
: UserNetworkConfigurationUpdater(policy_service),
user_(&user),
network_config_handler_(network_config_handler) {
DCHECK(user_);
// The updater is created with |client_certificate_importer_| unset and is
// responsible for creating it. This requires |GetNSSCertDatabaseForProfile|
// call, which is not safe before the profile initialization is finalized.
// Thus, listen for OnProfileInitializationComplete notification, on which
// |cert_importer_| creation should start. https://crbug.com/171406
// TODO(crbug.com/40113187): Investigate if this is still required.
profile_observation_.Observe(profile);
// Make sure that the |NetworkCertLoader| which makes certificates available
// to the chromeos network code gets policy-pushed certificates from the
// primary profile. This assumes that a |UserNetworkConfigurationUpdaterAsh|
// is only created for the primary profile. NetworkCertLoader may be not
// initialized in tests.
if (ash::NetworkCertLoader::IsInitialized())
ash::NetworkCertLoader::Get()->SetUserPolicyCertificateProvider(this);
// Set profile-wide expansions for policy networks (i.e. those that apply to
// all networks in this profile). Note that this does currently not apply
// user-imported networks (through chrome://network) because those currently
// don't use the ManagedNetworkConfigurationHandler (b/235297258).
network_config_handler_->SetProfileWideVariableExpansions(
user.username_hash(), ash::onc::GetVariableExpansionsForUser(&user));
}
void UserNetworkConfigurationUpdaterAsh::ImportClientCertificates() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If certificate importer is not yet set, the import of client certificates
// will be re-triggered in SetClientCertificateImporter.
if (client_certificate_importer_) {
client_certificate_importer_->ImportClientCertificates(
GetClientCertificates(), base::DoNothing());
}
}
void UserNetworkConfigurationUpdaterAsh::ApplyNetworkPolicy(
const base::Value::List& network_configs_onc,
const base::Value::Dict& global_network_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(user_);
// Call on UserSessionManager to send the user's password to session manager
// if the password substitution variable exists in the ONC.
bool save_password =
ash::onc::HasUserPasswordSubstitutionVariable(network_configs_onc);
ash::UserSessionManager::GetInstance()->VoteForSavingLoginPassword(
ash::UserSessionManager::PasswordConsumingService::kNetwork,
save_password);
network_config_handler_->SetPolicy(onc_source_, user_->username_hash(),
network_configs_onc,
global_network_config);
}
void UserNetworkConfigurationUpdaterAsh::OnProfileInitializationComplete(
Profile* profile) {
DCHECK(profile_observation_.IsObservingSource(profile));
profile_observation_.Reset();
// Note: This unsafely grabs a persistent reference to the `NssService`'s
// `NSSCertDatabase`, which may be invalidated once `profile` is shut down.
// TODO(crbug.com/40753707): Provide better lifetime guarantees and
// pass the `NssCertDatabaseGetter` to the `CertificateImporterImpl`.
content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&GetNssCertDatabaseOnIOThread,
NssServiceFactory::GetForContext(profile)
->CreateNSSCertDatabaseGetterForIOThread(),
base::BindPostTaskToCurrentDefault(base::BindOnce(
&UserNetworkConfigurationUpdaterAsh::
CreateAndSetClientCertificateImporter,
weak_factory_.GetWeakPtr()))));
}
void UserNetworkConfigurationUpdaterAsh::CreateAndSetClientCertificateImporter(
net::NSSCertDatabase* database) {
DCHECK(database);
SetClientCertificateImporter(
std::make_unique<ash::onc::CertificateImporterImpl>(
content::GetIOThreadTaskRunner({}), database));
}
void UserNetworkConfigurationUpdaterAsh::SetClientCertificateImporter(
std::unique_ptr<ash::onc::CertificateImporter>
client_certificate_importer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool initial_client_certificate_importer =
client_certificate_importer_ == nullptr;
client_certificate_importer_ = std::move(client_certificate_importer);
if (initial_client_certificate_importer && !GetClientCertificates().empty()) {
client_certificate_importer_->ImportClientCertificates(
GetClientCertificates(), base::DoNothing());
}
}
} // namespace policy
|