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
SessionManagerOperation(const Callback & callback)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
~SessionManagerOperation()36 SessionManagerOperation::~SessionManagerOperation() {}
37
Start(SessionManagerClient * session_manager_client,scoped_refptr<OwnerKeyUtil> owner_key_util,scoped_refptr<PublicKey> public_key)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
RestartLoad(bool key_changed)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
StartLoading()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
ReportResult(DeviceSettingsService::Status status)70 void SessionManagerOperation::ReportResult(
71 DeviceSettingsService::Status status) {
72 callback_.Run(this, status);
73 }
74
EnsurePublicKey(const base::Closure & callback)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
LoadPublicKey(scoped_refptr<OwnerKeyUtil> util,scoped_refptr<PublicKey> current_key)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
StorePublicKey(const base::Closure & callback,scoped_refptr<PublicKey> new_key)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
RetrieveDeviceSettings()126 void SessionManagerOperation::RetrieveDeviceSettings() {
127 session_manager_client()->RetrieveDevicePolicy(
128 base::Bind(&SessionManagerOperation::ValidateDeviceSettings,
129 weak_factory_.GetWeakPtr()));
130 }
131
ValidateDeviceSettings(const std::string & policy_blob)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
ReportValidatorStatus(policy::DeviceCloudPolicyValidator * validator)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
LoadSettingsOperation(const Callback & callback)209 LoadSettingsOperation::LoadSettingsOperation(const Callback& callback)
210 : SessionManagerOperation(callback) {}
211
~LoadSettingsOperation()212 LoadSettingsOperation::~LoadSettingsOperation() {}
213
Run()214 void LoadSettingsOperation::Run() {
215 StartLoading();
216 }
217
StoreSettingsOperation(const Callback & callback,scoped_ptr<em::PolicyFetchResponse> policy)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
~StoreSettingsOperation()225 StoreSettingsOperation::~StoreSettingsOperation() {}
226
Run()227 void StoreSettingsOperation::Run() {
228 session_manager_client()->StoreDevicePolicy(
229 policy_->SerializeAsString(),
230 base::Bind(&StoreSettingsOperation::HandleStoreResult,
231 weak_factory_.GetWeakPtr()));
232 }
233
HandleStoreResult(bool success)234 void StoreSettingsOperation::HandleStoreResult(bool success) {
235 if (!success)
236 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
237 else
238 StartLoading();
239 }
240
SignAndStoreSettingsOperation(const Callback & callback,scoped_ptr<em::PolicyData> new_policy)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
~SignAndStoreSettingsOperation()250 SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
251
Run()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
StartSigning(bool is_owner)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
StoreDeviceSettingsBlob(std::string device_settings_blob)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
HandleStoreResult(bool success)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