Index: net/base/transport_security_state.cc |
=================================================================== |
--- net/base/transport_security_state.cc (revision 80507) |
+++ net/base/transport_security_state.cc (working copy) |
@@ -4,6 +4,8 @@ |
#include "net/base/transport_security_state.h" |
+#include <set> |
+ |
#include "base/base64.h" |
#include "base/json/json_reader.h" |
#include "base/json/json_writer.h" |
@@ -17,6 +19,8 @@ |
#include "base/values.h" |
#include "googleurl/src/gurl.h" |
#include "net/base/dns_util.h" |
+#include "net/base/x509_cert_types.h" |
+#include "net/base/x509_certificate.h" |
namespace net { |
@@ -32,6 +36,9 @@ |
if (canonicalized_host.empty()) |
return; |
+ // TODO(cevans) -- we likely want to permit a host to override a built-in, |
+ // for at least the case where the override is stricter (i.e. includes |
+ // subdomains, or includes certificate pinning). |
bool temp; |
if (IsPreloadedSTS(canonicalized_host, &temp)) |
return; |
@@ -128,6 +135,41 @@ |
return false; |
} |
+bool TransportSecurityState::IsAcceptableCertificate(const std::string& host, |
+ X509Certificate* cert) { |
+ DomainState state; |
+ if (!IsEnabledForHost(&state, host)) |
+ return true; |
+ |
+ if (state.cert_pins.empty()) |
+ return true; |
+ |
+ std::set<std::string> fingerprints; |
+ X509Certificate::OSCertHandles cert_chain; |
+ X509Certificate::GetCertChainFromCert(cert->os_cert_handle(), &cert_chain); |
+ { |
+ X509Certificate::OSCertHandles::const_iterator i; |
+ for (i = cert_chain.begin(); i != cert_chain.end(); ++i) { |
+ // TODO(cevans): we also want to match on fingerprints of various subsets |
+ // of the certificate, such as SubjectPublicKeyInfos, to enable a site |
+ // to seamlessly add SANs or have multiple pseudo-identical certs with |
+ // different expiries. |
+ net::SHA1Fingerprint fingerprint = |
+ X509Certificate::CalculateFingerprint(*i); |
+ fingerprints.insert(fingerprint.GetString()); |
+ } |
+ } |
+ X509Certificate::DestroyCertChain(&cert_chain); |
+ std::vector<std::string>::const_iterator pins_iter; |
+ for (pins_iter = state.cert_pins.begin(); |
+ pins_iter != state.cert_pins.end(); ++pins_iter) { |
+ std::string cert_lock = *pins_iter; |
+ if (fingerprints.find(cert_lock) != fingerprints.end()) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
void TransportSecurityState::DeleteSince(const base::Time& time) { |
bool dirtied = false; |
@@ -312,6 +354,14 @@ |
continue; |
} |
+ ListValue* pins = new ListValue; |
+ std::vector<std::string>::const_iterator pin_strings; |
+ for (pin_strings = i->second.cert_pins.begin(); |
+ pin_strings != i->second.cert_pins.end(); |
+ ++pin_strings) |
+ pins->Append(new StringValue(*pin_strings)); |
+ state->Set("cert_pins", pins); |
+ |
toplevel.Set(HashedDomainToExternalString(i->first), state); |
} |
@@ -349,6 +399,17 @@ |
continue; |
} |
+ ListValue* pins_list; |
+ std::vector<std::string> cert_pins; |
+ if (state->GetList("cert_pins", &pins_list)) { |
+ size_t num_pins = pins_list->GetSize(); |
+ for (size_t i = 0; i < num_pins; ++i) { |
+ std::string pin_string; |
+ if (pins_list->GetString(i, &pin_string)) |
+ cert_pins.push_back(pin_string); |
+ } |
+ } |
+ |
DomainState::Mode mode; |
if (mode_string == "strict") { |
mode = DomainState::MODE_STRICT; |
@@ -380,14 +441,17 @@ |
} |
std::string hashed = ExternalStringToHashedDomain(*i); |
- if (hashed.empty()) |
+ if (hashed.empty()) { |
+ dirtied = true; |
continue; |
+ } |
DomainState new_state; |
new_state.mode = mode; |
new_state.created = created_time; |
new_state.expiry = expiry_time; |
new_state.include_subdomains = include_subdomains; |
+ new_state.cert_pins = cert_pins; |
enabled_hosts_[hashed] = new_state; |
} |