// 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 <utility>
#include <vector>

#include <base/memory/ptr_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread_task_runner_handle.h>
#include <brillo/dbus/dbus_method_invoker.h>
#include <dbus/authpolicy/dbus-constants.h>
#include <dbus/login_manager/dbus-constants.h>

#include "authpolicy/authpolicy_metrics.h"
#include "authpolicy/path_service.h"
#include "authpolicy/proto_bindings/active_directory_info.pb.h"
#include "authpolicy/samba_interface.h"
#include "bindings/device_management_backend.pb.h"

namespace em = enterprise_management;

using brillo::dbus_utils::DBusObject;
using brillo::dbus_utils::ExtractMethodCallResults;

namespace authpolicy {

const char kChromeUserPolicyType[] = "google/chromeos/user";
const char kChromeDevicePolicyType[] = "google/chromeos/device";

namespace {

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

const char* GetSessionManagerStoreMethod(bool is_user_policy) {
  return is_user_policy
             ? login_manager::kSessionManagerStoreUnsignedPolicyForUser
             : login_manager::kSessionManagerStoreUnsignedPolicy;
}

DBusCallType GetPolicyDBusCallType(bool is_user_policy) {
  return is_user_policy ? DBUS_CALL_REFRESH_USER_POLICY
                        : DBUS_CALL_REFRESH_DEVICE_POLICY;
}

}  // namespace

// static
std::unique_ptr<DBusObject> AuthPolicy::GetDBusObject(
    brillo::dbus_utils::ExportedObjectManager* object_manager) {
  return base::MakeUnique<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_(base::ThreadTaskRunnerHandle::Get(), metrics, path_service),
      weak_ptr_factory_(this) {}

ErrorType AuthPolicy::Initialize(bool expect_config) {
  return samba_.Initialize(expect_config);
}

void AuthPolicy::RegisterAsync(
    std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object,
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  DCHECK(!dbus_object_);
  dbus_object_ = std::move(dbus_object);
  // Make sure the task runner passed to |samba_| in the constructor is actually
  // the D-Bus task runner. This guarantees that automatic TGT renewal won't
  // interfere with D-Bus calls. Note that |GetDBusTaskRunner()| returns a
  // TaskRunner, which is a base class of SingleThreadTaskRunner accepted by
  // |samba_|.
  CHECK_EQ(base::ThreadTaskRunnerHandle::Get(),
           dbus_object_->GetBus()->GetDBusTaskRunner());
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);
  session_manager_proxy_ = dbus_object_->GetBus()->GetObjectProxy(
      login_manager::kSessionManagerServiceName,
      dbus::ObjectPath(login_manager::kSessionManagerServicePath));
  DCHECK(session_manager_proxy_);
}

void AuthPolicy::AuthenticateUser(dbus::MethodCall* method_call,
                                  brillo::dbus_utils::ResponseSender sender) {
  // Read input arguments.
  std::string user_principal_name;
  std::string account_id;
  dbus::FileDescriptor password_fd;
  dbus::MessageReader reader(method_call);
  bool success = reader.PopString(&user_principal_name);
  if (success)
    reader.PopString(&account_id);  // Optional, ignore return value!
  success = success && reader.PopFileDescriptor(&password_fd);

  // Call actual AuthenticateUser method.
  int32_t int_error;
  std::vector<uint8_t> account_info_blob;
  if (success) {
    password_fd.CheckValidity();
    AuthenticateUser(user_principal_name,
                     account_id,
                     password_fd,
                     &int_error,
                     &account_info_blob);
  } else {
    int_error = ERROR_DBUS_FAILURE;
  }

  // Send response.
  std::unique_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendInt32(int_error);
  writer.AppendArrayOfBytes(account_info_blob.data(), account_info_blob.size());
  sender.Run(std::move(response));
}

void AuthPolicy::AuthenticateUser(const std::string& user_principal_name,
                                  const std::string& account_id,
                                  const dbus::FileDescriptor& password_fd,
                                  int32_t* int_error,
                                  std::vector<uint8_t>* account_info_blob) {
  LOG(INFO) << "Received 'AuthenticateUser' request";
  ScopedTimerReporter timer(TIMER_AUTHENTICATE_USER);

  authpolicy::ActiveDirectoryAccountInfo account_info;
  ErrorType error = samba_.AuthenticateUser(
      user_principal_name, account_id, password_fd.value(), &account_info);
  if (error == ERROR_NONE) {
    std::string buffer;
    if (!account_info.SerializeToString(&buffer)) {
      LOG(ERROR) << "Failed to serialize account data";
      error = ERROR_PARSE_FAILED;
    } else {
      account_info_blob->assign(buffer.begin(), buffer.end());
    }
  }
  PrintError("AuthenticateUser", error);
  metrics_->ReportDBusResult(DBUS_CALL_AUTHENTICATE_USER, error);
  *int_error = static_cast<int>(error);
}

void AuthPolicy::GetUserStatus(const std::string& account_id,
                               int32_t* int_error,
                               std::vector<uint8_t>* user_status_blob) {
  LOG(INFO) << "Received 'GetUserStatus' request";
  ScopedTimerReporter timer(TIMER_GET_USER_STATUS);

  authpolicy::ActiveDirectoryUserStatus user_status;
  ErrorType error = samba_.GetUserStatus(account_id, &user_status);
  if (error == ERROR_NONE) {
    std::string buffer;
    if (!user_status.SerializeToString(&buffer)) {
      LOG(ERROR) << "Failed to serialize user status";
      error = ERROR_PARSE_FAILED;
    } else {
      user_status_blob->assign(buffer.begin(), buffer.end());
    }
  }
  PrintError("GetUserStatus", error);
  metrics_->ReportDBusResult(DBUS_CALL_GET_USER_STATUS, error);
  *int_error = static_cast<int>(error);
}

int32_t AuthPolicy::JoinADDomain(const std::string& machine_name,
                                 const std::string& user_principal_name,
                                 const dbus::FileDescriptor& password_fd) {
  LOG(INFO) << "Received 'JoinADDomain' request";
  ScopedTimerReporter timer(TIMER_JOIN_AD_DOMAIN);

  ErrorType error = samba_.JoinMachine(
      machine_name, user_principal_name, password_fd.value());
  PrintError("JoinADDomain", error);
  metrics_->ReportDBusResult(DBUS_CALL_JOIN_AD_DOMAIN, error);
  return error;
}

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

