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.h"
10 #include "base/bind_helpers.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
13 #include "chrome/browser/chromeos/profiles/profile_helper.h"
14 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_source.h"
22 #include "crypto/nss_util.h"
23 #include "crypto/nss_util_internal.h"
24 #include "crypto/rsa_private_key.h"
25 #include "crypto/scoped_nss_types.h"
26 #include "crypto/signature_creator.h"
28 namespace em = enterprise_management;
30 using content::BrowserThread;
36 scoped_refptr<OwnerKeyUtil>* g_owner_key_util_for_testing = NULL;
37 DeviceSettingsService* g_device_settings_service_for_testing = NULL;
39 // Assembles PolicyData based on |settings|, |policy_data| and
41 scoped_ptr<em::PolicyData> AssemblePolicy(
42 const std::string& user_id,
43 const em::PolicyData* policy_data,
44 const em::ChromeDeviceSettingsProto* settings) {
45 scoped_ptr<em::PolicyData> policy(new em::PolicyData());
47 // Preserve management settings.
48 if (policy_data->has_management_mode())
49 policy->set_management_mode(policy_data->management_mode());
50 if (policy_data->has_request_token())
51 policy->set_request_token(policy_data->request_token());
52 if (policy_data->has_device_id())
53 policy->set_device_id(policy_data->device_id());
55 // If there's no previous policy data, this is the first time the device
56 // setting is set. We set the management mode to NOT_MANAGED initially.
57 policy->set_management_mode(em::PolicyData::NOT_MANAGED);
59 policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
60 policy->set_timestamp(
61 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
62 policy->set_username(user_id);
63 if (!settings->SerializeToString(policy->mutable_policy_value()))
64 return scoped_ptr<em::PolicyData>();
69 std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
70 crypto::RSAPrivateKey* private_key) {
71 // Assemble the policy.
72 em::PolicyFetchResponse policy_response;
73 if (!policy->SerializeToString(policy_response.mutable_policy_data())) {
74 LOG(ERROR) << "Failed to encode policy payload.";
78 // Generate the signature.
79 scoped_ptr<crypto::SignatureCreator> signature_creator(
80 crypto::SignatureCreator::Create(private_key));
81 signature_creator->Update(
82 reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
83 policy_response.policy_data().size());
84 std::vector<uint8> signature_bytes;
85 std::string policy_blob;
86 if (!signature_creator->Final(&signature_bytes)) {
87 LOG(ERROR) << "Failed to create policy signature.";
91 policy_response.mutable_policy_data_signature()->assign(
92 reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
93 signature_bytes.size());
94 return policy_response.SerializeAsString();
97 void LoadPrivateKeyByPublicKey(
98 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
99 scoped_refptr<PublicKey> public_key,
100 const std::string& username_hash,
101 const base::Callback<void(scoped_refptr<PublicKey> public_key,
102 scoped_refptr<PrivateKey> private_key)>&
104 crypto::EnsureNSSInit();
105 crypto::ScopedPK11Slot slot =
106 crypto::GetPublicSlotForChromeOSUser(username_hash);
107 scoped_refptr<PrivateKey> private_key(new PrivateKey(
108 owner_key_util->FindPrivateKeyInSlot(public_key->data(), slot.get())));
109 BrowserThread::PostTask(BrowserThread::UI,
111 base::Bind(callback, public_key, private_key));
114 void LoadPrivateKey(const scoped_refptr<OwnerKeyUtil>& owner_key_util,
115 const std::string username_hash,
116 const base::Callback<void(
117 scoped_refptr<PublicKey> public_key,
118 scoped_refptr<PrivateKey> private_key)>& callback) {
119 std::vector<uint8> public_key_data;
120 scoped_refptr<PublicKey> public_key;
121 if (!owner_key_util->ImportPublicKey(&public_key_data)) {
122 scoped_refptr<PrivateKey> private_key;
123 BrowserThread::PostTask(BrowserThread::UI,
125 base::Bind(callback, public_key, private_key));
128 public_key = new PublicKey();
129 public_key->data().swap(public_key_data);
130 bool rv = BrowserThread::PostTask(BrowserThread::IO,
132 base::Bind(&LoadPrivateKeyByPublicKey,
138 // IO thread doesn't exists in unit tests, but it's safe to use NSS from
139 // BlockingPool in unit tests.
140 LoadPrivateKeyByPublicKey(
141 owner_key_util, public_key, username_hash, callback);
145 bool DoesPrivateKeyExistAsyncHelper(
146 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
147 std::vector<uint8> public_key;
148 if (!owner_key_util->ImportPublicKey(&public_key))
150 scoped_ptr<crypto::RSAPrivateKey> key(
151 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key));
152 bool is_owner = key.get() != NULL;
156 // Checks whether NSS slots with private key are mounted or
157 // not. Responds via |callback|.
158 void DoesPrivateKeyExistAsync(
159 const OwnerSettingsService::IsOwnerCallback& callback) {
160 scoped_refptr<OwnerKeyUtil> owner_key_util;
161 if (g_owner_key_util_for_testing)
162 owner_key_util = *g_owner_key_util_for_testing;
164 owner_key_util = OwnerKeyUtil::Create();
165 scoped_refptr<base::TaskRunner> task_runner =
166 content::BrowserThread::GetBlockingPool()
167 ->GetTaskRunnerWithShutdownBehavior(
168 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
169 base::PostTaskAndReplyWithResult(
172 base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
176 // Returns the current management mode.
177 em::PolicyData::ManagementMode GetManagementMode(
178 DeviceSettingsService* service) {
180 LOG(ERROR) << "DeviceSettingsService is not initialized";
181 return em::PolicyData::NOT_MANAGED;
184 const em::PolicyData* policy_data = service->policy_data();
185 if (policy_data && policy_data->has_management_mode())
186 return policy_data->management_mode();
187 return em::PolicyData::NOT_MANAGED;
190 // Returns true if it is okay to transfer from the current mode to the new
191 // mode. This function should be called in SetManagementMode().
192 bool CheckManagementModeTransition(em::PolicyData::ManagementMode current_mode,
193 em::PolicyData::ManagementMode new_mode) {
194 // Mode is not changed.
195 if (current_mode == new_mode)
198 switch (current_mode) {
199 case em::PolicyData::NOT_MANAGED:
200 // For consumer management enrollment.
201 return new_mode == em::PolicyData::CONSUMER_MANAGED;
203 case em::PolicyData::ENTERPRISE_MANAGED:
204 // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
207 case em::PolicyData::CONSUMER_MANAGED:
208 // For consumer management unenrollment.
209 return new_mode == em::PolicyData::NOT_MANAGED;
218 OwnerSettingsService::OwnerSettingsService(Profile* profile)
220 owner_key_util_(OwnerKeyUtil::Create()),
221 waiting_for_profile_creation_(true),
222 waiting_for_tpm_token_(true),
223 weak_factory_(this) {
224 if (TPMTokenLoader::IsInitialized()) {
225 waiting_for_tpm_token_ = !TPMTokenLoader::Get()->IsTPMTokenReady();
226 TPMTokenLoader::Get()->AddObserver(this);
229 if (DBusThreadManager::IsInitialized() &&
230 DBusThreadManager::Get()->GetSessionManagerClient()) {
231 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
235 chrome::NOTIFICATION_PROFILE_CREATED,
236 content::Source<Profile>(profile_));
239 OwnerSettingsService::~OwnerSettingsService() {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 if (TPMTokenLoader::IsInitialized())
242 TPMTokenLoader::Get()->RemoveObserver(this);
244 if (DBusThreadManager::IsInitialized() &&
245 DBusThreadManager::Get()->GetSessionManagerClient()) {
246 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
250 bool OwnerSettingsService::IsOwner() {
251 DCHECK(thread_checker_.CalledOnValidThread());
252 return private_key_ && private_key_->key();
255 void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) {
256 DCHECK(thread_checker_.CalledOnValidThread());
258 base::MessageLoop::current()->PostTask(FROM_HERE,
259 base::Bind(callback, IsOwner()));
261 pending_is_owner_callbacks_.push_back(callback);
265 bool OwnerSettingsService::AssembleAndSignPolicyAsync(
266 scoped_ptr<em::PolicyData> policy,
267 const AssembleAndSignPolicyCallback& callback) {
268 DCHECK(thread_checker_.CalledOnValidThread());
271 base::PostTaskAndReplyWithResult(
272 BrowserThread::GetBlockingPool(),
275 &AssembleAndSignPolicy, base::Passed(&policy), private_key_->key()),
280 void OwnerSettingsService::SignAndStoreAsync(
281 scoped_ptr<em::ChromeDeviceSettingsProto> settings,
282 const base::Closure& callback) {
283 DCHECK(thread_checker_.CalledOnValidThread());
284 scoped_ptr<em::PolicyData> policy = AssemblePolicy(
285 user_id_, GetDeviceSettingsService()->policy_data(), settings.get());
287 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
291 EnqueueSignAndStore(policy.Pass(), callback);
294 void OwnerSettingsService::SetManagementSettingsAsync(
295 em::PolicyData::ManagementMode management_mode,
296 const std::string& request_token,
297 const std::string& device_id,
298 const base::Closure& callback) {
299 em::PolicyData::ManagementMode current_mode =
300 GetManagementMode(GetDeviceSettingsService());
301 if (!CheckManagementModeTransition(current_mode, management_mode)) {
302 LOG(ERROR) << "Invalid management mode transition: current mode = "
303 << current_mode << ", new mode = " << management_mode;
304 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
308 DeviceSettingsService* service = GetDeviceSettingsService();
309 scoped_ptr<em::PolicyData> policy = AssemblePolicy(
310 user_id_, service->policy_data(), service->device_settings());
312 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
316 policy->set_management_mode(management_mode);
317 policy->set_request_token(request_token);
318 policy->set_device_id(device_id);
320 EnqueueSignAndStore(policy.Pass(), callback);
323 void OwnerSettingsService::Observe(
325 const content::NotificationSource& source,
326 const content::NotificationDetails& details) {
327 DCHECK(thread_checker_.CalledOnValidThread());
328 if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
333 Profile* profile = content::Source<Profile>(source).ptr();
334 if (profile != profile_) {
339 waiting_for_profile_creation_ = false;
343 void OwnerSettingsService::OnTPMTokenReady() {
344 DCHECK(thread_checker_.CalledOnValidThread());
345 waiting_for_tpm_token_ = false;
347 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
348 // determine ownership. Force a reload once we know these are initialized.
352 void OwnerSettingsService::OwnerKeySet(bool success) {
353 DCHECK(thread_checker_.CalledOnValidThread());
359 void OwnerSettingsService::IsOwnerForSafeModeAsync(
360 const std::string& user_id,
361 const std::string& user_hash,
362 const IsOwnerCallback& callback) {
363 CHECK(chromeos::LoginState::Get()->IsInSafeMode());
365 // Make sure NSS is initialized and NSS DB is loaded for the user before
366 // searching for the owner key.
367 BrowserThread::PostTaskAndReply(
370 base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
373 ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
374 base::Bind(&DoesPrivateKeyExistAsync, callback));
378 void OwnerSettingsService::SetOwnerKeyUtilForTesting(
379 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
381 if (g_owner_key_util_for_testing) {
382 delete g_owner_key_util_for_testing;
383 g_owner_key_util_for_testing = NULL;
385 if (owner_key_util.get()) {
386 g_owner_key_util_for_testing = new scoped_refptr<OwnerKeyUtil>();
387 *g_owner_key_util_for_testing = owner_key_util;
392 void OwnerSettingsService::SetDeviceSettingsServiceForTesting(
393 DeviceSettingsService* device_settings_service) {
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 g_device_settings_service_for_testing = device_settings_service;
398 void OwnerSettingsService::ReloadPrivateKey() {
399 DCHECK(thread_checker_.CalledOnValidThread());
400 if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
402 scoped_refptr<base::TaskRunner> task_runner =
403 content::BrowserThread::GetBlockingPool()
404 ->GetTaskRunnerWithShutdownBehavior(
405 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
406 task_runner->PostTask(
408 base::Bind(&LoadPrivateKey,
410 ProfileHelper::GetUserIdHashFromProfile(profile_),
411 base::Bind(&OwnerSettingsService::OnPrivateKeyLoaded,
412 weak_factory_.GetWeakPtr())));
415 void OwnerSettingsService::OnPrivateKeyLoaded(
416 scoped_refptr<PublicKey> public_key,
417 scoped_refptr<PrivateKey> private_key) {
418 DCHECK(thread_checker_.CalledOnValidThread());
419 public_key_ = public_key;
420 private_key_ = private_key;
422 user_id_ = profile_->GetProfileName();
423 if (user_id_ == OwnerSettingsServiceFactory::GetInstance()->GetUsername())
424 GetDeviceSettingsService()->InitOwner(user_id_, weak_factory_.GetWeakPtr());
426 std::vector<IsOwnerCallback> is_owner_callbacks;
427 is_owner_callbacks.swap(pending_is_owner_callbacks_);
428 const bool is_owner = IsOwner();
429 for (std::vector<IsOwnerCallback>::iterator it(is_owner_callbacks.begin());
430 it != is_owner_callbacks.end();
436 void OwnerSettingsService::EnqueueSignAndStore(
437 scoped_ptr<em::PolicyData> policy,
438 const base::Closure& callback) {
439 SignAndStoreSettingsOperation* operation = new SignAndStoreSettingsOperation(
440 base::Bind(&OwnerSettingsService::HandleCompletedOperation,
441 weak_factory_.GetWeakPtr(),
444 operation->set_delegate(weak_factory_.GetWeakPtr());
445 pending_operations_.push_back(operation);
446 if (pending_operations_.front() == operation)
447 StartNextOperation();
450 void OwnerSettingsService::StartNextOperation() {
451 DeviceSettingsService* service = GetDeviceSettingsService();
452 if (!pending_operations_.empty() && service &&
453 service->session_manager_client()) {
454 pending_operations_.front()->Start(
455 service->session_manager_client(), GetOwnerKeyUtil(), public_key_);
459 void OwnerSettingsService::HandleCompletedOperation(
460 const base::Closure& callback,
461 SessionManagerOperation* operation,
462 DeviceSettingsService::Status status) {
463 DCHECK_EQ(operation, pending_operations_.front());
465 DeviceSettingsService* service = GetDeviceSettingsService();
466 if (status == DeviceSettingsService::STORE_SUCCESS) {
467 service->set_policy_data(operation->policy_data().Pass());
468 service->set_device_settings(operation->device_settings().Pass());
471 if ((operation->public_key() && !public_key_) ||
472 (operation->public_key() && public_key_ &&
473 operation->public_key()->data() != public_key_->data())) {
474 // Public part changed so we need to reload private part too.
476 content::NotificationService::current()->Notify(
477 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
478 content::Source<OwnerSettingsService>(this),
479 content::NotificationService::NoDetails());
481 service->OnSignAndStoreOperationCompleted(status);
482 if (!callback.is_null())
485 pending_operations_.pop_front();
487 StartNextOperation();
490 void OwnerSettingsService::HandleError(DeviceSettingsService::Status status,
491 const base::Closure& callback) {
492 LOG(ERROR) << "Session manager operation failed: " << status;
493 GetDeviceSettingsService()->OnSignAndStoreOperationCompleted(status);
494 if (!callback.is_null())
498 scoped_refptr<OwnerKeyUtil> OwnerSettingsService::GetOwnerKeyUtil() {
499 DCHECK(thread_checker_.CalledOnValidThread());
500 if (g_owner_key_util_for_testing)
501 return *g_owner_key_util_for_testing;
502 return owner_key_util_;
505 DeviceSettingsService* OwnerSettingsService::GetDeviceSettingsService() {
506 DCHECK(thread_checker_.CalledOnValidThread());
507 if (g_device_settings_service_for_testing)
508 return g_device_settings_service_for_testing;
509 if (DeviceSettingsService::IsInitialized())
510 return DeviceSettingsService::Get();
514 } // namespace chromeos