| OLD | NEW |
| (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/user_cloud_policy_store_chromeos.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/callback.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/memory/ref_counted.h" | |
| 13 #include "base/metrics/histogram.h" | |
| 14 #include "base/stl_util.h" | |
| 15 #include "base/stringprintf.h" | |
| 16 #include "chrome/browser/policy/proto/cloud_policy.pb.h" | |
| 17 #include "chrome/browser/policy/proto/device_management_local.pb.h" | |
| 18 #include "chrome/browser/policy/user_policy_disk_cache.h" | |
| 19 #include "chrome/browser/policy/user_policy_token_loader.h" | |
| 20 #include "chromeos/dbus/cryptohome_client.h" | |
| 21 #include "chromeos/dbus/session_manager_client.h" | |
| 22 #include "content/public/browser/browser_thread.h" | |
| 23 #include "google_apis/gaia/gaia_auth_util.h" | |
| 24 | |
| 25 namespace em = enterprise_management; | |
| 26 | |
| 27 namespace policy { | |
| 28 | |
| 29 namespace { | |
| 30 | |
| 31 // Path within |user_policy_key_dir_| that contains the policy key. | |
| 32 // "%s" must be substituted with the sanitized username. | |
| 33 const base::FilePath::CharType kPolicyKeyFile[] = | |
| 34 FILE_PATH_LITERAL("%s/policy.pub"); | |
| 35 | |
| 36 // Maximum key size that will be loaded, in bytes. | |
| 37 const int kKeySizeLimit = 16 * 1024; | |
| 38 | |
| 39 enum ValidationFailure { | |
| 40 VALIDATION_FAILURE_DBUS, | |
| 41 VALIDATION_FAILURE_LOAD_KEY, | |
| 42 VALIDATION_FAILURE_SIZE, | |
| 43 }; | |
| 44 | |
| 45 void SampleValidationFailure(ValidationFailure sample) { | |
| 46 UMA_HISTOGRAM_ENUMERATION("Enterprise.UserPolicyValidationFailure", | |
| 47 sample, | |
| 48 VALIDATION_FAILURE_SIZE); | |
| 49 } | |
| 50 | |
| 51 } // namespace | |
| 52 | |
| 53 // Helper class for loading legacy policy caches. | |
| 54 class LegacyPolicyCacheLoader : public UserPolicyTokenLoader::Delegate, | |
| 55 public UserPolicyDiskCache::Delegate { | |
| 56 public: | |
| 57 typedef base::Callback<void(const std::string&, | |
| 58 const std::string&, | |
| 59 CloudPolicyStore::Status, | |
| 60 scoped_ptr<em::PolicyFetchResponse>)> Callback; | |
| 61 | |
| 62 LegacyPolicyCacheLoader(const base::FilePath& token_cache_file, | |
| 63 const base::FilePath& policy_cache_file); | |
| 64 virtual ~LegacyPolicyCacheLoader(); | |
| 65 | |
| 66 // Starts loading, and reports the result to |callback| when done. | |
| 67 void Load(const Callback& callback); | |
| 68 | |
| 69 // UserPolicyTokenLoader::Delegate: | |
| 70 virtual void OnTokenLoaded(const std::string& token, | |
| 71 const std::string& device_id) OVERRIDE; | |
| 72 | |
| 73 // UserPolicyDiskCache::Delegate: | |
| 74 virtual void OnDiskCacheLoaded( | |
| 75 UserPolicyDiskCache::LoadResult result, | |
| 76 const em::CachedCloudPolicyResponse& policy) OVERRIDE; | |
| 77 | |
| 78 private: | |
| 79 // Checks whether the load operations from the legacy caches completed. If so, | |
| 80 // fires the appropriate notification. | |
| 81 void CheckLoadFinished(); | |
| 82 | |
| 83 // Maps a disk cache LoadResult to a CloudPolicyStore::Status. | |
| 84 static CloudPolicyStore::Status TranslateLoadResult( | |
| 85 UserPolicyDiskCache::LoadResult result); | |
| 86 | |
| 87 base::WeakPtrFactory<LegacyPolicyCacheLoader> weak_factory_; | |
| 88 | |
| 89 scoped_refptr<UserPolicyTokenLoader> token_loader_; | |
| 90 scoped_refptr<UserPolicyDiskCache> policy_cache_; | |
| 91 | |
| 92 std::string dm_token_; | |
| 93 std::string device_id_; | |
| 94 bool has_policy_; | |
| 95 scoped_ptr<em::PolicyFetchResponse> policy_; | |
| 96 CloudPolicyStore::Status status_; | |
| 97 | |
| 98 Callback callback_; | |
| 99 | |
| 100 DISALLOW_COPY_AND_ASSIGN(LegacyPolicyCacheLoader); | |
| 101 }; | |
| 102 | |
| 103 LegacyPolicyCacheLoader::LegacyPolicyCacheLoader( | |
| 104 const base::FilePath& token_cache_file, | |
| 105 const base::FilePath& policy_cache_file) | |
| 106 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | |
| 107 has_policy_(false), | |
| 108 status_(CloudPolicyStore::STATUS_OK) { | |
| 109 token_loader_ = new UserPolicyTokenLoader(weak_factory_.GetWeakPtr(), | |
| 110 token_cache_file); | |
| 111 policy_cache_ = new UserPolicyDiskCache(weak_factory_.GetWeakPtr(), | |
| 112 policy_cache_file); | |
| 113 } | |
| 114 | |
| 115 LegacyPolicyCacheLoader::~LegacyPolicyCacheLoader() {} | |
| 116 | |
| 117 void LegacyPolicyCacheLoader::Load(const Callback& callback) { | |
| 118 callback_ = callback; | |
| 119 token_loader_->Load(); | |
| 120 policy_cache_->Load(); | |
| 121 } | |
| 122 | |
| 123 void LegacyPolicyCacheLoader::OnTokenLoaded(const std::string& token, | |
| 124 const std::string& device_id) { | |
| 125 dm_token_ = token; | |
| 126 device_id_ = device_id; | |
| 127 token_loader_ = NULL; | |
| 128 CheckLoadFinished(); | |
| 129 } | |
| 130 | |
| 131 void LegacyPolicyCacheLoader::OnDiskCacheLoaded( | |
| 132 UserPolicyDiskCache::LoadResult result, | |
| 133 const em::CachedCloudPolicyResponse& policy) { | |
| 134 status_ = TranslateLoadResult(result); | |
| 135 if (result == UserPolicyDiskCache::LOAD_RESULT_SUCCESS) { | |
| 136 if (policy.has_cloud_policy()) | |
| 137 policy_.reset(new em::PolicyFetchResponse(policy.cloud_policy())); | |
| 138 } else { | |
| 139 LOG(WARNING) << "Failed to load legacy policy cache: " << result; | |
| 140 } | |
| 141 policy_cache_ = NULL; | |
| 142 CheckLoadFinished(); | |
| 143 } | |
| 144 | |
| 145 void LegacyPolicyCacheLoader::CheckLoadFinished() { | |
| 146 if (!token_loader_.get() && !policy_cache_.get()) | |
| 147 callback_.Run(dm_token_, device_id_, status_, policy_.Pass()); | |
| 148 } | |
| 149 | |
| 150 // static | |
| 151 CloudPolicyStore::Status LegacyPolicyCacheLoader::TranslateLoadResult( | |
| 152 UserPolicyDiskCache::LoadResult result) { | |
| 153 switch (result) { | |
| 154 case UserPolicyDiskCache::LOAD_RESULT_SUCCESS: | |
| 155 case UserPolicyDiskCache::LOAD_RESULT_NOT_FOUND: | |
| 156 return CloudPolicyStore::STATUS_OK; | |
| 157 case UserPolicyDiskCache::LOAD_RESULT_PARSE_ERROR: | |
| 158 case UserPolicyDiskCache::LOAD_RESULT_READ_ERROR: | |
| 159 return CloudPolicyStore::STATUS_LOAD_ERROR; | |
| 160 } | |
| 161 NOTREACHED(); | |
| 162 return CloudPolicyStore::STATUS_OK; | |
| 163 } | |
| 164 | |
| 165 UserCloudPolicyStoreChromeOS::UserCloudPolicyStoreChromeOS( | |
| 166 chromeos::CryptohomeClient* cryptohome_client, | |
| 167 chromeos::SessionManagerClient* session_manager_client, | |
| 168 const std::string& username, | |
| 169 const base::FilePath& user_policy_key_dir, | |
| 170 const base::FilePath& legacy_token_cache_file, | |
| 171 const base::FilePath& legacy_policy_cache_file) | |
| 172 : cryptohome_client_(cryptohome_client), | |
| 173 session_manager_client_(session_manager_client), | |
| 174 username_(username), | |
| 175 user_policy_key_dir_(user_policy_key_dir), | |
| 176 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | |
| 177 legacy_cache_dir_(legacy_token_cache_file.DirName()), | |
| 178 legacy_loader_(new LegacyPolicyCacheLoader(legacy_token_cache_file, | |
| 179 legacy_policy_cache_file)), | |
| 180 legacy_caches_loaded_(false), | |
| 181 policy_key_loaded_(false) {} | |
| 182 | |
| 183 UserCloudPolicyStoreChromeOS::~UserCloudPolicyStoreChromeOS() {} | |
| 184 | |
| 185 void UserCloudPolicyStoreChromeOS::Store( | |
| 186 const em::PolicyFetchResponse& policy) { | |
| 187 // Cancel all pending requests. | |
| 188 weak_factory_.InvalidateWeakPtrs(); | |
| 189 scoped_ptr<em::PolicyFetchResponse> response( | |
| 190 new em::PolicyFetchResponse(policy)); | |
| 191 EnsurePolicyKeyLoaded( | |
| 192 base::Bind(&UserCloudPolicyStoreChromeOS::ValidatePolicyForStore, | |
| 193 weak_factory_.GetWeakPtr(), | |
| 194 base::Passed(&response))); | |
| 195 } | |
| 196 | |
| 197 void UserCloudPolicyStoreChromeOS::Load() { | |
| 198 // Cancel all pending requests. | |
| 199 weak_factory_.InvalidateWeakPtrs(); | |
| 200 session_manager_client_->RetrieveUserPolicy( | |
| 201 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyRetrieved, | |
| 202 weak_factory_.GetWeakPtr())); | |
| 203 } | |
| 204 | |
| 205 void UserCloudPolicyStoreChromeOS::ValidatePolicyForStore( | |
| 206 scoped_ptr<em::PolicyFetchResponse> policy) { | |
| 207 // Create and configure a validator. | |
| 208 scoped_ptr<UserCloudPolicyValidator> validator = | |
| 209 CreateValidator(policy.Pass()); | |
| 210 validator->ValidateUsername(username_); | |
| 211 if (policy_key_.empty()) { | |
| 212 validator->ValidateInitialKey(); | |
| 213 } else { | |
| 214 const bool allow_rotation = true; | |
| 215 validator->ValidateSignature(policy_key_, allow_rotation); | |
| 216 } | |
| 217 | |
| 218 // Start validation. The Validator will delete itself once validation is | |
| 219 // complete. | |
| 220 validator.release()->StartValidation( | |
| 221 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated, | |
| 222 weak_factory_.GetWeakPtr())); | |
| 223 } | |
| 224 | |
| 225 void UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated( | |
| 226 UserCloudPolicyValidator* validator) { | |
| 227 validation_status_ = validator->status(); | |
| 228 | |
| 229 UMA_HISTOGRAM_ENUMERATION( | |
| 230 "Enterprise.UserPolicyValidationStoreStatus", | |
| 231 validation_status_, | |
| 232 UserCloudPolicyValidator::VALIDATION_POLICY_PARSE_ERROR + 1); | |
| 233 | |
| 234 if (!validator->success()) { | |
| 235 status_ = STATUS_VALIDATION_ERROR; | |
| 236 NotifyStoreError(); | |
| 237 return; | |
| 238 } | |
| 239 | |
| 240 std::string policy_blob; | |
| 241 if (!validator->policy()->SerializeToString(&policy_blob)) { | |
| 242 status_ = STATUS_SERIALIZE_ERROR; | |
| 243 NotifyStoreError(); | |
| 244 return; | |
| 245 } | |
| 246 | |
| 247 session_manager_client_->StoreUserPolicy( | |
| 248 policy_blob, | |
| 249 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyStored, | |
| 250 weak_factory_.GetWeakPtr())); | |
| 251 } | |
| 252 | |
| 253 void UserCloudPolicyStoreChromeOS::OnPolicyStored(bool success) { | |
| 254 if (!success) { | |
| 255 status_ = STATUS_STORE_ERROR; | |
| 256 NotifyStoreError(); | |
| 257 } else { | |
| 258 // Load the policy right after storing it, to make sure it was accepted by | |
| 259 // the session manager. An additional validation is performed after the | |
| 260 // load; reload the key for that validation too, in case it was rotated. | |
| 261 ReloadPolicyKey(base::Bind(&UserCloudPolicyStoreChromeOS::Load, | |
| 262 weak_factory_.GetWeakPtr())); | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 void UserCloudPolicyStoreChromeOS::OnPolicyRetrieved( | |
| 267 const std::string& policy_blob) { | |
| 268 if (policy_blob.empty()) { | |
| 269 // Policy fetch failed. Try legacy caches if we haven't done that already. | |
| 270 if (!legacy_caches_loaded_ && legacy_loader_.get()) { | |
| 271 legacy_caches_loaded_ = true; | |
| 272 legacy_loader_->Load( | |
| 273 base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished, | |
| 274 weak_factory_.GetWeakPtr())); | |
| 275 } else { | |
| 276 // session_manager doesn't have policy. Adjust internal state and notify | |
| 277 // the world about the policy update. | |
| 278 policy_.reset(); | |
| 279 NotifyStoreLoaded(); | |
| 280 } | |
| 281 return; | |
| 282 } | |
| 283 | |
| 284 // Policy is supplied by session_manager. Disregard legacy data from now on. | |
| 285 legacy_loader_.reset(); | |
| 286 | |
| 287 scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse()); | |
| 288 if (!policy->ParseFromString(policy_blob)) { | |
| 289 status_ = STATUS_PARSE_ERROR; | |
| 290 NotifyStoreError(); | |
| 291 return; | |
| 292 } | |
| 293 | |
| 294 // Load |policy_key_| to verify the loaded policy. | |
| 295 EnsurePolicyKeyLoaded( | |
| 296 base::Bind(&UserCloudPolicyStoreChromeOS::ValidateRetrievedPolicy, | |
| 297 weak_factory_.GetWeakPtr(), | |
| 298 base::Passed(&policy))); | |
| 299 } | |
| 300 | |
| 301 void UserCloudPolicyStoreChromeOS::ValidateRetrievedPolicy( | |
| 302 scoped_ptr<em::PolicyFetchResponse> policy) { | |
| 303 // Create and configure a validator for the loaded policy. | |
| 304 scoped_ptr<UserCloudPolicyValidator> validator = | |
| 305 CreateValidator(policy.Pass()); | |
| 306 validator->ValidateUsername(username_); | |
| 307 const bool allow_rotation = false; | |
| 308 validator->ValidateSignature(policy_key_, allow_rotation); | |
| 309 // Start validation. The Validator will delete itself once validation is | |
| 310 // complete. | |
| 311 validator.release()->StartValidation( | |
| 312 base::Bind(&UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated, | |
| 313 weak_factory_.GetWeakPtr())); | |
| 314 } | |
| 315 | |
| 316 void UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated( | |
| 317 UserCloudPolicyValidator* validator) { | |
| 318 validation_status_ = validator->status(); | |
| 319 | |
| 320 UMA_HISTOGRAM_ENUMERATION( | |
| 321 "Enterprise.UserPolicyValidationLoadStatus", | |
| 322 validation_status_, | |
| 323 UserCloudPolicyValidator::VALIDATION_POLICY_PARSE_ERROR + 1); | |
| 324 | |
| 325 if (!validator->success()) { | |
| 326 status_ = STATUS_VALIDATION_ERROR; | |
| 327 NotifyStoreError(); | |
| 328 return; | |
| 329 } | |
| 330 | |
| 331 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); | |
| 332 status_ = STATUS_OK; | |
| 333 | |
| 334 // Policy has been loaded successfully. This indicates that new-style policy | |
| 335 // is working, so the legacy cache directory can be removed. | |
| 336 if (!legacy_cache_dir_.empty()) { | |
| 337 content::BrowserThread::PostBlockingPoolTask( | |
| 338 FROM_HERE, | |
| 339 base::Bind(&UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir, | |
| 340 legacy_cache_dir_)); | |
| 341 legacy_cache_dir_.clear(); | |
| 342 } | |
| 343 NotifyStoreLoaded(); | |
| 344 } | |
| 345 | |
| 346 void UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished( | |
| 347 const std::string& dm_token, | |
| 348 const std::string& device_id, | |
| 349 Status status, | |
| 350 scoped_ptr<em::PolicyFetchResponse> policy) { | |
| 351 status_ = status; | |
| 352 if (policy.get()) { | |
| 353 // Create and configure a validator for the loaded legacy policy. Note that | |
| 354 // the signature on this policy is not verified. | |
| 355 scoped_ptr<UserCloudPolicyValidator> validator = | |
| 356 CreateValidator(policy.Pass()); | |
| 357 validator->ValidateUsername(username_); | |
| 358 validator.release()->StartValidation( | |
| 359 base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated, | |
| 360 weak_factory_.GetWeakPtr(), | |
| 361 dm_token, | |
| 362 device_id)); | |
| 363 } else { | |
| 364 InstallLegacyTokens(dm_token, device_id); | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 void UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated( | |
| 369 const std::string& dm_token, | |
| 370 const std::string& device_id, | |
| 371 UserCloudPolicyValidator* validator) { | |
| 372 validation_status_ = validator->status(); | |
| 373 if (validator->success()) { | |
| 374 status_ = STATUS_OK; | |
| 375 InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); | |
| 376 | |
| 377 // Clear the public key version. The public key version field would | |
| 378 // otherwise indicate that we have key installed in the store when in fact | |
| 379 // we haven't. This may result in policy updates failing signature | |
| 380 // verification. | |
| 381 policy_->clear_public_key_version(); | |
| 382 } else { | |
| 383 status_ = STATUS_VALIDATION_ERROR; | |
| 384 } | |
| 385 | |
| 386 InstallLegacyTokens(dm_token, device_id); | |
| 387 } | |
| 388 | |
| 389 void UserCloudPolicyStoreChromeOS::InstallLegacyTokens( | |
| 390 const std::string& dm_token, | |
| 391 const std::string& device_id) { | |
| 392 // Write token and device ID to |policy_|, giving them precedence over the | |
| 393 // policy blob. This is to match the legacy behavior, which used token and | |
| 394 // device id exclusively from the token cache file. | |
| 395 if (!dm_token.empty() && !device_id.empty()) { | |
| 396 if (!policy_.get()) | |
| 397 policy_.reset(new em::PolicyData()); | |
| 398 policy_->set_request_token(dm_token); | |
| 399 policy_->set_device_id(device_id); | |
| 400 } | |
| 401 | |
| 402 // Tell the rest of the world that the policy load completed. | |
| 403 NotifyStoreLoaded(); | |
| 404 } | |
| 405 | |
| 406 // static | |
| 407 void UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir( | |
| 408 const base::FilePath& dir) { | |
| 409 if (file_util::PathExists(dir) && !file_util::Delete(dir, true)) | |
| 410 LOG(ERROR) << "Failed to remove cache dir " << dir.value(); | |
| 411 } | |
| 412 | |
| 413 void UserCloudPolicyStoreChromeOS::ReloadPolicyKey( | |
| 414 const base::Closure& callback) { | |
| 415 std::vector<uint8>* key = new std::vector<uint8>(); | |
| 416 content::BrowserThread::PostBlockingPoolTaskAndReply( | |
| 417 FROM_HERE, | |
| 418 base::Bind(&UserCloudPolicyStoreChromeOS::LoadPolicyKey, | |
| 419 policy_key_path_, | |
| 420 key), | |
| 421 base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyKeyReloaded, | |
| 422 weak_factory_.GetWeakPtr(), | |
| 423 base::Owned(key), | |
| 424 callback)); | |
| 425 } | |
| 426 | |
| 427 // static | |
| 428 void UserCloudPolicyStoreChromeOS::LoadPolicyKey(const base::FilePath& path, | |
| 429 std::vector<uint8>* key) { | |
| 430 if (!file_util::PathExists(path)) { | |
| 431 // There is no policy key the first time that a user fetches policy. If | |
| 432 // |path| does not exist then that is the most likely scenario, so there's | |
| 433 // no need to sample a failure. | |
| 434 VLOG(1) << "No key at " << path.value(); | |
| 435 return; | |
| 436 } | |
| 437 | |
| 438 int64 size; | |
| 439 if (!file_util::GetFileSize(path, &size)) { | |
| 440 LOG(ERROR) << "Could not get size of " << path.value(); | |
| 441 } else if (size == 0 || size > kKeySizeLimit) { | |
| 442 LOG(ERROR) << "Key at " << path.value() << " has bad size " << size; | |
| 443 } else { | |
| 444 key->resize(size); | |
| 445 int read_size = file_util::ReadFile( | |
| 446 path, reinterpret_cast<char*>(vector_as_array(key)), size); | |
| 447 if (read_size != size) { | |
| 448 LOG(ERROR) << "Failed to read key at " << path.value(); | |
| 449 key->clear(); | |
| 450 } | |
| 451 } | |
| 452 | |
| 453 if (key->empty()) | |
| 454 SampleValidationFailure(VALIDATION_FAILURE_LOAD_KEY); | |
| 455 } | |
| 456 | |
| 457 void UserCloudPolicyStoreChromeOS::OnPolicyKeyReloaded( | |
| 458 std::vector<uint8>* key, | |
| 459 const base::Closure& callback) { | |
| 460 policy_key_.swap(*key); | |
| 461 policy_key_loaded_ = true; | |
| 462 callback.Run(); | |
| 463 } | |
| 464 | |
| 465 void UserCloudPolicyStoreChromeOS::EnsurePolicyKeyLoaded( | |
| 466 const base::Closure& callback) { | |
| 467 if (policy_key_loaded_) { | |
| 468 callback.Run(); | |
| 469 } else { | |
| 470 // Get the hashed username that's part of the key's path, to determine | |
| 471 // |policy_key_path_|. | |
| 472 cryptohome_client_->GetSanitizedUsername(username_, | |
| 473 base::Bind(&UserCloudPolicyStoreChromeOS::OnGetSanitizedUsername, | |
| 474 weak_factory_.GetWeakPtr(), | |
| 475 callback)); | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 void UserCloudPolicyStoreChromeOS::OnGetSanitizedUsername( | |
| 480 const base::Closure& callback, | |
| 481 chromeos::DBusMethodCallStatus call_status, | |
| 482 const std::string& sanitized_username) { | |
| 483 // The default empty path will always yield an empty key. | |
| 484 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS && | |
| 485 !sanitized_username.empty()) { | |
| 486 policy_key_path_ = user_policy_key_dir_.Append( | |
| 487 base::StringPrintf(kPolicyKeyFile, sanitized_username.c_str())); | |
| 488 } else { | |
| 489 SampleValidationFailure(VALIDATION_FAILURE_DBUS); | |
| 490 } | |
| 491 ReloadPolicyKey(callback); | |
| 492 } | |
| 493 | |
| 494 } // namespace policy | |
| OLD | NEW |