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.
5 #include "chrome/browser/internal_auth.h"
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"
16 class InternalAuthTest
: public ::testing::Test
{
19 long_string_
= "seed";
20 for (int i
= 20; i
--;)
21 long_string_
+= long_string_
;
23 virtual ~InternalAuthTest() {}
25 virtual void SetUp() {
28 virtual void TearDown() {
31 base::MessageLoop message_loop_
;
32 std::string long_string_
;
35 TEST_F(InternalAuthTest
, BasicGeneration
) {
36 std::map
<std::string
, std::string
> map
;
38 std::string token
= InternalAuthGeneration::GeneratePassport(
40 ASSERT_GT(token
.size(), 10u); // short token is insecure.
42 map
["key2"] = "value2";
43 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
44 ASSERT_GT(token
.size(), 10u);
47 TEST_F(InternalAuthTest
, DoubleGeneration
) {
48 std::map
<std::string
, std::string
> map
;
50 std::string token1
= InternalAuthGeneration::GeneratePassport(
52 ASSERT_GT(token1
.size(), 10u);
54 std::string token2
= InternalAuthGeneration::GeneratePassport(
56 ASSERT_GT(token2
.size(), 10u);
57 // tokens are different even if credentials coincide.
58 ASSERT_NE(token1
, token2
);
61 TEST_F(InternalAuthTest
, BadGeneration
) {
62 std::map
<std::string
, std::string
> map
;
64 // Trying huge domain.
65 std::string token
= InternalAuthGeneration::GeneratePassport(
67 ASSERT_TRUE(token
.empty());
68 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
69 token
, long_string_
, map
));
71 // Trying empty domain.
72 token
= InternalAuthGeneration::GeneratePassport(std::string(), map
);
73 ASSERT_TRUE(token
.empty());
75 InternalAuthVerification::VerifyPassport(token
, std::string(), map
));
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());
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
));
91 map
[std::string()] = "value";
93 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
94 ASSERT_TRUE(token
.empty());
95 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
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
));
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);
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
));
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
));
130 // We brute forced just too little, so original token must not expire yet.
131 ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
134 TEST_F(InternalAuthTest
, ExpirationAndBruteForce
) {
135 int kCustomVerificationWindow
= 2;
136 InternalAuthVerification::set_verification_window_seconds(
137 kCustomVerificationWindow
);
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);
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
;
150 for (size_t i
= 100; i
--;) {
151 std::next_permutation(dummy1
.begin(), dummy1
.end());
152 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
153 dummy1
, "zapata", map
));
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
));
160 if (base::Time::Now() - timestamp
> base::TimeDelta::FromSeconds(
161 kCustomVerificationWindow
+ 1)) {
165 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
166 // Reset verification window to default.
167 InternalAuthVerification::set_verification_window_seconds(0);
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);
176 InternalAuthGeneration::GenerateNewKey();
177 // Passport should survive key change.
178 ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
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
));
188 } // namespace chrome