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

#include <unistd.h>

#include <list>
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/important_file_writer.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/uuid.h"
#include "bindings/device_management_backend.pb.h"
#include "brillo/errors/error.h"
#include "brillo/files/file_util.h"
#include "cryptohome/proto_bindings/UserDataAuth.pb.h"
#include "policy/device_local_account_policy_util.h"
#include "secagentd/common.h"

namespace secagentd {

DeviceUser::DeviceUser(
    std::unique_ptr<org::chromium::SessionManagerInterfaceProxyInterface>
        session_manager)
    : DeviceUser(std::move(session_manager),
                 std::make_unique<org::chromium::UserDataAuthInterfaceProxy>(
                     common::GetDBus()),
                 base::FilePath("/")) {}

DeviceUser::DeviceUser(
    std::unique_ptr<org::chromium::SessionManagerInterfaceProxyInterface>
        session_manager,
    std::unique_ptr<org::chromium::UserDataAuthInterfaceProxyInterface>
        cryptohome_proxy,
    const base::FilePath& root_path)
    : weak_ptr_factory_(this),
      session_manager_(std::move(session_manager)),
      cryptohome_proxy_(std::move(cryptohome_proxy)),
      root_path_(root_path) {}

void DeviceUser::RegisterSessionChangeHandler() {
  session_manager_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(
          [](org::chromium::SessionManagerInterfaceProxyInterface*
                 session_manager,
             base::WeakPtr<DeviceUser> weak_ptr, bool available) {
            if (!available) {
              LOG(ERROR) << "Failed to register for session_manager's session "
                            "change signal";
              return;
            }
            session_manager->RegisterSessionStateChangedSignalHandler(
                base::BindRepeating(&DeviceUser::OnSessionStateChange,
                                    weak_ptr),
                base::BindOnce(&DeviceUser::OnRegistrationResult, weak_ptr));
            session_manager->GetObjectProxy()->SetNameOwnerChangedCallback(
                base::BindRepeating(&DeviceUser::OnSessionManagerNameChange,
                                    weak_ptr));
          },
          session_manager_.get(), weak_ptr_factory_.GetWeakPtr()));
}

void DeviceUser::RegisterRemoveCompletedHandler() {
  cryptohome_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(
          [](org::chromium::UserDataAuthInterfaceProxyInterface*
                 cryptohome_proxy,
             base::RepeatingCallback<void(
                 const user_data_auth::RemoveCompleted&)> signal_callback,
             dbus::ObjectProxy::OnConnectedCallback on_connected_callback,
             bool available) {
            if (!available) {
              LOG(ERROR) << "Failed to register for RemoveCompleted signal";
              return;
            }
            cryptohome_proxy->RegisterRemoveCompletedSignalHandler(
                std::move(signal_callback), std::move(on_connected_callback));
          },
          cryptohome_proxy_.get(),
          base::BindRepeating(&DeviceUser::OnRemoveCompleted,
                              weak_ptr_factory_.GetWeakPtr()),
          base::BindOnce(&DeviceUser::OnRegistrationResult,
                         weak_ptr_factory_.GetWeakPtr())));
}

void DeviceUser::RegisterScreenLockedHandler(
    base::RepeatingClosure signal_callback,
    dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
  session_manager_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(
          [](org::chromium::SessionManagerInterfaceProxyInterface*
                 session_manager,
             base::RepeatingClosure signal_callback,
             dbus::ObjectProxy::OnConnectedCallback on_connected_callback,
             bool available) {
            if (!available) {
              LOG(ERROR) << "Failed to register for session_manager's screen "
                            "locked signal";
              return;
            }
            session_manager->RegisterScreenIsLockedSignalHandler(
                std::move(signal_callback), std::move(on_connected_callback));
          },
          session_manager_.get(), std::move(signal_callback),
          std::move(on_connected_callback)));
}

