// 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.

#include "login_manager/session_manager_impl.h"

#include <errno.h>
#include <stdint.h>
#include <sys/socket.h>

#include <algorithm>
#include <locale>
#include <memory>
#include <string>
#include <utility>

#include <base/base64.h>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/memory/ptr_util.h>
#include <base/memory/ref_counted.h>
#include <base/message_loop/message_loop.h>
#include <base/rand_util.h>
#include <base/run_loop.h>
#include <base/strings/string_tokenizer.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <brillo/cryptohome.h>
#include <chromeos/dbus/service_constants.h>
#include <crypto/scoped_nss_types.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
#include <install_attributes/libinstallattributes.h>

#include "bindings/chrome_device_policy.pb.h"
#include "bindings/device_management_backend.pb.h"
#include "login_manager/crossystem.h"
#include "login_manager/dbus_signal_emitter.h"
#include "login_manager/dbus_util.h"
#include "login_manager/device_local_account_policy_service.h"
#include "login_manager/device_policy_service.h"
#include "login_manager/key_generator.h"
#include "login_manager/login_metrics.h"
#include "login_manager/nss_util.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_service.h"
#include "login_manager/process_manager_service_interface.h"
#include "login_manager/regen_mitigator.h"
#include "login_manager/system_utils.h"
#include "login_manager/upstart_signal_emitter.h"
#include "login_manager/user_policy_service_factory.h"
#include "login_manager/vpd_process.h"

using base::FilePath;
using brillo::cryptohome::home::GetRootPath;
using brillo::cryptohome::home::GetUserPath;
using brillo::cryptohome::home::SanitizeUserName;
using brillo::cryptohome::home::kGuestUserName;

namespace login_manager {  // NOLINT

const char SessionManagerImpl::kDemoUser[] = "demouser@";

const char SessionManagerImpl::kStarted[] = "started";
const char SessionManagerImpl::kStopping[] = "stopping";
const char SessionManagerImpl::kStopped[] = "stopped";

const char SessionManagerImpl::kLoggedInFlag[] =
    "/run/session_manager/logged_in";
const char SessionManagerImpl::kResetFile[] =
    "/mnt/stateful_partition/factory_install_reset";

const char SessionManagerImpl::kStartUserSessionSignal[] = "start-user-session";

const char SessionManagerImpl::kArcContainerName[] = "android";
const char SessionManagerImpl::kArcStartSignal[] = "start-arc-instance";
const char SessionManagerImpl::kArcStopSignal[] = "stop-arc-instance";
const char SessionManagerImpl::kArcNetworkStartSignal[] = "start-arc-network";
const char SessionManagerImpl::kArcNetworkStopSignal[] = "stop-arc-network";
const char SessionManagerImpl::kArcBootedSignal[] = "arc-booted";
const char SessionManagerImpl::kArcRemoveOldDataSignal[] =
    "remove-old-arc-data";

namespace {
// Constants used in email validation.
const char kEmailSeparator = '@';
const char kEmailLegalCharacters[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    ".@1234567890!#$%&'*+-/=?^_`{|}~";

// Should match chromium AccountId::kKeyGaiaIdPrefix .
const char kGaiaIdKeyPrefix[] = "g-";
// Should match chromium AccountId::kKeyAdIdPrefix .
const char kActiveDirectoryPrefix[] = "a-";
const char kAccountIdKeyLegalCharacters[] =
    "-0123456789"
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// The flag to pass to chrome to open a named socket for testing.
const char kTestingChannelFlag[] = "--testing-channel=NamedTestingInterface:";

// Device-local account state directory.
const base::FilePath::CharType kDeviceLocalAccountStateDir[] =
    FILE_PATH_LITERAL("/var/lib/device_local_accounts");

#if USE_CHEETS
// To launch ARC, certain amount of free disk space is needed.
// Path and the amount for the check.
constexpr base::FilePath::CharType kArcDiskCheckPath[] = "/home";
constexpr int64_t kArcCriticalDiskFreeBytes = 64 << 20;  // 64MB
constexpr size_t kArcContainerInstanceIdLength = 16;

// Name of android-data directory.
const base::FilePath::CharType kAndroidDataDirName[] =
    FILE_PATH_LITERAL("android-data");

// Name of android-data-old directory which RemoveArcDataInternal uses.
const base::FilePath::CharType kAndroidDataOldDirName[] =
    FILE_PATH_LITERAL("android-data-old");

// To set the CPU limits of the Android container.
const char kCpuSharesFile[] =
    "/sys/fs/cgroup/cpu/session_manager_containers/cpu.shares";
const unsigned int kCpuSharesForeground = 1024;
const unsigned int kCpuSharesBackground = 64;
#endif

// SystemUtils::EnsureJobExit() DCHECKs if the timeout is zero, so this is the
// minimum amount of time we must wait before killing the containers.
constexpr int kContainerTimeoutSec = 1;

// The interval used to periodically check if time sync was done by tlsdated.
constexpr int kSystemClockLastSyncInfoRetryMs = 1000;

bool IsIncognitoAccountId(const std::string& account_id) {
  const std::string lower_case_id(base::ToLowerASCII(account_id));
  return (lower_case_id == kGuestUserName) ||
         (lower_case_id == SessionManagerImpl::kDemoUser);
}

}  // namespace

SessionManagerImpl::Error::Error() : set_(false) {}

SessionManagerImpl::Error::Error(const std::string& name,
                                 const std::string& message)
    : name_(name), message_(message), set_(true) {}

SessionManagerImpl::Error::~Error() {}

void SessionManagerImpl::Error::Set(const std::string& name,
                                    const std::string& message) {
  name_ = name;
  message_ = message;
  set_ = true;
}

struct SessionManagerImpl::UserSession {
 public:
  UserSession(const std::string& username,
              const std::string& userhash,
              bool is_incognito,
              crypto::ScopedPK11Slot slot,
              std::unique_ptr<PolicyService> policy_service)
      : username(username),
        userhash(userhash),
        is_incognito(is_incognito),
        slot(std::move(slot)),
        policy_service(std::move(policy_service)) {}
  ~UserSession() {}

