Commit 6f919422 authored by Christopher Thompson's avatar Christopher Thompson Committed by Commit Bot

Flip default state when legacy TLS config not set

This will make all sites be treated as "control" (no warnings shown)
when the control site config has not yet been loaded. This will prevent
control sites from accidentally showing the warnings, at the expense of
occasionally not showing warnings on non-control sites near browser
startup time.

Bug: 1011089
Change-Id: I32ebb7affc0d0a4bc2a3f6b280c9e5943f9118eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1845488
Commit-Queue: Christopher Thompson <cthomp@chromium.org>
Reviewed-by: default avatarEmily Stark <estark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704904}
parent 8a0f68de
...@@ -140,15 +140,16 @@ SecurityStateTabHelper::GetVisibleSecurityState() { ...@@ -140,15 +140,16 @@ SecurityStateTabHelper::GetVisibleSecurityState() {
// entry. // entry.
int navigation_id = int navigation_id =
web_contents()->GetController().GetVisibleEntry()->GetUniqueID(); web_contents()->GetController().GetVisibleEntry()->GetUniqueID();
if (cached_is_legacy_tls_control_site_ && if (cached_should_suppress_legacy_tls_warning_ &&
cached_is_legacy_tls_control_site_.value().first == navigation_id) { cached_should_suppress_legacy_tls_warning_.value().first ==
state->is_legacy_tls_control_site = navigation_id) {
cached_is_legacy_tls_control_site_.value().second; state->should_suppress_legacy_tls_warning =
cached_should_suppress_legacy_tls_warning_.value().second;
} else { } else {
state->is_legacy_tls_control_site = state->should_suppress_legacy_tls_warning =
IsTLSDeprecationConfigControlSite(state->url); ShouldSuppressLegacyTLSWarning(state->url);
cached_is_legacy_tls_control_site_ = std::pair<int, bool>( cached_should_suppress_legacy_tls_warning_ = std::pair<int, bool>(
navigation_id, state->is_legacy_tls_control_site); navigation_id, state->should_suppress_legacy_tls_warning);
} }
} }
} }
......
...@@ -45,15 +45,14 @@ class SecurityStateTabHelper ...@@ -45,15 +45,14 @@ class SecurityStateTabHelper
bool UsedPolicyInstalledCertificate() const; bool UsedPolicyInstalledCertificate() const;
security_state::MaliciousContentStatus GetMaliciousContentStatus() const; security_state::MaliciousContentStatus GetMaliciousContentStatus() const;
// Caches the legacy TLS control site status for the duration of a page load // Caches the legacy TLS warning suppression status for the duration of a page
// (bound to a specific navigation ID) to ensure that we show consistent // load (bound to a specific navigation ID) to ensure that we show consistent
// security UI (e.g., security indicator and page info). This is because the // security UI (e.g., security indicator and page info). This is because the
// control site status depends on external state (a component loading from // status depends on external state (a component loading from disk), which can
// disk), which can cause inconsistent state across a page load if it isn't // cause inconsistent state across a page load if it isn't cached.
// cached.
base::Optional<std::pair<int /* navigation entry ID */, base::Optional<std::pair<int /* navigation entry ID */,
bool /* is_legacy_tls_control_site */>> bool /* should_suppress_legacy_tls_warning */>>
cached_is_legacy_tls_control_site_; cached_should_suppress_legacy_tls_warning_;
WEB_CONTENTS_USER_DATA_KEY_DECL(); WEB_CONTENTS_USER_DATA_KEY_DECL();
......
...@@ -1871,6 +1871,26 @@ IN_PROC_BROWSER_TEST_F( ...@@ -1871,6 +1871,26 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_NE(std::string::npos, explanation.recommendations[1].find("GCM")); EXPECT_NE(std::string::npos, explanation.recommendations[1].find("GCM"));
} }
// Tests that a connection with legacy TLS version (TLS 1.0/1.1) is not
// downgraded to SecurityLevel WARNING if no config proto is set (i.e., so we
// don't accidentally show the warning on control sites, see crbug.com/1011089).
IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, LegacyTLSNoProto) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
security_state::features::kLegacyTLSWarnings);
auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
auto* helper = SecurityStateTabHelper::FromWebContents(tab);
ui_test_utils::NavigateToURL(
browser(), GURL(std::string("https://") + kMockNonsecureHostname));
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_TRUE(
helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(security_state::SECURE, helper->GetSecurityLevel());
}
// Tests that a connection with legacy TLS versions (TLS 1.0/1.1) gets // Tests that a connection with legacy TLS versions (TLS 1.0/1.1) gets
// downgraded to SecurityLevel WARNING and |connection_used_legacy_tls| is set. // downgraded to SecurityLevel WARNING and |connection_used_legacy_tls| is set.
IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
...@@ -1879,6 +1899,11 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, ...@@ -1879,6 +1899,11 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
scoped_feature_list.InitAndEnableFeature( scoped_feature_list.InitAndEnableFeature(
security_state::features::kLegacyTLSWarnings); security_state::features::kLegacyTLSWarnings);
// Set an empty config (otherwise all sites are treated as control).
auto config =
std::make_unique<chrome_browser_ssl::LegacyTLSExperimentConfig>();
SetRemoteTLSDeprecationConfigProto(std::move(config));
auto* tab = browser()->tab_strip_model()->GetActiveWebContents(); auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
auto* helper = SecurityStateTabHelper::FromWebContents(tab); auto* helper = SecurityStateTabHelper::FromWebContents(tab);
...@@ -1886,7 +1911,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, ...@@ -1886,7 +1911,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
browser(), GURL(std::string("https://") + kMockNonsecureHostname)); browser(), GURL(std::string("https://") + kMockNonsecureHostname));
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_FALSE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_FALSE(
helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(security_state::WARNING, helper->GetSecurityLevel()); EXPECT_EQ(security_state::WARNING, helper->GetSecurityLevel());
} }
...@@ -1911,14 +1937,15 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, ...@@ -1911,14 +1937,15 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
ui_test_utils::NavigateToURL(browser(), control_site); ui_test_utils::NavigateToURL(browser(), control_site);
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_TRUE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_TRUE(
helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE); EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE);
// Reset the config to be empty. // Reset the config to be empty.
auto empty_config = auto empty_config =
std::make_unique<chrome_browser_ssl::LegacyTLSExperimentConfig>(); std::make_unique<chrome_browser_ssl::LegacyTLSExperimentConfig>();
SetRemoteTLSDeprecationConfigProto(std::move(empty_config)); SetRemoteTLSDeprecationConfigProto(std::move(empty_config));
ASSERT_FALSE(IsTLSDeprecationConfigControlSite(control_site)); ASSERT_FALSE(ShouldSuppressLegacyTLSWarning(control_site));
} }
// Tests that the SSLVersionMin policy can disable the Legacy TLS security // Tests that the SSLVersionMin policy can disable the Legacy TLS security
...@@ -1942,7 +1969,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, ...@@ -1942,7 +1969,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
browser(), GURL(std::string("https://") + kMockNonsecureHostname)); browser(), GURL(std::string("https://") + kMockNonsecureHostname));
EXPECT_FALSE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_FALSE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_FALSE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_FALSE(
helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE); EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE);
g_browser_process->local_state()->SetString(prefs::kSSLVersionMin, g_browser_process->local_state()->SetString(prefs::kSSLVersionMin,
...@@ -1965,26 +1993,28 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, ...@@ -1965,26 +1993,28 @@ IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest,
ui_test_utils::NavigateToURL(browser(), control_site); ui_test_utils::NavigateToURL(browser(), control_site);
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_FALSE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_TRUE(
EXPECT_EQ(helper->GetSecurityLevel(), security_state::WARNING); helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE);
// Set the config proto. // Set the config proto.
auto config = auto config =
std::make_unique<chrome_browser_ssl::LegacyTLSExperimentConfig>(); std::make_unique<chrome_browser_ssl::LegacyTLSExperimentConfig>();
config->add_control_site_hashes(kMockControlSiteHash);
SetRemoteTLSDeprecationConfigProto(std::move(config)); SetRemoteTLSDeprecationConfigProto(std::move(config));
// Security state for the current page should not change. // Security state for the current page should not change.
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_FALSE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_TRUE(
EXPECT_EQ(helper->GetSecurityLevel(), security_state::WARNING); helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE);
// Refreshing the page should update the page's security state to now be // Refreshing the page should update the page's security state to now show a
// treated as control group. // warning.
ui_test_utils::NavigateToURL(browser(), control_site); ui_test_utils::NavigateToURL(browser(), control_site);
EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls); EXPECT_TRUE(helper->GetVisibleSecurityState()->connection_used_legacy_tls);
EXPECT_TRUE(helper->GetVisibleSecurityState()->is_legacy_tls_control_site); EXPECT_FALSE(
EXPECT_EQ(helper->GetSecurityLevel(), security_state::SECURE); helper->GetVisibleSecurityState()->should_suppress_legacy_tls_warning);
EXPECT_EQ(helper->GetSecurityLevel(), security_state::WARNING);
} }
// Tests that the Not Secure chip does not show for error pages on http:// URLs. // Tests that the Not Secure chip does not show for error pages on http:// URLs.
......
...@@ -45,13 +45,15 @@ void SetRemoteTLSDeprecationConfigProto( ...@@ -45,13 +45,15 @@ void SetRemoteTLSDeprecationConfigProto(
TLSDeprecationConfigSingleton::GetInstance().SetProto(std::move(proto)); TLSDeprecationConfigSingleton::GetInstance().SetProto(std::move(proto));
} }
bool IsTLSDeprecationConfigControlSite(const GURL& url) { bool ShouldSuppressLegacyTLSWarning(const GURL& url) {
if (!url.has_host() || !url.SchemeIsCryptographic()) if (!url.has_host() || !url.SchemeIsCryptographic())
return false; return false;
auto* proto = TLSDeprecationConfigSingleton::GetInstance().GetProto(); auto* proto = TLSDeprecationConfigSingleton::GetInstance().GetProto();
// If the config is not yet loaded, we err on the side of not showing warnings
// for any sites.
if (!proto) if (!proto)
return false; return true;
// Convert bytes from crypto::SHA256 so we can compare to the proto contents. // Convert bytes from crypto::SHA256 so we can compare to the proto contents.
std::string host_hash_bytes = crypto::SHA256HashString(url.host_piece()); std::string host_hash_bytes = crypto::SHA256HashString(url.host_piece());
......
...@@ -16,6 +16,6 @@ class LegacyTLSExperimentConfig; ...@@ -16,6 +16,6 @@ class LegacyTLSExperimentConfig;
void SetRemoteTLSDeprecationConfigProto( void SetRemoteTLSDeprecationConfigProto(
std::unique_ptr<chrome_browser_ssl::LegacyTLSExperimentConfig> proto); std::unique_ptr<chrome_browser_ssl::LegacyTLSExperimentConfig> proto);
bool IsTLSDeprecationConfigControlSite(const GURL& url); bool ShouldSuppressLegacyTLSWarning(const GURL& url);
#endif // CHROME_BROWSER_SSL_TLS_DEPRECATION_CONFIG_H_ #endif // CHROME_BROWSER_SSL_TLS_DEPRECATION_CONFIG_H_
...@@ -15,7 +15,7 @@ using chrome_browser_ssl::LegacyTLSExperimentConfig; ...@@ -15,7 +15,7 @@ using chrome_browser_ssl::LegacyTLSExperimentConfig;
// Tests the case where no proto has been set by the component installer. // Tests the case where no proto has been set by the component installer.
TEST(TLSDeprecationConfigTest, NoProto) { TEST(TLSDeprecationConfigTest, NoProto) {
EXPECT_FALSE(IsTLSDeprecationConfigControlSite(GURL("https://example.test"))); EXPECT_TRUE(ShouldSuppressLegacyTLSWarning(GURL("https://example.test")));
} }
// This tests that when no sites are in the control set, // This tests that when no sites are in the control set,
...@@ -30,7 +30,7 @@ TEST(TLSDeprecationConfigTest, NoControlSites) { ...@@ -30,7 +30,7 @@ TEST(TLSDeprecationConfigTest, NoControlSites) {
auto config = std::make_unique<LegacyTLSExperimentConfig>(); auto config = std::make_unique<LegacyTLSExperimentConfig>();
SetRemoteTLSDeprecationConfigProto(std::move(config)); SetRemoteTLSDeprecationConfigProto(std::move(config));
EXPECT_FALSE(IsTLSDeprecationConfigControlSite(control_site)); EXPECT_FALSE(ShouldSuppressLegacyTLSWarning(control_site));
} }
// This tests that when only a single control site is in the control set, // This tests that when only a single control site is in the control set,
...@@ -53,11 +53,11 @@ TEST(TLSDeprecationConfigTest, SingleControlSite) { ...@@ -53,11 +53,11 @@ TEST(TLSDeprecationConfigTest, SingleControlSite) {
SetRemoteTLSDeprecationConfigProto(std::move(config)); SetRemoteTLSDeprecationConfigProto(std::move(config));
EXPECT_TRUE(IsTLSDeprecationConfigControlSite(control_site)); EXPECT_TRUE(ShouldSuppressLegacyTLSWarning(control_site));
EXPECT_FALSE(IsTLSDeprecationConfigControlSite(non_control_site)); EXPECT_FALSE(ShouldSuppressLegacyTLSWarning(non_control_site));
// And HTTP sites should not count either. // And HTTP sites should not count either.
EXPECT_FALSE(IsTLSDeprecationConfigControlSite(http_site)); EXPECT_FALSE(ShouldSuppressLegacyTLSWarning(http_site));
} }
// This tests that the binary search in IsTLSDeprecationControlSite() works for // This tests that the binary search in IsTLSDeprecationControlSite() works for
...@@ -98,8 +98,8 @@ TEST(TLSDeprecationConfigTest, ManyControlSites) { ...@@ -98,8 +98,8 @@ TEST(TLSDeprecationConfigTest, ManyControlSites) {
SetRemoteTLSDeprecationConfigProto(std::move(config)); SetRemoteTLSDeprecationConfigProto(std::move(config));
for (auto& site : kControlSites) { for (auto& site : kControlSites) {
EXPECT_TRUE(IsTLSDeprecationConfigControlSite(site.url)); EXPECT_TRUE(ShouldSuppressLegacyTLSWarning(site.url));
} }
EXPECT_FALSE(IsTLSDeprecationConfigControlSite(non_control_site)); EXPECT_FALSE(ShouldSuppressLegacyTLSWarning(non_control_site));
} }
...@@ -830,7 +830,7 @@ void PageInfo::ComputeUIInputs( ...@@ -830,7 +830,7 @@ void PageInfo::ComputeUIInputs(
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
security_state::features::kLegacyTLSWarnings) && security_state::features::kLegacyTLSWarnings) &&
visible_security_state.connection_used_legacy_tls && visible_security_state.connection_used_legacy_tls &&
!visible_security_state.is_legacy_tls_control_site) { !visible_security_state.should_suppress_legacy_tls_warning) {
site_connection_status_ = SITE_CONNECTION_STATUS_LEGACY_TLS; site_connection_status_ = SITE_CONNECTION_STATUS_LEGACY_TLS;
} }
......
...@@ -872,7 +872,7 @@ TEST_F(PageInfoTest, LegacyTLS) { ...@@ -872,7 +872,7 @@ TEST_F(PageInfoTest, LegacyTLS) {
visible_security_state_.connection_status = status; visible_security_state_.connection_status = status;
visible_security_state_.connection_info_initialized = true; visible_security_state_.connection_info_initialized = true;
visible_security_state_.connection_used_legacy_tls = true; visible_security_state_.connection_used_legacy_tls = true;
visible_security_state_.is_legacy_tls_control_site = false; visible_security_state_.should_suppress_legacy_tls_warning = false;
SetDefaultUIExpectations(mock_ui()); SetDefaultUIExpectations(mock_ui());
...@@ -900,7 +900,7 @@ TEST_F(PageInfoTest, LegacyTLSControlSite) { ...@@ -900,7 +900,7 @@ TEST_F(PageInfoTest, LegacyTLSControlSite) {
visible_security_state_.connection_status = status; visible_security_state_.connection_status = status;
visible_security_state_.connection_info_initialized = true; visible_security_state_.connection_info_initialized = true;
visible_security_state_.connection_used_legacy_tls = true; visible_security_state_.connection_used_legacy_tls = true;
visible_security_state_.is_legacy_tls_control_site = true; visible_security_state_.should_suppress_legacy_tls_warning = true;
SetDefaultUIExpectations(mock_ui()); SetDefaultUIExpectations(mock_ui());
......
...@@ -159,7 +159,7 @@ SecurityLevel GetSecurityLevel( ...@@ -159,7 +159,7 @@ SecurityLevel GetSecurityLevel(
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
security_state::features::kLegacyTLSWarnings) && security_state::features::kLegacyTLSWarnings) &&
visible_security_state.connection_used_legacy_tls && visible_security_state.connection_used_legacy_tls &&
!visible_security_state.is_legacy_tls_control_site) { !visible_security_state.should_suppress_legacy_tls_warning) {
return WARNING; return WARNING;
} }
...@@ -231,7 +231,7 @@ VisibleSecurityState::VisibleSecurityState() ...@@ -231,7 +231,7 @@ VisibleSecurityState::VisibleSecurityState()
is_view_source(false), is_view_source(false),
is_devtools(false), is_devtools(false),
connection_used_legacy_tls(false), connection_used_legacy_tls(false),
is_legacy_tls_control_site(false) {} should_suppress_legacy_tls_warning(false) {}
VisibleSecurityState::~VisibleSecurityState() {} VisibleSecurityState::~VisibleSecurityState() {}
......
...@@ -181,7 +181,7 @@ struct VisibleSecurityState { ...@@ -181,7 +181,7 @@ struct VisibleSecurityState {
bool connection_used_legacy_tls; bool connection_used_legacy_tls;
// True if the page should be excluded from a UI treatment for legacy TLS // True if the page should be excluded from a UI treatment for legacy TLS
// (used for control group in an experimental UI rollout). // (used for control group in an experimental UI rollout).
bool is_legacy_tls_control_site; bool should_suppress_legacy_tls_warning;
// Contains information about input events that may impact the security // Contains information about input events that may impact the security
// level of the page. // level of the page.
InsecureInputEventData insecure_input_events; InsecureInputEventData insecure_input_events;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment