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

Side by Side Diff: net/http/transport_security_persister_unittest.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
« no previous file with comments | « net/http/transport_security_persister.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <map> 7 #include <map>
8 #include <memory> 8 #include <memory>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h" 14 #include "base/files/scoped_temp_dir.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/test/scoped_feature_list.h"
17 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
18 #include "net/http/transport_security_state.h" 19 #include "net/http/transport_security_state.h"
19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
20 21
21 namespace net { 22 namespace net {
22 23
23 namespace { 24 namespace {
24 25
25 const char kReportUri[] = "http://www.example.test/report"; 26 const char kReportUri[] = "http://www.example.test/report";
26 27
(...skipping 14 matching lines...) Expand all
41 &state_, temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get(), 42 &state_, temp_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get(),
42 false)); 43 false));
43 } 44 }
44 45
45 protected: 46 protected:
46 base::ScopedTempDir temp_dir_; 47 base::ScopedTempDir temp_dir_;
47 TransportSecurityState state_; 48 TransportSecurityState state_;
48 std::unique_ptr<TransportSecurityPersister> persister_; 49 std::unique_ptr<TransportSecurityPersister> persister_;
49 }; 50 };
50 51
52 // Tests that LoadEntries() clears existing non-static entries.
53 TEST_F(TransportSecurityPersisterTest, LoadEntriesClearsExistingState) {
54 base::test::ScopedFeatureList feature_list;
55 feature_list.InitAndEnableFeature(
56 TransportSecurityState::kDynamicExpectCTFeature);
57 std::string output;
58 bool dirty;
59
60 TransportSecurityState::STSState sts_state;
61 TransportSecurityState::PKPState pkp_state;
62 TransportSecurityState::ExpectCTState expect_ct_state;
63 const base::Time current_time(base::Time::Now());
64 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
65 static const char kYahooDomain[] = "yahoo.com";
66
67 EXPECT_FALSE(state_.GetDynamicSTSState(kYahooDomain, &sts_state));
68 EXPECT_FALSE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state));
69
70 state_.AddHSTS(kYahooDomain, expiry, false /* include subdomains */);
71 HashValue spki(HASH_VALUE_SHA256);
72 memset(spki.data(), 0, spki.size());
73 HashValueVector dynamic_spki_hashes;
74 dynamic_spki_hashes.push_back(spki);
75 state_.AddHPKP(kYahooDomain, expiry, false, dynamic_spki_hashes, GURL());
76 state_.AddExpectCT(kYahooDomain, expiry, true /* enforce */, GURL());
77
78 EXPECT_TRUE(state_.GetDynamicSTSState(kYahooDomain, &sts_state));
79 EXPECT_TRUE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state));
80 EXPECT_TRUE(state_.GetDynamicExpectCTState(kYahooDomain, &expect_ct_state));
81
82 EXPECT_TRUE(persister_->LoadEntries("{}", &dirty));
83 EXPECT_FALSE(dirty);
84
85 EXPECT_FALSE(state_.GetDynamicSTSState(kYahooDomain, &sts_state));
86 EXPECT_FALSE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state));
87 EXPECT_FALSE(state_.GetDynamicExpectCTState(kYahooDomain, &expect_ct_state));
88 }
89
51 TEST_F(TransportSecurityPersisterTest, SerializeData1) { 90 TEST_F(TransportSecurityPersisterTest, SerializeData1) {
52 std::string output; 91 std::string output;
53 bool dirty; 92 bool dirty;
54 93
55 EXPECT_TRUE(persister_->SerializeData(&output)); 94 EXPECT_TRUE(persister_->SerializeData(&output));
56 EXPECT_TRUE(persister_->LoadEntries(output, &dirty)); 95 EXPECT_TRUE(persister_->LoadEntries(output, &dirty));
57 EXPECT_FALSE(dirty); 96 EXPECT_FALSE(dirty);
58 } 97 }
59 98
60 TEST_F(TransportSecurityPersisterTest, SerializeData2) { 99 TEST_F(TransportSecurityPersisterTest, SerializeData2) {
(...skipping 25 matching lines...) Expand all
86 EXPECT_TRUE(state_.GetDynamicSTSState("foo.bar.yahoo.com", &sts_state)); 125 EXPECT_TRUE(state_.GetDynamicSTSState("foo.bar.yahoo.com", &sts_state));
87 EXPECT_EQ(sts_state.upgrade_mode, 126 EXPECT_EQ(sts_state.upgrade_mode,
88 TransportSecurityState::STSState::MODE_FORCE_HTTPS); 127 TransportSecurityState::STSState::MODE_FORCE_HTTPS);
89 EXPECT_TRUE(state_.GetDynamicSTSState("foo.bar.baz.yahoo.com", &sts_state)); 128 EXPECT_TRUE(state_.GetDynamicSTSState("foo.bar.baz.yahoo.com", &sts_state));
90 EXPECT_EQ(sts_state.upgrade_mode, 129 EXPECT_EQ(sts_state.upgrade_mode,
91 TransportSecurityState::STSState::MODE_FORCE_HTTPS); 130 TransportSecurityState::STSState::MODE_FORCE_HTTPS);
92 EXPECT_FALSE(state_.GetStaticDomainState("com", &sts_state, &pkp_state)); 131 EXPECT_FALSE(state_.GetStaticDomainState("com", &sts_state, &pkp_state));
93 } 132 }
94 133
95 TEST_F(TransportSecurityPersisterTest, SerializeData3) { 134 TEST_F(TransportSecurityPersisterTest, SerializeData3) {
135 base::test::ScopedFeatureList feature_list;
136 feature_list.InitAndEnableFeature(
137 TransportSecurityState::kDynamicExpectCTFeature);
96 const GURL report_uri(kReportUri); 138 const GURL report_uri(kReportUri);
97 // Add an entry. 139 // Add an entry.
98 HashValue fp1(HASH_VALUE_SHA256); 140 HashValue fp1(HASH_VALUE_SHA256);
99 memset(fp1.data(), 0, fp1.size()); 141 memset(fp1.data(), 0, fp1.size());
100 HashValue fp2(HASH_VALUE_SHA256); 142 HashValue fp2(HASH_VALUE_SHA256);
101 memset(fp2.data(), 1, fp2.size()); 143 memset(fp2.data(), 1, fp2.size());
102 base::Time expiry = 144 base::Time expiry =
103 base::Time::Now() + base::TimeDelta::FromSeconds(1000); 145 base::Time::Now() + base::TimeDelta::FromSeconds(1000);
104 HashValueVector dynamic_spki_hashes; 146 HashValueVector dynamic_spki_hashes;
105 dynamic_spki_hashes.push_back(fp1); 147 dynamic_spki_hashes.push_back(fp1);
106 dynamic_spki_hashes.push_back(fp2); 148 dynamic_spki_hashes.push_back(fp2);
107 bool include_subdomains = false; 149 bool include_subdomains = false;
108 state_.AddHSTS("www.example.com", expiry, include_subdomains); 150 state_.AddHSTS("www.example.com", expiry, include_subdomains);
109 state_.AddHPKP("www.example.com", expiry, include_subdomains, 151 state_.AddHPKP("www.example.com", expiry, include_subdomains,
110 dynamic_spki_hashes, report_uri); 152 dynamic_spki_hashes, report_uri);
153 state_.AddExpectCT("www.example.com", expiry, true /* enforce */, GURL());
111 154
112 // Add another entry. 155 // Add another entry.
113 memset(fp1.data(), 2, fp1.size()); 156 memset(fp1.data(), 2, fp1.size());
114 memset(fp2.data(), 3, fp2.size()); 157 memset(fp2.data(), 3, fp2.size());
115 expiry = 158 expiry =
116 base::Time::Now() + base::TimeDelta::FromSeconds(3000); 159 base::Time::Now() + base::TimeDelta::FromSeconds(3000);
117 dynamic_spki_hashes.push_back(fp1); 160 dynamic_spki_hashes.push_back(fp1);
118 dynamic_spki_hashes.push_back(fp2); 161 dynamic_spki_hashes.push_back(fp2);
119 state_.AddHSTS("www.example.net", expiry, include_subdomains); 162 state_.AddHSTS("www.example.net", expiry, include_subdomains);
120 state_.AddHPKP("www.example.net", expiry, include_subdomains, 163 state_.AddHPKP("www.example.net", expiry, include_subdomains,
121 dynamic_spki_hashes, report_uri); 164 dynamic_spki_hashes, report_uri);
165 state_.AddExpectCT("www.example.net", expiry, false /* enforce */,
166 report_uri);
122 167
123 // Save a copy of everything. 168 // Save a copy of everything.
124 std::set<std::string> sts_saved; 169 std::set<std::string> sts_saved;
125 TransportSecurityState::STSStateIterator sts_iter(state_); 170 TransportSecurityState::STSStateIterator sts_iter(state_);
126 while (sts_iter.HasNext()) { 171 while (sts_iter.HasNext()) {
127 sts_saved.insert(sts_iter.hostname()); 172 sts_saved.insert(sts_iter.hostname());
128 sts_iter.Advance(); 173 sts_iter.Advance();
129 } 174 }
130 175
131 std::set<std::string> pkp_saved; 176 std::set<std::string> pkp_saved;
132 TransportSecurityState::PKPStateIterator pkp_iter(state_); 177 TransportSecurityState::PKPStateIterator pkp_iter(state_);
133 while (pkp_iter.HasNext()) { 178 while (pkp_iter.HasNext()) {
134 pkp_saved.insert(pkp_iter.hostname()); 179 pkp_saved.insert(pkp_iter.hostname());
135 pkp_iter.Advance(); 180 pkp_iter.Advance();
136 } 181 }
137 182
183 std::set<std::string> expect_ct_saved;
184 TransportSecurityState::ExpectCTStateIterator expect_ct_iter(state_);
185 while (expect_ct_iter.HasNext()) {
186 expect_ct_saved.insert(expect_ct_iter.hostname());
187 expect_ct_iter.Advance();
188 }
189
138 std::string serialized; 190 std::string serialized;
139 EXPECT_TRUE(persister_->SerializeData(&serialized)); 191 EXPECT_TRUE(persister_->SerializeData(&serialized));
140 192
141 // Persist the data to the file. For the test to be fast and not flaky, we 193 // Persist the data to the file. For the test to be fast and not flaky, we
142 // just do it directly rather than call persister_->StateIsDirty. (That uses 194 // just do it directly rather than call persister_->StateIsDirty. (That uses
143 // ImportantFileWriter, which has an asynchronous commit interval rather 195 // ImportantFileWriter, which has an asynchronous commit interval rather
144 // than block.) Use a different basename just for cleanliness. 196 // than block.) Use a different basename just for cleanliness.
145 base::FilePath path = 197 base::FilePath path =
146 temp_dir_.GetPath().AppendASCII("TransportSecurityPersisterTest"); 198 temp_dir_.GetPath().AppendASCII("TransportSecurityPersisterTest");
147 EXPECT_EQ(static_cast<int>(serialized.size()), 199 EXPECT_EQ(static_cast<int>(serialized.size()),
(...skipping 16 matching lines...) Expand all
164 } 216 }
165 EXPECT_EQ(count, sts_saved.size()); 217 EXPECT_EQ(count, sts_saved.size());
166 218
167 count = 0; 219 count = 0;
168 TransportSecurityState::PKPStateIterator pkp_iter2(state_); 220 TransportSecurityState::PKPStateIterator pkp_iter2(state_);
169 while (pkp_iter2.HasNext()) { 221 while (pkp_iter2.HasNext()) {
170 count++; 222 count++;
171 pkp_iter2.Advance(); 223 pkp_iter2.Advance();
172 } 224 }
173 EXPECT_EQ(count, pkp_saved.size()); 225 EXPECT_EQ(count, pkp_saved.size());
226
227 count = 0;
228 TransportSecurityState::ExpectCTStateIterator expect_ct_iter2(state_);
229 while (expect_ct_iter2.HasNext()) {
230 count++;
231 expect_ct_iter2.Advance();
232 }
233 EXPECT_EQ(count, expect_ct_saved.size());
174 } 234 }
175 235
176 TEST_F(TransportSecurityPersisterTest, SerializeDataOld) { 236 TEST_F(TransportSecurityPersisterTest, SerializeDataOld) {
177 // This is an old-style piece of transport state JSON, which has no creation 237 // This is an old-style piece of transport state JSON, which has no creation
178 // date. 238 // date.
179 std::string output = 239 std::string output =
180 "{ " 240 "{ "
181 "\"NiyD+3J1r6z1wjl2n1ALBu94Zj9OsEAMo0kCN8js0Uk=\": {" 241 "\"NiyD+3J1r6z1wjl2n1ALBu94Zj9OsEAMo0kCN8js0Uk=\": {"
182 "\"expiry\": 1266815027.983453, " 242 "\"expiry\": 1266815027.983453, "
183 "\"include_subdomains\": false, " 243 "\"include_subdomains\": false, "
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 284
225 TransportSecurityState::PKPState new_pkp_state; 285 TransportSecurityState::PKPState new_pkp_state;
226 EXPECT_TRUE(state_.GetDynamicPKPState(kTestDomain, &new_pkp_state)); 286 EXPECT_TRUE(state_.GetDynamicPKPState(kTestDomain, &new_pkp_state));
227 EXPECT_EQ(1u, new_pkp_state.spki_hashes.size()); 287 EXPECT_EQ(1u, new_pkp_state.spki_hashes.size());
228 EXPECT_EQ(sha256.tag, new_pkp_state.spki_hashes[0].tag); 288 EXPECT_EQ(sha256.tag, new_pkp_state.spki_hashes[0].tag);
229 EXPECT_EQ(0, memcmp(new_pkp_state.spki_hashes[0].data(), sha256.data(), 289 EXPECT_EQ(0, memcmp(new_pkp_state.spki_hashes[0].data(), sha256.data(),
230 sha256.size())); 290 sha256.size()));
231 EXPECT_EQ(report_uri, new_pkp_state.report_uri); 291 EXPECT_EQ(report_uri, new_pkp_state.report_uri);
232 } 292 }
233 293
294 // Tests that dynamic Expect-CT state is serialized and deserialized correctly.
295 TEST_F(TransportSecurityPersisterTest, ExpectCT) {
296 base::test::ScopedFeatureList feature_list;
297 feature_list.InitAndEnableFeature(
298 TransportSecurityState::kDynamicExpectCTFeature);
299 const GURL report_uri(kReportUri);
300 TransportSecurityState::ExpectCTState expect_ct_state;
301 static const char kTestDomain[] = "example.test";
302
303 EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state));
304
305 const base::Time current_time(base::Time::Now());
306 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
307 state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL());
308 std::string serialized;
309 EXPECT_TRUE(persister_->SerializeData(&serialized));
310 bool dirty;
311 // LoadEntries() clears existing dynamic data before loading entries from
312 // |serialized|.
313 EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty));
314
315 TransportSecurityState::ExpectCTState new_expect_ct_state;
316 EXPECT_TRUE(
317 state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state));
318 EXPECT_TRUE(new_expect_ct_state.enforce);
319 EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
320 EXPECT_EQ(expiry, new_expect_ct_state.expiry);
321
322 // Update the state for the domain and check that it is
323 // serialized/deserialized correctly.
324 state_.AddExpectCT(kTestDomain, expiry, false /* enforce */, report_uri);
325 EXPECT_TRUE(persister_->SerializeData(&serialized));
326 EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty));
327 EXPECT_TRUE(
328 state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state));
329 EXPECT_FALSE(new_expect_ct_state.enforce);
330 EXPECT_EQ(report_uri, new_expect_ct_state.report_uri);
331 EXPECT_EQ(expiry, new_expect_ct_state.expiry);
332 }
333
334 // Tests that dynamic Expect-CT state is serialized and deserialized correctly
335 // when there is also PKP and STS data present.
336 TEST_F(TransportSecurityPersisterTest, ExpectCTWithSTSAndPKPDataPresent) {
337 base::test::ScopedFeatureList feature_list;
338 feature_list.InitAndEnableFeature(
339 TransportSecurityState::kDynamicExpectCTFeature);
340 const GURL report_uri(kReportUri);
341 TransportSecurityState::ExpectCTState expect_ct_state;
342 static const char kTestDomain[] = "example.test";
343
344 EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state));
345
346 const base::Time current_time(base::Time::Now());
347 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
348 state_.AddHSTS(kTestDomain, expiry, false /* include subdomains */);
349 state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL());
350 HashValue spki_hash(HASH_VALUE_SHA256);
351 memset(spki_hash.data(), 0, spki_hash.size());
352 HashValueVector dynamic_spki_hashes;
353 dynamic_spki_hashes.push_back(spki_hash);
354 state_.AddHPKP(kTestDomain, expiry, false /* include subdomains */,
355 dynamic_spki_hashes, GURL());
356
357 std::string serialized;
358 EXPECT_TRUE(persister_->SerializeData(&serialized));
359 bool dirty;
360 // LoadEntries() clears existing dynamic data before loading entries from
361 // |serialized|.
362 EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty));
363
364 TransportSecurityState::ExpectCTState new_expect_ct_state;
365 EXPECT_TRUE(
366 state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state));
367 EXPECT_TRUE(new_expect_ct_state.enforce);
368 EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
369 EXPECT_EQ(expiry, new_expect_ct_state.expiry);
370 // Check that STS and PKP state are loaded properly as well.
371 TransportSecurityState::STSState sts_state;
372 EXPECT_TRUE(state_.GetDynamicSTSState(kTestDomain, &sts_state));
373 EXPECT_EQ(sts_state.upgrade_mode,
374 TransportSecurityState::STSState::MODE_FORCE_HTTPS);
375 TransportSecurityState::PKPState pkp_state;
376 EXPECT_TRUE(state_.GetDynamicPKPState(kTestDomain, &pkp_state));
377 EXPECT_EQ(1u, pkp_state.spki_hashes.size());
378 EXPECT_EQ(0, memcmp(pkp_state.spki_hashes[0].data(), spki_hash.data(),
379 spki_hash.size()));
380 }
381
382 // Tests that Expect-CT state is not serialized and persisted when the feature
383 // is disabled.
384 TEST_F(TransportSecurityPersisterTest, ExpectCTDisabled) {
385 base::test::ScopedFeatureList feature_list;
386 feature_list.InitAndDisableFeature(
387 TransportSecurityState::kDynamicExpectCTFeature);
388 const GURL report_uri(kReportUri);
389 TransportSecurityState::ExpectCTState expect_ct_state;
390 static const char kTestDomain[] = "example.test";
391
392 EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state));
393
394 const base::Time current_time(base::Time::Now());
395 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
396 state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL());
397 std::string serialized;
398 EXPECT_TRUE(persister_->SerializeData(&serialized));
399 bool dirty;
400 EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty));
401
402 TransportSecurityState::ExpectCTState new_expect_ct_state;
403 EXPECT_FALSE(
404 state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state));
405 }
406
234 } // namespace 407 } // namespace
235 408
236 } // namespace net 409 } // namespace net
OLDNEW
« no previous file with comments | « net/http/transport_security_persister.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698