// Copyright 2016 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 "authpolicy/authpolicy.h"

#include <unordered_set>
#include <utility>
#include <vector>

#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread_task_runner_handle.h>
#include <dbus/authpolicy/dbus-constants.h>
#include <login_manager/proto_bindings/policy_descriptor.pb.h>

#include "authpolicy/authpolicy_metrics.h"
#include "authpolicy/cryptohome_client.h"
#include "authpolicy/log_colors.h"
#include "authpolicy/path_service.h"
#include "authpolicy/proto_bindings/active_directory_info.pb.h"
#include "authpolicy/samba_helper.h"
#include "authpolicy/samba_interface.h"
#include "authpolicy/session_manager_client.h"
#include "bindings/device_management_backend.pb.h"

namespace em = enterprise_management;

using brillo::dbus_utils::DBusObject;
using login_manager::PolicyDescriptor;

namespace authpolicy {

constexpr char kChromeUserPolicyType[] = "google/chromeos/user";
constexpr char kChromeDevicePolicyType[] = "google/chromeos/device";
constexpr char kChromeExtensionPolicyType[] = "google/chrome/extension";

namespace {

// Returns true if the given |domain| is expected to be associated with a
// component id in PolicyDescriptor, e.g. an extension id for
// POLICY_DOMAIN_EXTENSIONS.
bool DomainRequiresComponentId(login_manager::PolicyDomain domain) {
  switch (domain) {
    case login_manager::POLICY_DOMAIN_CHROME:
      return false;
    case login_manager::POLICY_DOMAIN_EXTENSIONS:
    case login_manager::POLICY_DOMAIN_SIGNIN_EXTENSIONS:
      // The component id is the extension id.
      return true;
  }
  NOTREACHED() << "Invalid domain";
}

void PrintResult(const char* msg, ErrorType error) {
  if (error == ERROR_NONE) {
    LOG(INFO) << kColorRequestSuccess << msg << " succeeded" << kColorReset;
  } else {
    LOG(INFO) << kColorRequestFail << msg << " failed with code " << error
              << kColorReset;
  }
}

ErrorMetricType GetPolicyErrorMetricType(bool is_refresh_user_policy) {
  return is_refresh_user_policy ? ERROR_OF_REFRESH_USER_POLICY
                                : ERROR_OF_REFRESH_DEVICE_POLICY;
}

// Serializes |proto| to a vector of bytes. CHECKs for success (should
// never fail if there are no required proto fields).
std::vector<uint8_t> SerializeProto(
    const google::protobuf::MessageLite& proto) {
  std::vector<uint8_t> proto_blob(proto.ByteSizeLong());
  CHECK(proto.SerializeToArray(proto_blob.data(), proto_blob.size()));
  return proto_blob;
}

WARN_UNUSED_RESULT ErrorType
ParseProto(google::protobuf::MessageLite* proto,
           const std::vector<uint8_t>& proto_blob) {
  if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
    LOG(ERROR) << "Failed to parse proto";
    return ERROR_PARSE_FAILED;
  }
  return ERROR_NONE;
}

}  // namespace

// Tracks responses from D-Bus calls to Session Manager's StorePolicy during a
// Refresh*Policy call to AuthPolicy. StorePolicy is called N + 1 times (once
// for the main user/device policy and N times for extension policies, once per
// extension). The Refresh*Policy response callback is only called after all
// StorePolicy responses have been received. This class counts the responses and
// calls the Refresh*Policy response callback after the last response has been
// received. For tracking purposes, a failure to call StorePolicy (e.g. since
// parameters failed to serialize) counts as received response.
class ResponseTracker : public base::RefCountedThreadSafe<ResponseTracker> {
 public:
  ResponseTracker(bool is_refresh_user_policy,
                  int total_response_count,
                  AuthPolicyMetrics* metrics,
                  std::unique_ptr<ScopedTimerReporter> timer,
                  AuthPolicy::PolicyResponseCallback callback)
      : is_refresh_user_policy_(is_refresh_user_policy),
        outstanding_response_count_(total_response_count),
        metrics_(metrics),
        timer_(std::move(timer)),
        callback_(std::move(callback)) {}

