// Copyright (c) 2012 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 "chrome/browser/internal_auth.h"

#include <stddef.h>

#include <algorithm>

#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"

class InternalAuthTest : public ::testing::Test {
 public:
  InternalAuthTest() {
    long_string_ = "seed";
    for (int i = 20; i--;)
      long_string_ += long_string_;
  }
  ~InternalAuthTest() override {}

  void SetUp() override {}

  void TearDown() override {}

  base::MessageLoop message_loop_;
  std::string long_string_;
};

TEST_F(InternalAuthTest, BasicGeneration) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token = InternalAuthGeneration::GeneratePassport(
      "zapata", map);
  ASSERT_GT(token.size(), 10u);  // short token is insecure.

  map["key2"] = "value2";
  token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);
}

TEST_F(InternalAuthTest, DoubleGeneration) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token1 = InternalAuthGeneration::GeneratePassport(
      "zapata", map);
  ASSERT_GT(token1.size(), 10u);

  std::string token2 = InternalAuthGeneration::GeneratePassport(
      "zapata", map);
  ASSERT_GT(token2.size(), 10u);
  // tokens are different even if credentials coincide.
  ASSERT_NE(token1, token2);
}

TEST_F(InternalAuthTest, BadGeneration) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  // Trying huge domain.
  std::string token = InternalAuthGeneration::GeneratePassport(
      long_string_, map);
  ASSERT_TRUE(token.empty());
  ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
      token, long_string_, map));

  // Trying empty domain.
  token = InternalAuthGeneration::GeneratePassport(std::string(), map);
  ASSERT_TRUE(token.empty());
  ASSERT_FALSE(
      InternalAuthVerification::VerifyPassport(token, std::string(), map));

  std::string dummy("abcdefghij");
  for (size_t i = 1000; i--;) {
    std::string key = dummy;
    std::next_permutation(dummy.begin(), dummy.end());
    std::string value = dummy;
    std::next_permutation(dummy.begin(), dummy.end());
    map[key] = value;
  }
  // Trying huge var=value map.
  token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_TRUE(token.empty());
  ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));

  map.clear();
  map[std::string()] = "value";
  // Trying empty key.
  token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_TRUE(token.empty());
  ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
}

TEST_F(InternalAuthTest, BasicVerification) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);
  ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
  // Passport can not be reused.
  for (int i = 1000; i--;) {
    ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
        token, "zapata", map));
  }
}

TEST_F(InternalAuthTest, BruteForce) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);

  // Trying bruteforce.
  std::string dummy = token;
  for (size_t i = 100; i--;) {
    std::next_permutation(dummy.begin(), dummy.end());
    ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
        dummy, "zapata", map));
  }
  dummy = token;
  for (size_t i = 100; i--;) {
    std::next_permutation(dummy.begin(), dummy.begin() + dummy.size() / 2);
    ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
        dummy, "zapata", map));
  }
  // We brute forced just too little, so original token must not expire yet.
  ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
}

TEST_F(InternalAuthTest, ExpirationAndBruteForce) {
  int kCustomVerificationWindow = 2;
  InternalAuthVerification::set_verification_window_seconds(
      kCustomVerificationWindow);

  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);

  // We want to test token expiration, so we need to wait some amount of time,
  // so we are brute-forcing during this time.
  base::Time timestamp = base::Time::Now();
  std::string dummy1 = token;
  std::string dummy2 = token;
  for (;;) {
    for (size_t i = 100; i--;) {
      std::next_permutation(dummy1.begin(), dummy1.end());
      ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
          dummy1, "zapata", map));
    }
    for (size_t i = 100; i--;) {
      std::next_permutation(dummy2.begin(), dummy2.begin() + dummy2.size() / 2);
      ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
          dummy2, "zapata", map));
    }
    if (base::Time::Now() - timestamp > base::TimeDelta::FromSeconds(
        kCustomVerificationWindow + 1)) {
      break;
    }
  }
  ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
  // Reset verification window to default.
  InternalAuthVerification::set_verification_window_seconds(0);
}

TEST_F(InternalAuthTest, ChangeKey) {
  std::map<std::string, std::string> map;
  map["key"] = "value";
  std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);

  InternalAuthGeneration::GenerateNewKey();
  // Passport should survive key change.
  ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));

  token = InternalAuthGeneration::GeneratePassport("zapata", map);
  ASSERT_GT(token.size(), 10u);
  for (int i = 20; i--;)
    InternalAuthGeneration::GenerateNewKey();
  // Passport should not survive series of key changes.
  ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
}
