1 // Copyright (c) 2011 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. 4 5 #ifndef NET_BASE_TRANSPORT_SECURITY_STATE_H_ 6 #define NET_BASE_TRANSPORT_SECURITY_STATE_H_ 7 #pragma once 8 9 #include <map> 10 #include <string> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/time.h" 17 #include "net/base/x509_cert_types.h" 18 19 namespace net { 20 21 // TransportSecurityState 22 // 23 // Tracks which hosts have enabled *-Transport-Security. This object manages 24 // the in-memory store. A separate object must register itself with this object 25 // in order to persist the state to disk. 26 class TransportSecurityState : 27 public base::RefCountedThreadSafe<TransportSecurityState> { 28 public: 29 TransportSecurityState(); 30 31 // A DomainState is the information that we persist about a given domain. 32 struct DomainState { 33 enum Mode { 34 // Strict mode implies: 35 // * We generate internal redirects from HTTP -> HTTPS. 36 // * Certificate issues are fatal. 37 MODE_STRICT = 0, 38 // Opportunistic mode implies: 39 // * We'll request HTTP URLs over HTTPS 40 // * Certificate issues are ignored. 41 MODE_OPPORTUNISTIC = 1, 42 // SPDY_ONLY (aka X-Bodge-Transport-Security) is a hopefully temporary 43 // measure. It implies: 44 // * We'll request HTTP URLs over HTTPS iff we have SPDY support. 45 // * Certificate issues are fatal. 46 MODE_SPDY_ONLY = 2, 47 // None means there is no HSTS for this domain. 48 MODE_NONE = 3, 49 }; 50 51 DomainState(); 52 ~DomainState(); 53 54 // IsChainOfPublicKeysPermitted takes a set of public key hashes and 55 // returns true if: 56 // 1) |public_key_hashes| is empty, i.e. no public keys have been pinned. 57 // 2) |hashes| and |public_key_hashes| are not disjoint. 58 bool IsChainOfPublicKeysPermitted( 59 const std::vector<SHA1Fingerprint>& hashes); 60 61 Mode mode; 62 base::Time created; // when this host entry was first created 63 base::Time expiry; // the absolute time (UTC) when this record expires 64 bool include_subdomains; // subdomains included? 65 std::vector<SHA1Fingerprint> public_key_hashes; // optional; permitted keys 66 67 // The follow members are not valid when stored in |enabled_hosts_|. 68 bool preloaded; // is this a preloaded entry? 69 std::string domain; // the domain which matched 70 }; 71 72 // Enable TransportSecurity for |host|. 73 void EnableHost(const std::string& host, const DomainState& state); 74 75 // Delete any entry for |host|. If |host| doesn't have an exact entry then no 76 // action is taken. Returns true iff an entry was deleted. 77 bool DeleteHost(const std::string& host); 78 79 // Returns true if |host| has TransportSecurity enabled, in the context of 80 // |sni_available|. In that case, *result is filled out. 81 bool IsEnabledForHost(DomainState* result, 82 const std::string& host, 83 bool sni_available); 84 85 // Deletes all records created since a given time. 86 void DeleteSince(const base::Time& time); 87 88 // Returns |true| if |value| parses as a valid *-Transport-Security 89 // header value. The values of max-age and and includeSubDomains are 90 // returned in |max_age| and |include_subdomains|, respectively. The out 91 // parameters are not modified if the function returns |false|. 92 static bool ParseHeader(const std::string& value, 93 int* max_age, 94 bool* include_subdomains); 95 96 class Delegate { 97 public: 98 // This function may not block and may be called with internal locks held. 99 // Thus it must not reenter the TransportSecurityState object. 100 virtual void StateIsDirty(TransportSecurityState* state) = 0; 101 102 protected: 103 virtual ~Delegate() {} 104 }; 105 106 void SetDelegate(Delegate*); 107 108 bool Serialise(std::string* output); 109 // Existing non-preloaded entries are cleared and repopulated from the 110 // passed JSON string. 111 bool LoadEntries(const std::string& state, bool* dirty); 112 113 // The maximum number of seconds for which we'll cache an HSTS request. 114 static const long int kMaxHSTSAgeSecs; 115 116 private: 117 friend class base::RefCountedThreadSafe<TransportSecurityState>; 118 FRIEND_TEST_ALL_PREFIXES(TransportSecurityStateTest, IsPreloaded); 119 120 ~TransportSecurityState(); 121 122 // If we have a callback configured, call it to let our serialiser know that 123 // our state is dirty. 124 void DirtyNotify(); 125 126 static std::string CanonicalizeHost(const std::string& host); 127 static bool IsPreloadedSTS(const std::string& canonicalized_host, 128 bool sni_available, 129 DomainState* out); 130 static bool Deserialise(const std::string& state, 131 bool* dirty, 132 std::map<std::string, DomainState>* out); 133 134 // The set of hosts that have enabled TransportSecurity. The keys here 135 // are SHA256(DNSForm(domain)) where DNSForm converts from dotted form 136 // ('www.google.com') to the form used in DNS: "\x03www\x06google\x03com" 137 std::map<std::string, DomainState> enabled_hosts_; 138 139 // Our delegate who gets notified when we are dirtied, or NULL. 140 Delegate* delegate_; 141 142 DISALLOW_COPY_AND_ASSIGN(TransportSecurityState); 143 }; 144 145 } // namespace net 146 147 #endif // NET_BASE_TRANSPORT_SECURITY_STATE_H_ 148