  // Should be called when a response finished either successfully or not or if
  // the corresponding StorePolicy call was never made, e.g. due to an error on
  // call parameter setup. If |error_message| is empty, assumes that the
  // StorePolicy call succeeded.
  void OnResponseFinished(bool success) {
    if (!success)
      all_responses_succeeded_ = false;

    // Don't use DCHECK here since bad policy store call counting could have
    // security implications.
    CHECK_GT(outstanding_response_count_, 0);
    if (--outstanding_response_count_ == 0) {
      // This is the last response, call the callback.
      const ErrorMetricType metric_type =
          GetPolicyErrorMetricType(is_refresh_user_policy_);
      ErrorType error =
          all_responses_succeeded_ ? ERROR_NONE : ERROR_STORE_POLICY_FAILED;
      metrics_->ReportError(metric_type, error);
      callback_->Return(error);

      const char* request =
          is_refresh_user_policy_ ? "RefreshUserPolicy" : "RefreshDevicePolicy";
      PrintResult(request, error);

      // Destroy the timer, which triggers the metric. It's going to be
      // destroyed with this instance, anyway, but doing it here explicitly is
      // easier to follow.
      timer_.reset();
    }
  }

 private:
  bool is_refresh_user_policy_;
  int outstanding_response_count_;
  AuthPolicyMetrics* metrics_;  // Not owned.
  std::unique_ptr<ScopedTimerReporter> timer_;
  AuthPolicy::PolicyResponseCallback callback_;
  bool all_responses_succeeded_ = true;
};

// static
std::unique_ptr<DBusObject> AuthPolicy::GetDBusObject(
    brillo::dbus_utils::ExportedObjectManager* object_manager) {
  return std::make_unique<DBusObject>(
      object_manager, object_manager->GetBus(),
      org::chromium::AuthPolicyAdaptor::GetObjectPath());
}

AuthPolicy::AuthPolicy(AuthPolicyMetrics* metrics,
                       const PathService* path_service)
    : org::chromium::AuthPolicyAdaptor(this),
      metrics_(metrics),
      samba_(metrics,
             path_service,
             base::Bind(&AuthPolicy::OnUserKerberosFilesChanged,
                        base::Unretained(this))) {}

AuthPolicy::~AuthPolicy() = default;

ErrorType AuthPolicy::Initialize(bool device_is_locked) {
  device_is_locked_ = device_is_locked;
  return samba_.Initialize(device_is_locked_ /* expect_config */);
}

void AuthPolicy::RegisterAsync(
    std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object,
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
        completion_callback) {
  DCHECK(!dbus_object_);
  dbus_object_ = std::move(dbus_object);

  // Make sure the task runner used in some places is actually the D-Bus task
  // runner. This guarantees that tasks scheduled on the task runner won't
  // interfere with D-Bus calls.
  CHECK_EQ(base::ThreadTaskRunnerHandle::Get(),
           dbus_object_->GetBus()->GetDBusTaskRunner());
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);

  session_manager_client_ =
      std::make_unique<SessionManagerClient>(dbus_object_.get());

  // Listen to session state changes for backing up user TGT and other data.
  session_manager_client_->ConnectToSessionStateChangedSignal(base::Bind(
      &SambaInterface::OnSessionStateChanged, base::Unretained(&samba_)));

  // Set proper session state.
  samba_.OnSessionStateChanged(session_manager_client_->RetrieveSessionState());

  // Give Samba access to Cryptohome.
  samba_.SetCryptohomeClient(
      std::make_unique<CryptohomeClient>(dbus_object_.get()));
}

void AuthPolicy::AuthenticateUser(
    AuthenticateUserResponseCallback callback,
    const std::vector<uint8_t>& auth_user_request_blob,
    const base::ScopedFD& password_fd) {
  LOG(INFO) << kColorRequest << "Received 'AuthenticateUser' request"
            << kColorReset;
  ScopedTimerReporter timer(TIMER_AUTHENTICATE_USER);
  authpolicy::AuthenticateUserRequest request;
  ErrorType error = ParseProto(&request, auth_user_request_blob);

  ActiveDirectoryAccountInfo account_info;
  if (error == ERROR_NONE) {
    error = samba_.AuthenticateUser(request.user_principal_name(),
                                    request.account_id(), password_fd.get(),
                                    &account_info);
  }

  std::vector<uint8_t> account_info_blob;
  if (error == ERROR_NONE)
    account_info_blob = SerializeProto(account_info);

  PrintResult("AuthenticateUser", error);
  metrics_->ReportError(ERROR_OF_AUTHENTICATE_USER, error);
  callback->Return(static_cast<int>(error), std::move(account_info_blob));

  // Kick off the user affiliation check after responding, so that it can be
  // done in parallel to Chrome startup. The affiliation flag is not needed
  // until user policy fetch.
  if (error == ERROR_NONE)
    samba_.UpdateUserAffiliation();
}

