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_HTTP_TRANSPORT_SECURITY_STATE_H_ | 5 #ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_H_ |
6 #define NET_HTTP_TRANSPORT_SECURITY_STATE_H_ | 6 #define NET_HTTP_TRANSPORT_SECURITY_STATE_H_ |
7 | 7 |
8 #include <map> | 8 #include <map> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
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/time.h" | 16 #include "base/time/time.h" |
17 #include "net/base/net_export.h" | 17 #include "net/base/net_export.h" |
18 #include "net/cert/x509_cert_types.h" | 18 #include "net/cert/x509_cert_types.h" |
19 #include "net/cert/x509_certificate.h" | 19 #include "net/cert/x509_certificate.h" |
20 | 20 |
| 21 class GURL; |
| 22 |
21 namespace net { | 23 namespace net { |
22 | 24 |
23 class SSLInfo; | 25 class SSLInfo; |
24 | 26 |
25 // Tracks which hosts have enabled strict transport security and/or public | 27 // Tracks which hosts have enabled strict transport security and/or public |
26 // key pins. | 28 // key pins. |
27 // | 29 // |
28 // This object manages the in-memory store. Register a Delegate with | 30 // This object manages the in-memory store. Register a Delegate with |
29 // |SetDelegate| to persist the state to disk. | 31 // |SetDelegate| to persist the state to disk. |
30 // | 32 // |
31 // HTTP strict transport security (HSTS) is defined in | 33 // HTTP strict transport security (HSTS) is defined in |
32 // http://tools.ietf.org/html/ietf-websec-strict-transport-sec, and | 34 // http://tools.ietf.org/html/ietf-websec-strict-transport-sec, and |
33 // HTTP-based dynamic public key pinning (HPKP) is defined in | 35 // HTTP-based dynamic public key pinning (HPKP) is defined in |
34 // http://tools.ietf.org/html/ietf-websec-key-pinning. | 36 // http://tools.ietf.org/html/ietf-websec-key-pinning. |
35 class NET_EXPORT TransportSecurityState | 37 class NET_EXPORT TransportSecurityState |
36 : NON_EXPORTED_BASE(public base::NonThreadSafe) { | 38 : NON_EXPORTED_BASE(public base::NonThreadSafe) { |
37 public: | 39 public: |
38 class NET_EXPORT Delegate { | 40 class NET_EXPORT Delegate { |
39 public: | 41 public: |
40 // This function may not block and may be called with internal locks held. | 42 // This function may not block and may be called with internal locks held. |
41 // Thus it must not reenter the TransportSecurityState object. | 43 // Thus it must not reenter the TransportSecurityState object. |
42 virtual void StateIsDirty(TransportSecurityState* state) = 0; | 44 virtual void StateIsDirty(TransportSecurityState* state) = 0; |
43 | 45 |
44 protected: | 46 protected: |
45 virtual ~Delegate() {} | 47 virtual ~Delegate() {} |
46 }; | 48 }; |
47 | 49 |
48 TransportSecurityState(); | |
49 ~TransportSecurityState(); | |
50 | |
51 // A DomainState describes the transport security state (required upgrade | 50 // A DomainState describes the transport security state (required upgrade |
52 // to HTTPS, and/or any public key pins). | 51 // to HTTPS, and/or any public key pins). |
53 // | 52 // |
54 // TODO(davidben): STSState and PKPState are queried and processed | 53 // TODO(davidben): STSState and PKPState are queried and processed |
55 // independently (with the exception of ShouldSSLErrorsBeFatal triggering on | 54 // independently (with the exception of ShouldSSLErrorsBeFatal triggering on |
56 // both and on-disk storage). DomainState should be split into the | 55 // both and on-disk storage). DomainState should be split into the |
57 // two. https://crbug.com/470295. | 56 // two. https://crbug.com/470295. |
58 class NET_EXPORT DomainState { | 57 class NET_EXPORT DomainState { |
59 public: | 58 public: |
60 enum UpgradeMode { | 59 enum UpgradeMode { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 // NOT intersect with the set of SPKIs in the TLS server's certificate | 105 // NOT intersect with the set of SPKIs in the TLS server's certificate |
107 // chain. | 106 // chain. |
108 HashValueVector bad_spki_hashes; | 107 HashValueVector bad_spki_hashes; |
109 | 108 |
110 // Are subdomains subject to this policy state? | 109 // Are subdomains subject to this policy state? |
111 bool include_subdomains; | 110 bool include_subdomains; |
112 | 111 |
113 // The domain which matched during a search for this DomainState entry. | 112 // The domain which matched during a search for this DomainState entry. |
114 // Updated by |GetDynamicDomainState| and |GetStaticDomainState|. | 113 // Updated by |GetDynamicDomainState| and |GetStaticDomainState|. |
115 std::string domain; | 114 std::string domain; |
| 115 |
| 116 // Optional; a uri-reference indicating where reports should be |
| 117 // sent when this pin is violated. |
| 118 std::string report_uri; |
116 }; | 119 }; |
117 | 120 |
118 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: | 121 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: |
119 // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND | 122 // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND |
120 // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty | 123 // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty |
121 // or at least one of them intersects |hashes|. | 124 // or at least one of them intersects |hashes|. |
122 // | 125 // |
123 // |{dynamic,static}_spki_hashes| contain trustworthy public key hashes, | 126 // |{dynamic,static}_spki_hashes| contain trustworthy public key hashes, |
124 // any one of which is sufficient to validate the certificate chain in | 127 // any one of which is sufficient to validate the certificate chain in |
125 // question. The public keys could be of a root CA, intermediate CA, or | 128 // question. The public keys could be of a root CA, intermediate CA, or |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 bool HasNext() const { return iterator_ != end_; } | 162 bool HasNext() const { return iterator_ != end_; } |
160 void Advance() { ++iterator_; } | 163 void Advance() { ++iterator_; } |
161 const std::string& hostname() const { return iterator_->first; } | 164 const std::string& hostname() const { return iterator_->first; } |
162 const DomainState& domain_state() const { return iterator_->second; } | 165 const DomainState& domain_state() const { return iterator_->second; } |
163 | 166 |
164 private: | 167 private: |
165 std::map<std::string, DomainState>::const_iterator iterator_; | 168 std::map<std::string, DomainState>::const_iterator iterator_; |
166 std::map<std::string, DomainState>::const_iterator end_; | 169 std::map<std::string, DomainState>::const_iterator end_; |
167 }; | 170 }; |
168 | 171 |
| 172 class NET_EXPORT Reporter { |
| 173 public: |
| 174 virtual ~Reporter() {} |
| 175 |
| 176 // Returns true if a violation report should be sent for the host in |
| 177 // the given |pkp_state|, and returns the report destination URI in |
| 178 // |report_uri|. Returns false if a report should not be sent. |
| 179 virtual bool GetHPKPReportUri(const DomainState::PKPState& pkp_state, |
| 180 GURL* report_uri) = 0; |
| 181 |
| 182 // Builds a serialized HPKP violation report in |
| 183 // |serialized_report|. Returns true on success and false on |
| 184 // failure. |
| 185 virtual bool BuildHPKPReport( |
| 186 const std::string& hostname, |
| 187 uint16_t port, |
| 188 const base::Time& expiry, |
| 189 bool include_subdomains, |
| 190 const std::string& effective_hostname, |
| 191 const scoped_refptr<X509Certificate>& served_certificate_chain, |
| 192 const scoped_refptr<X509Certificate>& validated_certificate_chain, |
| 193 const HashValueVector& spki_hashes, |
| 194 std::string* serialized_report) = 0; |
| 195 |
| 196 // Sends the given serialized |report| to |report_uri|. |
| 197 virtual void SendHPKPReport(const GURL& report_uri, |
| 198 const std::string& report) = 0; |
| 199 }; |
| 200 |
| 201 // Indicates whether or not a public key pin check should send a |
| 202 // report if a violation is detected. |
| 203 enum PublicKeyPinReportStatus { |
| 204 DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, |
| 205 SEND_PUBLIC_KEY_PIN_REPORT |
| 206 }; |
| 207 |
| 208 TransportSecurityState(); |
| 209 ~TransportSecurityState(); |
| 210 |
169 // These functions search for static and dynamic DomainStates, and invoke the | 211 // These functions search for static and dynamic DomainStates, and invoke the |
170 // functions of the same name on them. These functions are the primary public | 212 // functions of the same name on them. These functions are the primary public |
171 // interface; direct access to DomainStates is best left to tests. | 213 // interface; direct access to DomainStates is best left to tests. |
172 bool ShouldSSLErrorsBeFatal(const std::string& host); | 214 bool ShouldSSLErrorsBeFatal(const std::string& host); |
173 bool ShouldUpgradeToSSL(const std::string& host); | 215 bool ShouldUpgradeToSSL(const std::string& host); |
174 bool CheckPublicKeyPins(const std::string& host, | 216 bool CheckPublicKeyPins( |
175 bool is_issued_by_known_root, | 217 const std::string& host, |
176 const HashValueVector& hashes, | 218 bool is_issued_by_known_root, |
177 std::string* failure_log); | 219 const HashValueVector& hashes, |
| 220 uint16_t port, |
| 221 const scoped_refptr<X509Certificate>& served_certificate_chain, |
| 222 const scoped_refptr<X509Certificate>& validated_certificate_chain, |
| 223 const PublicKeyPinReportStatus report_status, |
| 224 std::string* failure_log); |
178 bool HasPublicKeyPins(const std::string& host); | 225 bool HasPublicKeyPins(const std::string& host); |
179 | 226 |
180 // Assign a |Delegate| for persisting the transport security state. If | 227 // Assign a |Delegate| for persisting the transport security state. If |
181 // |NULL|, state will not be persisted. The caller retains | 228 // |NULL|, state will not be persisted. The caller retains |
182 // ownership of |delegate|. | 229 // ownership of |delegate|. |
183 // Note: This is only used for serializing/deserializing the | 230 // Note: This is only used for serializing/deserializing the |
184 // TransportSecurityState. | 231 // TransportSecurityState. |
185 void SetDelegate(Delegate* delegate); | 232 void SetDelegate(Delegate* delegate); |
186 | 233 |
| 234 void SetReporter(Reporter* reporter); |
| 235 |
187 // Clears all dynamic data (e.g. HSTS and HPKP data). | 236 // Clears all dynamic data (e.g. HSTS and HPKP data). |
188 // | 237 // |
189 // Does NOT persist changes using the Delegate, as this function is only | 238 // Does NOT persist changes using the Delegate, as this function is only |
190 // used to clear any dynamic data prior to re-loading it from a file. | 239 // used to clear any dynamic data prior to re-loading it from a file. |
191 // Note: This is only used for serializing/deserializing the | 240 // Note: This is only used for serializing/deserializing the |
192 // TransportSecurityState. | 241 // TransportSecurityState. |
193 void ClearDynamicData(); | 242 void ClearDynamicData(); |
194 | 243 |
195 // Inserts |state| into |enabled_hosts_| under the key |hashed_host|. | 244 // Inserts |state| into |enabled_hosts_| under the key |hashed_host|. |
196 // |hashed_host| is already in the internal representation. | 245 // |hashed_host| is already in the internal representation. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 // HSTS header (used for net-internals and unit tests). | 296 // HSTS header (used for net-internals and unit tests). |
248 void AddHSTS(const std::string& host, | 297 void AddHSTS(const std::string& host, |
249 const base::Time& expiry, | 298 const base::Time& expiry, |
250 bool include_subdomains); | 299 bool include_subdomains); |
251 | 300 |
252 // Adds explicitly-specified data as if it was processed from an | 301 // Adds explicitly-specified data as if it was processed from an |
253 // HPKP header (used for net-internals and unit tests). | 302 // HPKP header (used for net-internals and unit tests). |
254 void AddHPKP(const std::string& host, | 303 void AddHPKP(const std::string& host, |
255 const base::Time& expiry, | 304 const base::Time& expiry, |
256 bool include_subdomains, | 305 bool include_subdomains, |
257 const HashValueVector& hashes); | 306 const HashValueVector& hashes, |
| 307 const std::string& report_uri); |
258 | 308 |
259 // Returns true iff we have any static public key pins for the |host| and | 309 // Returns true iff we have any static public key pins for the |host| and |
260 // iff its set of required pins is the set we expect for Google | 310 // iff its set of required pins is the set we expect for Google |
261 // properties. | 311 // properties. |
262 // | 312 // |
263 // If |host| matches both an exact entry and is a subdomain of another | 313 // If |host| matches both an exact entry and is a subdomain of another |
264 // entry, the exact match determines the return value. | 314 // entry, the exact match determines the return value. |
265 static bool IsGooglePinnedProperty(const std::string& host); | 315 static bool IsGooglePinnedProperty(const std::string& host); |
266 | 316 |
267 // The maximum number of seconds for which we'll cache an HSTS request. | 317 // The maximum number of seconds for which we'll cache an HSTS request. |
(...skipping 16 matching lines...) Expand all Loading... |
284 // representation of first-class DomainStates, and exposing the preloads | 334 // representation of first-class DomainStates, and exposing the preloads |
285 // to the caller with |GetStaticDomainState|. | 335 // to the caller with |GetStaticDomainState|. |
286 static void ReportUMAOnPinFailure(const std::string& host); | 336 static void ReportUMAOnPinFailure(const std::string& host); |
287 | 337 |
288 // IsBuildTimely returns true if the current build is new enough ensure that | 338 // IsBuildTimely returns true if the current build is new enough ensure that |
289 // built in security information (i.e. HSTS preloading and pinning | 339 // built in security information (i.e. HSTS preloading and pinning |
290 // information) is timely. | 340 // information) is timely. |
291 static bool IsBuildTimely(); | 341 static bool IsBuildTimely(); |
292 | 342 |
293 // Helper method for actually checking pins. | 343 // Helper method for actually checking pins. |
294 bool CheckPublicKeyPinsImpl(const std::string& host, | 344 bool CheckPublicKeyPinsImpl( |
295 const HashValueVector& hashes, | 345 const std::string& host, |
296 std::string* failure_log); | 346 const HashValueVector& hashes, |
| 347 uint16_t port, |
| 348 const scoped_refptr<X509Certificate>& served_certificate_chain, |
| 349 const scoped_refptr<X509Certificate>& validated_certificate_chain, |
| 350 const PublicKeyPinReportStatus report_status, |
| 351 std::string* failure_log); |
297 | 352 |
298 // If a Delegate is present, notify it that the internal state has | 353 // If a Delegate is present, notify it that the internal state has |
299 // changed. | 354 // changed. |
300 void DirtyNotify(); | 355 void DirtyNotify(); |
301 | 356 |
302 // Adds HSTS state to |host|. | 357 // Adds HSTS state to |host|. |
303 void AddHSTSInternal(const std::string& host, | 358 void AddHSTSInternal(const std::string& host, |
304 DomainState::UpgradeMode upgrade_mode, | 359 DomainState::UpgradeMode upgrade_mode, |
305 const base::Time& expiry, | 360 const base::Time& expiry, |
306 bool include_subdomains); | 361 bool include_subdomains); |
307 | 362 |
308 // Adds HPKP state to |host|. | 363 // Adds HPKP state to |host|. |
309 void AddHPKPInternal(const std::string& host, | 364 void AddHPKPInternal(const std::string& host, |
310 const base::Time& last_observed, | 365 const base::Time& last_observed, |
311 const base::Time& expiry, | 366 const base::Time& expiry, |
312 bool include_subdomains, | 367 bool include_subdomains, |
313 const HashValueVector& hashes); | 368 const HashValueVector& hashes, |
| 369 const std::string& report_uri); |
314 | 370 |
315 // Enable TransportSecurity for |host|. |state| supercedes any previous | 371 // Enable TransportSecurity for |host|. |state| supercedes any previous |
316 // state for the |host|, including static entries. | 372 // state for the |host|, including static entries. |
317 // | 373 // |
318 // The new state for |host| is persisted using the Delegate (if any). | 374 // The new state for |host| is persisted using the Delegate (if any). |
319 void EnableHost(const std::string& host, const DomainState& state); | 375 void EnableHost(const std::string& host, const DomainState& state); |
320 | 376 |
321 // The set of hosts that have enabled TransportSecurity. |sts.domain| and | 377 // The set of hosts that have enabled TransportSecurity. |sts.domain| and |
322 // |pkp.domain| will always be empty for a DomainState in this map; the domain | 378 // |pkp.domain| will always be empty for a DomainState in this map; the domain |
323 // comes from the map key instead. | 379 // comes from the map key instead. |
324 DomainStateMap enabled_hosts_; | 380 DomainStateMap enabled_hosts_; |
325 | 381 |
326 Delegate* delegate_; | 382 Delegate* delegate_; |
327 | 383 |
| 384 Reporter* reporter_; |
| 385 |
328 // True if static pins should be used. | 386 // True if static pins should be used. |
329 bool enable_static_pins_; | 387 bool enable_static_pins_; |
330 | 388 |
331 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); | 389 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); |
332 }; | 390 }; |
333 | 391 |
334 } // namespace net | 392 } // namespace net |
335 | 393 |
336 #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_H_ | 394 #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_H_ |
OLD | NEW |