// 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 <memory>
#include <string>
#include <sysexits.h>
#include <utility>

#include "absl/status/status.h"
#include "attestation-client/attestation/dbus-proxies.h"
#include "base/files/file_path.h"
#include "base/files/file_util.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 "brillo/files/file_util.h"
#include "secagentd/bpf_skeleton_wrappers.h"
#include "secagentd/device_user.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,
    feature::PlatformFeaturesInterface* platform_features,
    bool bypass_policy_for_testing,
    bool bypass_enq_ok_wait_for_testing,
    bool stop_reporting_for_unaffiliated_users,
    uint32_t heartbeat_period_s,
    uint32_t plugin_batch_interval_s,
    uint32_t feature_poll_interval_s_for_testing,
    const base::FilePath& root_path)
    : 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_(platform_features),
      bypass_policy_for_testing_(bypass_policy_for_testing),
      bypass_enq_ok_wait_for_testing_(bypass_enq_ok_wait_for_testing),
      stop_reporting_for_unaffiliated_users_(
          stop_reporting_for_unaffiliated_users),
      heartbeat_period_s_(heartbeat_period_s),
      plugin_batch_interval_s_(plugin_batch_interval_s),
      feature_poll_interval_s_(feature_poll_interval_s_for_testing),
      quit_daemon_cb_(std::move(quit_daemon_cb)),
      root_path_(root_path),
      weak_ptr_factory_(this) {
  policies_features_broker_ = base::MakeRefCounted<PoliciesFeaturesBroker>(
      std::make_unique<policy::PolicyProvider>(), platform_features_,
      base::BindRepeating(&SecAgent::CheckPolicyAndFeature,
                          weak_ptr_factory_.GetWeakPtr()));
}