void AuthPolicy::GetUserStatus(
    const std::vector<uint8_t>& get_status_request_blob,
    int32_t* int_error,
    std::vector<uint8_t>* user_status_blob) {
  LOG(INFO) << kColorRequest << "Received 'GetUserStatus' request"
            << kColorReset;
  ScopedTimerReporter timer(TIMER_GET_USER_STATUS);
  authpolicy::GetUserStatusRequest request;
  ErrorType error = ParseProto(&request, get_status_request_blob);

  ActiveDirectoryUserStatus user_status;
  if (error == ERROR_NONE) {
    error = samba_.GetUserStatus(request.user_principal_name(),
                                 request.account_id(), &user_status);
  }
  if (error == ERROR_NONE)
    *user_status_blob = SerializeProto(user_status);

  PrintResult("GetUserStatus", error);
  metrics_->ReportError(ERROR_OF_GET_USER_STATUS, error);
  *int_error = static_cast<int>(error);
}

void AuthPolicy::GetUserKerberosFiles(
    const std::string& account_id,
    int32_t* int_error,
    std::vector<uint8_t>* kerberos_files_blob) {
  LOG(INFO) << kColorRequest << "Received 'GetUserKerberosFiles' request"
            << kColorReset;
  ScopedTimerReporter timer(TIMER_GET_USER_KERBEROS_FILES);

  KerberosFiles kerberos_files;
  ErrorType error = samba_.GetUserKerberosFiles(account_id, &kerberos_files);
  if (error == ERROR_NONE)
    *kerberos_files_blob = SerializeProto(kerberos_files);
  PrintResult("GetUserKerberosFiles", error);
  metrics_->ReportError(ERROR_OF_GET_USER_KERBEROS_FILES, error);
  *int_error = static_cast<int>(error);
}

void AuthPolicy::JoinADDomain(
    const std::vector<uint8_t>& join_domain_request_blob,
    const base::ScopedFD& password_fd,
    int32_t* int_error,
    std::string* joined_domain) {
  LOG(INFO) << kColorRequest << "Received 'JoinADDomain' request"
            << kColorReset;
  ScopedTimerReporter timer(TIMER_JOIN_AD_DOMAIN);

  JoinDomainRequest request;
  ErrorType error = ParseProto(&request, join_domain_request_blob);

  if (error == ERROR_NONE) {
    std::vector<std::string> machine_ou(request.machine_ou().begin(),
                                        request.machine_ou().end());

    error = samba_.JoinMachine(request.machine_name(), request.machine_domain(),
                               machine_ou, request.user_principal_name(),
                               request.kerberos_encryption_types(),
                               password_fd.get(), joined_domain);
  }

  PrintResult("JoinADDomain", error);
  metrics_->ReportError(ERROR_OF_JOIN_AD_DOMAIN, error);
  *int_error = static_cast<int>(error);
}

void AuthPolicy::RefreshUserPolicy(PolicyResponseCallback callback,
                                   const std::string& account_id) {
  LOG(INFO) << kColorRequest << "Received 'RefreshUserPolicy' request"
            << kColorReset;
  auto timer = std::make_unique<ScopedTimerReporter>(TIMER_REFRESH_USER_POLICY);

  // Fetch GPOs for the current user.
  auto gpo_policy_data = std::make_unique<protos::GpoPolicyData>();
  ErrorType error = samba_.FetchUserGpos(account_id, gpo_policy_data.get());

  // Return immediately on error.
  if (error != ERROR_NONE) {
    PrintResult("RefreshUserPolicy", error);
    metrics_->ReportError(ERROR_OF_REFRESH_USER_POLICY, error);
    callback->Return(error);
    return;
  }

  // Send policy to Session Manager.
  const std::string account_id_key = GetAccountIdKey(account_id);
  StorePolicy(std::move(gpo_policy_data), &account_id_key, std::move(timer),
              std::move(callback));
}

