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 ~InternalAuthTest() override
{}
25 void SetUp() override
{}
27 void TearDown() override
{}
29 base::MessageLoop message_loop_
;
30 std::string long_string_
;
33 TEST_F(InternalAuthTest
, BasicGeneration
) {
34 std::map
<std::string
, std::string
> map
;
36 std::string token
= InternalAuthGeneration::GeneratePassport(
38 ASSERT_GT(token
.size(), 10u); // short token is insecure.
40 map
["key2"] = "value2";
41 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
42 ASSERT_GT(token
.size(), 10u);
45 TEST_F(InternalAuthTest
, DoubleGeneration
) {
46 std::map
<std::string
, std::string
> map
;
48 std::string token1
= InternalAuthGeneration::GeneratePassport(
50 ASSERT_GT(token1
.size(), 10u);
52 std::string token2
= InternalAuthGeneration::GeneratePassport(
54 ASSERT_GT(token2
.size(), 10u);
55 // tokens are different even if credentials coincide.
56 ASSERT_NE(token1
, token2
);
59 TEST_F(InternalAuthTest
, BadGeneration
) {
60 std::map
<std::string
, std::string
> map
;
62 // Trying huge domain.
63 std::string token
= InternalAuthGeneration::GeneratePassport(
65 ASSERT_TRUE(token
.empty());
66 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
67 token
, long_string_
, map
));
69 // Trying empty domain.
70 token
= InternalAuthGeneration::GeneratePassport(std::string(), map
);
71 ASSERT_TRUE(token
.empty());
73 InternalAuthVerification::VerifyPassport(token
, std::string(), map
));
75 std::string
dummy("abcdefghij");
76 for (size_t i
= 1000; i
--;) {
77 std::string key
= dummy
;
78 std::next_permutation(dummy
.begin(), dummy
.end());
79 std::string value
= dummy
;
80 std::next_permutation(dummy
.begin(), dummy
.end());
83 // Trying huge var=value map.
84 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
85 ASSERT_TRUE(token
.empty());
86 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
89 map
[std::string()] = "value";
91 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
92 ASSERT_TRUE(token
.empty());
93 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
96 TEST_F(InternalAuthTest
, BasicVerification
) {
97 std::map
<std::string
, std::string
> map
;
99 std::string token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
100 ASSERT_GT(token
.size(), 10u);
101 ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
102 // Passport can not be reused.
103 for (int i
= 1000; i
--;) {
104 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
105 token
, "zapata", map
));
109 TEST_F(InternalAuthTest
, BruteForce
) {
110 std::map
<std::string
, std::string
> map
;
111 map
["key"] = "value";
112 std::string token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
113 ASSERT_GT(token
.size(), 10u);
115 // Trying bruteforce.
116 std::string dummy
= token
;
117 for (size_t i
= 100; i
--;) {
118 std::next_permutation(dummy
.begin(), dummy
.end());
119 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
120 dummy
, "zapata", map
));
123 for (size_t i
= 100; i
--;) {
124 std::next_permutation(dummy
.begin(), dummy
.begin() + dummy
.size() / 2);
125 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
126 dummy
, "zapata", map
));
128 // We brute forced just too little, so original token must not expire yet.
129 ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
132 TEST_F(InternalAuthTest
, ExpirationAndBruteForce
) {
133 int kCustomVerificationWindow
= 2;
134 InternalAuthVerification::set_verification_window_seconds(
135 kCustomVerificationWindow
);
137 std::map
<std::string
, std::string
> map
;
138 map
["key"] = "value";
139 std::string token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
140 ASSERT_GT(token
.size(), 10u);
142 // We want to test token expiration, so we need to wait some amount of time,
143 // so we are brute-forcing during this time.
144 base::Time timestamp
= base::Time::Now();
145 std::string dummy1
= token
;
146 std::string dummy2
= token
;
148 for (size_t i
= 100; i
--;) {
149 std::next_permutation(dummy1
.begin(), dummy1
.end());
150 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
151 dummy1
, "zapata", map
));
153 for (size_t i
= 100; i
--;) {
154 std::next_permutation(dummy2
.begin(), dummy2
.begin() + dummy2
.size() / 2);
155 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(
156 dummy2
, "zapata", map
));
158 if (base::Time::Now() - timestamp
> base::TimeDelta::FromSeconds(
159 kCustomVerificationWindow
+ 1)) {
163 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
164 // Reset verification window to default.
165 InternalAuthVerification::set_verification_window_seconds(0);
168 TEST_F(InternalAuthTest
, ChangeKey
) {
169 std::map
<std::string
, std::string
> map
;
170 map
["key"] = "value";
171 std::string token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
172 ASSERT_GT(token
.size(), 10u);
174 InternalAuthGeneration::GenerateNewKey();
175 // Passport should survive key change.
176 ASSERT_TRUE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
178 token
= InternalAuthGeneration::GeneratePassport("zapata", map
);
179 ASSERT_GT(token
.size(), 10u);
180 for (int i
= 20; i
--;)
181 InternalAuthGeneration::GenerateNewKey();
182 // Passport should not survive series of key changes.
183 ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token
, "zapata", map
));
186 } // namespace chrome