Home | History | Annotate | Download | only in settings
      1 // Copyright (c) 2012 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/settings/session_manager_operation.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/files/file_path.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/stl_util.h"
     12 #include "base/task_runner_util.h"
     13 #include "base/threading/sequenced_worker_pool.h"
     14 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
     15 #include "chrome/browser/net/nss_context.h"
     16 #include "components/ownership/owner_key_util.h"
     17 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "crypto/rsa_private_key.h"
     20 #include "crypto/signature_creator.h"
     21 #include "policy/proto/device_management_backend.pb.h"
     22 
     23 using ownership::OwnerKeyUtil;
     24 using ownership::PublicKey;
     25 
     26 namespace em = enterprise_management;
     27 
     28 namespace chromeos {
     29 
     30 SessionManagerOperation::SessionManagerOperation(const Callback& callback)
     31     : session_manager_client_(NULL),
     32       callback_(callback),
     33       force_key_load_(false),
     34       is_loading_(false),
     35       weak_factory_(this) {}
     36 
     37 SessionManagerOperation::~SessionManagerOperation() {}
     38 
     39 void SessionManagerOperation::Start(
     40     SessionManagerClient* session_manager_client,
     41     scoped_refptr<OwnerKeyUtil> owner_key_util,
     42     scoped_refptr<PublicKey> public_key) {
     43   session_manager_client_ = session_manager_client;
     44   owner_key_util_ = owner_key_util;
     45   public_key_ = public_key;
     46   Run();
     47 }
     48 
     49 void SessionManagerOperation::RestartLoad(bool key_changed) {
     50   if (key_changed)
     51     public_key_ = NULL;
     52 
     53   if (!is_loading_)
     54     return;
     55 
     56   // Abort previous load operations.
     57   weak_factory_.InvalidateWeakPtrs();
     58   // Mark as not loading to start loading again.
     59   is_loading_ = false;
     60   StartLoading();
     61 }
     62 
     63 void SessionManagerOperation::StartLoading() {
     64   if (is_loading_)
     65     return;
     66   is_loading_ = true;
     67   EnsurePublicKey(base::Bind(&SessionManagerOperation::RetrieveDeviceSettings,
     68                              weak_factory_.GetWeakPtr()));
     69 }
     70 
     71 void SessionManagerOperation::ReportResult(
     72     DeviceSettingsService::Status status) {
     73   callback_.Run(this, status);
     74 }
     75 
     76 void SessionManagerOperation::EnsurePublicKey(const base::Closure& callback) {
     77   if (force_key_load_ || !public_key_.get() || !public_key_->is_loaded()) {
     78     scoped_refptr<base::TaskRunner> task_runner =
     79         content::BrowserThread::GetBlockingPool()
     80             ->GetTaskRunnerWithShutdownBehavior(
     81                 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
     82     base::PostTaskAndReplyWithResult(
     83         task_runner.get(),
     84         FROM_HERE,
     85         base::Bind(&SessionManagerOperation::LoadPublicKey,
     86                    owner_key_util_,
     87                    public_key_),
     88         base::Bind(&SessionManagerOperation::StorePublicKey,
     89                    weak_factory_.GetWeakPtr(),
     90                    callback));
     91   } else {
     92     callback.Run();
     93   }
     94 }
     95 
     96 // static
     97 scoped_refptr<PublicKey> SessionManagerOperation::LoadPublicKey(
     98     scoped_refptr<OwnerKeyUtil> util,
     99     scoped_refptr<PublicKey> current_key) {
    100   scoped_refptr<PublicKey> public_key(new PublicKey());
    101 
    102   // Keep already-existing public key.
    103   if (current_key.get() && current_key->is_loaded()) {
    104     public_key->data() = current_key->data();
    105   }
    106   if (!public_key->is_loaded() && util->IsPublicKeyPresent()) {
    107     if (!util->ImportPublicKey(&public_key->data()))
    108       LOG(ERROR) << "Failed to load public owner key.";
    109   }
    110 
    111   return public_key;
    112 }
    113 
    114 void SessionManagerOperation::StorePublicKey(const base::Closure& callback,
    115                                              scoped_refptr<PublicKey> new_key) {
    116   force_key_load_ = false;
    117   public_key_ = new_key;
    118 
    119   if (!public_key_.get() || !public_key_->is_loaded()) {
    120     ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
    121     return;
    122   }
    123 
    124   callback.Run();
    125 }
    126 
    127 void SessionManagerOperation::RetrieveDeviceSettings() {
    128   session_manager_client()->RetrieveDevicePolicy(
    129       base::Bind(&SessionManagerOperation::ValidateDeviceSettings,
    130                  weak_factory_.GetWeakPtr()));
    131 }
    132 
    133 void SessionManagerOperation::ValidateDeviceSettings(
    134     const std::string& policy_blob) {
    135   scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
    136   if (policy_blob.empty()) {
    137     ReportResult(DeviceSettingsService::STORE_NO_POLICY);
    138     return;
    139   }
    140 
    141   if (!policy->ParseFromString(policy_blob) ||
    142       !policy->IsInitialized()) {
    143     ReportResult(DeviceSettingsService::STORE_INVALID_POLICY);
    144     return;
    145   }
    146 
    147   base::SequencedWorkerPool* pool =
    148       content::BrowserThread::GetBlockingPool();
    149   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
    150       pool->GetSequencedTaskRunnerWithShutdownBehavior(
    151           pool->GetSequenceToken(),
    152           base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
    153 
    154   policy::DeviceCloudPolicyValidator* validator =
    155       policy::DeviceCloudPolicyValidator::Create(policy.Pass(),
    156                                                  background_task_runner);
    157 
    158 
    159   // Policy auto-generated by session manager doesn't include a timestamp, so
    160   // the timestamp shouldn't be verified in that case.
    161   //
    162   // Additionally, offline devices can get their clock set backwards in time
    163   // under some hardware conditions; checking the timestamp now could likely
    164   // find a value in the future, and prevent the user from signing-in or
    165   // starting guest mode. Tlsdate will eventually fix the clock when the device
    166   // is back online, but the network configuration may come from device ONC.
    167   //
    168   // To prevent all of these issues the timestamp is just not verified when
    169   // loading the device policy from the cache. Note that the timestamp is still
    170   // verified during enrollment and when a new policy is fetched from the
    171   // server.
    172   validator->ValidateAgainstCurrentPolicy(
    173       policy_data_.get(),
    174       policy::CloudPolicyValidatorBase::TIMESTAMP_NOT_REQUIRED,
    175       policy::CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED);
    176   validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType);
    177   validator->ValidatePayload();
    178   // We don't check the DMServer verification key below, because the signing
    179   // key is validated when it is installed.
    180   validator->ValidateSignature(public_key_->as_string(),
    181                                std::string(),  // No key validation check.
    182                                std::string(),
    183                                false);
    184   validator->StartValidation(
    185       base::Bind(&SessionManagerOperation::ReportValidatorStatus,
    186                  weak_factory_.GetWeakPtr()));
    187 }
    188 
    189 void SessionManagerOperation::ReportValidatorStatus(
    190     policy::DeviceCloudPolicyValidator* validator) {
    191   DeviceSettingsService::Status status =
    192       DeviceSettingsService::STORE_VALIDATION_ERROR;
    193   if (validator->success()) {
    194     status = DeviceSettingsService::STORE_SUCCESS;
    195     policy_data_ = validator->policy_data().Pass();
    196     device_settings_ = validator->payload().Pass();
    197   } else {
    198     LOG(ERROR) << "Policy validation failed: " << validator->status();
    199 
    200     // Those are mostly caused by RTC loss and are recoverable.
    201     if (validator->status() ==
    202         policy::DeviceCloudPolicyValidator::VALIDATION_BAD_TIMESTAMP) {
    203       status = DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR;
    204     }
    205   }
    206 
    207   ReportResult(status);
    208 }
    209 
    210 LoadSettingsOperation::LoadSettingsOperation(const Callback& callback)
    211     : SessionManagerOperation(callback) {}
    212 
    213 LoadSettingsOperation::~LoadSettingsOperation() {}
    214 
    215 void LoadSettingsOperation::Run() {
    216   StartLoading();
    217 }
    218 
    219 StoreSettingsOperation::StoreSettingsOperation(
    220     const Callback& callback,
    221     scoped_ptr<em::PolicyFetchResponse> policy)
    222     : SessionManagerOperation(callback),
    223       policy_(policy.Pass()),
    224       weak_factory_(this) {}
    225 
    226 StoreSettingsOperation::~StoreSettingsOperation() {}
    227 
    228 void StoreSettingsOperation::Run() {
    229   session_manager_client()->StoreDevicePolicy(
    230       policy_->SerializeAsString(),
    231       base::Bind(&StoreSettingsOperation::HandleStoreResult,
    232                  weak_factory_.GetWeakPtr()));
    233 }
    234 
    235 void StoreSettingsOperation::HandleStoreResult(bool success) {
    236   if (!success)
    237     ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
    238   else
    239     StartLoading();
    240 }
    241 
    242 SignAndStoreSettingsOperation::SignAndStoreSettingsOperation(
    243     const Callback& callback,
    244     scoped_ptr<em::PolicyData> new_policy)
    245     : SessionManagerOperation(callback),
    246       new_policy_(new_policy.Pass()),
    247       weak_factory_(this) {
    248   DCHECK(new_policy_);
    249 }
    250 
    251 SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
    252 
    253 void SignAndStoreSettingsOperation::Run() {
    254   if (!owner_settings_service_) {
    255     ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
    256     return;
    257   }
    258   owner_settings_service_->IsOwnerAsync(
    259       base::Bind(&SignAndStoreSettingsOperation::StartSigning,
    260                  weak_factory_.GetWeakPtr()));
    261 }
    262 
    263 void SignAndStoreSettingsOperation::StartSigning(bool is_owner) {
    264   if (!owner_settings_service_ || !is_owner) {
    265     ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
    266     return;
    267   }
    268 
    269   bool rv = owner_settings_service_->AssembleAndSignPolicyAsync(
    270       content::BrowserThread::GetBlockingPool(),
    271       new_policy_.Pass(),
    272       base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob,
    273                  weak_factory_.GetWeakPtr()));
    274   if (!rv) {
    275     ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
    276     return;
    277   }
    278 }
    279 
    280 void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob(
    281     std::string device_settings_blob) {
    282   if (device_settings_blob.empty()) {
    283     ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
    284     return;
    285   }
    286 
    287   session_manager_client()->StoreDevicePolicy(
    288       device_settings_blob,
    289       base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult,
    290                  weak_factory_.GetWeakPtr()));
    291 }
    292 
    293 void SignAndStoreSettingsOperation::HandleStoreResult(bool success) {
    294   if (!success)
    295     ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
    296   else
    297     StartLoading();
    298 }
    299 
    300 }  // namespace chromeos
    301