blob: a8ec9ae1771edef384a3e4b2d6fce59251336433 [file] [log] [blame]
// Copyright (c) 2009-2010 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.
// Mount - class for managing cryptohome user keys and mounts. In Chrome OS,
// users are managed on top of a shared unix user, chronos. When a user logs
// in, cryptohome mounts their encrypted home directory to /home/chronos/user,
// and Chrome does a profile switch to that directory. All user data in their
// home directory is transparently encrypted, providing protection against
// offline theft. On logout, the mount point is removed.
#ifndef CRYPTOHOME_MOUNT_H_
#define CRYPTOHOME_MOUNT_H_
#include <base/basictypes.h>
#include <base/file_path.h>
#include <base/scoped_ptr.h>
#include "credentials.h"
#include "crypto.h"
#include "platform.h"
#include "secure_blob.h"
#include "user_session.h"
#include "vault_keyset.h"
#include "vault_keyset.pb.h"
namespace cryptohome {
// The directory to mount the user's cryptohome at
extern const std::string kDefaultHomeDir;
// The directory containing the system salt and the user vaults
extern const std::string kDefaultShadowRoot;
// The default shared user (chronos)
extern const std::string kDefaultSharedUser;
// The default skeleton source (/etc/skel)
extern const std::string kDefaultSkeletonSource;
// The incognito user
extern const std::string kIncognitoUser;
// Directories that we intend to track (make pass-through in cryptohome vault)
extern const char* kCacheDir;
extern const char* kDownloadsDir;
// Minimum free disk space on stateful_partition not to begin the cleanup
const int64 kMinFreeSpace = 512 * 1LL << 20; // 500M bytes
// Enough free disk space on stateful_partition to stop the cleanup
const int64 kEnoughFreeSpace = 1LL << 30; // 1G bytes
// The Mount class handles mounting/unmounting of the user's cryptohome
// directory as well as offline verification of the user's credentials against
// the directory's crypto key.
class Mount : public EntropySource {
public:
enum MountError {
MOUNT_ERROR_NONE = 0,
MOUNT_ERROR_FATAL = 1 << 0,
MOUNT_ERROR_KEY_FAILURE = 1 << 1,
MOUNT_ERROR_MOUNT_POINT_BUSY = 1 << 2,
MOUNT_ERROR_TPM_COMM_ERROR = 1 << 3,
MOUNT_ERROR_TPM_DEFEND_LOCK = 1 << 4,
MOUNT_ERROR_USER_DOES_NOT_EXIST = 1 << 5,
MOUNT_ERROR_RECREATED = 1 << 31,
};
struct MountArgs {
bool create_if_missing;
MountArgs() : create_if_missing(false) {
}
void CopyFrom(const MountArgs& rhs) {
this->create_if_missing = rhs.create_if_missing;
}
};
// Sets up Mount with the default locations, username, etc., as defined above.
Mount();
virtual ~Mount();
// Gets the uid/gid of the default user and loads the system salt
virtual bool Init();
// Attempts to mount the cryptohome for the given credentials
//
// Parameters
// credentials - The Credentials representing the user
// mount_args - The options for the call to mount: whether to create the
// cryptohome if it doesn't exist and any tracked directories
// to create
// error - The specific error condition on failure
virtual bool MountCryptohome(const Credentials& credentials,
const MountArgs& mount_args,
MountError* error) const;
// Unmounts any mount at the cryptohome mount point
virtual bool UnmountCryptohome() const;
// Remove a user's cryptohome
virtual bool RemoveCryptohome(const Credentials& credentials) const;
// Checks if the mount point currently has a mount
virtual bool IsCryptohomeMounted() const;
// Checks if the mount point currently has a mount, and if that mount is for
// the specified credentials
//
// Parameters
// credentials - The Credentials for which to test the mount point
virtual bool IsCryptohomeMountedForUser(const Credentials& credentials) const;
// Checks if the cryptohome vault exists for the given credentials and creates
// it if not (calls CreateCryptohome).
//
// Parameters
// credentials - The Credentials representing the user whose cryptohome
// should be ensured.
// created (OUT) - Whether the cryptohome was created
virtual bool EnsureCryptohome(const Credentials& credentials,
const MountArgs& mount_args,
bool* created) const;
// Checks if the cryptohome vault exists for the given credentials
//
// Parameters
// credentials - The Credentials representing the user whose cryptohome
// should be checked.
virtual bool DoesCryptohomeExist(const Credentials& credentials) const;
// Creates the cryptohome salt, key, and vault for the specified credentials
//
// Parameters
// credentials - The Credentials representing the user whose cryptohome
// should be created.
virtual bool CreateCryptohome(const Credentials& credentials,
const MountArgs& mount_args) const;
// Creates the the tracked subdirectories in a user's cryptohome
// If the cryptohome did not have tracked directories, but had them untracked,
// migrate their contents.
//
// Parameters
// credentials - The Credentials representing the user
// is_new - True, if the cryptohome is being created and there is
// no need in migration
virtual bool CreateTrackedSubdirectories(const Credentials& credentials,
bool is_new) const;
// Cleans (removes) content from unmounted tracked subdirectories
virtual void CleanUnmountedTrackedSubdirectories();
// Deletes all tracking subdirectories of the given vault.
// This callback is OBSOLETE.
// TODO(glotov): remove the callback after feature implementation
// croosbug.com/9620) is complete.
virtual void DeleteTrackedDirsCallback(const FilePath& vault);
// Deletes Cache tracking directory of the given vault
virtual void DeleteCacheCallback(const FilePath& vault);
// Checks free disk space and if it falls below minimum
// (kMinFreeSpace), performs cleanup
virtual void DoAutomaticFreeDiskSpaceControl();
// Update user activity timestamp to be able to detect old users.
virtual void UpdateUserActivityTimestamp() const;
// Tests if the given credentials would decrypt the user's cryptohome key
//
// Parameters
// credentials - The Credentials to attempt to decrypt the key with
virtual bool TestCredentials(const Credentials& credentials) const;
// Migrages a user's vault key from one passkey to another
//
// Parameters
// credentials - The new Credentials for the user
// from_key - The old Credentials
virtual bool MigratePasskey(const Credentials& credentials,
const char* old_key) const;
// Mounts a guest home directory to the cryptohome mount point
virtual bool MountGuestCryptohome() const;
// Returns the system salt
virtual void GetSystemSalt(chromeos::Blob* salt) const;
virtual bool LoadVaultKeyset(const Credentials& credentials,
SerializedVaultKeyset* encrypted_keyset) const;
virtual bool LoadVaultKeysetForUser(
const std::string& obsfucated_username,
SerializedVaultKeyset* encrypted_keyset) const;
virtual bool StoreVaultKeyset(
const Credentials& credentials,
const SerializedVaultKeyset& encrypted_keyset) const;
virtual bool StoreVaultKeysetForUser(
const std::string& obsfucated_username,
const SerializedVaultKeyset& encrypted_keyset) const;
// Used to disable setting vault ownership
void set_set_vault_ownership(bool value) {
set_vault_ownership_ = value;
}
// Used to override the default home directory
void set_home_dir(const std::string& value) {
home_dir_ = value;
}
// Used to override the default shadow root
void set_shadow_root(const std::string& value) {
shadow_root_ = value;
}
// Get the shadow root
std::string get_shadow_root() {
return shadow_root_;
}
// Used to override the default shared username
void set_shared_user(const std::string& value) {
default_username_ = value;
}
// Used to override the default skeleton directory
void set_skel_source(const std::string& value) {
skel_source_ = value;
}
// Used to override the default Crypto handler (does not take ownership)
void set_crypto(Crypto* value) {
crypto_ = value;
}
// Get the Crypto instance
virtual Crypto* get_crypto() {
return crypto_;
}
// Used to override the default Platform handler (does not take ownership)
void set_platform(Platform* value) {
platform_ = value;
}
// Override whether to use scrypt for added security when the TPM is off or
// disabled
void set_fallback_to_scrypt(bool value) {
fallback_to_scrypt_ = value;
}
// Override whether to use the TPM for added security
void set_use_tpm(bool value) {
use_tpm_ = value;
}
// Manually set the logged in user
void set_current_user(UserSession* value) {
current_user_ = value;
}
// Get the user session
UserSession* get_current_user() {
return current_user_;
}
// Manually set the logged in user
void set_current_user_credentials(const Credentials& credentials) {
current_user_->SetUser(credentials);
}
// Manually clear the current logged-in user
void reset_current_user_credentials() {
current_user_->Reset();
}
// Loads the contents of the specified file as a blob
//
// Parameters
// path - The file path to read from
// blob (OUT) - Where to store the loaded file bytes
static bool LoadFileBytes(const FilePath& path, SecureBlob* blob);
// Loads the contents of the specified file as a string
//
// Parameters
// path - The file path to read from
// content (OUT) - The string value
static bool LoadFileString(const FilePath& path, std::string* content);
// Encrypts and adds the VaultKeyset to the serialized store
//
// Parameters
// credentials - The Credentials for the user
// vault_keyset - The VaultKeyset to save
// serialized (IN/OUT) - The SerializedVaultKeyset to add the encrypted
// VaultKeyset to
bool AddVaultKeyset(const Credentials& credentials,
const VaultKeyset& vault_keyset,
SerializedVaultKeyset* serialized) const;
// Resaves the vault keyset, restoring on failure. The vault_keyset supplied
// is encrypted and stored in the wrapped_keyset parameter of serialized,
// which is then saved to disk.
//
// Parameters
// credentials - The Credentials for the user
// vault_keyset - The VaultKeyset to save
// serialized (IN/OUT) - The serialized container to be saved
bool ReEncryptVaultKeyset(const Credentials& credentials,
const VaultKeyset& vault_keyset,
SerializedVaultKeyset* serialized) const;
// Attempt to decrypt the keyset for the specified user. The method both
// deserializes the SerializedVaultKeyset from disk and decrypts the
// encrypted vault keyset, returning it in vault_keyset.
//
// Parameters
// credentials - The user credentials to use
// vault_keyset (OUT) - The unencrypted vault keyset on success
// serialized (OUT) - The keyset container as deserialized from disk
// error (OUT) - The specific error when decrypting
bool DecryptVaultKeyset(const Credentials& credentials,
bool migrate_if_needed,
VaultKeyset* vault_keyset,
SerializedVaultKeyset* serialized,
MountError* error) const;
// Saves the VaultKeyset for the user in the old method
//
// Parameters
// credentials - The Credentials for the user
// vault_keyset - The VaultKeyset to save
bool SaveVaultKeysetOld(const Credentials& credentials,
const VaultKeyset& vault_keyset) const;
// Attempt to decrypt the keyset using the old method for a user
//
// Parameters
// credentials - The user credentials to use
// vault_keyset (OUT) - The unencrypted vault keyset on success
// error (OUT) - The specific error when decrypting
bool DecryptVaultKeysetOld(const Credentials& credentials,
VaultKeyset* vault_keyset,
MountError* error) const;
// Remove the key file and (old) salt file if they exist
//
// Parameters
// credentials - The user credentials to remove the files for
bool RemoveOldFiles(const Credentials& credentials) const;
// Cache the old key file and salt file during migration
//
// Parameters
// credentials - The user credentials to cache the files for
// files - The file names to cache
bool CacheOldFiles(const Credentials& credentials,
std::vector<std::string>& files) const;
// Move the cached files back to the original files
//
// Parameters
// credentials - The user credentials to un-cache the files for
// files - The file names to un-cache
bool RevertCacheFiles(const Credentials& credentials,
std::vector<std::string>& files) const;
// Remove the cached files for the user
//
// Parameters
// credentials - The user credentials to remove the files for
// files - The file names to remove
bool DeleteCacheFiles(const Credentials& credentials,
std::vector<std::string>& files) const;
// Gets the directory in the shadow root where the user's salt, key, and vault
// are stored.
//
// Parameters
// credentials - The Credentials representing the user
std::string GetUserDirectory(const Credentials& credentials) const;
// Gets the user's key file name
//
// Parameters
// credentials - The Credentials representing the user
std::string GetUserKeyFile(const Credentials& credentials) const;
// Gets the user's key file name
//
// Parameters
// obsfucated_username - Obsfucated username field of the Credentials
std::string GetUserKeyFileForUser(
const std::string& obsfucated_username) const;
// Gets the user's salt file name
//
// Parameters
// credentials - The Credentials representing the user
std::string GetUserSaltFile(const Credentials& credentials) const;
// Gets the user's vault directory
//
// Parameters
// credentials - The Credentials representing the user
std::string GetUserVaultPath(const Credentials& credentials) const;
private:
// Invokes given callback for every unmounted cryptohome
//
// Parameters
// callback - Routine to invoke.
typedef void (Mount::*CryptohomeCallback)(const FilePath&);
void DoForEveryUnmountedCryptohome(CryptohomeCallback callback);
// Same as MountCryptohome but specifies if the cryptohome directory should be
// recreated on a fatal error
//
// Parameters
// credentials - The Credentials representing the user
// mount_args - The options for the call to mount: whether to create the
// cryptohome if it doesn't exist and any tracked directories
// to create
// recreate_decrypt_fatal - Attempt to recreate the cryptohome directory on
// a fatal error (for example, TPM was cleared)
// error - The specific error condition on failure
virtual bool MountCryptohomeInner(const Credentials& credentials,
const MountArgs& mount_args,
bool recreate_decrypt_fatal,
MountError* error) const;
// Recursively copies directory contents to the destination if the destination
// file does not exist. Sets ownership to the default_user_
//
// Parameters
// destination - Where to copy files to
// source - Where to copy files from
void RecursiveCopy(const FilePath& destination, const FilePath& source) const;
// Copies the skeleton directory to the user's cryptohome if that user is
// currently mounted
//
// Parameters
// credentials - The Credentials representing the user
void CopySkeletonForUser(const Credentials& credentials) const;
// Copies the skeleton directory to the cryptohome mount point
//
void CopySkeleton() const;
// Returns the specified number of random bytes
//
// Parameters
// rand (IN/OUT) - Where to store the bytes, must be a least length bytes
// length - The number of random bytes to return
void GetSecureRandom(unsigned char *rand, unsigned int length) const;
// Returns the user's salt
//
// Parameters
// credentials - The Credentials representing the user
// force - Whether to force creation of a new salt
// salt (OUT) - The user's salt
void GetUserSalt(const Credentials& credentials, bool force_new,
SecureBlob* salt) const;
// The uid of the shared user. Ownership of the user's vault is set to this
// uid.
uid_t default_user_;
// The gid of the shared user. Ownership of the user's vault is set to this
// gid.
gid_t default_group_;
// The shared user name. This user's uid/gid is used for vault ownership.
std::string default_username_;
// The file path to mount cryptohome at. Defaults to /home/chronos/user
std::string home_dir_;
// Where to store the system salt and user salt/key/vault. Defaults to
// /home/chronos/shadow
std::string shadow_root_;
// Where the skeleton for the user's cryptohome is copied from
std::string skel_source_;
// Stores the global system salt
cryptohome::SecureBlob system_salt_;
// Whether to change ownership of the vault file
bool set_vault_ownership_;
// The crypto implementation
scoped_ptr<Crypto> default_crypto_;
Crypto *crypto_;
// The platform-specific calls
scoped_ptr<Platform> default_platform_;
Platform *platform_;
// Whether to use scrypt for added security when use of the TPM is disabled
bool fallback_to_scrypt_;
// Whether to use the TPM for added security
bool use_tpm_;
// Used to keep track of the current logged-in user
scoped_ptr<UserSession> default_current_user_;
UserSession* current_user_;
DISALLOW_COPY_AND_ASSIGN(Mount);
};
} // namespace cryptohome
#endif // CRYPTOHOME_MOUNT_H_