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