  const std::string username;
  const std::string userhash;
  const bool is_incognito;
  crypto::ScopedPK11Slot slot;
  std::unique_ptr<PolicyService> policy_service;
};

SessionManagerImpl::SessionManagerImpl(
    std::unique_ptr<InitDaemonController> init_controller,
    DBusSignalEmitterInterface* dbus_emitter,
    base::Closure lock_screen_closure,
    base::Closure restart_device_closure,
    base::Closure start_arc_instance_closure,
    base::Closure stop_arc_instance_closure,
    KeyGenerator* key_gen,
    ServerBackedStateKeyGenerator* state_key_generator,
    ProcessManagerServiceInterface* manager,
    LoginMetrics* metrics,
    NssUtil* nss,
    SystemUtils* utils,
    Crossystem* crossystem,
    VpdProcess* vpd_process,
    PolicyKey* owner_key,
    ContainerManagerInterface* android_container,
    InstallAttributesReader* install_attributes_reader,
    dbus::ObjectProxy* system_clock_proxy)
    : session_started_(false),
      session_stopping_(false),
      screen_locked_(false),
      supervised_user_creation_ongoing_(false),
      system_clock_synchronized_(false),
      init_controller_(std::move(init_controller)),
      lock_screen_closure_(lock_screen_closure),
      restart_device_closure_(restart_device_closure),
      start_arc_instance_closure_(start_arc_instance_closure),
      stop_arc_instance_closure_(stop_arc_instance_closure),
      dbus_emitter_(dbus_emitter),
      key_gen_(key_gen),
      state_key_generator_(state_key_generator),
      manager_(manager),
      login_metrics_(metrics),
      nss_(nss),
      system_(utils),
      crossystem_(crossystem),
      vpd_process_(vpd_process),
      owner_key_(owner_key),
      android_container_(android_container),
      install_attributes_reader_(install_attributes_reader),
      system_clock_proxy_(system_clock_proxy),
      mitigator_(key_gen),
      weak_ptr_factory_(this) {}

SessionManagerImpl::~SessionManagerImpl() {
  device_policy_->set_delegate(NULL);  // Could use WeakPtr instead?
}

// static
bool SessionManagerImpl::ValidateAccountIdKey(const std::string& account_id) {
  if (account_id.find_first_not_of(kAccountIdKeyLegalCharacters) !=
      std::string::npos)
    return false;

  return base::StartsWith(account_id, kGaiaIdKeyPrefix,
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(account_id, kActiveDirectoryPrefix,
                          base::CompareCase::SENSITIVE);
}

// static
bool SessionManagerImpl::ValidateEmail(const std::string& email_address) {
  if (email_address.find_first_not_of(kEmailLegalCharacters) !=
      std::string::npos) {
    return false;
  }

  size_t at = email_address.find(kEmailSeparator);
  // it has NO @.
  if (at == std::string::npos)
    return false;

  // it has more than one @.
  if (email_address.find(kEmailSeparator, at + 1) != std::string::npos)
    return false;

  return true;
}

#if USE_CHEETS
// static
base::FilePath SessionManagerImpl::GetAndroidDataDirForUser(
    const std::string& normalized_account_id) {
  return GetRootPath(normalized_account_id).Append(kAndroidDataDirName);
}

// static
base::FilePath SessionManagerImpl::GetAndroidDataOldDirForUser(
    const std::string& normalized_account_id) {
  return GetRootPath(normalized_account_id).Append(kAndroidDataOldDirName);
}
#endif  // USE_CHEETS

void SessionManagerImpl::SetPolicyServicesForTest(
    std::unique_ptr<DevicePolicyService> device_policy,
    std::unique_ptr<UserPolicyServiceFactory> user_policy_factory,
    std::unique_ptr<DeviceLocalAccountPolicyService>
        device_local_account_policy) {
  device_policy_ = std::move(device_policy);
  user_policy_factory_ = std::move(user_policy_factory);
  device_local_account_policy_ = std::move(device_local_account_policy);
}

void SessionManagerImpl::AnnounceSessionStoppingIfNeeded() {
  if (session_started_) {
    session_stopping_ = true;
    DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStopping;
    dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStopping);
  }
}

void SessionManagerImpl::AnnounceSessionStopped() {
  session_stopping_ = session_started_ = false;
  DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStopped;
  dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStopped);
}

bool SessionManagerImpl::ShouldEndSession() {
  return screen_locked_ || supervised_user_creation_ongoing_;
}

bool SessionManagerImpl::Initialize() {
  key_gen_->set_delegate(this);

  system_clock_proxy_->WaitForServiceToBeAvailable(
      base::Bind(&SessionManagerImpl::OnSystemClockServiceAvailable,
                 weak_ptr_factory_.GetWeakPtr()));

  if (!device_policy_) {
    device_policy_.reset(
        DevicePolicyService::Create(login_metrics_, owner_key_, &mitigator_,
                                    nss_, crossystem_, vpd_process_));
    device_policy_->set_delegate(this);

    user_policy_factory_.reset(
        new UserPolicyServiceFactory(getuid(), nss_, system_));
    device_local_account_policy_.reset(new DeviceLocalAccountPolicyService(
        base::FilePath(kDeviceLocalAccountStateDir), owner_key_));

    if (!device_policy_->Initialize()) {
      return false;
    }
    device_local_account_policy_->UpdateDeviceSettings(
        device_policy_->GetSettings());
    if (device_policy_->MayUpdateSystemSettings()) {
      device_policy_->UpdateSystemSettings(PolicyService::Completion());
    }
  }
  return true;
}

void SessionManagerImpl::Finalize() {
  device_policy_->PersistPolicy(PolicyService::Completion());
  for (UserSessionMap::const_iterator it = user_sessions_.begin();
       it != user_sessions_.end(); ++it) {
    if (it->second)
      it->second->policy_service->PersistPolicy(PolicyService::Completion());
  }
  // We want to stop any running containers.  Containers are per-session and
  // cannot persist across sessions.
  android_container_->RequestJobExit();
  android_container_->EnsureJobExit(
      base::TimeDelta::FromSeconds(kContainerTimeoutSec));
}

void SessionManagerImpl::EmitLoginPromptVisible() {
  login_metrics_->RecordStats("login-prompt-visible");
  dbus_emitter_->EmitSignal(kLoginPromptVisibleSignal);
  init_controller_->TriggerImpulse("login-prompt-visible", {},
                                   InitDaemonController::TriggerMode::ASYNC);
}

bool SessionManagerImpl::EnableChromeTesting(
    brillo::ErrorPtr* error,
    bool in_force_relaunch,
    const std::vector<std::string>& in_extra_arguments,
    std::string* out_filepath) {
  // Check to see if we already have Chrome testing enabled.
  bool already_enabled = !chrome_testing_path_.empty();

  if (!already_enabled) {
    base::FilePath temp_file_path;  // So we don't clobber chrome_testing_path_;
    if (!system_->GetUniqueFilenameInWriteOnlyTempDir(&temp_file_path)) {
      *error = CreateError(
          dbus_error::kTestingChannelError,
          "Could not create testing channel filename.");
      return false;
    }
    chrome_testing_path_ = temp_file_path;
  }

  if (!already_enabled || in_force_relaunch) {
    // Delete testing channel file if it already exists.
    system_->RemoveFile(chrome_testing_path_);

    // Add testing channel argument to extra arguments.
    std::string testing_argument = kTestingChannelFlag;
    testing_argument.append(chrome_testing_path_.value());
    std::vector<std::string> extra_args = in_extra_arguments;
    extra_args.push_back(testing_argument);
    manager_->RestartBrowserWithArgs(extra_args, true);
  }
  *out_filepath = chrome_testing_path_.value();
  return true;
}

bool SessionManagerImpl::StartSession(brillo::ErrorPtr* error,
                                      const std::string& in_account_id,
                                      const std::string& in_unique_identifier) {
  std::string actual_account_id;
  if (!NormalizeAccountId(in_account_id, &actual_account_id, error)) {
    DCHECK(*error);
    return false;
  }

  // Check if this user already started a session.
  if (user_sessions_.count(actual_account_id) > 0) {
    constexpr char kMessage[] = "Provided user id already started a session.";
    LOG(ERROR) << kMessage;
    *error = CreateError(dbus_error::kSessionExists, kMessage);
    return false;
  }

  // Create a UserSession object for this user.
  const bool is_incognito = IsIncognitoAccountId(actual_account_id);
  auto user_session =
      CreateUserSession(actual_account_id, is_incognito, error);
  if (!user_session) {
    DCHECK(*error);
    return false;
  }

  // Check whether the current user is the owner, and if so make sure she is
  // whitelisted and has an owner key.
  bool user_is_owner = false;
  if (!device_policy_->CheckAndHandleOwnerLogin(
          user_session->username, user_session->slot.get(), &user_is_owner,
          error)) {
    DCHECK(*error);
    return false;
  }

  // If all previous sessions were incognito (or no previous sessions exist).
  bool is_first_real_user = AllSessionsAreIncognito() && !is_incognito;

  // Send each user login event to UMA (right before we start session
  // since the metrics library does not log events in guest mode).
  const DevModeState dev_mode_state = system_->GetDevModeState();
  if (dev_mode_state != DevModeState::DEV_MODE_UNKNOWN) {
    login_metrics_->SendLoginUserType(
        dev_mode_state != DevModeState::DEV_MODE_OFF, is_incognito,
        user_is_owner);
  }

  init_controller_->TriggerImpulse(kStartUserSessionSignal,
                                   {"CHROMEOS_USER=" + actual_account_id},
                                   InitDaemonController::TriggerMode::ASYNC);
  LOG(INFO) << "Starting user session";
  manager_->SetBrowserSessionForUser(actual_account_id, user_session->userhash);
  session_started_ = true;
  user_sessions_[actual_account_id] = std::move(user_session);
  DLOG(INFO) << "emitting D-Bus signal SessionStateChanged:" << kStarted;
  dbus_emitter_->EmitSignalWithString(kSessionStateChangedSignal, kStarted);

  // Active Directory managed devices are not expected to have a policy key.
  // Don't create one for them.
  const bool is_active_directory =
      install_attributes_reader_->GetAttribute(
          InstallAttributesReader::kAttrMode) ==
      InstallAttributesReader::kDeviceModeEnterpriseAD;
  if (device_policy_->KeyMissing() && !is_active_directory &&
      !device_policy_->Mitigating() && is_first_real_user) {
    // This is the first sign-in on this unmanaged device.  Take ownership.
    key_gen_->Start(actual_account_id);
  }

  // Record that a login has successfully completed on this boot.
  system_->AtomicFileWrite(base::FilePath(kLoggedInFlag), "1");
  return true;
}

void SessionManagerImpl::StopSession(const std::string& in_unique_identifier) {
  LOG(INFO) << "Stopping all sessions";
  // Most calls to StopSession() will log the reason for the call.
  // If you don't see a log message saying the reason for the call, it is
  // likely a DBUS message. See session_manager_dbus_adaptor.cc for that call.
  manager_->ScheduleShutdown();
  // TODO(cmasone): re-enable these when we try to enable logout without exiting
  //                the session manager
  // browser_.job->StopSession();
  // user_policy_.reset();
  // session_started_ = false;
}

void SessionManagerImpl::StorePolicy(
    const uint8_t* policy_blob,
    size_t policy_blob_len,
    SignatureCheck signature_check,
    const PolicyService::Completion& completion) {
  // Skipping of signature checks is gated on enterprise_ad device mode being
  // locked into install attributes.
  if (signature_check == SignatureCheck::kDisabled) {
    const std::string& mode = install_attributes_reader_->GetAttribute(
        InstallAttributesReader::kAttrMode);
    if (mode != InstallAttributesReader::kDeviceModeEnterpriseAD) {
      constexpr char kMessage[] =
          "Device mode doesn't permit unsigned policy!";
      LOG(ERROR) << kMessage;
      completion.Run(CreateError(
          dbus_error::kPolicySignatureRequired, kMessage));
      return;
    }
  }

  int flags = PolicyService::KEY_ROTATE;
  if (!session_started_)
    flags |= PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_CLOBBER;
  device_policy_->Store(policy_blob, policy_blob_len, flags, signature_check,
                        completion);
}

void SessionManagerImpl::RetrievePolicy(std::vector<uint8_t>* policy_data,
                                        Error* error) {
  if (!device_policy_->Retrieve(policy_data)) {
    static const char msg[] = "Failed to retrieve policy data.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kSigEncodeFail, msg);
    return;
  }
}

void SessionManagerImpl::StorePolicyForUser(
    const std::string& account_id,
    const uint8_t* policy_blob,
    size_t policy_blob_len,
    SignatureCheck signature_check,
    const PolicyService::Completion& completion) {
  // Skipping of signature checks is gated on enterprise_ad device mode being
  // locked into install attributes.
  if (signature_check == SignatureCheck::kDisabled) {
    const std::string& mode = install_attributes_reader_->GetAttribute(
        InstallAttributesReader::kAttrMode);
    if (mode != InstallAttributesReader::kDeviceModeEnterpriseAD) {
      constexpr char kMessage[] =
          "Device mode doesn't permit unsigned policy!";
      LOG(ERROR) << kMessage;
      completion.Run(CreateError(
          dbus_error::kPolicySignatureRequired, kMessage));
      return;
    }
  }

  PolicyService* policy_service = GetPolicyService(account_id);
  if (!policy_service) {
    constexpr char kMessage[] =
        "Cannot store user policy before session is started.";
    LOG(ERROR) << kMessage;
    completion.Run(CreateError(dbus_error::kSessionDoesNotExist, kMessage));
    return;
  }

  policy_service->Store(
      policy_blob, policy_blob_len,
      PolicyService::KEY_INSTALL_NEW | PolicyService::KEY_ROTATE,
      signature_check, completion);
}

void SessionManagerImpl::RetrievePolicyForUser(
    const std::string& account_id,
    std::vector<uint8_t>* policy_data,
    Error* error) {
  PolicyService* policy_service = GetPolicyService(account_id);
  if (!policy_service) {
    static const char msg[] =
        "Cannot retrieve user policy before session is started.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kSessionDoesNotExist, msg);
    return;
  }
  if (!policy_service->Retrieve(policy_data)) {
    static const char msg[] = "Failed to retrieve policy data.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kSigEncodeFail, msg);
  }
}

void SessionManagerImpl::StoreDeviceLocalAccountPolicy(
    const std::string& account_id,
    const uint8_t* policy_blob,
    size_t policy_blob_len,
    const PolicyService::Completion& completion) {
  device_local_account_policy_->Store(account_id, policy_blob, policy_blob_len,
                                      completion);
}

void SessionManagerImpl::RetrieveDeviceLocalAccountPolicy(
    const std::string& account_id,
    std::vector<uint8_t>* policy_data,
    Error* error) {
  if (!device_local_account_policy_->Retrieve(account_id, policy_data)) {
    static const char msg[] = "Failed to retrieve policy data.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kSigEncodeFail, msg);
    return;
  }
}

const char* SessionManagerImpl::RetrieveSessionState() {
  if (!session_started_)
    return kStopped;
  else
    return (session_stopping_ ? kStopping : kStarted);
}

void SessionManagerImpl::RetrieveActiveSessions(
    std::map<std::string, std::string>* active_sessions) {
  for (UserSessionMap::const_iterator it = user_sessions_.begin();
       it != user_sessions_.end(); ++it) {
    if (it->second) {
      (*active_sessions)[it->second->username] = it->second->userhash;
    }
  }
}

void SessionManagerImpl::HandleSupervisedUserCreationStarting() {
  supervised_user_creation_ongoing_ = true;
}

void SessionManagerImpl::HandleSupervisedUserCreationFinished() {
  supervised_user_creation_ongoing_ = false;
}

void SessionManagerImpl::LockScreen(Error* error) {
  if (!session_started_) {
    static const char msg[] = "Attempt to lock screen outside of user session.";
    LOG(WARNING) << msg;
    error->Set(dbus_error::kSessionDoesNotExist, msg);
    return;
  }
  // If all sessions are incognito, then locking is not allowed.
  if (AllSessionsAreIncognito()) {
    static const char msg[] = "Attempt to lock screen during Guest session.";
    LOG(WARNING) << msg;
    error->Set(dbus_error::kSessionExists, msg);
    return;
  }
  if (!screen_locked_) {
    screen_locked_ = true;
    lock_screen_closure_.Run();
  }
  LOG(INFO) << "LockScreen() method called.";
}

void SessionManagerImpl::HandleLockScreenShown() {
  LOG(INFO) << "HandleLockScreenShown() method called.";
  dbus_emitter_->EmitSignal(kScreenIsLockedSignal);
}

void SessionManagerImpl::HandleLockScreenDismissed() {
  screen_locked_ = false;
  LOG(INFO) << "HandleLockScreenDismissed() method called.";
  dbus_emitter_->EmitSignal(kScreenIsUnlockedSignal);
}

bool SessionManagerImpl::RestartJob(brillo::ErrorPtr* error,
                                    const dbus::FileDescriptor& in_cred_fd,
                                    const std::vector<std::string>& in_argv) {
  struct ucred ucred = {0};
  socklen_t len = sizeof(struct ucred);
  if (!in_cred_fd.is_valid() ||
      getsockopt(
          in_cred_fd.value(), SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
    PLOG(ERROR) << "Can't get peer creds";
    *error = CreateError("GetPeerCredsFailed", strerror(errno));
    return false;
  }

  if (!manager_->IsBrowser(ucred.pid)) {
    constexpr char kMessage[] = "Provided pid is unknown.";
    LOG(ERROR) << kMessage;
    *error = CreateError(dbus_error::kUnknownPid, kMessage);
    return false;
  }

  // To set "logged-in" state for BWSI mode.
  if (!StartSession(error, kGuestUserName, "")) {
    DCHECK(*error);
    return false;
  }

  manager_->RestartBrowserWithArgs(in_argv, false);
  return true;
}

bool SessionManagerImpl::StartDeviceWipe(brillo::ErrorPtr* error) {
  if (system_->Exists(base::FilePath(kLoggedInFlag))) {
    constexpr char kMessage[] = "A user has already logged in this boot.";
    LOG(ERROR) << kMessage;
    *error = CreateError(dbus_error::kSessionExists, kMessage);
    return false;
  }
  InitiateDeviceWipe("session_manager_dbus_request");
  return true;
}

void SessionManagerImpl::SetFlagsForUser(
    const std::string& account_id,
    const std::vector<std::string>& session_user_flags) {
  manager_->SetFlagsForUser(account_id, session_user_flags);
}

void SessionManagerImpl::RequestServerBackedStateKeys(
    const ServerBackedStateKeyGenerator::StateKeyCallback& callback) {
  if (system_clock_synchronized_) {
    state_key_generator_->RequestStateKeys(callback);
  } else {
    pending_state_key_callbacks_.push_back(callback);
  }
}

void SessionManagerImpl::OnSystemClockServiceAvailable(bool service_available) {
  if (!service_available) {
    LOG(ERROR) << "Failed to listen for tlsdated service start";
    return;
  }

  GetSystemClockLastSyncInfo();
}

void SessionManagerImpl::GetSystemClockLastSyncInfo() {
  dbus::MethodCall method_call(system_clock::kSystemClockInterface,
                               system_clock::kSystemLastSyncInfo);
  dbus::MessageWriter writer(&method_call);

  system_clock_proxy_->CallMethod(
      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
      base::Bind(&SessionManagerImpl::OnGotSystemClockLastSyncInfo,
                 weak_ptr_factory_.GetWeakPtr()));
}

void SessionManagerImpl::OnGotSystemClockLastSyncInfo(
    dbus::Response* response) {
  if (!response) {
    LOG(ERROR) << system_clock::kSystemClockInterface << "."
               << system_clock::kSystemLastSyncInfo << " request failed.";
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, base::Bind(&SessionManagerImpl::GetSystemClockLastSyncInfo,
                              weak_ptr_factory_.GetWeakPtr()),
        base::TimeDelta::FromMilliseconds(kSystemClockLastSyncInfoRetryMs));
    return;
  }

  dbus::MessageReader reader(response);
  bool network_synchronized = false;
  if (!reader.PopBool(&network_synchronized)) {
    LOG(ERROR) << system_clock::kSystemClockInterface << "."
               << system_clock::kSystemLastSyncInfo
               << " response lacks network-synchronized argument";
    return;
  }

  if (network_synchronized) {
    system_clock_synchronized_ = true;
    for (auto it = pending_state_key_callbacks_.begin();
         it != pending_state_key_callbacks_.end(); ++it) {
      state_key_generator_->RequestStateKeys(*it);
    }
    pending_state_key_callbacks_.clear();
  } else {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, base::Bind(&SessionManagerImpl::GetSystemClockLastSyncInfo,
                              weak_ptr_factory_.GetWeakPtr()),
        base::TimeDelta::FromMilliseconds(kSystemClockLastSyncInfoRetryMs));
  }
}

