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

#include <algorithm>
#include <utility>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <krb5.h>
#include <profile.h>

#include "kerberos/error_strings.h"

namespace kerberos {

namespace {

// Environment variable for the Kerberos configuration (krb5.conf).
constexpr char kKrb5ConfigEnvVar[] = "KRB5_CONFIG";

// Wrapper classes for safe construction and destruction.
struct ScopedKrb5Context {
  ScopedKrb5Context() = default;
  ~ScopedKrb5Context() {
    if (ctx) {
      krb5_free_context(ctx);
      ctx = nullptr;
    }
  }

  // Converts the krb5 |code| to a human readable error message.
  std::string GetErrorMessage(errcode_t code) {
    // Fallback if error happens during ctx initialization (e.g. bad config).
    if (!ctx)
      return base::StringPrintf("Error %ld", code);

    const char* emsg = krb5_get_error_message(ctx, code);
    std::string msg = base::StringPrintf("%s (%ld)", emsg, code);
    krb5_free_error_message(ctx, emsg);
    return msg;
  }

  krb5_context get() const { return ctx; }
  krb5_context* get_mutable_ptr() { return &ctx; }

 private:
  krb5_context ctx = nullptr;
};

struct ScopedKrb5CCache {
  // Prefer the constructor taking a context if possible.
  ScopedKrb5CCache() {}
  explicit ScopedKrb5CCache(krb5_context _ctx) { set_ctx(_ctx); }

  ~ScopedKrb5CCache() {
    if (ccache) {
      DCHECK(ctx);
      krb5_cc_close(ctx, ccache);
      ccache = nullptr;
    }
  }

  // The context must be set if |ccache| is set (though get_mutable_ptr())
  // before this object is destroyed.
  void set_ctx(krb5_context _ctx) {
    ctx = _ctx;
    DCHECK(ctx);
  }

  krb5_ccache get() const { return ccache; }
  krb5_ccache* get_mutable_ptr() { return &ccache; }

 private:
  // Pointer to parent data, not owned.
  krb5_context ctx = nullptr;
  krb5_ccache ccache = nullptr;
};

// Maps some common krb5 error codes to our internal codes. If something is not
// reported properly, add more cases here.
ErrorType TranslateErrorCode(errcode_t code) {
  switch (code) {
    case KRB5KDC_ERR_NONE:
      return ERROR_NONE;

    case KRB5_KDC_UNREACH:
      return ERROR_NETWORK_PROBLEM;

    case KRB5_CONFIG_BADFORMAT:
    case PROF_BAD_BOOLEAN:
    case PROF_BAD_INTEGER:
      return ERROR_BAD_CONFIG;

    case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
      return ERROR_BAD_PRINCIPAL;

    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KDC_ERR_PREAUTH_FAILED:
      return ERROR_BAD_PASSWORD;

    case KRB5KDC_ERR_KEY_EXP:
      return ERROR_PASSWORD_EXPIRED;

    // TODO(https://crbug.com/951741): Verify
    case KRB5_KPASSWD_SOFTERROR:
      return ERROR_PASSWORD_REJECTED;

    // TODO(https://crbug.com/951741): Verify
    case KRB5_FCC_NOFILE:
      return ERROR_NO_CREDENTIALS_CACHE_FOUND;

    // TODO(https://crbug.com/951741): Verify
    case KRB5KRB_AP_ERR_TKT_EXPIRED:
      return ERROR_KERBEROS_TICKET_EXPIRED;

    case KRB5KDC_ERR_ETYPE_NOSUPP:
      return ERROR_KDC_DOES_NOT_SUPPORT_ENCRYPTION_TYPE;

    case KRB5_REALM_UNKNOWN:
      return ERROR_CONTACTING_KDC_FAILED;

    default:
      return ERROR_UNKNOWN_KRB5_ERROR;
  }
}

// Returns true if the string contained in |data| matches |str_to_match|.
bool DataMatches(const krb5_data& data, const char* str_to_match) {
  // It is not clear whether data.data is null terminated, so a strcmp might
  // not work.
  return strlen(str_to_match) == data.length &&
         memcmp(str_to_match, data.data, data.length) == 0;
}

// Returns true if |creds| has a server that starts with "krbtgt".
bool IsTgt(const krb5_creds& creds) {
  return creds.server && creds.server->length > 0 &&
         DataMatches(creds.server->data[0], "krbtgt");
}

enum class Action { AcquireTgt, RenewTgt };

struct Options {
  std::string principal_name;
  std::string password;
  std::string krb5cc_path;
  std::string config_path;
  Action action = Action::AcquireTgt;
};

// Encapsulates krb5 context data required for kinit.
class KinitContext {
 public:
  explicit KinitContext(Options options) : options_(std::move(options)) {
    memset(&k5_, 0, sizeof(k5_));
  }

  // Runs kinit with the options passed to the constructor. Only call once per
  // context. While in principle it should be fine to run multiple times, the
  // code path probably hasn't been tested (kinit does not call this multiple
  // times).
  ErrorType Run() {
    DCHECK(!did_run_);
    did_run_ = true;

    ErrorType error = Initialize();
    if (error == ERROR_NONE)
      error = RunKinit();
    Finalize();
    return error;
  }

