// Copyright 2014 The Chromium 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 "net/ssl/channel_id_service.h"

#include <memory>
#include <string>
#include <vector>

#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_runner.h"
#include "base/test/null_task_runner.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "crypto/ec_private_key.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/asn1_util.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/default_channel_id_store.h"
#include "net/test/channel_id_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/net_test_suite.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using net::test::IsError;
using net::test::IsOk;

namespace net {

namespace {

void FailTest(int /* result */) {
  FAIL();
}

class MockChannelIDStoreWithAsyncGet
    : public DefaultChannelIDStore {
 public:
  MockChannelIDStoreWithAsyncGet()
      : DefaultChannelIDStore(NULL), channel_id_count_(0) {}

  int GetChannelID(const std::string& server_identifier,
                   std::unique_ptr<crypto::ECPrivateKey>* key_result,
                   const GetChannelIDCallback& callback) override;

  void SetChannelID(std::unique_ptr<ChannelID> channel_id) override {
    channel_id_count_ = 1;
  }

  int GetChannelIDCount() override { return channel_id_count_; }

  void CallGetChannelIDCallbackWithResult(int err, crypto::ECPrivateKey* key);

 private:
  GetChannelIDCallback callback_;
  std::string server_identifier_;
  int channel_id_count_;
};

int MockChannelIDStoreWithAsyncGet::GetChannelID(
    const std::string& server_identifier,
    std::unique_ptr<crypto::ECPrivateKey>* key_result,
    const GetChannelIDCallback& callback) {
  server_identifier_ = server_identifier;
  callback_ = callback;
  // Reset the cert count, it'll get incremented in either SetChannelID or
  // CallGetChannelIDCallbackWithResult.
  channel_id_count_ = 0;
  // Do nothing else: the results to be provided will be specified through
  // CallGetChannelIDCallbackWithResult.
  return ERR_IO_PENDING;
}

void MockChannelIDStoreWithAsyncGet::CallGetChannelIDCallbackWithResult(
    int err,
    crypto::ECPrivateKey* key) {
  if (err == OK)
    channel_id_count_ = 1;
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(callback_, err, server_identifier_,
                            base::Passed(key ? key->Copy() : nullptr)));
}

class ChannelIDServiceTest : public testing::Test {
 public:
  ChannelIDServiceTest()
      : service_(new ChannelIDService(new DefaultChannelIDStore(NULL))) {}

 protected:
  std::unique_ptr<ChannelIDService> service_;
};

TEST_F(ChannelIDServiceTest, GetDomainForHost) {
  EXPECT_EQ("google.com",
            ChannelIDService::GetDomainForHost("google.com"));
  EXPECT_EQ("google.com",
            ChannelIDService::GetDomainForHost("www.google.com"));
  EXPECT_EQ("foo.appspot.com",
            ChannelIDService::GetDomainForHost("foo.appspot.com"));
  EXPECT_EQ("bar.appspot.com",
            ChannelIDService::GetDomainForHost("foo.bar.appspot.com"));
  EXPECT_EQ("appspot.com",
            ChannelIDService::GetDomainForHost("appspot.com"));
  EXPECT_EQ("google.com",
            ChannelIDService::GetDomainForHost("www.mail.google.com"));
  EXPECT_EQ("goto",
            ChannelIDService::GetDomainForHost("goto"));
  EXPECT_EQ("127.0.0.1",
            ChannelIDService::GetDomainForHost("127.0.0.1"));
}

TEST_F(ChannelIDServiceTest, GetCacheMiss) {
  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Synchronous completion, because the store is initialized.
  std::unique_ptr<crypto::ECPrivateKey> key;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetChannelID(host, &key, callback.callback(), &request);
  EXPECT_THAT(error, IsError(ERR_FILE_NOT_FOUND));
  EXPECT_FALSE(request.is_active());
  EXPECT_EQ(0, service_->channel_id_count());
  EXPECT_FALSE(key);
}

TEST_F(ChannelIDServiceTest, CacheHit) {
  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Asynchronous completion.
  std::unique_ptr<crypto::ECPrivateKey> key1;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetOrCreateChannelID(host, &key1, callback.callback(),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_TRUE(key1);
  EXPECT_FALSE(request.is_active());

  // Synchronous completion.
  std::unique_ptr<crypto::ECPrivateKey> key2;
  error = service_->GetOrCreateChannelID(host, &key2, callback.callback(),
                                         &request);
  EXPECT_FALSE(request.is_active());
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));