void SessionManagerImpl::InitMachineInfo(const std::string& data,
                                         Error* error) {
  std::map<std::string, std::string> params;
  if (!ServerBackedStateKeyGenerator::ParseMachineInfo(data, &params))
    error->Set(dbus_error::kInitMachineInfoFail, "Parse failure.");

  if (!state_key_generator_->InitMachineInfo(params))
    error->Set(dbus_error::kInitMachineInfoFail, "Missing parameters.");
}

void SessionManagerImpl::StartArcInstance(
    const std::string& account_id,
    bool skip_boot_completed_broadcast,
    bool scan_vendor_priv_app,
    std::string* container_instance_id_out,
    Error* error) {
#if USE_CHEETS
  arc_start_time_ = base::TimeTicks::Now();

  // To boot ARC instance, certain amount of disk space is needed under the
  // home. We first check it.
  if (system_->AmountOfFreeDiskSpace(base::FilePath(kArcDiskCheckPath)) <
      kArcCriticalDiskFreeBytes) {
    static const char msg[] = "Low free disk under /home";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kLowFreeDisk, msg);
    return;
  }

  brillo::ErrorPtr error_ptr;
  std::string actual_account_id;
  if (!NormalizeAccountId(account_id, &actual_account_id, &error_ptr)) {
    DCHECK(error_ptr.get());
    error->Set(error_ptr->GetCode(), error_ptr->GetMessage());
    return;
  }
  if (user_sessions_.count(actual_account_id) == 0) {
    static const char msg[] = "Provided user ID does not have a session.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kSessionDoesNotExist, msg);
    return;
  }

  const base::FilePath android_data_dir =
      GetAndroidDataDirForUser(actual_account_id);
  const base::FilePath android_data_old_dir =
      GetAndroidDataOldDirForUser(actual_account_id);

  // When GetDevModeState() returns UNKNOWN, assign true to |is_dev_mode|.
  const bool is_dev_mode =
      system_->GetDevModeState() != DevModeState::DEV_MODE_OFF;
  // When GetVmState() returns UNKNOWN, assign false to |is_inside_vm|.
  const bool is_inside_vm = system_->GetVmState() == VmState::INSIDE_VM;

  const std::vector<std::string> keyvals = {
      base::StringPrintf("ANDROID_DATA_DIR=%s",
                         android_data_dir.value().c_str()),
      base::StringPrintf("ANDROID_DATA_OLD_DIR=%s",
                         android_data_old_dir.value().c_str()),
      base::StringPrintf("CHROMEOS_USER=%s", actual_account_id.c_str()),
      base::StringPrintf("CHROMEOS_DEV_MODE=%d", is_dev_mode),
      base::StringPrintf("CHROMEOS_INSIDE_VM=%d", is_inside_vm),
      base::StringPrintf("DISABLE_BOOT_COMPLETED_BROADCAST=%d",
                         skip_boot_completed_broadcast),
      base::StringPrintf("ENABLE_VENDOR_PRIVILEGED=%d",
                         scan_vendor_priv_app),
  };

  if (!init_controller_->TriggerImpulse(
          kArcStartSignal, keyvals, InitDaemonController::TriggerMode::SYNC)) {
    static const char msg[] = "Emitting start-arc-instance signal failed.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kEmitFailed, msg);
    return;
  }

  bool started_container = false;
  const char* dbus_error = nullptr;
  std::string error_message;
  // Container instance id needs to be valid ASCII/UTF-8, so encode as base64.
  std::string container_instance_id =
      base::RandBytesAsString(kArcContainerInstanceIdLength);
  base::Base64Encode(container_instance_id, &container_instance_id);
  if (!StartArcInstanceInternal(container_instance_id, &started_container,
                                &dbus_error, &error_message)) {
    LOG(ERROR) << error_message;
    error->Set(dbus_error, error_message);
    init_controller_->TriggerImpulse(kArcStopSignal, {},
                                     InitDaemonController::TriggerMode::SYNC);
    if (started_container) {
      android_container_->RequestJobExit();
      android_container_->EnsureJobExit(
          base::TimeDelta::FromSeconds(kContainerTimeoutSec));
    }
    return;
  }
  *container_instance_id_out = std::move(container_instance_id);
  start_arc_instance_closure_.Run();
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif  // !USE_CHEETS
}

