// 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/kerberos_adaptor.h"

#include <string>
#include <unordered_set>
#include <utility>

#include <base/compiler_specific.h>
#include <base/files/file_util.h>
#include <base/optional.h>
#include <base/threading/thread_task_runner_handle.h>
#include <base/time/time.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/errors/error.h>
#include <dbus/login_manager/dbus-constants.h>
#include <libpasswordprovider/password_provider.h>
#include <session_manager/dbus-proxies.h>

#include "kerberos/account_manager.h"
#include "kerberos/error_strings.h"
#include "kerberos/kerberos_metrics.h"
#include "kerberos/krb5_interface.h"
#include "kerberos/krb5_interface_impl.h"
#include "kerberos/krb5_jail_wrapper.h"
#include "kerberos/platform_helper.h"

namespace kerberos {

namespace {

constexpr base::TimeDelta kTicketExpiryCheckDelay =
    base::TimeDelta::FromSeconds(3);

using ByteArray = KerberosAdaptor::ByteArray;

// Serializes |proto| to a vector of bytes. CHECKs for success (should
// never fail if there are no required proto fields).
ByteArray SerializeProto(const google::protobuf::MessageLite& proto) {
  ByteArray proto_blob(proto.ByteSizeLong());
  CHECK(proto.SerializeToArray(proto_blob.data(), proto_blob.size()));
  return proto_blob;
}

// Parses a proto from an array of bytes |proto_blob|. Returns
// ERROR_PARSE_REQUEST_FAILED on error.
WARN_UNUSED_RESULT ErrorType ParseProto(google::protobuf::MessageLite* proto,
                                        const ByteArray& proto_blob) {
  if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
    LOG(ERROR) << "Failed to parse proto";
    return ERROR_PARSE_REQUEST_FAILED;
  }
  return ERROR_NONE;
}

void PrintRequest(const char* method_name) {
  LOG(INFO) << ">>> " << method_name;
}

void PrintResult(const char* method_name, ErrorType error) {
  if (error == ERROR_NONE)
    LOG(INFO) << "<<< " << method_name << " succeeded";
  else
    LOG(ERROR) << "<<< " << method_name << " failed: " << GetErrorString(error);
}

// Calls Session Manager to get the user hash for the primary session. Returns
// an empty string and logs on error.
std::string GetSanitizedUsername(brillo::dbus_utils::DBusObject* dbus_object) {
  std::string username;
  std::string sanitized_username;
  brillo::ErrorPtr error;
  org::chromium::SessionManagerInterfaceProxy proxy(dbus_object->GetBus());
  if (!proxy.RetrievePrimarySession(&username, &sanitized_username, &error)) {
    const char* error_msg =
        error ? error->GetMessage().c_str() : "Unknown error.";
    LOG(ERROR) << "Call to RetrievePrimarySession failed. " << error_msg;
    return std::string();
  }
  return sanitized_username;
}

}  // namespace

KerberosAdaptor::KerberosAdaptor(
    std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
    : org::chromium::KerberosAdaptor(this),
      dbus_object_(std::move(dbus_object)) {}

KerberosAdaptor::~KerberosAdaptor() = default;

void KerberosAdaptor::RegisterAsync(
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
        completion_callback) {
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);

  // Get the sanitized username (aka user hash). It's needded to determine the
  // daemon store directory where account data is stored.
  base::FilePath storage_dir;
  if (storage_dir_for_testing_) {
    storage_dir = *storage_dir_for_testing_;
  } else {
    const std::string sanitized_username =
        GetSanitizedUsername(dbus_object_.get());
    if (!sanitized_username.empty()) {
      storage_dir = base::FilePath("/run/daemon-store/kerberosd/")
                        .Append(sanitized_username);
    } else {
      // /tmp is a tmpfs and the daemon is shut down on logout, so data is
      // cleared on logout. Better than nothing, though.
      storage_dir = base::FilePath("/tmp");
      LOG(ERROR) << "Failed to retrieve user hash to determine storage "
                    "directory. Falling back to "
                 << storage_dir.value() << ".";
    }
  }

  // Might have already been set for testing.
  if (!metrics_)
    metrics_ = std::make_unique<KerberosMetrics>(storage_dir);

  // Create krb5 or use the one given for testing.
  auto krb5 = krb5_for_testing_ ? std::move(krb5_for_testing_)
                                : std::make_unique<Krb5JailWrapper>(
                                      std::make_unique<Krb5InterfaceImpl>());

  manager_ = std::make_unique<AccountManager>(
      storage_dir,
      base::BindRepeating(&KerberosAdaptor::OnKerberosFilesChanged,
                          base::Unretained(this)),
      base::BindRepeating(&KerberosAdaptor::OnKerberosTicketExpiring,
                          base::Unretained(this)),
      std::move(krb5), std::make_unique<password_provider::PasswordProvider>(),
      metrics_.get());
  manager_->LoadAccounts();

  // Wait a little before calling StartObservingTickets. Apparently, signals
  // are not quite wired up properly at this point. If signals are emitted here,
  // they never reach Chrome, even if Chrome made sure it connected to the
  // signal.
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::BindRepeating(&KerberosAdaptor::StartObservingTickets,
                          weak_ptr_factory_.GetWeakPtr()),
      kTicketExpiryCheckDelay);
}

