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 |