// 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(
      base::MakeRefCounted<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
