Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef NET_BASE_TRANSPORT_SECURITY_STATE_H_ | 5 #ifndef NET_BASE_TRANSPORT_SECURITY_STATE_H_ |
| 6 #define NET_BASE_TRANSPORT_SECURITY_STATE_H_ | 6 #define NET_BASE_TRANSPORT_SECURITY_STATE_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/gtest_prod_util.h" | 14 #include "base/gtest_prod_util.h" |
| 15 #include "base/threading/non_thread_safe.h" | 15 #include "base/threading/non_thread_safe.h" |
| 16 #include "base/time.h" | 16 #include "base/time.h" |
| 17 #include "net/base/net_export.h" | 17 #include "net/base/net_export.h" |
| 18 #include "net/base/x509_certificate.h" | 18 #include "net/base/x509_certificate.h" |
| 19 #include "net/base/x509_cert_types.h" | 19 #include "net/base/x509_cert_types.h" |
| 20 | 20 |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 class SSLInfo; | 23 class SSLInfo; |
| 24 | 24 |
| 25 typedef std::vector<SHA1Fingerprint> FingerprintVector; | 25 // We need a generic Fingerprint type, with at least two implementations: |
| 26 | 26 // SHA1 and SHA256. TODO(palmer): Specify and implement that in |
|
Ryan Sleevi
2012/02/17 05:16:01
Comment nit: Drop the "we"
Comment nit: Place TODO
palmer
2012/03/05 23:47:51
Done.
| |
| 27 // TransportSecurityState | 27 // net/base/x509_cert_types.h. |
| 28 // | 28 // |
| 29 // Tracks which hosts have enabled *-Transport-Security. This object manages | 29 // Until that work is done, this typedef expresses the intent. |
| 30 // the in-memory store. A separate object must register itself with this object | 30 typedef SHA1Fingerprint Fingerprint; |
| 31 // in order to persist the state to disk. | 31 |
| 32 typedef std::vector<Fingerprint> FingerprintVector; | |
| 33 | |
| 34 // Tracks which hosts have enabled strict transport security and/or public | |
| 35 // key pins. | |
| 36 // | |
| 37 // This object manages the in-memory store. Register a SerializationDelegate | |
| 38 // with |SetSerializationDelegate| to persist the state to disk. | |
| 39 // | |
| 40 // HTTP strict transport security (HSTS) is defined in | |
| 41 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-04, and | |
| 42 // HTTP-based dynamic public key pinning (HPKP) is defined in | |
| 43 // http://tools.ietf.org/html/draft-ietf-websec-key-pinning-01. | |
| 32 class NET_EXPORT TransportSecurityState | 44 class NET_EXPORT TransportSecurityState |
| 33 : NON_EXPORTED_BASE(public base::NonThreadSafe) { | 45 : NON_EXPORTED_BASE(public base::NonThreadSafe) { |
| 34 public: | 46 public: |
| 35 // If non-empty, |hsts_hosts| is a JSON-formatted string to treat as if it | 47 // If non-empty, |hsts_hosts| is a JSON string to treat as if it |
| 36 // were a built-in entry (same format as persisted metadata in the | 48 // were a built-in DomainState entry. See |Serialize| for details on the |
| 37 // TransportSecurityState file). | 49 // format. |
|
Ryan Sleevi
2012/02/17 05:16:01
So, it feels very weird to have this interface dir
palmer
2012/03/05 23:47:51
Yeah, I know. I was trying to "refactor, but not t
Ryan Sleevi
2012/03/07 06:02:46
Works a hell of a lot better, thanks. Still not th
| |
| 38 explicit TransportSecurityState(const std::string& hsts_hosts); | 50 explicit TransportSecurityState(const std::string& hsts_hosts); |
| 51 | |
| 39 ~TransportSecurityState(); | 52 ~TransportSecurityState(); |
| 40 | 53 |
| 41 // A DomainState is the information that we persist about a given domain. | 54 // A DomainState describes the transport security state (required upgrade |
| 55 // to HTTPS, and/or any public key pins). | |
| 42 struct NET_EXPORT DomainState { | 56 struct NET_EXPORT DomainState { |
| 43 enum Mode { | 57 enum UpgradeMode { |
|
Ryan Sleevi
2012/02/17 05:16:01
What does this upgrade?
Upgrade to HTTPS?
Mode {
palmer
2012/03/05 23:47:51
Done.
| |
| 44 // Strict mode implies: | 58 UPGRADE_NEVER = 0, |
| 45 // * We generate internal redirects from HTTP -> HTTPS. | 59 UPGRADE_ALWAYS = 1, |
| 46 // * Certificate issues are fatal. | |
| 47 MODE_STRICT = 0, | |
| 48 // This used to be opportunistic HTTPS, but we removed support. | |
| 49 MODE_OPPORTUNISTIC_REMOVED = 1, | |
| 50 // SPDY_ONLY (aka X-Bodge-Transport-Security) is a hopefully temporary | |
| 51 // measure. It implies: | |
| 52 // * We'll request HTTP URLs over HTTPS iff we have SPDY support. | |
| 53 // * Certificate issues are fatal. | |
| 54 MODE_SPDY_ONLY = 2, | |
| 55 // Pinning means there are no HTTP -> HTTPS redirects, however certificate | |
| 56 // issues are still fatal and there may be public key pins. | |
| 57 MODE_PINNING_ONLY = 3, | |
| 58 }; | 60 }; |
| 59 | 61 |
| 60 DomainState(); | 62 DomainState(); |
| 61 ~DomainState(); | 63 ~DomainState(); |
| 62 | 64 |
| 65 // Parses |value| as a Public-Key-Pins header. If successful, returns true | |
| 66 // and updates the |dynamic_spki_hashes| and |dynamic_spki_hashes_expiry| | |
| 67 // fields; otherwise, returns false without updating any fields. | |
| 68 bool ParsePinsHeader(const std::string& value, const SSLInfo& ssl_info); | |
| 69 | |
| 70 // Parses |value| as a Strict-Transport-Security header. If successful, | |
| 71 // returns true and updates the |upgrade_mode|, |upgrade_expiry| and | |
| 72 // |include_subdomains| fields; otherwise, returns false without updating | |
| 73 // any fields. | |
| 74 bool ParseSTSHeader(const std::string& value); | |
| 75 | |
| 63 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: | 76 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: |
| 64 // 1) |bad_preloaded_spki_hashes| does not intersect |hashes|; AND | 77 // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND |
| 65 // 2) Both |preloaded_spki_hashes| and |dynamic_spki_hashes| are empty | 78 // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty |
| 66 // or at least one of them intersects |hashes|. | 79 // or at least one of them intersects |hashes|. |
| 67 // | 80 // |
| 68 // |{dynamic,preloaded}_spki_hashes| contain trustworthy public key | 81 // |{dynamic,static}_spki_hashes| contain trustworthy public key hashes, |
| 69 // hashes, any one of which is sufficient to validate the certificate | 82 // any one of which is sufficient to validate the certificate chain in |
| 70 // chain in question. The public keys could be of a root CA, intermediate | 83 // question. The public keys could be of a root CA, intermediate CA, or |
| 71 // CA, or leaf certificate, depending on the security vs. disaster | 84 // leaf certificate, depending on the security vs. disaster recovery |
| 72 // recovery tradeoff selected. (Pinning only to leaf certifiates increases | 85 // tradeoff selected. (Pinning only to leaf certifiates increases |
| 73 // security because you no longer trust any CAs, but it hampers disaster | 86 // security because you no longer trust any CAs, but it hampers disaster |
| 74 // recovery because you can't just get a new certificate signed by the | 87 // recovery because you can't just get a new certificate signed by the |
| 75 // CA.) | 88 // CA.) |
| 76 // | 89 // |
| 77 // |bad_preloaded_spki_hashes| contains public keys that we don't want to | 90 // |bad_static_spki_hashes| contains public keys that we don't want to |
| 78 // trust. | 91 // trust. |
| 79 bool IsChainOfPublicKeysPermitted(const FingerprintVector& hashes); | 92 bool IsChainOfPublicKeysPermitted(const FingerprintVector& hashes) const; |
| 93 | |
| 94 // Returns true if any of the FingerprintVectors |static_spki_hashes|, | |
| 95 // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any | |
| 96 // items. | |
| 97 bool HasPins() const; | |
| 80 | 98 |
| 81 // Returns true if |this| describes a more strict policy than |other|. | 99 // Returns true if |this| describes a more strict policy than |other|. |
| 82 // Used to see if a dynamic DomainState should override a preloaded one. | 100 // Used to see if a dynamic DomainState should override a static one. |
| 83 bool IsMoreStrict(const DomainState& other); | 101 bool IsMoreStrict(const DomainState& other) const; |
|
Ryan Sleevi
2012/02/17 05:16:01
IsStricterThan?
That said, both strictness and st
palmer
2012/03/05 23:47:51
The implementation is not even that well-defined,
| |
| 84 | |
| 85 // ShouldCertificateErrorsBeFatal returns true iff, given the |mode| of this | |
| 86 // DomainState, certificate errors on this domain should be fatal (i.e. no | |
| 87 // user bypass). | |
| 88 bool ShouldCertificateErrorsBeFatal() const; | |
| 89 | 102 |
| 90 // ShouldRedirectHTTPToHTTPS returns true iff, given the |mode| of this | 103 // ShouldRedirectHTTPToHTTPS returns true iff, given the |mode| of this |
| 91 // DomainState, HTTP requests should be internally redirected to HTTPS. | 104 // DomainState, HTTP requests should be internally redirected to HTTPS. |
| 92 bool ShouldRedirectHTTPToHTTPS() const; | 105 bool ShouldRedirectHTTPToHTTPS() const; |
| 93 | 106 |
| 94 Mode mode; | 107 UpgradeMode upgrade_mode; |
| 95 base::Time created; // when this host entry was first created | 108 |
| 96 base::Time expiry; // the absolute time (UTC) when this record expires | 109 // The absolute time (UTC) when this DomainState was first created. |
| 97 bool include_subdomains; // subdomains included? | 110 // |
| 98 | 111 // Static entries do not have a created time. |
| 99 // Optional; hashes of preloaded "pinned" SubjectPublicKeyInfos. Unless | 112 base::Time created; |
| 100 // both are empty, at least one of |preloaded_spki_hashes| and | 113 |
| 114 // The absolute time (UTC) when the |upgrade_mode|, if set to | |
| 115 // UPGRADE_ALWAYS, downgrades to UPGRADE_NEVER. | |
| 116 base::Time upgrade_expiry; | |
| 117 | |
| 118 // Are subdomains subject to this DomainState? | |
| 119 // | |
| 120 // TODO(palmer): Decide if we should have separate |pin_subdomains| and | |
| 121 // |upgrade_subdomains|. Alternately, and perhaps better, is to separate | |
| 122 // DomainState into UpgradeState and PinState (requiring also changing the | |
| 123 // serialization format?). | |
| 124 bool include_subdomains; | |
| 125 | |
| 126 // Optional; hashes of static pinned SubjectPublicKeyInfos. Unless both | |
| 127 // are empty, at least one of |static_spki_hashes| and | |
| 101 // |dynamic_spki_hashes| MUST intersect with the set of SPKIs in the TLS | 128 // |dynamic_spki_hashes| MUST intersect with the set of SPKIs in the TLS |
| 102 // server's certificate chain. | 129 // server's certificate chain. |
| 103 // | 130 // |
| 104 // |dynamic_spki_hashes| take precedence over |preloaded_spki_hashes|. | 131 // |dynamic_spki_hashes| take precedence over |static_spki_hashes|. |
| 105 // That is, when performing pin validation, first check dynamic and then | 132 // That is, |IsChainOfPublicKeysPermitted| first checks dynamic pins and |
| 106 // check preloaded. | 133 // then checks static pins. |
| 107 FingerprintVector preloaded_spki_hashes; | 134 FingerprintVector static_spki_hashes; |
| 108 | 135 |
| 109 // Optional; hashes of dynamically pinned SubjectPublicKeyInfos. (They | 136 // Optional; hashes of dynamically pinned SubjectPublicKeyInfos. (They |
|
Ryan Sleevi
2012/02/17 05:16:01
nit: Mentioning the means at which it can be set s
palmer
2012/03/05 23:47:51
Done.
| |
| 110 // could be set e.g. by an HTTP header or by a superfluous certificate.) | 137 // could be set e.g. by an HTTP Public-Key-Pins header, or by a |
| 138 // superfluous certificate, or by the user in | |
| 139 // chrome://net-internals/#hsts.) | |
| 111 FingerprintVector dynamic_spki_hashes; | 140 FingerprintVector dynamic_spki_hashes; |
| 112 | 141 |
| 113 // The absolute time (UTC) when the |dynamic_spki_hashes| expire. | 142 // The absolute time (UTC) when the |dynamic_spki_hashes| expire. |
| 114 base::Time dynamic_spki_hashes_expiry; | 143 base::Time dynamic_spki_hashes_expiry; |
| 115 | 144 |
| 116 // The max-age directive of the Public-Key-Pins header as parsed. Do not | 145 // Optional; hashes of static known-bad SubjectPublicKeyInfos which |
| 117 // persist this; it is only for testing. TODO(palmer): Therefore, get rid | |
| 118 // of it and find a better way to test. | |
| 119 int max_age; | |
| 120 | |
| 121 // Optional; hashes of preloaded known-bad SubjectPublicKeyInfos which | |
| 122 // MUST NOT intersect with the set of SPKIs in the TLS server's | 146 // MUST NOT intersect with the set of SPKIs in the TLS server's |
| 123 // certificate chain. | 147 // certificate chain. |
| 124 FingerprintVector bad_preloaded_spki_hashes; | 148 FingerprintVector bad_static_spki_hashes; |
| 125 | 149 |
| 126 // The following members are not valid when stored in |enabled_hosts_|. | 150 // The following members are not valid when stored in |enabled_hosts_|: |
| 127 bool preloaded; // is this a preloaded entry? | 151 |
| 128 std::string domain; // the domain which matched | 152 // The domain which matched during a search for this DomainState entry. |
| 153 // Updated by |GetDomainState| and |GetStaticDomainState|. | |
| 154 std::string domain; | |
| 129 }; | 155 }; |
| 130 | 156 |
| 131 class Delegate { | 157 class SerializationDelegate { |
|
Ryan Sleevi
2012/02/17 05:16:01
Why the rename? Delegate is certainly the more com
palmer
2012/03/05 23:47:51
Wow, I bet that is confusing.
But if that's the w
Ryan Sleevi
2012/03/07 06:02:46
Not really, since any inheritance from a nested cl
| |
| 132 public: | 158 public: |
| 133 // This function may not block and may be called with internal locks held. | 159 // This function may not block and may be called with internal locks held. |
| 134 // Thus it must not reenter the TransportSecurityState object. | 160 // Thus it must not reenter the TransportSecurityState object. |
| 135 virtual void StateIsDirty(TransportSecurityState* state) = 0; | 161 virtual void StateIsDirty(TransportSecurityState* state) = 0; |
| 136 | 162 |
| 137 protected: | 163 protected: |
| 138 virtual ~Delegate() {} | 164 virtual ~SerializationDelegate() {} |
| 139 }; | 165 }; |
| 140 | 166 |
| 141 void SetDelegate(Delegate* delegate); | 167 void SetSerializationDelegate(SerializationDelegate* delegate); |
| 142 | 168 |
| 143 // Enable TransportSecurity for |host|. | 169 // Enable TransportSecurity for |host|. |state| supercedes any previous |
| 170 // state for the |host|, including static entries. | |
| 171 // | |
| 172 // The new state for |host| is persisted using the SerializationDelegate | |
| 173 // (if any). | |
| 144 void EnableHost(const std::string& host, const DomainState& state); | 174 void EnableHost(const std::string& host, const DomainState& state); |
| 145 | 175 |
| 146 // Delete any entry for |host|. If |host| doesn't have an exact entry then no | 176 // Delete any entry for |host|. If |host| doesn't have an exact entry then |
| 147 // action is taken. Returns true iff an entry was deleted. | 177 // no action is taken. Does not delete static entries. Returns true iff an |
| 178 // entry was deleted. | |
| 179 // | |
| 180 // The new state for |host| is persisted using the SerializationDelegate | |
| 181 // (if any). | |
| 148 bool DeleteHost(const std::string& host); | 182 bool DeleteHost(const std::string& host); |
| 149 | 183 |
| 150 // Returns true if |host| has TransportSecurity enabled. Before operating | 184 // Deletes all records created since a given time. |
| 151 // on this result, consult |result->mode|, as the expected behavior of | 185 void DeleteSince(const base::Time& time); |
| 152 // TransportSecurity can significantly differ based on mode. | 186 |
| 153 // | 187 // Returns true and updates |*result| if there is a DomainState for |
| 154 // If |sni_available| is true, searches the preloads defined for SNI-using | 188 // |host|. (If there is no DomainState for |host|, |*result| is not |
|
Ryan Sleevi
2012/02/17 05:16:01
You can remove the ().
Also note http://google-st
palmer
2012/03/05 23:47:51
Done.
| |
| 155 // hosts as well as the usual preload list. | 189 // updated.) |
| 156 // | 190 // |
| 157 // Note that |*result| is always overwritten on every call. | 191 // If |sni_available| is true, searches the static pins defined for |
|
Ryan Sleevi
2012/02/17 05:16:01
The whole |sni_available| doesn't feel like an apt
palmer
2012/03/05 23:47:51
Done.
| |
| 158 // TODO(palmer): Only update |*result| on success. | 192 // SNI-using hosts as well as the rest of the pins. |
| 193 // | |
| 194 // If |host| matches both an exact entry and is a subdomain of another | |
| 195 // entry, the exact match determines the return value. | |
| 159 bool GetDomainState(DomainState* result, | 196 bool GetDomainState(DomainState* result, |
| 160 const std::string& host, | 197 const std::string& host, |
| 161 bool sni_available); | 198 bool sni_available) const; |
| 162 | 199 |
| 163 // Returns true if there are any certificates pinned for |host|. | 200 // Returns true and updates |*result| if there is a static DomainState for |
| 164 // If so, updates the |preloaded_spki_hashes|, |dynamic_spki_hashes|, and | 201 // |host|. (If there is no static DomainState for |host|, |*result| is not |
| 165 // |bad_preloaded_spki_hashes| fields of |*result| with the pins. | 202 // updated.) |
|
Ryan Sleevi
2012/02/17 05:16:01
Same comment here as on 188
palmer
2012/03/05 23:47:51
Done.
| |
| 166 // | 203 // |
| 167 // Note that |*result| is always overwritten on every call, regardless of | 204 // |GetStaticDomainState| is identical to |GetDomainState| except that it |
| 168 // whether or not pins are enabled. | 205 // searches only the statically-defined transport security state, ignoring |
| 169 // | 206 // all dynamically-added DomainStates. |
| 170 // If |sni_available| is true, searches the preloads defined for SNI-using | 207 // |
| 171 // hosts as well as the usual preload list. | 208 // If |sni_available| is true, searches the static pins defined for |
| 172 // | 209 // SNI-using hosts as well as the rest of the pins. |
| 173 // TODO(palmer): Only update |*result| if pins exist. | 210 // |
| 174 bool HasPinsForHost(DomainState* result, | 211 // If |host| matches both an exact entry and is a subdomain of another |
| 175 const std::string& host, | 212 // entry, the exact match determines the return value. |
| 176 bool sni_available); | 213 bool GetStaticDomainState(DomainState* result, |
| 177 | 214 const std::string& host, |
| 178 // Returns true and updates |*result| if there is any |DomainState| | 215 bool sni_available) const; |
| 179 // metadata for |host| in the local TransportSecurityState database; | 216 |
| 180 // returns false otherwise. TODO(palmer): Unlike the other | 217 // Serializes the transport security state (the set of DomainStates |
| 181 // TransportSecurityState lookup functions in this class (e.g | 218 // for all hosts) into |*output|. Returns true if all DomainStates were |
| 182 // |HasPinsForHost|, |GetDomainState|), |*result| is updated iff metadata | 219 // serialized correctly. |
| 183 // is found. The other functions are buggy and will be fixed to behave | 220 // |
| 184 // like this one. | 221 // The serialization format is JSON; the JSON represents a dictionary of |
| 185 // | 222 // host:DomainState pairs (host is a string). The DomainState is |
| 186 // If |sni_available| is true, searches the preloads defined for SNI-using | 223 // represented as a dictionary containing the following keys and value |
| 187 // hosts as well as the usual preload list. | 224 // types (not all keys will always be present): |
| 188 bool HasMetadata(DomainState* result, | 225 // |
| 189 const std::string& host, | 226 // "include_subdomains": true|false |
| 190 bool sni_available); | 227 // "created": double |
| 191 | 228 // "expiry": double |
| 192 // Returns true if we have a preloaded certificate pin for the |host| and if | 229 // "dynamic_spki_hashes_expiry": double |
| 193 // its set of required certificates is the set we expect for Google | 230 // "mode": "always"|"never" |
| 231 // legacy value synonyms "strict"|"pinning-only" | |
| 232 // legacy value "spdy-only" is unused and ignored | |
| 233 // "static_spki_hashes": list of strings | |
| 234 // legacy key synonym "preloaded_spki_hashes" | |
| 235 // "bad_static_spki_hashes": list of strings | |
| 236 // legacy key synonym "bad_preloaded_spki_hashes" | |
| 237 // "dynamic_spki_hashes": list of strings | |
| 238 bool Serialize(std::string* output) const; | |
|
Ryan Sleevi
2012/02/17 05:16:01
see comments re: serialization being part of this
palmer
2012/03/05 23:47:51
Is it better to implement a const_iterator for Tra
Ryan Sleevi
2012/03/07 06:02:46
+1. I recently did that for expiring_cache, and th
palmer
2012/03/13 20:13:39
Done.
| |
| 239 | |
| 240 // Clears any existing non-static entries, and then re-populates the | |
| 241 // transport security state from the JSON string |state|. Returns true if | |
| 242 // all entries were parsed and deserialized correctly. | |
| 243 // | |
| 244 // Sets |*dirty| to true if the new state differs from the persisted | |
| 245 // state; false otherwise. | |
| 246 bool LoadEntries(const std::string& state, bool* dirty); | |
| 247 | |
| 248 // Returns true iff we have any static public key pins for the |host| and | |
| 249 // iff its set of required pins is the set we expect for Google | |
| 194 // properties. | 250 // properties. |
| 195 // | 251 // |
| 196 // If |sni_available| is true, searches the preloads defined for SNI-using | 252 // If |sni_available| is true, searches the static pins defined for |
| 197 // hosts as well as the usual preload list. | 253 // SNI-using hosts as well as the rest of the pins. |
| 198 // | 254 // |
| 199 // Note that like HasMetadata, if |host| matches both an exact entry and is a | 255 // If |host| matches both an exact entry and is a subdomain of another |
| 200 // subdomain of another entry, the exact match determines the return value. | 256 // entry, the exact match determines the return value. |
| 201 static bool IsGooglePinnedProperty(const std::string& host, | 257 static bool IsGooglePinnedProperty(const std::string& host, |
|
Ryan Sleevi
2012/02/17 05:16:01
This never quite felt like the right layer to stic
palmer
2012/03/05 23:47:51
The implementation relies on private implementatio
Ryan Sleevi
2012/03/07 06:02:46
Fundamentally, how does this differ from GetStatic
palmer
2012/03/13 20:13:39
Correct.
| |
| 202 bool sni_available); | 258 bool sni_available); |
| 203 | 259 |
| 204 // Reports UMA statistics upon public key pin failure. Reports only down to | 260 // Reports UMA statistics upon public key pin failure. Reports only down to |
| 205 // the second-level domain of |host| (e.g. google.com if |host| is | 261 // the second-level domain of |host| (e.g. google.com if |host| is |
| 206 // mail.google.com), and only if |host| is a preloaded STS host. | 262 // mail.google.com), and only if |host| has a static entry. |
| 207 static void ReportUMAOnPinFailure(const std::string& host); | 263 static void ReportUMAOnPinFailure(const std::string& host); |
|
Ryan Sleevi
2012/02/17 05:16:01
This seems like it belongs somewhere else. Unfortu
palmer
2012/03/05 23:47:51
Unlike IsGooglePinnedProperty, it is fairly straig
| |
| 208 | 264 |
| 209 // Parses |cert|'s Subject Public Key Info structure, hashes it, and writes | 265 // Parses |cert|'s Subject Public Key Info structure, hashes it, and writes |
| 210 // the hash into |spki_hash|. Returns true on parse success, false on | 266 // the hash into |spki_hash|. Returns true on parse success, false on |
| 211 // failure. | 267 // failure. |
| 212 static bool GetPublicKeyHash(const X509Certificate& cert, | 268 static bool GetPublicKeyHash(const X509Certificate& cert, |
|
Ryan Sleevi
2012/02/17 05:16:01
It seems like this would be better suited in X509C
palmer
2012/03/05 23:47:51
Done.
| |
| 213 SHA1Fingerprint* spki_hash); | 269 Fingerprint* spki_hash); |
| 214 | 270 |
| 215 // Decodes a pin string |value| (e.g. "sha1/hvfkN/qlp/zhXR3cuerq6jd2Z7g=") | 271 // Decodes a pin string |value| (e.g. "sha1/hvfkN/qlp/zhXR3cuerq6jd2Z7g="). |
| 216 // and populates |out|. | 272 // If parsing succeeded, updates |*out| and returns true; otherwise returns |
| 217 static bool ParsePin(const std::string& value, SHA1Fingerprint* out); | 273 // false without updating |*out|. |
| 218 | 274 static bool ParsePin(const std::string& value, Fingerprint* out); |
| 219 // Deletes all records created since a given time. | 275 |
| 220 void DeleteSince(const base::Time& time); | 276 // The maximum number of seconds for which we'll cache an HSTS request. |
| 221 | 277 static const long int kMaxHSTSAgeSecs; |
| 222 // Parses |value| as a Public-Key-Pins header. If successful, returns |true| | 278 |
| 223 // and updates the |dynamic_spki_hashes| and |dynamic_spki_hashes_expiry| | 279 // Converts |hostname| from dotted form ("www.google.com") to the form |
| 224 // fields of |*state|; otherwise, returns |false| without updating |*state|. | 280 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns |
| 225 static bool ParsePinsHeader(const std::string& value, | 281 // the result. |
| 226 const SSLInfo& ssl_info, | 282 static std::string CanonicalizeHost(const std::string& hostname); |
|
Ryan Sleevi
2012/02/17 05:16:01
Does this really need to be part of the public int
palmer
2012/03/05 23:47:51
It looks like it's public for use in transport_sec
Ryan Sleevi
2012/03/07 06:02:46
Yup. You can use either FRIEND_TEST (declared betw
palmer
2012/03/13 20:13:39
Turns out CanonicalizeHost needs to be public anyw
| |
| 227 DomainState* state); | 283 |
| 228 | 284 // Parses |side_info| as a side pin (TODO(agl): document the format). If |
|
Ryan Sleevi
2012/02/17 05:16:01
TODOs on newlines at the end of the description.
palmer
2012/03/05 23:47:51
Done.
| |
| 229 // Returns |true| if |value| parses as a valid *-Transport-Security | 285 // successful, returns true and appends the hash of the public key that signed |
| 230 // header value. The values of max-age and and includeSubDomains are | 286 // |leaf_spki| to |*out_pub_key_hash|. |
| 231 // returned in |max_age| and |include_subdomains|, respectively. The out | 287 // |
| 232 // parameters are not modified if the function returns |false|. | 288 // A side pin is a way for a site to sign their public key with a key that is |
| 233 static bool ParseHeader(const std::string& value, | 289 // offline but still controlled by them. |
| 234 int* max_age, | |
| 235 bool* include_subdomains); | |
| 236 | |
| 237 // ParseSidePin attempts to parse a side pin from |side_info| which signs the | |
| 238 // SubjectPublicKeyInfo in |leaf_spki|. A side pin is a way for a site to | |
| 239 // sign their public key with a key that is offline but still controlled by | |
| 240 // them. If successful, the hash of the public key used to sign |leaf_spki| | |
| 241 // is put into |out_pub_key_hash|. | |
| 242 static bool ParseSidePin(const base::StringPiece& leaf_spki, | 290 static bool ParseSidePin(const base::StringPiece& leaf_spki, |
|
Ryan Sleevi
2012/02/17 05:16:01
Another weird sort of utility function here that f
palmer
2012/03/05 23:47:51
Agreed. Got a better candidate place? X509Certific
Ryan Sleevi
2012/03/07 06:02:46
Side pins always come in as an X.509 extension, ri
palmer
2012/03/13 20:13:39
Done.
| |
| 243 const base::StringPiece& side_info, | 291 const base::StringPiece& side_info, |
| 244 FingerprintVector* out_pub_key_hash); | 292 FingerprintVector* out_pub_key_hash); |
| 245 | 293 |
| 246 bool Serialise(std::string* output); | |
| 247 // Existing non-preloaded entries are cleared and repopulated from the | |
| 248 // passed JSON string. | |
| 249 bool LoadEntries(const std::string& state, bool* dirty); | |
| 250 | |
| 251 // The maximum number of seconds for which we'll cache an HSTS request. | |
| 252 static const long int kMaxHSTSAgeSecs; | |
| 253 | |
| 254 private: | 294 private: |
| 255 FRIEND_TEST_ALL_PREFIXES(TransportSecurityStateTest, IsPreloaded); | 295 // If we have a SerializationDelegate, call its |StateIsDirty| function. |
| 256 | |
| 257 // If we have a callback configured, call it to let our serialiser know that | |
| 258 // our state is dirty. | |
| 259 void DirtyNotify(); | 296 void DirtyNotify(); |
| 260 bool IsPreloadedSTS(const std::string& canonicalized_host, | 297 |
| 261 bool sni_available, | 298 static bool Deserialize(const std::string& state, |
| 262 DomainState* out); | |
| 263 | |
| 264 static std::string CanonicalizeHost(const std::string& host); | |
| 265 static bool Deserialise(const std::string& state, | |
| 266 bool* dirty, | 299 bool* dirty, |
| 267 std::map<std::string, DomainState>* out); | 300 std::map<std::string, DomainState>* out); |
| 268 | 301 |
| 269 // The set of hosts that have enabled TransportSecurity. The keys here | 302 // The set of hosts that have enabled TransportSecurity. The keys are |
| 270 // are SHA256(DNSForm(domain)) where DNSForm converts from dotted form | 303 // SHA256(CanonicalizeHost(domain)). The reason for hashing them is so |
| 271 // ('www.google.com') to the form used in DNS: "\x03www\x06google\x03com" | 304 // that the stored state does not trivially reveal a user's browing |
| 305 // history to an attacker reading the serialized state on disk. | |
|
Ryan Sleevi
2012/02/17 05:16:01
Since this class doesn't do any formal serializati
palmer
2012/03/05 23:47:51
Agreed.
| |
| 272 std::map<std::string, DomainState> enabled_hosts_; | 306 std::map<std::string, DomainState> enabled_hosts_; |
| 273 | 307 |
| 274 // These hosts are extra rules to treat as built-in, passed in the | 308 // Extra entries to treat as if they were static (typically originating |
| 275 // constructor (typically originating from the command line). | 309 // from the command line). |
|
Ryan Sleevi
2012/02/17 05:16:01
Since you mentioned |enabled_hosts_| keys, what is
palmer
2012/03/05 23:47:51
It's even less usable than that. It's base64encode
| |
| 276 std::map<std::string, DomainState> forced_hosts_; | 310 std::map<std::string, DomainState> forced_hosts_; |
| 277 | 311 |
| 278 // Our delegate who gets notified when we are dirtied, or NULL. | 312 SerializationDelegate* serialization_delegate_; |
|
Ryan Sleevi
2012/02/17 05:16:01
What's the ownership of this pointer? (I'm guessin
palmer
2012/03/05 23:47:51
I agree. I think there is no ownership at all, and
Ryan Sleevi
2012/03/07 06:02:46
That gets a bit messier - then objects which have-
palmer
2012/03/13 20:13:39
TSS is per-profile, so they do live a long time.
| |
| 279 Delegate* delegate_; | |
| 280 | 313 |
| 281 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); | 314 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); |
| 282 }; | 315 }; |
| 283 | 316 |
| 284 } // namespace net | 317 } // namespace net |
| 285 | 318 |
| 286 #endif // NET_BASE_TRANSPORT_SECURITY_STATE_H_ | 319 #endif // NET_BASE_TRANSPORT_SECURITY_STATE_H_ |
| OLD | NEW |