// 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(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);
  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;
  std::string msg;
  if (!response) {
    // In case of error, session_manager_proxy_ prints out the error string and
    // response is empty.
    msg =
        base::StringPrintf("Call to %s failed. No response or error.", method);
  } else if (!ExtractMethodCallResults(response, &brillo_error)) {
    // Response is expected have no call results.
    msg = base::StringPrintf(
        "Call to %s failed. %s",
        method,
        brillo_error ? brillo_error->GetMessage().c_str() : "Unknown error.");
  }

  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
