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

#include <unistd.h>

#include <cstdlib>
#include <iomanip>
#include <memory>
#include <string>
#include <sysexits.h>
#include <utility>

#include "absl/status/status.h"
#include "attestation-client/attestation/dbus-proxies.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "brillo/daemons/daemon.h"
#include "brillo/daemons/dbus_daemon.h"
#include "missive/client/missive_client.h"
#include "secagentd/daemon.h"
#include "secagentd/message_sender.h"
#include "secagentd/metrics_sender.h"
#include "secagentd/plugins.h"
#include "secagentd/policies_features_broker.h"
#include "secagentd/process_cache.h"

namespace secagentd {

SecAgent::SecAgent(
    base::OnceCallback<void(int)> quit_daemon_cb,
    scoped_refptr<MessageSenderInterface> message_sender,
    scoped_refptr<ProcessCacheInterface> process_cache,
    scoped_refptr<DeviceUserInterface> device_user,
    std::unique_ptr<PluginFactoryInterface> plugin_factory,
    std::unique_ptr<org::chromium::AttestationProxyInterface> attestation_proxy,
    std::unique_ptr<org::chromium::TpmManagerProxyInterface> tpm_proxy,
    std::unique_ptr<feature::PlatformFeaturesInterface> platform_features,
    bool bypass_policy_for_testing,
    bool bypass_enq_ok_wait_for_testing,
    uint32_t heartbeat_period_s,
    uint32_t plugin_batch_interval_s)
    : message_sender_(message_sender),
      process_cache_(process_cache),
      device_user_(device_user),
      plugin_factory_(std::move(plugin_factory)),
      attestation_proxy_(std::move(attestation_proxy)),
      tpm_proxy_(std::move(tpm_proxy)),
      platform_features_(std::move(platform_features)),
      bypass_policy_for_testing_(bypass_policy_for_testing),
      bypass_enq_ok_wait_for_testing_(bypass_enq_ok_wait_for_testing),
      heartbeat_period_s_(heartbeat_period_s),
      plugin_batch_interval_s_(plugin_batch_interval_s),
      quit_daemon_cb_(std::move(quit_daemon_cb)),
      weak_ptr_factory_(this) {
  policies_features_broker_ = base::MakeRefCounted<PoliciesFeaturesBroker>(
      std::make_unique<policy::PolicyProvider>(), std::move(platform_features_),
      base::BindRepeating(&SecAgent::CheckPolicyAndFeature,
                          weak_ptr_factory_.GetWeakPtr()));
}

void SecAgent::Activate() {
  absl::Status result = message_sender_->Initialize();
  if (result != absl::OkStatus()) {
    LOG(ERROR) << result.message();
    std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    return;
  }

  process_cache_->InitializeFilter();

  // This will post a task to run CheckPolicyAndFeature.
  policies_features_broker_->StartAndBlockForSync(
      PoliciesFeaturesBroker::kDefaultPollDuration);
}

void SecAgent::CheckPolicyAndFeature() {
  static bool first_visit = true;
  bool xdr_reporting_policy =
      policies_features_broker_->GetDeviceReportXDREventsPolicy() ||
      bypass_policy_for_testing_;
  bool xdr_reporting_feature = policies_features_broker_->GetFeature(
      PoliciesFeaturesBroker::Feature::kCrOSLateBootSecagentdXDRReporting);
  // If either policy is false do not report.
  if (reporting_events_ && !(xdr_reporting_feature && xdr_reporting_policy)) {
    LOG(INFO) << "Stopping event reporting and quitting. Policy: "
              << std::to_string(xdr_reporting_policy)
              << " Feature: " << std::to_string(xdr_reporting_feature);
    reporting_events_ = false;
    // Will exit and restart secagentd.
    std::move(quit_daemon_cb_).Run(EX_OK);
    return;
  } else if (!reporting_events_ &&
             (xdr_reporting_feature && xdr_reporting_policy)) {
    LOG(INFO) << "Starting event reporting";
    // This is emitted at most once per daemon lifetime.
    MetricsSender::GetInstance().SendEnumMetricToUMA(metrics::kPolicy,
                                                     metrics::Policy::kEnabled);
    reporting_events_ = true;
    StartXDRReporting();
  } else if (first_visit) {
    LOG(INFO) << "Not reporting yet.";
    LOG(INFO) << "DeviceReportXDREventsPolicy: " << xdr_reporting_policy
              << (bypass_policy_for_testing_ ? " (set by flag)" : "");
    LOG(INFO) << "CrOSLateBootSecagentdXDRReporting: " << xdr_reporting_feature;
  }
  // Else do nothing until the next poll.
  first_visit = false;
}

void SecAgent::StartXDRReporting() {
  device_user_->RegisterSessionChangeHandler();
  MetricsSender::GetInstance().InitBatchedMetrics();

  using CbType = base::OnceCallback<void()>;
  CbType cb_for_agent =
      base::BindOnce(&SecAgent::RunPlugins, weak_ptr_factory_.GetWeakPtr());
  CbType cb_for_now = base::DoNothing();
  if (bypass_enq_ok_wait_for_testing_) {
    std::swap(cb_for_agent, cb_for_now);
  }
  agent_plugin_ = plugin_factory_->CreateAgentPlugin(
      message_sender_, device_user_, std::move(attestation_proxy_),
      std::move(tpm_proxy_), std::move(cb_for_agent), heartbeat_period_s_);
  if (!agent_plugin_) {
    std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    return;
  }

  absl::Status result = agent_plugin_->Activate();
  if (!result.ok()) {
    LOG(ERROR) << result.message();
    std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    return;
  }

  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, std::move(cb_for_now));
}

void SecAgent::RunPlugins() {
  if (CreatePlugin(Types::Plugin::kProcess) != EX_OK) {
    std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    return;
  }

  for (auto& plugin : plugins_) {
    absl::Status result = plugin->Activate();
    if (!result.ok()) {
      LOG(ERROR) << result.message();
      std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
      return;
    }
  }
}

int SecAgent::CreatePlugin(Types::Plugin type) {
  std::unique_ptr<PluginInterface> plugin;
  switch (type) {
    case Types::Plugin::kProcess: {
      plugin = plugin_factory_->Create(
          Types::Plugin::kProcess, message_sender_, process_cache_,
          policies_features_broker_, device_user_, plugin_batch_interval_s_);
      break;
    }
    default:
      CHECK(false) << "Unsupported plugin type";
  }

  if (!plugin) {
    return EX_SOFTWARE;
  }
  plugins_.push_back(std::move(plugin));
  return EX_OK;
}

}  // namespace secagentd