  // Synchronous get.
  std::unique_ptr<crypto::ECPrivateKey> key3;
  error = service_->GetChannelID(host, &key3, callback.callback(), &request);
  EXPECT_FALSE(request.is_active());
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_TRUE(KeysEqual(key1.get(), key3.get()));

  EXPECT_EQ(3u, service_->requests());
  EXPECT_EQ(2u, service_->key_store_hits());
  EXPECT_EQ(0u, service_->inflight_joins());
}

TEST_F(ChannelIDServiceTest, StoreChannelIDs) {
  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  std::string host1("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key1;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetOrCreateChannelID(host1, &key1, callback.callback(),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());

  std::string host2("www.verisign.com");
  std::unique_ptr<crypto::ECPrivateKey> key2;
  error = service_->GetOrCreateChannelID(host2, &key2, callback.callback(),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(2, service_->channel_id_count());

  std::string host3("www.twitter.com");
  std::unique_ptr<crypto::ECPrivateKey> key3;
  error = service_->GetOrCreateChannelID(host3, &key3, callback.callback(),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(3, service_->channel_id_count());

  EXPECT_FALSE(KeysEqual(key1.get(), key2.get()));
  EXPECT_FALSE(KeysEqual(key1.get(), key3.get()));
  EXPECT_FALSE(KeysEqual(key2.get(), key3.get()));
}

// Tests an inflight join.
TEST_F(ChannelIDServiceTest, InflightJoin) {
  std::string host("encrypted.google.com");
  int error;

  std::unique_ptr<crypto::ECPrivateKey> key1;
  TestCompletionCallback callback1;
  ChannelIDService::Request request1;

  std::unique_ptr<crypto::ECPrivateKey> key2;
  TestCompletionCallback callback2;
  ChannelIDService::Request request2;

  error = service_->GetOrCreateChannelID(host, &key1, callback1.callback(),
                                         &request1);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request1.is_active());
  // Should join with the original request.
  error = service_->GetOrCreateChannelID(host, &key2, callback2.callback(),
                                         &request2);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request2.is_active());

  error = callback1.WaitForResult();
  EXPECT_THAT(error, IsOk());
  error = callback2.WaitForResult();
  EXPECT_THAT(error, IsOk());

  EXPECT_EQ(2u, service_->requests());
  EXPECT_EQ(0u, service_->key_store_hits());
  EXPECT_EQ(1u, service_->inflight_joins());
  EXPECT_EQ(1u, service_->workers_created());
}

// Tests an inflight join of a Get request to a GetOrCreate request.
TEST_F(ChannelIDServiceTest, InflightJoinGetOrCreateAndGet) {
  std::string host("encrypted.google.com");
  int error;

  std::unique_ptr<crypto::ECPrivateKey> key1;
  TestCompletionCallback callback1;
  ChannelIDService::Request request1;

  std::unique_ptr<crypto::ECPrivateKey> key2;
  TestCompletionCallback callback2;
  ChannelIDService::Request request2;

  error = service_->GetOrCreateChannelID(host, &key1, callback1.callback(),
                                         &request1);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request1.is_active());
  // Should join with the original request.
  error = service_->GetChannelID(host, &key2, callback2.callback(), &request2);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request2.is_active());

  error = callback1.WaitForResult();
  EXPECT_THAT(error, IsOk());
  error = callback2.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));

  EXPECT_EQ(2u, service_->requests());
  EXPECT_EQ(0u, service_->key_store_hits());
  EXPECT_EQ(1u, service_->inflight_joins());
  EXPECT_EQ(1u, service_->workers_created());
}

// Tests that the callback of a canceled request is never made.
TEST_F(ChannelIDServiceTest, CancelRequest) {
  std::string host("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key;
  int error;
  ChannelIDService::Request request;

  error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
  request.Cancel();
  EXPECT_FALSE(request.is_active());

  // Wait for reply from ChannelIDServiceWorker to be posted back to the
  // ChannelIDService.
  NetTestSuite::GetScopedTaskEnvironment()->RunUntilIdle();

  // Even though the original request was cancelled, the service will still
  // store the result, it just doesn't call the callback.
  EXPECT_EQ(1, service_->channel_id_count());
}

// Tests that destructing the Request cancels the request.
TEST_F(ChannelIDServiceTest, CancelRequestByHandleDestruction) {
  std::string host("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key;
  int error;
  std::unique_ptr<ChannelIDService::Request> request(
      new ChannelIDService::Request());

  error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
                                         request.get());
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request->is_active());

  // Delete the Request object.
  request.reset();

  // Wait for reply from ChannelIDServiceWorker to be posted back to the
  // ChannelIDService.
  NetTestSuite::GetScopedTaskEnvironment()->RunUntilIdle();

  // Even though the original request was cancelled, the service will still
  // store the result, it just doesn't call the callback.
  EXPECT_EQ(1, service_->channel_id_count());
}

