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

Side by Side Diff: chrome/browser/policy/cros_user_policy_cache.cc

Issue 7233006: Store/Retrieve CrOS user policy in session_manager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 8 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/policy/cros_user_policy_cache.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/file_path.h"
13 #include "base/file_util.h"
14 #include "chrome/browser/chromeos/dbus/session_manager_client.h"
15 #include "chrome/browser/policy/proto/cloud_policy.pb.h"
16 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
17 #include "chrome/browser/policy/proto/device_management_local.pb.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "crypto/signature_verifier.h"
20
21 using content::BrowserThread;
22
23 namespace em = enterprise_management;
24
25 namespace policy {
26
27 // Decodes a CloudPolicySettings object into a policy map. The implementation is
28 // generated code in policy/cloud_policy_generated.cc.
29 void DecodePolicy(const em::CloudPolicySettings& policy,
30 PolicyMap* policies);
31
32 // Takes care of sending a new policy blob to session manager and reports back
33 // the status through a callback.
34 class CrosUserPolicyCache::StorePolicyOperation {
35 public:
36 typedef base::Callback<void(bool)> StatusCallback;
37
38 StorePolicyOperation(
39 const em::PolicyFetchResponse& policy,
40 chromeos::SessionManagerClient* session_manager_client,
41 const StatusCallback& callback);
42
43 // Executes the operation.
44 void Run();
45
46 // Cancels a pending callback.
47 void Cancel();
48
49 const em::PolicyFetchResponse& policy() { return policy_; }
50
51 private:
52 // StorePolicyOperation manages its own lifetime.
53 ~StorePolicyOperation() {}
54
55 // A callback function suitable for passing to session_manager_client.
56 void OnPolicyStored(bool result);
57
58 em::PolicyFetchResponse policy_;
59 chromeos::SessionManagerClient* session_manager_client_;
60 StatusCallback callback_;
61
62 DISALLOW_COPY_AND_ASSIGN(StorePolicyOperation);
63 };
64
65 // static
pastarmovj 2012/04/05 09:56:21 The constructor is static?
Mattias Nissler (ping if slow) 2012/04/05 10:26:04 Done.
66 CrosUserPolicyCache::StorePolicyOperation::StorePolicyOperation(
67 const em::PolicyFetchResponse& policy,
68 chromeos::SessionManagerClient* session_manager_client,
69 const StatusCallback& callback)
70 : policy_(policy),
71 session_manager_client_(session_manager_client),
72 callback_(callback) {}
73
74 void CrosUserPolicyCache::StorePolicyOperation::Run() {
75 std::string serialized;
76 if (!policy_.SerializeToString(&serialized)) {
77 LOG(ERROR) << "Failed to serialize policy protobuf!";
78 callback_.Run(false);
79 delete this;
80 }
81 session_manager_client_->StoreUserPolicy(
82 serialized,
83 base::Bind(&CrosUserPolicyCache::StorePolicyOperation::OnPolicyStored,
84 base::Unretained(this)));
85 }
86
87 void CrosUserPolicyCache::StorePolicyOperation::Cancel() {
88 callback_.Reset();
89 }
90
91 void CrosUserPolicyCache::StorePolicyOperation::OnPolicyStored(bool result) {
92 if (!callback_.is_null())
93 callback_.Run(result);
94 delete this;
95 }
96
97 class CrosUserPolicyCache::RetrievePolicyOperation {
98 public:
99 typedef base::Callback<void(bool, const em::PolicyFetchResponse&)>
100 ResultCallback;
101
102 RetrievePolicyOperation(
103 chromeos::SessionManagerClient* session_manager_client,
104 const ResultCallback& callback);
105
106 // Executes the operation.
107 void Run();
108
109 // Cancels a pending callback.
110 void Cancel();
111
112 private:
113 explicit RetrievePolicyOperation(const ResultCallback& callback);
pastarmovj 2012/04/05 09:56:21 Is this one needed/implemented?
Mattias Nissler (ping if slow) 2012/04/05 10:26:04 No. Done.
114
115 // RetrievePolicyOperation manages its own lifetime.
116 ~RetrievePolicyOperation() {}
117
118 // Decodes the policy data and triggers a signature check.
119 void OnPolicyRetrieved(const std::string& policy_blob);
120
121 chromeos::SessionManagerClient* session_manager_client_;
122 ResultCallback callback_;
123
124 DISALLOW_COPY_AND_ASSIGN(RetrievePolicyOperation);
125 };
126
127 // static
pastarmovj 2012/04/05 09:56:21 Ditto.
Mattias Nissler (ping if slow) 2012/04/05 10:26:04 Done.
128 CrosUserPolicyCache::RetrievePolicyOperation::RetrievePolicyOperation(
129 chromeos::SessionManagerClient* session_manager_client,
130 const ResultCallback& callback)
131 : session_manager_client_(session_manager_client),
132 callback_(callback) {}
133
134 void CrosUserPolicyCache::RetrievePolicyOperation::Run() {
135 session_manager_client_->RetrieveUserPolicy(
136 base::Bind(
137 &CrosUserPolicyCache::RetrievePolicyOperation::OnPolicyRetrieved,
138 base::Unretained(this)));
139 }
140
141 void CrosUserPolicyCache::RetrievePolicyOperation::Cancel() {
142 callback_.Reset();
143 }
144
145 void CrosUserPolicyCache::RetrievePolicyOperation::OnPolicyRetrieved(
146 const std::string& policy_blob) {
147 bool status = true;
148 em::PolicyFetchResponse policy;
149 if (!policy.ParseFromString(policy_blob) ||
150 !policy.has_policy_data() ||
151 !policy.has_policy_data_signature()) {
152 LOG(ERROR) << "Failed to decode policy";
153 status = false;
154 }
155
156 if (!callback_.is_null())
157 callback_.Run(status, policy);
158 delete this;
159 }
160
161 CrosUserPolicyCache::CrosUserPolicyCache(
162 chromeos::SessionManagerClient* session_manager_client,
163 CloudPolicyDataStore* data_store,
164 bool wait_for_policy_fetch,
165 const FilePath& legacy_token_cache_file,
166 const FilePath& legacy_policy_cache_file)
167 : session_manager_client_(session_manager_client),
168 data_store_(data_store),
169 pending_policy_fetch_(wait_for_policy_fetch),
170 pending_disk_cache_load_(true),
171 store_operation_(NULL),
172 retrieve_operation_(NULL),
173 legacy_cache_dir_(legacy_token_cache_file.DirName()),
174 ALLOW_THIS_IN_INITIALIZER_LIST(
175 legacy_token_cache_delegate_factory_(this)),
176 ALLOW_THIS_IN_INITIALIZER_LIST(
177 legacy_policy_cache_delegate_factory_(this)) {
178 DCHECK_EQ(legacy_token_cache_file.DirName().value(),
179 legacy_policy_cache_file.DirName().value());
180
181 legacy_token_loader_ =
182 new UserPolicyTokenLoader(
183 legacy_token_cache_delegate_factory_.GetWeakPtr(),
184 legacy_token_cache_file);
185 legacy_policy_cache_ =
186 new UserPolicyDiskCache(
187 legacy_policy_cache_delegate_factory_.GetWeakPtr(),
188 legacy_policy_cache_file);
189 }
190
191 CrosUserPolicyCache::~CrosUserPolicyCache() {
192 CancelStore();
193 CancelRetrieve();
194 }
195
196 void CrosUserPolicyCache::Load() {
197 retrieve_operation_ =
198 new RetrievePolicyOperation(
199 session_manager_client_,
200 base::Bind(&CrosUserPolicyCache::OnPolicyLoadDone,
201 base::Unretained(this)));
202 retrieve_operation_->Run();
203 }
204
205 bool CrosUserPolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) {
206 CancelStore();
207 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
208 pending_policy_fetch_ = true;
209 store_operation_ =
210 new StorePolicyOperation(policy,
211 session_manager_client_,
212 base::Bind(&CrosUserPolicyCache::OnPolicyStored,
213 base::Unretained(this)));
214 store_operation_->Run();
215 return true;
216 }
217
218 void CrosUserPolicyCache::SetUnmanaged() {
219 base::Time now(base::Time::NowFromSystemTime());
220 SetUnmanagedInternal(now);
221
222 // Construct a policy blob with unmanaged state.
223 em::PolicyData policy_data;
224 policy_data.set_policy_type(data_store_->policy_type());
225 policy_data.set_timestamp((now - base::Time::UnixEpoch()).InMilliseconds());
226 policy_data.set_state(em::PolicyData::UNMANAGED);
227
228 em::PolicyFetchResponse policy;
229 if (!policy_data.SerializeToString(policy.mutable_policy_data())) {
230 LOG(ERROR) << "Failed to serialize policy_data";
231 return;
232 }
233
234 SetPolicy(policy);
235 }
236
237 void CrosUserPolicyCache::SetFetchingDone() {
238 // If there is a pending policy store or reload, wait for that to complete
239 // before reporting fetching done.
240 if (store_operation_ || retrieve_operation_)
241 return;
242
243 pending_policy_fetch_ = false;
244 CheckIfDone();
245 }
246
247 bool CrosUserPolicyCache::DecodePolicyData(const em::PolicyData& policy_data,
248 PolicyMap* policies) {
249 em::CloudPolicySettings policy;
250 if (!policy.ParseFromString(policy_data.policy_value())) {
251 LOG(WARNING) << "Failed to parse CloudPolicySettings protobuf.";
252 return false;
253 }
254 DecodePolicy(policy, policies);
255 return true;
256 }
257
258 void CrosUserPolicyCache::OnTokenLoaded(const std::string& token,
259 const std::string& device_id) {
260 if (token.empty())
261 LOG(WARNING) << "Failed to load legacy token cache";
262
263 data_store_->set_device_id(device_id);
264 data_store_->SetDeviceToken(token, true);
265 }
266
267 void CrosUserPolicyCache::OnDiskCacheLoaded(
268 UserPolicyDiskCache::LoadResult result,
269 const em::CachedCloudPolicyResponse& policy) {
270 if (result == UserPolicyDiskCache::LOAD_RESULT_SUCCESS) {
271 if (policy.unmanaged())
272 SetUnmanagedInternal(base::Time::FromTimeT(policy.timestamp()));
273 else if (policy.has_cloud_policy())
274 InstallLegacyPolicy(policy.cloud_policy());
275 } else {
276 LOG(WARNING) << "Failed to load legacy policy cache " << result;
277 }
278
279 pending_disk_cache_load_ = false;
280 CheckIfDone();
281 }
282
283 void CrosUserPolicyCache::OnPolicyStored(bool result) {
284 DCHECK(store_operation_);
285 CancelStore();
286 if (result) {
287 // Policy is stored successfully, reload from session_manager and apply.
288 // This helps us making sure we only use policy that session_manager has
289 // checked and confirmed to be good.
290 CancelRetrieve();
291 retrieve_operation_ =
292 new RetrievePolicyOperation(
293 session_manager_client_,
294 base::Bind(&CrosUserPolicyCache::OnPolicyReloadDone,
295 base::Unretained(this)));
296 retrieve_operation_->Run();
297
298 // Now that the new policy blob is installed, remove the old cache dir.
299 if (!legacy_cache_dir_.empty()) {
300 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
301 base::Bind(&RemoveLegacyCacheDir,
302 legacy_cache_dir_));
303 }
304 } else {
305 LOG(ERROR) << "Failed to store user policy.";
306 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
307 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
308 pending_policy_fetch_ = false;
309 CheckIfDone();
310 }
311 }
312
313 void CrosUserPolicyCache::OnPolicyLoadDone(
314 bool result,
315 const em::PolicyFetchResponse& policy) {
316 DCHECK(retrieve_operation_);
317 CancelRetrieve();
318 if (!result) {
319 LOG(WARNING) << "No user policy present, trying legacy caches.";
320 legacy_token_loader_->Load();
321 legacy_policy_cache_->Load();
322 return;
323 }
324
325 // We have new-style policy, no need to clean up.
326 legacy_cache_dir_.clear();
327
328 em::PolicyData policy_data;
329 if (!policy_data.ParseFromString(policy.policy_data())) {
330 LOG(WARNING) << "Failed to parse PolicyData protobuf.";
331 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
332 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
333 data_store_->SetDeviceToken(std::string(), true);
334 } else if (policy_data.request_token().empty() ||
335 policy_data.username().empty() ||
pastarmovj 2012/04/05 09:56:21 Shouldn't those lines aline with the ( of the if?
Mattias Nissler (ping if slow) 2012/04/05 10:26:04 Absolutely. Done.
336 policy_data.device_id().empty()) {
337 LOG(WARNING) << "Policy protobuf is missing credentials";
338 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
339 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
340 data_store_->SetDeviceToken(std::string(), true);
341 } else {
342 data_store_->set_device_id(policy_data.device_id());
343 data_store_->SetDeviceToken(policy_data.request_token(), true);
344 if (SetPolicyInternal(policy, NULL, true))
345 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
346 }
347
348 pending_disk_cache_load_ = false;
349 CheckIfDone();
350 }
351
352 void CrosUserPolicyCache::OnPolicyReloadDone(
353 bool result,
354 const em::PolicyFetchResponse& policy) {
355 DCHECK(retrieve_operation_);
356 CancelRetrieve();
357 if (result) {
358 if (SetPolicyInternal(policy, NULL, false))
359 set_last_policy_refresh_time(base::Time::NowFromSystemTime());
360 } else {
361 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
362 CloudPolicySubsystem::POLICY_LOCAL_ERROR);
363 }
364 pending_policy_fetch_ = false;
365 CheckIfDone();
366 }
367
368 void CrosUserPolicyCache::CancelStore() {
369 if (store_operation_) {
370 store_operation_->Cancel();
371 store_operation_ = NULL;
372 }
373 }
374
375 void CrosUserPolicyCache::CancelRetrieve() {
376 if (retrieve_operation_) {
377 retrieve_operation_->Cancel();
378 retrieve_operation_ = NULL;
379 }
380 }
381
382 void CrosUserPolicyCache::CheckIfDone() {
383 if (!pending_policy_fetch_ && !pending_disk_cache_load_) {
384 if (!IsReady())
385 SetReady();
386 CloudPolicyCacheBase::SetFetchingDone();
387 }
388 }
389
390 void CrosUserPolicyCache::InstallLegacyPolicy(
391 const em::PolicyFetchResponse& policy) {
392 em::PolicyFetchResponse mutable_policy(policy);
393 mutable_policy.clear_policy_data_signature();
394 mutable_policy.clear_new_public_key();
395 mutable_policy.clear_new_public_key_signature();
396 em::PolicyData policy_data;
397 if (!policy_data.ParseFromString(mutable_policy.policy_data())) {
398 LOG(ERROR) << "Failed to parse policy data.";
399 return;
400 }
401
402 policy_data.clear_public_key_version();
403 if (!policy_data.SerializeToString(mutable_policy.mutable_policy_data())) {
404 LOG(ERROR) << "Failed to serialize policy data.";
405 return;
406 }
407
408 base::Time timestamp;
409 if (SetPolicyInternal(mutable_policy, &timestamp, true))
410 set_last_policy_refresh_time(timestamp);
411 }
412
413 // static
414 void CrosUserPolicyCache::RemoveLegacyCacheDir(const FilePath& dir) {
415 if (!file_util::Delete(dir, true))
416 PLOG(ERROR) << "Failed to remove " << dir.value();
417 }
418
419 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698