void SecAgent::Activate() {
  LOG(INFO) << absl::StrFormat(
      "BypassPolicyForTesting:%d,"
      "BypassEnqOkWaitForTesting:%d,StopReportingForUnaffiliatedUsers:%d,"
      "HeartbeatPeriodSeconds:%d,"
      "PluginBatchIntervalSeconds:%d,FeaturePollIntervalSeconds:%d",
      bypass_policy_for_testing_, bypass_enq_ok_wait_for_testing_,
      stop_reporting_for_unaffiliated_users_, heartbeat_period_s_,
      plugin_batch_interval_s_, feature_poll_interval_s_);
  absl::Status result = message_sender_->Initialize();
  if (result != absl::OkStatus()) {
    LOG(ERROR) << result.message();
    std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    return;
  }

  if (stop_reporting_for_unaffiliated_users_) {
    device_user_->SetFlushCallback(base::BindRepeating(
        &SecAgent::FlushAllPluginEvents, weak_ptr_factory_.GetWeakPtr()));
    // The session change listener will indirectly call CheckPolicyAndFeature
    // to start polling.
    device_user_->RegisterSessionChangeListener(base::BindRepeating(
        &SecAgent::OnSessionStateChange, weak_ptr_factory_.GetWeakPtr()));
    device_user_->RegisterSessionChangeHandler();
  } else {
    policies_features_broker_->StartAndBlockForSync(
        base::Seconds(feature_poll_interval_s_));
  }
  // Some BPF maps are pinned for easy sharing between BPF programs.
  std::string_view relative_bpf_pin_path(kDefaultBpfPinDir);
  if (relative_bpf_pin_path.starts_with("/")) {
    relative_bpf_pin_path.remove_prefix(1);
  }

  base::FilePath absolute_bpf_pin_dir =
      root_path_.Append(relative_bpf_pin_path);
  const std::vector<base::FilePath> pinned_map_names{
      base::FilePath("shared_process_info")};
  for (const auto& map_path : pinned_map_names) {
    base::FilePath pinned_map = absolute_bpf_pin_dir.Append(map_path);
    if (base::PathExists(pinned_map)) {
      LOG(INFO) << "Cleaning up " << absolute_bpf_pin_dir.Append(map_path);
      brillo::DeleteFile(absolute_bpf_pin_dir.Append(map_path));
    }
  }
  process_cache_->InitializeFilter();
}

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 (first_visit) {
    LOG(INFO) << "DeviceReportXDREventsPolicy: " << xdr_reporting_policy
              << (bypass_policy_for_testing_ ? " (set by flag)" : "");
    LOG(INFO) << "CrOSLateBootSecagentdXDRReporting: " << xdr_reporting_feature;
  }

  stop_reporting_for_unaffiliated_users_ =
      policies_features_broker_->GetFeature(
          PoliciesFeaturesBroker::Feature::
              kCrosLateBootSecagentdXDRStopReportingForUnaffiliated);
  if (stop_reporting_for_unaffiliated_users_ &&
      device_user_->GetIsUnaffiliated() && !reporting_events_) {
    if (first_visit) {
      LOG(INFO) << "Not starting reporting because unaffiliated user signed in";
    }
    return;
  }

  // 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 (reporting_events_ && xdr_reporting_feature &&
             xdr_reporting_policy) {
    // BPF plugins were activated in the past. Repoll features and
    // activate/deactivate relevant plugins.
    ActivateOrDeactivatePlugins();
  } else if (first_visit) {
    LOG(INFO) << "Not reporting yet.";
  }

  // Else do nothing until the next poll.
  first_visit = false;
}

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

  using CbType = base::OnceCallback<void()>;
  CbType cb_for_agent = base::BindOnce(&SecAgent::CreateAndActivatePlugins,
                                       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::ActivateOrDeactivatePlugins() {
  absl::Status result;
  std::string action;
  auto activate = [&action](PluginConfig& pc) {
    if (!pc.plugin->IsActive()) {
      action = "activated";
      return pc.plugin->Activate();
    }
    return absl::OkStatus();
  };
  auto deactivate = [&action](PluginConfig& pc) {
    if (pc.plugin->IsActive()) {
      action = "deactivated";
      return pc.plugin->Deactivate();
    }
    return absl::OkStatus();
  };

  for (auto& plugin_config : plugins_) {
    auto& feature = plugin_config.gated_by_feature;
    auto& plugin = plugin_config.plugin;
    action = "";
    if (feature.has_value()) {
      // The plugin is gated by a feature.
      if (policies_features_broker_->GetFeature(feature.value())) {
        result = activate(plugin_config);
      } else {
        result = deactivate(plugin_config);
      }
    } else {
      result = activate(plugin_config);
    }
    if (!result.ok()) {
      LOG(ERROR) << result.message();
    } else if (!action.empty()) {
      LOG(INFO) << plugin->GetName() << " plugin " << action;
    }
  }
}

void SecAgent::CreateAndActivatePlugins() {
  using Feature = PoliciesFeaturesBrokerInterface::Feature;
  using Plugin = Types::Plugin;
  static const std::vector<std::pair<Plugin, std::optional<Feature>>> plugins =
      {std::make_pair(
           Plugin::kAuthenticate,
           std::optional(Feature::kCrOSLateBootSecagentdXDRAuthenticateEvents)),
       std::make_pair(
           Plugin::kNetwork,
           std::optional(Feature::kCrOSLateBootSecagentdXDRNetworkEvents)),
       std::make_pair(Plugin::kProcess, std::nullopt)};
  std::unique_ptr<PluginInterface> plugin;
  for (const auto& p : plugins) {
    plugin = plugin_factory_->Create(p.first, message_sender_, process_cache_,
                                     policies_features_broker_, device_user_,
                                     plugin_batch_interval_s_);
    if (!plugin) {
      std::move(quit_daemon_cb_).Run(EX_SOFTWARE);
    }
    plugins_.push_back({p.second, std::move(plugin)});
  }
  ActivateOrDeactivatePlugins();
}

void SecAgent::OnSessionStateChange(const std::string& state) {
  static bool started_polling = false;

  // Make sure device user is updated before starting reporting.
  if (!started_polling) {
    policies_features_broker_->StartAndBlockForSync(
        base::Seconds(feature_poll_interval_s_));
    started_polling = true;
  }

  if (stop_reporting_for_unaffiliated_users_) {
    device_user_->GetDeviceUserAsync(base::BindOnce(
        &SecAgent::OnDeviceUserRetrieved, weak_ptr_factory_.GetWeakPtr()));
  }
}

void SecAgent::OnDeviceUserRetrieved(const std::string& user) {
  if (reporting_events_) {
    if (device_user_->GetIsUnaffiliated()) {
      LOG(INFO) << "Stopping reporting: Unaffiliated user signed in";
      std::move(quit_daemon_cb_).Run(EX_OK);
    }
  } else {
    CheckPolicyAndFeature();
  }
}

void SecAgent::FlushAllPluginEvents() {
  for (auto& plugin : plugins_) {
    plugin.plugin->Flush();
  }
}

}  // namespace secagentd
