// Copyright 2019 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 "kerberos/account_manager.h"

#include <limits>
#include <utility>

#include <base/base64.h>
#include <base/check.h>
#include <base/containers/contains.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <libpasswordprovider/password.h>
#include <libpasswordprovider/password_provider.h>

#include "kerberos/error_strings.h"
#include "kerberos/kerberos_metrics.h"
#include "kerberos/krb5_interface.h"
#include "kerberos/krb5_jail_wrapper.h"

namespace kerberos {

namespace {

constexpr int kInvalidIndex = -1;

constexpr int kFileMode_rw =
    base::FILE_PERMISSION_READ_BY_USER | base::FILE_PERMISSION_WRITE_BY_USER;

constexpr int kFileMode_rwxrwx =
    base::FILE_PERMISSION_USER_MASK | base::FILE_PERMISSION_GROUP_MASK;

// Kerberos config files are stored as storage_dir/account_dir/this.
constexpr char kKrb5ConfFilePart[] = "krb5.conf";
// Kerberos credential caches are stored as storage_dir/account_dir/this.
constexpr char kKrb5CCFilePart[] = "krb5cc";
// Passwords are stored as storage_dir/account_dir/this.
constexpr char kPasswordFilePart[] = "password";
// Account data is stored as storage_dir + this.
constexpr char kAccountsFile[] = "accounts";

// Size limit for file (1 MB).
constexpr size_t kFileSizeLimit = 1024 * 1024;

// Returns the base64 encoded |principal_name|. This is used to create safe
// filenames while at the same time allowing easy debugging.
std::string GetSafeFilename(const std::string& principal_name) {
  std::string encoded_principal;
  base::Base64Encode(principal_name, &encoded_principal);
  return encoded_principal;
}

// Reads the file at |path| into |data|. Returns |ERROR_LOCAL_IO| if the file
// could not be read.
WARN_UNUSED_RESULT ErrorType LoadFile(const base::FilePath& path,
                                      std::string* data) {
  data->clear();
  if (!base::ReadFileToStringWithMaxSize(path, data, kFileSizeLimit)) {
    PLOG(ERROR) << "Failed to read " << path.value();
    data->clear();
    return ERROR_LOCAL_IO;
  }
  return ERROR_NONE;
}

// Writes |data| to the file at |path|. Returns |ERROR_LOCAL_IO| if the file
// could not be written.
WARN_UNUSED_RESULT ErrorType SaveFile(const base::FilePath& path,
                                      const std::string& data) {
  const int data_size = static_cast<int>(data.size());
  if (base::WriteFile(path, data.data(), data_size) != data_size) {
    LOG(ERROR) << "Failed to write '" << path.value() << "'";
    return ERROR_LOCAL_IO;
  }
  return ERROR_NONE;
}

// Sets file permissions for a given |path|. Returns ERROR_LOCAL_IO on error.
WARN_UNUSED_RESULT ErrorType SetFilePermissions(const base::FilePath& path,
                                                int mode) {
  if (!base::SetPosixFilePermissions(path, mode)) {
    LOG(ERROR) << "Failed to set permissions on '" << path.value() << "'";
    return ERROR_LOCAL_IO;
  }
  return ERROR_NONE;
}

}  // namespace

AccountManager::AccountManager(
    base::FilePath storage_dir,
    KerberosFilesChangedCallback kerberos_files_changed,
    KerberosTicketExpiringCallback kerberos_ticket_expiring,
    std::unique_ptr<Krb5Interface> krb5,
    std::unique_ptr<password_provider::PasswordProviderInterface>
        password_provider,
    KerberosMetrics* metrics)
    : storage_dir_(std::move(storage_dir)),
      accounts_path_(storage_dir_.Append(kAccountsFile)),
      kerberos_files_changed_(std::move(kerberos_files_changed)),
      kerberos_ticket_expiring_(std::move(kerberos_ticket_expiring)),
      krb5_(std::move(krb5)),
      password_provider_(std::move(password_provider)),
      metrics_(metrics) {
  DCHECK(kerberos_files_changed_);
  DCHECK(kerberos_ticket_expiring_);
}

AccountManager::~AccountManager() = default;

ErrorType AccountManager::SaveAccounts() const {
  // Copy |accounts_| into proto message.
  AccountDataList storage_accounts;
  for (const auto& account : accounts_)
    *storage_accounts.add_accounts() = account.data;

  // Store serialized proto message on disk.
  std::string accounts_blob;
  if (!storage_accounts.SerializeToString(&accounts_blob)) {
    LOG(ERROR) << "Failed to serialize accounts list to string";
    return ERROR_LOCAL_IO;
  }

  ErrorType error = SaveFile(accounts_path_, accounts_blob);
  if (error != ERROR_NONE)
    return error;

  // Remove group and other read access. This prevents kerberosd-exec from
  // reading it (it's none of its business).
  return SetFilePermissions(accounts_path_, kFileMode_rw);
}

ErrorType AccountManager::LoadAccounts() {
  accounts_.clear();

  // A missing file counts as a file with empty data.
  if (!base::PathExists(accounts_path_))
    return ERROR_NONE;

  // Load serialized proto blob.
  std::string accounts_blob;
  ErrorType error = LoadFile(accounts_path_, &accounts_blob);
  if (error != ERROR_NONE)
    return error;

  // Parse blob into proto message.
  AccountDataList storage_accounts;
  if (!storage_accounts.ParseFromString(accounts_blob)) {
    LOG(ERROR) << "Failed to parse accounts list from string";
    return ERROR_LOCAL_IO;
  }

  // Copy data into |accounts_|.
  accounts_.reserve(storage_accounts.accounts_size());
  for (int n = 0; n < storage_accounts.accounts_size(); ++n) {
    accounts_.emplace_back(std::move(*storage_accounts.mutable_accounts(n)),
                           this);
  }

  return ERROR_NONE;
}

ErrorType AccountManager::AddAccount(const std::string& principal_name,
                                     bool is_managed) {
  int index = GetAccountIndex(principal_name);
  if (index != kInvalidIndex) {
    // Policy should overwrite user-added accounts, but user-added accounts
    // should not overwrite policy accounts.
    if (!accounts_[index].data.is_managed() && is_managed) {
      DeleteAllFilesFor(principal_name);
      accounts_[index].data.set_is_managed(is_managed);
      SaveAccounts();
    }
    return ERROR_DUPLICATE_PRINCIPAL_NAME;
  }

  // Create the account directory.
  const base::FilePath account_dir = GetAccountDir(principal_name);
  base::File::Error ferror;
  if (!base::CreateDirectoryAndGetError(account_dir, &ferror)) {
    LOG(ERROR) << "Failed to create directory '" << account_dir.value()
               << "': " << base::File::ErrorToString(ferror);
    return ERROR_LOCAL_IO;
  }

  // The account directory needs to be group accessible since kinit runs as
  // kerberosd-exec user and wants to write krbcc into that directory.
  ErrorType error = SetFilePermissions(account_dir, kFileMode_rwxrwx);
  if (error != ERROR_NONE) {
    base::DeletePathRecursively(account_dir);
    return error;
  }

  // Create account record.
  AccountData data;
  data.set_principal_name(principal_name);
  data.set_is_managed(is_managed);
  accounts_.emplace_back(std::move(data), this);
  SaveAccounts();
  return ERROR_NONE;
}

ErrorType AccountManager::RemoveAccount(const std::string& principal_name) {
  int index = GetAccountIndex(principal_name);
  if (index == kInvalidIndex)
    return ERROR_UNKNOWN_PRINCIPAL_NAME;

  DeleteAllFilesFor(principal_name);
  accounts_.erase(accounts_.begin() + index);

  SaveAccounts();
  return ERROR_NONE;
}

void AccountManager::DeleteAllFilesFor(const std::string& principal_name) {
  const bool krb5cc_existed = base::PathExists(GetKrb5CCPath(principal_name));
  CHECK(base::DeletePathRecursively(GetAccountDir(principal_name)));
  if (krb5cc_existed)
    TriggerKerberosFilesChanged(principal_name);
}

ErrorType AccountManager::ClearAccounts(
    ClearMode mode, std::unordered_set<std::string> keep_list) {
  // Early out.
  if (accounts_.size() == 0)
    return ERROR_NONE;

  for (auto it = accounts_.begin(); it != accounts_.end(); /* empty */) {
    if (base::Contains(keep_list, it->data.principal_name())) {
      ++it;
      continue;
    }

    switch (DetermineWhatToRemove(mode, *it)) {
      case WhatToRemove::kNothing:
        ++it;
        continue;

      case WhatToRemove::kPassword:
        CHECK(base::DeleteFile(GetPasswordPath(it->data.principal_name())));
        ++it;
        continue;

      case WhatToRemove::kAccount:
        DeleteAllFilesFor(it->data.principal_name());
        it = accounts_.erase(it);
        continue;
    }
  }

  SaveAccounts();
  return ERROR_NONE;
}

std::vector<Account> AccountManager::ListAccounts() const {
  std::vector<Account> accounts;

  for (const auto& it : accounts_) {
    Account account;
    account.set_principal_name(it.data.principal_name());
    account.set_is_managed(it.data.is_managed());
    account.set_password_was_remembered(
        base::PathExists(GetPasswordPath(it.data.principal_name())));
    account.set_use_login_password(it.data.use_login_password());

    // TODO(https://crbug.com/952239): Set additional properties.

    // Do a best effort reporting results, don't bail on the first error. If
    // there's a broken account, the user is able to recover the situation
    // this way (reauthenticate or remove account and add back).

    // Check PathExists, so that no error is printed if the file doesn't exist.
    std::string krb5conf;
    const base::FilePath krb5conf_path =
        GetKrb5ConfPath(it.data.principal_name());
    if (base::PathExists(krb5conf_path) &&
        LoadFile(krb5conf_path, &krb5conf) == ERROR_NONE) {
      account.set_krb5conf(krb5conf);
    }

    // A missing krb5cc file just translates to an invalid ticket (lifetime 0).
    Krb5Interface::TgtStatus tgt_status;
    const base::FilePath krb5cc_path = GetKrb5CCPath(it.data.principal_name());
    if (base::PathExists(krb5cc_path) &&
        krb5_->GetTgtStatus(krb5cc_path, &tgt_status) == ERROR_NONE) {
      account.set_tgt_validity_seconds(tgt_status.validity_seconds);
      account.set_tgt_renewal_seconds(tgt_status.renewal_seconds);
    }

    accounts.push_back(std::move(account));
  }

  return accounts;
}

ErrorType AccountManager::SetConfig(const std::string& principal_name,
                                    const std::string& krb5conf) const {
  const InternalAccount* account = GetAccount(principal_name);
  if (!account)
    return ERROR_UNKNOWN_PRINCIPAL_NAME;

  // Validate configuration before setting it to make sure it doesn't contain
  // invalid options.
  ConfigErrorInfo error_info;
  ErrorType error = krb5_->ValidateConfig(krb5conf, &error_info);
  if (error != ERROR_NONE)
    return error;

  error = SaveFile(GetKrb5ConfPath(principal_name), krb5conf);

  // Triggering the signal is only necessary if the credential cache exists.
  if (error == ERROR_NONE && base::PathExists(GetKrb5CCPath(principal_name)))
    TriggerKerberosFilesChanged(principal_name);
  return error;
}

ErrorType AccountManager::ValidateConfig(const std::string& krb5conf,
                                         ConfigErrorInfo* error_info) const {
  return krb5_->ValidateConfig(krb5conf, error_info);
}

ErrorType AccountManager::AcquireTgt(const std::string& principal_name,
                                     std::string password,
                                     bool remember_password,
                                     bool use_login_password) {
  InternalAccount* account = GetMutableAccount(principal_name);
  if (!account)
    return ERROR_UNKNOWN_PRINCIPAL_NAME;

  // Remember whether to use the login password.
  if (account->data.use_login_password() != use_login_password) {
    account->data.set_use_login_password(use_login_password);
    SaveAccounts();
  }

  ErrorType error = use_login_password
                        ? UpdatePasswordFromLogin(principal_name, &password)
                        : UpdatePasswordFromSaved(principal_name,
                                                  remember_password, &password);
  if (error != ERROR_NONE)
    return error;

  // Acquire a Kerberos ticket-granting-ticket.
  error =
      krb5_->AcquireTgt(principal_name, password, GetKrb5CCPath(principal_name),
                        GetKrb5ConfPath(principal_name));

  if (error == ERROR_NONE) {
    // Schedule task to automatically renew the ticket. If the ticket is invalid
    // for whatever reason, don't notify expiration immediately. This might lead
    // to an infinite loop when a password is stored and MaybeAutoAcquireTgt
    // tries to acquire a new TGT immediately.
    account->tgt_renewal_scheduler_->ScheduleRenewal(
        false /* notify_expiration */);

    // Assume the ticket changed if AcquireTgt() was successful.
    TriggerKerberosFilesChanged(principal_name);

    std::string krb5conf;
    ErrorType load_config_error =
        LoadFile(GetKrb5ConfPath(principal_name), &krb5conf);

    if (load_config_error == ERROR_NONE) {
      KerberosEncryptionTypes encryption_types;
      bool success =
          config_parser_.GetEncryptionTypes(krb5conf, &encryption_types);
      if (success) {
        metrics_->ReportKerberosEncryptionTypes(encryption_types);
      }
    }
  }

  // Trying to acquire a ticket qualifies this user as an active user, so report
  // stats.
  MaybeReportDailyUsageStats();

  return error;
}

ErrorType AccountManager::GetKerberosFiles(const std::string& principal_name,
                                           KerberosFiles* files) const {
  // Trying to get Kerberos files qualifies this user as an active user, so
  // report stats.
  MaybeReportDailyUsageStats();

  files->clear_krb5cc();
  files->clear_krb5conf();

  const InternalAccount* account = GetAccount(principal_name);
  if (!account)
    return ERROR_UNKNOWN_PRINCIPAL_NAME;

  // By convention, no credential cache means no error.
  const base::FilePath krb5cc_path = GetKrb5CCPath(principal_name);
  if (!base::PathExists(krb5cc_path))
    return ERROR_NONE;

  std::string krb5cc;
  ErrorType error = LoadFile(krb5cc_path, &krb5cc);
  if (error != ERROR_NONE)
    return error;

  std::string krb5conf;
  error = LoadFile(GetKrb5ConfPath(principal_name), &krb5conf);
  if (error != ERROR_NONE)
    return error;

  files->mutable_krb5cc()->assign(krb5cc.begin(), krb5cc.end());
  files->mutable_krb5conf()->assign(krb5conf.begin(), krb5conf.end());
  return ERROR_NONE;
}

void AccountManager::StartObservingTickets() {
  for (const auto& account : accounts_) {
    const base::FilePath krb5cc_path =
        GetKrb5CCPath(account.data.principal_name());

    // Might happen for managed accounts (e.g. misconfigured password). Chrome
    // only allows adding unmanaged accounts if a ticket can be acquired.
    if (!base::PathExists(krb5cc_path))
      continue;

    // A ticket where GetTgtStatus fails is considered broken and hence invalid.
    Krb5Interface::TgtStatus tgt_status;
    if (krb5_->GetTgtStatus(krb5cc_path, &tgt_status) != ERROR_NONE ||
        tgt_status.validity_seconds <= 0) {
      NotifyTgtExpiration(account.data.principal_name(),
                          TgtRenewalScheduler::TgtExpiration::kExpired);
      continue;
    }

    // Ticket is valid. Schedule task to automatically renew it.
    account.tgt_renewal_scheduler_->ScheduleRenewal(
        true /* notify_expiration */);
  }
}

// static
std::string AccountManager::GetSafeFilenameForTesting(
    const std::string& principal_name) {
  return GetSafeFilename(principal_name);
}

void AccountManager::WrapKrb5ForTesting() {
  krb5_ = std::make_unique<Krb5JailWrapper>(std::move(krb5_));
}

void AccountManager::TriggerKerberosFilesChanged(
    const std::string& principal_name) const {
  kerberos_files_changed_.Run(principal_name);
}

void AccountManager::TriggerKerberosTicketExpiring(
    const std::string& principal_name) const {
  kerberos_ticket_expiring_.Run(principal_name);
}

ErrorType AccountManager::GetTgtStatus(const std::string& principal_name,
                                       Krb5Interface::TgtStatus* tgt_status) {
  return krb5_->GetTgtStatus(GetKrb5CCPath(principal_name), tgt_status);
}

ErrorType AccountManager::RenewTgt(const std::string& principal_name) {
  ErrorType error =
      krb5_->RenewTgt(principal_name, GetKrb5CCPath(principal_name),
                      GetKrb5ConfPath(principal_name));

  if (error != ERROR_NONE) {
    VLOG(1) << "RenewTgt failed with " << GetErrorString(error);

    // Renewal didn't work. See if we have a password stored and try to
    // auto-renew.
    MaybeAutoAcquireTgt(principal_name, &error);
  }

  last_renew_tgt_error_for_testing_ = error;
  return error;
}

void AccountManager::NotifyTgtExpiration(
    const std::string& principal_name,
    TgtRenewalScheduler::TgtExpiration expiration) {
  // First try to auto-acquire the TGT (usually works if password is stored).
  // Only if that isn't possible or doesn't work, trigger the signal.
  ErrorType error = ERROR_NONE;
  if (!MaybeAutoAcquireTgt(principal_name, &error) || error != ERROR_NONE) {
    // TODO(https://crbug.com/952245): Distinguish between "about to expire" and
    // "expired" in the KerberosTicketExpiring signal and in the Chrome
    // notification.
    TriggerKerberosTicketExpiring(principal_name);
  }
}

bool AccountManager::MaybeAutoAcquireTgt(const std::string& principal_name,
                                         ErrorType* error) {
  InternalAccount* account = GetMutableAccount(principal_name);
  DCHECK(account);

  // Check if |account| has access to the password.
  const bool use_login_password = account->data.use_login_password();
  const bool password_was_remembered =
      base::PathExists(GetPasswordPath(principal_name));
  if (!use_login_password && !password_was_remembered)
    return false;

  // Should not have remembered login password ourselves.
  DCHECK(!(use_login_password && password_was_remembered));

  VLOG(1) << "Auto-acquiring new TGT using "
          << (use_login_password ? "login" : "remembered") << " password";

  *error = AcquireTgt(principal_name, std::string() /* password */,
                      password_was_remembered /* keep remembering */,
                      use_login_password);

  if (*error != ERROR_NONE)
    VLOG(1) << "Auto-acquiring TGT failed with " << GetErrorString(*error);

  return true;
}

base::FilePath AccountManager::GetAccountDir(
    const std::string& principal_name) const {
  return storage_dir_.Append(GetSafeFilename(principal_name));
}

base::FilePath AccountManager::GetKrb5ConfPath(
    const std::string& principal_name) const {
  return GetAccountDir(principal_name).Append(kKrb5ConfFilePart);
}

base::FilePath AccountManager::GetKrb5CCPath(
    const std::string& principal_name) const {
  return GetAccountDir(principal_name).Append(kKrb5CCFilePart);
}

base::FilePath AccountManager::GetPasswordPath(
    const std::string& principal_name) const {
  return GetAccountDir(principal_name).Append(kPasswordFilePart);
}

ErrorType AccountManager::UpdatePasswordFromLogin(
    const std::string& principal_name, std::string* password) {
  // Erase a previously remembered password.
  base::DeleteFile(GetPasswordPath(principal_name));

  // Get login password from |password_provider_|.
  std::unique_ptr<password_provider::Password> login_password =
      password_provider_->GetPassword();
  if (!login_password || login_password->size() == 0) {
    password->clear();
    LOG(WARNING) << "Unable to retrieve login password";
  } else {
    *password = std::string(login_password->GetRaw(), login_password->size());
  }
  return ERROR_NONE;
}

ErrorType AccountManager::UpdatePasswordFromSaved(
    const std::string& principal_name,
    bool remember_password,
    std::string* password) {
  // Decision table what to do with the password:
  // pw empty / remember| false                      | true
  // -------------------+----------------------------+------------------------
  // false              | use given, erase file      | use given, save to file
  // true               | load from file, erase file | load from file

  // Remember password (even if authentication is going to fail below).
  const base::FilePath password_path = GetPasswordPath(principal_name);
  if (!password->empty() && remember_password) {
    ErrorType error = SaveFile(password_path, *password);
    if (error != ERROR_NONE)
      return error;

    // Remove group and other read access, just keep kerberosd rw. This prevents
    // kerberosd-exec from accessing the password.
    error = SetFilePermissions(password_path, kFileMode_rw);
    if (error != ERROR_NONE) {
      // Do a best effort removing the password.
      base::DeleteFile(password_path);
      return error;
    }
  }

  // Try to load a saved password if available and none is given.
  if (password->empty() && base::PathExists(password_path)) {
    ErrorType error = LoadFile(password_path, password);
    if (error != ERROR_NONE)
      return error;
  }

  // Erase a previously remembered password.
  if (!remember_password)
    base::DeleteFile(password_path);

  return ERROR_NONE;
}

void AccountManager::MaybeReportDailyUsageStats() const {
  // Did a day pass already?
  if (!metrics_->ShouldReportDailyUsageStats())
    return;

  // Count different kinds of accounts.
  int total_count = static_cast<int>(accounts_.size());
  int managed_count = 0;
  int unmanaged_count = 0;
  int remembered_password_count = 0;
  int use_login_password_count = 0;

  for (const auto& account : accounts_) {
    if (account.data.is_managed())
      managed_count++;
    else
      unmanaged_count++;
    if (base::PathExists(GetPasswordPath(account.data.principal_name())))
      remembered_password_count++;
    if (account.data.use_login_password())
      use_login_password_count++;
  }

  // Report UMA stats.
  metrics_->ReportDailyUsageStats(total_count, managed_count, unmanaged_count,
                                  remembered_password_count,
                                  use_login_password_count);
}

AccountManager::InternalAccount::InternalAccount(
    AccountData&& _data, TgtRenewalScheduler::Delegate* delegate)
    : data(std::move(_data)),
      tgt_renewal_scheduler_(std::make_unique<TgtRenewalScheduler>(
          data.principal_name(), delegate)) {}

int AccountManager::GetAccountIndex(const std::string& principal_name) const {
  for (size_t n = 0; n < accounts_.size(); ++n) {
    if (accounts_[n].data.principal_name() == principal_name) {
      CHECK(n <= std::numeric_limits<int>::max());
      return static_cast<int>(n);
    }
  }
  return kInvalidIndex;
}

const AccountManager::InternalAccount* AccountManager::GetAccount(
    const std::string& principal_name) const {
  int index = GetAccountIndex(principal_name);
  return index != kInvalidIndex ? &accounts_[index] : nullptr;
}

AccountManager::InternalAccount* AccountManager::GetMutableAccount(
    const std::string& principal_name) {
  int index = GetAccountIndex(principal_name);
  return index != kInvalidIndex ? &accounts_[index] : nullptr;
}

AccountManager::WhatToRemove AccountManager::DetermineWhatToRemove(
    ClearMode mode, const InternalAccount& account) {
  switch (mode) {
    case CLEAR_ALL:
      return WhatToRemove::kAccount;

    case CLEAR_ONLY_MANAGED_ACCOUNTS:
      return account.data.is_managed() ? WhatToRemove::kAccount
                                       : WhatToRemove::kNothing;

    case CLEAR_ONLY_UNMANAGED_ACCOUNTS:
      return !account.data.is_managed() ? WhatToRemove::kAccount
                                        : WhatToRemove::kNothing;

    case CLEAR_ONLY_UNMANAGED_REMEMBERED_PASSWORDS:
      return !account.data.is_managed() ? WhatToRemove::kPassword
                                        : WhatToRemove::kNothing;
  }
  return WhatToRemove::kNothing;
}

}  // namespace kerberos
