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

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. Created 8 years, 3 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)
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 validator->ValidateSignature(*owner_key_->public_key(), false);
162 validator->StartValidation();
163 }
164
165 void SessionManagerOperation::ReportValidatorStatus(
166 policy::DeviceCloudPolicyValidator* validator) {
167 DeviceSettingsService::Status status =
168 DeviceSettingsService::STORE_VALIDATION_ERROR;
169 if (validator->success()) {
170 status = DeviceSettingsService::STORE_SUCCESS;
171 policy_data_ = validator->policy_data().Pass();
172 device_settings_ = validator->payload().Pass();
173 } else {
174 LOG(ERROR) << "Policy validation failed: " << validator->status();
175 }
176
177 ReportResult(status);
178 }
179
180 LoadSettingsOperation::LoadSettingsOperation(const Callback& callback)
181 : SessionManagerOperation(callback) {}
182
183 LoadSettingsOperation::~LoadSettingsOperation() {}
184
185 void LoadSettingsOperation::Run() {
186 StartLoading();
187 }
188
189 StoreSettingsOperation::StoreSettingsOperation(const Callback& callback,
190 const std::string& policy_blob)
191 : SessionManagerOperation(callback),
192 policy_blob_(policy_blob),
193 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
194
195 StoreSettingsOperation::~StoreSettingsOperation() {}
196
197 void StoreSettingsOperation::Run() {
198 session_manager_client()->StoreDevicePolicy(
199 policy_blob_,
200 base::Bind(&StoreSettingsOperation::HandleStoreResult,
201 weak_factory_.GetWeakPtr()));
202 }
203
204 void StoreSettingsOperation::HandleStoreResult(bool success) {
205 if (!success)
206 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
207 else
208 StartLoading();
209 }
210
211 SignAndStoreSettingsOperation::SignAndStoreSettingsOperation(
212 const Callback& callback,
213 scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
214 const std::string& username)
215 : SessionManagerOperation(callback),
216 new_settings_(new_settings.Pass()),
217 username_(username),
218 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
219 DCHECK(new_settings_.get());
220 }
221
222 SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
223
224 void SignAndStoreSettingsOperation::Run() {
225 EnsureOwnerKey(base::Bind(&SignAndStoreSettingsOperation::StartSigning,
226 weak_factory_.GetWeakPtr()));
227 }
228
229 void SignAndStoreSettingsOperation::StartSigning() {
230 if (!owner_key() || !owner_key()->private_key() || username_.empty()) {
231 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
232 return;
233 }
234
235 base::PostTaskAndReplyWithResult(
236 content::BrowserThread::GetBlockingPool(),
237 FROM_HERE,
238 base::Bind(&SignAndStoreSettingsOperation::AssembleAndSignPolicy,
239 base::Passed(&new_settings_), username_, owner_key()),
240 base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob,
241 weak_factory_.GetWeakPtr()));
242 }
243
244 // static
245 std::string SignAndStoreSettingsOperation::AssembleAndSignPolicy(
246 scoped_ptr<em::ChromeDeviceSettingsProto> device_settings,
247 const std::string& username,
248 scoped_refptr<OwnerKey> owner_key) {
249 // Assemble the policy.
250 em::PolicyFetchResponse policy_response;
251 em::PolicyData policy;
252 policy.set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
253 policy.set_timestamp((base::Time::NowFromSystemTime() -
254 base::Time::UnixEpoch()).InMilliseconds());
255 policy.set_username(username);
256 if (!device_settings->SerializeToString(policy.mutable_policy_value()) ||
257 !policy.SerializeToString(policy_response.mutable_policy_data())) {
258 LOG(ERROR) << "Failed to encode policy payload.";
259 return std::string();
260 }
261
262 // Generate the signature.
263 scoped_ptr<crypto::SignatureCreator> signature_creator(
264 crypto::SignatureCreator::Create(owner_key->private_key()));
265 signature_creator->Update(
266 reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
267 policy_response.policy_data().size());
268 std::vector<uint8> signature_bytes;
269 std::string policy_blob;
270 if (!signature_creator->Final(&signature_bytes)) {
271 LOG(ERROR) << "Failed to create policy signature.";
272 return std::string();
273 }
274
275 policy_response.mutable_policy_data_signature()->assign(
276 reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
277 signature_bytes.size());
278 return policy_response.SerializeAsString();
279 }
280
281 void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob(
282 std::string device_settings_blob) {
283 if (device_settings_blob.empty()) {
284 ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
285 return;
286 }
287
288 session_manager_client()->StoreDevicePolicy(
289 device_settings_blob,
290 base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult,
291 weak_factory_.GetWeakPtr()));
292 }
293
294 void SignAndStoreSettingsOperation::HandleStoreResult(bool success) {
295 if (!success)
296 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
297 else
298 StartLoading();
299 }
300
301 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698