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

#include <algorithm>

#include <base/files/file_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread_task_runner_handle.h>
#include <base/time/time.h>

#include "bindings/kerberos_containers.pb.h"
#include "kerberos/error_strings.h"
#include "kerberos/krb5_interface.h"

namespace kerberos {
namespace {

// Nice marker for TGT renewal related logs, for easy grepping.
constexpr char kLogHeader[] = "TGT RENEWAL - ";

// Don't try to renew TGTs more often than this interval.
constexpr int kMinTgtRenewDelaySeconds = 60;
static_assert(kMinTgtRenewDelaySeconds > 0, "");

// Formats a time delta in 1h 2m 3s format.
std::string FormatTimeDelta(int64_t delta_seconds) {
  int h = delta_seconds / 3600;
  int m = (delta_seconds / 60) % 60;
  int s = delta_seconds % 60;

  std::string str;
  if (h > 0)
    str += base::StringPrintf("%ih ", h);
  if (h > 0 || m > 0)
    str += base::StringPrintf("%im ", m);
  str += base::StringPrintf("%is", s);
  return str;
}

std::ostream& operator<<(std::ostream& os,
                         const Krb5Interface::TgtStatus& tgt_status) {
  os << "(valid for " << FormatTimeDelta(tgt_status.validity_seconds)
     << ", renewable for " << FormatTimeDelta(tgt_status.renewal_seconds)
     << ")";
  return os;
}

}  // namespace

TgtRenewalScheduler::TgtRenewalScheduler(const std::string& principal_name,
                                         Delegate* delegate)
    : principal_name_(principal_name), delegate_(delegate) {}

void TgtRenewalScheduler::ScheduleRenewal(bool notify_expiration) {
  // Cancel an existing callback if there is any.
  if (!tgt_renewal_callback_.IsCancelled())
    tgt_renewal_callback_.Cancel();

  // If the TGT exists, but it's broken somehow, assume it's invalid.
  Krb5Interface::TgtStatus tgt_status;
  if (delegate_->GetTgtStatus(principal_name_, &tgt_status) != ERROR_NONE) {
    VLOG(1) << kLogHeader << "Failed to get TGT status";
    if (notify_expiration)
      delegate_->NotifyTgtExpiration(principal_name_, TgtExpiration::kExpired);
    return;
  }

  // Is the TGT expired?
  if (tgt_status.validity_seconds <= 0) {
    VLOG(1) << kLogHeader << "TGT about to expire or expired";
    if (notify_expiration)
      delegate_->NotifyTgtExpiration(principal_name_, TgtExpiration::kExpired);
    return;
  }

  // Is the TGT about to expire? At this point we already give up and show a
  // notification in Chrome, so the user can relog.
  if (tgt_status.validity_seconds <= kExpirationHeadsUpTimeSeconds) {
    VLOG(1) << kLogHeader << "TGT about to expire";
    if (notify_expiration)
      delegate_->NotifyTgtExpiration(principal_name_,
                                     TgtExpiration::kAboutToExpire);
    return;
  }

  // Note: Reschedule even if the ticket is not renewable anymore, i.e.
  // if tgt_status.validity_seconds >= tgt_status.renewal_seconds. The account
  // manager might have credentials stored for the account, which allows it to
  // auto-refresh the ticket without user input. If we didn't reschedule, we'd
  // miss the opportunity to auth-refresh the ticket.

  // Trigger the renewal somewhere in the validity lifetime of the TGT.
  int delay_seconds = static_cast<int>(tgt_status.validity_seconds *
                                       kTgtRenewValidityLifetimeFraction);

  // Make sure we don't trigger excessively often in case the renewal
  // fails and we're getting close to the end of the validity lifetime.
  delay_seconds = std::max(delay_seconds, kMinTgtRenewDelaySeconds);

  VLOG(1) << kLogHeader << "Scheduling renewal in "
          << FormatTimeDelta(delay_seconds) << " " << tgt_status;

  tgt_renewal_callback_.Reset(base::Bind(
      &TgtRenewalScheduler::RunScheduledTgtRenewal, base::Unretained(this)));
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, tgt_renewal_callback_.callback(),
      base::TimeDelta::FromSeconds(delay_seconds));
}

void TgtRenewalScheduler::RunScheduledTgtRenewal() {
  VLOG(1) << kLogHeader << "Running scheduled TGT renewal";

  ErrorType error = delegate_->RenewTgt(principal_name_);

  // No matter if it worked or not, reschedule auto-renewal. We might be offline
  // and want to try again later.
  ScheduleRenewal(true /* notify_expiration */);

  if (error == ERROR_NONE)
    VLOG(1) << kLogHeader << "Succeeded";
  else
    LOG(ERROR) << kLogHeader << "Failed with error " << GetErrorString(error);
}

}  // namespace kerberos