  // Fetch GPOs for the current user.
  std::string policy_blob;
  ErrorType error = samba_.FetchUserGpos(account_id_key, &policy_blob);
  PrintError("User policy fetch and parsing", error);

  // Return immediately on error.
  if (error != ERROR_NONE) {
    metrics_->ReportDBusResult(DBUS_CALL_REFRESH_USER_POLICY, error);
    callback->Return(error);
    return;
  }

  // Send policy to Session Manager.
  StorePolicy(
      policy_blob, &account_id_key, std::move(timer), std::move(callback));
}

void AuthPolicy::RefreshDevicePolicy(PolicyResponseCallback callback) {
  LOG(INFO) << "Received 'RefreshDevicePolicy' request";
  auto timer =
      base::MakeUnique<ScopedTimerReporter>(TIMER_REFRESH_DEVICE_POLICY);

  // Fetch GPOs for the device.
  std::string policy_blob;
  ErrorType error = samba_.FetchDeviceGpos(&policy_blob);
  PrintError("Device policy fetch and parsing", error);

  // Return immediately on error.
  if (error != ERROR_NONE) {
    metrics_->ReportDBusResult(DBUS_CALL_REFRESH_DEVICE_POLICY, error);
    callback->Return(error);
    return;
  }

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

void AuthPolicy::StorePolicy(const std::string& policy_blob,
                             const std::string* account_id_key,
                             std::unique_ptr<ScopedTimerReporter> timer,
                             PolicyResponseCallback callback) {
  // Note: Only policy_value required here, the other data only impacts
  // signature, but since we don't sign, we don't need it.
  const bool is_user_policy = account_id_key != nullptr;
  const char* const policy_type =
      is_user_policy ? kChromeUserPolicyType : kChromeDevicePolicyType;

  em::PolicyData policy_data;
  policy_data.set_policy_value(policy_blob);
  policy_data.set_policy_type(policy_type);
  // Note: No signature required here, Active Directory policy is unsigned!

  em::PolicyFetchResponse policy_response;
  std::string response_blob;
  if (!policy_data.SerializeToString(policy_response.mutable_policy_data()) ||
      !policy_response.SerializeToString(&response_blob)) {
    LOG(ERROR) << "Failed to serialize policy data";
    const DBusCallType call_type = GetPolicyDBusCallType(is_user_policy);
    metrics_->ReportDBusResult(call_type, ERROR_STORE_POLICY_FAILED);
    callback->Return(ERROR_STORE_POLICY_FAILED);
    return;
  }

  const char* const method = GetSessionManagerStoreMethod(is_user_policy);
  LOG(INFO) << "Calling Session Manager D-Bus method " << method;
  dbus::MethodCall method_call(login_manager::kSessionManagerInterface, method);
  dbus::MessageWriter writer(&method_call);
  if (account_id_key)
    writer.AppendString(*account_id_key);
  writer.AppendArrayOfBytes(
      reinterpret_cast<const uint8_t*>(response_blob.data()),
      response_blob.size());
  session_manager_proxy_->CallMethod(&method_call,
                                     dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
                                     base::Bind(&AuthPolicy::OnPolicyStored,
                                                weak_ptr_factory_.GetWeakPtr(),
                                                is_user_policy,
                                                base::Passed(&timer),
                                                base::Passed(&callback)));
}

void AuthPolicy::OnPolicyStored(
    bool is_user_policy,
    std::unique_ptr<ScopedTimerReporter> /* timer */,
    PolicyResponseCallback callback,
    dbus::Response* response) {
  const char* const method = GetSessionManagerStoreMethod(is_user_policy);
  brillo::ErrorPtr brillo_error;
  bool done = false;
  std::string msg;
  if (!response) {
    msg = base::StringPrintf("Call to %s failed. No response.", method);
  } else if (!ExtractMethodCallResults(response, &brillo_error, &done)) {
    msg = base::StringPrintf(
        "Call to %s failed. %s",
        method,
        brillo_error ? brillo_error->GetMessage().c_str() : "Unknown error.");
  } else if (!done) {
    msg = base::StringPrintf("Call to %s failed. Call returned false.", method);
  }

  ErrorType error;
  if (!msg.empty()) {
    LOG(ERROR) << msg;
    error = ERROR_STORE_POLICY_FAILED;
  } else {
    LOG(INFO) << "Call to " << method << " succeeded.";
    error = ERROR_NONE;
  }
  const DBusCallType call_type = GetPolicyDBusCallType(is_user_policy);
  metrics_->ReportDBusResult(call_type, error);
  callback->Return(error);
}

}  // namespace authpolicy
