blob: 17508b65e5dda79aca99f388869f9ed39c8667a5 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Contains the implementation of class Platform
#include "cryptohome/fake_platform.h"
#include <memory>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
#include <base/files/file_path.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>
namespace cryptohome {
namespace {
class ProxyFileEnumerator : public FileEnumerator {
public:
ProxyFileEnumerator(const base::FilePath& tmpfs_rootfs,
FileEnumerator* real_enumerator)
: tmpfs_rootfs_(tmpfs_rootfs), real_enumerator_(real_enumerator) {}
// Removed tmpfs prefix from the returned path.
base::FilePath Next() override {
base::FilePath next = real_enumerator_->Next();
if (!tmpfs_rootfs_.IsParent(next)) {
return next;
}
base::FilePath assumed_path("/");
CHECK(tmpfs_rootfs_.AppendRelativePath(next, &assumed_path));
return assumed_path;
}
FileEnumerator::FileInfo GetInfo() override {
return real_enumerator_->GetInfo();
}
private:
base::FilePath tmpfs_rootfs_;
std::unique_ptr<FileEnumerator> real_enumerator_;
};
} // namespace
// Constructor/destructor
FakePlatform::FakePlatform() : Platform() {
base::GetTempDir(&tmpfs_rootfs_);
tmpfs_rootfs_ = tmpfs_rootfs_.Append(real_platform_.GetRandomSuffix());
if (!real_platform_.CreateDirectory(tmpfs_rootfs_)) {
LOG(ERROR) << "Failed to create test dir: " << tmpfs_rootfs_;
}
}
FakePlatform::~FakePlatform() {
real_platform_.DeletePathRecursively(tmpfs_rootfs_);
}
// Helpers
base::FilePath FakePlatform::TestFilePath(const base::FilePath& path) const {
std::string path_str = path.NormalizePathSeparators().value();
// Make the path relative.
CHECK(path.IsAbsolute());
if (path_str.length() > 0 && path_str[0] == '/') {
path_str = path_str.substr(1);
}
return tmpfs_rootfs_.Append(path_str);
}
// Platform API
bool FakePlatform::Rename(const base::FilePath& from,
const base::FilePath& to) {
return real_platform_.Rename(TestFilePath(from), TestFilePath(to));
}
bool FakePlatform::Move(const base::FilePath& from, const base::FilePath& to) {
return real_platform_.Move(TestFilePath(from), TestFilePath(to));
}
bool FakePlatform::Copy(const base::FilePath& from, const base::FilePath& to) {
return real_platform_.Copy(TestFilePath(from), TestFilePath(to));
}
bool FakePlatform::EnumerateDirectoryEntries(
const base::FilePath& path,
bool recursive,
std::vector<base::FilePath>* ent_list) {
return real_platform_.EnumerateDirectoryEntries(TestFilePath(path), recursive,
ent_list);
}
bool FakePlatform::DeleteFile(const base::FilePath& path) {
return real_platform_.DeleteFile(TestFilePath(path));
}
bool FakePlatform::DeletePathRecursively(const base::FilePath& path) {
return real_platform_.DeletePathRecursively(TestFilePath(path));
}
bool FakePlatform::DeleteFileDurable(const base::FilePath& path) {
return real_platform_.DeleteFileDurable(TestFilePath(path));
}
bool FakePlatform::FileExists(const base::FilePath& path) {
return real_platform_.FileExists(TestFilePath(path));
}
bool FakePlatform::DirectoryExists(const base::FilePath& path) {
return real_platform_.DirectoryExists(TestFilePath(path));
}
bool FakePlatform::CreateDirectory(const base::FilePath& path) {
return real_platform_.CreateDirectory(TestFilePath(path));
}
bool FakePlatform::CreateSparseFile(const base::FilePath& path, int64_t size) {
return real_platform_.CreateSparseFile(TestFilePath(path), size);
}
bool FakePlatform::ReadFile(const base::FilePath& path, brillo::Blob* blob) {
return real_platform_.ReadFile(TestFilePath(path), blob);
}
bool FakePlatform::ReadFileToString(const base::FilePath& path,
std::string* str) {
return real_platform_.ReadFileToString(TestFilePath(path), str);
}
bool FakePlatform::ReadFileToSecureBlob(const base::FilePath& path,
brillo::SecureBlob* sblob) {
return real_platform_.ReadFileToSecureBlob(TestFilePath(path), sblob);
}
bool FakePlatform::WriteFile(const base::FilePath& path,
const brillo::Blob& blob) {
return real_platform_.WriteFile(TestFilePath(path), blob);
}
bool FakePlatform::WriteSecureBlobToFile(const base::FilePath& path,
const brillo::SecureBlob& sblob) {
return real_platform_.WriteSecureBlobToFile(TestFilePath(path), sblob);
}
bool FakePlatform::WriteFileAtomic(const base::FilePath& path,
const brillo::Blob& blob,
mode_t mode) {
return real_platform_.WriteFileAtomic(TestFilePath(path), blob, mode);
}
bool FakePlatform::WriteSecureBlobToFileAtomic(const base::FilePath& path,
const brillo::SecureBlob& sblob,
mode_t mode) {
return real_platform_.WriteSecureBlobToFileAtomic(TestFilePath(path), sblob,
mode);
}
bool FakePlatform::WriteFileAtomicDurable(const base::FilePath& path,
const brillo::Blob& blob,
mode_t mode) {
return real_platform_.WriteFileAtomicDurable(TestFilePath(path), blob, mode);
}
bool FakePlatform::WriteSecureBlobToFileAtomicDurable(
const base::FilePath& path, const brillo::SecureBlob& sblob, mode_t mode) {
return real_platform_.WriteSecureBlobToFileAtomicDurable(TestFilePath(path),
sblob, mode);
}
bool FakePlatform::WriteStringToFile(const base::FilePath& path,
const std::string& str) {
return real_platform_.WriteStringToFile(TestFilePath(path), str);
}
bool FakePlatform::WriteStringToFileAtomicDurable(const base::FilePath& path,
const std::string& str,
mode_t mode) {
return real_platform_.WriteStringToFileAtomicDurable(TestFilePath(path), str,
mode);
}
bool FakePlatform::WriteArrayToFile(const base::FilePath& path,
const char* data,
size_t size) {
return real_platform_.WriteArrayToFile(TestFilePath(path), data, size);
}
FILE* FakePlatform::OpenFile(const base::FilePath& path, const char* mode) {
return real_platform_.OpenFile(TestFilePath(path), mode);
}
bool FakePlatform::CloseFile(FILE* file) {
return real_platform_.CloseFile(file);
}
FileEnumerator* FakePlatform::GetFileEnumerator(const base::FilePath& path,
bool recursive,
int file_type) {
return new ProxyFileEnumerator(
tmpfs_rootfs_, real_platform_.GetFileEnumerator(TestFilePath(path),
recursive, file_type));
}
bool FakePlatform::GetFileSize(const base::FilePath& path, int64_t* size) {
return real_platform_.GetFileSize(TestFilePath(path), size);
}
bool FakePlatform::HasExtendedFileAttribute(const base::FilePath& path,
const std::string& name) {
return real_platform_.HasExtendedFileAttribute(TestFilePath(path), name);
}
bool FakePlatform::ListExtendedFileAttributes(
const base::FilePath& path, std::vector<std::string>* attr_list) {
return real_platform_.ListExtendedFileAttributes(TestFilePath(path),
attr_list);
}
bool FakePlatform::GetExtendedFileAttributeAsString(const base::FilePath& path,
const std::string& name,
std::string* value) {
return real_platform_.GetExtendedFileAttributeAsString(TestFilePath(path),
name, value);
}
bool FakePlatform::GetExtendedFileAttribute(const base::FilePath& path,
const std::string& name,
char* value,
ssize_t size) {
return real_platform_.GetExtendedFileAttribute(TestFilePath(path), name,
value, size);
}
bool FakePlatform::SetExtendedFileAttribute(const base::FilePath& path,
const std::string& name,
const char* value,
size_t size) {
return real_platform_.SetExtendedFileAttribute(TestFilePath(path), name,
value, size);
}
bool FakePlatform::RemoveExtendedFileAttribute(const base::FilePath& path,
const std::string& name) {
return real_platform_.RemoveExtendedFileAttribute(TestFilePath(path), name);
}
bool FakePlatform::GetOwnership(const base::FilePath& path,
uid_t* user_id,
gid_t* group_id,
bool follow_links) const {
// TODO(chromium:1141301, dlunev): here and further check for file existence.
// Can not do it at present due to weird test dependencies.
if (file_owners_.find(path) == file_owners_.end()) {
*user_id = fake_platform::kChronosUID;
*group_id = fake_platform::kChronosGID;
return true;
}
*user_id = file_owners_.at(path).first;
*group_id = file_owners_.at(path).second;
return true;
}
bool FakePlatform::SetOwnership(const base::FilePath& path,
uid_t user_id,
gid_t group_id,
bool follow_links) const {
file_owners_[path] = {user_id, group_id};
return true;
}
bool FakePlatform::GetPermissions(const base::FilePath& path,
mode_t* mode) const {
if (file_mode_.find(path) == file_mode_.end()) {
*mode = S_IRWXU | S_IRGRP | S_IXGRP;
return true;
}
*mode = file_mode_.at(path);
return true;
}
bool FakePlatform::SetPermissions(const base::FilePath& path,
mode_t mode) const {
file_mode_[path] = mode;
return true;
}
bool FakePlatform::FakePlatform::GetUserId(const std::string& user,
uid_t* user_id,
gid_t* group_id) const {
CHECK(user_id);
CHECK(group_id);
if (uids_.find(user) == uids_.end() || gids_.find(user) == gids_.end()) {
LOG(ERROR) << "No user: " << user;
return false;
}
*user_id = uids_.at(user);
*group_id = gids_.at(user);
return true;
}
bool FakePlatform::GetGroupId(const std::string& group, gid_t* group_id) const {
CHECK(group_id);
if (gids_.find(group) == gids_.end()) {
LOG(ERROR) << "No group: " << group;
return false;
}
*group_id = gids_.at(group);
return true;
}
// Test API
void FakePlatform::SetUserId(const std::string& user, uid_t user_id) {
CHECK(uids_.find(user) == uids_.end());
uids_[user] = user_id;
}
void FakePlatform::SetGroupId(const std::string& group, gid_t group_id) {
CHECK(gids_.find(group) == gids_.end());
gids_[group] = group_id;
}
void FakePlatform::SetStandardUsersAndGroups() {
SetUserId(fake_platform::kRoot, fake_platform::kRootUID);
SetGroupId(fake_platform::kRoot, fake_platform::kRootGID);
SetUserId(fake_platform::kChapsUser, fake_platform::kChapsUID);
SetGroupId(fake_platform::kChapsUser, fake_platform::kChapsGID);
SetUserId(fake_platform::kChronosUser, fake_platform::kChronosUID);
SetGroupId(fake_platform::kChronosUser, fake_platform::kChronosGID);
SetGroupId(fake_platform::kSharedGroup, fake_platform::kSharedGID);
}
void FakePlatform::SetSystemSaltForLibbrillo(const brillo::SecureBlob& salt) {
std::string* brillo_salt = new std::string();
brillo_salt->resize(salt.size());
brillo_salt->assign(reinterpret_cast<const char*>(salt.data()), salt.size());
brillo::cryptohome::home::SetSystemSalt(brillo_salt);
}
void FakePlatform::RemoveSystemSaltForLibbrillo() {
std::string* salt = brillo::cryptohome::home::GetSystemSalt();
brillo::cryptohome::home::SetSystemSalt(NULL);
delete salt;
}
} // namespace cryptohome