diff options
Diffstat (limited to 'chromium/components/policy/core/common/cloud/resource_cache.cc')
-rw-r--r-- | chromium/components/policy/core/common/cloud/resource_cache.cc | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/chromium/components/policy/core/common/cloud/resource_cache.cc b/chromium/components/policy/core/common/cloud/resource_cache.cc deleted file mode 100644 index 7b9e327acd7..00000000000 --- a/chromium/components/policy/core/common/cloud/resource_cache.cc +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2013 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 "components/policy/core/common/cloud/resource_cache.h" - -#include "base/base64.h" -#include "base/callback.h" -#include "base/file_util.h" -#include "base/files/file_enumerator.h" -#include "base/logging.h" -#include "base/safe_numerics.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/string_util.h" - -namespace policy { - -namespace { - -// Verifies that |value| is not empty and encodes it into base64url format, -// which is safe to use as a file name on all platforms. -bool Base64Encode(const std::string& value, std::string* encoded) { - DCHECK(!value.empty()); - if (value.empty()) - return false; - base::Base64Encode(value, encoded); - base::ReplaceChars(*encoded, "+", "-", encoded); - base::ReplaceChars(*encoded, "/", "_", encoded); - return true; -} - -// Decodes all elements of |input| from base64url format and stores the decoded -// elements in |output|. -bool Base64Encode(const std::set<std::string>& input, - std::set<std::string>* output) { - output->clear(); - for (std::set<std::string>::const_iterator it = input.begin(); - it != input.end(); ++it) { - std::string encoded; - if (!Base64Encode(*it, &encoded)) { - output->clear(); - return false; - } - output->insert(encoded); - } - return true; -} - -// Decodes |encoded| from base64url format and verifies that the result is not -// emtpy. -bool Base64Decode(const std::string& encoded, std::string* value) { - std::string buffer; - base::ReplaceChars(encoded, "-", "+", &buffer); - base::ReplaceChars(buffer, "_", "/", &buffer); - return base::Base64Decode(buffer, value) && !value->empty(); -} - -} // namespace - -ResourceCache::ResourceCache( - const base::FilePath& cache_dir, - scoped_refptr<base::SequencedTaskRunner> task_runner) - : cache_dir_(cache_dir), - task_runner_(task_runner) { -} - -ResourceCache::~ResourceCache() { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); -} - -bool ResourceCache::Store(const std::string& key, - const std::string& subkey, - const std::string& data) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::FilePath subkey_path; - // Delete the file before writing to it. This ensures that the write does not - // follow a symlink planted at |subkey_path|, clobbering a file outside the - // cache directory. The mechanism is meant to foil file-system-level attacks - // where a symlink is planted in the cache directory before Chrome has - // started. An attacker controlling a process running concurrently with Chrome - // would be able to race against the protection by re-creating the symlink - // between these two calls. There is nothing in file_util that could be used - // to protect against such races, especially as the cache is cross-platform - // and therefore cannot use any POSIX-only tricks. - int size = base::checked_numeric_cast<int>(data.size()); - return VerifyKeyPathAndGetSubkeyPath(key, true, subkey, &subkey_path) && - base::DeleteFile(subkey_path, false) && - (file_util::WriteFile(subkey_path, data.data(), size) == size); -} - -bool ResourceCache::Load(const std::string& key, - const std::string& subkey, - std::string* data) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::FilePath subkey_path; - // Only read from |subkey_path| if it is not a symlink. - if (!VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path) || - base::IsLink(subkey_path)) { - return false; - } - data->clear(); - return base::ReadFileToString(subkey_path, data); -} - -void ResourceCache::LoadAllSubkeys( - const std::string& key, - std::map<std::string, std::string>* contents) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - contents->clear(); - base::FilePath key_path; - if (!VerifyKeyPath(key, false, &key_path)) - return; - - base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES); - for (base::FilePath path = enumerator.Next(); !path.empty(); - path = enumerator.Next()) { - const std::string encoded_subkey = path.BaseName().MaybeAsASCII(); - std::string subkey; - std::string data; - // Only read from |subkey_path| if it is not a symlink and its name is - // a base64-encoded string. - if (!base::IsLink(path) && - Base64Decode(encoded_subkey, &subkey) && - base::ReadFileToString(path, &data)) { - (*contents)[subkey].swap(data); - } - } -} - -void ResourceCache::Delete(const std::string& key, const std::string& subkey) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::FilePath subkey_path; - if (VerifyKeyPathAndGetSubkeyPath(key, false, subkey, &subkey_path)) - base::DeleteFile(subkey_path, false); - // Delete() does nothing if the directory given to it is not empty. Hence, the - // call below deletes the directory representing |key| if its last subkey was - // just removed and does nothing otherwise. - base::DeleteFile(subkey_path.DirName(), false); -} - -void ResourceCache::Clear(const std::string& key) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::FilePath key_path; - if (VerifyKeyPath(key, false, &key_path)) - base::DeleteFile(key_path, true); -} - -void ResourceCache::FilterSubkeys(const std::string& key, - const SubkeyFilter& test) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - - base::FilePath key_path; - if (!VerifyKeyPath(key, false, &key_path)) - return; - - base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES); - for (base::FilePath subkey_path = enumerator.Next(); - !subkey_path.empty(); subkey_path = enumerator.Next()) { - std::string subkey; - // Delete files with invalid names, and files whose subkey doesn't pass the - // filter. - if (!Base64Decode(subkey_path.BaseName().MaybeAsASCII(), &subkey) || - test.Run(subkey)) { - base::DeleteFile(subkey_path, true); - } - } - - // Delete() does nothing if the directory given to it is not empty. Hence, the - // call below deletes the directory representing |key| if all of its subkeys - // were just removed and does nothing otherwise. - base::DeleteFile(key_path, false); -} - -void ResourceCache::PurgeOtherKeys(const std::set<std::string>& keys_to_keep) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - std::set<std::string> encoded_keys_to_keep; - if (!Base64Encode(keys_to_keep, &encoded_keys_to_keep)) - return; - - base::FileEnumerator enumerator( - cache_dir_, false, base::FileEnumerator::DIRECTORIES); - for (base::FilePath path = enumerator.Next(); !path.empty(); - path = enumerator.Next()) { - const std::string name(path.BaseName().MaybeAsASCII()); - if (encoded_keys_to_keep.find(name) == encoded_keys_to_keep.end()) - base::DeleteFile(path, true); - } -} - -void ResourceCache::PurgeOtherSubkeys( - const std::string& key, - const std::set<std::string>& subkeys_to_keep) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - base::FilePath key_path; - if (!VerifyKeyPath(key, false, &key_path)) - return; - - std::set<std::string> encoded_subkeys_to_keep; - if (!Base64Encode(subkeys_to_keep, &encoded_subkeys_to_keep)) - return; - - base::FileEnumerator enumerator(key_path, false, base::FileEnumerator::FILES); - for (base::FilePath path = enumerator.Next(); !path.empty(); - path = enumerator.Next()) { - const std::string name(path.BaseName().MaybeAsASCII()); - if (encoded_subkeys_to_keep.find(name) == encoded_subkeys_to_keep.end()) - base::DeleteFile(path, false); - } - // Delete() does nothing if the directory given to it is not empty. Hence, the - // call below deletes the directory representing |key| if all of its subkeys - // were just removed and does nothing otherwise. - base::DeleteFile(key_path, false); -} - -bool ResourceCache::VerifyKeyPath(const std::string& key, - bool allow_create, - base::FilePath* path) { - std::string encoded; - if (!Base64Encode(key, &encoded)) - return false; - *path = cache_dir_.AppendASCII(encoded); - return allow_create ? base::CreateDirectory(*path) : - base::DirectoryExists(*path); -} - -bool ResourceCache::VerifyKeyPathAndGetSubkeyPath(const std::string& key, - bool allow_create_key, - const std::string& subkey, - base::FilePath* path) { - base::FilePath key_path; - std::string encoded; - if (!VerifyKeyPath(key, allow_create_key, &key_path) || - !Base64Encode(subkey, &encoded)) { - return false; - } - *path = key_path.AppendASCII(encoded); - return true; -} - - -} // namespace policy |