// 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/proxy_connect_job.h"

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <utility>

#include <curl/curl.h>

#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/strings/stringprintf.h>
#include <base/task/single_thread_task_executor.h>
#include <base/test/test_mock_time_task_runner.h>
#include <brillo/message_loops/base_message_loop.h>
#include <chromeos/patchpanel/net_util.h>
#include <chromeos/patchpanel/socket.h>
#include <chromeos/patchpanel/socket_forwarder.h>

#include "bindings/worker_common.pb.h"
#include "system-proxy/protobuf_util.h"
#include "system-proxy/test_http_server.h"

namespace {

constexpr char kCredentials[] = "username:pwd";
constexpr char kValidConnectRequest[] =
    "CONNECT www.example.server.com:443 HTTP/1.1\r\n\r\n";
constexpr char kProxyAuthorizationHeaderToken[] = "Proxy-Authorization:";
}  // namespace

namespace system_proxy {

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

class ProxyConnectJobTest : public ::testing::Test {
 public:
  struct HttpAuthEntry {
    HttpAuthEntry(const std::string& origin,
                  const std::string& scheme,
                  const std::string& realm,
                  const std::string& credentials)
        : origin(origin),
          scheme(scheme),
          realm(realm),
          credentials(credentials) {}
    std::string origin;
    std::string scheme;
    std::string realm;
    std::string credentials;
  };
  ProxyConnectJobTest() = default;
  ProxyConnectJobTest(const ProxyConnectJobTest&) = delete;
  ProxyConnectJobTest& operator=(const ProxyConnectJobTest&) = delete;
  ~ProxyConnectJobTest() = default;

  void SetUp() override {
    int fds[2];
    ASSERT_NE(-1,
              socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
                         0 /* protocol */, fds));
    cros_client_socket_ =
        std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[1]));

    connect_job_ = std::make_unique<ProxyConnectJob>(
        std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[0])), "",
        CURLAUTH_ANY,
        base::BindOnce(&ProxyConnectJobTest::ResolveProxy,
                       base::Unretained(this)),
        base::BindRepeating(&ProxyConnectJobTest::OnAuthCredentialsRequired,
                            base::Unretained(this)),
        base::BindOnce(&ProxyConnectJobTest::OnConnectionSetupFinished,
                       base::Unretained(this)));
  }

 protected:
  virtual void OnConnectionSetupFinished(
      std::unique_ptr<patchpanel::SocketForwarder> fwd,
      ProxyConnectJob* connect_job) {}
  virtual void ResolveProxy(
      const std::string& target_url,
      base::OnceCallback<void(const std::list<std::string>&)> callback) {
    std::move(callback).Run({});
  }
  virtual void OnAuthCredentialsRequired(
      const std::string& proxy_url,
      const std::string& scheme,
      const std::string& realm,
      const std::string& bad_credentials,
      base::RepeatingCallback<void(const std::string&)> callback) {
    std::move(callback).Run(/* credentials = */ "");
  }

  std::unique_ptr<ProxyConnectJob> connect_job_;
  base::SingleThreadTaskExecutor task_executor_{base::MessagePumpType::IO};
  std::unique_ptr<brillo::BaseMessageLoop> brillo_loop_{
      std::make_unique<brillo::BaseMessageLoop>(task_executor_.task_runner())};
  std::unique_ptr<patchpanel::Socket> cros_client_socket_;

  FRIEND_TEST(ProxyConnectJobTest, ClientConnectTimeoutJobCanceled);
};

