// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "secagentd/plugins.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <utility>
#include <variant>

#include "absl/status/status.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "cryptohome/proto_bindings/UserDataAuth.pb.h"
#include "dbus/bus.h"
#include "missive/proto/record_constants.pb.h"
#include "secagentd/common.h"
#include "secagentd/device_user.h"
#include "secagentd/message_sender.h"
#include "secagentd/metrics_sender.h"
#include "secagentd/policies_features_broker.h"
#include "secagentd/proto/security_xdr_events.pb.h"
#include "user_data_auth/dbus-proxies.h"

namespace secagentd {

namespace pb = cros_xdr::reporting;

namespace {
bool UpdateNumFailedAttempts(const int64_t latest_success,
                             const AuthFactorType auth_factor_type,
                             pb::UserEventAtomicVariant* event) {
  // Check that timestamp is greater than the most recent
  // success and auth
  // factor matches. If so increment number of failed attempts
  // by 1.
  if ((event->has_common() &&
       event->common().create_timestamp_us() > latest_success) &&
      (event->has_failure() && event->failure().has_authentication() &&
       event->failure().authentication().auth_factor_size() >= 1 &&
       event->failure().authentication().auth_factor()[0] ==
           auth_factor_type)) {
    event->mutable_failure()->mutable_authentication()->set_num_failed_attempts(
        event->failure().authentication().num_failed_attempts() + 1);
    return true;
  }
  return false;
}

std::optional<std::pair<metrics::EnumMetric<metrics::AuthFactor>, int>>
GetEventEnumTypeAndAuthFactor(const pb::UserEventAtomicVariant& atomic_event) {
  int auth_factor = 0;
  if (atomic_event.has_logon()) {
    if (atomic_event.logon().has_authentication() &&
        atomic_event.logon().authentication().auth_factor_size() >= 1) {
      auth_factor = atomic_event.logon().authentication().auth_factor()[0];
    }
    return std::make_pair(metrics::kLogin, auth_factor);
  } else if (atomic_event.has_unlock()) {
    if (atomic_event.unlock().has_authentication() &&
        atomic_event.unlock().authentication().auth_factor_size() >= 1) {
      auth_factor = atomic_event.unlock().authentication().auth_factor()[0];
    }
    return std::make_pair(metrics::kUnlock, auth_factor);
  }

  return std::nullopt;
}
}  // namespace

AuthenticationPlugin::AuthenticationPlugin(
    scoped_refptr<MessageSenderInterface> message_sender,
    scoped_refptr<PoliciesFeaturesBrokerInterface> policies_features_broker,
    scoped_refptr<DeviceUserInterface> device_user,
    uint32_t batch_interval_s)
    : weak_ptr_factory_(this),
      policies_features_broker_(policies_features_broker),
      device_user_(device_user) {
  batch_sender_ = std::make_unique<BatchSender<std::monostate, pb::XdrUserEvent,
                                               pb::UserEventAtomicVariant>>(
      base::BindRepeating(
          [](const cros_xdr::reporting::UserEventAtomicVariant& event)
              -> std::monostate {
            // Only the most recent event type will need to be visited
            // so monostate is used. This makes it so for each type of auth
            // variation only 1 event is tracked.
            return std::monostate();
          }),
      message_sender, reporting::Destination::CROS_SECURITY_USER,
      batch_interval_s);
  CHECK(message_sender != nullptr);
}

std::string AuthenticationPlugin::GetName() const {
  return "Authentication";
}

absl::Status AuthenticationPlugin::Activate() {
  if (is_active_) {
    return absl::OkStatus();
  }

  batch_sender_->Start();

  // Register cryptohome proxy for authentication result.
  if (!cryptohome_proxy_) {
    cryptohome_proxy_ =
        std::make_unique<org::chromium::UserDataAuthInterfaceProxy>(
            common::GetDBus());
  }
  cryptohome_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(
          [](org::chromium::UserDataAuthInterfaceProxyInterface*
                 cryptohome_proxy,
             base::RepeatingCallback<void(
                 const user_data_auth::AuthenticateAuthFactorCompleted&)>
                 signal_callback,
             dbus::ObjectProxy::OnConnectedCallback on_connected_callback,
             bool available) {
            if (!available) {
              LOG(ERROR) << "Failed to register for "
                            "AuthenticateAuthFactorCompleted signal";
              return;
            }
            cryptohome_proxy
                ->RegisterAuthenticateAuthFactorCompletedSignalHandler(
                    std::move(signal_callback),
                    std::move(on_connected_callback));
          },
          cryptohome_proxy_.get(),
          base::BindRepeating(
              &AuthenticationPlugin::OnAuthenticateAuthFactorCompleted,
              weak_ptr_factory_.GetWeakPtr()),
          base::BindOnce(&AuthenticationPlugin::OnRegistrationResult,
                         weak_ptr_factory_.GetWeakPtr())));

