diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 18:59:06 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 18:59:06 +0000 |
commit | 2fc4c21d0b6cebaf8ebc101cc3fe20ef38407373 (patch) | |
tree | 9dbd8252cd5ad79a1ee356b0bfc0635b73d07bac | |
parent | a39f1a98657144b7be6eb294820fb363f8267582 (diff) | |
download | chromium_src-2fc4c21d0b6cebaf8ebc101cc3fe20ef38407373.zip chromium_src-2fc4c21d0b6cebaf8ebc101cc3fe20ef38407373.tar.gz chromium_src-2fc4c21d0b6cebaf8ebc101cc3fe20ef38407373.tar.bz2 |
Add paypal.com to the preloaded STS list.
TEST=Navigating to http://paypal.com should always be rewritten to https
BUG=none
http://codereview.chromium.org/815003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41180 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/base/transport_security_state.cc | 45 | ||||
-rw-r--r-- | net/base/transport_security_state.h | 4 | ||||
-rw-r--r-- | net/base/transport_security_state_unittest.cc | 188 |
3 files changed, 163 insertions, 74 deletions
diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc index 54d8cce..d033b94 100644 --- a/net/base/transport_security_state.cc +++ b/net/base/transport_security_state.cc @@ -27,6 +27,11 @@ void TransportSecurityState::EnableHost(const std::string& host, const std::string canonicalised_host = CanonicaliseHost(host); if (canonicalised_host.empty()) return; + + bool temp; + if (isPreloadedSTS(canonicalised_host, &temp)) + return; + char hashed[base::SHA256_LENGTH]; base::SHA256HashString(canonicalised_host, hashed, sizeof(hashed)); @@ -48,6 +53,14 @@ bool TransportSecurityState::IsEnabledForHost(DomainState* result, if (canonicalised_host.empty()) return false; + bool include_subdomains; + if (isPreloadedSTS(canonicalised_host, &include_subdomains)) { + result->created = result->expiry = base::Time::FromTimeT(0); + result->mode = DomainState::MODE_STRICT; + result->include_subdomains = include_subdomains; + return true; + } + base::Time current_time(base::Time::Now()); AutoLock lock(lock_); @@ -378,4 +391,36 @@ std::string TransportSecurityState::CanonicaliseHost(const std::string& host) { return new_host; } +// isPreloadedSTS returns true if the canonicalised hostname should always be +// considered to have STS enabled. +// static +bool TransportSecurityState::isPreloadedSTS( + const std::string& canonicalised_host, bool *include_subdomains) { + // In the medium term this list is likely to just be hardcoded here. This, + // slightly odd, form removes the need for additional relocations records. + static const struct { + uint8 length; + bool include_subdomains; + char dns_name[30]; + } preloadedSTS[] = { + {16, false, "\003www\006paypal\003com"}, + }; + static const size_t numPreloadedSTS = + sizeof(preloadedSTS) / sizeof(preloadedSTS[0]); + + for (size_t i = 0; canonicalised_host[i]; i += canonicalised_host[i] + 1) { + for (size_t j = 0; j < numPreloadedSTS; j++) { + if (preloadedSTS[j].length == canonicalised_host.size() + 1 - i && + (preloadedSTS[j].include_subdomains || i == 0) && + memcmp(preloadedSTS[j].dns_name, &canonicalised_host[i], + preloadedSTS[j].length) == 0) { + *include_subdomains = preloadedSTS[j].include_subdomains; + return true; + } + } + } + + return false; +} + } // namespace diff --git a/net/base/transport_security_state.h b/net/base/transport_security_state.h index 523f28e..05a0fc1 100644 --- a/net/base/transport_security_state.h +++ b/net/base/transport_security_state.h @@ -12,6 +12,7 @@ #include "base/lock.h" #include "base/ref_counted.h" #include "base/time.h" +#include "testing/gtest/include/gtest/gtest_prod.h" class GURL; @@ -88,6 +89,7 @@ class TransportSecurityState : private: friend class base::RefCountedThreadSafe<TransportSecurityState>; + FRIEND_TEST(TransportSecurityStateTest, IsPreloaded); ~TransportSecurityState() {} @@ -107,6 +109,8 @@ class TransportSecurityState : Delegate* delegate_; static std::string CanonicaliseHost(const std::string& host); + static bool isPreloadedSTS(const std::string& canonicalised_host, + bool* out_include_subdomains); DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); }; diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc index 2561b0b..6250105 100644 --- a/net/base/transport_security_state_unittest.cc +++ b/net/base/transport_security_state_unittest.cc @@ -5,6 +5,8 @@ #include "net/base/transport_security_state.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + class TransportSecurityStateTest : public testing::Test { }; @@ -12,71 +14,71 @@ TEST_F(TransportSecurityStateTest, BogusHeaders) { int max_age = 42; bool include_subdomains = false; - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "abc", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " abc", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " abc ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age=", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age =", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age= ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age = ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age = xy", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( " max-age = 3488a923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488a923 ", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-ag=3488923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-aged=3488923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age==3488923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "amax-age=3488923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=-3488923", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923;", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 e", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomain", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923includesubdomains", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923=includesubdomains", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomainx", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomain=", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomain=true", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomainsx", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=3488923 includesubdomains x", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=34889.23 includesubdomains", &max_age, &include_subdomains)); - EXPECT_FALSE(net::TransportSecurityState::ParseHeader( + EXPECT_FALSE(TransportSecurityState::ParseHeader( "max-age=34889 includesubdomains", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 42); @@ -87,51 +89,51 @@ TEST_F(TransportSecurityStateTest, ValidHeaders) { int max_age = 42; bool include_subdomains = true; - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( "max-age=243", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 243); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( " Max-agE = 567", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 567); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( " mAx-aGe = 890 ", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 890); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( "max-age=123;incLudesUbdOmains", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 123); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( "max-age=394082; incLudesUbdOmains", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 394082); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( "max-age=39408299 ;incLudesUbdOmains", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 39408299); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( "max-age=394082038 ; incLudesUbdOmains", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 394082038); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(net::TransportSecurityState::ParseHeader( + EXPECT_TRUE(TransportSecurityState::ParseHeader( " max-age=0 ; incLudesUbdOmains ", &max_age, &include_subdomains)); EXPECT_EQ(max_age, 0); EXPECT_TRUE(include_subdomains); } TEST_F(TransportSecurityStateTest, SimpleMatches) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -142,9 +144,9 @@ TEST_F(TransportSecurityStateTest, SimpleMatches) { } TEST_F(TransportSecurityStateTest, MatchesCase1) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -155,9 +157,9 @@ TEST_F(TransportSecurityStateTest, MatchesCase1) { } TEST_F(TransportSecurityStateTest, MatchesCase2) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -168,9 +170,9 @@ TEST_F(TransportSecurityStateTest, MatchesCase2) { } TEST_F(TransportSecurityStateTest, SubdomainMatches) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -187,8 +189,8 @@ TEST_F(TransportSecurityStateTest, SubdomainMatches) { } TEST_F(TransportSecurityStateTest, Serialise1) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); std::string output; bool dirty; state->Serialise(&output); @@ -197,15 +199,15 @@ TEST_F(TransportSecurityStateTest, Serialise1) { } TEST_F(TransportSecurityStateTest, Serialise2) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "google.com")); - domain_state.mode = net::TransportSecurityState::DomainState::MODE_STRICT; + domain_state.mode = TransportSecurityState::DomainState::MODE_STRICT; domain_state.expiry = expiry; domain_state.include_subdomains = true; state->EnableHost("google.com", domain_state); @@ -216,27 +218,27 @@ TEST_F(TransportSecurityStateTest, Serialise2) { EXPECT_TRUE(state->Deserialise(output, &dirty)); EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "google.com")); - EXPECT_EQ(domain_state.mode, net::TransportSecurityState::DomainState::MODE_STRICT); + EXPECT_EQ(domain_state.mode, TransportSecurityState::DomainState::MODE_STRICT); EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "foo.google.com")); - EXPECT_EQ(domain_state.mode, net::TransportSecurityState::DomainState::MODE_STRICT); + EXPECT_EQ(domain_state.mode, TransportSecurityState::DomainState::MODE_STRICT); EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "foo.bar.google.com")); - EXPECT_EQ(domain_state.mode, net::TransportSecurityState::DomainState::MODE_STRICT); + EXPECT_EQ(domain_state.mode, TransportSecurityState::DomainState::MODE_STRICT); EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "foo.bar.baz.google.com")); - EXPECT_EQ(domain_state.mode, net::TransportSecurityState::DomainState::MODE_STRICT); + EXPECT_EQ(domain_state.mode, TransportSecurityState::DomainState::MODE_STRICT); EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "com")); } TEST_F(TransportSecurityStateTest, Serialise3) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "google.com")); - domain_state.mode = net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC; + domain_state.mode = TransportSecurityState::DomainState::MODE_OPPORTUNISTIC; domain_state.expiry = expiry; state->EnableHost("google.com", domain_state); @@ -247,20 +249,20 @@ TEST_F(TransportSecurityStateTest, Serialise3) { EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "google.com")); EXPECT_EQ(domain_state.mode, - net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC); + TransportSecurityState::DomainState::MODE_OPPORTUNISTIC); } TEST_F(TransportSecurityStateTest, DeleteSince) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); - net::TransportSecurityState::DomainState domain_state; + TransportSecurityState::DomainState domain_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); const base::Time older = current_time - base::TimeDelta::FromSeconds(1000); EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "google.com")); - domain_state.mode = net::TransportSecurityState::DomainState::MODE_STRICT; + domain_state.mode = TransportSecurityState::DomainState::MODE_STRICT; domain_state.expiry = expiry; state->EnableHost("google.com", domain_state); @@ -271,8 +273,8 @@ TEST_F(TransportSecurityStateTest, DeleteSince) { } TEST_F(TransportSecurityStateTest, SerialiseOld) { - scoped_refptr<net::TransportSecurityState> state( - new net::TransportSecurityState); + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); // This is an old-style piece of transport state JSON, which has no creation // date. std::string output = @@ -288,3 +290,41 @@ TEST_F(TransportSecurityStateTest, SerialiseOld) { EXPECT_TRUE(dirty); } +TEST_F(TransportSecurityStateTest, IsPreloaded) { + const std::string paypal = + TransportSecurityState::CanonicaliseHost("paypal.com"); + const std::string www_paypal = + TransportSecurityState::CanonicaliseHost("www.paypal.com"); + const std::string a_www_paypal = + TransportSecurityState::CanonicaliseHost("a.www.paypal.com"); + const std::string abc_paypal = + TransportSecurityState::CanonicaliseHost("a.b.c.paypal.com"); + const std::string example = + TransportSecurityState::CanonicaliseHost("example.com"); + const std::string aypal = + TransportSecurityState::CanonicaliseHost("aypal.com"); + + bool b; + EXPECT_FALSE(TransportSecurityState::isPreloadedSTS(paypal, &b)); + EXPECT_TRUE(TransportSecurityState::isPreloadedSTS(www_paypal, &b)); + EXPECT_FALSE(b); + EXPECT_FALSE(TransportSecurityState::isPreloadedSTS(a_www_paypal, &b)); + EXPECT_FALSE(TransportSecurityState::isPreloadedSTS(abc_paypal, &b)); + EXPECT_FALSE(TransportSecurityState::isPreloadedSTS(example, &b)); + EXPECT_FALSE(TransportSecurityState::isPreloadedSTS(aypal, &b)); +} + +TEST_F(TransportSecurityStateTest, Preloaded) { + scoped_refptr<TransportSecurityState> state( + new TransportSecurityState); + TransportSecurityState::DomainState domain_state; + EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "paypal.com")); + EXPECT_TRUE(state->IsEnabledForHost(&domain_state, "www.paypal.com")); + EXPECT_EQ(domain_state.mode, + TransportSecurityState::DomainState::MODE_STRICT); + EXPECT_FALSE(domain_state.include_subdomains); + EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "www2.paypal.com")); + EXPECT_FALSE(state->IsEnabledForHost(&domain_state, "a.www.paypal.com")); +} + +} // namespace net |