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

Side by Side Diff: chrome/browser/ssl/ssl_browser_tests.cc

Issue 2620203003: Add initial version of captive portal list checking. (Closed)
Patch Set: estark and rsleevi comments Created 3 years, 10 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
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 <utility> 5 #include <utility>
6 6
7 #include "base/base_switches.h" 7 #include "base/base_switches.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/metrics/field_trial.h" 14 #include "base/metrics/field_trial.h"
15 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_split.h" 16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/test/histogram_tester.h" 20 #include "base/test/histogram_tester.h"
21 #include "base/test/scoped_feature_list.h"
21 #include "base/test/simple_test_clock.h" 22 #include "base/test/simple_test_clock.h"
22 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
23 #include "base/time/default_clock.h" 24 #include "base/time/default_clock.h"
24 #include "base/time/default_tick_clock.h" 25 #include "base/time/default_tick_clock.h"
25 #include "base/time/time.h" 26 #include "base/time/time.h"
26 #include "build/build_config.h" 27 #include "build/build_config.h"
27 #include "chrome/app/chrome_command_ids.h" 28 #include "chrome/app/chrome_command_ids.h"
28 #include "chrome/browser/browser_process.h" 29 #include "chrome/browser/browser_process.h"
29 #include "chrome/browser/chrome_notification_types.h" 30 #include "chrome/browser/chrome_notification_types.h"
30 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" 31 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
31 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h" 32 #include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
32 #include "chrome/browser/profiles/profile.h" 33 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/browser/ssl/bad_clock_blocking_page.h" 34 #include "chrome/browser/ssl/bad_clock_blocking_page.h"
34 #include "chrome/browser/ssl/cert_report_helper.h" 35 #include "chrome/browser/ssl/cert_report_helper.h"
35 #include "chrome/browser/ssl/cert_verifier_browser_test.h" 36 #include "chrome/browser/ssl/cert_verifier_browser_test.h"
36 #include "chrome/browser/ssl/certificate_reporting_test_utils.h" 37 #include "chrome/browser/ssl/certificate_reporting_test_utils.h"
37 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" 38 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
38 #include "chrome/browser/ssl/common_name_mismatch_handler.h" 39 #include "chrome/browser/ssl/common_name_mismatch_handler.h"
39 #include "chrome/browser/ssl/security_state_tab_helper.h" 40 #include "chrome/browser/ssl/security_state_tab_helper.h"
40 #include "chrome/browser/ssl/ssl_blocking_page.h" 41 #include "chrome/browser/ssl/ssl_blocking_page.h"
42 #include "chrome/browser/ssl/ssl_error_assistant.pb.h"
41 #include "chrome/browser/ssl/ssl_error_handler.h" 43 #include "chrome/browser/ssl/ssl_error_handler.h"
42 #include "chrome/browser/ui/browser.h" 44 #include "chrome/browser/ui/browser.h"
43 #include "chrome/browser/ui/browser_commands.h" 45 #include "chrome/browser/ui/browser_commands.h"
44 #include "chrome/browser/ui/browser_finder.h" 46 #include "chrome/browser/ui/browser_finder.h"
45 #include "chrome/browser/ui/browser_navigator.h" 47 #include "chrome/browser/ui/browser_navigator.h"
46 #include "chrome/browser/ui/browser_navigator_params.h" 48 #include "chrome/browser/ui/browser_navigator_params.h"
47 #include "chrome/browser/ui/browser_tabstrip.h" 49 #include "chrome/browser/ui/browser_tabstrip.h"
48 #include "chrome/browser/ui/tabs/tab_strip_model.h" 50 #include "chrome/browser/ui/tabs/tab_strip_model.h"
49 #include "chrome/common/chrome_paths.h" 51 #include "chrome/common/chrome_paths.h"
50 #include "chrome/common/chrome_switches.h" 52 #include "chrome/common/chrome_switches.h"
(...skipping 26 matching lines...) Expand all
77 #include "content/public/browser/web_contents.h" 79 #include "content/public/browser/web_contents.h"
78 #include "content/public/browser/web_contents_observer.h" 80 #include "content/public/browser/web_contents_observer.h"
79 #include "content/public/common/browser_side_navigation_policy.h" 81 #include "content/public/common/browser_side_navigation_policy.h"
80 #include "content/public/common/content_switches.h" 82 #include "content/public/common/content_switches.h"
81 #include "content/public/common/page_state.h" 83 #include "content/public/common/page_state.h"
82 #include "content/public/test/browser_test_utils.h" 84 #include "content/public/test/browser_test_utils.h"
83 #include "content/public/test/download_test_observer.h" 85 #include "content/public/test/download_test_observer.h"
84 #include "content/public/test/test_navigation_observer.h" 86 #include "content/public/test/test_navigation_observer.h"
85 #include "content/public/test/test_renderer_host.h" 87 #include "content/public/test/test_renderer_host.h"
86 #include "content/public/test/test_utils.h" 88 #include "content/public/test/test_utils.h"
89 #include "crypto/sha2.h"
87 #include "net/base/host_port_pair.h" 90 #include "net/base/host_port_pair.h"
88 #include "net/base/io_buffer.h" 91 #include "net/base/io_buffer.h"
89 #include "net/base/net_errors.h" 92 #include "net/base/net_errors.h"
93 #include "net/cert/asn1_util.h"
90 #include "net/cert/cert_status_flags.h" 94 #include "net/cert/cert_status_flags.h"
91 #include "net/cert/mock_cert_verifier.h" 95 #include "net/cert/mock_cert_verifier.h"
92 #include "net/cert/x509_certificate.h" 96 #include "net/cert/x509_certificate.h"
93 #include "net/dns/mock_host_resolver.h" 97 #include "net/dns/mock_host_resolver.h"
94 #include "net/http/http_response_headers.h" 98 #include "net/http/http_response_headers.h"
95 #include "net/ssl/ssl_info.h" 99 #include "net/ssl/ssl_info.h"
96 #include "net/test/cert_test_util.h" 100 #include "net/test/cert_test_util.h"
97 #include "net/test/embedded_test_server/embedded_test_server.h" 101 #include "net/test/embedded_test_server/embedded_test_server.h"
98 #include "net/test/embedded_test_server/request_handler_util.h" 102 #include "net/test/embedded_test_server/request_handler_util.h"
99 #include "net/test/spawned_test_server/spawned_test_server.h" 103 #include "net/test/spawned_test_server/spawned_test_server.h"
100 #include "net/test/test_certificate_data.h" 104 #include "net/test/test_certificate_data.h"
101 #include "net/test/test_data_directory.h" 105 #include "net/test/test_data_directory.h"
102 #include "net/url_request/url_request_context.h" 106 #include "net/url_request/url_request_context.h"
103 #include "net/url_request/url_request_filter.h" 107 #include "net/url_request/url_request_filter.h"
104 #include "net/url_request/url_request_job.h" 108 #include "net/url_request/url_request_job.h"
105 #include "net/url_request/url_request_test_util.h" 109 #include "net/url_request/url_request_test_util.h"
106 110
107 #if defined(USE_NSS_CERTS) 111 #if defined(USE_NSS_CERTS)
108 #include "chrome/browser/net/nss_context.h" 112 #include "chrome/browser/net/nss_context.h"
109 #include "net/base/crypto_module.h" 113 #include "net/base/crypto_module.h"
110 #include "net/cert/nss_cert_database.h" 114 #include "net/cert/nss_cert_database.h"
111 #endif // defined(USE_NSS_CERTS) 115 #endif // defined(USE_NSS_CERTS)
112 116
117 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
Bernhard Bauer 2017/02/07 10:53:03 Nit: Move this before USE_NSS_CERTS so the #ifdef
meacer 2017/02/07 20:22:50 Done.
118 #include "chrome/browser/ssl/captive_portal_blocking_page.h"
119 #endif
120
113 using base::ASCIIToUTF16; 121 using base::ASCIIToUTF16;
114 using chrome_browser_interstitials::SecurityInterstitialIDNTest; 122 using chrome_browser_interstitials::SecurityInterstitialIDNTest;
115 using content::InterstitialPage; 123 using content::InterstitialPage;
116 using content::NavigationController; 124 using content::NavigationController;
117 using content::NavigationEntry; 125 using content::NavigationEntry;
118 using content::SSLStatus; 126 using content::SSLStatus;
119 using content::WebContents; 127 using content::WebContents;
120 using web_modal::WebContentsModalDialogManager; 128 using web_modal::WebContentsModalDialogManager;
121 129
122 const base::FilePath::CharType kDocRoot[] = 130 const base::FilePath::CharType kDocRoot[] =
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(&callback_); 227 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(&callback_);
220 } 228 }
221 229
222 ~SSLInterstitialTimerObserver() { 230 ~SSLInterstitialTimerObserver() {
223 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(nullptr); 231 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(nullptr);
224 } 232 }
225 233
226 // Waits until the interstitial delay timer in SSLErrorHandler is started. 234 // Waits until the interstitial delay timer in SSLErrorHandler is started.
227 void WaitForTimerStarted() { message_loop_runner_->Run(); } 235 void WaitForTimerStarted() { message_loop_runner_->Run(); }
228 236
237 // Returns true if the interstitial delay timer has been started.
238 bool timer_started() const { return timer_started_; }
239
229 private: 240 private:
230 void OnTimerStarted(content::WebContents* web_contents) { 241 void OnTimerStarted(content::WebContents* web_contents) {
242 timer_started_ = true;
231 if (web_contents_ == web_contents) 243 if (web_contents_ == web_contents)
232 message_loop_runner_->Quit(); 244 message_loop_runner_->Quit();
233 } 245 }
234 246
247 bool timer_started_ = false;
235 const content::WebContents* web_contents_; 248 const content::WebContents* web_contents_;
236 SSLErrorHandler::TimerStartedCallback callback_; 249 SSLErrorHandler::TimerStartedCallback callback_;
237 250
238 std::unique_ptr<base::RunLoop> message_loop_runner_; 251 std::unique_ptr<base::RunLoop> message_loop_runner_;
239 252
240 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver); 253 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver);
241 }; 254 };
242 255
243 class HungJob : public net::URLRequestJob { 256 class HungJob : public net::URLRequestJob {
244 public: 257 public:
(...skipping 21 matching lines...) Expand all
266 private: 279 private:
267 DISALLOW_COPY_AND_ASSIGN(FaviconFilter); 280 DISALLOW_COPY_AND_ASSIGN(FaviconFilter);
268 }; 281 };
269 282
270 std::string EncodeQuery(const std::string& query) { 283 std::string EncodeQuery(const std::string& query) {
271 url::RawCanonOutputT<char> buffer; 284 url::RawCanonOutputT<char> buffer;
272 url::EncodeURIComponent(query.data(), query.size(), &buffer); 285 url::EncodeURIComponent(query.data(), query.size(), &buffer);
273 return std::string(buffer.data(), buffer.length()); 286 return std::string(buffer.data(), buffer.length());
274 } 287 }
275 288
289 // Returns the Sha256 hash of the SPKI of |cert|.
290 net::HashValue GetSPKIHash(net::X509Certificate* cert) {
291 std::string der_data;
292 EXPECT_TRUE(
Bernhard Bauer 2017/02/07 10:53:03 ASSERT_TRUE? If this fails, the subsequent checks
meacer 2017/02/07 20:22:50 Can't ASSERT_TRUE here since the function returns
293 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_data));
294 base::StringPiece der_bytes(der_data);
295 base::StringPiece spki_bytes;
296 EXPECT_TRUE(net::asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes));
297 net::HashValue sha256(net::HASH_VALUE_SHA256);
298 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length);
299 return sha256;
300 }
301
276 } // namespace 302 } // namespace
277 303
278 class SSLUITest : public InProcessBrowserTest { 304 class SSLUITest : public InProcessBrowserTest {
279 public: 305 public:
280 SSLUITest() 306 SSLUITest()
281 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), 307 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
282 https_server_expired_(net::EmbeddedTestServer::TYPE_HTTPS), 308 https_server_expired_(net::EmbeddedTestServer::TYPE_HTTPS),
283 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS), 309 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS),
284 wss_server_expired_(net::SpawnedTestServer::TYPE_WSS, 310 wss_server_expired_(net::SpawnedTestServer::TYPE_WSS,
285 SSLOptions(SSLOptions::CERT_EXPIRED), 311 SSLOptions(SSLOptions::CERT_EXPIRED),
(...skipping 15 matching lines...) Expand all
301 // authentication state. To avoid this non-determinism, add an 327 // authentication state. To avoid this non-determinism, add an
302 // interceptor to hang all favicon requests. 328 // interceptor to hang all favicon requests.
303 std::unique_ptr<net::URLRequestInterceptor> interceptor(new FaviconFilter); 329 std::unique_ptr<net::URLRequestInterceptor> interceptor(new FaviconFilter);
304 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 330 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
305 "https", "127.0.0.1", std::move(interceptor)); 331 "https", "127.0.0.1", std::move(interceptor));
306 interceptor.reset(new FaviconFilter); 332 interceptor.reset(new FaviconFilter);
307 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 333 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
308 "https", "localhost", std::move(interceptor)); 334 "https", "localhost", std::move(interceptor));
309 } 335 }
310 336
337 void SetUp() override {
338 InProcessBrowserTest::SetUp();
339 SSLErrorHandler::ResetConfigForTesting();
340 }
341
342 void TearDown() override {
343 SSLErrorHandler::ResetConfigForTesting();
344 InProcessBrowserTest::TearDown();
345 }
346
311 void SetUpCommandLine(base::CommandLine* command_line) override { 347 void SetUpCommandLine(base::CommandLine* command_line) override {
312 // Browser will both run and display insecure content. 348 // Browser will both run and display insecure content.
313 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); 349 command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
314 // Use process-per-site so that navigating to a same-site page in a 350 // Use process-per-site so that navigating to a same-site page in a
315 // new tab will use the same process. 351 // new tab will use the same process.
316 command_line->AppendSwitch(switches::kProcessPerSite); 352 command_line->AppendSwitch(switches::kProcessPerSite);
317 } 353 }
318 354
319 void CheckAuthenticatedState(WebContents* tab, 355 void CheckAuthenticatedState(WebContents* tab,
320 int expected_authentication_state) { 356 int expected_authentication_state) {
(...skipping 3557 matching lines...) Expand 10 before | Expand all | Expand 10 after
3878 IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreLocalhostCertErrors, 3914 IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreLocalhostCertErrors,
3879 NoCrashOnLoadWithNoNavigationEntry) { 3915 NoCrashOnLoadWithNoNavigationEntry) {
3880 ASSERT_TRUE(embedded_test_server()->Start()); 3916 ASSERT_TRUE(embedded_test_server()->Start());
3881 3917
3882 ui_test_utils::NavigateToURL( 3918 ui_test_utils::NavigateToURL(
3883 browser(), embedded_test_server()->GetURL("/ssl/google.html")); 3919 browser(), embedded_test_server()->GetURL("/ssl/google.html"));
3884 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 3920 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3885 ASSERT_TRUE(content::ExecuteScript(tab, "window.open()")); 3921 ASSERT_TRUE(content::ExecuteScript(tab, "window.open()"));
3886 } 3922 }
3887 3923
3924 // Put captive portal related tests under a different namespace for nicer
3925 // pattern matching.
3926 using SSLUICaptivePortalListTest = SSLUITest;
3927
3928 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
3929
3930 // Tests that the captive portal certificate list is not used when the feature
3931 // is disabled via Finch. The list is passed to SSLErrorHandler via a proto.
3932 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest,
3933 CaptivePortalCertificateList_Disabled) {
3934 base::test::ScopedFeatureList scoped_feature_list;
3935 // Use InitFromCommandLine instead of InitAndDisableFeature to avoid making
3936 // the feature public in SSLErrorHandler header.
3937 scoped_feature_list.InitFromCommandLine(
3938 "" /* enabled */, "CaptivePortalCertificateList" /* disabled */);
Bernhard Bauer 2017/02/07 10:53:03 Nit: Use an empty std::string() constructor to sav
meacer 2017/02/07 20:22:50 Done.
3939
3940 ASSERT_TRUE(https_server_mismatched_.Start());
3941 base::HistogramTester histograms;
3942
3943 // Mark the server's cert as a captive portal cert.
3944 const net::HashValue server_spki_hash =
3945 GetSPKIHash(https_server_mismatched_.GetCertificate().get());
3946 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
3947 config_proto.add_captive_portal_cert()->set_sha256_hash(
3948 server_spki_hash.ToString());
3949 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
3950
3951 // Navigate to an unsafe page on the server. A normal SSL interstitial should
3952 // be displayed since CaptivePortalCertificateList feature is disabled.
3953 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3954 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
3955 ui_test_utils::NavigateToURL(
3956 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
3957 content::WaitForInterstitialAttach(tab);
3958
3959 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
3960 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
3961 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
3962 EXPECT_TRUE(interstitial_timer_observer.timer_started());
3963
3964 // Check that the histogram for the SSL interstitial was recorded.
3965 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
3966 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
3967 SSLErrorHandler::HANDLE_ALL, 1);
3968 histograms.ExpectBucketCount(
3969 SSLErrorHandler::GetHistogramNameForTesting(),
3970 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
3971 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
3972 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 0);
3973 }
3974
3975 // Tests that the captive portal certificate list is used when the feature
3976 // is enabled via Finch. The list is passed to SSLErrorHandler via a proto.
3977 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest,
3978 CaptivePortalCertificateList_Enabled_FromProto) {
3979 base::test::ScopedFeatureList scoped_feature_list;
3980 scoped_feature_list.InitFromCommandLine(
3981 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
3982
3983 ASSERT_TRUE(https_server_mismatched_.Start());
3984 base::HistogramTester histograms;
3985
3986 // Mark the server's cert as a captive portal cert.
3987 const net::HashValue server_spki_hash =
3988 GetSPKIHash(https_server_mismatched_.GetCertificate().get());
3989 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
3990 config_proto.add_captive_portal_cert()->set_sha256_hash(
3991 server_spki_hash.ToString());
3992 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
3993
3994 // Navigate to an unsafe page on the server. The captive portal interstitial
3995 // should be displayed since CaptivePortalCertificateList feature is enabled.
3996 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3997 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
3998 ui_test_utils::NavigateToURL(
3999 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
4000 content::WaitForInterstitialAttach(tab);
4001
4002 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4003 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
4004 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4005 EXPECT_FALSE(interstitial_timer_observer.timer_started());
4006
4007 // Check that the histogram for the captive portal cert was recorded.
4008 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
4009 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4010 SSLErrorHandler::HANDLE_ALL, 1);
4011 histograms.ExpectBucketCount(
4012 SSLErrorHandler::GetHistogramNameForTesting(),
4013 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
4014 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4015 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
4016 }
4017
4018 namespace {
4019
4020 // Test class that mimics a URL request with a certificate whose SPKI hash is in
4021 // ssl_error_assistant.asciipb resource. A better way of testing the SPKI hashes
4022 // inside the resource bundle would be to serve the actual certificate from the
4023 // embedded test server, but the test server can only serve a limited number of
4024 // predefined certificates.
4025 class SSLUICaptivePortalListResourceBundleTest
4026 : public CertVerifierBrowserTest {
4027 public:
4028 SSLUICaptivePortalListResourceBundleTest()
4029 : CertVerifierBrowserTest(),
4030 https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
4031 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS) {
4032 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
4033
4034 https_server_mismatched_.SetSSLConfig(
4035 net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
4036 https_server_mismatched_.AddDefaultHandlers(base::FilePath(kDocRoot));
4037 }
4038
4039 void SetUp() override {
4040 CertVerifierBrowserTest::SetUp();
4041 SSLErrorHandler::ResetConfigForTesting();
4042 SetUpCertVerifier(0, net::OK);
4043 }
4044
4045 void TearDown() override {
4046 SSLErrorHandler::ResetConfigForTesting();
4047 CertVerifierBrowserTest::TearDown();
4048 }
4049
4050 protected:
4051 void SetUpCertVerifier(net::CertStatus cert_status, int net_result) {
4052 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
4053 net::CertVerifyResult verify_result;
4054 verify_result.is_issued_by_known_root =
4055 (net_result != net::ERR_CERT_AUTHORITY_INVALID);
4056 verify_result.verified_cert = cert;
4057 verify_result.cert_status = cert_status;
4058
4059 // Set the SPKI hash to captive-portal.badssl.com leaf certificate. This
4060 // doesn't match the actual cert (ok_cert.pem) but is good enough for
4061 // testing.
4062 net::HashValue hash;
4063 ASSERT_TRUE(
4064 hash.FromString("sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI="));
4065 verify_result.public_key_hashes.push_back(hash);
4066 mock_cert_verifier()->AddResultForCert(cert, verify_result, net_result);
4067 }
4068
4069 net::EmbeddedTestServer* https_server() { return &https_server_; }
4070 net::EmbeddedTestServer* https_server_mismatched() {
4071 return &https_server_mismatched_;
4072 }
4073
4074 private:
4075 net::EmbeddedTestServer https_server_;
4076 net::EmbeddedTestServer https_server_mismatched_;
4077 };
4078
4079 } // namespace
4080
4081 // Same as CaptivePortalCertificateList_Enabled_FromProto, but this time the
4082 // cert's SPKI hash is listed in ssl_error_assistant.asciipb.
4083 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest,
4084 Enabled_FromResource) {
4085 base::test::ScopedFeatureList scoped_feature_list;
4086 scoped_feature_list.InitFromCommandLine(
4087 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
4088 ASSERT_TRUE(https_server()->Start());
4089 base::HistogramTester histograms;
4090
4091 // Mark the server's cert as a captive portal cert.
4092 SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID,
4093 net::ERR_CERT_COMMON_NAME_INVALID);
4094
4095 // Navigate to an unsafe page on the server. The captive portal interstitial
4096 // should be displayed since CaptivePortalCertificateList feature is enabled.
4097 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
4098 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
4099 ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
4100 content::WaitForInterstitialAttach(tab);
4101
4102 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4103 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
4104 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4105 EXPECT_FALSE(interstitial_timer_observer.timer_started());
4106
4107 // Check that the histogram for the captive portal cert was recorded.
4108 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
4109 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4110 SSLErrorHandler::HANDLE_ALL, 1);
4111 histograms.ExpectBucketCount(
4112 SSLErrorHandler::GetHistogramNameForTesting(),
4113 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
4114 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4115 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
4116 }
4117
4118 // Same as SSLUICaptivePortalNameMismatchTest, but this time the error is
4119 // authority-invalid. Captive portal interstitial should not be shown.
4120 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest,
4121 Enabled_FromResource_AuthorityInvalid) {
4122 base::test::ScopedFeatureList scoped_feature_list;
4123 scoped_feature_list.InitFromCommandLine(
4124 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
4125 ASSERT_TRUE(https_server()->Start());
4126 base::HistogramTester histograms;
4127
4128 // Set interstitial delay to zero.
4129 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
4130 // Mark the server's cert as a captive portal cert, but with an
4131 // authority-invalid error.
4132 SetUpCertVerifier(net::CERT_STATUS_AUTHORITY_INVALID,
4133 net::ERR_CERT_AUTHORITY_INVALID);
4134
4135 // Navigate to an unsafe page on the server. CaptivePortalCertificateList
4136 // feature is enabled but the error is not a name mismatch, so a generic SSL
4137 // interstitial should be displayed.
4138 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
4139 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
4140 ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
4141 content::WaitForInterstitialAttach(tab);
4142
4143 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4144 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
4145 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4146 EXPECT_TRUE(interstitial_timer_observer.timer_started());
4147
4148 // Check that the histogram for the captive portal cert was recorded.
4149 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
4150 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4151 SSLErrorHandler::HANDLE_ALL, 1);
4152 histograms.ExpectBucketCount(
4153 SSLErrorHandler::GetHistogramNameForTesting(),
4154 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
4155 }
4156
4157 #else
4158
4159 // Tests that the captive portal certificate list is not used when captive
4160 // portal checks are disabled by build, even if the captive portal certificate
4161 // list feature is enabled via Finch. The list is passed to SSLErrorHandler via
4162 // a proto.
4163 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, PortalChecksDisabled) {
4164 base::test::ScopedFeatureList scoped_feature_list;
4165 scoped_feature_list.InitFromCommandLine(
4166 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
4167
4168 ASSERT_TRUE(https_server_mismatched_.Start());
4169 base::HistogramTester histograms;
4170
4171 // Mark the server's cert as a captive portal cert.
4172 const net::HashValue server_spki_hash =
4173 GetSPKIHash(https_server_mismatched_.GetCertificate().get());
4174 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
4175 config_proto.add_captive_portal_cert()->set_sha256_hash(
4176 server_spki_hash.ToString());
4177 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
4178
4179 // Navigate to an unsafe page on the server. The captive portal interstitial
4180 // should be displayed since CaptivePortalCertificateList feature is enabled.
4181 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
4182 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
4183 ui_test_utils::NavigateToURL(
4184 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
4185 content::WaitForInterstitialAttach(tab);
4186
4187 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4188 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
4189 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4190 EXPECT_FALSE(interstitial_timer_observer.timer_started());
4191
4192 // Check that the histogram for the captive portal cert was recorded.
4193 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
4194 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4195 SSLErrorHandler::HANDLE_ALL, 1);
4196 histograms.ExpectBucketCount(
4197 SSLErrorHandler::GetHistogramNameForTesting(),
4198 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
4199 }
4200
4201 #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
4202
3888 // TODO(jcampan): more tests to do below. 4203 // TODO(jcampan): more tests to do below.
3889 4204
3890 // Visit a page over https that contains a frame with a redirect. 4205 // Visit a page over https that contains a frame with a redirect.
3891 4206
3892 // XMLHttpRequest insecure content in synchronous mode. 4207 // XMLHttpRequest insecure content in synchronous mode.
3893 4208
3894 // XMLHttpRequest insecure content in asynchronous mode. 4209 // XMLHttpRequest insecure content in asynchronous mode.
3895 4210
3896 // XMLHttpRequest over bad ssl in synchronous mode. 4211 // XMLHttpRequest over bad ssl in synchronous mode.
3897 4212
3898 // XMLHttpRequest over OK ssl in synchronous mode. 4213 // XMLHttpRequest over OK ssl in synchronous mode.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698