  // Register for lock/unlock signals.
  device_user_->RegisterScreenLockedHandler(
      base::BindRepeating(&AuthenticationPlugin::OnScreenLock,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindOnce(&AuthenticationPlugin::OnRegistrationResult,
                     weak_ptr_factory_.GetWeakPtr()));
  device_user_->RegisterScreenUnlockedHandler(
      base::BindRepeating(&AuthenticationPlugin::OnScreenUnlock,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindOnce(&AuthenticationPlugin::OnRegistrationResult,
                     weak_ptr_factory_.GetWeakPtr()));

  // Register for login/out signal.
  device_user_->RegisterSessionChangeListener(
      base::BindRepeating(&AuthenticationPlugin::OnSessionStateChange,
                          weak_ptr_factory_.GetWeakPtr()));

  is_active_ = true;
  return absl::OkStatus();
}

absl::Status AuthenticationPlugin::Deactivate() {
  return absl::UnimplementedError(
      "Deactivate not implemented for AuthenticationPlugin.");
}

bool AuthenticationPlugin::IsActive() const {
  return is_active_;
}

void AuthenticationPlugin::OnScreenLock() {
  auto screen_lock = std::make_unique<pb::UserEventAtomicVariant>();
  screen_lock->mutable_lock();
  screen_lock->mutable_common()->set_create_timestamp_us(
      base::Time::Now().InMillisecondsSinceUnixEpoch() *
      base::Time::kMicrosecondsPerMillisecond);
  device_user_->GetDeviceUserAsync(
      base::BindOnce(&AuthenticationPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(screen_lock)));
}

void AuthenticationPlugin::OnScreenUnlock() {
  auto screen_unlock = std::make_unique<pb::UserEventAtomicVariant>();
  screen_unlock->mutable_common()->set_create_timestamp_us(
      base::Time::Now().InMillisecondsSinceUnixEpoch() *
      base::Time::kMicrosecondsPerMillisecond);
  latest_successful_login_timestamp_ =
      screen_unlock->common().create_timestamp_us();

  auto* authentication =
      screen_unlock->mutable_unlock()->mutable_authentication();
  if (!FillAuthFactor(authentication)) {
    authentication->clear_auth_factor();
    base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&AuthenticationPlugin::DelayedCheckForAuthSignal,
                       weak_ptr_factory_.GetWeakPtr(), std::move(screen_unlock),
                       authentication),
        kWaitForAuthFactorS);
    return;
  }

  auth_factor_type_ =
      AuthFactorType::Authentication_AuthenticationType_AUTH_TYPE_UNKNOWN;
  device_user_->GetDeviceUserAsync(
      base::BindOnce(&AuthenticationPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(screen_unlock)));
}

