// 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include <list>
#include <utility>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/callback_helpers.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/memory/weak_ptr.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/stringprintf.h>
#include <brillo/dbus/async_event_sequencer.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/message_loops/base_message_loop.h>
#include <dbus/object_path.h>
#include <dbus/message.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/mock_object_proxy.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/kerberos/dbus-constants.h>

#include "bindings/worker_common.pb.h"
#include "system-proxy/kerberos_client.h"
#include "system_proxy/proto_bindings/system_proxy_service.pb.h"
#include "system-proxy/protobuf_util.h"
#include "system-proxy/sandboxed_worker.h"

using testing::_;
using testing::Return;

namespace system_proxy {
namespace {
const char kUser[] = "proxy_user";
const char kPassword[] = "proxy_password";
const char kPrincipalName[] = "user@TEST";
const char kLocalProxyHostPort[] = "local.proxy.url:3128";
const char kObjectPath[] = "/object/path";

// Stub completion callback for RegisterAsync().
void DoNothing(bool /* unused */) {}

}  // namespace

class FakeSandboxedWorker : public SandboxedWorker {
 public:
  explicit FakeSandboxedWorker(base::WeakPtr<SystemProxyAdaptor> adaptor)
      : SandboxedWorker(adaptor) {}
  FakeSandboxedWorker(const FakeSandboxedWorker&) = delete;
  FakeSandboxedWorker& operator=(const FakeSandboxedWorker&) = delete;
  ~FakeSandboxedWorker() override = default;

  bool Start() override { return is_running_ = true; }
  bool Stop() override { return is_running_ = false; }
  bool IsRunning() override { return is_running_; }

  std::string local_proxy_host_and_port() override {
    return kLocalProxyHostPort;
  }

 private:
  bool is_running_;
};

class FakeSystemProxyAdaptor : public SystemProxyAdaptor {
 public:
  FakeSystemProxyAdaptor(
      std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
      : SystemProxyAdaptor(std::move(dbus_object)), weak_ptr_factory_(this) {}
  FakeSystemProxyAdaptor(const FakeSystemProxyAdaptor&) = delete;
  FakeSystemProxyAdaptor& operator=(const FakeSystemProxyAdaptor&) = delete;
  ~FakeSystemProxyAdaptor() override = default;

 protected:
  std::unique_ptr<SandboxedWorker> CreateWorker() override {
    return std::make_unique<FakeSandboxedWorker>(
        weak_ptr_factory_.GetWeakPtr());
  }
  void ConnectNamespace(SandboxedWorker* worker, bool user_traffic) override {
    OnNamespaceConnected(worker, user_traffic);
  }

 private:
  FRIEND_TEST(SystemProxyAdaptorTest, KerberosEnabled);
  FRIEND_TEST(SystemProxyAdaptorTest, ConnectNamespace);
  FRIEND_TEST(SystemProxyAdaptorTest, ProxyResolutionFilter);

  base::WeakPtrFactory<FakeSystemProxyAdaptor> weak_ptr_factory_;
};

class SystemProxyAdaptorTest : public ::testing::Test {
 public:
  SystemProxyAdaptorTest() {
    const dbus::ObjectPath object_path(kObjectPath);

    // Mock out D-Bus initialization.
    mock_exported_object_ =
        base::MakeRefCounted<dbus::MockExportedObject>(bus_.get(), object_path);

    EXPECT_CALL(*bus_, GetExportedObject(_))
        .WillRepeatedly(Return(mock_exported_object_.get()));

    EXPECT_CALL(*mock_exported_object_, ExportMethod(_, _, _, _))
        .Times(testing::AnyNumber());

    mock_kerberos_proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>(
        bus_.get(), kerberos::kKerberosServiceName,
        dbus::ObjectPath(kerberos::kKerberosServicePath));
    EXPECT_CALL(*bus_, GetObjectProxy(kerberos::kKerberosServiceName, _))
        .WillRepeatedly(Return(mock_kerberos_proxy_.get()));

    adaptor_.reset(new FakeSystemProxyAdaptor(
        std::make_unique<brillo::dbus_utils::DBusObject>(nullptr, bus_,
                                                         object_path)));
    adaptor_->RegisterAsync(base::BindRepeating(&DoNothing));
    mock_patchpanel_proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>(
        bus_.get(), patchpanel::kPatchPanelServiceName,
        dbus::ObjectPath(patchpanel::kPatchPanelServicePath));
    brillo_loop_.SetAsCurrent();
  }
  SystemProxyAdaptorTest(const SystemProxyAdaptorTest&) = delete;
  SystemProxyAdaptorTest& operator=(const SystemProxyAdaptorTest&) = delete;
  ~SystemProxyAdaptorTest() override = default;

