blob: f2879c60c1bc62dea9733d103d288e83390dd3b9 [file] [log] [blame]
// Copyright (c) 2012 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.
// Homedirs - manages the collection of user home directories on disk. When a
// homedir is actually mounted, it becomes a Mount.
#ifndef CRYPTOHOME_STORAGE_HOMEDIRS_H_
#define CRYPTOHOME_STORAGE_HOMEDIRS_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/time/time.h>
// TODO(b/177929620): Cleanup once lvm utils are built unconditionally.
#if USE_LVM_STATEFUL_PARTITION
#include <brillo/blkdev_utils/lvm.h>
#endif // USE_LVM_STATEFUL_PARTITION
#include <brillo/secure_blob.h>
#include <chaps/token_manager_client.h>
#include <cryptohome/proto_bindings/rpc.pb.h>
#include <dbus/cryptohome/dbus-constants.h>
#include <gtest/gtest_prod.h>
#include <policy/device_policy.h>
#include <policy/libpolicy.h>
#include "cryptohome/crypto.h"
#include "cryptohome/platform.h"
#include "cryptohome/storage/cryptohome_vault.h"
#include "cryptohome/storage/cryptohome_vault_factory.h"
#include "cryptohome/storage/encrypted_container/encrypted_container.h"
#include "cryptohome/storage/encrypted_container/encrypted_container_factory.h"
namespace cryptohome {
// The uid shift of ARC++ container.
const uid_t kArcContainerShiftUid = 655360;
// The gid shift of ARC++ container.
const gid_t kArcContainerShiftGid = 655360;
extern const char kAndroidCacheInodeAttribute[];
extern const char kAndroidCodeCacheInodeAttribute[];
extern const char kTrackedDirectoryNameAttribute[];
extern const char kRemovableFileAttribute[];
class HomeDirs {
public:
// HomeDir contains lists the current user profiles.
struct HomeDir {
std::string obfuscated;
bool is_mounted = false;
};
using RemoveCallback =
base::RepeatingCallback<void(const std::string& obfuscated_username)>;
HomeDirs() = default;
// |remove_callback| is executed in Remove() to make sure LE Credentials of
// the corresponding |obfuscated_username| is also removed when user's
// cryptohome is removed from the device.
HomeDirs(Platform* platform,
std::unique_ptr<policy::PolicyProvider> policy_provider,
const RemoveCallback& remove_callback);
HomeDirs(Platform* platform,
std::unique_ptr<policy::PolicyProvider> policy_provider,
const RemoveCallback& remove_callback,
std::unique_ptr<CryptohomeVaultFactory> vault_factory);
HomeDirs(const HomeDirs&) = delete;
HomeDirs& operator=(const HomeDirs&) = delete;
virtual ~HomeDirs();
// Removes all cryptohomes owned by anyone other than the owner user (if set),
// regardless of free disk space.
virtual void RemoveNonOwnerCryptohomes();
// Returns the owner's obfuscated username.
virtual bool GetOwner(std::string* owner);
virtual bool GetPlainOwner(std::string* owner);
// Returns whether the given user is a non-enterprise owner, or if it will
// become such in case it signs in now.
bool IsOrWillBeOwner(const std::string& account_id);
// Returns whether the ephemeral users policy is enabled.
virtual bool AreEphemeralUsersEnabled();
// Returns whether Keylocker should be used for per-user encrypted storage.
virtual bool KeylockerForStorageEncryptionEnabled();
// Returns whether the automatic cleanup during login policy is enabled.
virtual bool MustRunAutomaticCleanupOnLogin();
// Creates the cryptohome for the named user.
virtual bool Create(const std::string& username);
// Removes the cryptohome for the given obfuscated username.
virtual bool Remove(const std::string& obfuscated);
// Removes the Dmcryot cache container for the named user.
virtual bool RemoveDmcryptCacheContainer(const std::string& username);
// Computes the size of cryptohome for the named user.
// Return 0 if the given user is invalid of non-existent.
// Negative values are reserved for future cases whereby we need to do some
// form of error reporting.
// Note that this method calculates the disk usage instead of apparent size.
virtual int64_t ComputeDiskUsage(const std::string& account_id);
// Returns true if a path exists for the given obfuscated username.
virtual bool Exists(const std::string& obfuscated_username) const;
// Checks if a cryptohome vault exists for the given obfuscated username.
virtual bool CryptohomeExists(const std::string& obfuscated_username,
MountError* error) const;
// Checks if a eCryptfs cryptohome vault exists for the given obfuscated
// username.
virtual bool EcryptfsCryptohomeExists(
const std::string& obfuscated_username) const;
// Checks if a dircrypto cryptohome vault exists for the given obfuscated
// username.
virtual bool DircryptoCryptohomeExists(const std::string& obfuscated_username,
MountError* error) const;
// Check if a dm-crypt container exists for the given obfuscated username.
virtual bool DmcryptContainerExists(
const std::string& obfuscated_username,
const std::string& container_suffix) const;
// Checks if a dm-crypt cryptohome vault exists for the given obfuscated
// username.
virtual bool DmcryptCryptohomeExists(
const std::string& obfuscated_username) const;
// Checks if the dm-crypt cryptohome's cache container exists for the given
// obfuscated username.
virtual bool DmcryptCacheContainerExists(
const std::string& obfuscated_username) const;
// Returns the path to the user's chaps token directory.
virtual base::FilePath GetChapsTokenDir(const std::string& username) const;
// Returns true if the cryptohome for the given obfuscated username should
// migrate to dircrypto.
virtual bool NeedsDircryptoMigration(
const std::string& obfuscated_username) const;
// Get the number of unmounted android-data directory. Each android users
// that is not currently logged in should have exactly one android-data
// directory.
virtual int32_t GetUnmountedAndroidDataCount();
// Marks that the device got locked to be able to use only data of a single
// user until reboot. Internally touches a file in temporary storage marking
// that PCR was extended.
virtual bool SetLockedToSingleUser() const;
// Get the list of cryptohomes on the system.
virtual std::vector<HomeDir> GetHomeDirs();
// Accessors. Mostly used for unit testing. These do not take ownership of
// passed-in pointers.
virtual void set_enterprise_owned(bool value) { enterprise_owned_ = value; }
virtual bool enterprise_owned() const { return enterprise_owned_; }
virtual void set_lvm_migration_enabled(bool value) {
lvm_migration_enabled_ = value;
}
// Pick the most appropriate vault type for the user.
virtual EncryptedContainerType PickVaultType(
const std::string& obfuscated_username,
const CryptohomeVault::Options& options,
MountError* error);
virtual CryptohomeVaultFactory* GetVaultFactory() {
return vault_factory_.get();
}
// TODO(b/177929620): Cleanup once lvm utils are built unconditionally.
#if USE_LVM_STATEFUL_PARTITION
void SetLogicalVolumeManagerForTesting(
std::unique_ptr<brillo::LogicalVolumeManager> lvm) {
lvm_ = std::move(lvm);
}
#endif // USE_LVM_STATEFUL_PARTITION
private:
// Choose the vault type for new vaults.
EncryptedContainerType ChooseVaultType();
// Verifies that flags match the vault type.
MountError VerifyVaultType(EncryptedContainerType vault_type,
const CryptohomeVault::Options& options);
// Get the type of an existing vault.
EncryptedContainerType GetVaultType(const std::string& obfuscated_username,
MountError* error);
base::TimeDelta GetUserInactivityThresholdForRemoval();
// Loads the device policy, either by initializing it or reloading the
// existing one.
void LoadDevicePolicy();
// Returns the path of the specified tracked directory (i.e. a directory which
// we can locate even when without the key).
bool GetTrackedDirectory(const base::FilePath& user_dir,
const base::FilePath& tracked_dir_name,
base::FilePath* out);
// GetTrackedDirectory() implementation for dircrypto.
bool GetTrackedDirectoryForDirCrypto(const base::FilePath& mount_dir,
const base::FilePath& tracked_dir_name,
base::FilePath* out);
// Removes all mounted homedirs from the vector
void FilterMountedHomedirs(std::vector<HomeDir>* homedirs);
// Helper function to check if the directory contains subdirectory that looks
// like encrypted android-data (see definition of looks-like-android-data in
// the LooksLikeAndroidData function). Each file names under mounted_user_dir
// filesystem tree has encrypted name, but unencrypted metadata.
// False positive is possible, but practically should never happen. Even if
// false positive happens, installd in ARC++ will use non-quota path and the
// system will keep running properly (though a bit slower) so it is still
// safe.
bool MayContainAndroidData(const base::FilePath& mounted_user_dir) const;
// Helper function to check if the directory looks like android-data. A
// directory is said to look like android-data if it has subdirectory owned by
// Android system. It is possible for a directory that looks like android-data
// to not actually be android-data, but the other way around is not possible.
// But practically in current home directory structure, directory that looks
// like android-data is always android-data. So normally, this function
// accurately predicts if the directory in the parameter is actually
// android-data.
bool LooksLikeAndroidData(const base::FilePath& directory) const;
// Helper function to check if the directory is owned by android system
// UID.
bool IsOwnedByAndroidSystem(const base::FilePath& directory) const;
Platform* platform_;
std::unique_ptr<policy::PolicyProvider> policy_provider_;
bool enterprise_owned_;
// lvm migration flag is temporary, it will be removed when defaulted to
// |true|.
bool lvm_migration_enabled_;
chaps::TokenManagerClient chaps_client_;
std::unique_ptr<CryptohomeVaultFactory> vault_factory_;
std::vector<HomeDir> unmounted_homedirs_;
// This callback will be run in Remove() to remove LE Credentials when the
// home directory of the corresponding user is removed.
RemoveCallback remove_callback_;
// The container a not-shifted system UID in ARC++ container (AID_SYSTEM).
static constexpr uid_t kAndroidSystemUid = 1000;
// TODO(b/177929620): Cleanup once lvm utils are built unconditionally.
#if USE_LVM_STATEFUL_PARTITION
std::unique_ptr<brillo::LogicalVolumeManager> lvm_;
#endif // USE_LVM_STATEFUL_PARTITION
friend class HomeDirsTest;
FRIEND_TEST(HomeDirsTest, GetTrackedDirectoryForDirCrypto);
};
} // namespace cryptohome
#endif // CRYPTOHOME_STORAGE_HOMEDIRS_H_