Index: net/http/transport_security_state.cc |
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc |
index 609c233a3ea43d02d0f2997afcf1541cf79a6673..e967c659c07c65828fe704f4dfc3083820e3126f 100644 |
--- a/net/http/transport_security_state.cc |
+++ b/net/http/transport_security_state.cc |
@@ -95,6 +95,61 @@ TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) |
TransportSecurityState::Iterator::~Iterator() {} |
+bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host, |
+ bool sni_enabled) { |
+ DomainState state; |
+ if (GetStaticDomainState(host, sni_enabled, &state)) |
+ return true; |
+ return GetDynamicDomainState(host, &state); |
+} |
+ |
+bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, |
+ bool sni_enabled) { |
+ DomainState dynamic_state; |
+ if (GetDynamicDomainState(host, &dynamic_state)) |
+ return dynamic_state.ShouldUpgradeToSSL(); |
+ |
+ DomainState static_state; |
+ if (GetStaticDomainState(host, sni_enabled, &static_state) && |
+ static_state.ShouldUpgradeToSSL()) { |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, |
+ bool sni_enabled, |
+ const HashValueVector& hashes, |
+ std::string* failure_log) { |
+ DomainState dynamic_state; |
+ if (GetDynamicDomainState(host, &dynamic_state)) |
+ return dynamic_state.CheckPublicKeyPins(hashes, failure_log); |
+ |
+ DomainState static_state; |
+ if (GetStaticDomainState(host, sni_enabled, &static_state) && |
+ static_state.CheckPublicKeyPins(hashes, failure_log)) { |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool TransportSecurityState::HasPublicKeyPins(const std::string& host, |
+ bool sni_enabled) { |
+ DomainState dynamic_state; |
+ if (GetDynamicDomainState(host, &dynamic_state)) |
+ return dynamic_state.HasPublicKeyPins(); |
+ |
+ DomainState static_state; |
+ if (GetStaticDomainState(host, sni_enabled, &static_state)) { |
+ if (static_state.HasPublicKeyPins()) |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
void TransportSecurityState::SetDelegate( |
TransportSecurityState::Delegate* delegate) { |
DCHECK(CalledOnValidThread()); |
@@ -135,61 +190,6 @@ bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) { |
return false; |
} |
-bool TransportSecurityState::GetDomainState(const std::string& host, |
- bool sni_enabled, |
- DomainState* result) { |
- DCHECK(CalledOnValidThread()); |
- |
- DomainState state; |
- const std::string canonicalized_host = CanonicalizeHost(host); |
- if (canonicalized_host.empty()) |
- return false; |
- |
- bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled, |
- &state); |
- std::string canonicalized_preload = CanonicalizeHost(state.domain); |
- GetDynamicDomainState(host, &state); |
- |
- base::Time current_time(base::Time::Now()); |
- |
- for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
- std::string host_sub_chunk(&canonicalized_host[i], |
- canonicalized_host.size() - i); |
- // Exact match of a preload always wins. |
- if (has_preload && host_sub_chunk == canonicalized_preload) { |
- *result = state; |
- return true; |
- } |
- |
- DomainStateMap::iterator j = |
- enabled_hosts_.find(HashHost(host_sub_chunk)); |
- if (j == enabled_hosts_.end()) |
- continue; |
- |
- if (current_time > j->second.upgrade_expiry && |
- current_time > j->second.dynamic_spki_hashes_expiry) { |
- enabled_hosts_.erase(j); |
- DirtyNotify(); |
- continue; |
- } |
- |
- state = j->second; |
- state.domain = DNSDomainToString(host_sub_chunk); |
- |
- // Succeed if we matched the domain exactly or if subdomain matches are |
- // allowed. |
- if (i == 0 || j->second.sts_include_subdomains || |
- j->second.pkp_include_subdomains) { |
- *result = state; |
- return true; |
- } |
- |
- return false; |
- } |
- |
- return false; |
-} |
- |
void TransportSecurityState::ClearDynamicData() { |
DCHECK(CalledOnValidThread()); |
enabled_hosts_.clear(); |
@@ -201,18 +201,20 @@ void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { |
bool dirtied = false; |
DomainStateMap::iterator i = enabled_hosts_.begin(); |
while (i != enabled_hosts_.end()) { |
- if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { |
+ if (i->second.sts.last_observed >= time && |
+ i->second.pkp.last_observed >= time) { |
dirtied = true; |
enabled_hosts_.erase(i++); |
continue; |
} |
- if (i->second.sts_observed >= time) { |
+ if (i->second.sts.last_observed >= time) { |
dirtied = true; |
- i->second.upgrade_mode = DomainState::MODE_DEFAULT; |
- } else if (i->second.pkp_observed >= time) { |
+ i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
+ } else if (i->second.pkp.last_observed >= time) { |
dirtied = true; |
- i->second.dynamic_spki_hashes.clear(); |
+ i->second.pkp.spki_hashes.clear(); |
+ i->second.pkp.expiry = base::Time(); |
} |
++i; |
} |
@@ -555,22 +557,27 @@ static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, |
if (!entries[j].include_subdomains && i != 0) { |
*ret = false; |
} else { |
- out->sts_include_subdomains = entries[j].include_subdomains; |
- out->pkp_include_subdomains = entries[j].include_subdomains; |
+ out->sts.include_subdomains = entries[j].include_subdomains; |
+ out->sts.last_observed = base::GetBuildTime(); |
+ out->pkp.include_subdomains = entries[j].include_subdomains; |
+ out->pkp.last_observed = base::GetBuildTime(); |
*ret = true; |
+ out->sts.upgrade_mode = |
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS; |
if (!entries[j].https_required) |
- out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; |
+ out->sts.upgrade_mode = |
+ TransportSecurityState::DomainState::MODE_DEFAULT; |
if (entries[j].pins.required_hashes) { |
const char* const* sha1_hash = entries[j].pins.required_hashes; |
while (*sha1_hash) { |
- AddHash(*sha1_hash, &out->static_spki_hashes); |
+ AddHash(*sha1_hash, &out->pkp.spki_hashes); |
sha1_hash++; |
} |
} |
if (entries[j].pins.excluded_hashes) { |
const char* const* sha1_hash = entries[j].pins.excluded_hashes; |
while (*sha1_hash) { |
- AddHash(*sha1_hash, &out->bad_static_spki_hashes); |
+ AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); |
sha1_hash++; |
} |
} |
@@ -618,14 +625,14 @@ bool TransportSecurityState::AddHSTSHeader(const std::string& host, |
base::TimeDelta max_age; |
TransportSecurityState::DomainState domain_state; |
GetDynamicDomainState(host, &domain_state); |
- if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { |
+ if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) { |
// Handle max-age == 0 |
if (max_age.InSeconds() == 0) |
- domain_state.upgrade_mode = DomainState::MODE_DEFAULT; |
+ domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
else |
- domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
- domain_state.sts_observed = now; |
- domain_state.upgrade_expiry = now + max_age; |
+ domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
+ domain_state.sts.last_observed = now; |
+ domain_state.sts.expiry = now + max_age; |
EnableHost(host, domain_state); |
return true; |
} |
@@ -641,12 +648,14 @@ bool TransportSecurityState::AddHPKPHeader(const std::string& host, |
base::TimeDelta max_age; |
TransportSecurityState::DomainState domain_state; |
GetDynamicDomainState(host, &domain_state); |
- if (ParseHPKPHeader(value, ssl_info.public_key_hashes, |
- &max_age, &domain_state.pkp_include_subdomains, |
- &domain_state.dynamic_spki_hashes)) { |
+ if (ParseHPKPHeader(value, |
+ ssl_info.public_key_hashes, |
+ &max_age, |
+ &domain_state.pkp.include_subdomains, |
+ &domain_state.pkp.spki_hashes)) { |
// TODO(palmer): http://crbug.com/243865 handle max-age == 0. |
- domain_state.pkp_observed = now; |
- domain_state.dynamic_spki_hashes_expiry = now + max_age; |
+ domain_state.pkp.last_observed = now; |
+ domain_state.pkp.expiry = now + max_age; |
EnableHost(host, domain_state); |
return true; |
} |
@@ -667,10 +676,10 @@ bool TransportSecurityState::AddHSTS(const std::string& host, |
if (i != enabled_hosts_.end()) |
domain_state = i->second; |
- domain_state.sts_observed = base::Time::Now(); |
- domain_state.sts_include_subdomains = include_subdomains; |
- domain_state.upgrade_expiry = expiry; |
- domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
+ domain_state.sts.last_observed = base::Time::Now(); |
+ domain_state.sts.include_subdomains = include_subdomains; |
+ domain_state.sts.expiry = expiry; |
+ domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
EnableHost(host, domain_state); |
return true; |
} |
@@ -690,10 +699,10 @@ bool TransportSecurityState::AddHPKP(const std::string& host, |
if (i != enabled_hosts_.end()) |
domain_state = i->second; |
- domain_state.pkp_observed = base::Time::Now(); |
- domain_state.pkp_include_subdomains = include_subdomains; |
- domain_state.dynamic_spki_hashes_expiry = expiry; |
- domain_state.dynamic_spki_hashes = hashes; |
+ domain_state.pkp.last_observed = base::Time::Now(); |
+ domain_state.pkp.include_subdomains = include_subdomains; |
+ domain_state.pkp.expiry = expiry; |
+ domain_state.pkp.spki_hashes = hashes; |
EnableHost(host, domain_state); |
return true; |
} |
@@ -750,15 +759,16 @@ bool TransportSecurityState::IsBuildTimely() { |
return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
} |
-bool TransportSecurityState::GetStaticDomainState( |
- const std::string& canonicalized_host, |
- bool sni_enabled, |
- DomainState* out) { |
+bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
+ bool sni_enabled, |
+ DomainState* out) const { |
DCHECK(CalledOnValidThread()); |
- out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
- out->sts_include_subdomains = false; |
- out->pkp_include_subdomains = false; |
+ const std::string canonicalized_host = CanonicalizeHost(host); |
+ |
+ out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
+ out->sts.include_subdomains = false; |
+ out->pkp.include_subdomains = false; |
const bool is_build_timely = IsBuildTimely(); |
@@ -802,8 +812,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, |
if (j == enabled_hosts_.end()) |
continue; |
- if (current_time > j->second.upgrade_expiry && |
- current_time > j->second.dynamic_spki_hashes_expiry) { |
+ if (current_time > j->second.sts.expiry && |
+ current_time > j->second.pkp.expiry) { |
enabled_hosts_.erase(j); |
DirtyNotify(); |
continue; |
@@ -814,8 +824,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, |
// Succeed if we matched the domain exactly or if subdomain matches are |
// allowed. |
- if (i == 0 || j->second.sts_include_subdomains || |
- j->second.pkp_include_subdomains) { |
+ if (i == 0 || j->second.sts.include_subdomains || |
+ j->second.pkp.include_subdomains) { |
*result = state; |
return true; |
} |
@@ -826,20 +836,16 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, |
return false; |
} |
- |
void TransportSecurityState::AddOrUpdateEnabledHosts( |
const std::string& hashed_host, const DomainState& state) { |
DCHECK(CalledOnValidThread()); |
enabled_hosts_[hashed_host] = state; |
} |
-TransportSecurityState::DomainState::DomainState() |
- : upgrade_mode(MODE_DEFAULT), |
- sts_include_subdomains(false), |
- pkp_include_subdomains(false) { |
- base::Time now(base::Time::Now()); |
- sts_observed = now; |
- pkp_observed = now; |
+TransportSecurityState::DomainState::DomainState() { |
+ sts.upgrade_mode = MODE_DEFAULT; |
+ sts.include_subdomains = false; |
+ pkp.include_subdomains = false; |
} |
TransportSecurityState::DomainState::~DomainState() { |
@@ -851,37 +857,36 @@ bool TransportSecurityState::DomainState::CheckPublicKeyPins( |
// production), that should never happen, but it's good to be defensive. |
// And, hashes *can* be empty in some test scenarios. |
if (hashes.empty()) { |
- *failure_log = "Rejecting empty public key chain for public-key-pinned " |
- "domains: " + domain; |
+ failure_log->append( |
+ "Rejecting empty public key chain for public-key-pinned domains: " + |
+ domain); |
return false; |
} |
- if (HashesIntersect(bad_static_spki_hashes, hashes)) { |
- *failure_log = "Rejecting public key chain for domain " + domain + |
- ". Validated chain: " + HashesToBase64String(hashes) + |
- ", matches one or more bad hashes: " + |
- HashesToBase64String(bad_static_spki_hashes); |
+ if (HashesIntersect(pkp.bad_spki_hashes, hashes)) { |
+ failure_log->append("Rejecting public key chain for domain " + domain + |
+ ". Validated chain: " + HashesToBase64String(hashes) + |
+ ", matches one or more bad hashes: " + |
+ HashesToBase64String(pkp.bad_spki_hashes)); |
return false; |
} |
// If there are no pins, then any valid chain is acceptable. |
- if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) |
+ if (pkp.spki_hashes.empty()) |
return true; |
- if (HashesIntersect(dynamic_spki_hashes, hashes) || |
- HashesIntersect(static_spki_hashes, hashes)) { |
+ if (HashesIntersect(pkp.spki_hashes, hashes)) { |
return true; |
} |
- *failure_log = "Rejecting public key chain for domain " + domain + |
- ". Validated chain: " + HashesToBase64String(hashes) + |
- ", expected: " + HashesToBase64String(dynamic_spki_hashes) + |
- " or: " + HashesToBase64String(static_spki_hashes); |
+ failure_log->append("Rejecting public key chain for domain " + domain + |
+ ". Validated chain: " + HashesToBase64String(hashes) + |
+ ", expected: " + HashesToBase64String(pkp.spki_hashes)); |
return false; |
} |
bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { |
- return upgrade_mode == MODE_FORCE_HTTPS; |
+ return sts.upgrade_mode == MODE_FORCE_HTTPS; |
} |
bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { |
@@ -889,9 +894,13 @@ bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { |
} |
bool TransportSecurityState::DomainState::HasPublicKeyPins() const { |
- return static_spki_hashes.size() > 0 || |
- bad_static_spki_hashes.size() > 0 || |
- dynamic_spki_hashes.size() > 0; |
+ return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; |
+} |
+ |
+TransportSecurityState::DomainState::PKPState::PKPState() { |
+} |
+ |
+TransportSecurityState::DomainState::PKPState::~PKPState() { |
} |
} // namespace |