void SessionManagerImpl::StopArcInstance(Error* error) {
#if USE_CHEETS
  pid_t pid;
  if (!android_container_->GetContainerPID(&pid)) {
    static const char msg[] = "Error getting Android container pid.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kContainerShutdownFail, msg);
    return;
  }

  android_container_->RequestJobExit();
  android_container_->EnsureJobExit(
      base::TimeDelta::FromSeconds(kContainerTimeoutSec));
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif  // USE_CHEETS
}

void SessionManagerImpl::SetArcCpuRestriction(
    ContainerCpuRestrictionState state, Error* error) {
#if USE_CHEETS
  std::string shares_out;
  switch (state) {
    case CONTAINER_CPU_RESTRICTION_FOREGROUND:
      shares_out = std::to_string(kCpuSharesForeground);
      break;
    case CONTAINER_CPU_RESTRICTION_BACKGROUND:
      shares_out = std::to_string(kCpuSharesBackground);
      break;
    default:
      constexpr char msg[] = "Invalid CPU restriction state specified.";
      LOG(ERROR) << msg;
      error->Set(dbus_error::kArcCpuCgroupFail, msg);
      return;
  }
  if (base::WriteFile(base::FilePath(kCpuSharesFile), shares_out.c_str(),
                      shares_out.length()) != shares_out.length()) {
    constexpr char msg[] = "Error updating Android container's cgroups.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kArcCpuCgroupFail, msg);
  }
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif
}

