// 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/files/file_util.h>
#include <base/logging.h>
#include <base/stl_util.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::DeleteFile(account_dir, true /* recursive */);
    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::DeleteFile(GetAccountDir(principal_name), true /* recursive */));
  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()),
                               false /* recursive */));
        ++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), false /* recursive */);

  // 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, false /* recursive */);
      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, false /* recursive */);

  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
