Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: content/common/origin_trials/trial_token_unittest.cc

Issue 1858763003: Change origin trial token format (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update parser unit tests, improve error detection Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/origin_trials/trial_token.h" 5 #include "content/common/origin_trials/trial_token.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_piece.h" 9 #include "base/strings/string_piece.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e, 42 // 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
43 // 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca 43 // 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
44 const uint8_t kTestPublicKey2[] = { 44 const uint8_t kTestPublicKey2[] = {
45 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 45 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
46 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 46 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
47 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca, 47 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
48 }; 48 };
49 49
50 // This is a good trial token, signed with the above test private key. 50 // This is a good trial token, signed with the above test private key.
51 const char* kSampleToken = 51 const char* kSampleToken =
52 "1|UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+" 52 "AesWbWX2tRJ0+oGm0ybp9ccm8YTjbV0z5aMVyw2a5zr59hjUU9zLFTgPSz0SPsSU"
53 "SdUwk7Dyk/qbDw==|https://valid.example.com|Frobulate|1458766277"; 53 "0c4y51N/9Gx/oLI9W93ZHQkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
54 const uint8_t kExpectedVersion = 1; 54 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
55 const char* kExpectedSignature = 55 "IjogMTQ1ODc2NjI3N30=";
56 "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S" 56
57 "dUwk7Dyk/qbDw==";
58 const char* kExpectedData = "https://valid.example.com|Frobulate|1458766277";
59 const char* kExpectedFeatureName = "Frobulate"; 57 const char* kExpectedFeatureName = "Frobulate";
60 const char* kExpectedOrigin = "https://valid.example.com"; 58 const char* kExpectedOrigin = "https://valid.example.com";
61 const uint64_t kExpectedExpiry = 1458766277; 59 const uint64_t kExpectedExpiry = 1458766277;
62 60
63 // The token should not be valid for this origin, or for this feature. 61 // The token should not be valid for this origin, or for this feature.
64 const char* kInvalidOrigin = "https://invalid.example.com"; 62 const char* kInvalidOrigin = "https://invalid.example.com";
65 const char* kInsecureOrigin = "http://valid.example.com"; 63 const char* kInsecureOrigin = "http://valid.example.com";
66 const char* kInvalidFeatureName = "Grokalyze"; 64 const char* kInvalidFeatureName = "Grokalyze";
67 65
68 // The token should be valid if the current time is kValidTimestamp or earlier. 66 // The token should be valid if the current time is kValidTimestamp or earlier.
69 double kValidTimestamp = 1458766276.0; 67 double kValidTimestamp = 1458766276.0;
70 68
71 // The token should be invalid if the current time is kInvalidTimestamp or 69 // The token should be invalid if the current time is kInvalidTimestamp or
72 // later. 70 // later.
73 double kInvalidTimestamp = 1458766278.0; 71 double kInvalidTimestamp = 1458766278.0;
74 72
75 // Well-formed trial token with an invalid signature. 73 // Well-formed trial token with an invalid signature.
76 const char* kInvalidSignatureToken = 74 const char* kInvalidSignatureToken =
77 "1|CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKYFauBg/" 75 "AYeNXSDktgG9p4ns5B1WKsLq2TytMxfR4whfbi+oyT0rXyzh+qXYfxbDMGmyjU2Z"
78 "hnxmba765hz0mXMc==|https://valid.example.com|Frobulate|1458766277"; 76 "lEJ16vQObMXJoOaYUqd8xwkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
77 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
78 "IjogMTQ1ODc2NjI3N30=";
79
80 // Trial token truncated in the middle of the length field; too short to
81 // possibly be valid.
82 const char kTruncatedToken[] =
83 "AesWbWX2tRJ0+oGm0ybp9ccm8YTjbV0z5aMVyw2a5zr59hjUU9zLFTgPSz0SPsSU"
84 "0c4y51N/9Gx/oLI9W93ZHQkA";
85
86 // Trial token with an incorrectly-declared length, but with a valid signature.
87 const char kIncorrectLengthToken[] =
88 "AQruItutcZelo3W81CdbVHuUFygSJ6Zpktgnl1JIE+QHEMz0ZqjITe1nWdq7c1VC"
89 "EdMFVozO5VIgX3mUWYLsTw4AAABaeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
90 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
91 "IjogMTQ1ODc2NjI3N30=";
92
93 // Trial token with a misidentified version (2).
94 const char kIncorrectVersionToken[] =
95 "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj"
96 "7FO5L22sNvkZZnacLvmfNwsAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
97 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
98 "IjogMTQ1ODc2NjI3N30=";
99
100 const char kSampleTokenJSON[] =
101 "{\"origin\": \"https://valid.example.com:443\", \"feature\": "
102 "\"Frobulate\", \"expiry\": 1458766277}";
79 103
80 // Various ill-formed trial tokens. These should all fail to parse. 104 // Various ill-formed trial tokens. These should all fail to parse.
81 const char* kInvalidTokens[] = { 105 const char* kInvalidTokens[] = {
82 // Invalid - only one part 106 // Invalid - Not JSON at all
83 "abcde", 107 "abcde",
84 // Not enough parts 108 // Invalid JSON
85 "https://valid.example.com|FeatureName|1458766277", 109 "{",
86 "Signature|https://valid.example.com|FeatureName|1458766277", 110 // Not an object
87 // Non-numeric version 111 "\"abcde\"",
88 "a|Signature|https://valid.example.com|FeatureName|1458766277", 112 "123.4",
89 "1x|Signature|https://valid.example.com|FeatureName|1458766277", 113 "[0, 1, 2]",
90 // Unsupported version (< min, > max, negative, overflow) 114 // Missing keys
91 "0|Signature|https://valid.example.com|FeatureName|1458766277", 115 "{}",
92 "2|Signature|https://valid.example.com|FeatureName|1458766277", 116 "{\"something\": 1}",
93 "-1|Signature|https://valid.example.com|FeatureName|1458766277", 117 "{\"origin\": \"https://a.a\"}",
94 "99999|Signature|https://valid.example.com|FeatureName|1458766277", 118 "{\"origin\": \"https://a.a\", \"feature\": \"a\"}"
95 // Delimiter in feature name 119 "{\"origin\": \"https://a.a\", \"expiry\": 1458766277}",
96 "1|Signature|https://valid.example.com|Feature|Name|1458766277", 120 "{\"feature\": \"FeatureName\", \"expiry\": 1458766277}",
97 // Extra string field 121 // Incorrect types
98 "1|Signature|https://valid.example.com|FeatureName|1458766277|ExtraField", 122 "{\"origin\": 1, \"feature\": \"a\", \"expiry\": 1458766277}",
99 // Extra numeric field 123 "{\"origin\": \"https://a.a\", \"feature\": 1, \"expiry\": 1458766277}",
100 "1|Signature|https://valid.example.com|FeatureName|1458766277|1458766277", 124 "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": \"1\"}",
101 // Non-numeric expiry timestamp
102 "1|Signature|https://valid.example.com|FeatureName|abcdefghij",
103 "1|Signature|https://valid.example.com|FeatureName|1458766277x",
104 // Negative expiry timestamp 125 // Negative expiry timestamp
105 "1|Signature|https://valid.example.com|FeatureName|-1458766277", 126 "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": -1}",
106 // Origin not a proper origin URL 127 // Origin not a proper origin URL
107 "1|Signature|abcdef|FeatureName|1458766277", 128 "{\"origin\": \"abcdef\", \"feature\": \"a\", \"expiry\": 1458766277}",
108 "1|Signature|data:text/plain,abcdef|FeatureName|1458766277", 129 "{\"origin\": \"data:text/plain,abcdef\", \"feature\": \"a\", \"expiry\": "
109 "1|Signature|javascript:alert(1)|FeatureName|1458766277"}; 130 "1458766277}",
131 "{\"origin\": \"javascript:alert(1)\", \"feature\": \"a\", \"expiry\": "
132 "1458766277}"};
110 const size_t kNumInvalidTokens = arraysize(kInvalidTokens); 133 const size_t kNumInvalidTokens = arraysize(kInvalidTokens);
111 134
112 } // namespace 135 } // namespace
113 136
114 class TrialTokenTest : public testing::Test { 137 class TrialTokenTest : public testing::Test {
115 public: 138 public:
116 TrialTokenTest() 139 TrialTokenTest()
117 : expected_origin_(GURL(kExpectedOrigin)), 140 : expected_origin_(GURL(kExpectedOrigin)),
118 invalid_origin_(GURL(kInvalidOrigin)), 141 invalid_origin_(GURL(kInvalidOrigin)),
119 insecure_origin_(GURL(kInsecureOrigin)), 142 insecure_origin_(GURL(kInsecureOrigin)),
(...skipping 27 matching lines...) Expand all
147 170
148 const url::Origin expected_origin_; 171 const url::Origin expected_origin_;
149 const url::Origin invalid_origin_; 172 const url::Origin invalid_origin_;
150 const url::Origin insecure_origin_; 173 const url::Origin insecure_origin_;
151 174
152 private: 175 private:
153 base::StringPiece correct_public_key_; 176 base::StringPiece correct_public_key_;
154 base::StringPiece incorrect_public_key_; 177 base::StringPiece incorrect_public_key_;
155 }; 178 };
156 179
180 // Test the extraction of the signed payload from token strings. This includes
181 // checking the included version identifier, payload length, and cryptographic
182 // signature.
183
184 /* Test verification of signature and extraction of token JSON from signed token
185 */
186 TEST_F(TrialTokenTest, ValidateValidSignature) {
187 scoped_ptr<std::string> tokenJSON =
188 TrialToken::Extract(kSampleToken, correct_public_key());
189 ASSERT_TRUE(tokenJSON);
190 EXPECT_STREQ(kSampleTokenJSON, tokenJSON.get()->c_str());
191 }
192
193 TEST_F(TrialTokenTest, ValidateInvalidSignature) {
194 scoped_ptr<std::string> tokenJSON =
195 TrialToken::Extract(kInvalidSignatureToken, correct_public_key());
196 ASSERT_FALSE(tokenJSON);
197 }
198
199 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
200 scoped_ptr<std::string> tokenJSON =
201 TrialToken::Extract(kSampleToken, incorrect_public_key());
202 ASSERT_FALSE(tokenJSON);
203 }
204
205 TEST_F(TrialTokenTest, ValidateEmptyToken) {
206 scoped_ptr<std::string> tokenJSON =
207 TrialToken::Extract("", correct_public_key());
208 ASSERT_FALSE(tokenJSON);
209 }
210
211 TEST_F(TrialTokenTest, ValidateShortToken) {
212 scoped_ptr<std::string> tokenJSON =
213 TrialToken::Extract(kTruncatedToken, correct_public_key());
214 ASSERT_FALSE(tokenJSON);
215 }
216
217 TEST_F(TrialTokenTest, ValidateUnsupportedVersion) {
218 scoped_ptr<std::string> tokenJSON =
219 TrialToken::Extract(kIncorrectVersionToken, correct_public_key());
220 ASSERT_FALSE(tokenJSON);
221 }
222
223 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectLength) {
224 scoped_ptr<std::string> token =
225 TrialToken::Extract(kIncorrectLengthToken, correct_public_key());
226 ASSERT_FALSE(token);
227 }
228
229 /* Test parsing of fields from JSON token */
230
157 TEST_F(TrialTokenTest, ParseEmptyString) { 231 TEST_F(TrialTokenTest, ParseEmptyString) {
158 scoped_ptr<TrialToken> empty_token = TrialToken::Parse(""); 232 scoped_ptr<TrialToken> empty_token = TrialToken::Parse("");
159 EXPECT_FALSE(empty_token); 233 EXPECT_FALSE(empty_token);
160 } 234 }
161 235
162 TEST_F(TrialTokenTest, ParseInvalidStrings) { 236 TEST_F(TrialTokenTest, ParseInvalidStrings) {
163 for (size_t i = 0; i < kNumInvalidTokens; ++i) { 237 for (size_t i = 0; i < kNumInvalidTokens; ++i) {
164 scoped_ptr<TrialToken> empty_token = TrialToken::Parse(kInvalidTokens[i]); 238 scoped_ptr<TrialToken> empty_token = TrialToken::Parse(kInvalidTokens[i]);
165 EXPECT_FALSE(empty_token) << "Invalid trial token should not parse: " 239 EXPECT_FALSE(empty_token) << "Invalid trial token should not parse: "
166 << kInvalidTokens[i]; 240 << kInvalidTokens[i];
167 } 241 }
168 } 242 }
169 243
170 TEST_F(TrialTokenTest, ParseValidToken) { 244 TEST_F(TrialTokenTest, ParseValidToken) {
171 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken); 245 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleTokenJSON);
172 ASSERT_TRUE(token); 246 ASSERT_TRUE(token);
173 EXPECT_EQ(kExpectedVersion, token->version());
174 EXPECT_EQ(kExpectedFeatureName, token->feature_name()); 247 EXPECT_EQ(kExpectedFeatureName, token->feature_name());
175 EXPECT_EQ(kExpectedSignature, token->signature());
176 EXPECT_EQ(kExpectedData, token->data());
177 EXPECT_EQ(expected_origin_, token->origin()); 248 EXPECT_EQ(expected_origin_, token->origin());
178 EXPECT_EQ(base::Time::FromDoubleT(kExpectedExpiry), token->expiry_time()); 249 EXPECT_EQ(base::Time::FromDoubleT(kExpectedExpiry), token->expiry_time());
179 } 250 }
180 251
181 TEST_F(TrialTokenTest, ValidateValidToken) { 252 TEST_F(TrialTokenTest, ValidateValidToken) {
182 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken); 253 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleTokenJSON);
183 ASSERT_TRUE(token); 254 ASSERT_TRUE(token);
184 EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_)); 255 EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_));
185 EXPECT_FALSE(ValidateOrigin(token.get(), invalid_origin_)); 256 EXPECT_FALSE(ValidateOrigin(token.get(), invalid_origin_));
186 EXPECT_FALSE(ValidateOrigin(token.get(), insecure_origin_)); 257 EXPECT_FALSE(ValidateOrigin(token.get(), insecure_origin_));
187 EXPECT_TRUE(ValidateFeatureName(token.get(), kExpectedFeatureName)); 258 EXPECT_TRUE(ValidateFeatureName(token.get(), kExpectedFeatureName));
188 EXPECT_FALSE(ValidateFeatureName(token.get(), kInvalidFeatureName)); 259 EXPECT_FALSE(ValidateFeatureName(token.get(), kInvalidFeatureName));
189 EXPECT_FALSE(ValidateFeatureName( 260 EXPECT_FALSE(ValidateFeatureName(
190 token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str())); 261 token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str()));
191 EXPECT_FALSE(ValidateFeatureName( 262 EXPECT_FALSE(ValidateFeatureName(
192 token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str())); 263 token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str()));
193 EXPECT_TRUE( 264 EXPECT_TRUE(
194 ValidateDate(token.get(), base::Time::FromDoubleT(kValidTimestamp))); 265 ValidateDate(token.get(), base::Time::FromDoubleT(kValidTimestamp)));
195 EXPECT_FALSE( 266 EXPECT_FALSE(
196 ValidateDate(token.get(), base::Time::FromDoubleT(kInvalidTimestamp))); 267 ValidateDate(token.get(), base::Time::FromDoubleT(kInvalidTimestamp)));
197 } 268 }
198 269
199 TEST_F(TrialTokenTest, TokenIsAppropriateForOriginAndFeature) { 270 TEST_F(TrialTokenTest, TokenIsAppropriateForOriginAndFeature) {
200 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken); 271 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleTokenJSON);
201 ASSERT_TRUE(token); 272 ASSERT_TRUE(token);
202 EXPECT_TRUE(token->IsAppropriate(expected_origin_, kExpectedFeatureName)); 273 EXPECT_TRUE(token->IsAppropriate(expected_origin_, kExpectedFeatureName));
203 EXPECT_FALSE(token->IsAppropriate(expected_origin_, 274 EXPECT_FALSE(token->IsAppropriate(expected_origin_,
204 base::ToUpperASCII(kExpectedFeatureName))); 275 base::ToUpperASCII(kExpectedFeatureName)));
205 EXPECT_FALSE(token->IsAppropriate(expected_origin_, 276 EXPECT_FALSE(token->IsAppropriate(expected_origin_,
206 base::ToLowerASCII(kExpectedFeatureName))); 277 base::ToLowerASCII(kExpectedFeatureName)));
207 EXPECT_FALSE(token->IsAppropriate(invalid_origin_, kExpectedFeatureName)); 278 EXPECT_FALSE(token->IsAppropriate(invalid_origin_, kExpectedFeatureName));
208 EXPECT_FALSE(token->IsAppropriate(insecure_origin_, kExpectedFeatureName)); 279 EXPECT_FALSE(token->IsAppropriate(insecure_origin_, kExpectedFeatureName));
209 EXPECT_FALSE(token->IsAppropriate(expected_origin_, kInvalidFeatureName)); 280 EXPECT_FALSE(token->IsAppropriate(expected_origin_, kInvalidFeatureName));
210 } 281 }
211 282
212 TEST_F(TrialTokenTest, ValidateValidSignature) {
213 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
214 ASSERT_TRUE(token);
215 EXPECT_TRUE(ValidateSignature(token.get(), correct_public_key()));
216 }
217
218 TEST_F(TrialTokenTest, ValidateInvalidSignature) {
219 scoped_ptr<TrialToken> token = TrialToken::Parse(kInvalidSignatureToken);
220 ASSERT_TRUE(token);
221 EXPECT_FALSE(ValidateSignature(token.get(), correct_public_key()));
222 }
223
224 TEST_F(TrialTokenTest, ValidateTokenWithCorrectKey) {
225 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
226 ASSERT_TRUE(token);
227 EXPECT_TRUE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
228 correct_public_key()));
229 }
230
231 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
232 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
233 ASSERT_TRUE(token);
234 EXPECT_FALSE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
235 incorrect_public_key()));
236 }
237
238 TEST_F(TrialTokenTest, ValidateWhenNotExpired) {
239 scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
240 ASSERT_TRUE(token);
241 }
242 283
243 } // namespace content 284 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698