// Copyright 2020 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 "system-proxy/system_proxy_adaptor.h"

#include <string>
#include <utility>
#include <vector>

#include <base/location.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/message_loops/message_loop.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/patchpanel/dbus/client.h>
#include <dbus/object_proxy.h>

#include "system-proxy/kerberos_client.h"
#include "system-proxy/sandboxed_worker.h"

namespace system_proxy {
namespace {

constexpr int kProxyPort = 3128;
constexpr char kFailedToStartWorkerError[] = "Failed to start worker process";
// Time delay for calling patchpanel::ConnectNamespace(). Patchpanel needs to
// enter the network namespace of the worker process to configure it and fails
// if it's soon after the process starts. See https://crbug.com/1095170 for
// details.
constexpr base::TimeDelta kConnectNamespaceDelay =
    base::TimeDelta::FromSeconds(1);
constexpr int kNetworkNamespaceReconnectAttempts = 3;

// Serializes |proto| to a vector of bytes.
std::vector<uint8_t> SerializeProto(
    const google::protobuf::MessageLite& proto) {
  std::vector<uint8_t> proto_blob(proto.ByteSizeLong());
  bool result = proto.SerializeToArray(proto_blob.data(), proto_blob.size());
  DCHECK(result);
  return proto_blob;
}

// Parses a proto from an array of bytes |proto_blob|. Returns
// ERROR_PARSE_REQUEST_FAILED on error.
std::string DeserializeProto(const base::Location& from_here,
                             google::protobuf::MessageLite* proto,
                             const std::vector<uint8_t>& proto_blob) {
  if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
    const std::string error_message = "Failed to parse proto message.";
    LOG(ERROR) << from_here.ToString() << error_message;
    return error_message;
  }
  return "";
}
}  // namespace

SystemProxyAdaptor::SystemProxyAdaptor(
    std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
    : org::chromium::SystemProxyAdaptor(this),
      netns_reconnect_attempts_available_(kNetworkNamespaceReconnectAttempts),
      dbus_object_(std::move(dbus_object)),
      weak_ptr_factory_(this) {
  kerberos_client_ = std::make_unique<KerberosClient>(dbus_object_->GetBus());
}

SystemProxyAdaptor::~SystemProxyAdaptor() = default;

void SystemProxyAdaptor::RegisterAsync(
    const brillo::dbus_utils::AsyncEventSequencer::CompletionAction&
        completion_callback) {
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);
}

std::vector<uint8_t> SystemProxyAdaptor::SetAuthenticationDetails(
    const std::vector<uint8_t>& request_blob) {
  LOG(INFO) << "Received set authentication details request.";

  SetAuthenticationDetailsRequest request;
  std::string error_message =
      DeserializeProto(FROM_HERE, &request, request_blob);

  SetAuthenticationDetailsResponse response;
  if (!error_message.empty()) {
    response.set_error_message(error_message);
    return SerializeProto(response);
  }

  if (IncludesSystemTraffic(request.traffic_type())) {
    SetAuthenticationDetails(request, /*user_traffic=*/false, &error_message);
  }
  if (IncludesUserTraffic(request.traffic_type())) {
    SetAuthenticationDetails(request, /*user_traffic=*/true, &error_message);
  }
  if (!error_message.empty()) {
    response.set_error_message(error_message);
  }
  return SerializeProto(response);
}

void SystemProxyAdaptor::SetAuthenticationDetails(
    SetAuthenticationDetailsRequest auth_details,
    bool user_traffic,
    std::string* error_message) {
  SandboxedWorker* worker = CreateWorkerIfNeeded(user_traffic);
  if (!worker) {
    error_message->append(kFailedToStartWorkerError);
    return;
  }

  if (auth_details.has_credentials() || auth_details.has_protection_space()) {
    worker::Credentials credentials;
    if (auth_details.has_protection_space()) {
      worker::ProtectionSpace protection_space;
      protection_space.set_origin(auth_details.protection_space().origin());
      protection_space.set_scheme(auth_details.protection_space().scheme());
      protection_space.set_realm(auth_details.protection_space().realm());
      *credentials.mutable_protection_space() = protection_space;
    }

    if (auth_details.has_credentials()) {
      if (auth_details.credentials().has_username() &&
          auth_details.credentials().has_password()) {
        credentials.set_username(auth_details.credentials().username());
        credentials.set_password(auth_details.credentials().password());
      }
    }

    brillo::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&SystemProxyAdaptor::SetCredentialsTask,
                   weak_ptr_factory_.GetWeakPtr(), worker, credentials));
  }
  if (auth_details.has_kerberos_enabled()) {
    std::string principal_name = auth_details.has_active_principal_name()
                                     ? auth_details.active_principal_name()
                                     : std::string();

    brillo::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(&SystemProxyAdaptor::SetKerberosEnabledTask,
                              weak_ptr_factory_.GetWeakPtr(), worker,
                              auth_details.kerberos_enabled(), principal_name));
  }
}

