| OLD | NEW |
| 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 Loading... |
| 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 |
| 111 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 112 #include "chrome/browser/ssl/captive_portal_blocking_page.h" |
| 113 #endif |
| 114 |
| 107 #if defined(USE_NSS_CERTS) | 115 #if defined(USE_NSS_CERTS) |
| 108 #include "chrome/browser/net/nss_context.h" | 116 #include "chrome/browser/net/nss_context.h" |
| 109 #include "net/base/crypto_module.h" | 117 #include "net/base/crypto_module.h" |
| 110 #include "net/cert/nss_cert_database.h" | 118 #include "net/cert/nss_cert_database.h" |
| 111 #endif // defined(USE_NSS_CERTS) | 119 #endif // defined(USE_NSS_CERTS) |
| 112 | 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; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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( |
| 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 Loading... |
| 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 Loading... |
| 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 std::string() /* enabled */, |
| 3939 "CaptivePortalCertificateList" /* disabled */); |
| 3940 |
| 3941 ASSERT_TRUE(https_server_mismatched_.Start()); |
| 3942 base::HistogramTester histograms; |
| 3943 |
| 3944 // Mark the server's cert as a captive portal cert. |
| 3945 const net::HashValue server_spki_hash = |
| 3946 GetSPKIHash(https_server_mismatched_.GetCertificate().get()); |
| 3947 chrome_browser_ssl::SSLErrorAssistantConfig config_proto; |
| 3948 config_proto.add_captive_portal_cert()->set_sha256_hash( |
| 3949 server_spki_hash.ToString()); |
| 3950 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); |
| 3951 |
| 3952 // Navigate to an unsafe page on the server. A normal SSL interstitial should |
| 3953 // be displayed since CaptivePortalCertificateList feature is disabled. |
| 3954 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 3955 SSLInterstitialTimerObserver interstitial_timer_observer(tab); |
| 3956 ui_test_utils::NavigateToURL( |
| 3957 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html")); |
| 3958 content::WaitForInterstitialAttach(tab); |
| 3959 |
| 3960 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 3961 ASSERT_EQ(SSLBlockingPage::kTypeForTesting, |
| 3962 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 3963 EXPECT_TRUE(interstitial_timer_observer.timer_started()); |
| 3964 |
| 3965 // Check that the histogram for the SSL interstitial was recorded. |
| 3966 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); |
| 3967 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 3968 SSLErrorHandler::HANDLE_ALL, 1); |
| 3969 histograms.ExpectBucketCount( |
| 3970 SSLErrorHandler::GetHistogramNameForTesting(), |
| 3971 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); |
| 3972 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 3973 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 0); |
| 3974 } |
| 3975 |
| 3976 // Tests that the captive portal certificate list is used when the feature |
| 3977 // is enabled via Finch. The list is passed to SSLErrorHandler via a proto. |
| 3978 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, |
| 3979 CaptivePortalCertificateList_Enabled_FromProto) { |
| 3980 base::test::ScopedFeatureList scoped_feature_list; |
| 3981 scoped_feature_list.InitFromCommandLine( |
| 3982 "CaptivePortalCertificateList" /* enabled */, |
| 3983 std::string() /* disabled */); |
| 3984 |
| 3985 ASSERT_TRUE(https_server_mismatched_.Start()); |
| 3986 base::HistogramTester histograms; |
| 3987 |
| 3988 // Mark the server's cert as a captive portal cert. |
| 3989 const net::HashValue server_spki_hash = |
| 3990 GetSPKIHash(https_server_mismatched_.GetCertificate().get()); |
| 3991 chrome_browser_ssl::SSLErrorAssistantConfig config_proto; |
| 3992 config_proto.add_captive_portal_cert()->set_sha256_hash( |
| 3993 server_spki_hash.ToString()); |
| 3994 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); |
| 3995 |
| 3996 // Navigate to an unsafe page on the server. The captive portal interstitial |
| 3997 // should be displayed since CaptivePortalCertificateList feature is enabled. |
| 3998 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 3999 SSLInterstitialTimerObserver interstitial_timer_observer(tab); |
| 4000 ui_test_utils::NavigateToURL( |
| 4001 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html")); |
| 4002 content::WaitForInterstitialAttach(tab); |
| 4003 |
| 4004 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 4005 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting, |
| 4006 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 4007 EXPECT_FALSE(interstitial_timer_observer.timer_started()); |
| 4008 |
| 4009 // Check that the histogram for the captive portal cert was recorded. |
| 4010 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3); |
| 4011 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4012 SSLErrorHandler::HANDLE_ALL, 1); |
| 4013 histograms.ExpectBucketCount( |
| 4014 SSLErrorHandler::GetHistogramNameForTesting(), |
| 4015 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1); |
| 4016 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4017 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1); |
| 4018 } |
| 4019 |
| 4020 namespace { |
| 4021 |
| 4022 // Test class that mimics a URL request with a certificate whose SPKI hash is in |
| 4023 // ssl_error_assistant.asciipb resource. A better way of testing the SPKI hashes |
| 4024 // inside the resource bundle would be to serve the actual certificate from the |
| 4025 // embedded test server, but the test server can only serve a limited number of |
| 4026 // predefined certificates. |
| 4027 class SSLUICaptivePortalListResourceBundleTest |
| 4028 : public CertVerifierBrowserTest { |
| 4029 public: |
| 4030 SSLUICaptivePortalListResourceBundleTest() |
| 4031 : CertVerifierBrowserTest(), |
| 4032 https_server_(net::EmbeddedTestServer::TYPE_HTTPS), |
| 4033 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS) { |
| 4034 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); |
| 4035 |
| 4036 https_server_mismatched_.SetSSLConfig( |
| 4037 net::EmbeddedTestServer::CERT_MISMATCHED_NAME); |
| 4038 https_server_mismatched_.AddDefaultHandlers(base::FilePath(kDocRoot)); |
| 4039 } |
| 4040 |
| 4041 void SetUp() override { |
| 4042 CertVerifierBrowserTest::SetUp(); |
| 4043 SSLErrorHandler::ResetConfigForTesting(); |
| 4044 SetUpCertVerifier(0, net::OK); |
| 4045 } |
| 4046 |
| 4047 void TearDown() override { |
| 4048 SSLErrorHandler::ResetConfigForTesting(); |
| 4049 CertVerifierBrowserTest::TearDown(); |
| 4050 } |
| 4051 |
| 4052 protected: |
| 4053 void SetUpCertVerifier(net::CertStatus cert_status, int net_result) { |
| 4054 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); |
| 4055 net::CertVerifyResult verify_result; |
| 4056 verify_result.is_issued_by_known_root = |
| 4057 (net_result != net::ERR_CERT_AUTHORITY_INVALID); |
| 4058 verify_result.verified_cert = cert; |
| 4059 verify_result.cert_status = cert_status; |
| 4060 |
| 4061 // Set the SPKI hash to captive-portal.badssl.com leaf certificate. This |
| 4062 // doesn't match the actual cert (ok_cert.pem) but is good enough for |
| 4063 // testing. |
| 4064 net::HashValue hash; |
| 4065 ASSERT_TRUE( |
| 4066 hash.FromString("sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI=")); |
| 4067 verify_result.public_key_hashes.push_back(hash); |
| 4068 mock_cert_verifier()->AddResultForCert(cert, verify_result, net_result); |
| 4069 } |
| 4070 |
| 4071 net::EmbeddedTestServer* https_server() { return &https_server_; } |
| 4072 net::EmbeddedTestServer* https_server_mismatched() { |
| 4073 return &https_server_mismatched_; |
| 4074 } |
| 4075 |
| 4076 private: |
| 4077 net::EmbeddedTestServer https_server_; |
| 4078 net::EmbeddedTestServer https_server_mismatched_; |
| 4079 }; |
| 4080 |
| 4081 } // namespace |
| 4082 |
| 4083 // Same as CaptivePortalCertificateList_Enabled_FromProto, but this time the |
| 4084 // cert's SPKI hash is listed in ssl_error_assistant.asciipb. |
| 4085 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, |
| 4086 Enabled_FromResource) { |
| 4087 base::test::ScopedFeatureList scoped_feature_list; |
| 4088 scoped_feature_list.InitFromCommandLine( |
| 4089 "CaptivePortalCertificateList" /* enabled */, |
| 4090 std::string() /* disabled */); |
| 4091 ASSERT_TRUE(https_server()->Start()); |
| 4092 base::HistogramTester histograms; |
| 4093 |
| 4094 // Mark the server's cert as a captive portal cert. |
| 4095 SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID, |
| 4096 net::ERR_CERT_COMMON_NAME_INVALID); |
| 4097 |
| 4098 // Navigate to an unsafe page on the server. The captive portal interstitial |
| 4099 // should be displayed since CaptivePortalCertificateList feature is enabled. |
| 4100 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 4101 SSLInterstitialTimerObserver interstitial_timer_observer(tab); |
| 4102 ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/")); |
| 4103 content::WaitForInterstitialAttach(tab); |
| 4104 |
| 4105 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 4106 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting, |
| 4107 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 4108 EXPECT_FALSE(interstitial_timer_observer.timer_started()); |
| 4109 |
| 4110 // Check that the histogram for the captive portal cert was recorded. |
| 4111 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3); |
| 4112 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4113 SSLErrorHandler::HANDLE_ALL, 1); |
| 4114 histograms.ExpectBucketCount( |
| 4115 SSLErrorHandler::GetHistogramNameForTesting(), |
| 4116 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1); |
| 4117 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4118 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1); |
| 4119 } |
| 4120 |
| 4121 // Same as SSLUICaptivePortalNameMismatchTest, but this time the error is |
| 4122 // authority-invalid. Captive portal interstitial should not be shown. |
| 4123 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, |
| 4124 Enabled_FromResource_AuthorityInvalid) { |
| 4125 base::test::ScopedFeatureList scoped_feature_list; |
| 4126 scoped_feature_list.InitFromCommandLine( |
| 4127 "CaptivePortalCertificateList" /* enabled */, |
| 4128 std::string() /* disabled */); |
| 4129 ASSERT_TRUE(https_server()->Start()); |
| 4130 base::HistogramTester histograms; |
| 4131 |
| 4132 // Set interstitial delay to zero. |
| 4133 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta()); |
| 4134 // Mark the server's cert as a captive portal cert, but with an |
| 4135 // authority-invalid error. |
| 4136 SetUpCertVerifier(net::CERT_STATUS_AUTHORITY_INVALID, |
| 4137 net::ERR_CERT_AUTHORITY_INVALID); |
| 4138 |
| 4139 // Navigate to an unsafe page on the server. CaptivePortalCertificateList |
| 4140 // feature is enabled but the error is not a name mismatch, so a generic SSL |
| 4141 // interstitial should be displayed. |
| 4142 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 4143 SSLInterstitialTimerObserver interstitial_timer_observer(tab); |
| 4144 ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/")); |
| 4145 content::WaitForInterstitialAttach(tab); |
| 4146 |
| 4147 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 4148 ASSERT_EQ(SSLBlockingPage::kTypeForTesting, |
| 4149 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 4150 EXPECT_TRUE(interstitial_timer_observer.timer_started()); |
| 4151 |
| 4152 // Check that the histogram for the captive portal cert was recorded. |
| 4153 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); |
| 4154 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4155 SSLErrorHandler::HANDLE_ALL, 1); |
| 4156 histograms.ExpectBucketCount( |
| 4157 SSLErrorHandler::GetHistogramNameForTesting(), |
| 4158 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); |
| 4159 } |
| 4160 |
| 4161 #else |
| 4162 |
| 4163 // Tests that the captive portal certificate list is not used when captive |
| 4164 // portal checks are disabled by build, even if the captive portal certificate |
| 4165 // list feature is enabled via Finch. The list is passed to SSLErrorHandler via |
| 4166 // a proto. |
| 4167 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, PortalChecksDisabled) { |
| 4168 base::test::ScopedFeatureList scoped_feature_list; |
| 4169 scoped_feature_list.InitFromCommandLine( |
| 4170 "CaptivePortalCertificateList" /* enabled */, |
| 4171 std::string() /* disabled */); |
| 4172 |
| 4173 ASSERT_TRUE(https_server_mismatched_.Start()); |
| 4174 base::HistogramTester histograms; |
| 4175 |
| 4176 // Mark the server's cert as a captive portal cert. |
| 4177 const net::HashValue server_spki_hash = |
| 4178 GetSPKIHash(https_server_mismatched_.GetCertificate().get()); |
| 4179 chrome_browser_ssl::SSLErrorAssistantConfig config_proto; |
| 4180 config_proto.add_captive_portal_cert()->set_sha256_hash( |
| 4181 server_spki_hash.ToString()); |
| 4182 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto); |
| 4183 |
| 4184 // Navigate to an unsafe page on the server. The captive portal interstitial |
| 4185 // should be displayed since CaptivePortalCertificateList feature is enabled. |
| 4186 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); |
| 4187 SSLInterstitialTimerObserver interstitial_timer_observer(tab); |
| 4188 ui_test_utils::NavigateToURL( |
| 4189 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html")); |
| 4190 content::WaitForInterstitialAttach(tab); |
| 4191 |
| 4192 InterstitialPage* interstitial_page = tab->GetInterstitialPage(); |
| 4193 ASSERT_EQ(SSLBlockingPage::kTypeForTesting, |
| 4194 interstitial_page->GetDelegateForTesting()->GetTypeForTesting()); |
| 4195 EXPECT_FALSE(interstitial_timer_observer.timer_started()); |
| 4196 |
| 4197 // Check that the histogram for the captive portal cert was recorded. |
| 4198 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); |
| 4199 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), |
| 4200 SSLErrorHandler::HANDLE_ALL, 1); |
| 4201 histograms.ExpectBucketCount( |
| 4202 SSLErrorHandler::GetHistogramNameForTesting(), |
| 4203 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); |
| 4204 } |
| 4205 |
| 4206 #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| 4207 |
| 3888 // TODO(jcampan): more tests to do below. | 4208 // TODO(jcampan): more tests to do below. |
| 3889 | 4209 |
| 3890 // Visit a page over https that contains a frame with a redirect. | 4210 // Visit a page over https that contains a frame with a redirect. |
| 3891 | 4211 |
| 3892 // XMLHttpRequest insecure content in synchronous mode. | 4212 // XMLHttpRequest insecure content in synchronous mode. |
| 3893 | 4213 |
| 3894 // XMLHttpRequest insecure content in asynchronous mode. | 4214 // XMLHttpRequest insecure content in asynchronous mode. |
| 3895 | 4215 |
| 3896 // XMLHttpRequest over bad ssl in synchronous mode. | 4216 // XMLHttpRequest over bad ssl in synchronous mode. |
| 3897 | 4217 |
| 3898 // XMLHttpRequest over OK ssl in synchronous mode. | 4218 // XMLHttpRequest over OK ssl in synchronous mode. |
| OLD | NEW |