Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: net/http/transport_security_persister.cc

Issue 2751803002: Serialize and deserialize dynamic Expect-CT state (Closed)
Patch Set: add test for LoadEntries clearing Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/transport_security_persister.h" 5 #include "net/http/transport_security_persister.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/feature_list.h"
12 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
13 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
14 #include "base/json/json_reader.h" 15 #include "base/json/json_reader.h"
15 #include "base/json/json_writer.h" 16 #include "base/json/json_writer.h"
16 #include "base/location.h" 17 #include "base/location.h"
17 #include "base/sequenced_task_runner.h" 18 #include "base/sequenced_task_runner.h"
18 #include "base/task_runner_util.h" 19 #include "base/task_runner_util.h"
19 #include "base/threading/thread_task_runner_handle.h" 20 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/values.h" 21 #include "base/values.h"
21 #include "crypto/sha2.h" 22 #include "crypto/sha2.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 const char kDynamicSPKIHashesExpiry[] = "dynamic_spki_hashes_expiry"; 75 const char kDynamicSPKIHashesExpiry[] = "dynamic_spki_hashes_expiry";
75 const char kDynamicSPKIHashes[] = "dynamic_spki_hashes"; 76 const char kDynamicSPKIHashes[] = "dynamic_spki_hashes";
76 const char kForceHTTPS[] = "force-https"; 77 const char kForceHTTPS[] = "force-https";
77 const char kStrict[] = "strict"; 78 const char kStrict[] = "strict";
78 const char kDefault[] = "default"; 79 const char kDefault[] = "default";
79 const char kPinningOnly[] = "pinning-only"; 80 const char kPinningOnly[] = "pinning-only";
80 const char kCreated[] = "created"; 81 const char kCreated[] = "created";
81 const char kStsObserved[] = "sts_observed"; 82 const char kStsObserved[] = "sts_observed";
82 const char kPkpObserved[] = "pkp_observed"; 83 const char kPkpObserved[] = "pkp_observed";
83 const char kReportUri[] = "report-uri"; 84 const char kReportUri[] = "report-uri";
85 // The keys below are contained in a subdictionary keyed as
86 // |kExpectCTSubdictionary|.
87 const char kExpectCTSubdictionary[] = "expect_ct";
88 const char kExpectCTExpiry[] = "expect_ct_expiry";
89 const char kExpectCTObserved[] = "expect_ct_observed";
90 const char kExpectCTEnforce[] = "expect_ct_enforce";
91 const char kExpectCTReportUri[] = "expect_ct_report_uri";
84 92
85 std::string LoadState(const base::FilePath& path) { 93 std::string LoadState(const base::FilePath& path) {
86 std::string result; 94 std::string result;
87 if (!base::ReadFileToString(path, &result)) { 95 if (!base::ReadFileToString(path, &result)) {
88 return ""; 96 return "";
89 } 97 }
90 return result; 98 return result;
91 } 99 }
92 100
93 } // namespace 101 bool IsDynamicExpectCTEnabled() {
94 102 return base::FeatureList::IsEnabled(
95 TransportSecurityPersister::TransportSecurityPersister( 103 TransportSecurityState::kDynamicExpectCTFeature);
96 TransportSecurityState* state,
97 const base::FilePath& profile_path,
98 const scoped_refptr<base::SequencedTaskRunner>& background_runner,
99 bool readonly)
100 : transport_security_state_(state),
101 writer_(profile_path.AppendASCII("TransportSecurity"), background_runner),
102 foreground_runner_(base::ThreadTaskRunnerHandle::Get()),
103 background_runner_(background_runner),
104 readonly_(readonly),
105 weak_ptr_factory_(this) {
106 transport_security_state_->SetDelegate(this);
107
108 base::PostTaskAndReplyWithResult(
109 background_runner_.get(), FROM_HERE,
110 base::Bind(&LoadState, writer_.path()),
111 base::Bind(&TransportSecurityPersister::CompleteLoad,
112 weak_ptr_factory_.GetWeakPtr()));
113 } 104 }
114 105
115 TransportSecurityPersister::~TransportSecurityPersister() { 106 // Populates |host| with default values for the STS and PKP states.
116 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); 107 // These default values represent "null" states and are only useful to keep
108 // the entries in the resulting JSON consistent. The deserializer will ignore
109 // "null" states.
110 // TODO(davidben): This can be removed when the STS and PKP states are stored
111 // independently on disk. https://crbug.com/470295
112 void PopulateEntryWithDefaults(base::DictionaryValue* host) {
113 host->Clear();
117 114
118 if (writer_.HasPendingWrite()) 115 // STS default values.
119 writer_.DoScheduledWrite(); 116 host->SetBoolean(kStsIncludeSubdomains, false);
117 host->SetDouble(kStsObserved, 0.0);
118 host->SetDouble(kExpiry, 0.0);
119 host->SetString(kMode, kDefault);
120 120
121 transport_security_state_->SetDelegate(NULL); 121 // PKP default values.
122 host->SetBoolean(kPkpIncludeSubdomains, false);
123 host->SetDouble(kPkpObserved, 0.0);
124 host->SetDouble(kDynamicSPKIHashesExpiry, 0.0);
122 } 125 }
123 126
124 void TransportSecurityPersister::StateIsDirty( 127 // Serializes STS data from |state| into |toplevel|. Any existing state in
125 TransportSecurityState* state) { 128 // |toplevel| for each item is overwritten.
126 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); 129 void SerializeSTSData(TransportSecurityState* state,
127 DCHECK_EQ(transport_security_state_, state); 130 base::DictionaryValue* toplevel) {
128 131 TransportSecurityState::STSStateIterator sts_iterator(*state);
129 if (!readonly_)
130 writer_.ScheduleWrite(this);
131 }
132
133 bool TransportSecurityPersister::SerializeData(std::string* output) {
134 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
135
136 base::DictionaryValue toplevel;
137 base::Time now = base::Time::Now();
138
139 // TODO(davidben): Fix the serialization format by splitting the on-disk
140 // representation of the STS and PKP states. https://crbug.com/470295.
141 TransportSecurityState::STSStateIterator sts_iterator(
142 *transport_security_state_);
143 for (; sts_iterator.HasNext(); sts_iterator.Advance()) { 132 for (; sts_iterator.HasNext(); sts_iterator.Advance()) {
144 const std::string& hostname = sts_iterator.hostname(); 133 const std::string& hostname = sts_iterator.hostname();
145 const TransportSecurityState::STSState& sts_state = 134 const TransportSecurityState::STSState& sts_state =
146 sts_iterator.domain_state(); 135 sts_iterator.domain_state();
147 136
148 const std::string key = HashedDomainToExternalString(hostname); 137 const std::string key = HashedDomainToExternalString(hostname);
149 std::unique_ptr<base::DictionaryValue> serialized( 138 std::unique_ptr<base::DictionaryValue> serialized(
150 new base::DictionaryValue); 139 new base::DictionaryValue);
151 PopulateEntryWithDefaults(serialized.get()); 140 PopulateEntryWithDefaults(serialized.get());
152 141
153 serialized->SetBoolean(kStsIncludeSubdomains, sts_state.include_subdomains); 142 serialized->SetBoolean(kStsIncludeSubdomains, sts_state.include_subdomains);
154 serialized->SetDouble(kStsObserved, sts_state.last_observed.ToDoubleT()); 143 serialized->SetDouble(kStsObserved, sts_state.last_observed.ToDoubleT());
155 serialized->SetDouble(kExpiry, sts_state.expiry.ToDoubleT()); 144 serialized->SetDouble(kExpiry, sts_state.expiry.ToDoubleT());
156 145
157 switch (sts_state.upgrade_mode) { 146 switch (sts_state.upgrade_mode) {
158 case TransportSecurityState::STSState::MODE_FORCE_HTTPS: 147 case TransportSecurityState::STSState::MODE_FORCE_HTTPS:
159 serialized->SetString(kMode, kForceHTTPS); 148 serialized->SetString(kMode, kForceHTTPS);
160 break; 149 break;
161 case TransportSecurityState::STSState::MODE_DEFAULT: 150 case TransportSecurityState::STSState::MODE_DEFAULT:
162 serialized->SetString(kMode, kDefault); 151 serialized->SetString(kMode, kDefault);
163 break; 152 break;
164 default: 153 default:
165 NOTREACHED() << "STSState with unknown mode"; 154 NOTREACHED() << "STSState with unknown mode";
166 continue; 155 continue;
167 } 156 }
168 157
169 toplevel.Set(key, std::move(serialized)); 158 toplevel->Set(key, std::move(serialized));
170 } 159 }
160 }
171 161
172 TransportSecurityState::PKPStateIterator pkp_iterator( 162 // Serializes PKP data from |state| into |toplevel|. For each PKP item in
173 *transport_security_state_); 163 // |state|, if |toplevel| already contains an item for that hostname, the item
164 // is updated with the PKP data.
165 void SerializePKPData(TransportSecurityState* state,
166 base::DictionaryValue* toplevel) {
167 base::Time now = base::Time::Now();
168 TransportSecurityState::PKPStateIterator pkp_iterator(*state);
174 for (; pkp_iterator.HasNext(); pkp_iterator.Advance()) { 169 for (; pkp_iterator.HasNext(); pkp_iterator.Advance()) {
175 const std::string& hostname = pkp_iterator.hostname(); 170 const std::string& hostname = pkp_iterator.hostname();
176 const TransportSecurityState::PKPState& pkp_state = 171 const TransportSecurityState::PKPState& pkp_state =
177 pkp_iterator.domain_state(); 172 pkp_iterator.domain_state();
178 173
179 // See if the current |hostname| already has STS state and, if so, update 174 // See if the current |hostname| already has STS state and, if so, update
180 // that entry. 175 // that entry.
181 const std::string key = HashedDomainToExternalString(hostname); 176 const std::string key = HashedDomainToExternalString(hostname);
182 base::DictionaryValue* serialized = nullptr; 177 base::DictionaryValue* serialized = nullptr;
183 if (!toplevel.GetDictionary(key, &serialized)) { 178 if (!toplevel->GetDictionary(key, &serialized)) {
184 std::unique_ptr<base::DictionaryValue> serialized_scoped( 179 std::unique_ptr<base::DictionaryValue> serialized_scoped(
185 new base::DictionaryValue); 180 new base::DictionaryValue);
186 serialized = serialized_scoped.get(); 181 serialized = serialized_scoped.get();
187 PopulateEntryWithDefaults(serialized); 182 PopulateEntryWithDefaults(serialized);
188 toplevel.Set(key, std::move(serialized_scoped)); 183 toplevel->Set(key, std::move(serialized_scoped));
189 } 184 }
190 185
191 serialized->SetBoolean(kPkpIncludeSubdomains, pkp_state.include_subdomains); 186 serialized->SetBoolean(kPkpIncludeSubdomains, pkp_state.include_subdomains);
192 serialized->SetDouble(kPkpObserved, pkp_state.last_observed.ToDoubleT()); 187 serialized->SetDouble(kPkpObserved, pkp_state.last_observed.ToDoubleT());
193 serialized->SetDouble(kDynamicSPKIHashesExpiry, 188 serialized->SetDouble(kDynamicSPKIHashesExpiry,
194 pkp_state.expiry.ToDoubleT()); 189 pkp_state.expiry.ToDoubleT());
195 190
196 // TODO(svaldez): Historically, both SHA-1 and SHA-256 hashes were 191 // TODO(svaldez): Historically, both SHA-1 and SHA-256 hashes were
197 // accepted in pins. Per spec, only SHA-256 is accepted now, however 192 // accepted in pins. Per spec, only SHA-256 is accepted now, however
198 // existing serialized pins are still processed. Migrate historical pins 193 // existing serialized pins are still processed. Migrate historical pins
199 // with SHA-1 hashes properly, either by dropping just the bad hashes or 194 // with SHA-1 hashes properly, either by dropping just the bad hashes or
200 // the entire pin. See https://crbug.com/448501. 195 // the entire pin. See https://crbug.com/448501.
201 if (now < pkp_state.expiry) { 196 if (now < pkp_state.expiry) {
202 serialized->Set(kDynamicSPKIHashes, 197 serialized->Set(kDynamicSPKIHashes,
203 SPKIHashesToListValue(pkp_state.spki_hashes)); 198 SPKIHashesToListValue(pkp_state.spki_hashes));
204 } 199 }
205 200
206 serialized->SetString(kReportUri, pkp_state.report_uri.spec()); 201 serialized->SetString(kReportUri, pkp_state.report_uri.spec());
207 } 202 }
203 }
204
205 // Serializes Expect-CT data from |state| into |toplevel|. For each Expect-CT
206 // item in |state|, if |toplevel| already contains an item for that hostname,
207 // the item is updated to include a subdictionary with key
208 // |kExpectCTSubdictionary|; otherwise an item is created for that hostname with
209 // a |kExpectCTSubdictionary| subdictionary.
210 void SerializeExpectCTData(TransportSecurityState* state,
211 base::DictionaryValue* toplevel) {
212 if (!IsDynamicExpectCTEnabled())
213 return;
214 TransportSecurityState::ExpectCTStateIterator expect_ct_iterator(*state);
215 for (; expect_ct_iterator.HasNext(); expect_ct_iterator.Advance()) {
216 const std::string& hostname = expect_ct_iterator.hostname();
217 const TransportSecurityState::ExpectCTState& expect_ct_state =
218 expect_ct_iterator.domain_state();
219
220 // See if the current |hostname| already has STS/PKP state and, if so,
221 // update that entry.
222 const std::string key = HashedDomainToExternalString(hostname);
223 base::DictionaryValue* serialized = nullptr;
224 if (!toplevel->GetDictionary(key, &serialized)) {
225 std::unique_ptr<base::DictionaryValue> serialized_scoped(
226 new base::DictionaryValue);
227 serialized = serialized_scoped.get();
228 PopulateEntryWithDefaults(serialized);
229 toplevel->Set(key, std::move(serialized_scoped));
230 }
231
232 std::unique_ptr<base::DictionaryValue> expect_ct_subdictionary(
233 new base::DictionaryValue());
234 expect_ct_subdictionary->SetDouble(
235 kExpectCTObserved, expect_ct_state.last_observed.ToDoubleT());
236 expect_ct_subdictionary->SetDouble(kExpectCTExpiry,
237 expect_ct_state.expiry.ToDoubleT());
238 expect_ct_subdictionary->SetBoolean(kExpectCTEnforce,
239 expect_ct_state.enforce);
240 expect_ct_subdictionary->SetString(kExpectCTReportUri,
241 expect_ct_state.report_uri.spec());
242 serialized->Set(kExpectCTSubdictionary, std::move(expect_ct_subdictionary));
243 }
244 }
245
246 // Populates |state| with the values in the |kExpectCTSubdictionary|
247 // subdictionary in |parsed|. Returns false if |parsed| is malformed
248 // (e.g. missing a required Expect-CT key) and true otherwise. Note that true
249 // does not necessarily mean that Expect-CT state was present in |parsed|.
250 bool DeserializeExpectCTState(const base::DictionaryValue* parsed,
251 TransportSecurityState::ExpectCTState* state) {
252 const base::DictionaryValue* expect_ct_subdictionary;
253 if (!parsed->GetDictionary(kExpectCTSubdictionary,
254 &expect_ct_subdictionary)) {
255 // Expect-CT data is not required, so this item is not malformed.
256 return true;
257 }
258 double observed;
259 bool has_observed =
260 expect_ct_subdictionary->GetDouble(kExpectCTObserved, &observed);
261 double expiry;
262 bool has_expiry =
263 expect_ct_subdictionary->GetDouble(kExpectCTExpiry, &expiry);
264 bool enforce;
265 bool has_enforce =
266 expect_ct_subdictionary->GetBoolean(kExpectCTEnforce, &enforce);
267 std::string report_uri_str;
268 bool has_report_uri =
269 expect_ct_subdictionary->GetString(kExpectCTReportUri, &report_uri_str);
270
271 // If an Expect-CT subdictionary is present, it must have the required keys.
272 if (!has_observed || !has_expiry || !has_enforce)
273 return false;
274
275 state->last_observed = base::Time::FromDoubleT(observed);
276 state->expiry = base::Time::FromDoubleT(expiry);
277 state->enforce = enforce;
278 if (has_report_uri) {
279 GURL report_uri(report_uri_str);
280 if (report_uri.is_valid())
281 state->report_uri = report_uri;
282 }
283 return true;
284 }
285
286 } // namespace
287
288 TransportSecurityPersister::TransportSecurityPersister(
289 TransportSecurityState* state,
290 const base::FilePath& profile_path,
291 const scoped_refptr<base::SequencedTaskRunner>& background_runner,
292 bool readonly)
293 : transport_security_state_(state),
294 writer_(profile_path.AppendASCII("TransportSecurity"), background_runner),
295 foreground_runner_(base::ThreadTaskRunnerHandle::Get()),
296 background_runner_(background_runner),
297 readonly_(readonly),
298 weak_ptr_factory_(this) {
299 transport_security_state_->SetDelegate(this);
300
301 base::PostTaskAndReplyWithResult(
302 background_runner_.get(), FROM_HERE,
303 base::Bind(&LoadState, writer_.path()),
304 base::Bind(&TransportSecurityPersister::CompleteLoad,
305 weak_ptr_factory_.GetWeakPtr()));
306 }
307
308 TransportSecurityPersister::~TransportSecurityPersister() {
309 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
310
311 if (writer_.HasPendingWrite())
312 writer_.DoScheduledWrite();
313
314 transport_security_state_->SetDelegate(NULL);
315 }
316
317 void TransportSecurityPersister::StateIsDirty(TransportSecurityState* state) {
318 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
319 DCHECK_EQ(transport_security_state_, state);
320
321 if (!readonly_)
322 writer_.ScheduleWrite(this);
323 }
324
325 bool TransportSecurityPersister::SerializeData(std::string* output) {
326 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
327
328 base::DictionaryValue toplevel;
329
330 // TODO(davidben): Fix the serialization format by splitting the on-disk
331 // representation of the STS and PKP states. https://crbug.com/470295.
332 SerializeSTSData(transport_security_state_, &toplevel);
333 SerializePKPData(transport_security_state_, &toplevel);
334 SerializeExpectCTData(transport_security_state_, &toplevel);
208 335
209 base::JSONWriter::WriteWithOptions( 336 base::JSONWriter::WriteWithOptions(
210 toplevel, base::JSONWriter::OPTIONS_PRETTY_PRINT, output); 337 toplevel, base::JSONWriter::OPTIONS_PRETTY_PRINT, output);
211 return true; 338 return true;
212 } 339 }
213 340
214 bool TransportSecurityPersister::LoadEntries(const std::string& serialized, 341 bool TransportSecurityPersister::LoadEntries(const std::string& serialized,
215 bool* dirty) { 342 bool* dirty) {
216 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); 343 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
217 344
(...skipping 16 matching lines...) Expand all
234 for (base::DictionaryValue::Iterator i(*dict_value); 361 for (base::DictionaryValue::Iterator i(*dict_value);
235 !i.IsAtEnd(); i.Advance()) { 362 !i.IsAtEnd(); i.Advance()) {
236 const base::DictionaryValue* parsed = NULL; 363 const base::DictionaryValue* parsed = NULL;
237 if (!i.value().GetAsDictionary(&parsed)) { 364 if (!i.value().GetAsDictionary(&parsed)) {
238 LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry"; 365 LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry";
239 continue; 366 continue;
240 } 367 }
241 368
242 TransportSecurityState::STSState sts_state; 369 TransportSecurityState::STSState sts_state;
243 TransportSecurityState::PKPState pkp_state; 370 TransportSecurityState::PKPState pkp_state;
371 TransportSecurityState::ExpectCTState expect_ct_state;
244 372
245 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and 373 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and
246 // kPkpIncludeSubdomains. Parse at least one of these properties, 374 // kPkpIncludeSubdomains. Parse at least one of these properties,
247 // preferably the new ones. 375 // preferably the new ones.
248 bool include_subdomains = false; 376 bool include_subdomains = false;
249 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains, 377 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains,
250 &include_subdomains); 378 &include_subdomains);
251 sts_state.include_subdomains = include_subdomains; 379 sts_state.include_subdomains = include_subdomains;
252 pkp_state.include_subdomains = include_subdomains; 380 pkp_state.include_subdomains = include_subdomains;
253 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { 381 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 } 444 }
317 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) { 445 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) {
318 pkp_state.last_observed = base::Time::FromDoubleT(pkp_observed); 446 pkp_state.last_observed = base::Time::FromDoubleT(pkp_observed);
319 } else if (parsed->GetDouble(kCreated, &pkp_observed)) { 447 } else if (parsed->GetDouble(kCreated, &pkp_observed)) {
320 pkp_state.last_observed = base::Time::FromDoubleT(pkp_observed); 448 pkp_state.last_observed = base::Time::FromDoubleT(pkp_observed);
321 } else { 449 } else {
322 dirtied = true; 450 dirtied = true;
323 pkp_state.last_observed = base::Time::Now(); 451 pkp_state.last_observed = base::Time::Now();
324 } 452 }
325 453
454 if (!DeserializeExpectCTState(parsed, &expect_ct_state)) {
455 continue;
456 }
457
326 bool has_sts = 458 bool has_sts =
327 sts_state.expiry > current_time && sts_state.ShouldUpgradeToSSL(); 459 sts_state.expiry > current_time && sts_state.ShouldUpgradeToSSL();
328 bool has_pkp = 460 bool has_pkp =
329 pkp_state.expiry > current_time && pkp_state.HasPublicKeyPins(); 461 pkp_state.expiry > current_time && pkp_state.HasPublicKeyPins();
330 if (!has_sts && !has_pkp) { 462 bool has_expect_ct =
463 expect_ct_state.expiry > current_time &&
464 (expect_ct_state.enforce || !expect_ct_state.report_uri.is_empty());
465 if (!has_sts && !has_pkp && !has_expect_ct) {
331 // Make sure we dirty the state if we drop an entry. The entries can only 466 // Make sure we dirty the state if we drop an entry. The entries can only
332 // be dropped when both the STS and PKP states are expired or invalid. 467 // be dropped when all the STS, PKP, and Expect-CT states are expired or
468 // invalid.
333 dirtied = true; 469 dirtied = true;
334 continue; 470 continue;
335 } 471 }
336 472
337 std::string hashed = ExternalStringToHashedDomain(i.key()); 473 std::string hashed = ExternalStringToHashedDomain(i.key());
338 if (hashed.empty()) { 474 if (hashed.empty()) {
339 dirtied = true; 475 dirtied = true;
340 continue; 476 continue;
341 } 477 }
342 478
343 // Until the on-disk storage is split, there will always be 'null' entries. 479 // Until the on-disk storage is split, there will always be 'null' entries.
344 // We only register entries that have actual state. 480 // We only register entries that have actual state.
345 if (has_sts) 481 if (has_sts)
346 state->AddOrUpdateEnabledSTSHosts(hashed, sts_state); 482 state->AddOrUpdateEnabledSTSHosts(hashed, sts_state);
347 if (has_pkp) 483 if (has_pkp)
348 state->AddOrUpdateEnabledPKPHosts(hashed, pkp_state); 484 state->AddOrUpdateEnabledPKPHosts(hashed, pkp_state);
485 if (has_expect_ct)
486 state->AddOrUpdateEnabledExpectCTHosts(hashed, expect_ct_state);
349 } 487 }
350 488
351 *dirty = dirtied; 489 *dirty = dirtied;
352 return true; 490 return true;
353 } 491 }
354 492
355 void TransportSecurityPersister::PopulateEntryWithDefaults(
356 base::DictionaryValue* host) {
357 host->Clear();
358
359 // STS default values.
360 host->SetBoolean(kStsIncludeSubdomains, false);
361 host->SetDouble(kStsObserved, 0.0);
362 host->SetDouble(kExpiry, 0.0);
363 host->SetString(kMode, kDefault);
364
365 // PKP default values.
366 host->SetBoolean(kPkpIncludeSubdomains, false);
367 host->SetDouble(kPkpObserved, 0.0);
368 host->SetDouble(kDynamicSPKIHashesExpiry, 0.0);
369 }
370
371 void TransportSecurityPersister::CompleteLoad(const std::string& state) { 493 void TransportSecurityPersister::CompleteLoad(const std::string& state) {
372 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); 494 DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
373 495
374 if (state.empty()) 496 if (state.empty())
375 return; 497 return;
376 498
377 bool dirty = false; 499 bool dirty = false;
378 if (!LoadEntries(state, &dirty)) { 500 if (!LoadEntries(state, &dirty)) {
379 LOG(ERROR) << "Failed to deserialize state: " << state; 501 LOG(ERROR) << "Failed to deserialize state: " << state;
380 return; 502 return;
381 } 503 }
382 if (dirty) 504 if (dirty)
383 StateIsDirty(transport_security_state_); 505 StateIsDirty(transport_security_state_);
384 } 506 }
385 507
386 } // namespace net 508 } // namespace net
OLDNEW
« no previous file with comments | « net/http/transport_security_persister.h ('k') | net/http/transport_security_persister_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698