Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / http / transport_security_state.h
blobd7befb7cfef31d159e94633308074936a6088cd2
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
3 // found in the LICENSE file.
5 #ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_H_
6 #define NET_HTTP_TRANSPORT_SECURITY_STATE_H_
8 #include <stdint.h>
10 #include <map>
11 #include <string>
12 #include <utility>
13 #include <vector>
15 #include "base/gtest_prod_util.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "base/time/time.h"
18 #include "net/base/net_export.h"
19 #include "net/cert/x509_cert_types.h"
20 #include "net/cert/x509_certificate.h"
21 #include "url/gurl.h"
23 class GURL;
25 namespace net {
27 class HostPortPair;
28 class SSLInfo;
30 // Tracks which hosts have enabled strict transport security and/or public
31 // key pins.
33 // This object manages the in-memory store. Register a Delegate with
34 // |SetDelegate| to persist the state to disk.
36 // HTTP strict transport security (HSTS) is defined in
37 // http://tools.ietf.org/html/ietf-websec-strict-transport-sec, and
38 // HTTP-based dynamic public key pinning (HPKP) is defined in
39 // http://tools.ietf.org/html/ietf-websec-key-pinning.
40 class NET_EXPORT TransportSecurityState
41 : NON_EXPORTED_BASE(public base::NonThreadSafe) {
42 public:
43 class NET_EXPORT Delegate {
44 public:
45 // This function may not block and may be called with internal locks held.
46 // Thus it must not reenter the TransportSecurityState object.
47 virtual void StateIsDirty(TransportSecurityState* state) = 0;
49 protected:
50 virtual ~Delegate() {}
53 // A STSState describes the strict transport security state (required
54 // upgrade to HTTPS).
55 class NET_EXPORT STSState {
56 public:
57 enum UpgradeMode {
58 // These numbers must match those in hsts_view.js, function modeToString.
59 MODE_FORCE_HTTPS = 0,
60 MODE_DEFAULT = 1,
63 STSState();
64 ~STSState();
66 // The absolute time (UTC) when the |upgrade_mode| (and other state) was
67 // observed.
68 base::Time last_observed;
70 // The absolute time (UTC) when |upgrade_mode| (and other state)
71 // expires.
72 base::Time expiry;
74 UpgradeMode upgrade_mode;
76 // Are subdomains subject to this policy state?
77 bool include_subdomains;
79 // The domain which matched during a search for this STSState entry.
80 // Updated by |GetDynamicSTSState| and |GetStaticDomainState|.
81 std::string domain;
83 // ShouldUpgradeToSSL returns true iff HTTP requests should be internally
84 // redirected to HTTPS (also if WS should be upgraded to WSS).
85 bool ShouldUpgradeToSSL() const;
87 // ShouldSSLErrorsBeFatal returns true iff HTTPS errors should cause
88 // hard-fail behavior (e.g. if HSTS is set for the domain).
89 bool ShouldSSLErrorsBeFatal() const;
92 class NET_EXPORT STSStateIterator {
93 public:
94 explicit STSStateIterator(const TransportSecurityState& state);
95 ~STSStateIterator();
97 bool HasNext() const { return iterator_ != end_; }
98 void Advance() { ++iterator_; }
99 const std::string& hostname() const { return iterator_->first; }
100 const STSState& domain_state() const { return iterator_->second; }
102 private:
103 std::map<std::string, STSState>::const_iterator iterator_;
104 std::map<std::string, STSState>::const_iterator end_;
107 // A PKPState describes the public key pinning state.
108 class NET_EXPORT PKPState {
109 public:
110 PKPState();
111 ~PKPState();
113 // The absolute time (UTC) when the |spki_hashes| (and other state) were
114 // observed.
115 base::Time last_observed;
117 // The absolute time (UTC) when the |spki_hashes| expire.
118 base::Time expiry;
120 // Optional; hashes of pinned SubjectPublicKeyInfos.
121 HashValueVector spki_hashes;
123 // Optional; hashes of static known-bad SubjectPublicKeyInfos which MUST
124 // NOT intersect with the set of SPKIs in the TLS server's certificate
125 // chain.
126 HashValueVector bad_spki_hashes;
128 // Are subdomains subject to this policy state?
129 bool include_subdomains;
131 // The domain which matched during a search for this DomainState entry.
132 // Updated by |GetDynamicPKPState| and |GetStaticDomainState|.
133 std::string domain;
135 // An optional URI indicating where reports should be sent when this
136 // pin is violated, or empty when omitted.
137 GURL report_uri;
139 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if:
140 // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND
141 // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty
142 // or at least one of them intersects |hashes|.
144 // |{dynamic,static}_spki_hashes| contain trustworthy public key hashes,
145 // any one of which is sufficient to validate the certificate chain in
146 // question. The public keys could be of a root CA, intermediate CA, or
147 // leaf certificate, depending on the security vs. disaster recovery
148 // tradeoff selected. (Pinning only to leaf certifiates increases
149 // security because you no longer trust any CAs, but it hampers disaster
150 // recovery because you can't just get a new certificate signed by the
151 // CA.)
153 // |bad_static_spki_hashes| contains public keys that we don't want to
154 // trust.
155 bool CheckPublicKeyPins(const HashValueVector& hashes,
156 std::string* failure_log) const;
158 // Returns true if any of the HashValueVectors |static_spki_hashes|,
159 // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any
160 // items.
161 bool HasPublicKeyPins() const;
163 // ShouldSSLErrorsBeFatal returns true iff HTTPS errors should cause
164 // hard-fail behavior (e.g. if HSTS is set for the domain).
165 bool ShouldSSLErrorsBeFatal() const;
168 class NET_EXPORT PKPStateIterator {
169 public:
170 explicit PKPStateIterator(const TransportSecurityState& state);
171 ~PKPStateIterator();
173 bool HasNext() const { return iterator_ != end_; }
174 void Advance() { ++iterator_; }
175 const std::string& hostname() const { return iterator_->first; }
176 const PKPState& domain_state() const { return iterator_->second; }
178 private:
179 std::map<std::string, PKPState>::const_iterator iterator_;
180 std::map<std::string, PKPState>::const_iterator end_;
183 // An interface for asynchronously sending HPKP violation reports.
184 class NET_EXPORT ReportSender {
185 public:
186 // Sends the given serialized |report| to |report_uri|.
187 virtual void Send(const GURL& report_uri, const std::string& report) = 0;
189 protected:
190 virtual ~ReportSender() {}
193 // Indicates whether or not a public key pin check should send a
194 // report if a violation is detected.
195 enum PublicKeyPinReportStatus { ENABLE_PIN_REPORTS, DISABLE_PIN_REPORTS };
197 TransportSecurityState();
198 ~TransportSecurityState();
200 // These functions search for static and dynamic STS and PKP states, and
201 // invoke the functions of the same name on them. These functions are the
202 // primary public interface; direct access to STS and PKP states is best
203 // left to tests.
204 bool ShouldSSLErrorsBeFatal(const std::string& host);
205 bool ShouldUpgradeToSSL(const std::string& host);
206 bool CheckPublicKeyPins(const HostPortPair& host_port_pair,
207 bool is_issued_by_known_root,
208 const HashValueVector& hashes,
209 const X509Certificate* served_certificate_chain,
210 const X509Certificate* validated_certificate_chain,
211 const PublicKeyPinReportStatus report_status,
212 std::string* failure_log);
213 bool HasPublicKeyPins(const std::string& host);
215 // Assign a |Delegate| for persisting the transport security state. If
216 // |NULL|, state will not be persisted. The caller retains
217 // ownership of |delegate|.
218 // Note: This is only used for serializing/deserializing the
219 // TransportSecurityState.
220 void SetDelegate(Delegate* delegate);
222 void SetReportSender(ReportSender* report_sender);
224 // Clears all dynamic data (e.g. HSTS and HPKP data).
226 // Does NOT persist changes using the Delegate, as this function is only
227 // used to clear any dynamic data prior to re-loading it from a file.
228 // Note: This is only used for serializing/deserializing the
229 // TransportSecurityState.
230 void ClearDynamicData();
232 // Inserts |state| into |enabled_sts_hosts_| under the key |hashed_host|.
233 // |hashed_host| is already in the internal representation.
234 // Note: This is only used for serializing/deserializing the
235 // TransportSecurityState.
236 void AddOrUpdateEnabledSTSHosts(const std::string& hashed_host,
237 const STSState& state);
239 // Inserts |state| into |enabled_pkp_hosts_| under the key |hashed_host|.
240 // |hashed_host| is already in the internal representation.
241 // Note: This is only used for serializing/deserializing the
242 // TransportSecurityState.
243 void AddOrUpdateEnabledPKPHosts(const std::string& hashed_host,
244 const PKPState& state);
246 // Deletes all dynamic data (e.g. HSTS or HPKP data) created since a given
247 // time.
249 // If any entries are deleted, the new state will be persisted through
250 // the Delegate (if any).
251 void DeleteAllDynamicDataSince(const base::Time& time);
253 // Deletes any dynamic data stored for |host| (e.g. HSTS or HPKP data).
254 // If |host| doesn't have an exact entry then no action is taken. Does
255 // not delete static (i.e. preloaded) data. Returns true iff an entry
256 // was deleted.
258 // If an entry is deleted, the new state will be persisted through
259 // the Delegate (if any).
260 bool DeleteDynamicDataForHost(const std::string& host);
262 // Returns true and updates |*sts_result| and |*pkp_result| iff there is a
263 // static (built-in) state for |host|. If multiple entries match |host|,
264 // the most specific match determines the return value.
265 bool GetStaticDomainState(const std::string& host,
266 STSState* sts_result,
267 PKPState* pkp_result) const;
269 // Returns true and updates |*result| iff |host| has HSTS (respectively, HPKP)
270 // state. If multiple HSTS (respectively, HPKP) entries match |host|, the
271 // most specific match determines the HSTS (respectively, HPKP) return value.
273 // Note that these methods are not const because they opportunistically remove
274 // entries that have expired.
275 bool GetDynamicSTSState(const std::string& host, STSState* result);
276 bool GetDynamicPKPState(const std::string& host, PKPState* result);
278 // Processes an HSTS header value from the host, adding entries to
279 // dynamic state if necessary.
280 bool AddHSTSHeader(const std::string& host, const std::string& value);
282 // Processes an HPKP header value from the host, adding entries to
283 // dynamic state if necessary. ssl_info is used to check that
284 // the specified pins overlap with the certificate chain.
285 bool AddHPKPHeader(const std::string& host, const std::string& value,
286 const SSLInfo& ssl_info);
288 // Adds explicitly-specified data as if it was processed from an
289 // HSTS header (used for net-internals and unit tests).
290 void AddHSTS(const std::string& host,
291 const base::Time& expiry,
292 bool include_subdomains);
294 // Adds explicitly-specified data as if it was processed from an
295 // HPKP header (used for net-internals and unit tests).
296 void AddHPKP(const std::string& host,
297 const base::Time& expiry,
298 bool include_subdomains,
299 const HashValueVector& hashes,
300 const GURL& report_uri);
302 // Parses |value| as a Public-Key-Pins-Report-Only header value and
303 // sends a HPKP report for |host_port_pair| if |ssl_info| violates the
304 // pin. Returns true if |value| parses and includes a valid
305 // report-uri, and false otherwise.
306 bool ProcessHPKPReportOnlyHeader(const std::string& value,
307 const HostPortPair& host_port_pair,
308 const SSLInfo& ssl_info);
310 // Returns true iff we have any static public key pins for the |host| and
311 // iff its set of required pins is the set we expect for Google
312 // properties.
314 // If |host| matches both an exact entry and is a subdomain of another
315 // entry, the exact match determines the return value.
316 static bool IsGooglePinnedProperty(const std::string& host);
318 // The maximum number of seconds for which we'll cache an HSTS request.
319 static const long int kMaxHSTSAgeSecs;
321 private:
322 friend class TransportSecurityStateTest;
323 FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPOnly);
324 FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0);
325 FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, NoClobberPins);
327 typedef std::map<std::string, STSState> STSStateMap;
328 typedef std::map<std::string, PKPState> PKPStateMap;
330 // Send an UMA report on pin validation failure, if the host is in a
331 // statically-defined list of domains.
333 // TODO(palmer): This doesn't really belong here, and should be moved into
334 // the exactly one call site. This requires unifying |struct HSTSPreload|
335 // (an implementation detail of this class) with a more generic
336 // representation of first-class DomainStates, and exposing the preloads
337 // to the caller with |GetStaticDomainState|.
338 static void ReportUMAOnPinFailure(const std::string& host);
340 // IsBuildTimely returns true if the current build is new enough ensure that
341 // built in security information (i.e. HSTS preloading and pinning
342 // information) is timely.
343 static bool IsBuildTimely();
345 // Helper method for actually checking pins.
346 bool CheckPublicKeyPinsImpl(
347 const HostPortPair& host_port_pair,
348 const HashValueVector& hashes,
349 const X509Certificate* served_certificate_chain,
350 const X509Certificate* validated_certificate_chain,
351 const PublicKeyPinReportStatus report_status,
352 std::string* failure_log);
354 // If a Delegate is present, notify it that the internal state has
355 // changed.
356 void DirtyNotify();
358 // Adds HSTS state to |host|.
359 void AddHSTSInternal(const std::string& host,
360 STSState::UpgradeMode upgrade_mode,
361 const base::Time& expiry,
362 bool include_subdomains);
364 // Adds HPKP state to |host|.
365 void AddHPKPInternal(const std::string& host,
366 const base::Time& last_observed,
367 const base::Time& expiry,
368 bool include_subdomains,
369 const HashValueVector& hashes,
370 const GURL& report_uri);
372 // Enable TransportSecurity for |host|. |state| supercedes any previous
373 // state for the |host|, including static entries.
375 // The new state for |host| is persisted using the Delegate (if any).
376 void EnableSTSHost(const std::string& host, const STSState& state);
377 void EnablePKPHost(const std::string& host, const PKPState& state);
379 // The sets of hosts that have enabled TransportSecurity. |domain| will always
380 // be empty for a STSState or PKPState in these maps; the domain
381 // comes from the map keys instead. In addition, |upgrade_mode| in the
382 // STSState is never MODE_DEFAULT and |HasPublicKeyPins| in the PKPState
383 // always returns true.
384 STSStateMap enabled_sts_hosts_;
385 PKPStateMap enabled_pkp_hosts_;
387 Delegate* delegate_;
389 ReportSender* report_sender_;
391 // True if static pins should be used.
392 bool enable_static_pins_;
394 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState);
397 } // namespace net
399 #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_H_