void SessionManagerImpl::EmitArcBooted(const std::string& account_id,
                                       Error* error) {
#if USE_CHEETS
  std::vector<std::string> keyvals;
  if (!account_id.empty()) {
    brillo::ErrorPtr error_ptr;
    std::string actual_account_id;
    if (!NormalizeAccountId(account_id, &actual_account_id, &error_ptr)) {
      DCHECK(error_ptr.get());
      error->Set(error_ptr->GetCode(), error_ptr->GetMessage());
      return;
    }
    const base::FilePath android_data_old_dir =
        GetAndroidDataOldDirForUser(actual_account_id);
    keyvals.emplace_back("ANDROID_DATA_OLD_DIR=" +
                         android_data_old_dir.value());
  }

  if (!init_controller_->TriggerImpulse(
          kArcBootedSignal, keyvals, InitDaemonController::TriggerMode::SYNC)) {
    static const char msg[] = "Emitting arc-booted upstart signal failed.";
    LOG(ERROR) << msg;
    error->Set(dbus_error::kEmitFailed, msg);
  }
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif
}

base::TimeTicks SessionManagerImpl::GetArcStartTime(Error* error) {
#if USE_CHEETS
  if (arc_start_time_.is_null())
    error->Set(dbus_error::kNotStarted, "ARC is not started yet.");
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif  // !USE_CHEETS
  return arc_start_time_;
}

