Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: chrome/browser/chromeos/settings/session_manager_operation.cc

Issue 10828032: Add DeviceSettingsService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, move to chrome/browser/chromeos/settings. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/file_path.h"
10 #include "base/file_util.h"
11 #include "base/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/task_runner_util.h"
14 #include "base/threading/sequenced_worker_pool.h"
15 #include "base/time.h"
16 #include "chrome/browser/chromeos/settings/owner_key_util.h"
17 #include "chrome/browser/policy/cloud_policy_constants.h"
18 #include "chrome/browser/policy/cloud_policy_validator.h"
19 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
20 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "crypto/rsa_private_key.h"
23 #include "crypto/signature_creator.h"
24
25 namespace em = enterprise_management;
26
27 namespace chromeos {
28
29 SessionManagerOperation::SessionManagerOperation(const Callback& callback)
Chris Masone 2012/08/03 16:28:25 No unittests for this class? Did you forget to ad
Mattias Nissler (ping if slow) 2012/08/06 21:28:14 I consider the code here a mere implementation det
Chris Masone 2012/08/07 20:20:03 Well, wouldn't it be useful to test that LoadOwner
Mattias Nissler (ping if slow) 2012/08/17 13:22:42 OK, I added unit tests that should cover SessionMa
30 : session_manager_client_(NULL),
31 ALLOW_THIS_IN_INITIALIZER_LIST(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<OwnerKey> owner_key) {
42 session_manager_client_ = session_manager_client;
43 owner_key_util_ = owner_key_util;
44 owner_key_ = owner_key;
45 Run();
46 }
47
48 void SessionManagerOperation::RestartLoad(bool key_changed) {
49 if (key_changed)
50 owner_key_ = NULL;
51
52 if (!is_loading_)
53 return;
54
55 // Abort previous load operations.
56 weak_factory_.InvalidateWeakPtrs();
57 StartLoading();
58 }
59
60 void SessionManagerOperation::StartLoading() {
61 is_loading_ = true;
62 EnsureOwnerKey(base::Bind(&SessionManagerOperation::RetrieveDeviceSettings,
63 weak_factory_.GetWeakPtr()));
64 }
65
66 void SessionManagerOperation::ReportResult(
67 DeviceSettingsService::Status status) {
68 callback_.Run(this, status);
69 }
70
71 void SessionManagerOperation::EnsureOwnerKey(const base::Closure& callback) {
72 if (force_key_load_ || !owner_key_.get() || !owner_key_->public_key()) {
73 base::PostTaskAndReplyWithResult(
74 content::BrowserThread::GetBlockingPool(),
75 FROM_HERE,
76 base::Bind(&SessionManagerOperation::LoadOwnerKey,
77 owner_key_util_, owner_key_),
78 base::Bind(&SignAndStoreSettingsOperation::StoreOwnerKey,
79 weak_factory_.GetWeakPtr(), callback));
80 } else {
81 callback.Run();
82 }
83 }
84
85 // static
86 scoped_refptr<OwnerKey> SessionManagerOperation::LoadOwnerKey(
87 scoped_refptr<OwnerKeyUtil> util,
88 scoped_refptr<OwnerKey> current_key) {
89 scoped_ptr<std::vector<uint8> > public_key;
90 scoped_ptr<crypto::RSAPrivateKey> private_key;
91
92 // Keep any already-existing keys.
93 if (current_key.get()) {
94 if (current_key->public_key())
95 public_key.reset(new std::vector<uint8>(*current_key->public_key()));
96 if (current_key->private_key())
97 private_key.reset(current_key->private_key()->Copy());
98 }
99
100 if (!public_key.get() && util->IsPublicKeyPresent()) {
101 public_key.reset(new std::vector<uint8>());
102 if (!util->ImportPublicKey(public_key.get()))
103 LOG(ERROR) << "Failed to load public owner key.";
104 }
105
106 if (public_key.get() && !private_key.get()) {
107 private_key.reset(util->FindPrivateKey(*public_key));
108 if (!private_key.get())
109 VLOG(1) << "Failed to load private owner key.";
110 }
111
112 return new OwnerKey(public_key.Pass(), private_key.Pass());
113 }
114
115 void SessionManagerOperation::StoreOwnerKey(const base::Closure& callback,
116 scoped_refptr<OwnerKey> new_key) {
117 force_key_load_ = false;
118 owner_key_ = new_key;
119
120 if (!owner_key_.get() || !owner_key_->public_key()) {
121 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
122 return;
123 }
124
125 callback.Run();
126 }
127
128 void SessionManagerOperation::RetrieveDeviceSettings() {
129 session_manager_client()->RetrieveDevicePolicy(
130 base::Bind(&SessionManagerOperation::ValidateDeviceSettings,
131 weak_factory_.GetWeakPtr()));
132 }
133
134 void SessionManagerOperation::ValidateDeviceSettings(
135 const std::string& policy_blob) {
136 scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
137 if (policy_blob.empty()) {
138 ReportResult(DeviceSettingsService::STORE_NO_POLICY);
139 return;
140 }
141
142 if (!policy->ParseFromString(policy_blob) ||
143 !policy->IsInitialized()) {
144 ReportResult(DeviceSettingsService::STORE_INVALID_POLICY);
145 return;
146 }
147
148 policy::DeviceCloudPolicyValidator* validator =
149 policy::DeviceCloudPolicyValidator::Create(
150 policy.Pass(),
151 base::Bind(&SessionManagerOperation::ReportValidatorStatus,
152 weak_factory_.GetWeakPtr()));
153
154 // Policy auto-generated by session manager doesn't include a timestamp, so we
155 // need to allow missing timestamps.
156 validator->ValidateAgainstCurrentPolicy(
157 policy_data_.get(),
158 !policy_data_.get() || !policy_data_->has_request_token());
159 validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType);
160 validator->ValidatePayload();
161 const std::vector<uint8>* public_key = owner_key_->public_key();
162 validator->ValidateSignature(
163 std::string(reinterpret_cast<const char*>(vector_as_array(public_key)),
164 public_key->size()),
165 false);
166
167 validator->StartValidation();
168 }
169
170 void SessionManagerOperation::ReportValidatorStatus(
171 policy::DeviceCloudPolicyValidator* validator) {
172 DeviceSettingsService::Status status =
173 DeviceSettingsService::STORE_VALIDATION_ERROR;
174 if (validator->success()) {
175 status = DeviceSettingsService::STORE_SUCCESS;
176 policy_data_ = validator->policy_data().Pass();
177 device_settings_ = validator->payload().Pass();
178 } else {
179 LOG(ERROR) << "Policy validation failed: " << validator->status();
180 }
181
182 ReportResult(status);
183 }
184
185 LoadSettingsOperation::LoadSettingsOperation(const Callback& callback)
186 : SessionManagerOperation(callback) {}
187
188 LoadSettingsOperation::~LoadSettingsOperation() {}
189
190 void LoadSettingsOperation::Run() {
191 StartLoading();
192 }
193
194 StoreSettingsOperation::StoreSettingsOperation(const Callback& callback,
195 const std::string& policy_blob)
196 : SessionManagerOperation(callback),
197 policy_blob_(policy_blob),
198 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
199
200 StoreSettingsOperation::~StoreSettingsOperation() {}
201
202 void StoreSettingsOperation::Run() {
203 session_manager_client()->StoreDevicePolicy(
204 policy_blob_,
205 base::Bind(&StoreSettingsOperation::HandleStoreResult,
206 weak_factory_.GetWeakPtr()));
207 }
208
209 void StoreSettingsOperation::HandleStoreResult(bool success) {
210 if (!success)
211 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
212 else
213 StartLoading();
214 }
215
216 SignAndStoreSettingsOperation::SignAndStoreSettingsOperation(
217 const Callback& callback,
218 scoped_ptr<em::ChromeDeviceSettingsProto> settings,
219 const std::string& username)
220 : SessionManagerOperation(callback),
221 settings_(settings.Pass()),
222 username_(username),
223 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
224 DCHECK(settings_.get());
225 }
226
227 SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
228
229 void SignAndStoreSettingsOperation::Run() {
230 EnsureOwnerKey(base::Bind(&SignAndStoreSettingsOperation::StartSigning,
231 weak_factory_.GetWeakPtr()));
232 }
233
234 void SignAndStoreSettingsOperation::StartSigning() {
235 if (!owner_key() || !owner_key()->private_key() || username_.empty()) {
236 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
237 return;
238 }
239
240 base::PostTaskAndReplyWithResult(
241 content::BrowserThread::GetBlockingPool(),
242 FROM_HERE,
243 base::Bind(&SignAndStoreSettingsOperation::AssembleAndSignPolicy,
244 base::Passed(&settings_), username_, owner_key()),
245 base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob,
246 weak_factory_.GetWeakPtr()));
247 }
248
249 // static
250 std::string SignAndStoreSettingsOperation::AssembleAndSignPolicy(
251 scoped_ptr<em::ChromeDeviceSettingsProto> device_settings,
252 const std::string& username,
253 scoped_refptr<OwnerKey> owner_key) {
254 // Assemble the policy.
255 em::PolicyFetchResponse policy_response;
256 em::PolicyData policy;
257 policy.set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
258 policy.set_timestamp((base::Time::NowFromSystemTime() -
259 base::Time::UnixEpoch()).InMilliseconds());
260 policy.set_username(username);
261 if (!device_settings->SerializeToString(policy.mutable_policy_value()) ||
262 !policy.SerializeToString(policy_response.mutable_policy_data())) {
263 LOG(ERROR) << "Failed to encode policy payload.";
264 return std::string();
265 }
266
267 // Generate the signature.
268 scoped_ptr<crypto::SignatureCreator> signature_creator(
269 crypto::SignatureCreator::Create(owner_key->private_key()));
270 signature_creator->Update(
271 reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
272 policy_response.policy_data().size());
273 std::vector<uint8> signature_bytes;
274 std::string policy_blob;
275 if (!signature_creator->Final(&signature_bytes)) {
276 LOG(ERROR) << "Failed to create policy signature.";
277 return std::string();
278 }
279
280 policy_response.mutable_policy_data_signature()->assign(
281 reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
282 signature_bytes.size());
283 return policy_response.SerializeAsString();
284 }
285
286 void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob(
287 std::string device_settings_blob) {
288 if (device_settings_blob.empty()) {
289 ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
290 return;
291 }
292
293 session_manager_client()->StoreDevicePolicy(
294 device_settings_blob,
295 base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult,
296 weak_factory_.GetWeakPtr()));
297 }
298
299 void SignAndStoreSettingsOperation::HandleStoreResult(bool success) {
300 if (!success)
301 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
302 else
303 StartLoading();
304 }
305
306 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698