ByteArray KerberosAdaptor::AddAccount(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  AddAccountRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  if (error == ERROR_NONE) {
    error =
        manager_->AddAccount(request.principal_name(), request.is_managed());
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  AddAccountResponse response;
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::RemoveAccount(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  RemoveAccountRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  RemoveAccountResponse response;
  if (error == ERROR_NONE) {
    error = manager_->RemoveAccount(request.principal_name());
    GetAccountsList(response.mutable_accounts());
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::ClearAccounts(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  ClearAccountsRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  ClearAccountsResponse response;
  if (error == ERROR_NONE) {
    std::unordered_set<std::string> keep_list(
        request.principal_names_to_ignore_size());
    for (int n = 0; n < request.principal_names_to_ignore_size(); ++n)
      keep_list.insert(request.principal_names_to_ignore(n));

    error = manager_->ClearAccounts(request.mode(), std::move(keep_list));
    GetAccountsList(response.mutable_accounts());
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::ListAccounts(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  ListAccountsRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  // Note: request is empty right now, but keeping it for future changes.
  std::vector<Account> accounts;
  ListAccountsResponse response;
  if (error == ERROR_NONE)
    GetAccountsList(response.mutable_accounts());

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::SetConfig(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  SetConfigRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  if (error == ERROR_NONE)
    error = manager_->SetConfig(request.principal_name(), request.krb5conf());

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  SetConfigResponse response;
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::ValidateConfig(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  ValidateConfigRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  ConfigErrorInfo error_info;
  if (error == ERROR_NONE) {
    error = manager_->ValidateConfig(request.krb5conf(), &error_info);
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  metrics_->ReportValidateConfigErrorCode(error_info.code());
  ValidateConfigResponse response;
  response.set_error(error);
  *response.mutable_error_info() = error_info;
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::AcquireKerberosTgt(
    const ByteArray& request_blob, const base::ScopedFD& password_fd) {
  PrintRequest(__FUNCTION__);
  AcquireKerberosTgtRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  base::Optional<std::string> password;
  if (error == ERROR_NONE) {
    password = ReadPipeToString(password_fd.get());
    if (!password.has_value()) {
      LOG(ERROR) << "Failed to read password pipe";
      error = ERROR_LOCAL_IO;
    }
  }

  if (error == ERROR_NONE) {
    metrics_->StartAcquireTgtTimer();
    error = manager_->AcquireTgt(request.principal_name(), password.value(),
                                 request.remember_password(),
                                 request.use_login_password());
    metrics_->StopAcquireTgtTimerAndReport();
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  AcquireKerberosTgtResponse response;
  response.set_error(error);
  return SerializeProto(response);
}

ByteArray KerberosAdaptor::GetKerberosFiles(const ByteArray& request_blob) {
  PrintRequest(__FUNCTION__);
  GetKerberosFilesRequest request;
  ErrorType error = ParseProto(&request, request_blob);

  GetKerberosFilesResponse response;
  if (error == ERROR_NONE) {
    error = manager_->GetKerberosFiles(request.principal_name(),
                                       response.mutable_files());
  }

  PrintResult(__FUNCTION__, error);
  metrics_->ReportDBusCallResult(__FUNCTION__, error);
  response.set_error(error);
  return SerializeProto(response);
}

void KerberosAdaptor::set_storage_dir_for_testing(const base::FilePath& dir) {
  DCHECK(!manager_);
  storage_dir_for_testing_ = dir;
}

void KerberosAdaptor::set_krb5_for_testing(
    std::unique_ptr<Krb5Interface> krb5) {
  DCHECK(!manager_);
  krb5_for_testing_ = std::move(krb5);
}

void KerberosAdaptor::set_metrics_for_testing(
    std::unique_ptr<KerberosMetrics> metrics) {
  DCHECK(!manager_);
  metrics_ = std::move(metrics);
}

void KerberosAdaptor::StartObservingTickets() {
  manager_->StartObservingTickets();
}

void KerberosAdaptor::OnKerberosFilesChanged(
    const std::string& principal_name) {
  LOG(INFO) << "Firing signal KerberosFilesChanged";
  SendKerberosFilesChangedSignal(principal_name);
}

void KerberosAdaptor::OnKerberosTicketExpiring(
    const std::string& principal_name) {
  LOG(INFO) << "Firing signal KerberosTicketExpiring";
  SendKerberosTicketExpiringSignal(principal_name);
}

void KerberosAdaptor::GetAccountsList(RepeatedAccountField* repeated_accounts) {
  std::vector<Account> accounts = manager_->ListAccounts();
  for (const auto& account : accounts)
    *repeated_accounts->Add() = account;
}

}  // namespace kerberos
