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.
4
5// TransportSecurityState maintains an in memory database containing the
6// list of hosts that currently have transport security enabled. This
7// singleton object deals with writing that data out to disk as needed and
8// loading it at startup.
9
10// At startup we need to load the transport security state from the
11// disk. For the moment, we don't want to delay startup for this load, so we
12// let the TransportSecurityState run for a while without being loaded.
13// This means that it's possible for pages opened very quickly not to get the
14// correct transport security information.
15//
16// To load the state, we schedule a Task on background_runner, which
17// deserializes and configures the TransportSecurityState.
18//
19// The TransportSecurityState object supports running a callback function
20// when it changes. This object registers the callback, pointing at itself.
21//
22// TransportSecurityState calls...
23// TransportSecurityPersister::StateIsDirty
24//   since the callback isn't allowed to block or reenter, we schedule a Task
25//   on the file task runner after some small amount of time
26//
27// ...
28//
29// TransportSecurityPersister::SerializeState
30//   copies the current state of the TransportSecurityState, serializes
31//   and writes to disk.
32
33#ifndef NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
34#define NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
35
36#include <string>
37
38#include "base/files/file_path.h"
39#include "base/files/important_file_writer.h"
40#include "base/memory/ref_counted.h"
41#include "base/memory/weak_ptr.h"
42#include "net/base/net_export.h"
43#include "net/http/transport_security_state.h"
44
45namespace base {
46class SequencedTaskRunner;
47}
48
49namespace net {
50
51// Reads and updates on-disk TransportSecurity state. Clients of this class
52// should create, destroy, and call into it from one thread.
53//
54// background_runner is the task runner this class should use internally to
55// perform file IO, and can optionally be associated with a different thread.
56class NET_EXPORT TransportSecurityPersister
57    : public TransportSecurityState::Delegate,
58      public base::ImportantFileWriter::DataSerializer {
59 public:
60  TransportSecurityPersister(
61      TransportSecurityState* state,
62      const base::FilePath& profile_path,
63      const scoped_refptr<base::SequencedTaskRunner>& background_runner,
64      bool readonly);
65  virtual ~TransportSecurityPersister();
66
67  // Called by the TransportSecurityState when it changes its state.
68  virtual void StateIsDirty(TransportSecurityState*) OVERRIDE;
69
70  // ImportantFileWriter::DataSerializer:
71  //
72  // Serializes |transport_security_state_| into |*output|. Returns true if
73  // all DomainStates were serialized correctly.
74  //
75  // The serialization format is JSON; the JSON represents a dictionary of
76  // host:DomainState pairs (host is a string). The DomainState is
77  // represented as a dictionary containing the following keys and value
78  // types (not all keys will always be present):
79  //
80  //     "sts_include_subdomains": true|false
81  //     "pkp_include_subdomains": true|false
82  //     "created": double
83  //     "expiry": double
84  //     "dynamic_spki_hashes_expiry": double
85  //     "mode": "default"|"force-https"
86  //             legacy value synonyms "strict" = "force-https"
87  //                                   "pinning-only" = "default"
88  //             legacy value "spdy-only" is unused and ignored
89  //     "static_spki_hashes": list of strings
90  //         legacy key synonym "preloaded_spki_hashes"
91  //     "bad_static_spki_hashes": list of strings
92  //         legacy key synonym "bad_preloaded_spki_hashes"
93  //     "dynamic_spki_hashes": list of strings
94  //
95  // The JSON dictionary keys are strings containing
96  // Base64(SHA256(TransportSecurityState::CanonicalizeHost(domain))).
97  // The reason for hashing them is so that the stored state does not
98  // trivially reveal a user's browsing history to an attacker reading the
99  // serialized state on disk.
100  virtual bool SerializeData(std::string* data) OVERRIDE;
101
102  // Clears any existing non-static entries, and then re-populates
103  // |transport_security_state_|.
104  //
105  // Sets |*dirty| to true if the new state differs from the persisted
106  // state; false otherwise.
107  bool LoadEntries(const std::string& serialized, bool* dirty);
108
109 private:
110  // Populates |state| from the JSON string |serialized|. Returns true if
111  // all entries were parsed and deserialized correctly.
112  //
113  // Sets |*dirty| to true if the new state differs from the persisted
114  // state; false otherwise.
115  static bool Deserialize(const std::string& serialized,
116                          bool* dirty,
117                          TransportSecurityState* state);
118
119  void CompleteLoad(const std::string& state);
120
121  TransportSecurityState* transport_security_state_;
122
123  // Helper for safely writing the data.
124  base::ImportantFileWriter writer_;
125
126  scoped_refptr<base::SequencedTaskRunner> foreground_runner_;
127  scoped_refptr<base::SequencedTaskRunner> background_runner_;
128
129  // Whether or not we're in read-only mode.
130  const bool readonly_;
131
132  base::WeakPtrFactory<TransportSecurityPersister> weak_ptr_factory_;
133
134  DISALLOW_COPY_AND_ASSIGN(TransportSecurityPersister);
135};
136
137}  // namespace net
138
139#endif  // NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
140