void SessionManagerImpl::StartContainer(const std::string& name, Error* error) {
  // TODO(dgreid): Add support for other containers.
  const char msg[] = "Container not found.";
  LOG(ERROR) << msg;
  error->Set(dbus_error::kContainerStartupFail, msg);
}

void SessionManagerImpl::StopContainer(const std::string& name, Error* error) {
  // TODO(dgreid): Add support for other containers.
  const char msg[] = "Container not found.";
  LOG(ERROR) << msg;
  error->Set(dbus_error::kContainerShutdownFail, msg);
}

void SessionManagerImpl::RemoveArcData(const std::string& account_id,
                                       Error* error) {
#if USE_CHEETS
  pid_t pid = 0;
  if (android_container_->GetContainerPID(&pid)) {
    error->Set(dbus_error::kArcInstanceRunning, "ARC is currently running.");
    return;
  }

  brillo::ErrorPtr error_ptr;
  std::string actual_account_id;
  if (!NormalizeAccountId(account_id, &actual_account_id, &error_ptr)) {
    DCHECK(error_ptr.get());
    error->Set(error_ptr->GetCode(), error_ptr->GetMessage());
    return;
  }
  const base::FilePath android_data_dir =
      GetAndroidDataDirForUser(actual_account_id);
  const base::FilePath android_data_old_dir =
      GetAndroidDataOldDirForUser(actual_account_id);

  if (RemoveArcDataInternal(android_data_dir, android_data_old_dir, error))
    return;  // all done.

  PLOG(WARNING) << "Failed to rename " << android_data_dir.value()
                << "; directly deleting it instead";
  // As a last resort, directly delete the directory although it's not always
  // safe to do. If session_manager is killed or the device is shut down while
  // doing the removal, the directory will have an unusual set of files which
  // may confuse ARC and prevent it from booting.
  system_->RemoveDirTree(android_data_dir);
  LOG(INFO) << "Finished removing " << android_data_dir.value();
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif  // USE_CHEETS
}

