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 18namespace em = enterprise_management; 19 20namespace policy { 21 22DeviceCloudPolicyStoreChromeOS::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 34DeviceCloudPolicyStoreChromeOS::~DeviceCloudPolicyStoreChromeOS() { 35 device_settings_service_->RemoveObserver(this); 36} 37 38void 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 67void DeviceCloudPolicyStoreChromeOS::Load() { 68 device_settings_service_->Load(); 69} 70 71void 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 92void DeviceCloudPolicyStoreChromeOS::OwnershipStatusChanged() { 93 // Nothing to do. 94} 95 96void DeviceCloudPolicyStoreChromeOS::DeviceSettingsUpdated() { 97 if (!weak_factory_.HasWeakPtrs()) 98 UpdateFromService(); 99} 100 101scoped_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 115void 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 130void DeviceCloudPolicyStoreChromeOS::OnPolicyStored() { 131 UpdateFromService(); 132} 133 134void 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