 private:
  // The following code has been adapted from kinit.c in the mit-krb5 code base.
  // It has been formatted to fit this screen.

  struct Krb5Data {
    krb5_principal me;
    char* name;
  };

  // Wrapper around krb5 data to get rid of the gotos in the original code.
  struct KInitData {
    // Pointer to parent data, not owned.
    const krb5_context ctx = nullptr;
    // Pointer to parent data, not owned.
    const Krb5Data* k5 = nullptr;
    krb5_creds my_creds;
    krb5_get_init_creds_opt* options = nullptr;

    // The lifetime of the |k5| pointer must exceed the lifetime of this object.
    explicit KInitData(const krb5_context ctx, const Krb5Data* k5)
        : ctx(ctx), k5(k5) {
      memset(&my_creds, 0, sizeof(my_creds));
    }

    ~KInitData() {
      if (options)
        krb5_get_init_creds_opt_free(ctx, options);
      if (my_creds.client == k5->me)
        my_creds.client = nullptr;
      krb5_free_cred_contents(ctx, &my_creds);
    }
  };

  // Initializes krb5 data.
  ErrorType Initialize() {
    krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
      return TranslateErrorCode(ret);
    }

    out_cc.set_ctx(ctx.get());
    ret = krb5_cc_resolve(ctx.get(), options_.krb5cc_path.c_str(),
                          out_cc.get_mutable_ptr());
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " resolving ccache";
      return TranslateErrorCode(ret);
    }

    ret = krb5_parse_name_flags(ctx.get(), options_.principal_name.c_str(),
                                0 /* flags */, &k5_.me);
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " when parsing name";
      return TranslateErrorCode(ret);
    }

    ret = krb5_unparse_name(ctx.get(), k5_.me, &k5_.name);
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " when unparsing name";
      return TranslateErrorCode(ret);
    }

    options_.principal_name = k5_.name;
    return ERROR_NONE;
  }

  // Finalizes krb5 data.
  void Finalize() {
    krb5_free_unparsed_name(ctx.get(), k5_.name);
    krb5_free_principal(ctx.get(), k5_.me);
    memset(&k5_, 0, sizeof(k5_));
  }

  // Runs the actual kinit code and acquires/renews tickets.
  ErrorType RunKinit() {
    krb5_error_code ret;
    KInitData d(ctx.get(), &k5_);

    ret = krb5_get_init_creds_opt_alloc(ctx.get(), &d.options);
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
      return TranslateErrorCode(ret);
    }

    ret = krb5_get_init_creds_opt_set_out_ccache(ctx.get(), d.options,
                                                 out_cc.get());
    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
      return TranslateErrorCode(ret);
    }

    // To get notified of expiry, see
    // krb5_get_init_creds_opt_set_expire_callback

    switch (options_.action) {
      case Action::AcquireTgt:
        ret = krb5_get_init_creds_password(
            ctx.get(), &d.my_creds, k5_.me, options_.password.c_str(),
            nullptr /* prompter */, nullptr /* data */, 0 /* start_time */,
            nullptr /* in_tkt_service */, d.options);
        break;
      case Action::RenewTgt:
        ret =
            krb5_get_renewed_creds(ctx.get(), &d.my_creds, k5_.me, out_cc.get(),
                                   nullptr /* options_.in_tkt_service */);
        break;
    }

    if (ret) {
      LOG(ERROR) << ctx.GetErrorMessage(ret);
      return TranslateErrorCode(ret);
    }

    if (options_.action != Action::AcquireTgt) {
      ret = krb5_cc_initialize(ctx.get(), out_cc.get(), k5_.me);
      if (ret) {
        LOG(ERROR) << ctx.GetErrorMessage(ret) << " when initializing cache";
        return TranslateErrorCode(ret);
      }

      ret = krb5_cc_store_cred(ctx.get(), out_cc.get(), &d.my_creds);
      if (ret) {
        LOG(ERROR) << ctx.GetErrorMessage(ret) << " while storing credentials";
        return TranslateErrorCode(ret);
      }
    }

    return ERROR_NONE;
  }

  ScopedKrb5Context ctx;
  ScopedKrb5CCache out_cc;
  Krb5Data k5_;
  Options options_;
  bool did_run_ = false;
};

// Runs the Kerberos configuration |krb5conf| through the krb5 code to see if it
// can be parsed.
ErrorType ValidateConfigViaKrb5(const std::string& krb5conf) {
  // Since krb5 doesn't accept config passed as string, write it to disk.
  base::FilePath krb5conf_path;
  if (!base::CreateTemporaryFile(&krb5conf_path)) {
    LOG(ERROR) << "Failed to create temp file for validating config";
    return ERROR_LOCAL_IO;
  }

  const int size = static_cast<int>(krb5conf.size());
  if (base::WriteFile(krb5conf_path, krb5conf.data(), size) != size) {
    LOG(ERROR) << "Failed to write config to disk at " << krb5conf_path.value()
               << " for validating config";
    return ERROR_LOCAL_IO;
  }

  // krb5_init_context parses the config file.
  setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
  ScopedKrb5Context ctx;
  krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
  unsetenv(kKrb5ConfigEnvVar);
  base::DeleteFile(krb5conf_path, false /* recursive */);

  if (ret) {
    LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
    return TranslateErrorCode(ret);
  }

  return ERROR_NONE;
}

}  // namespace

