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.
5 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.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"
18 namespace em = enterprise_management;
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),
31 device_settings_service_->AddObserver(this);
34 DeviceCloudPolicyStoreChromeOS::~DeviceCloudPolicyStoreChromeOS() {
35 device_settings_service_->RemoveObserver(this);
38 void DeviceCloudPolicyStoreChromeOS::Store(
39 const em::PolicyFetchResponse& policy) {
40 // Cancel all pending requests.
41 weak_factory_.InvalidateWeakPtrs();
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;
53 scoped_ptr<DeviceCloudPolicyValidator> validator(CreateValidator(policy));
54 validator->ValidateSignature(public_key->as_string(),
55 GetPolicyVerificationKey(),
56 install_attributes_->GetDomain(),
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()));
67 void DeviceCloudPolicyStoreChromeOS::Load() {
68 device_settings_service_->Load();
71 void DeviceCloudPolicyStoreChromeOS::InstallInitialPolicy(
72 const em::PolicyFetchResponse& policy) {
73 // Cancel all pending requests.
74 weak_factory_.InvalidateWeakPtrs();
76 if (!install_attributes_->IsEnterpriseDevice() &&
77 device_settings_service_->status() !=
78 chromeos::DeviceSettingsService::STORE_NO_POLICY) {
79 status_ = STATUS_BAD_STATE;
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()));
92 void DeviceCloudPolicyStoreChromeOS::OwnershipStatusChanged() {
96 void DeviceCloudPolicyStoreChromeOS::DeviceSettingsUpdated() {
97 if (!weak_factory_.HasWeakPtrs())
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();
115 void DeviceCloudPolicyStoreChromeOS::OnPolicyToStoreValidated(
116 DeviceCloudPolicyValidator* validator) {
117 if (!validator->success()) {
118 status_ = STATUS_VALIDATION_ERROR;
119 validation_status_ = validator->status();
124 device_settings_service_->Store(
125 validator->policy().Pass(),
126 base::Bind(&DeviceCloudPolicyStoreChromeOS::OnPolicyStored,
127 weak_factory_.GetWeakPtr()));
130 void DeviceCloudPolicyStoreChromeOS::OnPolicyStored() {
134 void DeviceCloudPolicyStoreChromeOS::UpdateFromService() {
135 if (!install_attributes_->IsEnterpriseDevice()) {
136 status_ = STATUS_BAD_STATE;
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();
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();
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.
165 LOG(ERROR) << "Device policy read on enrolled device yields "
166 << "no DM token! Status: " << status << ".";
167 chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
169 UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken",
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.
182 case chromeos::DeviceSettingsService::STORE_SUCCESS: {
184 policy_.reset(new em::PolicyData());
185 if (device_settings_service_->policy_data())
186 policy_->MergeFrom(*device_settings_service_->policy_data());
188 PolicyMap new_policy_map;
190 DecodeDevicePolicy(*device_settings_service_->device_settings(),
191 &new_policy_map, install_attributes_);
193 policy_map_.Swap(&new_policy_map);
198 case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
199 status_ = STATUS_BAD_STATE;
201 case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
202 case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
203 status_ = STATUS_STORE_ERROR;
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;
216 } // namespace policy