TEST_F(ChannelIDServiceTest, DestructionWithPendingRequest) {
  std::string host("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key;
  int error;
  ChannelIDService::Request request;

  error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
                                         &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());

  // Cancel request and destroy the ChannelIDService.
  request.Cancel();
  service_.reset();

  // ChannelIDServiceWorker should not post anything back to the
  // non-existent ChannelIDService, but run the loop just to be sure it
  // doesn't.
  base::RunLoop().RunUntilIdle();

  // If we got here without crashing or a valgrind error, it worked.
}

// Tests that making new requests when the ChannelIDService can no longer post
// tasks gracefully fails. This is a regression test for http://crbug.com/236387
TEST_F(ChannelIDServiceTest, RequestAfterPoolShutdown) {
  service_->set_task_runner_for_testing(
      make_scoped_refptr(new base::NullTaskRunner()));

  // Make a request that will force synchronous completion.
  std::string host("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key;
  int error;
  ChannelIDService::Request request;

  error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
                                         &request);
  // If we got here without crashing or a valgrind error, it worked.
  ASSERT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());
}

// Tests that simultaneous creation of different certs works.
TEST_F(ChannelIDServiceTest, SimultaneousCreation) {
  int error;

  std::string host1("encrypted.google.com");
  std::unique_ptr<crypto::ECPrivateKey> key1;
  TestCompletionCallback callback1;
  ChannelIDService::Request request1;

  std::string host2("foo.com");
  std::unique_ptr<crypto::ECPrivateKey> key2;
  TestCompletionCallback callback2;
  ChannelIDService::Request request2;

  std::string host3("bar.com");
  std::unique_ptr<crypto::ECPrivateKey> key3;
  TestCompletionCallback callback3;
  ChannelIDService::Request request3;

  error = service_->GetOrCreateChannelID(host1, &key1, callback1.callback(),
                                         &request1);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request1.is_active());

  error = service_->GetOrCreateChannelID(host2, &key2, callback2.callback(),
                                         &request2);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request2.is_active());

  error = service_->GetOrCreateChannelID(host3, &key3, callback3.callback(),
                                         &request3);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request3.is_active());

  error = callback1.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_TRUE(key1);

  error = callback2.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_TRUE(key2);

  error = callback3.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_TRUE(key3);

  EXPECT_FALSE(KeysEqual(key1.get(), key2.get()));
  EXPECT_FALSE(KeysEqual(key1.get(), key3.get()));
  EXPECT_FALSE(KeysEqual(key2.get(), key3.get()));

  EXPECT_EQ(3, service_->channel_id_count());
}

TEST_F(ChannelIDServiceTest, AsyncStoreGetOrCreateNoChannelIDsInStore) {
  MockChannelIDStoreWithAsyncGet* mock_store =
      new MockChannelIDStoreWithAsyncGet();
  service_ =
      std::unique_ptr<ChannelIDService>(new ChannelIDService(mock_store));

  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Asynchronous completion with no certs in the store.
  std::unique_ptr<crypto::ECPrivateKey> key;
  EXPECT_EQ(0, service_->channel_id_count());
  error =
      service_->GetOrCreateChannelID(host, &key, callback.callback(), &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());

  mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);

  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_TRUE(key);
  EXPECT_FALSE(request.is_active());
}

TEST_F(ChannelIDServiceTest, AsyncStoreGetNoChannelIDsInStore) {
  MockChannelIDStoreWithAsyncGet* mock_store =
      new MockChannelIDStoreWithAsyncGet();
  service_ =
      std::unique_ptr<ChannelIDService>(new ChannelIDService(mock_store));

  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Asynchronous completion with no certs in the store.
  std::unique_ptr<crypto::ECPrivateKey> key;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetChannelID(host, &key, callback.callback(), &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());

  mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);

  error = callback.WaitForResult();
  EXPECT_THAT(error, IsError(ERR_FILE_NOT_FOUND));
  EXPECT_EQ(0, service_->channel_id_count());
  EXPECT_EQ(0u, service_->workers_created());
  EXPECT_FALSE(key);
  EXPECT_FALSE(request.is_active());
}

