Index: chrome/browser/policy/user_cloud_policy_store_chromeos.cc |
diff --git a/chrome/browser/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/policy/user_cloud_policy_store_chromeos.cc |
deleted file mode 100644 |
index 8112cef4d7629d5241ea8b111574a306f96a0df0..0000000000000000000000000000000000000000 |
--- a/chrome/browser/policy/user_cloud_policy_store_chromeos.cc |
+++ /dev/null |
@@ -1,494 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/policy/user_cloud_policy_store_chromeos.h" |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/callback.h" |
-#include "base/file_util.h" |
-#include "base/logging.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/metrics/histogram.h" |
-#include "base/stl_util.h" |
-#include "base/stringprintf.h" |
-#include "chrome/browser/policy/proto/cloud_policy.pb.h" |
-#include "chrome/browser/policy/proto/device_management_local.pb.h" |
-#include "chrome/browser/policy/user_policy_disk_cache.h" |
-#include "chrome/browser/policy/user_policy_token_loader.h" |
-#include "chromeos/dbus/cryptohome_client.h" |
-#include "chromeos/dbus/session_manager_client.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "google_apis/gaia/gaia_auth_util.h" |
- |
-namespace em = enterprise_management; |
- |
-namespace policy { |
- |
-namespace { |
- |
-// Path within |user_policy_key_dir_| that contains the policy key. |
-// "%s" must be substituted with the sanitized username. |
-const base::FilePath::CharType kPolicyKeyFile[] = |
- FILE_PATH_LITERAL("%s/policy.pub"); |
- |
-// Maximum key size that will be loaded, in bytes. |
-const int kKeySizeLimit = 16 * 1024; |
- |
-enum ValidationFailure { |
- VALIDATION_FAILURE_DBUS, |
- VALIDATION_FAILURE_LOAD_KEY, |
- VALIDATION_FAILURE_SIZE, |
-}; |
- |
-void SampleValidationFailure(ValidationFailure sample) { |
- UMA_HISTOGRAM_ENUMERATION("Enterprise.UserPolicyValidationFailure", |
- sample, |
- VALIDATION_FAILURE_SIZE); |
-} |
- |
-} // namespace |
- |
-// Helper class for loading legacy policy caches. |
-class LegacyPolicyCacheLoader : public UserPolicyTokenLoader::Delegate, |
- public UserPolicyDiskCache::Delegate { |
- public: |
- typedef base::Callback<void(const std::string&, |
- const std::string&, |
- CloudPolicyStore::Status, |
- scoped_ptr<em::PolicyFetchResponse>)> Callback; |
- |
- LegacyPolicyCacheLoader(const base::FilePath& token_cache_file, |
- const base::FilePath& policy_cache_file); |
- virtual ~LegacyPolicyCacheLoader(); |
- |
- // Starts loading, and reports the result to |callback| when done. |
- void Load(const Callback& callback); |
- |
- // UserPolicyTokenLoader::Delegate: |
- virtual void OnTokenLoaded(const std::string& token, |
- const std::string& device_id) OVERRIDE; |
- |
- // UserPolicyDiskCache::Delegate: |
- virtual void OnDiskCacheLoaded( |
- UserPolicyDiskCache::LoadResult result, |
- const em::CachedCloudPolicyResponse& policy) OVERRIDE; |
- |
- private: |
- // Checks whether the load operations from the legacy caches completed. If so, |
- // fires the appropriate notification. |
- void CheckLoadFinished(); |
- |
- // Maps a disk cache LoadResult to a CloudPolicyStore::Status. |
- static CloudPolicyStore::Status TranslateLoadResult( |
- UserPolicyDiskCache::LoadResult result); |
- |
- base::WeakPtrFactory<LegacyPolicyCacheLoader> weak_factory_; |
- |
- scoped_refptr<UserPolicyTokenLoader> token_loader_; |
- scoped_refptr<UserPolicyDiskCache> policy_cache_; |
- |
- std::string dm_token_; |
- std::string device_id_; |
- bool has_policy_; |
- scoped_ptr<em::PolicyFetchResponse> policy_; |
- CloudPolicyStore::Status status_; |
- |
- Callback callback_; |
- |
- DISALLOW_COPY_AND_ASSIGN(LegacyPolicyCacheLoader); |
-}; |
- |
-LegacyPolicyCacheLoader::LegacyPolicyCacheLoader( |
- const base::FilePath& token_cache_file, |
- const base::FilePath& policy_cache_file) |
- : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
- has_policy_(false), |
- status_(CloudPolicyStore::STATUS_OK) { |
- token_loader_ = new UserPolicyTokenLoader(weak_factory_.GetWeakPtr(), |
- token_cache_file); |
- policy_cache_ = new UserPolicyDiskCache(weak_factory_.GetWeakPtr(), |
- policy_cache_file); |
-} |
- |
-LegacyPolicyCacheLoader::~LegacyPolicyCacheLoader() {} |
- |
-void LegacyPolicyCacheLoader::Load(const Callback& callback) { |
- callback_ = callback; |
- token_loader_->Load(); |
- policy_cache_->Load(); |
-} |
- |
-void LegacyPolicyCacheLoader::OnTokenLoaded(const std::string& token, |
- const std::string& device_id) { |
- dm_token_ = token; |
- device_id_ = device_id; |
- token_loader_ = NULL; |
- CheckLoadFinished(); |
-} |
- |
-void LegacyPolicyCacheLoader::OnDiskCacheLoaded( |
- UserPolicyDiskCache::LoadResult result, |
- const em::CachedCloudPolicyResponse& policy) { |
- status_ = TranslateLoadResult(result); |
- if (result == UserPolicyDiskCache::LOAD_RESULT_SUCCESS) { |
- if (policy.has_cloud_policy()) |
- policy_.reset(new em::PolicyFetchResponse(policy.cloud_policy())); |
- } else { |
- LOG(WARNING) << "Failed to load legacy policy cache: " << result; |
- } |
- policy_cache_ = NULL; |
- CheckLoadFinished(); |
-} |
- |
-void LegacyPolicyCacheLoader::CheckLoadFinished() { |
- if (!token_loader_.get() && !policy_cache_.get()) |
- callback_.Run(dm_token_, device_id_, status_, policy_.Pass()); |
-} |
- |
-// static |
-CloudPolicyStore::Status LegacyPolicyCacheLoader::TranslateLoadResult( |
- UserPolicyDiskCache::LoadResult result) { |
- switch (result) { |
- case UserPolicyDiskCache::LOAD_RESULT_SUCCESS: |
- case UserPolicyDiskCache::LOAD_RESULT_NOT_FOUND: |
- return CloudPolicyStore::STATUS_OK; |
- case UserPolicyDiskCache::LOAD_RESULT_PARSE_ERROR: |
- case UserPolicyDiskCache::LOAD_RESULT_READ_ERROR: |
- return CloudPolicyStore::STATUS_LOAD_ERROR; |
- } |
- NOTREACHED(); |
- return CloudPolicyStore::STATUS_OK; |
-} |
- |
-UserCloudPolicyStoreChromeOS::UserCloudPolicyStoreChromeOS( |
- chromeos::CryptohomeClient* cryptohome_client, |
- chromeos::SessionManagerClient* session_manager_client, |
- const std::string& username, |
- const base::FilePath& user_policy_key_dir, |
- const base::FilePath& legacy_token_cache_file, |
- const base::FilePath& legacy_policy_cache_file) |
- : cryptohome_client_(cryptohome_client), |
- session_manager_client_(session_manager_client), |
- username_(username), |
- user_policy_key_dir_(user_policy_key_dir), |
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
- legacy_cache_dir_(legacy_token_cache_file.DirName()), |
- legacy_loader_(new LegacyPolicyCacheLoader(legacy_token_cache_file, |
- legacy_policy_cache_file)), |
- legacy_caches_loaded_(false), |
- policy_key_loaded_(false) {} |
- |
-UserCloudPolicyStoreChromeOS::~UserCloudPolicyStoreChromeOS() {} |
- |
-void UserCloudPolicyStoreChromeOS::Store( |
- const em::PolicyFetchResponse& policy) { |
- // Cancel all pending requests. |
- weak_factory_.InvalidateWeakPtrs(); |
- scoped_ptr<em::PolicyFetchResponse> response( |
- new em::PolicyFetchResponse(policy)); |
- EnsurePolicyKeyLoaded( |
- base::Bind(&UserCloudPolicyStoreChromeOS::ValidatePolicyForStore, |
- weak_factory_.GetWeakPtr(), |
- base::Passed(&response))); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::Load() { |
- // Cancel all pending requests. |
- weak_factory_.InvalidateWeakPtrs(); |
- session_manager_client_->RetrieveUserPolicy( |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyRetrieved, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::ValidatePolicyForStore( |
- scoped_ptr<em::PolicyFetchResponse> policy) { |
- // Create and configure a validator. |
- scoped_ptr<UserCloudPolicyValidator> validator = |
- CreateValidator(policy.Pass()); |
- validator->ValidateUsername(username_); |
- if (policy_key_.empty()) { |
- validator->ValidateInitialKey(); |
- } else { |
- const bool allow_rotation = true; |
- validator->ValidateSignature(policy_key_, allow_rotation); |
- } |
- |
- // Start validation. The Validator will delete itself once validation is |
- // complete. |
- validator.release()->StartValidation( |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnPolicyToStoreValidated( |
- UserCloudPolicyValidator* validator) { |
- validation_status_ = validator->status(); |
- |
- UMA_HISTOGRAM_ENUMERATION( |
- "Enterprise.UserPolicyValidationStoreStatus", |
- validation_status_, |
- UserCloudPolicyValidator::VALIDATION_POLICY_PARSE_ERROR + 1); |
- |
- if (!validator->success()) { |
- status_ = STATUS_VALIDATION_ERROR; |
- NotifyStoreError(); |
- return; |
- } |
- |
- std::string policy_blob; |
- if (!validator->policy()->SerializeToString(&policy_blob)) { |
- status_ = STATUS_SERIALIZE_ERROR; |
- NotifyStoreError(); |
- return; |
- } |
- |
- session_manager_client_->StoreUserPolicy( |
- policy_blob, |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyStored, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnPolicyStored(bool success) { |
- if (!success) { |
- status_ = STATUS_STORE_ERROR; |
- NotifyStoreError(); |
- } else { |
- // Load the policy right after storing it, to make sure it was accepted by |
- // the session manager. An additional validation is performed after the |
- // load; reload the key for that validation too, in case it was rotated. |
- ReloadPolicyKey(base::Bind(&UserCloudPolicyStoreChromeOS::Load, |
- weak_factory_.GetWeakPtr())); |
- } |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnPolicyRetrieved( |
- const std::string& policy_blob) { |
- if (policy_blob.empty()) { |
- // Policy fetch failed. Try legacy caches if we haven't done that already. |
- if (!legacy_caches_loaded_ && legacy_loader_.get()) { |
- legacy_caches_loaded_ = true; |
- legacy_loader_->Load( |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished, |
- weak_factory_.GetWeakPtr())); |
- } else { |
- // session_manager doesn't have policy. Adjust internal state and notify |
- // the world about the policy update. |
- policy_.reset(); |
- NotifyStoreLoaded(); |
- } |
- return; |
- } |
- |
- // Policy is supplied by session_manager. Disregard legacy data from now on. |
- legacy_loader_.reset(); |
- |
- scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse()); |
- if (!policy->ParseFromString(policy_blob)) { |
- status_ = STATUS_PARSE_ERROR; |
- NotifyStoreError(); |
- return; |
- } |
- |
- // Load |policy_key_| to verify the loaded policy. |
- EnsurePolicyKeyLoaded( |
- base::Bind(&UserCloudPolicyStoreChromeOS::ValidateRetrievedPolicy, |
- weak_factory_.GetWeakPtr(), |
- base::Passed(&policy))); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::ValidateRetrievedPolicy( |
- scoped_ptr<em::PolicyFetchResponse> policy) { |
- // Create and configure a validator for the loaded policy. |
- scoped_ptr<UserCloudPolicyValidator> validator = |
- CreateValidator(policy.Pass()); |
- validator->ValidateUsername(username_); |
- const bool allow_rotation = false; |
- validator->ValidateSignature(policy_key_, allow_rotation); |
- // Start validation. The Validator will delete itself once validation is |
- // complete. |
- validator.release()->StartValidation( |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnRetrievedPolicyValidated( |
- UserCloudPolicyValidator* validator) { |
- validation_status_ = validator->status(); |
- |
- UMA_HISTOGRAM_ENUMERATION( |
- "Enterprise.UserPolicyValidationLoadStatus", |
- validation_status_, |
- UserCloudPolicyValidator::VALIDATION_POLICY_PARSE_ERROR + 1); |
- |
- if (!validator->success()) { |
- status_ = STATUS_VALIDATION_ERROR; |
- NotifyStoreError(); |
- return; |
- } |
- |
- InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); |
- status_ = STATUS_OK; |
- |
- // Policy has been loaded successfully. This indicates that new-style policy |
- // is working, so the legacy cache directory can be removed. |
- if (!legacy_cache_dir_.empty()) { |
- content::BrowserThread::PostBlockingPoolTask( |
- FROM_HERE, |
- base::Bind(&UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir, |
- legacy_cache_dir_)); |
- legacy_cache_dir_.clear(); |
- } |
- NotifyStoreLoaded(); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnLegacyLoadFinished( |
- const std::string& dm_token, |
- const std::string& device_id, |
- Status status, |
- scoped_ptr<em::PolicyFetchResponse> policy) { |
- status_ = status; |
- if (policy.get()) { |
- // Create and configure a validator for the loaded legacy policy. Note that |
- // the signature on this policy is not verified. |
- scoped_ptr<UserCloudPolicyValidator> validator = |
- CreateValidator(policy.Pass()); |
- validator->ValidateUsername(username_); |
- validator.release()->StartValidation( |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated, |
- weak_factory_.GetWeakPtr(), |
- dm_token, |
- device_id)); |
- } else { |
- InstallLegacyTokens(dm_token, device_id); |
- } |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnLegacyPolicyValidated( |
- const std::string& dm_token, |
- const std::string& device_id, |
- UserCloudPolicyValidator* validator) { |
- validation_status_ = validator->status(); |
- if (validator->success()) { |
- status_ = STATUS_OK; |
- InstallPolicy(validator->policy_data().Pass(), validator->payload().Pass()); |
- |
- // Clear the public key version. The public key version field would |
- // otherwise indicate that we have key installed in the store when in fact |
- // we haven't. This may result in policy updates failing signature |
- // verification. |
- policy_->clear_public_key_version(); |
- } else { |
- status_ = STATUS_VALIDATION_ERROR; |
- } |
- |
- InstallLegacyTokens(dm_token, device_id); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::InstallLegacyTokens( |
- const std::string& dm_token, |
- const std::string& device_id) { |
- // Write token and device ID to |policy_|, giving them precedence over the |
- // policy blob. This is to match the legacy behavior, which used token and |
- // device id exclusively from the token cache file. |
- if (!dm_token.empty() && !device_id.empty()) { |
- if (!policy_.get()) |
- policy_.reset(new em::PolicyData()); |
- policy_->set_request_token(dm_token); |
- policy_->set_device_id(device_id); |
- } |
- |
- // Tell the rest of the world that the policy load completed. |
- NotifyStoreLoaded(); |
-} |
- |
-// static |
-void UserCloudPolicyStoreChromeOS::RemoveLegacyCacheDir( |
- const base::FilePath& dir) { |
- if (file_util::PathExists(dir) && !file_util::Delete(dir, true)) |
- LOG(ERROR) << "Failed to remove cache dir " << dir.value(); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::ReloadPolicyKey( |
- const base::Closure& callback) { |
- std::vector<uint8>* key = new std::vector<uint8>(); |
- content::BrowserThread::PostBlockingPoolTaskAndReply( |
- FROM_HERE, |
- base::Bind(&UserCloudPolicyStoreChromeOS::LoadPolicyKey, |
- policy_key_path_, |
- key), |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnPolicyKeyReloaded, |
- weak_factory_.GetWeakPtr(), |
- base::Owned(key), |
- callback)); |
-} |
- |
-// static |
-void UserCloudPolicyStoreChromeOS::LoadPolicyKey(const base::FilePath& path, |
- std::vector<uint8>* key) { |
- if (!file_util::PathExists(path)) { |
- // There is no policy key the first time that a user fetches policy. If |
- // |path| does not exist then that is the most likely scenario, so there's |
- // no need to sample a failure. |
- VLOG(1) << "No key at " << path.value(); |
- return; |
- } |
- |
- int64 size; |
- if (!file_util::GetFileSize(path, &size)) { |
- LOG(ERROR) << "Could not get size of " << path.value(); |
- } else if (size == 0 || size > kKeySizeLimit) { |
- LOG(ERROR) << "Key at " << path.value() << " has bad size " << size; |
- } else { |
- key->resize(size); |
- int read_size = file_util::ReadFile( |
- path, reinterpret_cast<char*>(vector_as_array(key)), size); |
- if (read_size != size) { |
- LOG(ERROR) << "Failed to read key at " << path.value(); |
- key->clear(); |
- } |
- } |
- |
- if (key->empty()) |
- SampleValidationFailure(VALIDATION_FAILURE_LOAD_KEY); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnPolicyKeyReloaded( |
- std::vector<uint8>* key, |
- const base::Closure& callback) { |
- policy_key_.swap(*key); |
- policy_key_loaded_ = true; |
- callback.Run(); |
-} |
- |
-void UserCloudPolicyStoreChromeOS::EnsurePolicyKeyLoaded( |
- const base::Closure& callback) { |
- if (policy_key_loaded_) { |
- callback.Run(); |
- } else { |
- // Get the hashed username that's part of the key's path, to determine |
- // |policy_key_path_|. |
- cryptohome_client_->GetSanitizedUsername(username_, |
- base::Bind(&UserCloudPolicyStoreChromeOS::OnGetSanitizedUsername, |
- weak_factory_.GetWeakPtr(), |
- callback)); |
- } |
-} |
- |
-void UserCloudPolicyStoreChromeOS::OnGetSanitizedUsername( |
- const base::Closure& callback, |
- chromeos::DBusMethodCallStatus call_status, |
- const std::string& sanitized_username) { |
- // The default empty path will always yield an empty key. |
- if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS && |
- !sanitized_username.empty()) { |
- policy_key_path_ = user_policy_key_dir_.Append( |
- base::StringPrintf(kPolicyKeyFile, sanitized_username.c_str())); |
- } else { |
- SampleValidationFailure(VALIDATION_FAILURE_DBUS); |
- } |
- ReloadPolicyKey(callback); |
-} |
- |
-} // namespace policy |