void AuthPolicy::RefreshDevicePolicy(PolicyResponseCallback callback) {
  LOG(INFO) << kColorRequest << "Received 'RefreshDevicePolicy' request"
            << kColorReset;
  auto timer =
      std::make_unique<ScopedTimerReporter>(TIMER_REFRESH_DEVICE_POLICY);

  if (cached_device_policy_data_) {
    // Send policy to Session Manager.
    LOG(INFO) << "Using cached policy";
    StorePolicy(std::move(cached_device_policy_data_), nullptr,
                std::move(timer), std::move(callback));
    return;
  }

  // Fetch GPOs for the device.
  auto gpo_policy_data = std::make_unique<protos::GpoPolicyData>();
  ErrorType error = samba_.FetchDeviceGpos(gpo_policy_data.get());

  device_is_locked_ = device_is_locked_ || InstallAttributesReader().IsLocked();
  if (!device_is_locked_ && error == ERROR_NONE) {
    LOG(INFO) << "Device is not locked yet. Caching device policy.";
    cached_device_policy_data_ = std::move(gpo_policy_data);
    error = ERROR_DEVICE_POLICY_CACHED_BUT_NOT_SENT;
  }

  // Return immediately on error.
  if (error != ERROR_NONE) {
    PrintResult("RefreshDevicePolicy", error);
    metrics_->ReportError(ERROR_OF_REFRESH_DEVICE_POLICY, error);
    callback->Return(error);
    return;
  }

  // Send policy to Session Manager.
  StorePolicy(std::move(gpo_policy_data), nullptr, std::move(timer),
              std::move(callback));
}

std::string AuthPolicy::SetDefaultLogLevel(int32_t level) {
  LOG(INFO) << kColorRequest << "Received 'SetDefaultLogLevel' request"
            << kColorReset;
  if (level < AuthPolicyFlags::kMinLevel ||
      level > AuthPolicyFlags::kMaxLevel) {
    std::string message = base::StringPrintf("Level must be between %i and %i.",
                                             AuthPolicyFlags::kMinLevel,
                                             AuthPolicyFlags::kMaxLevel);
    LOG(ERROR) << message;
    return message;
  }
  samba_.SetDefaultLogLevel(static_cast<AuthPolicyFlags::DefaultLevel>(level));
  return std::string();
}

int32_t AuthPolicy::ChangeMachinePasswordForTesting() {
  return samba_.ChangeMachinePasswordForTesting();
}

void AuthPolicy::OnUserKerberosFilesChanged() {
  LOG(INFO) << "Firing signal UserKerberosFilesChanged";
  SendUserKerberosFilesChangedSignal();
}

void AuthPolicy::StorePolicy(
    std::unique_ptr<protos::GpoPolicyData> gpo_policy_data,
    const std::string* account_id_key,
    std::unique_ptr<ScopedTimerReporter> timer,
    PolicyResponseCallback callback) {
  // Build descriptor that specifies where the policy is stored.
  PolicyDescriptor descriptor;
  const bool is_refresh_user_policy = account_id_key != nullptr;
  const char* policy_type = nullptr;
  if (is_refresh_user_policy) {
    DCHECK(!account_id_key->empty());
    descriptor.set_account_type(login_manager::ACCOUNT_TYPE_USER);
    descriptor.set_account_id(*account_id_key);
    policy_type = kChromeUserPolicyType;
  } else {
    descriptor.set_account_type(login_manager::ACCOUNT_TYPE_DEVICE);
    policy_type = kChromeDevicePolicyType;
  }

  // Query IDs of extension policy stored by Session Manager.
  descriptor.set_domain(login_manager::POLICY_DOMAIN_EXTENSIONS);
  std::vector<std::string> existing_extension_ids;
  if (!session_manager_client_->ListStoredComponentPolicies(
          SerializeProto(descriptor), &existing_extension_ids)) {
    // If this call fails, worst thing that can happen is stale extension
    // policy. Still seems better than not pushing policy at all, so keep going.
    existing_extension_ids.clear();
    LOG(WARNING) << "Cannot clean up stale extension policies: "
                    "Failed to get list of stored extension policies.";
  }

  // Extension policies that are no longer coming down from Active Directory
  // have to be deleted. Those are (IDs in Session Manager) - (IDs from AD).
  std::unordered_set<std::string> extension_ids_to_delete;
  extension_ids_to_delete.insert(existing_extension_ids.begin(),
                                 existing_extension_ids.end());
  for (int n = 0; n < gpo_policy_data->extension_policies_size(); ++n)
    extension_ids_to_delete.erase(gpo_policy_data->extension_policies(n).id());

  // Count total number of StorePolicy responses we're expecting and create a
  // tracker object that counts the number of outstanding responses and keeps
  // some unique pointers.
  const int num_extensions_to_store =
      gpo_policy_data->extension_policies_size();
  const int num_extensions_to_delete =
      static_cast<int>(extension_ids_to_delete.size());
  const int num_store_policy_calls =
      1 + num_extensions_to_store + num_extensions_to_delete;
  LOG(INFO) << "Sending " << (is_refresh_user_policy ? "user" : "device")
            << " policy to Session Manager (Chrome policy, "
            << num_extensions_to_store << " extensions). Deleting "
            << num_extensions_to_delete << " stale extensions.";

  scoped_refptr<ResponseTracker> response_tracker =
      new ResponseTracker(is_refresh_user_policy, num_store_policy_calls,
                          metrics_, std::move(timer), std::move(callback));

  // For double checking we counted the number of store calls right.
  int store_policy_call_count = 0;

  // Store the user or device policy.
  descriptor.set_domain(login_manager::POLICY_DOMAIN_CHROME);
  StoreSinglePolicy(descriptor, policy_type,
                    &gpo_policy_data->user_or_device_policy(),
                    response_tracker);
  store_policy_call_count++;

  // Store extension policies.
  descriptor.set_domain(login_manager::POLICY_DOMAIN_EXTENSIONS);
  for (int n = 0; n < num_extensions_to_store; ++n) {
    const protos::ExtensionPolicy& extension_policy =
        gpo_policy_data->extension_policies(n);
    descriptor.set_component_id(extension_policy.id());
    StoreSinglePolicy(descriptor, kChromeExtensionPolicyType,
                      &extension_policy.json_data(), response_tracker);
    store_policy_call_count++;
  }

  // Remove policies for extensions that are no longer coming down from AD.
  descriptor.set_domain(login_manager::POLICY_DOMAIN_EXTENSIONS);
  for (const std::string& extension_id : extension_ids_to_delete) {
    descriptor.set_component_id(extension_id);
    StoreSinglePolicy(descriptor, kChromeExtensionPolicyType,
                      nullptr /* policy_blob */, response_tracker);
    store_policy_call_count++;
  }

  // Don't use DCHECK here since bad policy store call counting could have
  // security implications.
  CHECK(store_policy_call_count == num_store_policy_calls);
}