Krb5InterfaceImpl::Krb5InterfaceImpl() = default;

Krb5InterfaceImpl::~Krb5InterfaceImpl() = default;

ErrorType Krb5InterfaceImpl::AcquireTgt(const std::string& principal_name,
                                        const std::string& password,
                                        const base::FilePath& krb5cc_path,
                                        const base::FilePath& krb5conf_path) {
  Options options;
  options.action = Action::AcquireTgt;
  options.principal_name = principal_name;
  options.password = password;
  options.krb5cc_path = krb5cc_path.value();
  setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
  ErrorType error = KinitContext(std::move(options)).Run();
  unsetenv(kKrb5ConfigEnvVar);
  return error;
}

ErrorType Krb5InterfaceImpl::RenewTgt(const std::string& principal_name,
                                      const base::FilePath& krb5cc_path,
                                      const base::FilePath& krb5conf_path) {
  Options options;
  options.action = Action::RenewTgt;
  options.principal_name = principal_name;
  options.krb5cc_path = krb5cc_path.value();
  setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
  ErrorType error = KinitContext(std::move(options)).Run();
  unsetenv(kKrb5ConfigEnvVar);
  return error;
}

ErrorType Krb5InterfaceImpl::GetTgtStatus(const base::FilePath& krb5cc_path,
                                          TgtStatus* status) {
  DCHECK(status);

  ScopedKrb5Context ctx;
  krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
  if (ret) {
    LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
    return TranslateErrorCode(ret);
  }

  ScopedKrb5CCache ccache(ctx.get());
  std::string prefixed_krb5cc_path = "FILE:" + krb5cc_path.value();
  ret = krb5_cc_resolve(ctx.get(), prefixed_krb5cc_path.c_str(),
                        ccache.get_mutable_ptr());
  if (ret) {
    LOG(ERROR) << ctx.GetErrorMessage(ret) << " while resolving cache";
    return TranslateErrorCode(ret);
  }

  krb5_cc_cursor cur;
  ret = krb5_cc_start_seq_get(ctx.get(), ccache.get(), &cur);
  if (ret) {
    LOG(ERROR) << ctx.GetErrorMessage(ret)
               << " while starting to retrieve tickets";
    return TranslateErrorCode(ret);
  }

  krb5_timestamp now = time(nullptr);

  krb5_creds creds;
  bool found_tgt = false;
  while ((ret = krb5_cc_next_cred(ctx.get(), ccache.get(), &cur, &creds)) ==
         0) {
    if (IsTgt(creds)) {
      if (creds.times.endtime)
        status->validity_seconds =
            std::max<int64_t>(creds.times.endtime - now, 0);

      if (creds.times.renew_till) {
        status->renewal_seconds =
            std::max<int64_t>(creds.times.renew_till - now, 0);
      }

      if (found_tgt) {
        LOG(WARNING) << "More than one TGT found in credential cache '"
                     << krb5cc_path.value() << ".";
      }
      found_tgt = true;
    }
    krb5_free_cred_contents(ctx.get(), &creds);
  }
  if (!found_tgt) {
    LOG(WARNING) << "No TGT found in credential cache '" << krb5cc_path.value()
                 << ".";
  }

  if (ret != KRB5_CC_END) {
    LOG(ERROR) << ctx.GetErrorMessage(ret) << " while retrieving a ticket";
    return TranslateErrorCode(ret);
  }

  ret = krb5_cc_end_seq_get(ctx.get(), ccache.get(), &cur);
  if (ret) {
    LOG(ERROR) << ctx.GetErrorMessage(ret)
               << " while finishing ticket retrieval";
    return TranslateErrorCode(ret);
  }

  return ERROR_NONE;
}

ErrorType Krb5InterfaceImpl::ValidateConfig(const std::string& krb5conf,
                                            ConfigErrorInfo* error_info) {
  *error_info = config_parser_.Validate(krb5conf);
  if (error_info->code() != CONFIG_ERROR_NONE)
    return ERROR_BAD_CONFIG;

  // Also try the mit krb5 code to parse the config.
  error_info->Clear();
  ErrorType error = ValidateConfigViaKrb5(krb5conf);
  if (error == ERROR_BAD_CONFIG) {
    error_info->set_code(CONFIG_ERROR_KRB5_FAILED_TO_PARSE);
    return error;
  }

  // Ignore all other errors, they're most likely unrelated. The
  // |config_parser_| should already cover pretty much everything, anyway.
  error_info->set_code(CONFIG_ERROR_NONE);
  if (error != ERROR_NONE) {
    LOG(WARNING) << "Ignoring unrelated error " << GetErrorString(error)
                 << " while validating config";
  }
  return error;
}

}  // namespace kerberos