bool SessionManagerImpl::RemoveArcDataInternal(
    const base::FilePath& android_data_dir,
    const base::FilePath& android_data_old_dir,
    Error* error) {
#if USE_CHEETS
  // It should never happen, but in case |android_data_old_dir| is a file,
  // remove it. RemoveFile() immediately returns false (i.e. no-op) when
  // |android_data_old_dir| is a directory.
  system_->RemoveFile(android_data_old_dir);

  // Create |android_data_old_dir| if it doesn't exist.
  if (!system_->DirectoryExists(android_data_old_dir)) {
    if (!system_->CreateDir(android_data_old_dir)) {
      PLOG(ERROR) << "Failed to create " << android_data_old_dir.value();
      return false;
    }
  }

  if (!system_->DirectoryExists(android_data_dir) &&
      system_->IsDirectoryEmpty(android_data_old_dir)) {
    return true;  // nothing to do.
  }

  // Create a random temporary directory in |android_data_old_dir|.
  // Note: Renaming a directory to an existing empty directory works.
  base::FilePath target_dir_name;
  if (!system_->CreateTemporaryDirIn(android_data_old_dir, &target_dir_name)) {
    LOG(WARNING) << "Failed to create a temporary directory in "
                 << android_data_old_dir.value();
    return false;
  }
  LOG(INFO) << "Renaming " << android_data_dir.value() << " to "
            << target_dir_name.value();

  // Does the actual renaming here with rename(2). Note that if the process
  // (or the device itself) is killed / turned off right before the rename(2)
  // operation, both |android_data_dir| and |android_data_old_dir| will remain
  // while ARC is disabled in the browser side. In that case, the browser will
  // call RemoveArcData() later as needed, and both directories will disappear.
  if (system_->DirectoryExists(android_data_dir)) {
    if (!system_->RenameDir(android_data_dir, target_dir_name)) {
      LOG(WARNING) << "Failed to rename " << android_data_dir.value() << " to "
                   << target_dir_name.value();
      return false;
    }
  }

  // Ask init to remove all files and directories in |android_data_old_dir|.
  // Note that the init job never deletes |android_data_old_dir| itself so the
  // rename() operation above never fails.
  LOG(INFO) << "Removing contents in " << android_data_old_dir.value();
  if (!init_controller_->TriggerImpulse(
          kArcRemoveOldDataSignal,
          {"ANDROID_DATA_OLD_DIR=" + android_data_old_dir.value()},
          InitDaemonController::TriggerMode::SYNC)) {
    LOG(ERROR) << "Failed to emit " << kArcRemoveOldDataSignal
               << " upstart signal";
  }
#else
  error->Set(dbus_error::kNotAvailable, "ARC not supported.");
#endif  // USE_CHEETS
  return true;
}

void SessionManagerImpl::OnPolicyPersisted(bool success) {
  device_local_account_policy_->UpdateDeviceSettings(
      device_policy_->GetSettings());
  dbus_emitter_->EmitSignalWithSuccessFailure(kPropertyChangeCompleteSignal,
                                              success);
}

void SessionManagerImpl::OnKeyPersisted(bool success) {
  dbus_emitter_->EmitSignalWithSuccessFailure(kOwnerKeySetSignal, success);
}

void SessionManagerImpl::OnKeyGenerated(const std::string& username,
                                        const base::FilePath& temp_key_file) {
  ImportValidateAndStoreGeneratedKey(username, temp_key_file);
}

void SessionManagerImpl::ImportValidateAndStoreGeneratedKey(
    const std::string& username,
    const base::FilePath& temp_key_file) {
  DLOG(INFO) << "Processing generated key at " << temp_key_file.value();
  std::string key;
  base::ReadFileToString(temp_key_file, &key);
  PLOG_IF(WARNING, !base::DeleteFile(temp_key_file, false))
      << "Can't delete " << temp_key_file.value();
  device_policy_->ValidateAndStoreOwnerKey(
      username, key, user_sessions_[username]->slot.get());
}

