| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_validator.h" | 5 #include "content/common/origin_trials/trial_token_validator.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 // Well-formed token, for an insecure origin. | 105 // Well-formed token, for an insecure origin. |
| 106 // Generate this token with the command (in tools/origin_trials): | 106 // Generate this token with the command (in tools/origin_trials): |
| 107 // generate_token.py http://valid.example.com Frobulate | 107 // generate_token.py http://valid.example.com Frobulate |
| 108 // --expire-timestamp=2000000000 | 108 // --expire-timestamp=2000000000 |
| 109 const char kInsecureOriginToken[] = | 109 const char kInsecureOriginToken[] = |
| 110 "AjfC47H1q8/Ho5ALFkjkwf9CBK6oUUeRTlFc50Dj+eZEyGGKFIY2WTxMBfy8cLc3" | 110 "AjfC47H1q8/Ho5ALFkjkwf9CBK6oUUeRTlFc50Dj+eZEyGGKFIY2WTxMBfy8cLc3" |
| 111 "E0nmFroDA3OmABmO5jMCFgkAAABXeyJvcmlnaW4iOiAiaHR0cDovL3ZhbGlkLmV4" | 111 "E0nmFroDA3OmABmO5jMCFgkAAABXeyJvcmlnaW4iOiAiaHR0cDovL3ZhbGlkLmV4" |
| 112 "YW1wbGUuY29tOjgwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6" | 112 "YW1wbGUuY29tOjgwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6" |
| 113 "IDIwMDAwMDAwMDB9"; | 113 "IDIwMDAwMDAwMDB9"; |
| 114 | 114 |
| 115 // These timestamps should be in the past and future, respectively. Sanity | 115 // This timestamp is set to a time after the expiry timestamp of kExpiredToken, |
| 116 // checks within the tests assert that that is true, to guard against poorly-set | 116 // but before the expiry timestamp of kValidToken. |
| 117 // system clocks. (And against the inevitable march of time past the year 2033) | 117 double kNowTimestamp = 1500000000; |
| 118 double kPastTimestamp = 1000000000; | |
| 119 double kFutureTimestamp = 2000000000; | |
| 120 | 118 |
| 121 class TestOriginTrialPolicy : public OriginTrialPolicy { | 119 class TestOriginTrialPolicy : public OriginTrialPolicy { |
| 122 public: | 120 public: |
| 123 base::StringPiece GetPublicKey() const override { | 121 base::StringPiece GetPublicKey() const override { |
| 124 return base::StringPiece(reinterpret_cast<const char*>(key_), | 122 return base::StringPiece(reinterpret_cast<const char*>(key_), |
| 125 arraysize(kTestPublicKey)); | 123 arraysize(kTestPublicKey)); |
| 126 } | 124 } |
| 127 bool IsFeatureDisabled(base::StringPiece feature) const override { | 125 bool IsFeatureDisabled(base::StringPiece feature) const override { |
| 128 return disabled_features_.count(feature.as_string()) > 0; | 126 return disabled_features_.count(feature.as_string()) > 0; |
| 129 } | 127 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 expired_token_signature_( | 181 expired_token_signature_( |
| 184 std::string(reinterpret_cast<const char*>(kExpiredTokenSignature), | 182 std::string(reinterpret_cast<const char*>(kExpiredTokenSignature), |
| 185 arraysize(kExpiredTokenSignature))), | 183 arraysize(kExpiredTokenSignature))), |
| 186 response_headers_(new net::HttpResponseHeaders("")) { | 184 response_headers_(new net::HttpResponseHeaders("")) { |
| 187 SetPublicKey(kTestPublicKey); | 185 SetPublicKey(kTestPublicKey); |
| 188 SetContentClient(&test_content_client_); | 186 SetContentClient(&test_content_client_); |
| 189 } | 187 } |
| 190 | 188 |
| 191 ~TrialTokenValidatorTest() override { SetContentClient(nullptr); } | 189 ~TrialTokenValidatorTest() override { SetContentClient(nullptr); } |
| 192 | 190 |
| 193 void SetUp() override { | |
| 194 // Ensure that the system clock is set to a date that the matches the test | |
| 195 // expectations. If this fails, either the clock on the test device is | |
| 196 // incorrect, or the actual date is after 2033-05-18, and the tokens need to | |
| 197 // be regenerated. | |
| 198 ASSERT_GT(base::Time::Now(), base::Time::FromDoubleT(kPastTimestamp)); | |
| 199 ASSERT_LT(base::Time::Now(), base::Time::FromDoubleT(kFutureTimestamp)); | |
| 200 } | |
| 201 | |
| 202 void SetPublicKey(const uint8_t* key) { | 191 void SetPublicKey(const uint8_t* key) { |
| 203 test_content_client_.SetOriginTrialPublicKey(key); | 192 test_content_client_.SetOriginTrialPublicKey(key); |
| 204 } | 193 } |
| 205 | 194 |
| 206 void DisableFeature(const std::string& feature) { | 195 void DisableFeature(const std::string& feature) { |
| 207 test_content_client_.DisableFeature(feature); | 196 test_content_client_.DisableFeature(feature); |
| 208 } | 197 } |
| 209 | 198 |
| 210 void DisableToken(const std::string& token_signature) { | 199 void DisableToken(const std::string& token_signature) { |
| 211 test_content_client_.DisableToken(token_signature); | 200 test_content_client_.DisableToken(token_signature); |
| 212 } | 201 } |
| 213 | 202 |
| 203 base::Time Now() { return base::Time::FromDoubleT(kNowTimestamp); } |
| 204 |
| 214 const url::Origin appropriate_origin_; | 205 const url::Origin appropriate_origin_; |
| 215 const url::Origin inappropriate_origin_; | 206 const url::Origin inappropriate_origin_; |
| 216 const url::Origin insecure_origin_; | 207 const url::Origin insecure_origin_; |
| 217 | 208 |
| 218 std::string valid_token_signature_; | 209 std::string valid_token_signature_; |
| 219 std::string expired_token_signature_; | 210 std::string expired_token_signature_; |
| 220 | 211 |
| 221 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 212 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 222 | 213 |
| 223 private: | 214 private: |
| 224 TestContentClient test_content_client_; | 215 TestContentClient test_content_client_; |
| 225 }; | 216 }; |
| 226 | 217 |
| 227 // Flaky on Android swarming bots: crbug.com/672294 | 218 TEST_F(TrialTokenValidatorTest, ValidateValidToken) { |
| 228 #if defined(OS_ANDROID) | |
| 229 #define MAYBE_ValidateValidToken DISABLED_ValidateValidToken | |
| 230 #else | |
| 231 #define MAYBE_ValidateValidToken ValidateValidToken | |
| 232 #endif | |
| 233 TEST_F(TrialTokenValidatorTest, MAYBE_ValidateValidToken) { | |
| 234 std::string feature; | 219 std::string feature; |
| 235 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, | 220 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, |
| 236 TrialTokenValidator::ValidateToken(kSampleToken, | 221 TrialTokenValidator::ValidateToken( |
| 237 appropriate_origin_, &feature)); | 222 kSampleToken, appropriate_origin_, &feature, Now())); |
| 238 EXPECT_EQ(kAppropriateFeatureName, feature); | 223 EXPECT_EQ(kAppropriateFeatureName, feature); |
| 239 } | 224 } |
| 240 | 225 |
| 241 TEST_F(TrialTokenValidatorTest, ValidateInappropriateOrigin) { | 226 TEST_F(TrialTokenValidatorTest, ValidateInappropriateOrigin) { |
| 242 std::string feature; | 227 std::string feature; |
| 243 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin, | 228 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin, |
| 244 TrialTokenValidator::ValidateToken( | 229 TrialTokenValidator::ValidateToken( |
| 245 kSampleToken, inappropriate_origin_, &feature)); | 230 kSampleToken, inappropriate_origin_, &feature, Now())); |
| 246 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin, | 231 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin, |
| 247 TrialTokenValidator::ValidateToken(kSampleToken, insecure_origin_, | 232 TrialTokenValidator::ValidateToken(kSampleToken, insecure_origin_, |
| 248 &feature)); | 233 &feature, Now())); |
| 249 } | 234 } |
| 250 | 235 |
| 251 TEST_F(TrialTokenValidatorTest, ValidateInvalidSignature) { | 236 TEST_F(TrialTokenValidatorTest, ValidateInvalidSignature) { |
| 252 std::string feature; | 237 std::string feature; |
| 253 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature, | 238 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature, |
| 254 TrialTokenValidator::ValidateToken(kInvalidSignatureToken, | 239 TrialTokenValidator::ValidateToken( |
| 255 appropriate_origin_, &feature)); | 240 kInvalidSignatureToken, appropriate_origin_, &feature, Now())); |
| 256 } | 241 } |
| 257 | 242 |
| 258 TEST_F(TrialTokenValidatorTest, ValidateUnparsableToken) { | 243 TEST_F(TrialTokenValidatorTest, ValidateUnparsableToken) { |
| 259 std::string feature; | 244 std::string feature; |
| 260 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kMalformed, | 245 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kMalformed, |
| 261 TrialTokenValidator::ValidateToken(kUnparsableToken, | 246 TrialTokenValidator::ValidateToken( |
| 262 appropriate_origin_, &feature)); | 247 kUnparsableToken, appropriate_origin_, &feature, Now())); |
| 263 } | 248 } |
| 264 | 249 |
| 265 TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) { | 250 TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) { |
| 266 std::string feature; | 251 std::string feature; |
| 267 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kExpired, | 252 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kExpired, |
| 268 TrialTokenValidator::ValidateToken(kExpiredToken, | 253 TrialTokenValidator::ValidateToken( |
| 269 appropriate_origin_, &feature)); | 254 kExpiredToken, appropriate_origin_, &feature, Now())); |
| 270 } | 255 } |
| 271 | 256 |
| 272 TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) { | 257 TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) { |
| 273 std::string feature; | 258 std::string feature; |
| 274 SetPublicKey(kTestPublicKey2); | 259 SetPublicKey(kTestPublicKey2); |
| 275 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature, | 260 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature, |
| 276 TrialTokenValidator::ValidateToken(kSampleToken, | 261 TrialTokenValidator::ValidateToken( |
| 277 appropriate_origin_, &feature)); | 262 kSampleToken, appropriate_origin_, &feature, Now())); |
| 278 } | 263 } |
| 279 | 264 |
| 280 // Flaky on Android swarming bots: crbug.com/672294 | 265 TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledFeatures) { |
| 281 #if defined(OS_ANDROID) | |
| 282 #define MAYBE_ValidatorRespectsDisabledFeatures DISABLED_ValidatorRespectsDisabl
edFeatures | |
| 283 #else | |
| 284 #define MAYBE_ValidatorRespectsDisabledFeatures ValidatorRespectsDisabledFeature
s | |
| 285 #endif | |
| 286 TEST_F(TrialTokenValidatorTest, MAYBE_ValidatorRespectsDisabledFeatures) { | |
| 287 std::string feature; | 266 std::string feature; |
| 288 // Disable an irrelevant feature; token should still validate | 267 // Disable an irrelevant feature; token should still validate |
| 289 DisableFeature(kInappropriateFeatureName); | 268 DisableFeature(kInappropriateFeatureName); |
| 290 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, | 269 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, |
| 291 TrialTokenValidator::ValidateToken(kSampleToken, | 270 TrialTokenValidator::ValidateToken( |
| 292 appropriate_origin_, &feature)); | 271 kSampleToken, appropriate_origin_, &feature, Now())); |
| 293 EXPECT_EQ(kAppropriateFeatureName, feature); | 272 EXPECT_EQ(kAppropriateFeatureName, feature); |
| 294 // Disable the token's feature; it should no longer be valid | 273 // Disable the token's feature; it should no longer be valid |
| 295 DisableFeature(kAppropriateFeatureName); | 274 DisableFeature(kAppropriateFeatureName); |
| 296 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kFeatureDisabled, | 275 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kFeatureDisabled, |
| 297 TrialTokenValidator::ValidateToken(kSampleToken, | 276 TrialTokenValidator::ValidateToken( |
| 298 appropriate_origin_, &feature)); | 277 kSampleToken, appropriate_origin_, &feature, Now())); |
| 299 } | 278 } |
| 300 | 279 |
| 301 TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledTokens) { | 280 TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledTokens) { |
| 302 std::string feature; | 281 std::string feature; |
| 303 // Disable an irrelevant token; token should still validate | 282 // Disable an irrelevant token; token should still validate |
| 304 DisableToken(expired_token_signature_); | 283 DisableToken(expired_token_signature_); |
| 305 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, | 284 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess, |
| 306 TrialTokenValidator::ValidateToken(kSampleToken, | 285 TrialTokenValidator::ValidateToken( |
| 307 appropriate_origin_, &feature)); | 286 kSampleToken, appropriate_origin_, &feature, Now())); |
| 308 EXPECT_EQ(kAppropriateFeatureName, feature); | 287 EXPECT_EQ(kAppropriateFeatureName, feature); |
| 309 // Disable the token; it should no longer be valid | 288 // Disable the token; it should no longer be valid |
| 310 DisableToken(valid_token_signature_); | 289 DisableToken(valid_token_signature_); |
| 311 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kTokenDisabled, | 290 EXPECT_EQ(blink::WebOriginTrialTokenStatus::kTokenDisabled, |
| 312 TrialTokenValidator::ValidateToken(kSampleToken, | 291 TrialTokenValidator::ValidateToken( |
| 313 appropriate_origin_, &feature)); | 292 kSampleToken, appropriate_origin_, &feature, Now())); |
| 314 } | 293 } |
| 315 | 294 |
| 316 TEST_F(TrialTokenValidatorTest, ValidateRequestInsecure) { | 295 TEST_F(TrialTokenValidatorTest, ValidateRequestInsecure) { |
| 317 response_headers_->AddHeader(std::string("Origin-Trial: ") + | 296 response_headers_->AddHeader(std::string("Origin-Trial: ") + |
| 318 kInsecureOriginToken); | 297 kInsecureOriginToken); |
| 319 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 298 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 320 GURL(kInsecureOrigin), response_headers_.get(), kAppropriateFeatureName)); | 299 GURL(kInsecureOrigin), response_headers_.get(), kAppropriateFeatureName, |
| 300 Now())); |
| 321 } | 301 } |
| 322 | 302 |
| 323 // Flaky on Android swarming bots: crbug.com/672294 | 303 TEST_F(TrialTokenValidatorTest, ValidateRequestValidToken) { |
| 324 #if defined(OS_ANDROID) | |
| 325 #define MAYBE_ValidateRequestValidToken DISABLED_ValidateRequestValidToken | |
| 326 #else | |
| 327 #define MAYBE_ValidateRequestValidToken ValidateRequestValidToken | |
| 328 #endif | |
| 329 TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestValidToken) { | |
| 330 response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken); | 304 response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken); |
| 331 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( | 305 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( |
| 332 GURL(kAppropriateOrigin), response_headers_.get(), | 306 GURL(kAppropriateOrigin), response_headers_.get(), |
| 333 kAppropriateFeatureName)); | 307 kAppropriateFeatureName, Now())); |
| 334 } | 308 } |
| 335 | 309 |
| 336 TEST_F(TrialTokenValidatorTest, ValidateRequestNoTokens) { | 310 TEST_F(TrialTokenValidatorTest, ValidateRequestNoTokens) { |
| 337 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 311 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 338 GURL(kAppropriateOrigin), response_headers_.get(), | 312 GURL(kAppropriateOrigin), response_headers_.get(), |
| 339 kAppropriateFeatureName)); | 313 kAppropriateFeatureName, Now())); |
| 340 } | 314 } |
| 341 | 315 |
| 342 // Flaky on Android swarming bots: crbug.com/672294 | 316 TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaders) { |
| 343 #if defined(OS_ANDROID) | |
| 344 #define MAYBE_ValidateRequestMultipleHeaders DISABLED_ValidateRequestMultipleHea
ders | |
| 345 #else | |
| 346 #define MAYBE_ValidateRequestMultipleHeaders ValidateRequestMultipleHeaders | |
| 347 #endif | |
| 348 TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestMultipleHeaders) { | |
| 349 response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken); | 317 response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken); |
| 350 response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken); | 318 response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken); |
| 351 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( | 319 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( |
| 352 GURL(kAppropriateOrigin), response_headers_.get(), | 320 GURL(kAppropriateOrigin), response_headers_.get(), |
| 353 kAppropriateFeatureName)); | 321 kAppropriateFeatureName, Now())); |
| 354 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 322 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 355 GURL(kAppropriateOrigin), response_headers_.get(), | 323 GURL(kAppropriateOrigin), response_headers_.get(), |
| 356 kInappropriateFeatureName)); | 324 kInappropriateFeatureName, Now())); |
| 357 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 325 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 358 GURL(kInappropriateOrigin), response_headers_.get(), | 326 GURL(kInappropriateOrigin), response_headers_.get(), |
| 359 kAppropriateFeatureName)); | 327 kAppropriateFeatureName, Now())); |
| 360 } | 328 } |
| 361 | 329 |
| 362 // Flaky on Android swarming bots: crbug.com/672294 | 330 TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaderValues) { |
| 363 #if defined(OS_ANDROID) | |
| 364 #define MAYBE_ValidateRequestMultipleHeaderValues DISABLED_ValidateRequestMultip
leHeaderValues | |
| 365 #else | |
| 366 #define MAYBE_ValidateRequestMultipleHeaderValues ValidateRequestMultipleHeaderV
alues | |
| 367 #endif | |
| 368 TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestMultipleHeaderValues) { | |
| 369 response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken + | 331 response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken + |
| 370 ", " + kSampleToken); | 332 ", " + kSampleToken); |
| 371 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( | 333 EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature( |
| 372 GURL(kAppropriateOrigin), response_headers_.get(), | 334 GURL(kAppropriateOrigin), response_headers_.get(), |
| 373 kAppropriateFeatureName)); | 335 kAppropriateFeatureName, Now())); |
| 374 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 336 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 375 GURL(kAppropriateOrigin), response_headers_.get(), | 337 GURL(kAppropriateOrigin), response_headers_.get(), |
| 376 kInappropriateFeatureName)); | 338 kInappropriateFeatureName, Now())); |
| 377 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( | 339 EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature( |
| 378 GURL(kInappropriateOrigin), response_headers_.get(), | 340 GURL(kInappropriateOrigin), response_headers_.get(), |
| 379 kAppropriateFeatureName)); | 341 kAppropriateFeatureName, Now())); |
| 380 } | 342 } |
| 381 | 343 |
| 382 } // namespace content | 344 } // namespace content |
| OLD | NEW |