void AuthenticationPlugin::OnSessionStateChange(const std::string& state) {
  auto log_event = std::make_unique<pb::UserEventAtomicVariant>();
  log_event->mutable_common()->set_create_timestamp_us(
      base::Time::Now().InMillisecondsSinceUnixEpoch() *
      base::Time::kMicrosecondsPerMillisecond);

  if (state == kStarted) {
    latest_successful_login_timestamp_ =
        log_event->common().create_timestamp_us();
    auto* authentication = log_event->mutable_logon()->mutable_authentication();
    if (!FillAuthFactor(authentication)) {
      authentication->clear_auth_factor();
      base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&AuthenticationPlugin::DelayedCheckForAuthSignal,
                         weak_ptr_factory_.GetWeakPtr(), std::move(log_event),
                         authentication),
          kWaitForAuthFactorS);
      return;
    }
    auth_factor_type_ =
        AuthFactorType::Authentication_AuthenticationType_AUTH_TYPE_UNKNOWN;
  } else if (state == kStopped) {
    log_event->mutable_logoff();
    if (signed_in_user_ != device_user::kEmpty) {
      log_event->mutable_common()->set_device_user(signed_in_user_);
    } else {
      log_event->mutable_common()->set_device_user(device_user::kUnknown);
    }
  } else if (state == kInit) {
    device_user_->GetDeviceUserAsync(
        base::BindOnce(&AuthenticationPlugin::OnFirstSessionStart,
                       weak_ptr_factory_.GetWeakPtr()));
    return;
  } else {
    return;
  }

  device_user_->GetDeviceUserAsync(
      base::BindOnce(&AuthenticationPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(log_event)));
}

void AuthenticationPlugin::OnRegistrationResult(const std::string& interface,
                                                const std::string& signal,
                                                bool success) {
  if (!success) {
    LOG(ERROR) << "Callback registration failed for dbus signal: " << signal
               << " on interface: " << interface;
  }
}

void AuthenticationPlugin::OnAuthenticateAuthFactorCompleted(
    const user_data_auth::AuthenticateAuthFactorCompleted& completed) {
  if (completed.user_creation()) {
    // If the proto contains an error indicating that creating the user failed,
    // ignore the error because no user was signed in.
    if (completed.has_error_info()) {
      return;
    }
    auth_factor_type_ =
        AuthFactorType::Authentication_AuthenticationType_AUTH_NEW_USER;
    return;
  }

  auto it = auth_factor_map_.find(completed.auth_factor_type());
  if (it == auth_factor_map_.end()) {
    LOG(ERROR) << "Unknown auth factor type " << completed.auth_factor_type();
    auth_factor_type_ =
        AuthFactorType::Authentication_AuthenticationType_AUTH_TYPE_UNKNOWN;
  } else {
    if (completed.has_error_info()) {
      // When a pin is incorrectly entered two Auth signals are sent on the
      // lockscreen. One trying the pin and one trying the password. In this
      // case ignore the password and keep the auth_factor as pin.
      // TODO(b:305093271): Update logic to handle if password is actually used.
      if (it->second ==
          AuthFactorType::Authentication_AuthenticationType_AUTH_PIN) {
        latest_pin_failure_ = base::Time::Now().InMillisecondsSinceUnixEpoch() /
                              base::Time::kMillisecondsPerSecond;
        last_auth_was_password_ = false;
      } else if (it->second ==
                 AuthFactorType::
                     Authentication_AuthenticationType_AUTH_PASSWORD) {
        if (auth_factor_type_ ==
                AuthFactorType::Authentication_AuthenticationType_AUTH_PIN &&
            !last_auth_was_password_ &&
            (base::Time::Now().InMillisecondsSinceUnixEpoch() /
             base::Time::kMillisecondsPerSecond) -
                    latest_pin_failure_ <=
                kMaxDelayForLockscreenAttemptsS) {
          last_auth_was_password_ = true;
          return;
        }
        last_auth_was_password_ = true;
      } else {
        last_auth_was_password_ = false;
      }
    }
    auth_factor_type_ = it->second;
  }

  if (completed.has_error_info()) {
    // Record auth factor for failure event.
    MetricsSender::GetInstance().SendEnumMetricToUMA(
        metrics::kFailure, static_cast<metrics::AuthFactor>(auth_factor_type_));
    if (!batch_sender_->Visit(pb::UserEventAtomicVariant::kFailure,
                              std::monostate(),
                              base::BindOnce(&UpdateNumFailedAttempts,
                                             latest_successful_login_timestamp_,
                                             auth_factor_type_))) {
      // Create new event if no matching failure event found and updated.
      auto failure_event = std::make_unique<pb::UserEventAtomicVariant>();
      failure_event->mutable_common()->set_create_timestamp_us(
          base::Time::Now().InMillisecondsSinceUnixEpoch() *
          base::Time::kMicrosecondsPerMillisecond);

      auto* authentication =
          failure_event->mutable_failure()->mutable_authentication();
      authentication->set_num_failed_attempts(1);
      FillAuthFactor(authentication);
      OnDeviceUserRetrieved(
          std::move(failure_event),
          device_user_->GetUsernameBasedOnAffiliation(
              completed.username(), completed.sanitized_username()));
    }
  }
}

