Skip to content

Commit

Permalink
Implement CT component updater killswitch
Browse files Browse the repository at this point in the history
Bug: 1211535
Change-Id: Ibf6b5d6ac6cc0afd98c9ff38c57f1568d2e0c897
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2910898
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: David Benjamin <davidben@chromium.org>
Commit-Queue: Carlos IL <carlosil@chromium.org>
Cr-Commit-Position: refs/heads/master@{#886778}
  • Loading branch information
carlosjoan91 authored and Chromium LUCI CQ committed May 26, 2021
1 parent 52364aa commit b87f568
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
4 changes: 4 additions & 0 deletions net/http/transport_security_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,10 @@ TransportSecurityState::CheckCTRequirements(
using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel;
std::string hostname = host_port_pair.host();

// If CT emergency disable flag is set, we don't require CT for any host.
if (ct_emergency_disable_)
return CT_NOT_REQUIRED;

// CT is not required if the certificate does not chain to a publicly
// trusted root certificate. Testing can override this, as certain tests
// rely on using a non-publicly-trusted root.
Expand Down
9 changes: 9 additions & 0 deletions net/http/transport_security_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,13 @@ class NET_EXPORT TransportSecurityState {
// occurs first.
void SetRequireCTDelegate(RequireCTDelegate* delegate);

// If |emergency_disable| is set to true, will stop requiring CT
// compliance on any further requests regardless of host or certificate
// status.
void SetCTEmergencyDisabled(bool emergency_disable) {
ct_emergency_disable_ = emergency_disable;
}

// Clears all dynamic data (e.g. HSTS and HPKP data).
//
// Does NOT persist changes using the Delegate, as this function is only
Expand Down Expand Up @@ -727,6 +734,8 @@ class NET_EXPORT TransportSecurityState {

std::set<std::string> hsts_host_bypass_list_;

bool ct_emergency_disable_ = false;

THREAD_CHECKER(thread_checker_);

DISALLOW_COPY_AND_ASSIGN(TransportSecurityState);
Expand Down
65 changes: 65 additions & 0 deletions net/http/transport_security_state_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,71 @@ TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) {
}
}

// Tests that the emergency disable flag causes CT to stop being required
// regardless of host or delegate status.
TEST_F(TransportSecurityStateTest, CTEmergencyDisable) {
using ::testing::_;
using ::testing::Return;
using CTRequirementLevel =
TransportSecurityState::RequireCTDelegate::CTRequirementLevel;

// Dummy cert to use as the validation chain. The contents do not matter.
scoped_refptr<X509Certificate> cert =
ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
ASSERT_TRUE(cert);

HashValueVector hashes;
hashes.push_back(
HashValue(X509Certificate::CalculateFingerprint256(cert->cert_buffer())));

TransportSecurityState state;

// Set CT emergency disable flag.
state.SetCTEmergencyDisabled(true);

MockRequireCTDelegate always_require_delegate;
EXPECT_CALL(always_require_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(CTRequirementLevel::REQUIRED));
state.SetRequireCTDelegate(&always_require_delegate);
EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
state.CheckCTRequirements(
HostPortPair("www.example.com", 443), true, hashes, cert.get(),
cert.get(), SignedCertificateTimestampAndStatusList(),
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
NetworkIsolationKey()));
EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
state.CheckCTRequirements(
HostPortPair("www.example.com", 443), true, hashes, cert.get(),
cert.get(), SignedCertificateTimestampAndStatusList(),
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
NetworkIsolationKey()));
EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
state.CheckCTRequirements(
HostPortPair("www.example.com", 443), true, hashes, cert.get(),
cert.get(), SignedCertificateTimestampAndStatusList(),
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
NetworkIsolationKey()));
EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
state.CheckCTRequirements(
HostPortPair("www.example.com", 443), true, hashes, cert.get(),
cert.get(), SignedCertificateTimestampAndStatusList(),
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY,
NetworkIsolationKey()));

state.SetRequireCTDelegate(nullptr);
EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
state.CheckCTRequirements(
HostPortPair("www.example.com", 443), true, hashes, cert.get(),
cert.get(), SignedCertificateTimestampAndStatusList(),
TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
NetworkIsolationKey()));
}

// Tests that Certificate Transparency is required for Symantec-issued
// certificates, unless the certificate was issued prior to 1 June 2016
// or the issuing CA is permitted as independently operated.
Expand Down
6 changes: 5 additions & 1 deletion services/network/network_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -733,10 +733,14 @@ void NetworkService::UpdateCtLogList(
}

void NetworkService::SetCtEnforcementEnabled(bool enabled) {
// TODO(crbug.com/1211535): Implement Certificate Transparency killswitch.
DCHECK(base::FeatureList::IsEnabled(
certificate_transparency::features::
kCertificateTransparencyComponentUpdater));
for (auto* context : network_contexts_) {
context->url_request_context()
->transport_security_state()
->SetCTEmergencyDisabled(!enabled);
}
}

#endif // BUILDFLAG(IS_CT_SUPPORTED)
Expand Down

0 comments on commit b87f568

Please sign in to comment.