TEST_F(ProxyConnectJobTest, BadHttpRequestWrongMethod) {
  connect_job_->Start();
  char badConnRequest[] = "GET www.example.server.com:443 HTTP/1.1\r\n\r\n";
  cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
  brillo_loop_->RunOnce(false);

  EXPECT_EQ("", connect_job_->target_url_);
  EXPECT_EQ(0, connect_job_->proxy_servers_.size());
  const std::string expected_http_response =
      "HTTP/1.1 400 Bad Request - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_http_response.size());
  ASSERT_TRUE(
      base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
  std::string actual_response(buf.data(), buf.size());
  EXPECT_EQ(expected_http_response, actual_response);
}

TEST_F(ProxyConnectJobTest, SlowlorisTimeout) {
  // Add a TaskRunner where we can control time.
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
      new base::TestMockTimeTaskRunner()};
  brillo_loop_ = nullptr;
  brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
  base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());

  connect_job_->Start();
  // No empty line after http message.
  char badConnRequest[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n";
  cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
  task_runner->RunUntilIdle();

  EXPECT_EQ(1, task_runner->GetPendingTaskCount());
  constexpr base::TimeDelta kDoubleWaitClientConnectTimeout =
      base::TimeDelta::FromSeconds(4);
  // Move the time ahead so that the client connection timeout callback is
  // triggered.
  task_runner->FastForwardBy(kDoubleWaitClientConnectTimeout);

  EXPECT_EQ("", connect_job_->target_url_);
  EXPECT_EQ(0, connect_job_->proxy_servers_.size());
  const std::string expected_http_response =
      "HTTP/1.1 408 Request Timeout - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_http_response.size());
  ASSERT_TRUE(
      base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
  std::string actual_response(buf.data(), buf.size());
  EXPECT_EQ(expected_http_response, actual_response);
}

TEST_F(ProxyConnectJobTest, WaitClientConnectTimeout) {
  // Add a TaskRunner where we can control time.
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
      new base::TestMockTimeTaskRunner()};
  brillo_loop_ = nullptr;
  brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
  base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());

  connect_job_->Start();

  EXPECT_EQ(1, task_runner->GetPendingTaskCount());
  // Move the time ahead so that the client connection timeout callback is
  // triggered.
  task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());

  const std::string expected_http_response =
      "HTTP/1.1 408 Request Timeout - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_http_response.size());
  ASSERT_TRUE(
      base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
  std::string actual_response(buf.data(), buf.size());

  EXPECT_EQ(expected_http_response, actual_response);
}

// Check that the client connect timeout callback is not fired if the owning
// proxy connect job is destroyed.
TEST_F(ProxyConnectJobTest, ClientConnectTimeoutJobCanceled) {
  // Add a TaskRunner where we can control time.
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
      new base::TestMockTimeTaskRunner()};
  brillo_loop_ = nullptr;
  brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
  base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());

  // Create a proxy connect job and start the client connect timeout counter.
  {
    int fds[2];
    ASSERT_NE(-1,
              socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
                         0 /* protocol */, fds));
    auto client_socket =
        std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[1]));

    auto connect_job = std::make_unique<ProxyConnectJob>(
        std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[0])), "",
        CURLAUTH_ANY,
        base::BindOnce(&ProxyConnectJobTest::ResolveProxy,
                       base::Unretained(this)),
        base::BindRepeating(&ProxyConnectJobTest::OnAuthCredentialsRequired,
                            base::Unretained(this)),
        base::BindOnce(&ProxyConnectJobTest::OnConnectionSetupFinished,
                       base::Unretained(this)));
    // Post the timeout task.
    connect_job->Start();
    EXPECT_TRUE(task_runner->HasPendingTask());
  }
  // Check that the task was canceled.
  EXPECT_FALSE(task_runner->HasPendingTask());
}

class HttpServerProxyConnectJobTest : public ProxyConnectJobTest {
 public:
  HttpServerProxyConnectJobTest() = default;
  HttpServerProxyConnectJobTest(const HttpServerProxyConnectJobTest&) = delete;
  HttpServerProxyConnectJobTest& operator=(
      const HttpServerProxyConnectJobTest&) = delete;
  ~HttpServerProxyConnectJobTest() = default;

 protected:
  HttpTestServer http_test_server_;

  std::vector<HttpAuthEntry> http_auth_cache_;
  bool auth_requested_ = false;

  void AddHttpAuthEntry(const std::string& origin,
                        const std::string& scheme,
                        const std::string& realm,
                        const std::string& credentials) {
    http_auth_cache_.push_back(
        HttpAuthEntry(origin, scheme, realm, credentials));
  }

  bool AuthRequested() { return auth_requested_; }

  void AddServerReply(HttpTestServer::HttpConnectReply reply) {
    http_test_server_.AddHttpConnectReply(reply);
  }

  void ResolveProxy(const std::string& target_url,
                    base::OnceCallback<void(const std::list<std::string>&)>
                        callback) override {
    // Return the URL of the test proxy.
    std::move(callback).Run({http_test_server_.GetUrl()});
  }

  void OnAuthCredentialsRequired(
      const std::string& proxy_url,
      const std::string& scheme,
      const std::string& realm,
      const std::string& bad_credentials,
      base::RepeatingCallback<void(const std::string&)> callback) override {
    auth_requested_ = true;
    for (const auto& auth_entry : http_auth_cache_) {
      if (auth_entry.origin == proxy_url && auth_entry.realm == realm &&
          auth_entry.scheme == scheme) {
        std::move(callback).Run(auth_entry.credentials);
        return;
      }
    }
    if (invoke_authentication_callback_) {
      std::move(callback).Run(/* credentials = */ "");
    }
  }
  void OnConnectionSetupFinished(
      std::unique_ptr<patchpanel::SocketForwarder> fwd,
      ProxyConnectJob* connect_job) override {
    ASSERT_EQ(connect_job, connect_job_.get());
    if (fwd) {
      forwarder_created_ = true;

      brillo_loop_->RunOnce(false);

      fwd.reset();
    }
  }