bool AuthenticationPlugin::FillAuthFactor(pb::Authentication* proto) {
  proto->add_auth_factor(auth_factor_type_);

  return auth_factor_type_ !=
         AuthFactorType::Authentication_AuthenticationType_AUTH_TYPE_UNKNOWN;
}

void AuthenticationPlugin::DelayedCheckForAuthSignal(
    std::unique_ptr<cros_xdr::reporting::UserEventAtomicVariant> xdr_proto,
    cros_xdr::reporting::Authentication* authentication) {
  if (FillAuthFactor(authentication)) {
    // Clear auth factor after it has been set.
    auth_factor_type_ =
        AuthFactorType::Authentication_AuthenticationType_AUTH_TYPE_UNKNOWN;
  }
  device_user_->GetDeviceUserAsync(
      base::BindOnce(&AuthenticationPlugin::OnDeviceUserRetrieved,
                     weak_ptr_factory_.GetWeakPtr(), std::move(xdr_proto)));
}

void AuthenticationPlugin::OnDeviceUserRetrieved(
    std::unique_ptr<pb::UserEventAtomicVariant> atomic_event,
    const std::string& device_user) {
  // Do not set device user for logoff events because it will be empty.
  if (!atomic_event->has_logoff()) {
    atomic_event->mutable_common()->set_device_user(device_user);
  }

  if (atomic_event->has_logon()) {
    if (device_user == device_user::kEmpty) {
      LOG(ERROR) << "Logon does NOT contain a device user";
      signed_in_user_ = device_user::kUnknown;
    } else {
      signed_in_user_ = device_user;
    }
  }

  // Send metric for which auth factor is used.
  auto pair = GetEventEnumTypeAndAuthFactor(*atomic_event.get());
  if (pair.has_value()) {
    MetricsSender::GetInstance().SendEnumMetricToUMA(
        pair.value().first,
        static_cast<metrics::AuthFactor>(pair.value().second));
  }

  // 3P needs the device_user to always be filled for authentication events. If
  // there is no device user fill it with kUnknown.
  if (atomic_event->common().device_user().empty()) {
    atomic_event->mutable_common()->set_device_user(device_user::kUnknown);
  }
  batch_sender_->Enqueue(std::move(atomic_event));
}

void AuthenticationPlugin::OnFirstSessionStart(const std::string& device_user) {
  // When the device_user is empty no user is signed in so do not send a login
  // event.
  // When the device_user is filled there is already a user signed in so a login
  // will be simulated.
  if (!device_user.empty()) {
    OnSessionStateChange(kStarted);
    signed_in_user_ = device_user;
  }
}

}  // namespace secagentd