void DeviceUser::RegisterScreenUnlockedHandler(
    base::RepeatingClosure signal_callback,
    dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
  session_manager_->GetObjectProxy()->WaitForServiceToBeAvailable(
      base::BindOnce(
          [](org::chromium::SessionManagerInterfaceProxyInterface*
                 session_manager,
             base::RepeatingClosure signal_callback,
             dbus::ObjectProxy::OnConnectedCallback on_connected_callback,
             bool available) {
            if (!available) {
              LOG(ERROR) << "Failed to register for session_manager's screen "
                            "unlocked signal";
              return;
            }
            session_manager->RegisterScreenIsUnlockedSignalHandler(
                std::move(signal_callback), std::move(on_connected_callback));
          },
          session_manager_.get(), std::move(signal_callback),
          std::move(on_connected_callback)));
}

void DeviceUser::RegisterSessionChangeListener(
    base::RepeatingCallback<void(const std::string&)> cb) {
  session_change_listeners_.push_back(std::move(cb));
}

void DeviceUser::OnSessionManagerNameChange(const std::string& old_owner,
                                            const std::string& new_owner) {
  // When session manager crashes it logs user out.
  device_user_ = device_user::kEmpty;

  LOG(INFO) << "Session manager's name changed. Old: " << old_owner
            << " New: " << new_owner;
}

void DeviceUser::GetDeviceUserAsync(
    base::OnceCallback<void(const std::string& device_user)> cb) {
  if (device_user_ready_) {
    std::move(cb).Run(device_user_);
  } else {
    on_device_user_ready_cbs_.push_back(std::move(cb));
  }
}

std::list<std::string> DeviceUser::GetUsernamesForRedaction() {
  return redacted_usernames_;
}

void DeviceUser::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;
    device_user_ = device_user::kUnknown;
  } else if (interface == "org.chromium.SessionManagerInterface" &&
             signal == "SessionStateChanged") {
    OnSessionStateChange(kInit);

    // [DO NOT REMOVE]: Removing or changing this log will break tast testing.
    // Log message that signifies secagentd is listening for session_manager's
    // session state change signal so testing can continue.
    VLOG(1) << "[DO NOT REMOVE] Used for tast testing: Listening for session "
               "state changes";
  }
}

void DeviceUser::OnRemoveCompleted(
    const user_data_auth::RemoveCompleted& remove_completed) {
  if (remove_completed.sanitized_username().empty()) {
    LOG(ERROR) << "RemoveCompleted signal has no username";
    return;
  }

  auto remove_directory = root_path_.Append(kSecagentdDirectory)
                              .Append(remove_completed.sanitized_username());
  if (!brillo::DeletePathRecursively(remove_directory)) {
    LOG(ERROR) << "Failed to delete removed user's affiliation file";
  }
}

void DeviceUser::OnSessionStateChange(const std::string& state) {
  device_user_ready_ = false;
  if (state == kStarted || state == kInit) {
    flush_cb_.Run();
    UpdateDeviceId();
    if (!UpdateDeviceUser(state)) {
      return;
    }
  } else if (state == kStopping) {
    device_user_ = device_user::kEmpty;
  } else if (state == kStopped) {
    device_user_ = device_user::kEmpty;
  }

  device_user_ready_ = true;
  for (auto& cb : on_device_user_ready_cbs_) {
    std::move(cb).Run(device_user_);
  }
  on_device_user_ready_cbs_.clear();

  for (auto cb : session_change_listeners_) {
    cb.Run(state);
  }
}

void DeviceUser::UpdateDeviceId() {
  if (device_id_ != device_user::kEmpty) {
    return;
  }

  auto response = RetrievePolicy(login_manager::ACCOUNT_TYPE_DEVICE, "");
  if (!response.ok()) {
    LOG(ERROR) << response.status();
    return;
  }

  auto device_policy = response.value();
  if (device_policy.device_affiliation_ids_size() >= 1) {
    device_id_ = device_policy.device_affiliation_ids()[0];
    if (device_policy.user_affiliation_ids_size() > 1) {
      // There should only be 1 ID in the list.
      LOG(ERROR) << "Greater than 1 Device ID. Count = "
                 << device_policy.user_affiliation_ids_size();
    }
  }
}

