Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: chrome/browser/chromeos/ownership/owner_settings_service.cc

Issue 548323003: Non-plafrom-specific part of an OwnerSettingsService is moved to components/ownership/*. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes to *.gypi and *.gn files. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/chromeos/ownership/owner_settings_service.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/prefs/pref_service.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/chromeos/profiles/profile_helper.h"
15 #include "chrome/browser/chromeos/settings/cros_settings.h"
16 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/tpm_token_loader.h"
20 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/notification_details.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/common/content_switches.h"
26 #include "crypto/nss_util.h"
27 #include "crypto/nss_util_internal.h"
28 #include "crypto/rsa_private_key.h"
29 #include "crypto/scoped_nss_types.h"
30 #include "crypto/signature_creator.h"
31
32 namespace em = enterprise_management;
33
34 using content::BrowserThread;
35 using ownership::OwnerKeyUtil;
36 using ownership::PrivateKey;
37 using ownership::PublicKey;
38
39 namespace chromeos {
40
41 namespace {
42
43 DeviceSettingsService* g_device_settings_service_for_testing = NULL;
44
45 bool IsOwnerInTests(const std::string& user_id) {
46 if (user_id.empty() ||
47 !CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType) ||
48 !CrosSettings::IsInitialized()) {
49 return false;
50 }
51 const base::Value* value = CrosSettings::Get()->GetPref(kDeviceOwner);
52 if (!value || value->GetType() != base::Value::TYPE_STRING)
53 return false;
54 return static_cast<const base::StringValue*>(value)->GetString() == user_id;
55 }
56
57 // Assembles PolicyData based on |settings|, |policy_data| and
58 // |user_id|.
59 scoped_ptr<em::PolicyData> AssemblePolicy(
60 const std::string& user_id,
61 const em::PolicyData* policy_data,
62 const em::ChromeDeviceSettingsProto* settings) {
63 scoped_ptr<em::PolicyData> policy(new em::PolicyData());
64 if (policy_data) {
65 // Preserve management settings.
66 if (policy_data->has_management_mode())
67 policy->set_management_mode(policy_data->management_mode());
68 if (policy_data->has_request_token())
69 policy->set_request_token(policy_data->request_token());
70 if (policy_data->has_device_id())
71 policy->set_device_id(policy_data->device_id());
72 } else {
73 // If there's no previous policy data, this is the first time the device
74 // setting is set. We set the management mode to NOT_MANAGED initially.
75 policy->set_management_mode(em::PolicyData::NOT_MANAGED);
76 }
77 policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
78 policy->set_timestamp(
79 (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds());
80 policy->set_username(user_id);
81 if (!settings->SerializeToString(policy->mutable_policy_value()))
82 return scoped_ptr<em::PolicyData>();
83
84 return policy.Pass();
85 }
86
87 std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
88 crypto::RSAPrivateKey* private_key) {
89 // Assemble the policy.
90 em::PolicyFetchResponse policy_response;
91 if (!policy->SerializeToString(policy_response.mutable_policy_data())) {
92 LOG(ERROR) << "Failed to encode policy payload.";
93 return std::string();
94 }
95
96 // Generate the signature.
97 scoped_ptr<crypto::SignatureCreator> signature_creator(
98 crypto::SignatureCreator::Create(private_key));
99 signature_creator->Update(
100 reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
101 policy_response.policy_data().size());
102 std::vector<uint8> signature_bytes;
103 std::string policy_blob;
104 if (!signature_creator->Final(&signature_bytes)) {
105 LOG(ERROR) << "Failed to create policy signature.";
106 return std::string();
107 }
108
109 policy_response.mutable_policy_data_signature()->assign(
110 reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
111 signature_bytes.size());
112 return policy_response.SerializeAsString();
113 }
114
115 void LoadPrivateKeyByPublicKey(
116 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
117 scoped_refptr<PublicKey> public_key,
118 const std::string& username_hash,
119 const base::Callback<void(scoped_refptr<PublicKey> public_key,
120 scoped_refptr<PrivateKey> private_key)>&
121 callback) {
122 crypto::EnsureNSSInit();
123 crypto::ScopedPK11Slot slot =
124 crypto::GetPublicSlotForChromeOSUser(username_hash);
125 scoped_refptr<PrivateKey> private_key(new PrivateKey(
126 owner_key_util->FindPrivateKeyInSlot(public_key->data(), slot.get())));
127 BrowserThread::PostTask(BrowserThread::UI,
128 FROM_HERE,
129 base::Bind(callback, public_key, private_key));
130 }
131
132 void LoadPrivateKey(const scoped_refptr<OwnerKeyUtil>& owner_key_util,
133 const std::string username_hash,
134 const base::Callback<void(
135 scoped_refptr<PublicKey> public_key,
136 scoped_refptr<PrivateKey> private_key)>& callback) {
137 std::vector<uint8> public_key_data;
138 scoped_refptr<PublicKey> public_key;
139 if (!owner_key_util->ImportPublicKey(&public_key_data)) {
140 scoped_refptr<PrivateKey> private_key;
141 BrowserThread::PostTask(BrowserThread::UI,
142 FROM_HERE,
143 base::Bind(callback, public_key, private_key));
144 return;
145 }
146 public_key = new PublicKey();
147 public_key->data().swap(public_key_data);
148 bool rv = BrowserThread::PostTask(BrowserThread::IO,
149 FROM_HERE,
150 base::Bind(&LoadPrivateKeyByPublicKey,
151 owner_key_util,
152 public_key,
153 username_hash,
154 callback));
155 if (!rv) {
156 // IO thread doesn't exists in unit tests, but it's safe to use NSS from
157 // BlockingPool in unit tests.
158 LoadPrivateKeyByPublicKey(
159 owner_key_util, public_key, username_hash, callback);
160 }
161 }
162
163 bool DoesPrivateKeyExistAsyncHelper(
164 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
165 std::vector<uint8> public_key;
166 if (!owner_key_util->ImportPublicKey(&public_key))
167 return false;
168 scoped_ptr<crypto::RSAPrivateKey> key(
169 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key));
170 bool is_owner = key.get() != NULL;
171 return is_owner;
172 }
173
174 // Checks whether NSS slots with private key are mounted or
175 // not. Responds via |callback|.
176 void DoesPrivateKeyExistAsync(
177 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
178 const OwnerSettingsService::IsOwnerCallback& callback) {
179 if (!owner_key_util) {
180 callback.Run(false);
181 return;
182 }
183 scoped_refptr<base::TaskRunner> task_runner =
184 content::BrowserThread::GetBlockingPool()
185 ->GetTaskRunnerWithShutdownBehavior(
186 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
187 base::PostTaskAndReplyWithResult(
188 task_runner.get(),
189 FROM_HERE,
190 base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
191 callback);
192 }
193
194 // Returns the current management mode.
195 em::PolicyData::ManagementMode GetManagementMode(
196 DeviceSettingsService* service) {
197 if (!service) {
198 LOG(ERROR) << "DeviceSettingsService is not initialized";
199 return em::PolicyData::NOT_MANAGED;
200 }
201
202 const em::PolicyData* policy_data = service->policy_data();
203 if (policy_data && policy_data->has_management_mode())
204 return policy_data->management_mode();
205 return em::PolicyData::NOT_MANAGED;
206 }
207
208 // Returns true if it is okay to transfer from the current mode to the new
209 // mode. This function should be called in SetManagementMode().
210 bool CheckManagementModeTransition(em::PolicyData::ManagementMode current_mode,
211 em::PolicyData::ManagementMode new_mode) {
212 // Mode is not changed.
213 if (current_mode == new_mode)
214 return true;
215
216 switch (current_mode) {
217 case em::PolicyData::NOT_MANAGED:
218 // For consumer management enrollment.
219 return new_mode == em::PolicyData::CONSUMER_MANAGED;
220
221 case em::PolicyData::ENTERPRISE_MANAGED:
222 // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
223 return false;
224
225 case em::PolicyData::CONSUMER_MANAGED:
226 // For consumer management unenrollment.
227 return new_mode == em::PolicyData::NOT_MANAGED;
228 }
229
230 NOTREACHED();
231 return false;
232 }
233
234 } // namespace
235
236 OwnerSettingsService::OwnerSettingsService(
237 Profile* profile,
238 const scoped_refptr<OwnerKeyUtil>& owner_key_util)
239 : profile_(profile),
240 owner_key_util_(owner_key_util),
241 waiting_for_profile_creation_(true),
242 waiting_for_tpm_token_(true),
243 weak_factory_(this) {
244 if (TPMTokenLoader::IsInitialized()) {
245 TPMTokenLoader::TPMTokenStatus tpm_token_status =
246 TPMTokenLoader::Get()->IsTPMTokenEnabled(
247 base::Bind(&OwnerSettingsService::OnTPMTokenReady, as_weak_ptr()));
248 waiting_for_tpm_token_ =
249 tpm_token_status == TPMTokenLoader::TPM_TOKEN_STATUS_UNDETERMINED;
250 }
251
252 if (DBusThreadManager::IsInitialized() &&
253 DBusThreadManager::Get()->GetSessionManagerClient()) {
254 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
255 }
256
257 registrar_.Add(this,
258 chrome::NOTIFICATION_PROFILE_CREATED,
259 content::Source<Profile>(profile_));
260 }
261
262 OwnerSettingsService::~OwnerSettingsService() {
263 DCHECK(thread_checker_.CalledOnValidThread());
264 if (DBusThreadManager::IsInitialized() &&
265 DBusThreadManager::Get()->GetSessionManagerClient()) {
266 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
267 }
268 }
269
270 bool OwnerSettingsService::IsOwner() {
271 DCHECK(thread_checker_.CalledOnValidThread());
272 return private_key_ && private_key_->key();
273 }
274
275 void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) {
276 DCHECK(thread_checker_.CalledOnValidThread());
277 if (private_key_) {
278 base::MessageLoop::current()->PostTask(FROM_HERE,
279 base::Bind(callback, IsOwner()));
280 } else {
281 pending_is_owner_callbacks_.push_back(callback);
282 }
283 }
284
285 bool OwnerSettingsService::AssembleAndSignPolicyAsync(
286 scoped_ptr<em::PolicyData> policy,
287 const AssembleAndSignPolicyCallback& callback) {
288 DCHECK(thread_checker_.CalledOnValidThread());
289 if (!IsOwner())
290 return false;
291 base::PostTaskAndReplyWithResult(
292 BrowserThread::GetBlockingPool(),
293 FROM_HERE,
294 base::Bind(
295 &AssembleAndSignPolicy, base::Passed(&policy), private_key_->key()),
296 callback);
297 return true;
298 }
299
300 void OwnerSettingsService::SignAndStoreAsync(
301 scoped_ptr<em::ChromeDeviceSettingsProto> settings,
302 const base::Closure& callback) {
303 DCHECK(thread_checker_.CalledOnValidThread());
304 scoped_ptr<em::PolicyData> policy = AssemblePolicy(
305 user_id_, GetDeviceSettingsService()->policy_data(), settings.get());
306 if (!policy) {
307 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
308 return;
309 }
310
311 EnqueueSignAndStore(policy.Pass(), callback);
312 }
313
314 void OwnerSettingsService::SetManagementSettingsAsync(
315 em::PolicyData::ManagementMode management_mode,
316 const std::string& request_token,
317 const std::string& device_id,
318 const base::Closure& callback) {
319 em::PolicyData::ManagementMode current_mode =
320 GetManagementMode(GetDeviceSettingsService());
321 if (!CheckManagementModeTransition(current_mode, management_mode)) {
322 LOG(ERROR) << "Invalid management mode transition: current mode = "
323 << current_mode << ", new mode = " << management_mode;
324 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
325 return;
326 }
327
328 DeviceSettingsService* service = GetDeviceSettingsService();
329 scoped_ptr<em::PolicyData> policy = AssemblePolicy(
330 user_id_, service->policy_data(), service->device_settings());
331 if (!policy) {
332 HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
333 return;
334 }
335
336 policy->set_management_mode(management_mode);
337 policy->set_request_token(request_token);
338 policy->set_device_id(device_id);
339
340 EnqueueSignAndStore(policy.Pass(), callback);
341 }
342
343 void OwnerSettingsService::Observe(
344 int type,
345 const content::NotificationSource& source,
346 const content::NotificationDetails& details) {
347 DCHECK(thread_checker_.CalledOnValidThread());
348 if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
349 NOTREACHED();
350 return;
351 }
352
353 Profile* profile = content::Source<Profile>(source).ptr();
354 if (profile != profile_) {
355 NOTREACHED();
356 return;
357 }
358
359 waiting_for_profile_creation_ = false;
360 ReloadPrivateKey();
361 }
362
363 void OwnerSettingsService::OnTPMTokenReady(bool /* unused token_enabled */) {
364 DCHECK(thread_checker_.CalledOnValidThread());
365 waiting_for_tpm_token_ = false;
366
367 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
368 // determine ownership. Force a reload once we know these are initialized.
369 ReloadPrivateKey();
370 }
371
372 void OwnerSettingsService::OwnerKeySet(bool success) {
373 DCHECK(thread_checker_.CalledOnValidThread());
374 if (success)
375 ReloadPrivateKey();
376 }
377
378 // static
379 void OwnerSettingsService::IsOwnerForSafeModeAsync(
380 const std::string& user_hash,
381 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
382 const IsOwnerCallback& callback) {
383 CHECK(chromeos::LoginState::Get()->IsInSafeMode());
384
385 // Make sure NSS is initialized and NSS DB is loaded for the user before
386 // searching for the owner key.
387 BrowserThread::PostTaskAndReply(
388 BrowserThread::IO,
389 FROM_HERE,
390 base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
391 user_hash,
392 ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
393 base::Bind(&DoesPrivateKeyExistAsync, owner_key_util, callback));
394 }
395
396 // static
397 void OwnerSettingsService::SetDeviceSettingsServiceForTesting(
398 DeviceSettingsService* device_settings_service) {
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
400 g_device_settings_service_for_testing = device_settings_service;
401 }
402
403 void OwnerSettingsService::ReloadPrivateKey() {
404 DCHECK(thread_checker_.CalledOnValidThread());
405 if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
406 return;
407 scoped_refptr<base::TaskRunner> task_runner =
408 content::BrowserThread::GetBlockingPool()
409 ->GetTaskRunnerWithShutdownBehavior(
410 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
411 task_runner->PostTask(
412 FROM_HERE,
413 base::Bind(&LoadPrivateKey,
414 GetOwnerKeyUtil(),
415 ProfileHelper::GetUserIdHashFromProfile(profile_),
416 base::Bind(&OwnerSettingsService::OnPrivateKeyLoaded,
417 weak_factory_.GetWeakPtr())));
418 }
419
420 void OwnerSettingsService::OnPrivateKeyLoaded(
421 scoped_refptr<PublicKey> public_key,
422 scoped_refptr<PrivateKey> private_key) {
423 DCHECK(thread_checker_.CalledOnValidThread());
424 public_key_ = public_key;
425 private_key_ = private_key;
426
427 user_id_ = profile_->GetProfileName();
428 const bool is_owner = IsOwner() || IsOwnerInTests(user_id_);
429 if (is_owner && GetDeviceSettingsService())
430 GetDeviceSettingsService()->InitOwner(user_id_, weak_factory_.GetWeakPtr());
431
432 std::vector<IsOwnerCallback> is_owner_callbacks;
433 is_owner_callbacks.swap(pending_is_owner_callbacks_);
434 for (std::vector<IsOwnerCallback>::iterator it(is_owner_callbacks.begin());
435 it != is_owner_callbacks.end();
436 ++it) {
437 it->Run(is_owner);
438 }
439 }
440
441 void OwnerSettingsService::EnqueueSignAndStore(
442 scoped_ptr<em::PolicyData> policy,
443 const base::Closure& callback) {
444 SignAndStoreSettingsOperation* operation = new SignAndStoreSettingsOperation(
445 base::Bind(&OwnerSettingsService::HandleCompletedOperation,
446 weak_factory_.GetWeakPtr(),
447 callback),
448 policy.Pass());
449 operation->set_delegate(weak_factory_.GetWeakPtr());
450 pending_operations_.push_back(operation);
451 if (pending_operations_.front() == operation)
452 StartNextOperation();
453 }
454
455 void OwnerSettingsService::StartNextOperation() {
456 DeviceSettingsService* service = GetDeviceSettingsService();
457 if (!pending_operations_.empty() && service &&
458 service->session_manager_client()) {
459 pending_operations_.front()->Start(
460 service->session_manager_client(), GetOwnerKeyUtil(), public_key_);
461 }
462 }
463
464 void OwnerSettingsService::HandleCompletedOperation(
465 const base::Closure& callback,
466 SessionManagerOperation* operation,
467 DeviceSettingsService::Status status) {
468 DCHECK_EQ(operation, pending_operations_.front());
469
470 DeviceSettingsService* service = GetDeviceSettingsService();
471 if (status == DeviceSettingsService::STORE_SUCCESS) {
472 service->set_policy_data(operation->policy_data().Pass());
473 service->set_device_settings(operation->device_settings().Pass());
474 }
475
476 if ((operation->public_key() && !public_key_) ||
477 (operation->public_key() && public_key_ &&
478 operation->public_key()->data() != public_key_->data())) {
479 // Public part changed so we need to reload private part too.
480 ReloadPrivateKey();
481 content::NotificationService::current()->Notify(
482 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
483 content::Source<OwnerSettingsService>(this),
484 content::NotificationService::NoDetails());
485 }
486 service->OnSignAndStoreOperationCompleted(status);
487 if (!callback.is_null())
488 callback.Run();
489
490 pending_operations_.pop_front();
491 delete operation;
492 StartNextOperation();
493 }
494
495 void OwnerSettingsService::HandleError(DeviceSettingsService::Status status,
496 const base::Closure& callback) {
497 LOG(ERROR) << "Session manager operation failed: " << status;
498 GetDeviceSettingsService()->OnSignAndStoreOperationCompleted(status);
499 if (!callback.is_null())
500 callback.Run();
501 }
502
503 scoped_refptr<OwnerKeyUtil> OwnerSettingsService::GetOwnerKeyUtil() {
504 DCHECK(thread_checker_.CalledOnValidThread());
505 return owner_key_util_;
506 }
507
508 DeviceSettingsService* OwnerSettingsService::GetDeviceSettingsService() {
509 DCHECK(thread_checker_.CalledOnValidThread());
510 if (g_device_settings_service_for_testing)
511 return g_device_settings_service_for_testing;
512 if (DeviceSettingsService::IsInitialized())
513 return DeviceSettingsService::Get();
514 return NULL;
515 }
516
517 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698