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