| Index: content/common/origin_trials/trial_token_unittest.cc
|
| diff --git a/content/common/origin_trials/trial_token_unittest.cc b/content/common/origin_trials/trial_token_unittest.cc
|
| index dd8350860fc34a3e994efaab11c9a8dff7998072..a9a9f06352cc9f38d32c72b1f4acc0e4e0c9fdee 100644
|
| --- a/content/common/origin_trials/trial_token_unittest.cc
|
| +++ b/content/common/origin_trials/trial_token_unittest.cc
|
| @@ -49,13 +49,11 @@ const uint8_t kTestPublicKey2[] = {
|
|
|
| // This is a good trial token, signed with the above test private key.
|
| const char* kSampleToken =
|
| - "1|UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+"
|
| - "SdUwk7Dyk/qbDw==|https://valid.example.com|Frobulate|1458766277";
|
| -const uint8_t kExpectedVersion = 1;
|
| -const char* kExpectedSignature =
|
| - "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S"
|
| - "dUwk7Dyk/qbDw==";
|
| -const char* kExpectedData = "https://valid.example.com|Frobulate|1458766277";
|
| + "AesWbWX2tRJ0+oGm0ybp9ccm8YTjbV0z5aMVyw2a5zr59hjUU9zLFTgPSz0SPsSU"
|
| + "0c4y51N/9Gx/oLI9W93ZHQkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
|
| + "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
|
| + "IjogMTQ1ODc2NjI3N30=";
|
| +
|
| const char* kExpectedFeatureName = "Frobulate";
|
| const char* kExpectedOrigin = "https://valid.example.com";
|
| const uint64_t kExpectedExpiry = 1458766277;
|
| @@ -74,39 +72,64 @@ double kInvalidTimestamp = 1458766278.0;
|
|
|
| // Well-formed trial token with an invalid signature.
|
| const char* kInvalidSignatureToken =
|
| - "1|CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKYFauBg/"
|
| - "hnxmba765hz0mXMc==|https://valid.example.com|Frobulate|1458766277";
|
| + "AYeNXSDktgG9p4ns5B1WKsLq2TytMxfR4whfbi+oyT0rXyzh+qXYfxbDMGmyjU2Z"
|
| + "lEJ16vQObMXJoOaYUqd8xwkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
|
| + "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
|
| + "IjogMTQ1ODc2NjI3N30=";
|
| +
|
| +// Trial token truncated in the middle of the length field; too short to
|
| +// possibly be valid.
|
| +const char kTruncatedToken[] =
|
| + "AesWbWX2tRJ0+oGm0ybp9ccm8YTjbV0z5aMVyw2a5zr59hjUU9zLFTgPSz0SPsSU"
|
| + "0c4y51N/9Gx/oLI9W93ZHQkA";
|
| +
|
| +// Trial token with an incorrectly-declared length, but with a valid signature.
|
| +const char kIncorrectLengthToken[] =
|
| + "AQruItutcZelo3W81CdbVHuUFygSJ6Zpktgnl1JIE+QHEMz0ZqjITe1nWdq7c1VC"
|
| + "EdMFVozO5VIgX3mUWYLsTw4AAABaeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
|
| + "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
|
| + "IjogMTQ1ODc2NjI3N30=";
|
| +
|
| +// Trial token with a misidentified version (2).
|
| +const char kIncorrectVersionToken[] =
|
| + "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj"
|
| + "7FO5L22sNvkZZnacLvmfNwsAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
|
| + "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
|
| + "IjogMTQ1ODc2NjI3N30=";
|
| +
|
| +const char kSampleTokenJSON[] =
|
| + "{\"origin\": \"https://valid.example.com:443\", \"feature\": "
|
| + "\"Frobulate\", \"expiry\": 1458766277}";
|
|
|
| // Various ill-formed trial tokens. These should all fail to parse.
|
| const char* kInvalidTokens[] = {
|
| - // Invalid - only one part
|
| + // Invalid - Not JSON at all
|
| "abcde",
|
| - // Not enough parts
|
| - "https://valid.example.com|FeatureName|1458766277",
|
| - "Signature|https://valid.example.com|FeatureName|1458766277",
|
| - // Non-numeric version
|
| - "a|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - "1x|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - // Unsupported version (< min, > max, negative, overflow)
|
| - "0|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - "2|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - "-1|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - "99999|Signature|https://valid.example.com|FeatureName|1458766277",
|
| - // Delimiter in feature name
|
| - "1|Signature|https://valid.example.com|Feature|Name|1458766277",
|
| - // Extra string field
|
| - "1|Signature|https://valid.example.com|FeatureName|1458766277|ExtraField",
|
| - // Extra numeric field
|
| - "1|Signature|https://valid.example.com|FeatureName|1458766277|1458766277",
|
| - // Non-numeric expiry timestamp
|
| - "1|Signature|https://valid.example.com|FeatureName|abcdefghij",
|
| - "1|Signature|https://valid.example.com|FeatureName|1458766277x",
|
| + // Invalid JSON
|
| + "{",
|
| + // Not an object
|
| + "\"abcde\"",
|
| + "123.4",
|
| + "[0, 1, 2]",
|
| + // Missing keys
|
| + "{}",
|
| + "{\"something\": 1}",
|
| + "{\"origin\": \"https://a.a\"}",
|
| + "{\"origin\": \"https://a.a\", \"feature\": \"a\"}"
|
| + "{\"origin\": \"https://a.a\", \"expiry\": 1458766277}",
|
| + "{\"feature\": \"FeatureName\", \"expiry\": 1458766277}",
|
| + // Incorrect types
|
| + "{\"origin\": 1, \"feature\": \"a\", \"expiry\": 1458766277}",
|
| + "{\"origin\": \"https://a.a\", \"feature\": 1, \"expiry\": 1458766277}",
|
| + "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": \"1\"}",
|
| // Negative expiry timestamp
|
| - "1|Signature|https://valid.example.com|FeatureName|-1458766277",
|
| + "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": -1}",
|
| // Origin not a proper origin URL
|
| - "1|Signature|abcdef|FeatureName|1458766277",
|
| - "1|Signature|data:text/plain,abcdef|FeatureName|1458766277",
|
| - "1|Signature|javascript:alert(1)|FeatureName|1458766277"};
|
| + "{\"origin\": \"abcdef\", \"feature\": \"a\", \"expiry\": 1458766277}",
|
| + "{\"origin\": \"data:text/plain,abcdef\", \"feature\": \"a\", \"expiry\": "
|
| + "1458766277}",
|
| + "{\"origin\": \"javascript:alert(1)\", \"feature\": \"a\", \"expiry\": "
|
| + "1458766277}"};
|
| const size_t kNumInvalidTokens = arraysize(kInvalidTokens);
|
|
|
| } // namespace
|
| @@ -117,6 +140,9 @@ class TrialTokenTest : public testing::Test {
|
| : expected_origin_(GURL(kExpectedOrigin)),
|
| invalid_origin_(GURL(kInvalidOrigin)),
|
| insecure_origin_(GURL(kInsecureOrigin)),
|
| + expected_expiry_(base::Time::FromDoubleT(kExpectedExpiry)),
|
| + valid_timestamp_(base::Time::FromDoubleT(kValidTimestamp)),
|
| + invalid_timestamp_(base::Time::FromDoubleT(kInvalidTimestamp)),
|
| correct_public_key_(
|
| base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
|
| arraysize(kTestPublicKey))),
|
| @@ -125,6 +151,14 @@ class TrialTokenTest : public testing::Test {
|
| arraysize(kTestPublicKey2))) {}
|
|
|
| protected:
|
| + scoped_ptr<std::string> Extract(const std::string& token_text,
|
| + base::StringPiece public_key) {
|
| + return TrialToken::Extract(token_text, public_key);
|
| + }
|
| + scoped_ptr<TrialToken> Parse(const std::string& token_payload) {
|
| + return TrialToken::Parse(token_payload);
|
| + }
|
| +
|
| bool ValidateOrigin(TrialToken* token, const url::Origin origin) {
|
| return token->ValidateOrigin(origin);
|
| }
|
| @@ -137,11 +171,6 @@ class TrialTokenTest : public testing::Test {
|
| return token->ValidateDate(now);
|
| }
|
|
|
| - bool ValidateSignature(TrialToken* token,
|
| - const base::StringPiece& public_key) {
|
| - return token->ValidateSignature(public_key);
|
| - }
|
| -
|
| base::StringPiece correct_public_key() { return correct_public_key_; }
|
| base::StringPiece incorrect_public_key() { return incorrect_public_key_; }
|
|
|
| @@ -149,37 +178,88 @@ class TrialTokenTest : public testing::Test {
|
| const url::Origin invalid_origin_;
|
| const url::Origin insecure_origin_;
|
|
|
| + const base::Time expected_expiry_;
|
| + const base::Time valid_timestamp_;
|
| + const base::Time invalid_timestamp_;
|
| +
|
| private:
|
| base::StringPiece correct_public_key_;
|
| base::StringPiece incorrect_public_key_;
|
| };
|
|
|
| +// Test the extraction of the signed payload from token strings. This includes
|
| +// checking the included version identifier, payload length, and cryptographic
|
| +// signature.
|
| +
|
| +/* Test verification of signature and extraction of token JSON from signed token
|
| + */
|
| +TEST_F(TrialTokenTest, ValidateValidSignature) {
|
| + scoped_ptr<std::string> tokenJSON =
|
| + Extract(kSampleToken, correct_public_key());
|
| + ASSERT_TRUE(tokenJSON);
|
| + EXPECT_STREQ(kSampleTokenJSON, tokenJSON.get()->c_str());
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateInvalidSignature) {
|
| + scoped_ptr<std::string> tokenJSON =
|
| + Extract(kInvalidSignatureToken, correct_public_key());
|
| + ASSERT_FALSE(tokenJSON);
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
|
| + scoped_ptr<std::string> tokenJSON =
|
| + Extract(kSampleToken, incorrect_public_key());
|
| + ASSERT_FALSE(tokenJSON);
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateEmptyToken) {
|
| + scoped_ptr<std::string> tokenJSON = Extract("", correct_public_key());
|
| + ASSERT_FALSE(tokenJSON);
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateShortToken) {
|
| + scoped_ptr<std::string> tokenJSON =
|
| + Extract(kTruncatedToken, correct_public_key());
|
| + ASSERT_FALSE(tokenJSON);
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateUnsupportedVersion) {
|
| + scoped_ptr<std::string> tokenJSON =
|
| + Extract(kIncorrectVersionToken, correct_public_key());
|
| + ASSERT_FALSE(tokenJSON);
|
| +}
|
| +
|
| +TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectLength) {
|
| + scoped_ptr<std::string> token =
|
| + Extract(kIncorrectLengthToken, correct_public_key());
|
| + ASSERT_FALSE(token);
|
| +}
|
| +
|
| +/* Test parsing of fields from JSON token */
|
| +
|
| TEST_F(TrialTokenTest, ParseEmptyString) {
|
| - scoped_ptr<TrialToken> empty_token = TrialToken::Parse("");
|
| + scoped_ptr<TrialToken> empty_token = Parse("");
|
| EXPECT_FALSE(empty_token);
|
| }
|
|
|
| TEST_F(TrialTokenTest, ParseInvalidStrings) {
|
| for (size_t i = 0; i < kNumInvalidTokens; ++i) {
|
| - scoped_ptr<TrialToken> empty_token = TrialToken::Parse(kInvalidTokens[i]);
|
| + scoped_ptr<TrialToken> empty_token = Parse(kInvalidTokens[i]);
|
| EXPECT_FALSE(empty_token) << "Invalid trial token should not parse: "
|
| << kInvalidTokens[i];
|
| }
|
| }
|
|
|
| TEST_F(TrialTokenTest, ParseValidToken) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| + scoped_ptr<TrialToken> token = Parse(kSampleTokenJSON);
|
| ASSERT_TRUE(token);
|
| - EXPECT_EQ(kExpectedVersion, token->version());
|
| EXPECT_EQ(kExpectedFeatureName, token->feature_name());
|
| - EXPECT_EQ(kExpectedSignature, token->signature());
|
| - EXPECT_EQ(kExpectedData, token->data());
|
| EXPECT_EQ(expected_origin_, token->origin());
|
| - EXPECT_EQ(base::Time::FromDoubleT(kExpectedExpiry), token->expiry_time());
|
| + EXPECT_EQ(expected_expiry_, token->expiry_time());
|
| }
|
|
|
| TEST_F(TrialTokenTest, ValidateValidToken) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| + scoped_ptr<TrialToken> token = Parse(kSampleTokenJSON);
|
| ASSERT_TRUE(token);
|
| EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_));
|
| EXPECT_FALSE(ValidateOrigin(token.get(), invalid_origin_));
|
| @@ -190,54 +270,30 @@ TEST_F(TrialTokenTest, ValidateValidToken) {
|
| token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str()));
|
| EXPECT_FALSE(ValidateFeatureName(
|
| token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str()));
|
| - EXPECT_TRUE(
|
| - ValidateDate(token.get(), base::Time::FromDoubleT(kValidTimestamp)));
|
| - EXPECT_FALSE(
|
| - ValidateDate(token.get(), base::Time::FromDoubleT(kInvalidTimestamp)));
|
| + EXPECT_TRUE(ValidateDate(token.get(), valid_timestamp_));
|
| + EXPECT_FALSE(ValidateDate(token.get(), invalid_timestamp_));
|
| }
|
|
|
| -TEST_F(TrialTokenTest, TokenIsAppropriateForOriginAndFeature) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| +TEST_F(TrialTokenTest, TokenIsValidForFeature) {
|
| + scoped_ptr<TrialToken> token = Parse(kSampleTokenJSON);
|
| ASSERT_TRUE(token);
|
| - EXPECT_TRUE(token->IsAppropriate(expected_origin_, kExpectedFeatureName));
|
| - EXPECT_FALSE(token->IsAppropriate(expected_origin_,
|
| - base::ToUpperASCII(kExpectedFeatureName)));
|
| - EXPECT_FALSE(token->IsAppropriate(expected_origin_,
|
| - base::ToLowerASCII(kExpectedFeatureName)));
|
| - EXPECT_FALSE(token->IsAppropriate(invalid_origin_, kExpectedFeatureName));
|
| - EXPECT_FALSE(token->IsAppropriate(insecure_origin_, kExpectedFeatureName));
|
| - EXPECT_FALSE(token->IsAppropriate(expected_origin_, kInvalidFeatureName));
|
| + EXPECT_TRUE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName,
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(
|
| + expected_origin_, base::ToUpperASCII(kExpectedFeatureName),
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(
|
| + expected_origin_, base::ToLowerASCII(kExpectedFeatureName),
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(invalid_origin_, kExpectedFeatureName,
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(insecure_origin_, kExpectedFeatureName,
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kInvalidFeatureName,
|
| + valid_timestamp_));
|
| + EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName,
|
| + invalid_timestamp_));
|
| }
|
|
|
| -TEST_F(TrialTokenTest, ValidateValidSignature) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| - ASSERT_TRUE(token);
|
| - EXPECT_TRUE(ValidateSignature(token.get(), correct_public_key()));
|
| -}
|
| -
|
| -TEST_F(TrialTokenTest, ValidateInvalidSignature) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kInvalidSignatureToken);
|
| - ASSERT_TRUE(token);
|
| - EXPECT_FALSE(ValidateSignature(token.get(), correct_public_key()));
|
| -}
|
| -
|
| -TEST_F(TrialTokenTest, ValidateTokenWithCorrectKey) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| - ASSERT_TRUE(token);
|
| - EXPECT_TRUE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
|
| - correct_public_key()));
|
| -}
|
| -
|
| -TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| - ASSERT_TRUE(token);
|
| - EXPECT_FALSE(token->IsValid(base::Time::FromDoubleT(kValidTimestamp),
|
| - incorrect_public_key()));
|
| -}
|
| -
|
| -TEST_F(TrialTokenTest, ValidateWhenNotExpired) {
|
| - scoped_ptr<TrialToken> token = TrialToken::Parse(kSampleToken);
|
| - ASSERT_TRUE(token);
|
| -}
|
|
|
| } // namespace content
|
|
|