// TODO(acostinas, crbug.com/1109144): Deprecated in favor of |ShutDownProcess|.
std::vector<uint8_t> SystemProxyAdaptor::ShutDown() {
  LOG(INFO) << "Received shutdown request.";

  std::string error_message;
  if (!ResetWorker(/* user_traffic=*/false)) {
    error_message =
        "Failure to terminate worker process for system services traffic.";
  }

  if (!ResetWorker(/* user_traffic=*/true)) {
    error_message += "Failure to terminate worker process for arc traffic.";
  }

  ShutDownResponse response;
  if (!error_message.empty())
    response.set_error_message(error_message);

  brillo::MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&SystemProxyAdaptor::ShutDownTask,
                            weak_ptr_factory_.GetWeakPtr()));

  return SerializeProto(response);
}

std::vector<uint8_t> SystemProxyAdaptor::ClearUserCredentials(
    const std::vector<uint8_t>& request_blob) {
  LOG(INFO) << "Received request to clear user credentials.";
  std::string error_message;
  ClearUserCredentials(/*user_traffic=*/false, &error_message);
  ClearUserCredentials(/*user_traffic=*/true, &error_message);

  ClearUserCredentialsResponse response;
  if (!error_message.empty())
    response.set_error_message(error_message);
  return SerializeProto(response);
}

void SystemProxyAdaptor::ClearUserCredentials(bool user_traffic,
                                              std::string* error_message) {
  SandboxedWorker* worker = GetWorker(user_traffic);
  if (!worker) {
    return;
  }
  if (!worker->ClearUserCredentials()) {
    error_message->append(
        base::StringPrintf("Failure to clear user credentials for worker with "
                           "pid %s. Restarting worker.",
                           std::to_string(worker->pid()).c_str()));
    ResetWorker(user_traffic);
    CreateWorkerIfNeeded(user_traffic);
  }
}

std::vector<uint8_t> SystemProxyAdaptor::ShutDownProcess(
    const std::vector<uint8_t>& request_blob) {
  LOG(INFO) << "Received shutdown request.";
  ShutDownRequest request;
  std::string error_message =
      DeserializeProto(FROM_HERE, &request, request_blob);

  if (IncludesSystemTraffic(request.traffic_type()) &&
      !ResetWorker(/* user_traffic=*/false)) {
    error_message =
        "Failure to terminate worker process for system services traffic.";
  }

  if (IncludesUserTraffic(request.traffic_type()) &&
      !ResetWorker(/* user_traffic=*/true)) {
    error_message += "Failure to terminate worker process for arc traffic.";
  }

  ShutDownResponse response;
  if (!error_message.empty())
    response.set_error_message(error_message);

  if (request.traffic_type() == TrafficOrigin::ALL) {
    brillo::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(&SystemProxyAdaptor::ShutDownTask,
                              weak_ptr_factory_.GetWeakPtr()));
  }
  return SerializeProto(response);
}

void SystemProxyAdaptor::GetChromeProxyServersAsync(
    const std::string& target_url,
    const brillo::http::GetChromeProxyServersCallback& callback) {
  brillo::http::GetChromeProxyServersAsync(dbus_object_->GetBus(), target_url,
                                           move(callback));
}

bool SystemProxyAdaptor::IsLocalProxy(const std::string& proxy) {
  if (system_services_worker_ &&
      proxy.find(system_services_worker_->local_proxy_host_and_port()) !=
          std::string::npos) {
    return true;
  }
  return arc_worker_ && proxy.find(arc_worker_->local_proxy_host_and_port()) !=
                            std::string::npos;
}

std::unique_ptr<SandboxedWorker> SystemProxyAdaptor::CreateWorker() {
  return std::make_unique<SandboxedWorker>(weak_ptr_factory_.GetWeakPtr());
}

SandboxedWorker* SystemProxyAdaptor::CreateWorkerIfNeeded(bool user_traffic) {
  SandboxedWorker* worker = GetWorker(user_traffic);
  if (worker) {
    // A worker for traffic indicated by |user_traffic| already exists.
    return worker;
  }
  SetWorker(user_traffic, CreateWorker());
  worker = GetWorker(user_traffic);

  if (!worker->Start()) {
    ResetWorker(user_traffic);
    return nullptr;
  }
  // patchpanel_proxy is owned by |dbus_object_->bus_|.
  dbus::ObjectProxy* patchpanel_proxy = dbus_object_->GetBus()->GetObjectProxy(
      patchpanel::kPatchPanelServiceName,
      dbus::ObjectPath(patchpanel::kPatchPanelServicePath));
  patchpanel_proxy->WaitForServiceToBeAvailable(
      base::Bind(&SystemProxyAdaptor::OnPatchpanelServiceAvailable,
                 weak_ptr_factory_.GetWeakPtr(), user_traffic));
  return worker;
}

void SystemProxyAdaptor::SetCredentialsTask(
    SandboxedWorker* worker, const worker::Credentials& credentials) {
  DCHECK(worker);
  worker->SetCredentials(credentials);
}