void SessionManagerImpl::InitiateDeviceWipe(const std::string& reason) {
  // The log string must not be confused with other clobbers-state parameters.
  // Sanitize by replacing all non-alphanumeric characters with underscores and
  // clamping size to 50 characters.
  std::string sanitized_reason(reason.substr(0, 50));
  std::locale locale("C");
  std::replace_if(sanitized_reason.begin(), sanitized_reason.end(),
                  [&locale](const std::string::value_type character) {
                    return !std::isalnum(character, locale);
                  },
                  '_');
  const base::FilePath reset_path(kResetFile);
  system_->AtomicFileWrite(reset_path,
                           "fast safe keepimg reason=" + sanitized_reason);
  restart_device_closure_.Run();
}

// static
bool SessionManagerImpl::NormalizeAccountId(const std::string& account_id,
                                            std::string* actual_account_id_out,
                                            brillo::ErrorPtr* error_out) {
  // Validate the |account_id|.
  if (IsIncognitoAccountId(account_id) || ValidateAccountIdKey(account_id)) {
    *actual_account_id_out = account_id;
    return true;
  }

  // Support legacy email addresses.
  // TODO(alemate): remove this after ChromeOS will stop using email as
  // cryptohome identifier.
  const std::string& lower_email = base::ToLowerASCII(account_id);
  if (!ValidateEmail(lower_email)) {
    constexpr char kMessage[] =
        "Provided email address is not valid.  ASCII only.";
    LOG(ERROR) << kMessage;
    *error_out = CreateError(dbus_error::kInvalidAccount, kMessage);
    return false;
  }

  *actual_account_id_out = lower_email;
  return true;
}

bool SessionManagerImpl::AllSessionsAreIncognito() {
  size_t incognito_count = 0;
  for (UserSessionMap::const_iterator it = user_sessions_.begin();
       it != user_sessions_.end(); ++it) {
    if (it->second)
      incognito_count += it->second->is_incognito;
  }
  return incognito_count == user_sessions_.size();
}

std::unique_ptr<SessionManagerImpl::UserSession>
SessionManagerImpl::CreateUserSession(const std::string& username,
                                      bool is_incognito,
                                      brillo::ErrorPtr* error) {
  std::unique_ptr<PolicyService> user_policy(
      user_policy_factory_->Create(username));
  if (!user_policy) {
    LOG(ERROR) << "User policy failed to initialize.";
    *error = CreateError(dbus_error::kPolicyInitFail, "Can't create session.");
    return nullptr;
  }

  crypto::ScopedPK11Slot slot(nss_->OpenUserDB(GetUserPath(username)));
  if (!slot) {
    LOG(ERROR) << "Could not open the current user's NSS database.";
    *error = CreateError(dbus_error::kNoUserNssDb, "Can't create session.");
    return nullptr;
  }

  return base::MakeUnique<UserSession>(
      username, SanitizeUserName(username), is_incognito, std::move(slot),
      std::move(user_policy));
}

PolicyService* SessionManagerImpl::GetPolicyService(const std::string& user) {
  UserSessionMap::const_iterator it = user_sessions_.find(user);
  return it == user_sessions_.end() ? NULL : it->second->policy_service.get();
}

bool SessionManagerImpl::StartArcInstanceInternal(
    const std::string& container_instance_id,
    bool* started_container_out,
    const char** dbus_error_out,
    std::string* error_message_out) {
  *started_container_out = false;
  *dbus_error_out = nullptr;
  error_message_out->clear();
  if (!android_container_->StartContainer(
          base::Bind(&SessionManagerImpl::OnAndroidContainerStopped,
                     weak_ptr_factory_.GetWeakPtr(), container_instance_id))) {
    *dbus_error_out = dbus_error::kContainerStartupFail;
    *error_message_out = "Starting Android container failed.";
    return false;
  }
  *started_container_out = true;

  login_metrics_->StartTrackingArcUseTime();

  base::FilePath root_path;
  pid_t pid = 0;
  if (!android_container_->GetRootFsPath(&root_path) ||
      !android_container_->GetContainerPID(&pid)) {
    *dbus_error_out = dbus_error::kContainerStartupFail;
    *error_message_out = "Getting Android container info failed.";
    return false;
  }

  // Also tell init to configure the network.
  if (!init_controller_->TriggerImpulse(
          kArcNetworkStartSignal,
          {"CONTAINER_NAME=" + std::string(kArcContainerName),
           "CONTAINER_PATH=" + root_path.value(),
           "CONTAINER_PID=" + std::to_string(pid)},
          InitDaemonController::TriggerMode::SYNC)) {
    *dbus_error_out = dbus_error::kEmitFailed;
    *error_message_out = "Emitting start-arc-network signal failed.";
    return false;
  }
  LOG(INFO) << "Started Android container pid " << pid;

  return true;
}

void SessionManagerImpl::OnAndroidContainerStopped(
    const std::string& container_instance_id, pid_t pid, bool clean) {
  if (clean) {
    LOG(INFO) << "Android Container with pid " << pid << " stopped";
  } else {
    LOG(ERROR) << "Android Container with pid " << pid << " crashed";
  }

  stop_arc_instance_closure_.Run();

  login_metrics_->StopTrackingArcUseTime();
  if (!init_controller_->TriggerImpulse(
          kArcStopSignal, {}, InitDaemonController::TriggerMode::SYNC)) {
    static const char msg[] = "Emitting stop-arc-instance init signal failed.";
    LOG(ERROR) << msg;
  }

  if (!init_controller_->TriggerImpulse(
          kArcNetworkStopSignal, {}, InitDaemonController::TriggerMode::SYNC)) {
    static const char msg[] = "Emitting stop-arc-network init signal failed.";
    LOG(ERROR) << msg;
  }

  dbus_emitter_->EmitSignalWithBoolAndString(
      kArcInstanceStopped, clean, container_instance_id);
}

}  // namespace login_manager