  bool forwarder_created_ = false;
  // Used to simulate time-outs while waiting for credentials from the Browser.
  bool invoke_authentication_callback_ = true;
};

TEST_F(HttpServerProxyConnectJobTest, SuccessfulConnection) {
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();

  connect_job_->Start();
  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);
  EXPECT_EQ("www.example.server.com:443", connect_job_->target_url_);
  EXPECT_EQ(1, connect_job_->proxy_servers_.size());
  EXPECT_EQ(http_test_server_.GetUrl(), connect_job_->proxy_servers_.front());
  EXPECT_TRUE(forwarder_created_);
}

TEST_F(HttpServerProxyConnectJobTest, MultipleReadConnectRequest) {
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();
  connect_job_->Start();
  char part1[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n";
  char part2[] = "\r\n";
  cros_client_socket_->SendTo(part1, std::strlen(part1));
  // Process the partial CONNECT request.
  brillo_loop_->RunOnce(false);
  cros_client_socket_->SendTo(part2, std::strlen(part2));
  brillo_loop_->RunOnce(false);
  EXPECT_EQ("www.example.server.com:443", connect_job_->target_url_);
  EXPECT_EQ(1, connect_job_->proxy_servers_.size());
  EXPECT_EQ(http_test_server_.GetUrl(), connect_job_->proxy_servers_.front());
  EXPECT_TRUE(forwarder_created_);
}

TEST_F(HttpServerProxyConnectJobTest, TunnelFailedBadGatewayFromRemote) {
  AddServerReply(HttpTestServer::HttpConnectReply::kBadGateway);
  http_test_server_.Start();

  connect_job_->Start();
  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);
  EXPECT_FALSE(forwarder_created_);

  std::string expected_server_reply =
      "HTTP/1.1 502 Error creating tunnel - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_server_reply.size());

  ASSERT_TRUE(cros_client_socket_->RecvFrom(buf.data(), buf.size()));
  std::string actual_server_reply(buf.data(), buf.size());
  EXPECT_EQ(expected_server_reply, actual_server_reply);
}

TEST_F(HttpServerProxyConnectJobTest, SuccessfulConnectionAltEnding) {
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();

  connect_job_->Start();
  char validConnRequest[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n\n";
  cros_client_socket_->SendTo(validConnRequest, std::strlen(validConnRequest));
  brillo_loop_->RunOnce(false);

  EXPECT_EQ("www.example.server.com:443", connect_job_->target_url_);
  EXPECT_EQ(1, connect_job_->proxy_servers_.size());
  EXPECT_EQ(http_test_server_.GetUrl(), connect_job_->proxy_servers_.front());
  EXPECT_TRUE(forwarder_created_);
  ASSERT_FALSE(AuthRequested());
}

// Test that the the CONNECT request is sent again after acquiring credentials.
TEST_F(HttpServerProxyConnectJobTest, ResendWithCredentials) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();

  AddHttpAuthEntry(http_test_server_.GetUrl(), "Basic", "\"My Proxy\"",
                   kCredentials);
  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  ASSERT_TRUE(AuthRequested());
  EXPECT_TRUE(forwarder_created_);
  EXPECT_EQ(kCredentials, connect_job_->credentials_);
  EXPECT_EQ(200, connect_job_->http_response_code_);
}

// Test that the proxy auth required status is forwarded to the client if
// credentials are missing.
TEST_F(HttpServerProxyConnectJobTest, NoCredentials) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  http_test_server_.Start();
  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  ASSERT_TRUE(AuthRequested());
  EXPECT_EQ("", connect_job_->credentials_);
  EXPECT_EQ(407, connect_job_->http_response_code_);
}

// Test that the proxy auth required status is forwarded to the client if the
// server chose Kerberos as an authentication method.
TEST_F(HttpServerProxyConnectJobTest, KerberosAuth) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredKerberos);
  http_test_server_.Start();

  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  ASSERT_FALSE(AuthRequested());
  EXPECT_EQ("", connect_job_->credentials_);
  EXPECT_EQ(407, connect_job_->http_response_code_);
}

