Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / ownership / owner_settings_service.cc
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 "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"
27
28 namespace em = enterprise_management;
29
30 using content::BrowserThread;
31
32 namespace chromeos {
33
34 namespace {
35
36 scoped_refptr<OwnerKeyUtil>* g_owner_key_util_for_testing = NULL;
37 DeviceSettingsService* g_device_settings_service_for_testing = NULL;
38
39 // Assembles PolicyData based on |settings|, |policy_data| and
40 // |user_id|.
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());
46   if (policy_data) {
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());
54   } else {
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);
58   }
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>();
65
66   return policy.Pass();
67 }
68
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.";
75     return std::string();
76   }
77
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.";
88     return std::string();
89   }
90
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();
95 }
96
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)>&
103         callback) {
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,
110                           FROM_HERE,
111                           base::Bind(callback, public_key, private_key));
112 }
113
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,
124                             FROM_HERE,
125                             base::Bind(callback, public_key, private_key));
126     return;
127   }
128   public_key = new PublicKey();
129   public_key->data().swap(public_key_data);
130   bool rv = BrowserThread::PostTask(BrowserThread::IO,
131                                     FROM_HERE,
132                                     base::Bind(&LoadPrivateKeyByPublicKey,
133                                                owner_key_util,
134                                                public_key,
135                                                username_hash,
136                                                callback));
137   if (!rv) {
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);
142   }
143 }
144
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))
149     return false;
150   scoped_ptr<crypto::RSAPrivateKey> key(
151       crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key));
152   bool is_owner = key.get() != NULL;
153   return is_owner;
154 }
155
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;
163   else
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(
170       task_runner.get(),
171       FROM_HERE,
172       base::Bind(&DoesPrivateKeyExistAsyncHelper, owner_key_util),
173       callback);
174 }
175
176 // Returns the current management mode.
177 em::PolicyData::ManagementMode GetManagementMode(
178     DeviceSettingsService* service) {
179   if (!service) {
180     LOG(ERROR) << "DeviceSettingsService is not initialized";
181     return em::PolicyData::NOT_MANAGED;
182   }
183
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;
188 }
189
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)
196     return true;
197
198   switch (current_mode) {
199     case em::PolicyData::NOT_MANAGED:
200       // For consumer management enrollment.
201       return new_mode == em::PolicyData::CONSUMER_MANAGED;
202
203     case em::PolicyData::ENTERPRISE_MANAGED:
204       // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
205       return false;
206
207     case em::PolicyData::CONSUMER_MANAGED:
208       // For consumer management unenrollment.
209       return new_mode == em::PolicyData::NOT_MANAGED;
210   }
211
212   NOTREACHED();
213   return false;
214 }
215
216 }  // namespace
217
218 OwnerSettingsService::OwnerSettingsService(Profile* profile)
219     : 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);
227   }
228
229   if (DBusThreadManager::IsInitialized() &&
230       DBusThreadManager::Get()->GetSessionManagerClient()) {
231     DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
232   }
233
234   registrar_.Add(this,
235                  chrome::NOTIFICATION_PROFILE_CREATED,
236                  content::Source<Profile>(profile_));
237 }
238
239 OwnerSettingsService::~OwnerSettingsService() {
240   DCHECK(thread_checker_.CalledOnValidThread());
241   if (TPMTokenLoader::IsInitialized())
242     TPMTokenLoader::Get()->RemoveObserver(this);
243
244   if (DBusThreadManager::IsInitialized() &&
245       DBusThreadManager::Get()->GetSessionManagerClient()) {
246     DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
247   }
248 }
249
250 bool OwnerSettingsService::IsOwner() {
251   DCHECK(thread_checker_.CalledOnValidThread());
252   return private_key_ && private_key_->key();
253 }
254
255 void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) {
256   DCHECK(thread_checker_.CalledOnValidThread());
257   if (private_key_) {
258     base::MessageLoop::current()->PostTask(FROM_HERE,
259                                            base::Bind(callback, IsOwner()));
260   } else {
261     pending_is_owner_callbacks_.push_back(callback);
262   }
263 }
264
265 bool OwnerSettingsService::AssembleAndSignPolicyAsync(
266     scoped_ptr<em::PolicyData> policy,
267     const AssembleAndSignPolicyCallback& callback) {
268   DCHECK(thread_checker_.CalledOnValidThread());
269   if (!IsOwner())
270     return false;
271   base::PostTaskAndReplyWithResult(
272       BrowserThread::GetBlockingPool(),
273       FROM_HERE,
274       base::Bind(
275           &AssembleAndSignPolicy, base::Passed(&policy), private_key_->key()),
276       callback);
277   return true;
278 }
279
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());
286   if (!policy) {
287     HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
288     return;
289   }
290
291   EnqueueSignAndStore(policy.Pass(), callback);
292 }
293
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);
305     return;
306   }
307
308   DeviceSettingsService* service = GetDeviceSettingsService();
309   scoped_ptr<em::PolicyData> policy = AssemblePolicy(
310       user_id_, service->policy_data(), service->device_settings());
311   if (!policy) {
312     HandleError(DeviceSettingsService::STORE_POLICY_ERROR, callback);
313     return;
314   }
315
316   policy->set_management_mode(management_mode);
317   policy->set_request_token(request_token);
318   policy->set_device_id(device_id);
319
320   EnqueueSignAndStore(policy.Pass(), callback);
321 }
322
323 void OwnerSettingsService::Observe(
324     int type,
325     const content::NotificationSource& source,
326     const content::NotificationDetails& details) {
327   DCHECK(thread_checker_.CalledOnValidThread());
328   if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
329     NOTREACHED();
330     return;
331   }
332
333   Profile* profile = content::Source<Profile>(source).ptr();
334   if (profile != profile_) {
335     NOTREACHED();
336     return;
337   }
338
339   waiting_for_profile_creation_ = false;
340   ReloadPrivateKey();
341 }
342
343 void OwnerSettingsService::OnTPMTokenReady() {
344   DCHECK(thread_checker_.CalledOnValidThread());
345   waiting_for_tpm_token_ = false;
346
347   // TPMTokenLoader initializes the TPM and NSS database which is necessary to
348   // determine ownership. Force a reload once we know these are initialized.
349   ReloadPrivateKey();
350 }
351
352 void OwnerSettingsService::OwnerKeySet(bool success) {
353   DCHECK(thread_checker_.CalledOnValidThread());
354   if (success)
355     ReloadPrivateKey();
356 }
357
358 // static
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());
364
365   // Make sure NSS is initialized and NSS DB is loaded for the user before
366   // searching for the owner key.
367   BrowserThread::PostTaskAndReply(
368       BrowserThread::IO,
369       FROM_HERE,
370       base::Bind(base::IgnoreResult(&crypto::InitializeNSSForChromeOSUser),
371                  user_id,
372                  user_hash,
373                  ProfileHelper::GetProfilePathByUserIdHash(user_hash)),
374       base::Bind(&DoesPrivateKeyExistAsync, callback));
375 }
376
377 // static
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;
384   }
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;
388   }
389 }
390
391 // static
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;
396 }
397
398 void OwnerSettingsService::ReloadPrivateKey() {
399   DCHECK(thread_checker_.CalledOnValidThread());
400   if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
401     return;
402   scoped_refptr<base::TaskRunner> task_runner =
403       content::BrowserThread::GetBlockingPool()
404           ->GetTaskRunnerWithShutdownBehavior(
405               base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
406   task_runner->PostTask(
407       FROM_HERE,
408       base::Bind(&LoadPrivateKey,
409                  GetOwnerKeyUtil(),
410                  ProfileHelper::GetUserIdHashFromProfile(profile_),
411                  base::Bind(&OwnerSettingsService::OnPrivateKeyLoaded,
412                             weak_factory_.GetWeakPtr())));
413 }
414
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;
421
422   user_id_ = profile_->GetProfileName();
423   if (user_id_ == OwnerSettingsServiceFactory::GetInstance()->GetUsername())
424     GetDeviceSettingsService()->InitOwner(user_id_, weak_factory_.GetWeakPtr());
425
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();
431        ++it) {
432     it->Run(is_owner);
433   }
434 }
435
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(),
442                  callback),
443       policy.Pass());
444   operation->set_delegate(weak_factory_.GetWeakPtr());
445   pending_operations_.push_back(operation);
446   if (pending_operations_.front() == operation)
447     StartNextOperation();
448 }
449
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_);
456   }
457 }
458
459 void OwnerSettingsService::HandleCompletedOperation(
460     const base::Closure& callback,
461     SessionManagerOperation* operation,
462     DeviceSettingsService::Status status) {
463   DCHECK_EQ(operation, pending_operations_.front());
464
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());
469   }
470
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.
475     ReloadPrivateKey();
476     content::NotificationService::current()->Notify(
477         chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
478         content::Source<OwnerSettingsService>(this),
479         content::NotificationService::NoDetails());
480   }
481   service->OnSignAndStoreOperationCompleted(status);
482   if (!callback.is_null())
483     callback.Run();
484
485   pending_operations_.pop_front();
486   delete operation;
487   StartNextOperation();
488 }
489
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())
495     callback.Run();
496 }
497
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_;
503 }
504
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();
511   return NULL;
512 }
513
514 }  // namespace chromeos