void SystemProxyAdaptor::SetKerberosEnabledTask(
    SandboxedWorker* worker,
    bool kerberos_enabled,
    const std::string& principal_name) {
  DCHECK(worker);
  worker->SetKerberosEnabled(kerberos_enabled,
                             kerberos_client_->krb5_conf_path(),
                             kerberos_client_->krb5_ccache_path());
  kerberos_client_->SetKerberosEnabled(kerberos_enabled);
  if (kerberos_enabled) {
    kerberos_client_->SetPrincipalName(principal_name);
  }
}

void SystemProxyAdaptor::ShutDownTask() {
  brillo::MessageLoop::current()->BreakLoop();
}

void SystemProxyAdaptor::SetWorker(bool user_traffic,
                                   std::unique_ptr<SandboxedWorker> worker) {
  if (user_traffic) {
    arc_worker_ = std::move(worker);
  } else {
    system_services_worker_ = std::move(worker);
  }
}

bool SystemProxyAdaptor::ResetWorker(bool user_traffic) {
  SandboxedWorker* worker =
      user_traffic ? arc_worker_.get() : system_services_worker_.get();
  if (!worker) {
    return true;
  }
  if (!worker->Stop()) {
    return false;
  }
  if (user_traffic) {
    arc_worker_.reset();
  } else {
    system_services_worker_.reset();
  }
  return true;
}

SandboxedWorker* SystemProxyAdaptor::GetWorker(bool user_traffic) {
  return user_traffic ? arc_worker_.get() : system_services_worker_.get();
}

bool SystemProxyAdaptor::IncludesSystemTraffic(TrafficOrigin traffic_origin) {
  return traffic_origin != TrafficOrigin::USER;
}

bool SystemProxyAdaptor::IncludesUserTraffic(TrafficOrigin traffic_origin) {
  return traffic_origin != TrafficOrigin::SYSTEM;
}

void SystemProxyAdaptor::OnPatchpanelServiceAvailable(bool user_traffic,
                                                      bool is_available) {
  if (!is_available) {
    LOG(ERROR) << "Patchpanel service not available";
    return;
  }
  ConnectNamespace(user_traffic);
}

void SystemProxyAdaptor::ConnectNamespace(bool user_traffic) {
  DCHECK_GT(netns_reconnect_attempts_available_, 0);
  --netns_reconnect_attempts_available_;
  SandboxedWorker* worker = GetWorker(user_traffic);
  DCHECK(worker);
  // TODO(b/160736881, acostinas): Remove the delay after patchpanel
  // implements "ip netns" to create the veth pair across network namespaces.
  brillo::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&SystemProxyAdaptor::ConnectNamespaceTask,
                 weak_ptr_factory_.GetWeakPtr(), worker, user_traffic),
      kConnectNamespaceDelay);
}

void SystemProxyAdaptor::ConnectNamespaceTask(SandboxedWorker* worker,
                                              bool user_traffic) {
  std::unique_ptr<patchpanel::Client> patchpanel_client =
      patchpanel::Client::New();
  if (!patchpanel_client) {
    LOG(ERROR) << "Failed to open networking service client";
    return;
  }

  std::pair<base::ScopedFD, patchpanel::ConnectNamespaceResponse> result =
      patchpanel_client->ConnectNamespace(
          worker->pid(), "" /* outbound_ifname */, user_traffic);

  if (!result.first.is_valid()) {
    LOG(ERROR) << "Failed to setup network namespace on attempt "
               << kNetworkNamespaceReconnectAttempts -
                      netns_reconnect_attempts_available_;
    if (netns_reconnect_attempts_available_ > 0) {
      ConnectNamespace(user_traffic);
    }
    return;
  }

  worker->SetNetNamespaceLifelineFd(std::move(result.first));
  if (!worker->SetListeningAddress(result.second.host_ipv4_address(),
                                   kProxyPort)) {
    return;
  }
  OnNamespaceConnected(worker, user_traffic);
}

void SystemProxyAdaptor::OnNamespaceConnected(SandboxedWorker* worker,
                                              bool user_traffic) {
  WorkerActiveSignalDetails details;
  details.set_traffic_origin(user_traffic ? TrafficOrigin::USER
                                          : TrafficOrigin::SYSTEM);
  details.set_local_proxy_url(worker->local_proxy_host_and_port());
  SendWorkerActiveSignal(SerializeProto(details));
}

void SystemProxyAdaptor::RequestAuthenticationCredentials(
    const worker::ProtectionSpace& protection_space,
    bool bad_cached_credentials) {
  AuthenticationRequiredDetails details;
  ProtectionSpace proxy_protection_space;
  proxy_protection_space.set_origin(protection_space.origin());
  proxy_protection_space.set_realm(protection_space.realm());
  proxy_protection_space.set_scheme(protection_space.scheme());
  *details.mutable_proxy_protection_space() = proxy_protection_space;
  details.set_bad_cached_credentials(bad_cached_credentials);
  SendAuthenticationRequiredSignal(SerializeProto(details));
}

}  // namespace system_proxy
