transport_security_persister_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  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. #include "net/http/transport_security_persister.h"
  5. #include <map>
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "base/files/file_path.h"
  10. #include "base/files/file_util.h"
  11. #include "base/files/scoped_temp_dir.h"
  12. #include "base/json/json_writer.h"
  13. #include "base/run_loop.h"
  14. #include "base/strings/string_util.h"
  15. #include "base/task/current_thread.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/test/scoped_feature_list.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "net/base/features.h"
  20. #include "net/base/network_isolation_key.h"
  21. #include "net/base/schemeful_site.h"
  22. #include "net/http/transport_security_state.h"
  23. #include "net/test/test_with_task_environment.h"
  24. #include "testing/gtest/include/gtest/gtest.h"
  25. #include "url/gurl.h"
  26. namespace net {
  27. namespace {
  28. const char kReportUri[] = "http://www.example.test/report";
  29. // The bool indicates whether kPartitionExpectCTStateByNetworkIsolationKey
  30. // should be enabled.
  31. class TransportSecurityPersisterTest : public ::testing::TestWithParam<bool>,
  32. public WithTaskEnvironment {
  33. public:
  34. TransportSecurityPersisterTest()
  35. : WithTaskEnvironment(
  36. base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
  37. // This feature is used in initializing |state_|.
  38. if (partition_expect_ct_state()) {
  39. feature_list_.InitAndEnableFeature(
  40. features::kPartitionExpectCTStateByNetworkIsolationKey);
  41. } else {
  42. feature_list_.InitAndDisableFeature(
  43. features::kPartitionExpectCTStateByNetworkIsolationKey);
  44. }
  45. // Mock out time so that entries with hard-coded json data can be
  46. // successfully loaded. Use a large enough value that dynamically created
  47. // entries have at least somewhat interesting expiration times.
  48. FastForwardBy(base::Days(3660));
  49. }
  50. ~TransportSecurityPersisterTest() override {
  51. EXPECT_TRUE(base::CurrentIOThread::IsSet());
  52. base::RunLoop().RunUntilIdle();
  53. }
  54. void SetUp() override {
  55. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  56. transport_security_file_path_ =
  57. temp_dir_.GetPath().AppendASCII("TransportSecurity");
  58. ASSERT_TRUE(base::CurrentIOThread::IsSet());
  59. scoped_refptr<base::SequencedTaskRunner> background_runner(
  60. base::ThreadPool::CreateSequencedTaskRunner(
  61. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  62. base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
  63. state_ = std::make_unique<TransportSecurityState>();
  64. persister_ = std::make_unique<TransportSecurityPersister>(
  65. state_.get(), std::move(background_runner),
  66. transport_security_file_path_);
  67. }
  68. bool partition_expect_ct_state() const { return GetParam(); }
  69. protected:
  70. base::FilePath transport_security_file_path_;
  71. base::ScopedTempDir temp_dir_;
  72. base::test::ScopedFeatureList feature_list_;
  73. std::unique_ptr<TransportSecurityState> state_;
  74. std::unique_ptr<TransportSecurityPersister> persister_;
  75. };
  76. INSTANTIATE_TEST_SUITE_P(All, TransportSecurityPersisterTest, testing::Bool());
  77. // Tests that LoadEntries() clears existing non-static entries.
  78. TEST_P(TransportSecurityPersisterTest, LoadEntriesClearsExistingState) {
  79. base::test::ScopedFeatureList feature_list;
  80. feature_list.InitAndEnableFeature(
  81. TransportSecurityState::kDynamicExpectCTFeature);
  82. TransportSecurityState::STSState sts_state;
  83. TransportSecurityState::ExpectCTState expect_ct_state;
  84. const base::Time current_time(base::Time::Now());
  85. const base::Time expiry = current_time + base::Seconds(1000);
  86. static const char kYahooDomain[] = "yahoo.com";
  87. EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
  88. state_->AddHSTS(kYahooDomain, expiry, false /* include subdomains */);
  89. state_->AddExpectCT(kYahooDomain, expiry, true /* enforce */, GURL(),
  90. NetworkIsolationKey());
  91. EXPECT_TRUE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
  92. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  93. kYahooDomain, NetworkIsolationKey(), &expect_ct_state));
  94. persister_->LoadEntries("{\"version\":2}");
  95. EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
  96. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  97. kYahooDomain, NetworkIsolationKey(), &expect_ct_state));
  98. }
  99. // Tests that serializing -> deserializing -> reserializing results in the same
  100. // output.
  101. TEST_P(TransportSecurityPersisterTest, SerializeData1) {
  102. std::string output;
  103. EXPECT_TRUE(persister_->SerializeData(&output));
  104. persister_->LoadEntries(output);
  105. std::string output2;
  106. EXPECT_TRUE(persister_->SerializeData(&output2));
  107. EXPECT_EQ(output, output2);
  108. }
  109. TEST_P(TransportSecurityPersisterTest, SerializeData2) {
  110. TransportSecurityState::STSState sts_state;
  111. const base::Time current_time(base::Time::Now());
  112. const base::Time expiry = current_time + base::Seconds(1000);
  113. static const char kYahooDomain[] = "yahoo.com";
  114. EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
  115. bool include_subdomains = true;
  116. state_->AddHSTS(kYahooDomain, expiry, include_subdomains);
  117. std::string output;
  118. EXPECT_TRUE(persister_->SerializeData(&output));
  119. persister_->LoadEntries(output);
  120. EXPECT_TRUE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
  121. EXPECT_EQ(sts_state.upgrade_mode,
  122. TransportSecurityState::STSState::MODE_FORCE_HTTPS);
  123. EXPECT_TRUE(state_->GetDynamicSTSState("foo.yahoo.com", &sts_state));
  124. EXPECT_EQ(sts_state.upgrade_mode,
  125. TransportSecurityState::STSState::MODE_FORCE_HTTPS);
  126. EXPECT_TRUE(state_->GetDynamicSTSState("foo.bar.yahoo.com", &sts_state));
  127. EXPECT_EQ(sts_state.upgrade_mode,
  128. TransportSecurityState::STSState::MODE_FORCE_HTTPS);
  129. EXPECT_TRUE(state_->GetDynamicSTSState("foo.bar.baz.yahoo.com", &sts_state));
  130. EXPECT_EQ(sts_state.upgrade_mode,
  131. TransportSecurityState::STSState::MODE_FORCE_HTTPS);
  132. }
  133. TEST_P(TransportSecurityPersisterTest, SerializeData3) {
  134. base::test::ScopedFeatureList feature_list;
  135. feature_list.InitAndEnableFeature(
  136. TransportSecurityState::kDynamicExpectCTFeature);
  137. const GURL report_uri(kReportUri);
  138. // Add an entry.
  139. base::Time expiry = base::Time::Now() + base::Seconds(1000);
  140. bool include_subdomains = false;
  141. state_->AddHSTS("www.example.com", expiry, include_subdomains);
  142. state_->AddExpectCT("www.example.com", expiry, true /* enforce */, GURL(),
  143. NetworkIsolationKey());
  144. // Add another entry.
  145. expiry = base::Time::Now() + base::Seconds(3000);
  146. state_->AddHSTS("www.example.net", expiry, include_subdomains);
  147. state_->AddExpectCT("www.example.net", expiry, false /* enforce */,
  148. report_uri, NetworkIsolationKey());
  149. // Save a copy of everything.
  150. std::set<std::string> sts_saved;
  151. TransportSecurityState::STSStateIterator sts_iter(*state_);
  152. while (sts_iter.HasNext()) {
  153. sts_saved.insert(sts_iter.hostname());
  154. sts_iter.Advance();
  155. }
  156. std::set<std::string> expect_ct_saved;
  157. TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
  158. while (expect_ct_iter.HasNext()) {
  159. expect_ct_saved.insert(expect_ct_iter.hostname());
  160. expect_ct_iter.Advance();
  161. }
  162. std::string serialized;
  163. EXPECT_TRUE(persister_->SerializeData(&serialized));
  164. // Persist the data to the file.
  165. base::RunLoop run_loop;
  166. persister_->WriteNow(state_.get(), run_loop.QuitClosure());
  167. run_loop.Run();
  168. // Read the data back.
  169. std::string persisted;
  170. EXPECT_TRUE(
  171. base::ReadFileToString(transport_security_file_path_, &persisted));
  172. EXPECT_EQ(persisted, serialized);
  173. persister_->LoadEntries(persisted);
  174. // Check that states are the same as saved.
  175. size_t count = 0;
  176. TransportSecurityState::STSStateIterator sts_iter2(*state_);
  177. while (sts_iter2.HasNext()) {
  178. count++;
  179. sts_iter2.Advance();
  180. }
  181. EXPECT_EQ(count, sts_saved.size());
  182. count = 0;
  183. TransportSecurityState::ExpectCTStateIterator expect_ct_iter2(*state_);
  184. while (expect_ct_iter2.HasNext()) {
  185. count++;
  186. expect_ct_iter2.Advance();
  187. }
  188. EXPECT_EQ(count, expect_ct_saved.size());
  189. }
  190. // Tests that deserializing bad data shouldn't result in any ExpectCT or STS
  191. // entries being added to the transport security state.
  192. TEST_P(TransportSecurityPersisterTest, DeserializeBadData) {
  193. persister_->LoadEntries("");
  194. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  195. EXPECT_EQ(0u, state_->num_sts_entries());
  196. persister_->LoadEntries("Foopy");
  197. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  198. EXPECT_EQ(0u, state_->num_sts_entries());
  199. persister_->LoadEntries("15");
  200. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  201. EXPECT_EQ(0u, state_->num_sts_entries());
  202. persister_->LoadEntries("[15]");
  203. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  204. EXPECT_EQ(0u, state_->num_sts_entries());
  205. persister_->LoadEntries("{\"version\":1}");
  206. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  207. EXPECT_EQ(0u, state_->num_sts_entries());
  208. }
  209. TEST_P(TransportSecurityPersisterTest, DeserializeDataOldWithoutCreationDate) {
  210. // This is an old-style piece of transport state JSON, which has no creation
  211. // date.
  212. const std::string kInput =
  213. "{ "
  214. "\"G0EywIek2XnIhLrUjaK4TrHBT1+2TcixDVRXwM3/CCo=\": {"
  215. "\"expiry\": 1266815027.983453, "
  216. "\"include_subdomains\": false, "
  217. "\"mode\": \"strict\" "
  218. "}"
  219. "}";
  220. persister_->LoadEntries(kInput);
  221. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  222. EXPECT_EQ(0u, state_->num_sts_entries());
  223. }
  224. TEST_P(TransportSecurityPersisterTest, DeserializeDataOldMergedDictionary) {
  225. // This is an old-style piece of transport state JSON, which uses a single
  226. // unversioned host-keyed dictionary of merged ExpectCT and HSTS data.
  227. const std::string kInput =
  228. "{"
  229. " \"CxLbri+JPdi5pZ8/a/2rjyzq+IYs07WJJ1yxjB4Lpw0=\": {"
  230. " \"expect_ct\": {"
  231. " \"expect_ct_enforce\": true,"
  232. " \"expect_ct_expiry\": 1590512843.283966,"
  233. " \"expect_ct_observed\": 1590511843.284064,"
  234. " \"expect_ct_report_uri\": \"https://expect_ct.test/report_uri\""
  235. " },"
  236. " \"expiry\": 0.0,"
  237. " \"mode\": \"default\","
  238. " \"sts_include_subdomains\": false,"
  239. " \"sts_observed\": 0.0"
  240. " },"
  241. " \"DkgjGShIBmYtgJcJf5lfX3rTr2S6dqyF+O8IAgjuleE=\": {"
  242. " \"expiry\": 1590512843.283966,"
  243. " \"mode\": \"force-https\","
  244. " \"sts_include_subdomains\": false,"
  245. " \"sts_observed\": 1590511843.284025"
  246. " },"
  247. " \"M5lkNV3JBeoPMlKrTOKRYT+mrUsZCS5eoQWsc9/r1MU=\": {"
  248. " \"expect_ct\": {"
  249. " \"expect_ct_enforce\": true,"
  250. " \"expect_ct_expiry\": 1590512843.283966,"
  251. " \"expect_ct_observed\": 1590511843.284098,"
  252. " \"expect_ct_report_uri\": \"\""
  253. " },"
  254. " \"expiry\": 1590512843.283966,"
  255. " \"mode\": \"force-https\","
  256. " \"sts_include_subdomains\": true,"
  257. " \"sts_observed\": 1590511843.284091"
  258. " }"
  259. "}";
  260. persister_->LoadEntries(kInput);
  261. EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
  262. EXPECT_EQ(0u, state_->num_sts_entries());
  263. }
  264. // Tests that dynamic Expect-CT state is serialized and deserialized correctly.
  265. TEST_P(TransportSecurityPersisterTest, ExpectCT) {
  266. base::test::ScopedFeatureList feature_list;
  267. feature_list.InitAndEnableFeature(
  268. TransportSecurityState::kDynamicExpectCTFeature);
  269. const GURL report_uri(kReportUri);
  270. TransportSecurityState::ExpectCTState expect_ct_state;
  271. static const char kTestDomain[] = "example.test";
  272. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  273. kTestDomain, NetworkIsolationKey(), &expect_ct_state));
  274. const base::Time current_time(base::Time::Now());
  275. const base::Time expiry = current_time + base::Seconds(1000);
  276. state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
  277. NetworkIsolationKey());
  278. std::string serialized;
  279. EXPECT_TRUE(persister_->SerializeData(&serialized));
  280. // LoadEntries() clears existing dynamic data before loading entries from
  281. // |serialized|.
  282. persister_->LoadEntries(serialized);
  283. TransportSecurityState::ExpectCTState new_expect_ct_state;
  284. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  285. kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
  286. EXPECT_TRUE(new_expect_ct_state.enforce);
  287. EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
  288. EXPECT_EQ(expiry, new_expect_ct_state.expiry);
  289. // Update the state for the domain and check that it is
  290. // serialized/deserialized correctly.
  291. state_->AddExpectCT(kTestDomain, expiry, false /* enforce */, report_uri,
  292. NetworkIsolationKey());
  293. EXPECT_TRUE(persister_->SerializeData(&serialized));
  294. persister_->LoadEntries(serialized);
  295. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  296. kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
  297. EXPECT_FALSE(new_expect_ct_state.enforce);
  298. EXPECT_EQ(report_uri, new_expect_ct_state.report_uri);
  299. EXPECT_EQ(expiry, new_expect_ct_state.expiry);
  300. }
  301. // Tests that dynamic Expect-CT state is serialized and deserialized correctly
  302. // when there is also STS data present.
  303. TEST_P(TransportSecurityPersisterTest, ExpectCTWithSTSDataPresent) {
  304. base::test::ScopedFeatureList feature_list;
  305. feature_list.InitAndEnableFeature(
  306. TransportSecurityState::kDynamicExpectCTFeature);
  307. const GURL report_uri(kReportUri);
  308. TransportSecurityState::ExpectCTState expect_ct_state;
  309. static const char kTestDomain[] = "example.test";
  310. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  311. kTestDomain, NetworkIsolationKey(), &expect_ct_state));
  312. const base::Time current_time(base::Time::Now());
  313. const base::Time expiry = current_time + base::Seconds(1000);
  314. state_->AddHSTS(kTestDomain, expiry, false /* include subdomains */);
  315. state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
  316. NetworkIsolationKey());
  317. std::string serialized;
  318. EXPECT_TRUE(persister_->SerializeData(&serialized));
  319. // LoadEntries() clears existing dynamic data before loading entries from
  320. // |serialized|.
  321. persister_->LoadEntries(serialized);
  322. TransportSecurityState::ExpectCTState new_expect_ct_state;
  323. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  324. kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
  325. EXPECT_TRUE(new_expect_ct_state.enforce);
  326. EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
  327. EXPECT_EQ(expiry, new_expect_ct_state.expiry);
  328. // Check that STS state is loaded properly as well.
  329. TransportSecurityState::STSState sts_state;
  330. EXPECT_TRUE(state_->GetDynamicSTSState(kTestDomain, &sts_state));
  331. EXPECT_EQ(sts_state.upgrade_mode,
  332. TransportSecurityState::STSState::MODE_FORCE_HTTPS);
  333. }
  334. // Tests that Expect-CT state is not serialized and persisted when the feature
  335. // is disabled.
  336. TEST_P(TransportSecurityPersisterTest, ExpectCTDisabled) {
  337. base::test::ScopedFeatureList feature_list;
  338. feature_list.InitAndDisableFeature(
  339. TransportSecurityState::kDynamicExpectCTFeature);
  340. const GURL report_uri(kReportUri);
  341. TransportSecurityState::ExpectCTState expect_ct_state;
  342. static const char kTestDomain[] = "example.test";
  343. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  344. kTestDomain, NetworkIsolationKey(), &expect_ct_state));
  345. const base::Time current_time(base::Time::Now());
  346. const base::Time expiry = current_time + base::Seconds(1000);
  347. state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
  348. NetworkIsolationKey());
  349. std::string serialized;
  350. EXPECT_TRUE(persister_->SerializeData(&serialized));
  351. persister_->LoadEntries(serialized);
  352. TransportSecurityState::ExpectCTState new_expect_ct_state;
  353. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  354. kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
  355. }
  356. // Save data with several NetworkIsolationKeys with
  357. // kPartitionExpectCTStateByNetworkIsolationKey enabled, and then load it with
  358. // the feature enabled or disabled, based on partition_expect_ct_state().
  359. TEST_P(TransportSecurityPersisterTest, ExpectCTWithNetworkIsolationKey) {
  360. base::test::ScopedFeatureList feature_list;
  361. feature_list.InitAndEnableFeature(
  362. TransportSecurityState::kDynamicExpectCTFeature);
  363. const GURL report_uri(kReportUri);
  364. static const char kTestDomain[] = "example.test";
  365. const SchemefulSite kSite(GURL("https://somewhere.else.test"));
  366. const NetworkIsolationKey empty_network_isolation_key;
  367. const NetworkIsolationKey network_isolation_key(kSite /* top_frame_site */,
  368. kSite /* frame_site */);
  369. const NetworkIsolationKey transient_network_isolation_key =
  370. NetworkIsolationKey::CreateTransient();
  371. const base::Time current_time(base::Time::Now());
  372. const base::Time expiry1 = current_time + base::Seconds(1000);
  373. const base::Time expiry2 = current_time + base::Seconds(2000);
  374. const base::Time expiry3 = current_time + base::Seconds(3000);
  375. // Serialize data with kPartitionExpectCTStateByNetworkIsolationKey enabled,
  376. // and then revert the feature to its previous value.
  377. std::string serialized;
  378. {
  379. base::test::ScopedFeatureList feature_list2;
  380. feature_list2.InitAndEnableFeature(
  381. features::kPartitionExpectCTStateByNetworkIsolationKey);
  382. TransportSecurityState state2;
  383. TransportSecurityPersister persister2(
  384. &state2,
  385. std::move(base::ThreadPool::CreateSequencedTaskRunner(
  386. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  387. base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
  388. transport_security_file_path_);
  389. TransportSecurityState::ExpectCTState expect_ct_state;
  390. state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
  391. empty_network_isolation_key);
  392. state2.AddExpectCT(kTestDomain, expiry2, true /* enforce */, GURL(),
  393. network_isolation_key);
  394. state2.AddExpectCT(kTestDomain, expiry3, true /* enforce */, GURL(),
  395. transient_network_isolation_key);
  396. EXPECT_TRUE(persister2.SerializeData(&serialized));
  397. EXPECT_TRUE(state2.GetDynamicExpectCTState(
  398. kTestDomain, empty_network_isolation_key, &expect_ct_state));
  399. EXPECT_TRUE(state2.GetDynamicExpectCTState(
  400. kTestDomain, network_isolation_key, &expect_ct_state));
  401. EXPECT_TRUE(state2.GetDynamicExpectCTState(
  402. kTestDomain, transient_network_isolation_key, &expect_ct_state));
  403. }
  404. // Load entries into the other persister.
  405. persister_->LoadEntries(serialized);
  406. if (partition_expect_ct_state()) {
  407. TransportSecurityState::ExpectCTState new_expect_ct_state;
  408. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  409. kTestDomain, empty_network_isolation_key, &new_expect_ct_state));
  410. EXPECT_TRUE(new_expect_ct_state.enforce);
  411. EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
  412. EXPECT_EQ(expiry1, new_expect_ct_state.expiry);
  413. EXPECT_TRUE(state_->GetDynamicExpectCTState(
  414. kTestDomain, network_isolation_key, &new_expect_ct_state));
  415. EXPECT_TRUE(new_expect_ct_state.enforce);
  416. EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
  417. EXPECT_EQ(expiry2, new_expect_ct_state.expiry);
  418. // The data associated with the transient NetworkIsolationKey should not
  419. // have been saved.
  420. EXPECT_FALSE(state_->GetDynamicExpectCTState(
  421. kTestDomain, transient_network_isolation_key, &new_expect_ct_state));
  422. } else {
  423. std::set<std::string> expect_ct_saved;
  424. TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
  425. ASSERT_TRUE(expect_ct_iter.HasNext());
  426. EXPECT_EQ(empty_network_isolation_key,
  427. expect_ct_iter.network_isolation_key());
  428. EXPECT_TRUE(expect_ct_iter.domain_state().enforce);
  429. EXPECT_TRUE(expect_ct_iter.domain_state().report_uri.is_empty());
  430. expect_ct_iter.Advance();
  431. EXPECT_FALSE(expect_ct_iter.HasNext());
  432. }
  433. }
  434. // Test the case when deserializing a NetworkIsolationKey fails.
  435. TEST_P(TransportSecurityPersisterTest,
  436. ExpectCTNetworkIsolationKeyDeserializationFails) {
  437. base::test::ScopedFeatureList feature_list;
  438. feature_list.InitWithFeatures(
  439. // enabled_features
  440. {TransportSecurityState::kDynamicExpectCTFeature,
  441. features::kPartitionExpectCTStateByNetworkIsolationKey},
  442. // disabled_features
  443. {});
  444. const GURL report_uri(kReportUri);
  445. static const char kTestDomain[] = "example.test";
  446. const SchemefulSite kSite(GURL("https://somewhere.else.test"));
  447. const NetworkIsolationKey empty_network_isolation_key;
  448. const NetworkIsolationKey network_isolation_key(kSite /* top_frame_site */,
  449. kSite /* frame_site */);
  450. const base::Time current_time(base::Time::Now());
  451. const base::Time expiry1 = current_time + base::Seconds(1000);
  452. const base::Time expiry2 = current_time + base::Seconds(2000);
  453. // Serialize data.
  454. std::string serialized;
  455. TransportSecurityState state2;
  456. TransportSecurityPersister persister2(
  457. &state2,
  458. std::move(base::ThreadPool::CreateSequencedTaskRunner(
  459. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  460. base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
  461. transport_security_file_path_);
  462. TransportSecurityState::ExpectCTState expect_ct_state;
  463. state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
  464. empty_network_isolation_key);
  465. state2.AddExpectCT(kTestDomain, expiry2, true /* enforce */, GURL(),
  466. network_isolation_key);
  467. EXPECT_TRUE(persister2.SerializeData(&serialized));
  468. EXPECT_TRUE(state2.GetDynamicExpectCTState(
  469. kTestDomain, empty_network_isolation_key, &expect_ct_state));
  470. EXPECT_TRUE(state2.GetDynamicExpectCTState(kTestDomain, network_isolation_key,
  471. &expect_ct_state));
  472. // Replace reference to |network_isolation_key|'s value with an invalid NIK
  473. // value.
  474. base::Value nik_value;
  475. ASSERT_TRUE(network_isolation_key.ToValue(&nik_value));
  476. std::string nik_string;
  477. ASSERT_TRUE(base::JSONWriter::Write(nik_value, &nik_string));
  478. base::ReplaceFirstSubstringAfterOffset(&serialized, 0, nik_string,
  479. "\"Not a valid NIK\"");
  480. // Load entries into the other persister.
  481. persister_->LoadEntries(serialized);
  482. // The entry with the non-empty NetworkIsolationKey should be dropped, since
  483. // its NIK is now invalid. The other entry should be preserved.
  484. std::set<std::string> expect_ct_saved;
  485. TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
  486. ASSERT_TRUE(expect_ct_iter.HasNext());
  487. EXPECT_EQ(empty_network_isolation_key,
  488. expect_ct_iter.network_isolation_key());
  489. EXPECT_TRUE(expect_ct_iter.domain_state().enforce);
  490. EXPECT_TRUE(expect_ct_iter.domain_state().report_uri.is_empty());
  491. expect_ct_iter.Advance();
  492. EXPECT_FALSE(expect_ct_iter.HasNext());
  493. }
  494. } // namespace
  495. } // namespace net