| 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;
|
| }
|
|
|
|
|