1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/threading/thread_checker.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/chromeos/settings/cros_settings.h"
18 #include "chrome/browser/chromeos/settings/device_settings_provider.h"
19 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chromeos/dbus/dbus_thread_manager.h"
22 #include "chromeos/tpm_token_loader.h"
23 #include "components/ownership/owner_key_util.h"
24 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/notification_source.h"
29 #include "content/public/common/content_switches.h"
30 #include "crypto/nss_util.h"
31 #include "crypto/nss_util_internal.h"
32 #include "crypto/rsa_private_key.h"
33 #include "crypto/scoped_nss_types.h"
34 #include "crypto/signature_creator.h"
36 namespace em = enterprise_management;
38 using content::BrowserThread;
39 using ownership::OwnerKeyUtil;
40 using ownership::PrivateKey;
41 using ownership::PublicKey;
47 bool IsOwnerInTests(const std::string& user_id) {
48 if (user_id.empty() ||
49 !CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType) ||
50 !CrosSettings::IsInitialized()) {
53 const base::Value* value = CrosSettings::Get()->GetPref(kDeviceOwner);
54 if (!value || value->GetType() != base::Value::TYPE_STRING)
56 return static_cast<const base::StringValue*>(value)->GetString() == user_id;
59 void LoadPrivateKeyByPublicKey(
60 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
61 scoped_refptr<PublicKey> public_key,
62 const std::string& username_hash,
63 const base::Callback<void(const scoped_refptr<PublicKey>& public_key,
64 const scoped_refptr<PrivateKey>& private_key)>&
66 crypto::EnsureNSSInit();
67 crypto::ScopedPK11Slot public_slot =
68 crypto::GetPublicSlotForChromeOSUser(username_hash);
69 crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser(
70 username_hash, base::Callback<void(crypto::ScopedPK11Slot)>());
72 // If private slot is already available, this will check it. If not,
73 // we'll get called again later when the TPM Token is ready, and the
74 // slot will be available then.
75 scoped_refptr<PrivateKey> private_key(
76 new PrivateKey(owner_key_util->FindPrivateKeyInSlot(public_key->data(),
77 private_slot.get())));
78 if (!private_key->key()) {
79 private_key = new PrivateKey(owner_key_util->FindPrivateKeyInSlot(
80 public_key->data(), public_slot.get()));
82 BrowserThread::PostTask(BrowserThread::UI,
84 base::Bind(callback, public_key, private_key));
88 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
89 const std::string username_hash,
90 const base::Callback<void(const scoped_refptr<PublicKey>& public_key,
91 const scoped_refptr<PrivateKey>& private_key)>&
93 std::vector<uint8> public_key_data;
94 scoped_refptr<PublicKey> public_key;
95 if (!owner_key_util->ImportPublicKey(&public_key_data)) {
96 scoped_refptr<PrivateKey> private_key;
97 BrowserThread::PostTask(BrowserThread::UI,
99 base::Bind(callback, public_key, private_key));
102 public_key = new PublicKey();
103 public_key->data().swap(public_key_data);
104 bool rv = BrowserThread::PostTask(BrowserThread::IO,
106 base::Bind(&LoadPrivateKeyByPublicKey,
112 // IO thread doesn't exists in unit tests, but it's safe to use NSS from
113 // BlockingPool in unit tests.
114 LoadPrivateKeyByPublicKey(
115 owner_key_util, public_key, username_hash, callback);
119 bool DoesPrivateKeyExistAsyncHelper(
120 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
121 std::vector<uint8> public_key;
122 if (!owner_key_util->ImportPublicKey(&public_key))
124 scoped_ptr<crypto::RSAPrivateKey> key(
125 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key));
126 bool is_owner = key.get() != NULL;
130 // Checks whether NSS slots with private key are mounted or
131 // not. Responds via |callback|.
132 void DoesPrivateKeyExistAsync(
133 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
134 const OwnerSettingsServiceChromeOS::IsOwnerCallback& callback) {
135 if (!owner_key_util.get()) {
139 scoped_refptr<base::TaskRunner> task_runner =
140 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
141 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
142 base::PostTaskAndReplyWithResult(
145 base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
151 OwnerSettingsServiceChromeOS::OwnerSettingsServiceChromeOS(
152 DeviceSettingsService* device_settings_service,
154 const scoped_refptr<OwnerKeyUtil>& owner_key_util)
155 : ownership::OwnerSettingsService(owner_key_util),
156 device_settings_service_(device_settings_service),
158 waiting_for_profile_creation_(true),
159 waiting_for_tpm_token_(true),
161 store_settings_factory_(this) {
162 if (TPMTokenLoader::IsInitialized()) {
163 TPMTokenLoader::TPMTokenStatus tpm_token_status =
164 TPMTokenLoader::Get()->IsTPMTokenEnabled(
165 base::Bind(&OwnerSettingsServiceChromeOS::OnTPMTokenReady,
166 weak_factory_.GetWeakPtr()));
167 waiting_for_tpm_token_ =
168 tpm_token_status == TPMTokenLoader::TPM_TOKEN_STATUS_UNDETERMINED;
171 if (DBusThreadManager::IsInitialized() &&
172 DBusThreadManager::Get()->GetSessionManagerClient()) {
173 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
176 if (device_settings_service_)
177 device_settings_service_->AddObserver(this);
180 chrome::NOTIFICATION_PROFILE_CREATED,
181 content::Source<Profile>(profile_));
184 OwnerSettingsServiceChromeOS::~OwnerSettingsServiceChromeOS() {
185 DCHECK(thread_checker_.CalledOnValidThread());
187 if (device_settings_service_)
188 device_settings_service_->RemoveObserver(this);
190 if (DBusThreadManager::IsInitialized() &&
191 DBusThreadManager::Get()->GetSessionManagerClient()) {
192 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
196 void OwnerSettingsServiceChromeOS::OnTPMTokenReady(
197 bool /* tpm_token_enabled */) {
198 DCHECK(thread_checker_.CalledOnValidThread());
199 waiting_for_tpm_token_ = false;
201 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
202 // determine ownership. Force a reload once we know these are initialized.
206 bool OwnerSettingsServiceChromeOS::HandlesSetting(const std::string& setting) {
207 return DeviceSettingsProvider::IsDeviceSetting(setting);
210 bool OwnerSettingsServiceChromeOS::Set(const std::string& setting,
211 const base::Value& value) {
212 if (!IsOwner() && !IsOwnerInTests(user_id_))
215 pending_changes_.add(setting, make_scoped_ptr(value.DeepCopy()));
217 em::ChromeDeviceSettingsProto settings;
218 if (tentative_settings_.get()) {
219 settings = *tentative_settings_;
220 } else if (device_settings_service_->status() ==
221 DeviceSettingsService::STORE_SUCCESS &&
222 device_settings_service_->device_settings()) {
223 settings = *device_settings_service_->device_settings();
225 UpdateDeviceSettings(setting, value, settings);
226 em::PolicyData policy_data;
227 policy_data.set_username(user_id_);
228 CHECK(settings.SerializeToString(policy_data.mutable_policy_value()));
229 FOR_EACH_OBSERVER(OwnerSettingsService::Observer, observers_,
230 OnTentativeChangesInPolicy(policy_data));
231 StorePendingChanges();
235 bool OwnerSettingsServiceChromeOS::CommitTentativeDeviceSettings(
236 scoped_ptr<enterprise_management::PolicyData> policy) {
237 if (!IsOwner() && !IsOwnerInTests(user_id_))
239 if (policy->username() != user_id_) {
240 LOG(ERROR) << "Username mismatch: " << policy->username() << " vs. "
244 tentative_settings_.reset(new em::ChromeDeviceSettingsProto);
245 CHECK(tentative_settings_->ParseFromString(policy->policy_value()));
246 StorePendingChanges();
250 void OwnerSettingsServiceChromeOS::Observe(
252 const content::NotificationSource& source,
253 const content::NotificationDetails& details) {
254 DCHECK(thread_checker_.CalledOnValidThread());
255 if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
260 Profile* profile = content::Source<Profile>(source).ptr();
261 if (profile != profile_) {
266 waiting_for_profile_creation_ = false;
270 void OwnerSettingsServiceChromeOS::OwnerKeySet(bool success) {
271 DCHECK(thread_checker_.CalledOnValidThread());
276 void OwnerSettingsServiceChromeOS::OwnershipStatusChanged() {
277 DCHECK(thread_checker_.CalledOnValidThread());
278 StorePendingChanges();
281 void OwnerSettingsServiceChromeOS::DeviceSettingsUpdated() {
282 DCHECK(thread_checker_.CalledOnValidThread());
283 StorePendingChanges();
286 void OwnerSettingsServiceChromeOS::OnDeviceSettingsServiceShutdown() {
287 device_settings_service_ = nullptr;
291 void OwnerSettingsServiceChromeOS::IsOwnerForSafeModeAsync(
292 const std::string& user_hash,
293 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
294 const IsOwnerCallback& callback) {
295 CHECK(chromeos::LoginState::Get()->IsInSafeMode());
297 // Make sure NSS is initialized and NSS DB is loaded for the user before
298 // searching for the owner key.
299 BrowserThread::PostTaskAndReply(
302 base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
304 ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
305 base::Bind(&DoesPrivateKeyExistAsync, owner_key_util, callback));
309 scoped_ptr<em::PolicyData> OwnerSettingsServiceChromeOS::AssemblePolicy(
310 const std::string& user_id,
311 const em::PolicyData* policy_data,
312 const em::ChromeDeviceSettingsProto* settings) {
313 scoped_ptr<em::PolicyData> policy(new em::PolicyData());
315 // Preserve management settings.
316 if (policy_data->has_management_mode())
317 policy->set_management_mode(policy_data->management_mode());
318 if (policy_data->has_request_token())
319 policy->set_request_token(policy_data->request_token());
320 if (policy_data->has_device_id())
321 policy->set_device_id(policy_data->device_id());
323 // If there's no previous policy data, this is the first time the device
324 // setting is set. We set the management mode to NOT_MANAGED initially.
325 policy->set_management_mode(em::PolicyData::NOT_MANAGED);
327 policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
328 policy->set_timestamp(
329 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
330 policy->set_username(user_id);
331 if (!settings->SerializeToString(policy->mutable_policy_value()))
332 return scoped_ptr<em::PolicyData>();
334 return policy.Pass();
338 void OwnerSettingsServiceChromeOS::UpdateDeviceSettings(
339 const std::string& path,
340 const base::Value& value,
341 enterprise_management::ChromeDeviceSettingsProto& settings) {
342 if (path == kAccountsPrefAllowNewUser) {
343 em::AllowNewUsersProto* allow = settings.mutable_allow_new_users();
345 if (value.GetAsBoolean(&allow_value)) {
346 allow->set_allow_new_users(allow_value);
350 } else if (path == kAccountsPrefAllowGuest) {
351 em::GuestModeEnabledProto* guest = settings.mutable_guest_mode_enabled();
353 if (value.GetAsBoolean(&guest_value))
354 guest->set_guest_mode_enabled(guest_value);
357 } else if (path == kAccountsPrefSupervisedUsersEnabled) {
358 em::SupervisedUsersSettingsProto* supervised =
359 settings.mutable_supervised_users_settings();
360 bool supervised_value;
361 if (value.GetAsBoolean(&supervised_value))
362 supervised->set_supervised_users_enabled(supervised_value);
365 } else if (path == kAccountsPrefShowUserNamesOnSignIn) {
366 em::ShowUserNamesOnSigninProto* show = settings.mutable_show_user_names();
368 if (value.GetAsBoolean(&show_value))
369 show->set_show_user_names(show_value);
372 } else if (path == kAccountsPrefDeviceLocalAccounts) {
373 em::DeviceLocalAccountsProto* device_local_accounts =
374 settings.mutable_device_local_accounts();
375 device_local_accounts->clear_account();
376 const base::ListValue* accounts_list = NULL;
377 if (value.GetAsList(&accounts_list)) {
378 for (base::ListValue::const_iterator entry(accounts_list->begin());
379 entry != accounts_list->end();
381 const base::DictionaryValue* entry_dict = NULL;
382 if ((*entry)->GetAsDictionary(&entry_dict)) {
383 em::DeviceLocalAccountInfoProto* account =
384 device_local_accounts->add_account();
385 std::string account_id;
386 if (entry_dict->GetStringWithoutPathExpansion(
387 kAccountsPrefDeviceLocalAccountsKeyId, &account_id)) {
388 account->set_account_id(account_id);
391 if (entry_dict->GetIntegerWithoutPathExpansion(
392 kAccountsPrefDeviceLocalAccountsKeyType, &type)) {
394 static_cast<em::DeviceLocalAccountInfoProto::AccountType>(
397 std::string kiosk_app_id;
398 if (entry_dict->GetStringWithoutPathExpansion(
399 kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
401 account->mutable_kiosk_app()->set_app_id(kiosk_app_id);
403 std::string kiosk_app_update_url;
404 if (entry_dict->GetStringWithoutPathExpansion(
405 kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL,
406 &kiosk_app_update_url)) {
407 account->mutable_kiosk_app()->set_update_url(kiosk_app_update_url);
416 } else if (path == kAccountsPrefDeviceLocalAccountAutoLoginId) {
417 em::DeviceLocalAccountsProto* device_local_accounts =
418 settings.mutable_device_local_accounts();
420 if (value.GetAsString(&id))
421 device_local_accounts->set_auto_login_id(id);
424 } else if (path == kAccountsPrefDeviceLocalAccountAutoLoginDelay) {
425 em::DeviceLocalAccountsProto* device_local_accounts =
426 settings.mutable_device_local_accounts();
428 if (value.GetAsInteger(&delay))
429 device_local_accounts->set_auto_login_delay(delay);
432 } else if (path == kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled) {
433 em::DeviceLocalAccountsProto* device_local_accounts =
434 settings.mutable_device_local_accounts();
436 if (value.GetAsBoolean(&enabled))
437 device_local_accounts->set_enable_auto_login_bailout(enabled);
441 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline) {
442 em::DeviceLocalAccountsProto* device_local_accounts =
443 settings.mutable_device_local_accounts();
445 if (value.GetAsBoolean(&should_prompt))
446 device_local_accounts->set_prompt_for_network_when_offline(should_prompt);
449 } else if (path == kSignedDataRoamingEnabled) {
450 em::DataRoamingEnabledProto* roam = settings.mutable_data_roaming_enabled();
451 bool roaming_value = false;
452 if (value.GetAsBoolean(&roaming_value))
453 roam->set_data_roaming_enabled(roaming_value);
456 } else if (path == kReleaseChannel) {
457 em::ReleaseChannelProto* release_channel =
458 settings.mutable_release_channel();
459 std::string channel_value;
460 if (value.GetAsString(&channel_value))
461 release_channel->set_release_channel(channel_value);
464 } else if (path == kStatsReportingPref) {
465 em::MetricsEnabledProto* metrics = settings.mutable_metrics_enabled();
466 bool metrics_value = false;
467 if (value.GetAsBoolean(&metrics_value))
468 metrics->set_metrics_enabled(metrics_value);
471 } else if (path == kAccountsPrefUsers) {
472 em::UserWhitelistProto* whitelist_proto = settings.mutable_user_whitelist();
473 whitelist_proto->clear_user_whitelist();
474 const base::ListValue* users;
475 if (value.GetAsList(&users)) {
476 for (base::ListValue::const_iterator i = users->begin();
480 if ((*i)->GetAsString(&email))
481 whitelist_proto->add_user_whitelist(email);
484 } else if (path == kAccountsPrefEphemeralUsersEnabled) {
485 em::EphemeralUsersEnabledProto* ephemeral_users_enabled =
486 settings.mutable_ephemeral_users_enabled();
487 bool ephemeral_users_enabled_value = false;
488 if (value.GetAsBoolean(&ephemeral_users_enabled_value)) {
489 ephemeral_users_enabled->set_ephemeral_users_enabled(
490 ephemeral_users_enabled_value);
494 } else if (path == kAllowRedeemChromeOsRegistrationOffers) {
495 em::AllowRedeemChromeOsRegistrationOffersProto* allow_redeem_offers =
496 settings.mutable_allow_redeem_offers();
497 bool allow_redeem_offers_value;
498 if (value.GetAsBoolean(&allow_redeem_offers_value)) {
499 allow_redeem_offers->set_allow_redeem_offers(allow_redeem_offers_value);
503 } else if (path == kStartUpFlags) {
504 em::StartUpFlagsProto* flags_proto = settings.mutable_start_up_flags();
505 flags_proto->Clear();
506 const base::ListValue* flags;
507 if (value.GetAsList(&flags)) {
508 for (base::ListValue::const_iterator i = flags->begin();
512 if ((*i)->GetAsString(&flag))
513 flags_proto->add_flags(flag);
516 } else if (path == kSystemUse24HourClock) {
517 em::SystemUse24HourClockProto* use_24hour_clock_proto =
518 settings.mutable_use_24hour_clock();
519 use_24hour_clock_proto->Clear();
520 bool use_24hour_clock_value;
521 if (value.GetAsBoolean(&use_24hour_clock_value)) {
522 use_24hour_clock_proto->set_use_24hour_clock(use_24hour_clock_value);
526 } else if (path == kAttestationForContentProtectionEnabled) {
527 em::AttestationSettingsProto* attestation_settings =
528 settings.mutable_attestation_settings();
529 bool setting_enabled;
530 if (value.GetAsBoolean(&setting_enabled)) {
531 attestation_settings->set_content_protection_enabled(setting_enabled);
536 // The remaining settings don't support Set(), since they are not
537 // intended to be customizable by the user:
538 // kAccountsPrefTransferSAMLCookies
540 // kDeviceAttestationEnabled
542 // kIdleLogoutTimeout
543 // kIdleLogoutWarningDuration
544 // kReleaseChannelDelegated
545 // kReportDeviceActivityTimes
546 // kReportDeviceBootMode
547 // kReportDeviceLocation
548 // kReportDeviceVersionInfo
549 // kReportDeviceNetworkInterfaces
550 // kReportDeviceUsers
551 // kScreenSaverExtensionId
552 // kScreenSaverTimeout
553 // kServiceAccountIdentity
555 // kSystemTimezonePolicy
556 // kVariationsRestrictParameter
558 // kDeviceDisabledMessage
560 LOG(FATAL) << "Device setting " << path << " is read-only.";
564 void OwnerSettingsServiceChromeOS::OnPostKeypairLoadedActions() {
565 DCHECK(thread_checker_.CalledOnValidThread());
567 user_id_ = profile_->GetProfileName();
568 const bool is_owner = IsOwner() || IsOwnerInTests(user_id_);
569 if (is_owner && device_settings_service_)
570 device_settings_service_->InitOwner(user_id_, weak_factory_.GetWeakPtr());
573 void OwnerSettingsServiceChromeOS::ReloadKeypairImpl(const base::Callback<
574 void(const scoped_refptr<PublicKey>& public_key,
575 const scoped_refptr<PrivateKey>& private_key)>& callback) {
576 DCHECK(thread_checker_.CalledOnValidThread());
578 if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
580 scoped_refptr<base::TaskRunner> task_runner =
581 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
582 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
583 task_runner->PostTask(
585 base::Bind(&LoadPrivateKey,
587 ProfileHelper::GetUserIdHashFromProfile(profile_),
591 void OwnerSettingsServiceChromeOS::StorePendingChanges() {
592 if (!has_pending_changes() || store_settings_factory_.HasWeakPtrs() ||
593 !device_settings_service_) {
597 em::ChromeDeviceSettingsProto settings;
598 if (tentative_settings_.get()) {
599 settings.Swap(tentative_settings_.get());
600 tentative_settings_.reset();
601 } else if (device_settings_service_->status() ==
602 DeviceSettingsService::STORE_SUCCESS &&
603 device_settings_service_->device_settings()) {
604 settings = *device_settings_service_->device_settings();
609 for (const auto& change : pending_changes_)
610 UpdateDeviceSettings(change.first, *change.second, settings);
611 pending_changes_.clear();
613 scoped_ptr<em::PolicyData> policy = AssemblePolicy(
614 user_id_, device_settings_service_->policy_data(), &settings);
615 bool rv = AssembleAndSignPolicyAsync(
616 content::BrowserThread::GetBlockingPool(), policy.Pass(),
617 base::Bind(&OwnerSettingsServiceChromeOS::OnPolicyAssembledAndSigned,
618 store_settings_factory_.GetWeakPtr()));
620 OnSignedPolicyStored(false /* success */);
623 void OwnerSettingsServiceChromeOS::OnPolicyAssembledAndSigned(
624 scoped_ptr<em::PolicyFetchResponse> policy_response) {
625 if (!policy_response.get() || !device_settings_service_) {
626 OnSignedPolicyStored(false /* success */);
629 device_settings_service_->Store(
630 policy_response.Pass(),
631 base::Bind(&OwnerSettingsServiceChromeOS::OnSignedPolicyStored,
632 store_settings_factory_.GetWeakPtr(),
633 true /* success */));
636 void OwnerSettingsServiceChromeOS::OnSignedPolicyStored(bool success) {
637 store_settings_factory_.InvalidateWeakPtrs();
638 FOR_EACH_OBSERVER(OwnerSettingsService::Observer,
640 OnSignedPolicyStored(success));
641 StorePendingChanges();
644 } // namespace chromeos