// Copyright (c) 2013 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 Mount

#include "cryptohome/mount.h"

#include <errno.h>
#include <sys/stat.h>

#include <map>
#include <set>

#include <base/bind.h>
#include <base/logging.h>
#include <base/sha1.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/platform_thread.h>
#include <base/values.h>
#include <chaps/isolate.h>
#include <chaps/token_manager_client.h>
#include <chromeos/cryptohome.h>
#include <chromeos/secure_blob.h>

#include "cryptohome/boot_lockbox.h"
#include "cryptohome/chaps_client_factory.h"
#include "cryptohome/crypto.h"
#include "cryptohome/cryptohome_common.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/homedirs.h"
#include "cryptohome/pkcs11_init.h"
#include "cryptohome/platform.h"
#include "cryptohome/tpm.h"
#include "cryptohome/username_passkey.h"
#include "cryptohome/vault_keyset.h"

#include "vault_keyset.pb.h"  // NOLINT(build/include)

using base::FilePath;
using base::StringPrintf;
using chaps::IsolateCredentialManager;
using chromeos::SecureBlob;
using std::string;

namespace cryptohome {

const char kDefaultHomeDir[] = "/home/chronos/user";
const char kDefaultShadowRoot[] = "/home/.shadow";
const char kDefaultSharedUser[] = "chronos";
const char kChapsUserName[] = "chaps";
const char kDefaultSharedAccessGroup[] = "chronos-access";
const char kDefaultSkeletonSource[] = "/etc/skel";
const uid_t kMountOwnerUid = 0;
const gid_t kMountOwnerGid = 0;
// TODO(fes): Remove once UI for BWSI switches to MountGuest()
const char kIncognitoUser[] = "incognito";
// Tracked directories - special sub-directories of the cryptohome
// vault, that are visible even if not mounted. Contents is still encrypted.
const char kVaultDir[] = "vault";
const char kCacheDir[] = "Cache";
const char kDownloadsDir[] = "Downloads";
const char kGCacheDir[] = "GCache";
const char kGCacheVersionDir[] = "v1";
const char kGCacheTmpDir[] = "tmp";
const char kUserHomeSuffix[] = "user";
const char kRootHomeSuffix[] = "root";
const char kMountDir[] = "mount";
const char kSkeletonDir[] = "skeleton";
const char kKeyFile[] = "master.";
const int kKeyFileMax = 100;  // master.0 ... master.99
const mode_t kKeyFilePermissions = 0600;
const char kKeyLegacyPrefix[] = "legacy-";
const char kEphemeralDir[] = "ephemeralfs";
const char kEphemeralMountType[] = "tmpfs";
const char kGuestMountPath[] = "guestfs";
const char kEphemeralMountPerms[] = "mode=0700";

const int kDefaultEcryptfsKeySize = CRYPTOHOME_AES_KEY_BYTES;
const gid_t kDaemonStoreGid = 400;

// A helper class for scoping umask changes.
class ScopedUmask {
 public:
  ScopedUmask(Platform* platform, int mask)
      : platform_(platform),
        old_mask_(platform_->SetMask(mask)) {}
  ~ScopedUmask() {platform_->SetMask(old_mask_);}
 private:
  Platform* platform_;
  int old_mask_;
};

Mount::ScopedMountPoint::ScopedMountPoint(Mount* mount,
                                          const string& path)
  : mount_(mount), path_(path) {
}

Mount::ScopedMountPoint::~ScopedMountPoint() {
  if (mount_->platform_->IsDirectoryMounted(path_)) {
    mount_->ForceUnmount(path_);
  }
}

Mount::Mount()
    : default_user_(-1),
      chaps_user_(-1),
      default_group_(-1),
      default_access_group_(-1),
      shadow_root_(kDefaultShadowRoot),
      skel_source_(kDefaultSkeletonSource),
      system_salt_(),
      default_platform_(new Platform()),
      platform_(default_platform_.get()),
      crypto_(NULL),
      default_homedirs_(new HomeDirs()),
      homedirs_(default_homedirs_.get()),
      use_tpm_(true),
      default_current_user_(new UserSession()),
      current_user_(default_current_user_.get()),
      user_timestamp_cache_(NULL),
      enterprise_owned_(false),
      pkcs11_state_(kUninitialized),
      is_pkcs11_passkey_migration_required_(false),
      legacy_mount_(true),
      ephemeral_mount_(false),
      default_chaps_client_factory_(new ChapsClientFactory()),
      chaps_client_factory_(default_chaps_client_factory_.get()),
      boot_lockbox_(NULL) {
}

Mount::~Mount() {
  if (IsMounted())
    UnmountCryptohome();
}

bool Mount::Init(Platform* platform, Crypto* crypto,
                 UserOldestActivityTimestampCache *cache) {
  platform_ = platform;
  crypto_ = crypto;
  user_timestamp_cache_ = cache;

  bool result = true;

  homedirs_->set_platform(platform_);
  homedirs_->set_shadow_root(shadow_root_);
  homedirs_->set_enterprise_owned(enterprise_owned_);

  // Make sure both we and |homedirs_| have a proper device policy object.
  EnsureDevicePolicyLoaded(false);
  homedirs_->set_policy_provider(policy_provider_.get());
  if (!homedirs_->Init(platform, crypto, user_timestamp_cache_))
    result = false;

  // Get the user id and group id of the default user
  if (!platform_->GetUserId(kDefaultSharedUser, &default_user_,
                           &default_group_)) {
    result = false;
  }

  // Get the user id of the chaps user.
  gid_t not_used;
  if (!platform_->GetUserId(kChapsUserName, &chaps_user_, &not_used)) {
    result = false;
  }

  // Get the group id of the default shared access group.
  if (!platform_->GetGroupId(kDefaultSharedAccessGroup,
                             &default_access_group_)) {
    result = false;
  }

  int original_mask = platform_->SetMask(kDefaultUmask);
  // Create the shadow root if it doesn't exist
  if (!platform_->DirectoryExists(shadow_root_)) {
    platform_->CreateDirectory(shadow_root_);
  }

  if (use_tpm_ && !boot_lockbox_) {
    default_boot_lockbox_.reset(
        new BootLockbox(Tpm::GetSingleton(), platform_, crypto_));
    boot_lockbox_ = default_boot_lockbox_.get();
  }

  // One-time load of the global system salt (used in generating username
  // hashes)
  FilePath system_salt_file(StringPrintf("%s/salt", shadow_root_.c_str()));
  if (!crypto_->GetOrCreateSalt(system_salt_file,
                                CRYPTOHOME_DEFAULT_SALT_LENGTH, false,
                                &system_salt_)) {
    LOG(ERROR) << "Failed to load or create the system salt";
    result = false;
  }
  platform_->SetMask(original_mask);

  current_user_->Init(system_salt_);

  return result;
}

bool Mount::EnsureCryptohome(const Credentials& credentials,
                             bool* created) const {
  // If the user has an old-style cryptohome, delete it
  const std::string old_image_path(StringPrintf("%s/image",
    GetUserDirectory(credentials).c_str()));
  if (platform_->FileExists(old_image_path)) {
    platform_->DeleteFile(GetUserDirectory(credentials), true);
  }
  if (!EnsureUserMountPoints(credentials)) {
    return false;
  }
  // Now check for the presence of a vault directory
  const std::string vault_path(GetUserVaultPath(
      credentials.GetObfuscatedUsername(system_salt_)));
  if (!platform_->DirectoryExists(vault_path)) {
    // If the vault directory doesn't exist, then create the cryptohome from
    // scratch
    bool result = CreateCryptohome(credentials);
    if (created) {
      *created = result;
    }
    return result;
  }
  if (created) {
    *created = false;
  }
  return true;
}

bool Mount::DoesCryptohomeExist(const Credentials& credentials) const {
  // Check for the presence of a vault directory
  const std::string vault_path(GetUserVaultPath(
      credentials.GetObfuscatedUsername(system_salt_)));
  return platform_->DirectoryExists(vault_path);
}

bool Mount::MountCryptohome(const Credentials& credentials,
                            const Mount::MountArgs& mount_args,
                            MountError* mount_error) {
  CHECK(boot_lockbox_ || !use_tpm_);
  if (boot_lockbox_ && !boot_lockbox_->FinalizeBoot()) {
    LOG(WARNING) << "Failed to finalize boot lockbox.";
  }

  if (IsMounted()) {
    *mount_error = MOUNT_ERROR_MOUNT_POINT_BUSY;
    return false;
  }

  MountError local_mount_error = MOUNT_ERROR_NONE;
  bool result = MountCryptohomeInner(credentials,
                                     mount_args,
                                     true,
                                     &local_mount_error);
  // Retry once if there is a TPM communications failure
  if (!result && local_mount_error == MOUNT_ERROR_TPM_COMM_ERROR) {
    result = MountCryptohomeInner(credentials,
                                  mount_args,
                                  true,
                                  &local_mount_error);
  }
  if (mount_error) {
    *mount_error = local_mount_error;
  }
  return result;
}

bool Mount::MountCryptohomeInner(const Credentials& credentials,
                                 const Mount::MountArgs& mount_args,
                                 bool recreate_decrypt_fatal,
                                 MountError* mount_error) {
  current_user_->Reset();

  string username = credentials.username();
  if (username.compare(kIncognitoUser) == 0) {
    // TODO(fes): Have guest set error conditions?
    if (mount_error) {
      *mount_error = MOUNT_ERROR_NONE;
    }
    return MountGuestCryptohome();
  }

  ReloadDevicePolicy();
  bool ephemeral_users = AreEphemeralUsersEnabled();
  const string obfuscated_owner = GetObfuscatedOwner();
  if (ephemeral_users)
    homedirs_->RemoveNonOwnerCryptohomes();

  bool non_owner = enterprise_owned_ || (!obfuscated_owner.empty() &&
      credentials.GetObfuscatedUsername(system_salt_) != obfuscated_owner);

  // If the user is not the owner and either the ephemeral users policy is
  // enabled or the |ensure_ephemeral| flag is set in the |mount_args|, mount an
  // ephemeral cryptohome.
  if (non_owner && (ephemeral_users || mount_args.ensure_ephemeral)) {
    if (!mount_args.create_if_missing) {
      LOG(ERROR) << "An ephemeral cryptohome can only be mounted when its "
                 << "creation on-the-fly is allowed.";
      *mount_error = MOUNT_ERROR_USER_DOES_NOT_EXIST;
      return false;
    }

    if (!MountEphemeralCryptohome(credentials)) {
      homedirs_->Remove(credentials.username());
      *mount_error = MOUNT_ERROR_FATAL;
      return false;
    }

    // Ephemeral and guest users will not have a key index.
    current_user_->SetUser(credentials);
    *mount_error = MOUNT_ERROR_NONE;
    return true;
  }

  // If the |ensure_ephemeral| flag is set in the |mount_args|, never mount a
  // non-ephemeral cryptohome. Fail with an error instead.
  if (mount_args.ensure_ephemeral) {
    LOG(ERROR) << "An ephemeral cryptohome can only be mounted when the user "
               << "is not the owner.";
    *mount_error = MOUNT_ERROR_FATAL;
    return false;
  }

  if (!mount_args.create_if_missing && !DoesCryptohomeExist(credentials)) {
    if (mount_error) {
      LOG(ERROR) << "Asked to mount nonexistent user";
      *mount_error = MOUNT_ERROR_USER_DOES_NOT_EXIST;
    }
    return false;
  }

  bool created = false;
  if (!EnsureCryptohome(credentials, &created)) {
    LOG(ERROR) << "Error creating cryptohome.";
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }


  // Attempt to decrypt the vault keyset with the specified credentials
  VaultKeyset vault_keyset;
  vault_keyset.Initialize(platform_, crypto_);
  SerializedVaultKeyset serialized;
  MountError local_mount_error = MOUNT_ERROR_NONE;
  int index = -1;
  if (!DecryptVaultKeyset(credentials, true, &vault_keyset, &serialized,
                          &index, &local_mount_error)) {
    if (mount_error) {
      *mount_error = local_mount_error;
    }
    if (recreate_decrypt_fatal & (local_mount_error & MOUNT_ERROR_FATAL)) {
      LOG(ERROR) << "Error, cryptohome must be re-created because of fatal "
                 << "error.";
      if (!homedirs_->Remove(credentials.username())) {
        LOG(ERROR) << "Fatal decryption error, but unable to remove "
                   << "cryptohome.";
        return false;
      }
      // Allow one recursion into MountCryptohomeInner by blocking re-create on
      // fatal.
      bool local_result = MountCryptohomeInner(credentials,
                                               mount_args,
                                               false,
                                               mount_error);
      // If the mount was successful, set the status to indicate that the
      // cryptohome was recreated.
      if (local_result && mount_error) {
        *mount_error = MOUNT_ERROR_RECREATED;
      }
      return local_result;
    }
    return false;
  }

  if (!serialized.has_wrapped_chaps_key()) {
    is_pkcs11_passkey_migration_required_ = true;
    vault_keyset.CreateRandomChapsKey();
    ReEncryptVaultKeyset(credentials, vault_keyset, index, &serialized);
  }

  SecureBlob local_chaps_key(vault_keyset.chaps_key().begin(),
                             vault_keyset.chaps_key().end());
  pkcs11_token_auth_data_.swap(local_chaps_key);
  crypto_->ClearKeyset();

  // Before we use the matching keyset, make sure it isn't being misused.
  // Note, privileges don't protect against information leakage, they are
  // just software/DAC policy enforcement mechanisms.
  //
  // In the future we may provide some assurance by wrapping privileges
  // with the wrapped_key, but that is still of limited benefit.
  if (serialized.has_key_data() &&  // legacy keys are full privs
      !serialized.key_data().privileges().mount()) {
    // TODO(wad): Convert to CRYPTOHOME_ERROR_AUTHORIZATION_KEY_DENIED
    // TODO(wad): Expose the safe-printable label rather than the Chrome
    //            supplied one for log output.
    LOG(INFO) << "Mount attempt with unprivileged key";
    *mount_error = MOUNT_ERROR_KEY_FAILURE;
    return false;
  }

  // Add the decrypted key to the keyring so that ecryptfs can use it.
  string key_signature, fnek_signature;
  if (!crypto_->AddKeyset(vault_keyset, &key_signature, &fnek_signature)) {
    LOG(INFO) << "Cryptohome mount failed because of keyring failure.";
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  // Specify the ecryptfs options for mounting the user's cryptohome.
  string ecryptfs_options = StringPrintf("ecryptfs_cipher=aes"
                                         ",ecryptfs_key_bytes=%d"
                                         ",ecryptfs_fnek_sig=%s"
                                         ",ecryptfs_sig=%s"
                                         ",ecryptfs_unlink_sigs",
                                         kDefaultEcryptfsKeySize,
                                         fnek_signature.c_str(),
                                         key_signature.c_str());

  // Mount cryptohome
  // /home/.shadow: owned by root
  // /home/.shadow/$hash: owned by root
  // /home/.shadow/$hash/vault: owned by root
  // /home/.shadow/$hash/mount: owned by root
  // /home/.shadow/$hash/mount/root: owned by root
  // /home/.shadow/$hash/mount/user: owned by chronos
  // /home/chronos: owned by chronos
  // /home/chronos/user: owned by chronos
  // /home/user/$hash: owned by chronos
  // /home/root/$hash: owned by root

  string obfuscated_username = credentials.GetObfuscatedUsername(system_salt_);
  string vault_path = GetUserVaultPath(obfuscated_username);
  // Create vault_path/user as a passthrough directory, move all the (encrypted)
  // contents of vault_path into vault_path/user, create vault_path/root.
  MigrateToUserHome(vault_path);

  // TODO(wad) Make mount_point_ not instance-wide or do it at Init time.
  mount_point_ = GetUserMountDirectory(obfuscated_username);
  if (!platform_->CreateDirectory(mount_point_)) {
    PLOG(ERROR) << "Directory creation failed for " << mount_point_;
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  // Since Service::Mount cleans up stale mounts, we should only reach
  // this point if someone attempts to re-mount an in-use mount point.
  if (platform_->IsDirectoryMounted(mount_point_)) {
    LOG(ERROR) << "Mount point is busy: " << mount_point_
               << " for " << vault_path;
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }
  // TODO(wad,ellyjones) Why does Mount take current_user_?
  if (!MountForUser(current_user_, vault_path, mount_point_, "ecryptfs",
                    ecryptfs_options)) {
    PLOG(ERROR) << "Cryptohome mount failed for vault " << vault_path;
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  // Set the current user here so we can rely on it in the helpers..
  // On failure, they will linger, but should be reset on a new MountCryptohome
  // request.
  current_user_->SetUser(credentials);
  current_user_->set_key_index(index);
  if (serialized.has_key_data()) {
    current_user_->set_key_data(serialized.key_data());
  }

  // Move the tracked subdirectories from mount_point_/user to vault_path
  // as passthrough directories.
  CreateTrackedSubdirectories(credentials, created);

  if (created)
    CopySkeleton();

  string user_home = GetMountedUserHomePath(obfuscated_username);
  if (!SetupGroupAccess(FilePath(user_home))) {
    UnmountAllForUser(current_user_);
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  if (legacy_mount_)
    MountLegacyHome(user_home, mount_error);

  string user_multi_home =
      chromeos::cryptohome::home::GetUserPath(username).value();
  if (!BindForUser(current_user_, user_home, user_multi_home)) {
    PLOG(ERROR) << "Bind mount failed: " << user_home << " -> "
                << user_multi_home;
    UnmountAllForUser(current_user_);
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  // Temporary while we do the migration involved in http://crbug.com/224291
  // TODO(ellyjones): remove this to fix http://crbug.com/229411
  string temp_multi_home = GetNewUserPath(username);
  if (!BindForUser(current_user_, user_home, temp_multi_home)) {
    PLOG(ERROR) << "Bind mount failed: " << user_home << " -> "
                << temp_multi_home;
    UnmountAllForUser(current_user_);
    if (mount_error)
      *mount_error = MOUNT_ERROR_FATAL;
    return false;
  }

  string root_home = GetMountedRootHomePath(obfuscated_username);
  string root_multi_home =
      chromeos::cryptohome::home::GetRootPath(username).value();
  if (!BindForUser(current_user_, root_home, root_multi_home)) {
    PLOG(ERROR) << "Bind mount failed: " << root_home << " -> "
                << root_multi_home;
    UnmountAllForUser(current_user_);
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  // TODO(ellyjones): Expose the path to the root directory over dbus for use by
  // daemons. We may also want to bind-mount it somewhere stable.

  if (mount_error) {
    *mount_error = MOUNT_ERROR_NONE;
  }

  if (is_pkcs11_passkey_migration_required_) {
    credentials.GetPasskey(&legacy_pkcs11_passkey_);
  }
  return true;
}

bool Mount::MountEphemeralCryptohome(const Credentials& credentials) {
  const string username = credentials.username();
  string path = GetUserEphemeralPath(credentials.GetObfuscatedUsername(
      system_salt_));
  const string user_multi_home =
      chromeos::cryptohome::home::GetUserPath(username).value();
  const string root_multi_home =
      chromeos::cryptohome::home::GetRootPath(username).value();

  // If we're mounting as a guest, as source use just "guestfs" instead of an
  // actual path. We don't want the guest cryptohome to persist even between
  // logins during the same boot.
  if (credentials.username() == chromeos::cryptohome::home::kGuestUserName)
    path = kGuestMountPath;

  if (!EnsureUserMountPoints(credentials))
    return false;
  if (!SetUpEphemeralCryptohome(path, user_multi_home))
    return false;
  if (!MountForUser(current_user_,
                    path,
                    root_multi_home,
                    kEphemeralMountType,
                    kEphemeralMountPerms)) {
    LOG(ERROR) << "Mount of ephemeral root home at " << root_multi_home
               << "failed: " << errno;
    UnmountAllForUser(current_user_);
    return false;
  }

  if (legacy_mount_)
    MountLegacyHome(user_multi_home, NULL);

  string temp_multi_home = GetNewUserPath(username);
  if (!BindForUser(current_user_, user_multi_home, temp_multi_home)) {
    PLOG(ERROR) << "Bind mount failed: " << user_multi_home << " -> "
                << temp_multi_home;
    UnmountAllForUser(current_user_);
    return false;
  }
  ephemeral_mount_ = true;
  return true;
}

bool Mount::SetUpEphemeralCryptohome(const string& source_path,
                                     const string& home_dir) {
  // First, build up the home dir at a mount point not accessible to chronos.
  // This helps to avoid chown race conditions.
  const string ephemeral_skeleton_path = GetEphemeralSkeletonPath();
  if (!platform_->CreateDirectory(ephemeral_skeleton_path)) {
    LOG(ERROR) << "Failed to create " << ephemeral_skeleton_path << ": "
               << errno;
    return false;
  }
  // Note! This mount point does not show up in the MountStack.
  // TODO(wad) check for existing mount first.
  if (!platform_->Mount(source_path,
                        ephemeral_skeleton_path,
                        kEphemeralMountType,
                        kEphemeralMountPerms)) {
    LOG(ERROR) << "Mount of ephemeral skeleton at " << ephemeral_skeleton_path
               << "failed: " << errno;
    return false;
  }
  // Whatever happens, we want to unmount the tmpfs used to build the skeleton
  // home directory.
  ScopedMountPoint scoped_skeleton_mount(this, ephemeral_skeleton_path);
  CopySkeleton();

  // Create the Downloads directory if it does not exist so that it can later be
  // made group accessible when SetupGroupAccess() is called.
  FilePath downloads_path =
      FilePath(ephemeral_skeleton_path).Append(kDownloadsDir);
  if (!platform_->DirectoryExists(downloads_path.value())) {
    if (!platform_->CreateDirectory(downloads_path.value()) ||
        !platform_->SetOwnership(downloads_path.value(),
                                 default_user_, default_group_)) {
      LOG(ERROR) << "Couldn't create user Downloads directory: "
                 << downloads_path.value();
      return false;
    }
  }

  if (!platform_->SetOwnership(ephemeral_skeleton_path,
                               default_user_,
                               default_access_group_)) {
    LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
               << default_access_group_ << ") of path: "
               << ephemeral_skeleton_path;
    return false;
  }

  if (!SetupGroupAccess(FilePath(ephemeral_skeleton_path)))
    return false;

  if (!BindForUser(current_user_, ephemeral_skeleton_path, home_dir)) {
    LOG(ERROR) << "Bind mount of ephemeral user home from "
               << ephemeral_skeleton_path << " to " << home_dir << " failed: "
               << errno;
    return false;
  }
  return true;
}

bool Mount::MountForUser(UserSession *user, const std::string& src,
                         const std::string& dest, const std::string& type,
                         const std::string& options) {
  if (platform_->Mount(src, dest, type, options)) {
    mounts_.Push(dest);
    return true;
  }
  return false;
}

bool Mount::BindForUser(UserSession *user, const std::string& src,
                        const std::string& dest) {
  if (platform_->Bind(src, dest)) {
    mounts_.Push(dest);
    return true;
  }
  return false;
}

bool Mount::UnmountForUser(UserSession *user) {
  std::string mount_point;
  if (!mounts_.Pop(&mount_point)) {
    return false;
  }
  ForceUnmount(mount_point);
  return true;
}

void Mount::UnmountAllForUser(UserSession *user) {
  while (UnmountForUser(user)) { }
}

void Mount::ForceUnmount(const std::string& mount_point) {
  // Try an immediate unmount
  bool was_busy;
  if (!platform_->Unmount(mount_point, false, &was_busy)) {
    LOG(ERROR) << "Couldn't unmount vault immediately, was_busy = " << was_busy;
    if (was_busy) {
      std::vector<ProcessInformation> processes;
      platform_->GetProcessesWithOpenFiles(mount_point, &processes);
      for (std::vector<ProcessInformation>::iterator proc_itr =
             processes.begin();
           proc_itr != processes.end();
           proc_itr++) {
        LOG(ERROR) << "Process " << proc_itr->get_process_id()
                   << " had open files.  Command line: "
                   << proc_itr->GetCommandLine();
        if (proc_itr->get_cwd().length()) {
          LOG(ERROR) << "  (" << proc_itr->get_process_id() << ") CWD: "
                     << proc_itr->get_cwd();
        }
        for (std::set<std::string>::iterator file_itr =
               proc_itr->get_open_files().begin();
             file_itr != proc_itr->get_open_files().end();
             file_itr++) {
          LOG(ERROR) << "  (" << proc_itr->get_process_id() << ") Open File: "
                     << (*file_itr);
        }
      }
    }
    // Failed to unmount immediately, do a lazy unmount.  If |was_busy| we also
    // want to sync before the unmount to help prevent data loss.
    platform_->LazyUnmountAndSync(mount_point, was_busy);
  }
}

bool Mount::UnmountCryptohome() {
  UnmountAllForUser(current_user_);
  ReloadDevicePolicy();
  if (AreEphemeralUsersEnabled())
    homedirs_->RemoveNonOwnerCryptohomes();
  else
    UpdateCurrentUserActivityTimestamp(0);

  RemovePkcs11Token();
  current_user_->Reset();
  ephemeral_mount_ = false;
  crypto_->ClearKeyset();

  return true;
}

bool Mount::IsMounted() const {
  return mounts_.size() != 0;
}

bool Mount::IsVaultMounted() const {
  string obfuscated_username;
  current_user_->GetObfuscatedUsername(&obfuscated_username);
  const std::string vault_path = GetUserMountDirectory(obfuscated_username);
  return mounts_.Contains(vault_path);
}

bool Mount::OwnsMountPoint(const std::string& path) const {
  return mounts_.Contains(path);
}

bool Mount::CreateCryptohome(const Credentials& credentials) const {
  int original_mask = platform_->SetMask(kDefaultUmask);

  // Create the user's entry in the shadow root
  FilePath user_dir(GetUserDirectory(credentials));
  platform_->CreateDirectory(user_dir.value());

  // Generate a new master key
  VaultKeyset vault_keyset;
  vault_keyset.Initialize(platform_, crypto_);
  vault_keyset.CreateRandom();
  SerializedVaultKeyset serialized;
  if (!AddVaultKeyset(credentials, vault_keyset, &serialized)) {
    platform_->SetMask(original_mask);
    LOG(ERROR) << "Failed to add vault keyset to new user";
    return false;
  }
  // Merge in the key data from credentials using the label() as
  // the existence test. (All new-format calls must populate the
  // label on creation.)
  if (!credentials.key_data().label().empty()) {
    *serialized.mutable_key_data() = credentials.key_data();
  }

  // TODO(wad) move to storage by label-derivative and not number.
  if (!StoreVaultKeysetForUser(
       credentials.GetObfuscatedUsername(system_salt_),
       0,  // first key
       serialized)) {
    platform_->SetMask(original_mask);
    LOG(ERROR) << "Failed to store vault keyset for new user";
    return false;
  }

  // Create the user's vault.
  std::string vault_path = GetUserVaultPath(
      credentials.GetObfuscatedUsername(system_salt_));
  if (!platform_->CreateDirectory(vault_path)) {
    LOG(ERROR) << "Couldn't create vault path: " << vault_path.c_str();
    platform_->SetMask(original_mask);
    return false;
  }

  // Restore the umask
  platform_->SetMask(original_mask);
  return true;
}

bool Mount::CreateTrackedSubdirectories(const Credentials& credentials,
                                        bool is_new) const {
  const int original_mask = platform_->SetMask(kDefaultUmask);

  // Add the subdirectories if they do not exist.
  const std::string obfuscated_username =
      credentials.GetObfuscatedUsername(system_salt_);
  const FilePath shadow_home(VaultPathToUserPath(GetUserVaultPath(
      obfuscated_username)));
  if (!platform_->DirectoryExists(shadow_home.value())) {
     LOG(ERROR) << "Can't create tracked subdirectories for a missing user.";
     platform_->SetMask(original_mask);
     return false;
  }

  const FilePath user_home(GetMountedUserHomePath(obfuscated_username));

  static const FilePath kTrackedDirs[] = {
    FilePath(kCacheDir),
    FilePath(kDownloadsDir),
    FilePath(kGCacheDir),
    FilePath(kGCacheDir).Append(kGCacheVersionDir),
    FilePath(kGCacheDir).Append(kGCacheVersionDir).Append(kGCacheTmpDir),
  };

  // The call is allowed to partially fail if directory creation fails, but we
  // want to have as many of the specified tracked directories created as
  // possible.
  bool result = true;
  for (size_t index = 0; index < arraysize(kTrackedDirs); ++index) {
    const FilePath shadowside_dir = shadow_home.Append(kTrackedDirs[index]);
    const FilePath userside_dir = user_home.Append(kTrackedDirs[index]);

    // If non-pass-through dir with the same name existed - delete it
    // to prevent duplication.
    if (!is_new && platform_->DirectoryExists(userside_dir.value()) &&
        !platform_->DirectoryExists(shadowside_dir.value())) {
      platform_->DeleteFile(userside_dir.value(), true);
    }

    // Create pass-through directory.
    if (!platform_->DirectoryExists(shadowside_dir.value())) {
      LOG(INFO) << "Creating pass-through directories "
                << shadowside_dir.value();
      platform_->CreateDirectory(shadowside_dir.value());
      if (!platform_->SetOwnership(shadowside_dir.value(),
                                   default_user_, default_group_)) {
        LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
                   << default_group_ << ") of tracked directory path: "
                   << shadowside_dir.value();
        platform_->DeleteFile(shadowside_dir.value(), true);
        result = false;
        continue;
      }
    }
  }

  // Restore the umask
  platform_->SetMask(original_mask);
  return result;
}

bool Mount::UpdateCurrentUserActivityTimestamp(int time_shift_sec) {
  string obfuscated_username;
  current_user_->GetObfuscatedUsername(&obfuscated_username);
  if (!obfuscated_username.empty() && !ephemeral_mount_) {
    SerializedVaultKeyset serialized;
    // TODO(wad) Start using current_user_'s key_data label when
    //           it is defined.
    LoadVaultKeysetForUser(obfuscated_username, current_user_->key_index(),
                           &serialized);
    base::Time timestamp = platform_->GetCurrentTime();
    if (time_shift_sec > 0)
      timestamp -= base::TimeDelta::FromSeconds(time_shift_sec);
    serialized.set_last_activity_timestamp(timestamp.ToInternalValue());
    // Only update the key in use.
    StoreVaultKeysetForUser(obfuscated_username, current_user_->key_index(),
                            serialized);
    if (user_timestamp_cache_->initialized()) {
      user_timestamp_cache_->UpdateExistingUser(
          FilePath(GetUserDirectoryForUser(obfuscated_username)), timestamp);
    }
    return true;
  }
  return false;
}

void Mount::EnsureDevicePolicyLoaded(bool force_reload) {
  if (!policy_provider_.get()) {
    policy_provider_.reset(new policy::PolicyProvider());
    homedirs_->set_policy_provider(policy_provider_.get());
  } else if (force_reload) {
    policy_provider_->Reload();
  }
}

void Mount::DoForEveryUnmountedCryptohome(
    const CryptohomeCallback& cryptohome_cb) {
  std::vector<std::string> entries;
  if (!platform_->EnumerateDirectoryEntries(shadow_root_, false, &entries))
    return;
  for (std::vector<std::string>::iterator it = entries.begin();
       it != entries.end(); ++it) {
    FilePath path(*it);
    const std::string dir_name = path.BaseName().value();
    if (!chromeos::cryptohome::home::IsSanitizedUserName(dir_name))
      continue;
    std::string vault_path = path.Append(kVaultDir).value();
    std::string mount_path = path.Append(kMountDir).value();
    if (!platform_->DirectoryExists(vault_path)) {
      continue;
    }
    if (platform_->IsDirectoryMountedWith(mount_path, vault_path)) {
      continue;
    }
    cryptohome_cb.Run(FilePath(vault_path));
  }
}

bool Mount::SetupGroupAccess(const FilePath& home_dir) const {
  // Make the following directories group accessible by other system daemons:
  //   {home_dir}
  //   {home_dir}/Downloads
  //   {home_dir}/GCache (only if it exists)
  //   {home_dir}/GCache/v1 (only if it exists)
  const struct {
    FilePath path;
    bool optional;
  } kGroupAccessiblePaths[] = {
    { home_dir },
    { home_dir.Append(kDownloadsDir), false },
    { home_dir.Append(kGCacheDir), true },
    { home_dir.Append(kGCacheDir).Append(kGCacheVersionDir), true },
  };

  mode_t mode = S_IXGRP;
  for (size_t i = 0; i < arraysize(kGroupAccessiblePaths); ++i) {
    if (!platform_->FileExists(kGroupAccessiblePaths[i].path.value()) &&
        kGroupAccessiblePaths[i].optional)
      continue;

    if (!platform_->SetGroupAccessible(kGroupAccessiblePaths[i].path.value(),
                                       default_access_group_, mode))
      return false;
  }
  return true;
}

bool Mount::AreSameUser(const Credentials& credentials) {
  return current_user_->CheckUser(credentials);
}

bool Mount::AreValid(const Credentials& credentials) {
  // If the current logged in user matches, use the UserSession to verify the
  // credentials.  This is less costly than a trip to the TPM, and only verifies
  // a user during their logged in session.
  if (current_user_->CheckUser(credentials)) {
    return current_user_->Verify(credentials);
  }
  return false;
}

bool Mount::LoadVaultKeyset(const Credentials& credentials,
                            int index,
                            SerializedVaultKeyset* serialized) const {
  return LoadVaultKeysetForUser(credentials.GetObfuscatedUsername(system_salt_),
                                index,
                                serialized);
}

bool Mount::LoadVaultKeysetForUser(const string& obfuscated_username,
                                   int index,
                                   SerializedVaultKeyset* serialized) const {
  if (index < 0 || index > kKeyFileMax) {
    LOG(ERROR) << "Attempted to load an invalid key index: " << index;
    return false;
  }
  // Load the encrypted keyset
  std::string user_key_file = GetUserLegacyKeyFileForUser(obfuscated_username,
                                                          index);
  if (!platform_->FileExists(user_key_file)) {
    return false;
  }
  SecureBlob cipher_text;
  if (!platform_->ReadFile(user_key_file, &cipher_text)) {
    LOG(ERROR) << "Failed to read keyset file for user " << obfuscated_username;
    return false;
  }
  if (!serialized->ParseFromArray(cipher_text.data(), cipher_text.size())) {
    LOG(ERROR) << "Failed to parse keyset for user " << obfuscated_username;
    return false;
  }
  return true;
}

bool Mount::StoreVaultKeysetForUser(
    const string& obfuscated_username,
    int index,
    const SerializedVaultKeyset& serialized) const {
  if (index < 0 || index > kKeyFileMax) {
    LOG(ERROR) << "Attempted to store an invalid key index: " << index;
    return false;
  }
  SecureBlob final_blob(serialized.ByteSize());
  serialized.SerializeWithCachedSizesToArray(
      static_cast<google::protobuf::uint8*>(final_blob.data()));
  return platform_->WriteFileAtomicDurable(
      GetUserLegacyKeyFileForUser(obfuscated_username, index),
      final_blob,
      kKeyFilePermissions);
}

bool Mount::DecryptVaultKeyset(const Credentials& credentials,
                               bool migrate_if_needed,
                               VaultKeyset* vault_keyset,
                               SerializedVaultKeyset* serialized,
                               int* index,
                               MountError* error) const {
  SecureBlob passkey;
  credentials.GetPasskey(&passkey);
  *error = MOUNT_ERROR_FATAL;

  std::string obfuscated_username =
    credentials.GetObfuscatedUsername(system_salt_);

  // Most straightforward approach, try every key. We can optimize
  // by walking the directory, but 100 failed open() calls isn't that
  // many on a sign-in failure.
  unsigned int crypt_flags = 0;
  Crypto::CryptoError crypto_error = Crypto::CE_NONE;
  *index = -1;
  std::vector<int> key_indices;
  if (!homedirs_->GetVaultKeysets(obfuscated_username, &key_indices)) {
    LOG(WARNING) << "No valid keysets on disk for " << obfuscated_username;
  }
  std::vector<int>::const_iterator iter = key_indices.begin();
  for ( ; iter != key_indices.end(); ++iter) {
    // Load the encrypted keyset
    if (!LoadVaultKeysetForUser(obfuscated_username, *iter, serialized)) {
      LOG(ERROR) << "Could not parse keyset " << *iter
                 << " for " << obfuscated_username;
      continue;
    }

    // If a specific key was requested by label, then check if the
    // label matches or if the key does not have a label, use the
    // legacy-key translation from index to label.
    //
    // Label-less requests will still iterate over all keys.
    if (!credentials.key_data().label().empty()) {
      // If we're searching by label, don't let a no-key-found become
      // MOUNT_ERROR_FATAL.  In the past, no parseable key was a fatal
      // error.  Just treat it like an invalid key.  This allows for
      // multiple per-label requests then a wildcard, worst case, before
      // the Cryptohome is removed.
      *error = MOUNT_ERROR_KEY_FAILURE;
      if (serialized->has_key_data()) {
        if (credentials.key_data().label() != serialized->key_data().label())
          continue;
      } else {
        if (credentials.key_data().label() !=
            StringPrintf("%s%d", kKeyLegacyPrefix, *iter))
          continue;
      }
    }

    // Attempt decrypt the master key with the passkey
    crypt_flags = 0;
    crypto_error = Crypto::CE_NONE;
    if (crypto_->DecryptVaultKeyset(*serialized, passkey, &crypt_flags,
                                    &crypto_error, vault_keyset)) {
      // Success!
      *error = MOUNT_ERROR_NONE;
      *index = *iter;
      break;
    }

    if (error) {
      switch (crypto_error) {
        case Crypto::CE_TPM_FATAL:
        case Crypto::CE_OTHER_FATAL:
          *error = MOUNT_ERROR_FATAL;
          break;
        // Don't keep trying on TPM errors.
        case Crypto::CE_TPM_COMM_ERROR:
          *error = MOUNT_ERROR_TPM_COMM_ERROR;
          return false;
        case Crypto::CE_TPM_DEFEND_LOCK:
          *error = MOUNT_ERROR_TPM_DEFEND_LOCK;
          return false;
        case Crypto::CE_TPM_REBOOT:
          *error = MOUNT_ERROR_TPM_NEEDS_REBOOT;
          return false;
        default:
          *error = MOUNT_ERROR_KEY_FAILURE;
          break;
      }
    }
  }
  // Failed to decrypt any keyset.
  if (*error != MOUNT_ERROR_NONE) {
    LOG(ERROR) << "Failed to decrypt any keysets for " << obfuscated_username;
    return false;
  }

  if (!migrate_if_needed)
    return true;

  // Calling EnsureTpm here handles the case where a user logged in while
  // cryptohome was taking TPM ownership.  In that case, their vault keyset
  // would be scrypt-wrapped and the TPM would not be connected.  If we're
  // configured to use the TPM, calling EnsureTpm will try to connect, and
  // if successful, the call to has_tpm() below will succeed, allowing
  // re-wrapping (migration) using the TPM.
  if (use_tpm_) {
    crypto_->EnsureTpm(false);
  }

  // If the vault keyset's TPM state is not the same as that configured for
  // the device, re-save the keyset (this will save in the device's default
  // method).
  //                      1   2   3   4   5   6   7   8   9  10  11  12
  // use_tpm              -   -   -   X   X   X   X   X   X   -   -   -
  //
  // fallback_to_scrypt   -   -   -   -   -   -   X   X   X   X   X   X
  //
  // tpm_wrapped          -   X   -   -   X   -   -   X   -   -   X   -
  //
  // scrypt_wrapped       -   -   X   -   -   X   -   -   X   -   -   X
  //
  // migrate              N   Y   Y   Y   N   Y   Y   N   Y   Y   Y   N
  bool tpm_wrapped =
      (crypt_flags & SerializedVaultKeyset::TPM_WRAPPED) != 0;
  bool scrypt_wrapped =
      (crypt_flags & SerializedVaultKeyset::SCRYPT_WRAPPED) != 0;
  bool should_tpm = (crypto_->has_tpm() && use_tpm_ &&
                     crypto_->is_cryptohome_key_loaded());
  bool should_scrypt = true;
  do {
    // If the keyset was TPM-wrapped, but there was no public key hash,
    // always re-save.  Otherwise, check the table.
    if (crypto_error != Crypto::CE_NO_PUBLIC_KEY_HASH) {
      if (tpm_wrapped && should_tpm)
        break;  // 5, 8
      if (scrypt_wrapped && should_scrypt && !should_tpm)
        break;  // 12
      if (!tpm_wrapped && !scrypt_wrapped && !should_tpm && !should_scrypt)
        break;  // 1
    }
    // This is not considered a fatal error.  Re-saving with the desired
    // protection is ideal, but not required.
    SerializedVaultKeyset new_serialized;
    new_serialized.CopyFrom(*serialized);
    if (ReEncryptVaultKeyset(credentials, *vault_keyset, *index,
                             &new_serialized)) {
      serialized->CopyFrom(new_serialized);
    }
  } while (false);

  return true;
}

bool Mount::AddVaultKeyset(const Credentials& credentials,
                           const VaultKeyset& vault_keyset,
                           SerializedVaultKeyset* serialized) const {
  // We don't do passkey to wrapper conversion because it is salted during save
  SecureBlob passkey;
  credentials.GetPasskey(&passkey);

  // Encrypt the vault keyset
  SecureBlob salt(CRYPTOHOME_DEFAULT_KEY_SALT_SIZE);
  CryptoLib::GetSecureRandom(salt.data(), salt.size());

  if (!crypto_->EncryptVaultKeyset(vault_keyset, passkey, salt, serialized)) {
    LOG(ERROR) << "Encrypting vault keyset failed";
    return false;
  }

  return true;
}

bool Mount::ReEncryptVaultKeyset(const Credentials& credentials,
                                 const VaultKeyset& vault_keyset,
                                 int key_index,
                                 SerializedVaultKeyset* serialized) const {
  std::string obfuscated_username =
    credentials.GetObfuscatedUsername(system_salt_);
  std::vector<std::string> files(2);
  files[0] = GetUserSaltFileForUser(obfuscated_username, key_index);
  files[1] = GetUserLegacyKeyFileForUser(obfuscated_username, key_index);
  if (!CacheOldFiles(files)) {
    LOG(ERROR) << "Couldn't cache old key material.";
    return false;
  }
  if (!AddVaultKeyset(credentials, vault_keyset, serialized)) {
    LOG(ERROR) << "Couldn't add keyset.";
    RevertCacheFiles(files);
    return false;
  }

  // Note that existing legacy keysets are not automatically annotated.
  // All _new_ interfaces that support KeyData will implicitly translate
  // master.<index> to label=<kKeyLegacyFormat,index> for checking on
  // label uniqueness.  This means that we will still be able to use the
  // lack of KeyData in the future as input to migration.
  if (!StoreVaultKeysetForUser(credentials.GetObfuscatedUsername(system_salt_),
                               key_index, *serialized)) {
    LOG(ERROR) << "Write to master key failed";
    RevertCacheFiles(files);
    return false;
  }
  DeleteCacheFiles(files);
  return true;
}

bool Mount::MountGuestCryptohome() {
  CHECK(boot_lockbox_ || !use_tpm_);
  if (boot_lockbox_ && !boot_lockbox_->FinalizeBoot()) {
    LOG(WARNING) << "Failed to finalize boot lockbox.";
  }

  std::string guest = chromeos::cryptohome::home::kGuestUserName;
  UsernamePasskey guest_creds(guest.c_str(), chromeos::Blob(0));
  current_user_->Reset();
  return MountEphemeralCryptohome(guest_creds);
}

string Mount::GetUserDirectory(const Credentials& credentials) const {
  return GetUserDirectoryForUser(
      credentials.GetObfuscatedUsername(system_salt_));
}

string Mount::GetUserDirectoryForUser(const string& obfuscated_username) const {
  return StringPrintf("%s/%s",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str());
}

string Mount::GetUserSaltFileForUser(const string& obfuscated_username,
                                    int index) const {
  DCHECK(index < kKeyFileMax && index >= 0);
  return StringPrintf("%s/%s/master.%d.salt",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str(),
                      index);
}

string Mount::GetUserLegacyKeyFileForUser(const string& obfuscated_username,
                                          int index) const {
  DCHECK(index < kKeyFileMax && index >= 0);
  return StringPrintf("%s/%s/%s%d",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str(),
                      kKeyFile,
                      index);
}

// This is the new planned format for keyfile storage.
string Mount::GetUserKeyFileForUser(const string& obfuscated_username,
                                    const string& label) const {
  DCHECK(!label.empty());
  // SHA1 is not for any other purpose than to provide a reasonably
  // collision-resistant, fixed length, path-safe file suffix.
  string digest = base::SHA1HashString(label);
  string safe_label = base::HexEncode(digest.c_str(), digest.length());
  return StringPrintf("%s/%s/%s%s",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str(),
                      kKeyFile,
                      safe_label.c_str());
}

string Mount::GetUserEphemeralPath(const string& obfuscated_username) const {
  return StringPrintf("%s/%s", kEphemeralDir, obfuscated_username.c_str());
}

string Mount::GetUserVaultPath(const std::string& obfuscated_username) const {
  return StringPrintf("%s/%s/%s",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str(),
                      kVaultDir);
}

string Mount::GetUserMountDirectory(
    const std::string& obfuscated_username) const {
  return StringPrintf("%s/%s/%s",
                      shadow_root_.c_str(),
                      obfuscated_username.c_str(),
                      kMountDir);
}

string Mount::VaultPathToUserPath(const std::string& vault) const {
  return StringPrintf("%s/%s", vault.c_str(), kUserHomeSuffix);
}

string Mount::VaultPathToRootPath(const std::string& vault) const {
  return StringPrintf("%s/%s", vault.c_str(), kRootHomeSuffix);
}

string Mount::GetMountedUserHomePath(
    const std::string& obfuscated_username) const {
  return StringPrintf("%s/%s",
                      GetUserMountDirectory(obfuscated_username).c_str(),
                      kUserHomeSuffix);
}

string Mount::GetMountedRootHomePath(
    const std::string& obfuscated_username) const {
  return StringPrintf("%s/%s",
                      GetUserMountDirectory(obfuscated_username).c_str(),
                      kRootHomeSuffix);
}

// TODO(dkrahn,wad) Makes this unique so we don't have to worry about
//                  parallelism.
string Mount::GetEphemeralSkeletonPath() const {
  return StringPrintf("%s/%s", shadow_root_.c_str(), kSkeletonDir);
}

string Mount::GetObfuscatedOwner() {
  EnsureDevicePolicyLoaded(false);
  string owner;
  if (policy_provider_->device_policy_is_loaded())
    policy_provider_->GetDevicePolicy().GetOwner(&owner);

  if (!owner.empty()) {
    return UsernamePasskey(owner.c_str(), chromeos::Blob())
        .GetObfuscatedUsername(system_salt_);
  }
  return "";
}

bool Mount::AreEphemeralUsersEnabled() {
  EnsureDevicePolicyLoaded(false);
  // If the policy cannot be loaded, default to non-ephemeral users.
  bool ephemeral_users_enabled = false;
  if (policy_provider_->device_policy_is_loaded())
    policy_provider_->GetDevicePolicy().GetEphemeralUsersEnabled(
        &ephemeral_users_enabled);
  return ephemeral_users_enabled;
}

void Mount::ReloadDevicePolicy() {
  EnsureDevicePolicyLoaded(true);
}

bool Mount::CheckChapsDirectory(const std::string& dir,
                                const std::string& legacy_dir) {
  const Platform::Permissions kChapsDirPermissions = {
    chaps_user_,                 // chaps
    default_access_group_,       // chronos-access
    S_IRWXU | S_IRGRP | S_IXGRP  // 0750
  };
  const Platform::Permissions kChapsFilePermissions = {
    chaps_user_,                 // chaps
    default_access_group_,       // chronos-access
    S_IRUSR | S_IWUSR | S_IRGRP  // 0640
  };
  const Platform::Permissions kChapsSaltPermissions = {
    0,                 // root
    0,                 // root
    S_IRUSR | S_IWUSR  // 0600
  };

  // If the Chaps database directory does not exist, create it.
  if (!platform_->DirectoryExists(dir)) {
    if (platform_->DirectoryExists(legacy_dir)) {
      LOG(INFO) << "Moving chaps directory from " << legacy_dir << " to "
                << dir;
      if (!platform_->CopyWithPermissions(legacy_dir, dir)) {
        return false;
      }
      if (!platform_->DeleteFile(legacy_dir, true)) {
        PLOG(WARNING) << "Failed to clean up " << legacy_dir;
        return false;
      }
    } else {
      if (!platform_->CreateDirectory(dir)) {
        LOG(ERROR) << "Failed to create " << dir;
        return false;
      }
      if (!platform_->SetOwnership(dir,
                                   kChapsDirPermissions.user,
                                   kChapsDirPermissions.group)) {
        LOG(ERROR) << "Couldn't set file ownership for " << dir;
        return false;
      }
      if (!platform_->SetPermissions(dir, kChapsDirPermissions.mode)) {
        LOG(ERROR) << "Couldn't set permissions for " << dir;
        return false;
      }
    }
    return true;
  }
  // Directory already exists so check permissions and log a warning
  // if not as expected then attempt to apply correct permissions.
  std::map<std::string, Platform::Permissions> special_cases;
  special_cases[dir + "/auth_data_salt"] = kChapsSaltPermissions;
  if (!platform_->ApplyPermissionsRecursive(dir,
                                            kChapsFilePermissions,
                                            kChapsDirPermissions,
                                            special_cases)) {
    LOG(ERROR) << "Chaps permissions failure.";
    return false;
  }
  return true;
}

bool Mount::InsertPkcs11Token() {
  std::string username = current_user_->username();
  FilePath token_dir = homedirs_->GetChapsTokenDir(username);
  FilePath legacy_token_dir = homedirs_->GetLegacyChapsTokenDir(username);
  if (!CheckChapsDirectory(token_dir.value(),
                           legacy_token_dir.value()))
    return false;
  // We may create a salt file and, if so, we want to restrict access to it.
  ScopedUmask scoped_umask(platform_, kDefaultUmask);

  // Derive authorization data for the token from the passkey.
  FilePath salt_file = homedirs_->GetChapsTokenSaltPath(username);

  scoped_ptr<chaps::TokenManagerClient> chaps_client(
      chaps_client_factory_->New());

  // If migration is required, send it before the login event.
  if (is_pkcs11_passkey_migration_required_) {
    LOG(INFO) << "Migrating authorization data.";
    SecureBlob old_auth_data;
    if (!crypto_->PasskeyToTokenAuthData(legacy_pkcs11_passkey_,
                                         salt_file,
                                         &old_auth_data))
      return false;
    chaps_client->ChangeTokenAuthData(
        token_dir,
        old_auth_data,
        pkcs11_token_auth_data_);
    is_pkcs11_passkey_migration_required_ = false;
    legacy_pkcs11_passkey_.clear();
  }

  Pkcs11Init pkcs11init;
  int slot_id = 0;
  if (!chaps_client->LoadToken(
      IsolateCredentialManager::GetDefaultIsolateCredential(),
      token_dir,
      pkcs11_token_auth_data_,
      pkcs11init.GetTpmTokenLabelForUser(current_user_->username()),
      &slot_id)) {
    LOG(ERROR) << "Failed to load PKCS #11 token.";
    ReportCryptohomeError(kLoadPkcs11TokenFailed);
  }
  pkcs11_token_auth_data_.clear();
  return true;
}

void Mount::RemovePkcs11Token() {
  std::string username = current_user_->username();
  FilePath token_dir = homedirs_->GetChapsTokenDir(username);
  scoped_ptr<chaps::TokenManagerClient> chaps_client(
      chaps_client_factory_->New());
  chaps_client->UnloadToken(
      IsolateCredentialManager::GetDefaultIsolateCredential(),
      token_dir);
}

void Mount::MigrateToUserHome(const std::string& vault_path) const {
  std::vector<string> ent_list;
  std::vector<string>::iterator ent_iter;
  FilePath user_path(VaultPathToUserPath(vault_path));
  FilePath root_path(VaultPathToRootPath(vault_path));
  struct stat st;

  // This check makes the migration idempotent; if we completed a migration,
  // root_path will exist and we're done, and if we didn't complete it, we can
  // finish it.
  if (platform_->Stat(root_path.value(), &st) &&
      S_ISDIR(st.st_mode) &&
      st.st_mode & S_ISVTX &&
      st.st_uid == kMountOwnerUid &&
      st.st_gid == kDaemonStoreGid) {
      return;
  }

  // There are three ways to get here:
  // 1) the Stat() call above succeeded, but what we saw was not a root-owned
  //    directory.
  // 2) the Stat() call above failed with -ENOENT
  // 3) the Stat() call above failed for some other reason
  // In any of these cases, it is safe for us to rm root_path, since the only
  // way it could have gotten there is if someone undertook some funny business
  // as root.
  platform_->DeleteFile(root_path.value(), true);

  // Get the list of entries before we create user_path, since user_path will be
  // inside dir.
  platform_->EnumerateDirectoryEntries(vault_path, false, &ent_list);

  if (!platform_->CreateDirectory(user_path.value())) {
    PLOG(ERROR) << "CreateDirectory() failed: " << user_path.value();
    return;
  }

  if (!platform_->SetOwnership(user_path.value(), default_user_,
                               default_group_)) {
    PLOG(ERROR) << "SetOwnership() failed: " << user_path.value();
    return;
  }

  for (ent_iter = ent_list.begin(); ent_iter != ent_list.end(); ent_iter++) {
    FilePath basename(*ent_iter);
    FilePath next_path = basename;
    basename = basename.BaseName();
    // Don't move the user/ directory itself. We're currently operating on an
    // _unmounted_ ecryptfs, which means all the filenames are encrypted except
    // the user and root passthrough directories.
    if (basename.value() == kUserHomeSuffix) {
      LOG(WARNING) << "Interrupted migration detected.";
      continue;
    }
    FilePath dest_path(user_path);
    dest_path = dest_path.Append(basename);
    if (!platform_->Rename(next_path.value(), dest_path.value())) {
      // TODO(ellyjones): UMA event log for this
      PLOG(WARNING) << "Migration fault: can't move " << next_path.value()
                    << " to " << dest_path.value();
    }
  }
  // Create root_path at the end as a sentinel for migration.
  if (!platform_->CreateDirectory(root_path.value())) {
    PLOG(ERROR) << "CreateDirectory() failed: " << root_path.value();
    return;
  }
  if (!platform_->SetOwnership(root_path.value(), kMountOwnerUid,
                               kDaemonStoreGid)) {
    PLOG(ERROR) << "SetOwnership() failed: " << root_path.value();
    return;
  }
  if (!platform_->SetPermissions(root_path.value(),
                                 S_IRWXU | S_IRWXG | S_ISVTX)) {
    PLOG(ERROR) << "SetPermissions() failed: " << root_path.value();
    return;
  }
  LOG(INFO) << "Migrated (or created) user directory: " << vault_path.c_str();
}

void Mount::CopySkeleton() const {
  CHECK(current_user_);
  FilePath destination = FilePath(GetEphemeralSkeletonPath());
  // For a Mount with a real vault, the skeleton can be safely
  // prepared under /home/.shadow/[hash]/mount/user, but for
  // ephemeral mounts, we use a single location.
  if (IsVaultMounted()) {
    std::string user;
    current_user_->GetObfuscatedUsername(&user);
    destination = FilePath(GetMountedUserHomePath(user));
  } else if (!platform_->IsDirectoryMounted(destination.value())) {
    LOG(ERROR) << "CopySkeleton with no mounted vault or ephemeral path.";
    return;
  }
  RecursiveCopy(destination, FilePath(skel_source_));
}


bool Mount::CacheOldFiles(const std::vector<std::string>& files) const {
  for (unsigned int index = 0; index < files.size(); ++index) {
    FilePath file(files[index]);
    FilePath file_bak(StringPrintf("%s.bak", files[index].c_str()));
    if (platform_->FileExists(file_bak.value())) {
      if (!platform_->DeleteFile(file_bak.value(), false)) {
        return false;
      }
    }
    if (platform_->FileExists(file.value())) {
      if (!platform_->Move(file.value(), file_bak.value())) {
        return false;
      }
    }
  }
  return true;
}

void Mount::RecursiveCopy(const FilePath& destination,
                          const FilePath& source) const {
  scoped_ptr<FileEnumerator> file_enumerator(
      platform_->GetFileEnumerator(source.value(), false,
                                   base::FileEnumerator::FILES));
  std::string next_path;
  while (!(next_path = file_enumerator->Next()).empty()) {
    FilePath file_name = FilePath(next_path).BaseName();
    FilePath destination_file = destination.Append(file_name);
    if (!platform_->Copy(next_path, destination_file.value()) ||
        !platform_->SetOwnership(destination_file.value(),
                                 default_user_, default_group_)) {
      LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
                 << default_group_ << ") of destination path: "
                 << destination_file.value().c_str();
    }
  }
  scoped_ptr<FileEnumerator> dir_enumerator(
      platform_->GetFileEnumerator(source.value(), false,
                                   base::FileEnumerator::DIRECTORIES));
  while (!(next_path = dir_enumerator->Next()).empty()) {
    FilePath dir_name = FilePath(next_path).BaseName();
    FilePath destination_dir = destination.Append(dir_name);
    LOG(INFO) << "RecursiveCopy: " << destination_dir.value();
    if (!platform_->CreateDirectory(destination_dir.value()) ||
        !platform_->SetOwnership(destination_dir.value(),
                                 default_user_, default_group_)) {
      LOG(ERROR) << "Couldn't change owner (" << default_user_ << ":"
                 << default_group_ << ") of destination path: "
                 << destination_dir.value().c_str();
    }
    RecursiveCopy(destination_dir, FilePath(next_path));
  }
}

bool Mount::RevertCacheFiles(const std::vector<std::string>& files) const {
  for (unsigned int index = 0; index < files.size(); ++index) {
    FilePath file(files[index]);
    FilePath file_bak(StringPrintf("%s.bak", files[index].c_str()));
    if (platform_->FileExists(file_bak.value())) {
      if (!platform_->Move(file_bak.value(), file.value())) {
        return false;
      }
    }
  }
  return true;
}

bool Mount::DeleteCacheFiles(const std::vector<std::string>& files) const {
  for (unsigned int index = 0; index < files.size(); ++index) {
    FilePath file(files[index]);
    FilePath file_bak(StringPrintf("%s.bak", files[index].c_str()));
    if (platform_->FileExists(file_bak.value())) {
      if (!platform_->DeleteFile(file_bak.value(), false)) {
        return false;
      }
    }
  }
  return true;
}

void Mount::GetUserSalt(const Credentials& credentials, bool force,
                        int key_index, SecureBlob* salt) const {
  FilePath path(GetUserSaltFileForUser(
                  credentials.GetObfuscatedUsername(system_salt_),
                  key_index));
  crypto_->GetOrCreateSalt(path, CRYPTOHOME_DEFAULT_SALT_LENGTH, force, salt);
}

bool Mount::EnsurePathComponent(const FilePath& fp, size_t num,
                                uid_t uid, gid_t gid) const {
  std::vector<std::string> path_parts;
  fp.GetComponents(&path_parts);
  FilePath check_path(path_parts[0]);
  for (size_t i = 1; i < num; i++)
    check_path = check_path.Append(path_parts[i]);

  struct stat st;
  if (!platform_->Stat(check_path.value(), &st)) {
    // Dirent not there, so create and set ownership.
    if (!platform_->CreateDirectory(check_path.value())) {
      PLOG(ERROR) << "Can't create: " << check_path.value();
      return false;
    }
    if (!platform_->SetOwnership(check_path.value(), uid, gid)) {
      PLOG(ERROR) << "Can't chown/chgrp: " << check_path.value()
                  << " uid " << uid << " gid " << gid;
      return false;
    }
  } else {
    // Dirent there; make sure it's acceptable.
    if (!S_ISDIR(st.st_mode)) {
      LOG(ERROR) << "Non-directory path: " << check_path.value();
      return false;
    }
    if (st.st_uid != uid) {
      LOG(ERROR) << "Owner mismatch: " << check_path.value()
                 << " " << st.st_uid << " != " << uid;
      return false;
    }
    if (st.st_gid != gid) {
      LOG(ERROR) << "Group mismatch: " << check_path.value()
                 << " " << st.st_gid << " != " << gid;
      return false;
    }
    if (st.st_mode & S_IWOTH) {
      LOG(ERROR) << "Permissions too lenient: " << check_path.value()
                 << " has " << std::oct << st.st_mode;
      return false;
    }
  }
  return true;
}

bool Mount::EnsureNewUserDirExists(const FilePath& fp, uid_t uid,
                                   gid_t gid) const {
  std::vector<std::string> path_parts;
  if (!EnsureDirHasOwner(fp.DirName(), uid, gid))
    return false;
  return platform_->CreateDirectory(fp.value());
}

bool Mount::EnsureDirHasOwner(const FilePath& fp, uid_t final_uid,
                              gid_t final_gid) const {
  std::vector<std::string> path_parts;
  fp.GetComponents(&path_parts);
  // The path given should be absolute to that its first part is /. This is not
  // actually checked so that relative paths can be used during testing.
  for (size_t i = 2; i <= path_parts.size(); i++) {
    bool last = (i == path_parts.size());
    uid_t uid = last ? final_uid : kMountOwnerUid;
    gid_t gid = last ? final_gid : kMountOwnerGid;
    if (!EnsurePathComponent(fp, i, uid, gid))
      return false;
  }
  return true;
}

bool Mount::EnsureUserMountPoints(const Credentials& credentials) const {
  const std::string username = credentials.username();
  FilePath root_path = chromeos::cryptohome::home::GetRootPath(username);
  FilePath user_path = chromeos::cryptohome::home::GetUserPath(username);
  FilePath temp_path(GetNewUserPath(username));
  if (!EnsureDirHasOwner(root_path, kMountOwnerUid, kMountOwnerGid)) {
    LOG(ERROR) << "Couldn't ensure root path: " << root_path.value();
    return false;
  }
  if (!EnsureDirHasOwner(user_path, default_user_, default_access_group_)) {
    LOG(ERROR) << "Couldn't ensure user path: " << user_path.value();
    return false;
  }
  if (!EnsureNewUserDirExists(temp_path, default_user_, default_group_)) {
    LOG(ERROR) << "Couldn't ensure temp path: " << temp_path.value();
    return false;
  }
  return true;
}

base::Value* Mount::GetStatus() {
  std::string user;
  SerializedVaultKeyset keyset;
  base::DictionaryValue* dv = new base::DictionaryValue();
  current_user_->GetObfuscatedUsername(&user);
  base::ListValue* keysets = new base::ListValue();
  std::vector<int> key_indices;
  if (user.length() && homedirs_->GetVaultKeysets(user, &key_indices)) {
    std::vector<int>::const_iterator iter = key_indices.begin();
    for ( ; iter != key_indices.end(); ++iter) {
      base::DictionaryValue* keyset_dict = new base::DictionaryValue();
      if (LoadVaultKeysetForUser(user, *iter, &keyset)) {
        bool tpm = keyset.flags() & SerializedVaultKeyset::TPM_WRAPPED;
        bool scrypt = keyset.flags() & SerializedVaultKeyset::SCRYPT_WRAPPED;
        keyset_dict->SetBoolean("tpm", tpm);
        keyset_dict->SetBoolean("scrypt", scrypt);
        keyset_dict->SetBoolean("ok", true);
        keyset_dict->SetInteger("last_activity",
                                keyset.last_activity_timestamp());
        if (keyset.has_key_data()) {
          // TODO(wad) Add additional KeyData
          keyset_dict->SetString("label", keyset.key_data().label());
        }
      } else {
        keyset_dict->SetBoolean("ok", false);
      }
      // TODO(wad) Replace key_index use with key_label() use once
      //           legacy keydata is populated.
      if (!ephemeral_mount_ && *iter == current_user_->key_index())
        keyset_dict->SetBoolean("current", true);
      keyset_dict->SetInteger("index", *iter);
      keysets->Append(keyset_dict);
    }
  }
  dv->Set("keysets", keysets);
  dv->SetBoolean("mounted", IsMounted());
  dv->SetString("owner", GetObfuscatedOwner());
  dv->SetBoolean("enterprise", enterprise_owned_);
  return dv;
}

std::string Mount::GetNewUserPath(const std::string& username) const {
  std::string sanitized =
      chromeos::cryptohome::home::SanitizeUserName(username);
  return StringPrintf("/home/chronos/u-%s", sanitized.c_str());
}

bool Mount::MountLegacyHome(const std::string& from, MountError* mount_error) {
  // Multiple mounts can't live on the legacy mountpoint.
  if (platform_->IsDirectoryMounted(kDefaultHomeDir)) {
    LOG(INFO) << "Skipping binding to /home/chronos/user.";
  } else if (!BindForUser(current_user_, from, kDefaultHomeDir)) {
    PLOG(ERROR) << "Bind mount failed: " << from << " -> "
                << kDefaultHomeDir;
    UnmountAllForUser(current_user_);
    if (mount_error) {
      *mount_error = MOUNT_ERROR_FATAL;
    }
    return false;
  }

  return true;
}

}  // namespace cryptohome
