123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- // Copyright (c) 2012 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.
- #include "net/http/transport_security_persister.h"
- #include <map>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/files/scoped_temp_dir.h"
- #include "base/json/json_writer.h"
- #include "base/run_loop.h"
- #include "base/strings/string_util.h"
- #include "base/task/current_thread.h"
- #include "base/task/thread_pool.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "net/base/features.h"
- #include "net/base/network_isolation_key.h"
- #include "net/base/schemeful_site.h"
- #include "net/http/transport_security_state.h"
- #include "net/test/test_with_task_environment.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "url/gurl.h"
- namespace net {
- namespace {
- const char kReportUri[] = "http://www.example.test/report";
- // The bool indicates whether kPartitionExpectCTStateByNetworkIsolationKey
- // should be enabled.
- class TransportSecurityPersisterTest : public ::testing::TestWithParam<bool>,
- public WithTaskEnvironment {
- public:
- TransportSecurityPersisterTest()
- : WithTaskEnvironment(
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
- // This feature is used in initializing |state_|.
- if (partition_expect_ct_state()) {
- feature_list_.InitAndEnableFeature(
- features::kPartitionExpectCTStateByNetworkIsolationKey);
- } else {
- feature_list_.InitAndDisableFeature(
- features::kPartitionExpectCTStateByNetworkIsolationKey);
- }
- // Mock out time so that entries with hard-coded json data can be
- // successfully loaded. Use a large enough value that dynamically created
- // entries have at least somewhat interesting expiration times.
- FastForwardBy(base::Days(3660));
- }
- ~TransportSecurityPersisterTest() override {
- EXPECT_TRUE(base::CurrentIOThread::IsSet());
- base::RunLoop().RunUntilIdle();
- }
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- transport_security_file_path_ =
- temp_dir_.GetPath().AppendASCII("TransportSecurity");
- ASSERT_TRUE(base::CurrentIOThread::IsSet());
- scoped_refptr<base::SequencedTaskRunner> background_runner(
- base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
- state_ = std::make_unique<TransportSecurityState>();
- persister_ = std::make_unique<TransportSecurityPersister>(
- state_.get(), std::move(background_runner),
- transport_security_file_path_);
- }
- bool partition_expect_ct_state() const { return GetParam(); }
- protected:
- base::FilePath transport_security_file_path_;
- base::ScopedTempDir temp_dir_;
- base::test::ScopedFeatureList feature_list_;
- std::unique_ptr<TransportSecurityState> state_;
- std::unique_ptr<TransportSecurityPersister> persister_;
- };
- INSTANTIATE_TEST_SUITE_P(All, TransportSecurityPersisterTest, testing::Bool());
- // Tests that LoadEntries() clears existing non-static entries.
- TEST_P(TransportSecurityPersisterTest, LoadEntriesClearsExistingState) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- TransportSecurityState::STSState sts_state;
- TransportSecurityState::ExpectCTState expect_ct_state;
- const base::Time current_time(base::Time::Now());
- const base::Time expiry = current_time + base::Seconds(1000);
- static const char kYahooDomain[] = "yahoo.com";
- EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
- state_->AddHSTS(kYahooDomain, expiry, false /* include subdomains */);
- state_->AddExpectCT(kYahooDomain, expiry, true /* enforce */, GURL(),
- NetworkIsolationKey());
- EXPECT_TRUE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kYahooDomain, NetworkIsolationKey(), &expect_ct_state));
- persister_->LoadEntries("{\"version\":2}");
- EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kYahooDomain, NetworkIsolationKey(), &expect_ct_state));
- }
- // Tests that serializing -> deserializing -> reserializing results in the same
- // output.
- TEST_P(TransportSecurityPersisterTest, SerializeData1) {
- std::string output;
- EXPECT_TRUE(persister_->SerializeData(&output));
- persister_->LoadEntries(output);
- std::string output2;
- EXPECT_TRUE(persister_->SerializeData(&output2));
- EXPECT_EQ(output, output2);
- }
- TEST_P(TransportSecurityPersisterTest, SerializeData2) {
- TransportSecurityState::STSState sts_state;
- const base::Time current_time(base::Time::Now());
- const base::Time expiry = current_time + base::Seconds(1000);
- static const char kYahooDomain[] = "yahoo.com";
- EXPECT_FALSE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
- bool include_subdomains = true;
- state_->AddHSTS(kYahooDomain, expiry, include_subdomains);
- std::string output;
- EXPECT_TRUE(persister_->SerializeData(&output));
- persister_->LoadEntries(output);
- EXPECT_TRUE(state_->GetDynamicSTSState(kYahooDomain, &sts_state));
- EXPECT_EQ(sts_state.upgrade_mode,
- TransportSecurityState::STSState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_->GetDynamicSTSState("foo.yahoo.com", &sts_state));
- EXPECT_EQ(sts_state.upgrade_mode,
- TransportSecurityState::STSState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_->GetDynamicSTSState("foo.bar.yahoo.com", &sts_state));
- EXPECT_EQ(sts_state.upgrade_mode,
- TransportSecurityState::STSState::MODE_FORCE_HTTPS);
- EXPECT_TRUE(state_->GetDynamicSTSState("foo.bar.baz.yahoo.com", &sts_state));
- EXPECT_EQ(sts_state.upgrade_mode,
- TransportSecurityState::STSState::MODE_FORCE_HTTPS);
- }
- TEST_P(TransportSecurityPersisterTest, SerializeData3) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- const GURL report_uri(kReportUri);
- // Add an entry.
- base::Time expiry = base::Time::Now() + base::Seconds(1000);
- bool include_subdomains = false;
- state_->AddHSTS("www.example.com", expiry, include_subdomains);
- state_->AddExpectCT("www.example.com", expiry, true /* enforce */, GURL(),
- NetworkIsolationKey());
- // Add another entry.
- expiry = base::Time::Now() + base::Seconds(3000);
- state_->AddHSTS("www.example.net", expiry, include_subdomains);
- state_->AddExpectCT("www.example.net", expiry, false /* enforce */,
- report_uri, NetworkIsolationKey());
- // Save a copy of everything.
- std::set<std::string> sts_saved;
- TransportSecurityState::STSStateIterator sts_iter(*state_);
- while (sts_iter.HasNext()) {
- sts_saved.insert(sts_iter.hostname());
- sts_iter.Advance();
- }
- std::set<std::string> expect_ct_saved;
- TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
- while (expect_ct_iter.HasNext()) {
- expect_ct_saved.insert(expect_ct_iter.hostname());
- expect_ct_iter.Advance();
- }
- std::string serialized;
- EXPECT_TRUE(persister_->SerializeData(&serialized));
- // Persist the data to the file.
- base::RunLoop run_loop;
- persister_->WriteNow(state_.get(), run_loop.QuitClosure());
- run_loop.Run();
- // Read the data back.
- std::string persisted;
- EXPECT_TRUE(
- base::ReadFileToString(transport_security_file_path_, &persisted));
- EXPECT_EQ(persisted, serialized);
- persister_->LoadEntries(persisted);
- // Check that states are the same as saved.
- size_t count = 0;
- TransportSecurityState::STSStateIterator sts_iter2(*state_);
- while (sts_iter2.HasNext()) {
- count++;
- sts_iter2.Advance();
- }
- EXPECT_EQ(count, sts_saved.size());
- count = 0;
- TransportSecurityState::ExpectCTStateIterator expect_ct_iter2(*state_);
- while (expect_ct_iter2.HasNext()) {
- count++;
- expect_ct_iter2.Advance();
- }
- EXPECT_EQ(count, expect_ct_saved.size());
- }
- // Tests that deserializing bad data shouldn't result in any ExpectCT or STS
- // entries being added to the transport security state.
- TEST_P(TransportSecurityPersisterTest, DeserializeBadData) {
- persister_->LoadEntries("");
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- persister_->LoadEntries("Foopy");
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- persister_->LoadEntries("15");
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- persister_->LoadEntries("[15]");
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- persister_->LoadEntries("{\"version\":1}");
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- }
- TEST_P(TransportSecurityPersisterTest, DeserializeDataOldWithoutCreationDate) {
- // This is an old-style piece of transport state JSON, which has no creation
- // date.
- const std::string kInput =
- "{ "
- "\"G0EywIek2XnIhLrUjaK4TrHBT1+2TcixDVRXwM3/CCo=\": {"
- "\"expiry\": 1266815027.983453, "
- "\"include_subdomains\": false, "
- "\"mode\": \"strict\" "
- "}"
- "}";
- persister_->LoadEntries(kInput);
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- }
- TEST_P(TransportSecurityPersisterTest, DeserializeDataOldMergedDictionary) {
- // This is an old-style piece of transport state JSON, which uses a single
- // unversioned host-keyed dictionary of merged ExpectCT and HSTS data.
- const std::string kInput =
- "{"
- " \"CxLbri+JPdi5pZ8/a/2rjyzq+IYs07WJJ1yxjB4Lpw0=\": {"
- " \"expect_ct\": {"
- " \"expect_ct_enforce\": true,"
- " \"expect_ct_expiry\": 1590512843.283966,"
- " \"expect_ct_observed\": 1590511843.284064,"
- " \"expect_ct_report_uri\": \"https://expect_ct.test/report_uri\""
- " },"
- " \"expiry\": 0.0,"
- " \"mode\": \"default\","
- " \"sts_include_subdomains\": false,"
- " \"sts_observed\": 0.0"
- " },"
- " \"DkgjGShIBmYtgJcJf5lfX3rTr2S6dqyF+O8IAgjuleE=\": {"
- " \"expiry\": 1590512843.283966,"
- " \"mode\": \"force-https\","
- " \"sts_include_subdomains\": false,"
- " \"sts_observed\": 1590511843.284025"
- " },"
- " \"M5lkNV3JBeoPMlKrTOKRYT+mrUsZCS5eoQWsc9/r1MU=\": {"
- " \"expect_ct\": {"
- " \"expect_ct_enforce\": true,"
- " \"expect_ct_expiry\": 1590512843.283966,"
- " \"expect_ct_observed\": 1590511843.284098,"
- " \"expect_ct_report_uri\": \"\""
- " },"
- " \"expiry\": 1590512843.283966,"
- " \"mode\": \"force-https\","
- " \"sts_include_subdomains\": true,"
- " \"sts_observed\": 1590511843.284091"
- " }"
- "}";
- persister_->LoadEntries(kInput);
- EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
- EXPECT_EQ(0u, state_->num_sts_entries());
- }
- // Tests that dynamic Expect-CT state is serialized and deserialized correctly.
- TEST_P(TransportSecurityPersisterTest, ExpectCT) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- const GURL report_uri(kReportUri);
- TransportSecurityState::ExpectCTState expect_ct_state;
- static const char kTestDomain[] = "example.test";
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &expect_ct_state));
- const base::Time current_time(base::Time::Now());
- const base::Time expiry = current_time + base::Seconds(1000);
- state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
- NetworkIsolationKey());
- std::string serialized;
- EXPECT_TRUE(persister_->SerializeData(&serialized));
- // LoadEntries() clears existing dynamic data before loading entries from
- // |serialized|.
- persister_->LoadEntries(serialized);
- TransportSecurityState::ExpectCTState new_expect_ct_state;
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
- EXPECT_TRUE(new_expect_ct_state.enforce);
- EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
- EXPECT_EQ(expiry, new_expect_ct_state.expiry);
- // Update the state for the domain and check that it is
- // serialized/deserialized correctly.
- state_->AddExpectCT(kTestDomain, expiry, false /* enforce */, report_uri,
- NetworkIsolationKey());
- EXPECT_TRUE(persister_->SerializeData(&serialized));
- persister_->LoadEntries(serialized);
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
- EXPECT_FALSE(new_expect_ct_state.enforce);
- EXPECT_EQ(report_uri, new_expect_ct_state.report_uri);
- EXPECT_EQ(expiry, new_expect_ct_state.expiry);
- }
- // Tests that dynamic Expect-CT state is serialized and deserialized correctly
- // when there is also STS data present.
- TEST_P(TransportSecurityPersisterTest, ExpectCTWithSTSDataPresent) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- const GURL report_uri(kReportUri);
- TransportSecurityState::ExpectCTState expect_ct_state;
- static const char kTestDomain[] = "example.test";
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &expect_ct_state));
- const base::Time current_time(base::Time::Now());
- const base::Time expiry = current_time + base::Seconds(1000);
- state_->AddHSTS(kTestDomain, expiry, false /* include subdomains */);
- state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
- NetworkIsolationKey());
- std::string serialized;
- EXPECT_TRUE(persister_->SerializeData(&serialized));
- // LoadEntries() clears existing dynamic data before loading entries from
- // |serialized|.
- persister_->LoadEntries(serialized);
- TransportSecurityState::ExpectCTState new_expect_ct_state;
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
- EXPECT_TRUE(new_expect_ct_state.enforce);
- EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
- EXPECT_EQ(expiry, new_expect_ct_state.expiry);
- // Check that STS state is loaded properly as well.
- TransportSecurityState::STSState sts_state;
- EXPECT_TRUE(state_->GetDynamicSTSState(kTestDomain, &sts_state));
- EXPECT_EQ(sts_state.upgrade_mode,
- TransportSecurityState::STSState::MODE_FORCE_HTTPS);
- }
- // Tests that Expect-CT state is not serialized and persisted when the feature
- // is disabled.
- TEST_P(TransportSecurityPersisterTest, ExpectCTDisabled) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- const GURL report_uri(kReportUri);
- TransportSecurityState::ExpectCTState expect_ct_state;
- static const char kTestDomain[] = "example.test";
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &expect_ct_state));
- const base::Time current_time(base::Time::Now());
- const base::Time expiry = current_time + base::Seconds(1000);
- state_->AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL(),
- NetworkIsolationKey());
- std::string serialized;
- EXPECT_TRUE(persister_->SerializeData(&serialized));
- persister_->LoadEntries(serialized);
- TransportSecurityState::ExpectCTState new_expect_ct_state;
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kTestDomain, NetworkIsolationKey(), &new_expect_ct_state));
- }
- // Save data with several NetworkIsolationKeys with
- // kPartitionExpectCTStateByNetworkIsolationKey enabled, and then load it with
- // the feature enabled or disabled, based on partition_expect_ct_state().
- TEST_P(TransportSecurityPersisterTest, ExpectCTWithNetworkIsolationKey) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- TransportSecurityState::kDynamicExpectCTFeature);
- const GURL report_uri(kReportUri);
- static const char kTestDomain[] = "example.test";
- const SchemefulSite kSite(GURL("https://somewhere.else.test"));
- const NetworkIsolationKey empty_network_isolation_key;
- const NetworkIsolationKey network_isolation_key(kSite /* top_frame_site */,
- kSite /* frame_site */);
- const NetworkIsolationKey transient_network_isolation_key =
- NetworkIsolationKey::CreateTransient();
- const base::Time current_time(base::Time::Now());
- const base::Time expiry1 = current_time + base::Seconds(1000);
- const base::Time expiry2 = current_time + base::Seconds(2000);
- const base::Time expiry3 = current_time + base::Seconds(3000);
- // Serialize data with kPartitionExpectCTStateByNetworkIsolationKey enabled,
- // and then revert the feature to its previous value.
- std::string serialized;
- {
- base::test::ScopedFeatureList feature_list2;
- feature_list2.InitAndEnableFeature(
- features::kPartitionExpectCTStateByNetworkIsolationKey);
- TransportSecurityState state2;
- TransportSecurityPersister persister2(
- &state2,
- std::move(base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
- transport_security_file_path_);
- TransportSecurityState::ExpectCTState expect_ct_state;
- state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
- empty_network_isolation_key);
- state2.AddExpectCT(kTestDomain, expiry2, true /* enforce */, GURL(),
- network_isolation_key);
- state2.AddExpectCT(kTestDomain, expiry3, true /* enforce */, GURL(),
- transient_network_isolation_key);
- EXPECT_TRUE(persister2.SerializeData(&serialized));
- EXPECT_TRUE(state2.GetDynamicExpectCTState(
- kTestDomain, empty_network_isolation_key, &expect_ct_state));
- EXPECT_TRUE(state2.GetDynamicExpectCTState(
- kTestDomain, network_isolation_key, &expect_ct_state));
- EXPECT_TRUE(state2.GetDynamicExpectCTState(
- kTestDomain, transient_network_isolation_key, &expect_ct_state));
- }
- // Load entries into the other persister.
- persister_->LoadEntries(serialized);
- if (partition_expect_ct_state()) {
- TransportSecurityState::ExpectCTState new_expect_ct_state;
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kTestDomain, empty_network_isolation_key, &new_expect_ct_state));
- EXPECT_TRUE(new_expect_ct_state.enforce);
- EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
- EXPECT_EQ(expiry1, new_expect_ct_state.expiry);
- EXPECT_TRUE(state_->GetDynamicExpectCTState(
- kTestDomain, network_isolation_key, &new_expect_ct_state));
- EXPECT_TRUE(new_expect_ct_state.enforce);
- EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty());
- EXPECT_EQ(expiry2, new_expect_ct_state.expiry);
- // The data associated with the transient NetworkIsolationKey should not
- // have been saved.
- EXPECT_FALSE(state_->GetDynamicExpectCTState(
- kTestDomain, transient_network_isolation_key, &new_expect_ct_state));
- } else {
- std::set<std::string> expect_ct_saved;
- TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
- ASSERT_TRUE(expect_ct_iter.HasNext());
- EXPECT_EQ(empty_network_isolation_key,
- expect_ct_iter.network_isolation_key());
- EXPECT_TRUE(expect_ct_iter.domain_state().enforce);
- EXPECT_TRUE(expect_ct_iter.domain_state().report_uri.is_empty());
- expect_ct_iter.Advance();
- EXPECT_FALSE(expect_ct_iter.HasNext());
- }
- }
- // Test the case when deserializing a NetworkIsolationKey fails.
- TEST_P(TransportSecurityPersisterTest,
- ExpectCTNetworkIsolationKeyDeserializationFails) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures(
- // enabled_features
- {TransportSecurityState::kDynamicExpectCTFeature,
- features::kPartitionExpectCTStateByNetworkIsolationKey},
- // disabled_features
- {});
- const GURL report_uri(kReportUri);
- static const char kTestDomain[] = "example.test";
- const SchemefulSite kSite(GURL("https://somewhere.else.test"));
- const NetworkIsolationKey empty_network_isolation_key;
- const NetworkIsolationKey network_isolation_key(kSite /* top_frame_site */,
- kSite /* frame_site */);
- const base::Time current_time(base::Time::Now());
- const base::Time expiry1 = current_time + base::Seconds(1000);
- const base::Time expiry2 = current_time + base::Seconds(2000);
- // Serialize data.
- std::string serialized;
- TransportSecurityState state2;
- TransportSecurityPersister persister2(
- &state2,
- std::move(base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
- transport_security_file_path_);
- TransportSecurityState::ExpectCTState expect_ct_state;
- state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
- empty_network_isolation_key);
- state2.AddExpectCT(kTestDomain, expiry2, true /* enforce */, GURL(),
- network_isolation_key);
- EXPECT_TRUE(persister2.SerializeData(&serialized));
- EXPECT_TRUE(state2.GetDynamicExpectCTState(
- kTestDomain, empty_network_isolation_key, &expect_ct_state));
- EXPECT_TRUE(state2.GetDynamicExpectCTState(kTestDomain, network_isolation_key,
- &expect_ct_state));
- // Replace reference to |network_isolation_key|'s value with an invalid NIK
- // value.
- base::Value nik_value;
- ASSERT_TRUE(network_isolation_key.ToValue(&nik_value));
- std::string nik_string;
- ASSERT_TRUE(base::JSONWriter::Write(nik_value, &nik_string));
- base::ReplaceFirstSubstringAfterOffset(&serialized, 0, nik_string,
- "\"Not a valid NIK\"");
- // Load entries into the other persister.
- persister_->LoadEntries(serialized);
- // The entry with the non-empty NetworkIsolationKey should be dropped, since
- // its NIK is now invalid. The other entry should be preserved.
- std::set<std::string> expect_ct_saved;
- TransportSecurityState::ExpectCTStateIterator expect_ct_iter(*state_);
- ASSERT_TRUE(expect_ct_iter.HasNext());
- EXPECT_EQ(empty_network_isolation_key,
- expect_ct_iter.network_isolation_key());
- EXPECT_TRUE(expect_ct_iter.domain_state().enforce);
- EXPECT_TRUE(expect_ct_iter.domain_state().report_uri.is_empty());
- expect_ct_iter.Advance();
- EXPECT_FALSE(expect_ct_iter.HasNext());
- }
- } // namespace
- } // namespace net
|