  void OnWorkerActive(dbus::Signal* signal) {
    EXPECT_EQ(signal->GetInterface(), "org.chromium.SystemProxy");
    EXPECT_EQ(signal->GetMember(), "WorkerActive");
    active_worker_signal_called_ = true;

    dbus::MessageReader signal_reader(signal);
    system_proxy::WorkerActiveSignalDetails details;
    EXPECT_TRUE(signal_reader.PopArrayOfBytesAsProto(&details));
    EXPECT_EQ(kLocalProxyHostPort, details.local_proxy_url());
  }

 protected:
  bool active_worker_signal_called_ = false;
  scoped_refptr<dbus::MockBus> bus_ = new dbus::MockBus(dbus::Bus::Options());
  scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
  // SystemProxyAdaptor instance that creates fake worker processes.
  std::unique_ptr<FakeSystemProxyAdaptor> adaptor_;

  scoped_refptr<dbus::MockObjectProxy> mock_patchpanel_proxy_;
  scoped_refptr<dbus::MockObjectProxy> mock_kerberos_proxy_;

  base::MessageLoopForIO loop_;
  brillo::BaseMessageLoop brillo_loop_{&loop_};
};

TEST_F(SystemProxyAdaptorTest, SetSystemTrafficCredentials) {
  EXPECT_CALL(*bus_, GetObjectProxy(patchpanel::kPatchPanelServiceName, _))
      .WillOnce(Return(mock_patchpanel_proxy_.get()));

  EXPECT_FALSE(adaptor_->system_services_worker_.get());
  SetSystemTrafficCredentialsRequest request;
  request.set_system_services_username(kUser);
  request.set_system_services_password(kPassword);
  std::vector<uint8_t> proto_blob(request.ByteSizeLong());
  request.SerializeToArray(proto_blob.data(), proto_blob.size());

  // First create a worker object.
  adaptor_->SetSystemTrafficCredentials(proto_blob);
  brillo_loop_.RunOnce(false);

  EXPECT_TRUE(adaptor_->system_services_worker_.get());
  EXPECT_TRUE(adaptor_->system_services_worker_->IsRunning());

  int fds[2];
  EXPECT_TRUE(base::CreateLocalNonBlockingPipe(fds));
  base::ScopedFD read_scoped_fd(fds[0]);
  // Reset the worker stdin pipe to read the input from the other endpoint.
  adaptor_->system_services_worker_->stdin_pipe_.reset(fds[1]);

  adaptor_->SetSystemTrafficCredentials(proto_blob);
  brillo_loop_.RunOnce(false);

  worker::WorkerConfigs config;
  ASSERT_TRUE(ReadProtobuf(read_scoped_fd.get(), &config));
  EXPECT_TRUE(config.has_credentials());
  EXPECT_EQ(config.credentials().username(), kUser);
  EXPECT_EQ(config.credentials().password(), kPassword);
}

TEST_F(SystemProxyAdaptorTest, SetAuthenticationDetails) {
  EXPECT_CALL(*bus_, GetObjectProxy(patchpanel::kPatchPanelServiceName, _))
      .WillOnce(Return(mock_patchpanel_proxy_.get()));

  EXPECT_FALSE(adaptor_->system_services_worker_.get());
  SetAuthenticationDetailsRequest request;
  Credentials credentials;
  credentials.set_username(kUser);
  credentials.set_password(kPassword);
  *request.mutable_credentials() = credentials;
  request.set_traffic_type(TrafficOrigin::SYSTEM);

  std::vector<uint8_t> proto_blob(request.ByteSizeLong());
  request.SerializeToArray(proto_blob.data(), proto_blob.size());

  // First create a worker object.
  adaptor_->SetAuthenticationDetails(proto_blob);
  ASSERT_TRUE(brillo_loop_.RunOnce(/*may_block=*/false));

  ASSERT_TRUE(adaptor_->system_services_worker_.get());
  EXPECT_TRUE(adaptor_->system_services_worker_->IsRunning());

  int fds[2];
  EXPECT_TRUE(base::CreateLocalNonBlockingPipe(fds));
  base::ScopedFD read_scoped_fd(fds[0]);
  // Reset the worker stdin pipe to read the input from the other endpoint.
  adaptor_->system_services_worker_->stdin_pipe_.reset(fds[1]);

  adaptor_->SetAuthenticationDetails(proto_blob);
  ASSERT_TRUE(brillo_loop_.RunOnce(/*may_block=*/false));

  worker::WorkerConfigs config;
  ASSERT_TRUE(ReadProtobuf(read_scoped_fd.get(), &config));
  EXPECT_TRUE(config.has_credentials());
  EXPECT_EQ(config.credentials().username(), kUser);
  EXPECT_EQ(config.credentials().password(), kPassword);
}

TEST_F(SystemProxyAdaptorTest, KerberosEnabled) {
  adaptor_->system_services_worker_ = adaptor_->CreateWorker();
  ASSERT_TRUE(adaptor_->system_services_worker_.get());

  int fds[2];
  ASSERT_TRUE(base::CreateLocalNonBlockingPipe(fds));
  base::ScopedFD read_scoped_fd(fds[0]);
  // Reset the worker stdin pipe to read the input from the other endpoint.
  adaptor_->system_services_worker_->stdin_pipe_.reset(fds[1]);

  SetAuthenticationDetailsRequest request;
  request.set_kerberos_enabled(true);
  request.set_active_principal_name(kPrincipalName);
  request.set_traffic_type(TrafficOrigin::SYSTEM);

  std::vector<uint8_t> proto_blob(request.ByteSizeLong());
  request.SerializeToArray(proto_blob.data(), proto_blob.size());

  // First create a worker object.
  adaptor_->SetAuthenticationDetails(proto_blob);
  brillo_loop_.RunOnce(false);

  // Expect that the availability of kerberos auth has been sent to the worker.
  worker::WorkerConfigs config;
  ASSERT_TRUE(ReadProtobuf(read_scoped_fd.get(), &config));
  EXPECT_TRUE(config.has_kerberos_config());
  EXPECT_TRUE(config.kerberos_config().enabled());
  EXPECT_EQ(config.kerberos_config().krb5cc_path(), "/tmp/ccache");
  EXPECT_EQ(config.kerberos_config().krb5conf_path(), "/tmp/krb5.conf");

  // Expect that the availability of kerberos auth has been sent to the kerberos
  // client.
  EXPECT_TRUE(adaptor_->kerberos_client_->kerberos_enabled_);
  EXPECT_EQ(adaptor_->kerberos_client_->principal_name_, kPrincipalName);
}

TEST_F(SystemProxyAdaptorTest, ShutDown) {
  EXPECT_CALL(*bus_, GetObjectProxy(patchpanel::kPatchPanelServiceName, _))
      .WillOnce(Return(mock_patchpanel_proxy_.get()));
  EXPECT_FALSE(adaptor_->system_services_worker_.get());
  SetSystemTrafficCredentialsRequest request;
  request.set_system_services_username(kUser);
  request.set_system_services_password(kPassword);
  std::vector<uint8_t> proto_blob(request.ByteSizeLong());
  request.SerializeToArray(proto_blob.data(), proto_blob.size());

  // First create a worker object.
  adaptor_->SetSystemTrafficCredentials(proto_blob);
  brillo_loop_.RunOnce(false);

  EXPECT_TRUE(adaptor_->system_services_worker_.get());
  EXPECT_TRUE(adaptor_->system_services_worker_->IsRunning());

  adaptor_->ShutDown();
  EXPECT_FALSE(adaptor_->system_services_worker_->IsRunning());
}

TEST_F(SystemProxyAdaptorTest, ConnectNamespace) {
  EXPECT_FALSE(active_worker_signal_called_);
  EXPECT_CALL(*mock_exported_object_, SendSignal(_))
      .WillOnce(Invoke(this, &SystemProxyAdaptorTest::OnWorkerActive));

  adaptor_->system_services_worker_ = adaptor_->CreateWorker();
  adaptor_->ConnectNamespace(adaptor_->system_services_worker_.get(),
                             /* user_traffic= */ false);
  EXPECT_TRUE(active_worker_signal_called_);
}

TEST_F(SystemProxyAdaptorTest, ProxyResolutionFilter) {
  std::vector<std::string> proxy_list = {
      base::StringPrintf("%s%s", "http://", kLocalProxyHostPort),
      "http://test.proxy.com", "https://test.proxy.com", "direct://"};

  adaptor_->system_services_worker_ = adaptor_->CreateWorker();
  int fds[2];
  ASSERT_TRUE(base::CreateLocalNonBlockingPipe(fds));
  base::ScopedFD read_scoped_fd(fds[0]);
  // Reset the worker stdin pipe to read the input from the other endpoint.
  adaptor_->system_services_worker_->stdin_pipe_.reset(fds[1]);
  adaptor_->system_services_worker_->OnProxyResolved("target_url", true,
                                                     proxy_list);

  brillo_loop_.RunOnce(false);

  worker::WorkerConfigs config;
  ASSERT_TRUE(ReadProtobuf(read_scoped_fd.get(), &config));
  EXPECT_TRUE(config.has_proxy_resolution_reply());
  std::list<std::string> proxies;
  const worker::ProxyResolutionReply& reply = config.proxy_resolution_reply();
  for (auto const& proxy : reply.proxy_servers())
    proxies.push_back(proxy);

  EXPECT_EQ("target_url", reply.target_url());
  EXPECT_EQ(2, proxies.size());
  EXPECT_EQ("http://test.proxy.com", proxies.front());
}

}  // namespace system_proxy