bool DeviceUser::UpdateDeviceUser(const std::string& state) {
  // Check if guest session is active.
  bool is_guest = false;
  brillo::ErrorPtr error;
  if (!session_manager_->IsGuestSessionActive(&is_guest, &error) ||
      error.get()) {
    device_user_ = device_user::kUnknown;
    // Do not exit method because possible that it is user session.
    LOG(ERROR) << "Failed to deterimine if guest session "
               << error->GetMessage();
  } else if (is_guest) {
    device_user_ = device_user::kGuest;
    return true;
  }

  // Retrieve the device username.
  std::string username;
  std::string sanitized;
  if (!session_manager_->RetrievePrimarySession(&username, &sanitized,
                                                &error) ||
      error.get()) {
    device_user_ = device_user::kUnknown;
    LOG(ERROR) << "Failed to retrieve primary session " << error->GetMessage();
    return true;
  } else {
    // No active session.
    if (username.empty()) {
      // Only set as empty when Guest session retrieval succeeds.
      if (device_user_ != device_user::kUnknown) {
        device_user_ = device_user::kEmpty;
      }
      return true;
    }

    // Set the username for redaction.
    if (std::find(redacted_usernames_.begin(), redacted_usernames_.end(),
                  username) == redacted_usernames_.end()) {
      redacted_usernames_.push_front(username);
    }

    if (SetDeviceUserIfLocalAccount(username)) {
      return true;
    }

    // Check if sanitzed username directory exists.
    base::FilePath directory_path =
        root_path_.Append(kSecagentdDirectory).Append(sanitized);
    if (base::DirectoryExists(directory_path)) {
      int64_t file_size;
      std::string uuid;
      if (base::PathExists(directory_path.Append("affiliated"))) {
        device_user_ = username;
        return true;
      } else if (!base::GetFileSize(directory_path.Append("unaffiliated"),
                                    &file_size) ||
                 file_size == 0) {
        LOG(ERROR)
            << "Failed to get username file size. Checking policy instead";
      } else if (!base::ReadFileToString(directory_path.Append("unaffiliated"),
                                         &uuid) ||
                 username.empty()) {
        LOG(ERROR) << "Failed to read uuid. Checking policy instead";
      } else {
        device_user_ = uuid;
        return true;
      }
    }

    // When a user logs in for the first time there is a delay for their
    // ID to be added. Add a slight delay so the ID can appear.
    base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&DeviceUser::HandleUserPolicyAndNotifyListeners,
                       weak_ptr_factory_.GetWeakPtr(), state, username,
                       directory_path),
        base::Seconds(2));
  }

  return false;
}

absl::StatusOr<enterprise_management::PolicyData> DeviceUser::RetrievePolicy(
    login_manager::PolicyAccountType account_type,
    const std::string& account_id) {
  login_manager::PolicyDescriptor descriptor;
  descriptor.set_account_type(account_type);
  descriptor.set_account_id(account_id);
  descriptor.set_domain(login_manager::POLICY_DOMAIN_CHROME);
  std::string account_type_string =
      account_type == login_manager::PolicyAccountType::ACCOUNT_TYPE_DEVICE
          ? "device"
          : "user";

  brillo::ErrorPtr error;
  std::vector<uint8_t> out_blob;
  std::string descriptor_string = descriptor.SerializeAsString();
  if (!session_manager_->RetrievePolicyEx(
          std::vector<uint8_t>(descriptor_string.begin(),
                               descriptor_string.end()),
          &out_blob, &error) ||
      error.get()) {
    return absl::InternalError("Failed to retrieve " + account_type_string +
                               " policy " + error->GetMessage());
  }
  enterprise_management::PolicyFetchResponse response;
  if (!response.ParseFromArray(out_blob.data(), out_blob.size())) {
    return absl::InternalError("Failed to parse policy response for " +
                               account_type_string);
  }

  enterprise_management::PolicyData policy_data;
  if (!policy_data.ParseFromArray(response.policy_data().data(),
                                  response.policy_data().size())) {
    return absl::InternalError("Failed to parse policy data for " +
                               account_type_string);
  }

  return policy_data;
}

bool DeviceUser::IsAffiliated(
    const enterprise_management::PolicyData& user_policy) {
  std::string user_id = "unset";
  if (user_policy.user_affiliation_ids_size() >= 1) {
    user_id = user_policy.user_affiliation_ids()[0];
    if (user_policy.user_affiliation_ids_size() > 1) {
      // There should only be 1 ID in the list.
      LOG(ERROR) << "Greater than 1 User ID. Count = "
                 << user_policy.user_affiliation_ids_size();
    }
  }

  return user_id == device_id_;
}

