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

Side by Side Diff: components/policy/core/common/cloud/user_cloud_policy_store.cc

Issue 116273002: Added support for signed policy blobs on desktop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix for ios. Created 6 years, 10 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/policy/core/common/cloud/user_cloud_policy_store.h" 5 #include "components/policy/core/common/cloud/user_cloud_policy_store.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/metrics/histogram.h"
10 #include "base/task_runner_util.h" 11 #include "base/task_runner_util.h"
11 #include "policy/proto/cloud_policy.pb.h" 12 #include "policy/proto/cloud_policy.pb.h"
12 #include "policy/proto/device_management_backend.pb.h" 13 #include "policy/proto/device_management_backend.pb.h"
14 #include "policy/proto/policy_signing_key.pb.h"
13 15
14 namespace em = enterprise_management; 16 namespace em = enterprise_management;
15 17
16 namespace policy { 18 namespace policy {
17 19
18 enum PolicyLoadStatus { 20 enum PolicyLoadStatus {
19 // Policy blob was successfully loaded and parsed. 21 // Policy blob was successfully loaded and parsed.
20 LOAD_RESULT_SUCCESS, 22 LOAD_RESULT_SUCCESS,
21 23
22 // No previously stored policy was found. 24 // No previously stored policy was found.
23 LOAD_RESULT_NO_POLICY_FILE, 25 LOAD_RESULT_NO_POLICY_FILE,
24 26
25 // Could not load the previously stored policy due to either a parse or 27 // Could not load the previously stored policy due to either a parse or
26 // file read error. 28 // file read error.
27 LOAD_RESULT_LOAD_ERROR, 29 LOAD_RESULT_LOAD_ERROR,
28 }; 30 };
29 31
30 // Struct containing the result of a policy load - if |status| == 32 // Struct containing the result of a policy load - if |status| ==
31 // LOAD_RESULT_SUCCESS, |policy| is initialized from the policy file on disk. 33 // LOAD_RESULT_SUCCESS, |policy| is initialized from the policy file on disk.
32 struct PolicyLoadResult { 34 struct PolicyLoadResult {
33 PolicyLoadStatus status; 35 PolicyLoadStatus status;
34 em::PolicyFetchResponse policy; 36 em::PolicyFetchResponse policy;
37 em::PolicySigningKey key;
35 }; 38 };
36 39
37 namespace { 40 namespace {
38 41
39 // Subdirectory in the user's profile for storing user policies. 42 // Subdirectory in the user's profile for storing user policies.
40 const base::FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Policy"); 43 const base::FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("Policy");
41 // File in the above directory for storing user policy data. 44 // File in the above directory for storing user policy data.
42 const base::FilePath::CharType kPolicyCacheFile[] = 45 const base::FilePath::CharType kPolicyCacheFile[] =
43 FILE_PATH_LITERAL("User Policy"); 46 FILE_PATH_LITERAL("User Policy");
44 47
48 // File in the above directory for storing policy signing key data.
49 const base::FilePath::CharType kKeyCacheFile[] =
50 FILE_PATH_LITERAL("Signing Key");
51
52 const char kMetricPolicyHasVerifiedCachedKey[] =
53 "Enterprise.PolicyHasVerifiedCachedKey";
54
45 // Loads policy from the backing file. Returns a PolicyLoadResult with the 55 // Loads policy from the backing file. Returns a PolicyLoadResult with the
46 // results of the fetch. 56 // results of the fetch.
47 policy::PolicyLoadResult LoadPolicyFromDisk(const base::FilePath& path) { 57 policy::PolicyLoadResult LoadPolicyFromDisk(
58 const base::FilePath& policy_path,
59 const base::FilePath& key_path) {
48 policy::PolicyLoadResult result; 60 policy::PolicyLoadResult result;
49 // If the backing file does not exist, just return. 61 // If the backing file does not exist, just return. We don't verify the key
50 if (!base::PathExists(path)) { 62 // path here, because the key is optional (the validation code will fail if
63 // the key does not exist but the loaded policy is unsigned).
64 if (!base::PathExists(policy_path)) {
51 result.status = policy::LOAD_RESULT_NO_POLICY_FILE; 65 result.status = policy::LOAD_RESULT_NO_POLICY_FILE;
52 return result; 66 return result;
53 } 67 }
54 std::string data; 68 std::string data;
55 if (!base::ReadFileToString(path, &data) || 69 // TODO(atwilson): Enforce a policy/key maxsize when ReadFileToString() can
56 !result.policy.ParseFromArray(data.c_str(), data.size())) { 70 // accept a max_size (http://crbug.com/339417).
57 LOG(WARNING) << "Failed to read or parse policy data from " << path.value(); 71 if (!base::ReadFileToString(policy_path, &data) ||
72 !result.policy.ParseFromString(data)) {
73 LOG(WARNING) << "Failed to read or parse policy data from "
74 << policy_path.value();
58 result.status = policy::LOAD_RESULT_LOAD_ERROR; 75 result.status = policy::LOAD_RESULT_LOAD_ERROR;
59 return result; 76 return result;
60 } 77 }
61 78
79 if (!base::ReadFileToString(key_path, &data) ||
80 !result.key.ParseFromString(data)) {
81 // Log an error on missing key data, but do not trigger a load failure
82 // for now since there are still old unsigned cached policy blobs in the
83 // wild with no associated key (see kMetricPolicyHasVerifiedCachedKey UMA
84 // stat below).
85 LOG(ERROR) << "Failed to read or parse key data from " << key_path.value();
86 result.key.clear_signing_key();
87 }
88
89 // Track the occurrence of valid cached keys - when this ratio gets high
90 // enough, we can update the code to reject unsigned policy or unverified
91 // keys.
92 UMA_HISTOGRAM_BOOLEAN(kMetricPolicyHasVerifiedCachedKey,
93 result.key.has_signing_key());
94
62 result.status = policy::LOAD_RESULT_SUCCESS; 95 result.status = policy::LOAD_RESULT_SUCCESS;
63 return result; 96 return result;
64 } 97 }
65 98
99 bool WriteStringToFile(const base::FilePath path, const std::string& data) {
100 if (!base::CreateDirectory(path.DirName())) {
101 DLOG(WARNING) << "Failed to create directory " << path.DirName().value();
102 return false;
103 }
104
105 int size = data.size();
106 if (file_util::WriteFile(path, data.c_str(), size) != size) {
107 DLOG(WARNING) << "Failed to write " << path.value();
108 return false;
109 }
110
111 return true;
112 }
113
66 // Stores policy to the backing file (must be called via a task on 114 // Stores policy to the backing file (must be called via a task on
67 // the background thread). 115 // the background thread).
68 void StorePolicyToDiskOnBackgroundThread( 116 void StorePolicyToDiskOnBackgroundThread(
69 const base::FilePath& path, 117 const base::FilePath& policy_path,
118 const base::FilePath& key_path,
70 const em::PolicyFetchResponse& policy) { 119 const em::PolicyFetchResponse& policy) {
71 DVLOG(1) << "Storing policy to " << path.value(); 120 DVLOG(1) << "Storing policy to " << policy_path.value();
72 std::string data; 121 std::string data;
73 if (!policy.SerializeToString(&data)) { 122 if (!policy.SerializeToString(&data)) {
74 DLOG(WARNING) << "Failed to serialize policy data"; 123 DLOG(WARNING) << "Failed to serialize policy data";
75 return; 124 return;
76 } 125 }
77 126
78 if (!base::CreateDirectory(path.DirName())) { 127 if (!WriteStringToFile(policy_path, data))
79 DLOG(WARNING) << "Failed to create directory " << path.DirName().value();
80 return; 128 return;
81 }
82 129
83 int size = data.size(); 130 if (policy.has_new_public_key()) {
84 if (file_util::WriteFile(path, data.c_str(), size) != size) { 131 // Write the new public key and its verification signature to a file.
85 DLOG(WARNING) << "Failed to write " << path.value(); 132 em::PolicySigningKey key_info;
133 key_info.set_signing_key(policy.new_public_key());
134 key_info.set_signing_key_signature(
135 policy.new_public_key_verification_signature());
136 std::string key_data;
137 if (!key_info.SerializeToString(&key_data)) {
138 DLOG(WARNING) << "Failed to serialize policy signing key";
139 return;
140 }
141
142 WriteStringToFile(key_path, key_data);
86 } 143 }
87 } 144 }
88 145
89 } // namespace 146 } // namespace
90 147
91 UserCloudPolicyStore::UserCloudPolicyStore( 148 UserCloudPolicyStore::UserCloudPolicyStore(
92 const base::FilePath& path, 149 const base::FilePath& policy_path,
150 const base::FilePath& key_path,
151 const std::string& verification_key,
93 scoped_refptr<base::SequencedTaskRunner> background_task_runner) 152 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
94 : UserCloudPolicyStoreBase(background_task_runner), 153 : UserCloudPolicyStoreBase(background_task_runner),
95 weak_factory_(this), 154 weak_factory_(this),
96 backing_file_path_(path) {} 155 policy_path_(policy_path),
156 key_path_(key_path),
157 verification_key_(verification_key) {}
97 158
98 UserCloudPolicyStore::~UserCloudPolicyStore() {} 159 UserCloudPolicyStore::~UserCloudPolicyStore() {}
99 160
100 // static 161 // static
101 scoped_ptr<UserCloudPolicyStore> UserCloudPolicyStore::Create( 162 scoped_ptr<UserCloudPolicyStore> UserCloudPolicyStore::Create(
102 const base::FilePath& profile_path, 163 const base::FilePath& profile_path,
164 const std::string& verification_key,
103 scoped_refptr<base::SequencedTaskRunner> background_task_runner) { 165 scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
104 base::FilePath path = 166 base::FilePath policy_path =
105 profile_path.Append(kPolicyDir).Append(kPolicyCacheFile); 167 profile_path.Append(kPolicyDir).Append(kPolicyCacheFile);
106 return make_scoped_ptr( 168 base::FilePath key_path =
107 new UserCloudPolicyStore(path, background_task_runner)); 169 profile_path.Append(kPolicyDir).Append(kKeyCacheFile);
170 return make_scoped_ptr(new UserCloudPolicyStore(
171 policy_path, key_path, verification_key, background_task_runner));
108 } 172 }
109 173
110 void UserCloudPolicyStore::SetSigninUsername(const std::string& username) { 174 void UserCloudPolicyStore::SetSigninUsername(const std::string& username) {
111 signin_username_ = username; 175 signin_username_ = username;
112 } 176 }
113 177
114 void UserCloudPolicyStore::LoadImmediately() { 178 void UserCloudPolicyStore::LoadImmediately() {
115 DVLOG(1) << "Initiating immediate policy load from disk"; 179 DVLOG(1) << "Initiating immediate policy load from disk";
116 // Cancel any pending Load/Store/Validate operations. 180 // Cancel any pending Load/Store/Validate operations.
117 weak_factory_.InvalidateWeakPtrs(); 181 weak_factory_.InvalidateWeakPtrs();
118 // Load the policy from disk... 182 // Load the policy from disk...
119 PolicyLoadResult result = LoadPolicyFromDisk(backing_file_path_); 183 PolicyLoadResult result = LoadPolicyFromDisk(policy_path_, key_path_);
120 // ...and install it, reporting success/failure to any observers. 184 // ...and install it, reporting success/failure to any observers.
121 PolicyLoaded(false, result); 185 PolicyLoaded(false, result);
122 } 186 }
123 187
124 void UserCloudPolicyStore::Clear() { 188 void UserCloudPolicyStore::Clear() {
125 background_task_runner()->PostTask( 189 background_task_runner()->PostTask(
126 FROM_HERE, 190 FROM_HERE,
127 base::Bind( 191 base::Bind(base::IgnoreResult(&base::DeleteFile), policy_path_, false));
128 base::IgnoreResult(&base::DeleteFile), backing_file_path_, false)); 192 background_task_runner()->PostTask(
193 FROM_HERE,
194 base::Bind(base::IgnoreResult(&base::DeleteFile), key_path_, false));
129 policy_.reset(); 195 policy_.reset();
130 policy_map_.Clear(); 196 policy_map_.Clear();
197 policy_key_.clear();
131 NotifyStoreLoaded(); 198 NotifyStoreLoaded();
132 } 199 }
133 200
134 void UserCloudPolicyStore::Load() { 201 void UserCloudPolicyStore::Load() {
135 DVLOG(1) << "Initiating policy load from disk"; 202 DVLOG(1) << "Initiating policy load from disk";
136 // Cancel any pending Load/Store/Validate operations. 203 // Cancel any pending Load/Store/Validate operations.
137 weak_factory_.InvalidateWeakPtrs(); 204 weak_factory_.InvalidateWeakPtrs();
138 205
139 // Start a new Load operation and have us get called back when it is 206 // Start a new Load operation and have us get called back when it is
140 // complete. 207 // complete.
141 base::PostTaskAndReplyWithResult( 208 base::PostTaskAndReplyWithResult(
142 background_task_runner(), 209 background_task_runner(),
143 FROM_HERE, 210 FROM_HERE,
144 base::Bind(&LoadPolicyFromDisk, backing_file_path_), 211 base::Bind(&LoadPolicyFromDisk, policy_path_, key_path_),
145 base::Bind(&UserCloudPolicyStore::PolicyLoaded, 212 base::Bind(&UserCloudPolicyStore::PolicyLoaded,
146 weak_factory_.GetWeakPtr(), true)); 213 weak_factory_.GetWeakPtr(), true));
147 } 214 }
148 215
149 void UserCloudPolicyStore::PolicyLoaded(bool validate_in_background, 216 void UserCloudPolicyStore::PolicyLoaded(bool validate_in_background,
150 PolicyLoadResult result) { 217 PolicyLoadResult result) {
151 switch (result.status) { 218 switch (result.status) {
152 case LOAD_RESULT_LOAD_ERROR: 219 case LOAD_RESULT_LOAD_ERROR:
153 status_ = STATUS_LOAD_ERROR; 220 status_ = STATUS_LOAD_ERROR;
154 NotifyStoreError(); 221 NotifyStoreError();
155 break; 222 break;
156 223
157 case LOAD_RESULT_NO_POLICY_FILE: 224 case LOAD_RESULT_NO_POLICY_FILE:
158 DVLOG(1) << "No policy found on disk"; 225 DVLOG(1) << "No policy found on disk";
159 NotifyStoreLoaded(); 226 NotifyStoreLoaded();
160 break; 227 break;
161 228
162 case LOAD_RESULT_SUCCESS: { 229 case LOAD_RESULT_SUCCESS: {
163 // Found policy on disk - need to validate it before it can be used. 230 // Found policy on disk - need to validate it before it can be used.
164 scoped_ptr<em::PolicyFetchResponse> cloud_policy( 231 scoped_ptr<em::PolicyFetchResponse> cloud_policy(
165 new em::PolicyFetchResponse(result.policy)); 232 new em::PolicyFetchResponse(result.policy));
233 scoped_ptr<em::PolicySigningKey> key(
234 new em::PolicySigningKey(result.key));
166 Validate(cloud_policy.Pass(), 235 Validate(cloud_policy.Pass(),
236 key.Pass(),
167 validate_in_background, 237 validate_in_background,
168 base::Bind( 238 base::Bind(
169 &UserCloudPolicyStore::InstallLoadedPolicyAfterValidation, 239 &UserCloudPolicyStore::InstallLoadedPolicyAfterValidation,
170 weak_factory_.GetWeakPtr())); 240 weak_factory_.GetWeakPtr(),
241 result.key.has_signing_key() ?
242 result.key.signing_key() : std::string()));
171 break; 243 break;
172 } 244 }
173 default: 245 default:
174 NOTREACHED(); 246 NOTREACHED();
175 } 247 }
176 } 248 }
177 249
178 void UserCloudPolicyStore::InstallLoadedPolicyAfterValidation( 250 void UserCloudPolicyStore::InstallLoadedPolicyAfterValidation(
251 const std::string& signing_key,
179 UserCloudPolicyValidator* validator) { 252 UserCloudPolicyValidator* validator) {
180 validation_status_ = validator->status(); 253 validation_status_ = validator->status();
181 if (!validator->success()) { 254 if (!validator->success()) {
182 DVLOG(1) << "Validation failed: status=" << validation_status_; 255 DVLOG(1) << "Validation failed: status=" << validation_status_;
183 status_ = STATUS_VALIDATION_ERROR; 256 status_ = STATUS_VALIDATION_ERROR;
184 NotifyStoreError(); 257 NotifyStoreError();
185 return; 258 return;
186 } 259 }
187 260
188 DVLOG(1) << "Validation succeeded - installing policy with dm_token: " << 261 DVLOG(1) << "Validation succeeded - installing policy with dm_token: " <<
189 validator->policy_data()->request_token(); 262 validator->policy_data()->request_token();
190 DVLOG(1) << "Device ID: " << validator->policy_data()->device_id(); 263 DVLOG(1) << "Device ID: " << validator->policy_data()->device_id();
191 264
192 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); 265 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
266 // Policy validation succeeded, so we know the signing key is good.
267 policy_key_ = signing_key;
193 status_ = STATUS_OK; 268 status_ = STATUS_OK;
194 NotifyStoreLoaded(); 269 NotifyStoreLoaded();
195 } 270 }
196 271
197 void UserCloudPolicyStore::Store(const em::PolicyFetchResponse& policy) { 272 void UserCloudPolicyStore::Store(const em::PolicyFetchResponse& policy) {
198 // Stop any pending requests to store policy, then validate the new policy 273 // Stop any pending requests to store policy, then validate the new policy
199 // before storing it. 274 // before storing it.
200 weak_factory_.InvalidateWeakPtrs(); 275 weak_factory_.InvalidateWeakPtrs();
201 scoped_ptr<em::PolicyFetchResponse> policy_copy( 276 scoped_ptr<em::PolicyFetchResponse> policy_copy(
202 new em::PolicyFetchResponse(policy)); 277 new em::PolicyFetchResponse(policy));
203 Validate(policy_copy.Pass(), 278 Validate(policy_copy.Pass(),
279 scoped_ptr<em::PolicySigningKey>(),
204 true, 280 true,
205 base::Bind(&UserCloudPolicyStore::StorePolicyAfterValidation, 281 base::Bind(&UserCloudPolicyStore::StorePolicyAfterValidation,
206 weak_factory_.GetWeakPtr())); 282 weak_factory_.GetWeakPtr()));
207 } 283 }
208 284
209 void UserCloudPolicyStore::Validate( 285 void UserCloudPolicyStore::Validate(
210 scoped_ptr<em::PolicyFetchResponse> policy, 286 scoped_ptr<em::PolicyFetchResponse> policy,
287 scoped_ptr<em::PolicySigningKey> cached_key,
211 bool validate_in_background, 288 bool validate_in_background,
212 const UserCloudPolicyValidator::CompletionCallback& callback) { 289 const UserCloudPolicyValidator::CompletionCallback& callback) {
290
291 const bool signed_policy = policy->has_policy_data_signature();
292
213 // Configure the validator. 293 // Configure the validator.
214 scoped_ptr<UserCloudPolicyValidator> validator = CreateValidator( 294 scoped_ptr<UserCloudPolicyValidator> validator = CreateValidator(
215 policy.Pass(), 295 policy.Pass(),
216 CloudPolicyValidatorBase::TIMESTAMP_NOT_BEFORE); 296 CloudPolicyValidatorBase::TIMESTAMP_NOT_BEFORE);
217 297
218 // Validate the username if the user is signed in. 298 // Validate the username if the user is signed in.
219 if (!signin_username_.empty()) 299 if (!signin_username_.empty()) {
300 DVLOG(1) << "Validating username: " << signin_username_;
220 validator->ValidateUsername(signin_username_); 301 validator->ValidateUsername(signin_username_);
302 }
303
304 // There are 4 cases:
305 //
306 // 1) Validation after loading from cache with no cached key.
307 // Action: Don't validate signature (migration from previously cached
308 // unsigned blob).
309 //
310 // 2) Validation after loading from cache with a cached key
311 // Action: Validate signature on policy blob but don't allow key rotation.
312 //
313 // 3) Validation after loading new policy from the server with no cached key
314 // Action: Validate as initial key provisioning (case where we are migrating
315 // from unsigned policy)
316 //
317 // 4) Validation after loading new policy from the server with a cached key
318 // Action: Validate as normal, and allow key rotation.
319 if (cached_key) {
320 // Loading from cache should not change the cached keys.
321 DCHECK(policy_key_.empty() || policy_key_ == cached_key->signing_key());
322 if (!signed_policy || !cached_key->has_signing_key()) {
323 // Case #1 - loading from cache with no signing key.
324 // TODO(atwilson): Reject policy with no cached key once
325 // kMetricPolicyHasVerifiedCachedKey rises to a high enough level.
326 DLOG(WARNING) << "Allowing unsigned cached blob for migration";
327 } else {
328 // Case #2 - loading from cache with a cached key - just do normal
329 // signature validation using this key. We're loading from cache so don't
330 // allow key rotation.
331 const bool no_rotation = false;
332 validator->ValidateSignature(cached_key->signing_key(),
333 verification_key_,
334 cached_key->signing_key_signature(),
335 no_rotation);
336 }
337 } else {
338 // No passed cached_key - this is not validating the initial policy load
339 // from cache, but rather an update from the server.
340 if (policy_key_.empty()) {
341 // Case #3 - no valid existing policy key, so this new policy fetch should
342 // include an initial key provision.
343 validator->ValidateInitialKey(verification_key_);
344 } else {
345 // Case #4 - verify new policy with existing key. We always allow key
346 // rotation - the verification key will prevent invalid policy from being
347 // injected. |policy_key_| is already known to be valid, so no
348 // verification signature is passed in.
349 const bool allow_rotation = true;
350 validator->ValidateSignature(
351 policy_key_, verification_key_, std::string(), allow_rotation);
352 }
353 }
221 354
222 if (validate_in_background) { 355 if (validate_in_background) {
223 // Start validation in the background. The Validator will free itself once 356 // Start validation in the background. The Validator will free itself once
224 // validation is complete. 357 // validation is complete.
225 validator.release()->StartValidation(callback); 358 validator.release()->StartValidation(callback);
226 } else { 359 } else {
227 // Run validation immediately and invoke the callback with the results. 360 // Run validation immediately and invoke the callback with the results.
228 validator->RunValidation(); 361 validator->RunValidation();
229 callback.Run(validator.get()); 362 callback.Run(validator.get());
230 } 363 }
231 } 364 }
232 365
233 void UserCloudPolicyStore::StorePolicyAfterValidation( 366 void UserCloudPolicyStore::StorePolicyAfterValidation(
234 UserCloudPolicyValidator* validator) { 367 UserCloudPolicyValidator* validator) {
235 validation_status_ = validator->status(); 368 validation_status_ = validator->status();
236 DVLOG(1) << "Policy validation complete: status = " << validation_status_; 369 DVLOG(1) << "Policy validation complete: status = " << validation_status_;
237 if (!validator->success()) { 370 if (!validator->success()) {
238 status_ = STATUS_VALIDATION_ERROR; 371 status_ = STATUS_VALIDATION_ERROR;
239 NotifyStoreError(); 372 NotifyStoreError();
240 return; 373 return;
241 } 374 }
242 375
243 // Persist the validated policy (just fire a task - don't bother getting a 376 // Persist the validated policy (just fire a task - don't bother getting a
244 // reply because we can't do anything if it fails). 377 // reply because we can't do anything if it fails).
245 background_task_runner()->PostTask( 378 background_task_runner()->PostTask(
246 FROM_HERE, 379 FROM_HERE,
247 base::Bind(&StorePolicyToDiskOnBackgroundThread, 380 base::Bind(&StorePolicyToDiskOnBackgroundThread,
248 backing_file_path_, *validator->policy())); 381 policy_path_, key_path_, *validator->policy()));
249 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); 382 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass());
383
384 // If the key was rotated, update our local cache of the key.
385 if (validator->policy()->has_new_public_key())
386 policy_key_ = validator->policy()->new_public_key();
250 status_ = STATUS_OK; 387 status_ = STATUS_OK;
251 NotifyStoreLoaded(); 388 NotifyStoreLoaded();
252 } 389 }
253 390
254 } // namespace policy 391 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698