void AuthPolicy::StoreSinglePolicy(
    const PolicyDescriptor& descriptor,
    const char* policy_type,
    const std::string* policy_blob,
    scoped_refptr<ResponseTracker> response_tracker) {
  // Sending an empty response_blob deletes the policy.
  if (!policy_blob) {
    session_manager_client_->StoreUnsignedPolicyEx(
        SerializeProto(descriptor), std::vector<uint8_t>() /* response_blob */,
        base::Bind(&ResponseTracker::OnResponseFinished, response_tracker));
    return;
  }
  // Wrap up the policy in a PolicyFetchResponse.
  em::PolicyData policy_data;
  policy_data.set_policy_value(*policy_blob);
  policy_data.set_policy_type(policy_type);
  if (descriptor.account_type() == login_manager::ACCOUNT_TYPE_USER) {
    policy_data.set_username(samba_.GetUserPrincipal());
    // Device id in the proto also could be used as an account/client id.
    policy_data.set_device_id(samba_.user_account_id());
    if (samba_.is_user_affiliated())
      policy_data.add_user_affiliation_ids(kAffiliationMarker);
  } else {
    DCHECK(descriptor.account_type() == login_manager::ACCOUNT_TYPE_DEVICE);
    policy_data.set_device_id(samba_.machine_name());
    policy_data.add_device_affiliation_ids(kAffiliationMarker);
  }

  // TODO(crbug.com/831995): Use timer that can never run backwards and enable
  // timestamp validation in the Chromium Active Directory policy manager.
  policy_data.set_timestamp(base::Time::Now().ToJavaTime());
  policy_data.set_management_mode(em::PolicyData::ENTERPRISE_MANAGED);
  policy_data.set_machine_name(samba_.machine_name());
  if (DomainRequiresComponentId(descriptor.domain())) {
    DCHECK(!descriptor.component_id().empty());
    policy_data.set_settings_entity_id(descriptor.component_id());
  }

  // Note: No signature required here, Active Directory policy is unsigned!

  em::PolicyFetchResponse policy_response;
  if (!policy_data.SerializeToString(policy_response.mutable_policy_data())) {
    LOG(ERROR) << "Failed to serialize policy data";
    response_tracker->OnResponseFinished(false);
    return;
  }

  session_manager_client_->StoreUnsignedPolicyEx(
      SerializeProto(descriptor), SerializeProto(policy_response),
      base::Bind(&ResponseTracker::OnResponseFinished, response_tracker));
}

}  // namespace authpolicy
