Home | History | Annotate | Download | only in base
      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