• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/internal_auth.h"
6 
7 #include <algorithm>
8 
9 #include "base/lazy_instance.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace chrome {
15 
16 class InternalAuthTest : public ::testing::Test {
17  public:
InternalAuthTest()18   InternalAuthTest() {
19     long_string_ = "seed";
20     for (int i = 20; i--;)
21       long_string_ += long_string_;
22   }
~InternalAuthTest()23   virtual ~InternalAuthTest() {}
24 
SetUp()25   virtual void SetUp() {
26   }
27 
TearDown()28   virtual void TearDown() {
29   }
30 
31   base::MessageLoop message_loop_;
32   std::string long_string_;
33 };
34 
TEST_F(InternalAuthTest,BasicGeneration)35 TEST_F(InternalAuthTest, BasicGeneration) {
36   std::map<std::string, std::string> map;
37   map["key"] = "value";
38   std::string token = InternalAuthGeneration::GeneratePassport(
39       "zapata", map);
40   ASSERT_GT(token.size(), 10u);  // short token is insecure.
41 
42   map["key2"] = "value2";
43   token = InternalAuthGeneration::GeneratePassport("zapata", map);
44   ASSERT_GT(token.size(), 10u);
45 }
46 
TEST_F(InternalAuthTest,DoubleGeneration)47 TEST_F(InternalAuthTest, DoubleGeneration) {
48   std::map<std::string, std::string> map;
49   map["key"] = "value";
50   std::string token1 = InternalAuthGeneration::GeneratePassport(
51       "zapata", map);
52   ASSERT_GT(token1.size(), 10u);
53 
54   std::string token2 = InternalAuthGeneration::GeneratePassport(
55       "zapata", map);
56   ASSERT_GT(token2.size(), 10u);
57   // tokens are different even if credentials coincide.
58   ASSERT_NE(token1, token2);
59 }
60 
TEST_F(InternalAuthTest,BadGeneration)61 TEST_F(InternalAuthTest, BadGeneration) {
62   std::map<std::string, std::string> map;
63   map["key"] = "value";
64   // Trying huge domain.
65   std::string token = InternalAuthGeneration::GeneratePassport(
66       long_string_, map);
67   ASSERT_TRUE(token.empty());
68   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
69       token, long_string_, map));
70 
71   // Trying empty domain.
72   token = InternalAuthGeneration::GeneratePassport(std::string(), map);
73   ASSERT_TRUE(token.empty());
74   ASSERT_FALSE(
75       InternalAuthVerification::VerifyPassport(token, std::string(), map));
76 
77   std::string dummy("abcdefghij");
78   for (size_t i = 1000; i--;) {
79     std::string key = dummy;
80     std::next_permutation(dummy.begin(), dummy.end());
81     std::string value = dummy;
82     std::next_permutation(dummy.begin(), dummy.end());
83     map[key] = value;
84   }
85   // Trying huge var=value map.
86   token = InternalAuthGeneration::GeneratePassport("zapata", map);
87   ASSERT_TRUE(token.empty());
88   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
89 
90   map.clear();
91   map[std::string()] = "value";
92   // Trying empty key.
93   token = InternalAuthGeneration::GeneratePassport("zapata", map);
94   ASSERT_TRUE(token.empty());
95   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
96 }
97 
TEST_F(InternalAuthTest,BasicVerification)98 TEST_F(InternalAuthTest, BasicVerification) {
99   std::map<std::string, std::string> map;
100   map["key"] = "value";
101   std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
102   ASSERT_GT(token.size(), 10u);
103   ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
104   // Passport can not be reused.
105   for (int i = 1000; i--;) {
106     ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
107         token, "zapata", map));
108   }
109 }
110 
TEST_F(InternalAuthTest,BruteForce)111 TEST_F(InternalAuthTest, BruteForce) {
112   std::map<std::string, std::string> map;
113   map["key"] = "value";
114   std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
115   ASSERT_GT(token.size(), 10u);
116 
117   // Trying bruteforce.
118   std::string dummy = token;
119   for (size_t i = 100; i--;) {
120     std::next_permutation(dummy.begin(), dummy.end());
121     ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
122         dummy, "zapata", map));
123   }
124   dummy = token;
125   for (size_t i = 100; i--;) {
126     std::next_permutation(dummy.begin(), dummy.begin() + dummy.size() / 2);
127     ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
128         dummy, "zapata", map));
129   }
130   // We brute forced just too little, so original token must not expire yet.
131   ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
132 }
133 
TEST_F(InternalAuthTest,ExpirationAndBruteForce)134 TEST_F(InternalAuthTest, ExpirationAndBruteForce) {
135   int kCustomVerificationWindow = 2;
136   InternalAuthVerification::set_verification_window_seconds(
137       kCustomVerificationWindow);
138 
139   std::map<std::string, std::string> map;
140   map["key"] = "value";
141   std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
142   ASSERT_GT(token.size(), 10u);
143 
144   // We want to test token expiration, so we need to wait some amount of time,
145   // so we are brute-forcing during this time.
146   base::Time timestamp = base::Time::Now();
147   std::string dummy1 = token;
148   std::string dummy2 = token;
149   for (;;) {
150     for (size_t i = 100; i--;) {
151       std::next_permutation(dummy1.begin(), dummy1.end());
152       ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
153           dummy1, "zapata", map));
154     }
155     for (size_t i = 100; i--;) {
156       std::next_permutation(dummy2.begin(), dummy2.begin() + dummy2.size() / 2);
157       ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
158           dummy2, "zapata", map));
159     }
160     if (base::Time::Now() - timestamp > base::TimeDelta::FromSeconds(
161         kCustomVerificationWindow + 1)) {
162       break;
163     }
164   }
165   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
166   // Reset verification window to default.
167   InternalAuthVerification::set_verification_window_seconds(0);
168 }
169 
TEST_F(InternalAuthTest,ChangeKey)170 TEST_F(InternalAuthTest, ChangeKey) {
171   std::map<std::string, std::string> map;
172   map["key"] = "value";
173   std::string token = InternalAuthGeneration::GeneratePassport("zapata", map);
174   ASSERT_GT(token.size(), 10u);
175 
176   InternalAuthGeneration::GenerateNewKey();
177   // Passport should survive key change.
178   ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
179 
180   token = InternalAuthGeneration::GeneratePassport("zapata", map);
181   ASSERT_GT(token.size(), 10u);
182   for (int i = 20; i--;)
183     InternalAuthGeneration::GenerateNewKey();
184   // Passport should not survive series of key changes.
185   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
186 }
187 
188 }  // namespace chrome
189