// 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/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
