Home | History | Annotate | Download | only in policy
      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/policy/device_cloud_policy_store_chromeos.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/sequenced_task_runner.h"
     11 #include "chrome/browser/chromeos/login/startup_utils.h"
     12 #include "chrome/browser/chromeos/policy/device_policy_decoder_chromeos.h"
     13 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
     14 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
     15 #include "components/ownership/owner_key_util.h"
     16 #include "policy/proto/device_management_backend.pb.h"
     17 
     18 namespace em = enterprise_management;
     19 
     20 namespace policy {
     21 
     22 DeviceCloudPolicyStoreChromeOS::DeviceCloudPolicyStoreChromeOS(
     23     chromeos::DeviceSettingsService* device_settings_service,
     24     EnterpriseInstallAttributes* install_attributes,
     25     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
     26     : device_settings_service_(device_settings_service),
     27       install_attributes_(install_attributes),
     28       background_task_runner_(background_task_runner),
     29       enrollment_validation_done_(false),
     30       weak_factory_(this) {
     31   device_settings_service_->AddObserver(this);
     32 }
     33 
     34 DeviceCloudPolicyStoreChromeOS::~DeviceCloudPolicyStoreChromeOS() {
     35   device_settings_service_->RemoveObserver(this);
     36 }
     37 
     38 void DeviceCloudPolicyStoreChromeOS::Store(
     39     const em::PolicyFetchResponse& policy) {
     40   // Cancel all pending requests.
     41   weak_factory_.InvalidateWeakPtrs();
     42 
     43   scoped_refptr<ownership::PublicKey> public_key(
     44       device_settings_service_->GetPublicKey());
     45   if (!install_attributes_->IsEnterpriseDevice() ||
     46       !device_settings_service_->policy_data() || !public_key.get() ||
     47       !public_key->is_loaded()) {
     48     status_ = STATUS_BAD_STATE;
     49     NotifyStoreError();
     50     return;
     51   }
     52 
     53   scoped_ptr<DeviceCloudPolicyValidator> validator(CreateValidator(policy));
     54   validator->ValidateSignature(public_key->as_string(),
     55                                GetPolicyVerificationKey(),
     56                                install_attributes_->GetDomain(),
     57                                true);
     58   validator->ValidateAgainstCurrentPolicy(
     59       device_settings_service_->policy_data(),
     60       CloudPolicyValidatorBase::TIMESTAMP_REQUIRED,
     61       CloudPolicyValidatorBase::DM_TOKEN_REQUIRED);
     62   validator.release()->StartValidation(
     63       base::Bind(&DeviceCloudPolicyStoreChromeOS::OnPolicyToStoreValidated,
     64                  weak_factory_.GetWeakPtr()));
     65 }
     66 
     67 void DeviceCloudPolicyStoreChromeOS::Load() {
     68   device_settings_service_->Load();
     69 }
     70 
     71 void DeviceCloudPolicyStoreChromeOS::InstallInitialPolicy(
     72     const em::PolicyFetchResponse& policy) {
     73   // Cancel all pending requests.
     74   weak_factory_.InvalidateWeakPtrs();
     75 
     76   if (!install_attributes_->IsEnterpriseDevice() &&
     77       device_settings_service_->status() !=
     78           chromeos::DeviceSettingsService::STORE_NO_POLICY) {
     79     status_ = STATUS_BAD_STATE;
     80     NotifyStoreError();
     81     return;
     82   }
     83 
     84   scoped_ptr<DeviceCloudPolicyValidator> validator(CreateValidator(policy));
     85   validator->ValidateInitialKey(GetPolicyVerificationKey(),
     86                                 install_attributes_->GetDomain());
     87   validator.release()->StartValidation(
     88       base::Bind(&DeviceCloudPolicyStoreChromeOS::OnPolicyToStoreValidated,
     89                  weak_factory_.GetWeakPtr()));
     90 }
     91 
     92 void DeviceCloudPolicyStoreChromeOS::OwnershipStatusChanged() {
     93   // Nothing to do.
     94 }
     95 
     96 void DeviceCloudPolicyStoreChromeOS::DeviceSettingsUpdated() {
     97   if (!weak_factory_.HasWeakPtrs())
     98     UpdateFromService();
     99 }
    100 
    101 scoped_ptr<DeviceCloudPolicyValidator>
    102     DeviceCloudPolicyStoreChromeOS::CreateValidator(
    103         const em::PolicyFetchResponse& policy) {
    104   scoped_ptr<DeviceCloudPolicyValidator> validator(
    105       DeviceCloudPolicyValidator::Create(
    106           scoped_ptr<em::PolicyFetchResponse>(
    107               new em::PolicyFetchResponse(policy)),
    108           background_task_runner_));
    109   validator->ValidateDomain(install_attributes_->GetDomain());
    110   validator->ValidatePolicyType(dm_protocol::kChromeDevicePolicyType);
    111   validator->ValidatePayload();
    112   return validator.Pass();
    113 }
    114 
    115 void DeviceCloudPolicyStoreChromeOS::OnPolicyToStoreValidated(
    116     DeviceCloudPolicyValidator* validator) {
    117   if (!validator->success()) {
    118     status_ = STATUS_VALIDATION_ERROR;
    119     validation_status_ = validator->status();
    120     NotifyStoreError();
    121     return;
    122   }
    123 
    124   device_settings_service_->Store(
    125       validator->policy().Pass(),
    126       base::Bind(&DeviceCloudPolicyStoreChromeOS::OnPolicyStored,
    127                  weak_factory_.GetWeakPtr()));
    128 }
    129 
    130 void DeviceCloudPolicyStoreChromeOS::OnPolicyStored() {
    131   UpdateFromService();
    132 }
    133 
    134 void DeviceCloudPolicyStoreChromeOS::UpdateFromService() {
    135   if (!install_attributes_->IsEnterpriseDevice()) {
    136     status_ = STATUS_BAD_STATE;
    137     NotifyStoreError();
    138     return;
    139   }
    140 
    141   // Once per session, validate internal consistency of enrollment state (DM
    142   // token must be present on enrolled devices) and in case of failure set flag
    143   // to indicate that recovery is required.
    144   const chromeos::DeviceSettingsService::Status status =
    145       device_settings_service_->status();
    146   switch (status) {
    147     case chromeos::DeviceSettingsService::STORE_SUCCESS:
    148     case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
    149     case chromeos::DeviceSettingsService::STORE_NO_POLICY:
    150     case chromeos::DeviceSettingsService::STORE_INVALID_POLICY:
    151     case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR: {
    152       if (!enrollment_validation_done_) {
    153         enrollment_validation_done_ = true;
    154         const bool has_dm_token =
    155             status == chromeos::DeviceSettingsService::STORE_SUCCESS &&
    156             device_settings_service_->policy_data() &&
    157             device_settings_service_->policy_data()->has_request_token();
    158 
    159         // At the time LoginDisplayHostImpl decides whether enrollment flow is
    160         // to be started, policy hasn't been read yet.  To work around this,
    161         // once the need for recovery is detected upon policy load, a flag is
    162         // stored in prefs which is accessed by LoginDisplayHostImpl early
    163         // during (next) boot.
    164         if (!has_dm_token) {
    165           LOG(ERROR) << "Device policy read on enrolled device yields "
    166                      << "no DM token! Status: " << status << ".";
    167           chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
    168         }
    169         UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken",
    170                               has_dm_token);
    171       }
    172       break;
    173     }
    174     case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
    175     case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
    176     case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
    177       // Do nothing for write errors or transient read errors.
    178       break;
    179   }
    180 
    181   switch (status) {
    182     case chromeos::DeviceSettingsService::STORE_SUCCESS: {
    183       status_ = STATUS_OK;
    184       policy_.reset(new em::PolicyData());
    185       if (device_settings_service_->policy_data())
    186         policy_->MergeFrom(*device_settings_service_->policy_data());
    187 
    188       PolicyMap new_policy_map;
    189       if (is_managed()) {
    190         DecodeDevicePolicy(*device_settings_service_->device_settings(),
    191                            &new_policy_map, install_attributes_);
    192       }
    193       policy_map_.Swap(&new_policy_map);
    194 
    195       NotifyStoreLoaded();
    196       return;
    197     }
    198     case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
    199       status_ = STATUS_BAD_STATE;
    200       break;
    201     case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
    202     case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
    203       status_ = STATUS_STORE_ERROR;
    204       break;
    205     case chromeos::DeviceSettingsService::STORE_NO_POLICY:
    206     case chromeos::DeviceSettingsService::STORE_INVALID_POLICY:
    207     case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR:
    208     case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
    209       status_ = STATUS_LOAD_ERROR;
    210       break;
    211   }
    212 
    213   NotifyStoreError();
    214 }
    215 
    216 }  // namespace policy
    217