bool DeviceUser::SetDeviceUserIfLocalAccount(std::string& username) {
  base::expected<DeviceAccountType, policy::GetDeviceLocalAccountTypeError>
      account_type = policy::GetDeviceLocalAccountType(&username);

  if (!account_type.has_value()) {
    return false;
  }

  auto it = local_account_map_.find(account_type.value());
  if (it == local_account_map_.end()) {
    LOG(ERROR) << "Unrecognized local account " << account_type.value();
    device_user_ = device_user::kUnknown;
  } else {
    device_user_ = it->second;
  }

  return true;
}

void DeviceUser::HandleUserPolicyAndNotifyListeners(
    const std::string& state,
    std::string username,
    base::FilePath user_directory) {
  bool directory_exists = false;
  if (base::DirectoryExists(user_directory) ||
      base::CreateDirectory(user_directory)) {
    directory_exists = true;
  } else {
    LOG(ERROR)
        << "Failed to create user directory. Not saving affiliation status.";
  }

  // Retrieve user policy information.
  auto response = RetrievePolicy(login_manager::ACCOUNT_TYPE_USER, username);
  if (!response.ok()) {
    device_user_ = device_user::kUnknown;
    LOG(ERROR) << response.status();
  } else {
    auto policy_data = response.value();

    // Fill in device_user if user is affiliated.
    if (IsAffiliated(policy_data)) {
      device_user_ = username;
      user_directory = user_directory.Append("affiliated");
      // Do not store the real name on the device, just mark as affiliated.
      if (directory_exists &&
          !base::ImportantFileWriter::WriteFileAtomically(user_directory, "")) {
        LOG(ERROR) << "Failed to write username to file";
      }
    } else {
      device_user_ = device_user::kUnaffiliatedPrefix +
                     base::Uuid::GenerateRandomV4().AsLowercaseString();
      user_directory = user_directory.Append("unaffiliated");
      if (directory_exists && !base::ImportantFileWriter::WriteFileAtomically(
                                  user_directory, device_user_)) {
        LOG(ERROR) << "Failed to write username to file";
      }
    }
  }

  device_user_ready_ = true;
  for (auto& cb : on_device_user_ready_cbs_) {
    std::move(cb).Run(device_user_);
  }
  on_device_user_ready_cbs_.clear();

  // Notify listeners.
  for (auto cb : session_change_listeners_) {
    cb.Run(state);
  }
}

bool DeviceUser::GetIsUnaffiliated() {
  // If there is no device user or it is one of the managed local accounts then
  // it is considered affiliated.
  const std::unordered_set<std::string> reporting_values = {
      device_user::kEmpty, device_user::kManagedGuest, device_user::kKioskApp};
  // If the user is unaffiliated their name will be a UUID. If they are
  // affiliated it will be their email which contains the @ symbol.
  return (!reporting_values.contains(device_user_) &&
          device_user_.find("@") == std::string::npos);
}

std::string DeviceUser::GetUsernameBasedOnAffiliation(
    const std::string& username, const std::string& sanitized_username) {
  base::FilePath directory_path =
      root_path_.Append(kSecagentdDirectory).Append(sanitized_username);

  if (base::DirectoryExists(directory_path)) {
    int64_t file_size;
    std::string uuid;
    if (base::PathExists(directory_path.Append("affiliated"))) {
      return username;
    } else if (!base::GetFileSize(directory_path.Append("unaffiliated"),
                                  &file_size) ||
               file_size == 0) {
      LOG(ERROR) << "Failed to get username file size.";
      return device_user::kUnknown;
    } else if (!base::ReadFileToString(directory_path.Append("unaffiliated"),
                                       &uuid) ||
               username.empty()) {
      LOG(ERROR) << "Failed to read uuid.";
      return device_user::kUnknown;
    } else {
      return uuid;
    }
  } else {
    // When a user has never signed into the device before their affiliation
    // cannot be determined. User will be marked as unknown in that case.
    LOG(INFO)
        << "Directory does not exist for user that failed authentication. "
           "Marking as Unknown";
    return device_user::kUnknown;
  }
}

void DeviceUser::SetFlushCallback(base::RepeatingCallback<void()> cb) {
  flush_cb_ = std::move(cb);
}
}  // namespace secagentd