// Test that the connection times out while waiting for credentials from the
// Browser.
TEST_F(HttpServerProxyConnectJobTest, AuthenticationTimeout) {
  // Add a TaskRunner where we can control time.
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
      new base::TestMockTimeTaskRunner()};
  brillo_loop_ = nullptr;
  brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
  base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());

  invoke_authentication_callback_ = false;

  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  http_test_server_.Start();

  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  task_runner->RunUntilIdle();
  // We need to manually invoke the method which reads from the client socket
  // because |task_runner| will not execute the FileDescriptorWatcher's tasks.
  connect_job_->OnClientReadReady();

  // Check that an authentication request was sent.
  ASSERT_TRUE(AuthRequested());
  EXPECT_EQ(1, task_runner->GetPendingTaskCount());
  // Move the time ahead so that the client connection timeout callback is
  // triggered.
  task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());

  const std::string expected_http_response =
      "HTTP/1.1 407 Credentials required - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_http_response.size());
  ASSERT_TRUE(
      base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
  std::string actual_response(buf.data(), buf.size());

  // Check that the auth failure was forwarded to the client.
  EXPECT_EQ(expected_http_response, actual_response);
}

// Verifies that the receiving the same bad credentials twice will send an auth
// failure to the Chrome OS local client.
TEST_F(HttpServerProxyConnectJobTest, CancelIfBadCredentials) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  http_test_server_.Start();

  AddHttpAuthEntry(http_test_server_.GetUrl(), "Basic", "\"My Proxy\"",
                   kCredentials);

  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  ASSERT_TRUE(AuthRequested());

  const std::string expected_http_response =
      "HTTP/1.1 407 Credentials required - Origin: local proxy\r\n\r\n";
  std::vector<char> buf(expected_http_response.size());
  ASSERT_TRUE(
      base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
  std::string actual_response(buf.data(), buf.size());

  EXPECT_EQ(expected_http_response, actual_response);
}

//  This test verifies that any data sent by a client immediately after the end
//  of the HTTP CONNECT request is cached correctly.
TEST_F(HttpServerProxyConnectJobTest, BufferedClientData) {
  char connectRequestwithData[] =
      "CONNECT www.example.server.com:443 HTTP/1.1\r\n\r\nTest body";
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();

  AddHttpAuthEntry(http_test_server_.GetUrl(), "Basic", "\"My Proxy\"",
                   kCredentials);
  connect_job_->Start();

  cros_client_socket_->SendTo(connectRequestwithData,
                              std::strlen(connectRequestwithData));
  brillo_loop_->RunOnce(false);

  const std::string expected = "Test body";
  const std::string actual(connect_job_->connect_data_.data(),
                           connect_job_->connect_data_.size());
}

TEST_F(HttpServerProxyConnectJobTest, BufferedClientDataAltEnding) {
  char connectRequestwithData[] =
      "CONNECT www.example.server.com:443 HTTP/1.1\r\n\nTest body";
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  AddServerReply(HttpTestServer::HttpConnectReply::kOk);
  http_test_server_.Start();

  AddHttpAuthEntry(http_test_server_.GetUrl(), "Basic", "\"My Proxy\"",
                   kCredentials);
  connect_job_->Start();

  cros_client_socket_->SendTo(connectRequestwithData,
                              std::strlen(connectRequestwithData));
  brillo_loop_->RunOnce(false);

  const std::string expected = "Test body";
  const std::string actual(connect_job_->connect_data_.data(),
                           connect_job_->connect_data_.size());
}

// Test that the policy auth scheme is respected by curl.
TEST_F(HttpServerProxyConnectJobTest, PolicyAuthSchemeOk) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  http_test_server_.Start();
  connect_job_->credentials_ = "a:b";
  connect_job_->curl_auth_schemes_ = CURLAUTH_BASIC;
  connect_job_->StoreRequestHeadersForTesting();
  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  std::size_t pos = connect_job_->GetRequestHeadersForTesting().find(
      kProxyAuthorizationHeaderToken);
  // Expect to find the proxy auth headers since CURLAUTH_BASIC is an allowed
  // auth scheme.
  EXPECT_NE(pos, std::string::npos);
}

// Test that proxy auth headers with credentials are not sent by curl if the
// auth scheme used by the server is not allowed.
TEST_F(HttpServerProxyConnectJobTest, PolicyAuthBadScheme) {
  AddServerReply(HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
  http_test_server_.Start();
  connect_job_->credentials_ = "a:b";
  connect_job_->curl_auth_schemes_ = CURLAUTH_DIGEST;
  connect_job_->StoreRequestHeadersForTesting();
  connect_job_->Start();

  cros_client_socket_->SendTo(kValidConnectRequest,
                              std::strlen(kValidConnectRequest));
  brillo_loop_->RunOnce(false);

  std::size_t pos = connect_job_->GetRequestHeadersForTesting().find(
      kProxyAuthorizationHeaderToken);
  // Expect not to find the proxy auth headers since CURLAUTH_BASIC is not an
  // allowed auth scheme.
  EXPECT_EQ(pos, std::string::npos);
}

}  // namespace system_proxy