TEST_F(ChannelIDServiceTest, AsyncStoreGetOrCreateOneCertInStore) {
  MockChannelIDStoreWithAsyncGet* mock_store =
      new MockChannelIDStoreWithAsyncGet();
  service_ =
      std::unique_ptr<ChannelIDService>(new ChannelIDService(mock_store));

  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Asynchronous completion with a cert in the store.
  std::unique_ptr<crypto::ECPrivateKey> key;
  EXPECT_EQ(0, service_->channel_id_count());
  error =
      service_->GetOrCreateChannelID(host, &key, callback.callback(), &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());

  std::unique_ptr<crypto::ECPrivateKey> expected_key(
      crypto::ECPrivateKey::Create());
  mock_store->CallGetChannelIDCallbackWithResult(OK, expected_key.get());

  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_EQ(1u, service_->requests());
  EXPECT_EQ(1u, service_->key_store_hits());
  // Because the cert was found in the store, no new workers should have been
  // created.
  EXPECT_EQ(0u, service_->workers_created());
  EXPECT_TRUE(key);
  EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
  EXPECT_FALSE(request.is_active());
}

TEST_F(ChannelIDServiceTest, AsyncStoreGetOneCertInStore) {
  MockChannelIDStoreWithAsyncGet* mock_store =
      new MockChannelIDStoreWithAsyncGet();
  service_ =
      std::unique_ptr<ChannelIDService>(new ChannelIDService(mock_store));

  std::string host("encrypted.google.com");

  int error;
  TestCompletionCallback callback;
  ChannelIDService::Request request;

  // Asynchronous completion with a cert in the store.
  std::unique_ptr<crypto::ECPrivateKey> key;
  std::string private_key, spki;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetChannelID(host, &key, callback.callback(), &request);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request.is_active());

  std::unique_ptr<crypto::ECPrivateKey> expected_key(
      crypto::ECPrivateKey::Create());
  mock_store->CallGetChannelIDCallbackWithResult(OK, expected_key.get());

  error = callback.WaitForResult();
  EXPECT_THAT(error, IsOk());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_EQ(1u, service_->requests());
  EXPECT_EQ(1u, service_->key_store_hits());
  // Because the cert was found in the store, no new workers should have been
  // created.
  EXPECT_EQ(0u, service_->workers_created());
  EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
  EXPECT_FALSE(request.is_active());
}

TEST_F(ChannelIDServiceTest, AsyncStoreGetThenCreateNoCertsInStore) {
  MockChannelIDStoreWithAsyncGet* mock_store =
      new MockChannelIDStoreWithAsyncGet();
  service_ =
      std::unique_ptr<ChannelIDService>(new ChannelIDService(mock_store));

  std::string host("encrypted.google.com");

  int error;

  // Asynchronous get with no certs in the store.
  TestCompletionCallback callback1;
  ChannelIDService::Request request1;
  std::unique_ptr<crypto::ECPrivateKey> key1;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetChannelID(host, &key1, callback1.callback(), &request1);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request1.is_active());

  // Asynchronous get/create with no certs in the store.
  TestCompletionCallback callback2;
  ChannelIDService::Request request2;
  std::unique_ptr<crypto::ECPrivateKey> key2;
  EXPECT_EQ(0, service_->channel_id_count());
  error = service_->GetOrCreateChannelID(host, &key2, callback2.callback(),
                                         &request2);
  EXPECT_THAT(error, IsError(ERR_IO_PENDING));
  EXPECT_TRUE(request2.is_active());

  mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);

  // Even though the first request didn't ask to create a cert, it gets joined
  // by the second, which does, so both succeed.
  error = callback1.WaitForResult();
  EXPECT_THAT(error, IsOk());
  error = callback2.WaitForResult();
  EXPECT_THAT(error, IsOk());

  // One cert is created, one request is joined.
  EXPECT_EQ(2U, service_->requests());
  EXPECT_EQ(1, service_->channel_id_count());
  EXPECT_EQ(1u, service_->workers_created());
  EXPECT_EQ(1u, service_->inflight_joins());
  EXPECT_TRUE(key1);
  EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));
  EXPECT_FALSE(request1.is_active());
  EXPECT_FALSE(request2.is_active());
}

}  // namespace

}  // namespace net
