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

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

Issue 2620203003: Add initial version of captive portal list checking. (Closed)
Patch Set: 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)
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[] =
123 FILE_PATH_LITERAL("chrome/test/data"); 131 FILE_PATH_LITERAL("chrome/test/data");
124 132
125 namespace { 133 namespace {
126 134
135 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
136 // A hostname that will trigger a captive portal interstitial. The actual value
137 // isn't important.
138 const char kCaptivePortalHostname[] = "captive-portal.test";
139 #endif
140
127 enum ProceedDecision { 141 enum ProceedDecision {
128 SSL_INTERSTITIAL_PROCEED, 142 SSL_INTERSTITIAL_PROCEED,
129 SSL_INTERSTITIAL_DO_NOT_PROCEED 143 SSL_INTERSTITIAL_DO_NOT_PROCEED
130 }; 144 };
131 145
132 namespace AuthState { 146 namespace AuthState {
133 147
134 enum AuthStateFlags { 148 enum AuthStateFlags {
135 NONE = 0, 149 NONE = 0,
136 DISPLAYED_INSECURE_CONTENT = 1 << 0, 150 DISPLAYED_INSECURE_CONTENT = 1 << 0,
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(&callback_); 233 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(&callback_);
220 } 234 }
221 235
222 ~SSLInterstitialTimerObserver() { 236 ~SSLInterstitialTimerObserver() {
223 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(nullptr); 237 SSLErrorHandler::SetInterstitialTimerStartedCallbackForTesting(nullptr);
224 } 238 }
225 239
226 // Waits until the interstitial delay timer in SSLErrorHandler is started. 240 // Waits until the interstitial delay timer in SSLErrorHandler is started.
227 void WaitForTimerStarted() { message_loop_runner_->Run(); } 241 void WaitForTimerStarted() { message_loop_runner_->Run(); }
228 242
243 // Returns true if the interstitial delay timer has been started.
244 bool timer_started() const { return timer_started_; }
245
229 private: 246 private:
230 void OnTimerStarted(content::WebContents* web_contents) { 247 void OnTimerStarted(content::WebContents* web_contents) {
248 timer_started_ = true;
231 if (web_contents_ == web_contents) 249 if (web_contents_ == web_contents)
232 message_loop_runner_->Quit(); 250 message_loop_runner_->Quit();
233 } 251 }
234 252
253 bool timer_started_ = false;
235 const content::WebContents* web_contents_; 254 const content::WebContents* web_contents_;
236 SSLErrorHandler::TimerStartedCallback callback_; 255 SSLErrorHandler::TimerStartedCallback callback_;
237 256
238 std::unique_ptr<base::RunLoop> message_loop_runner_; 257 std::unique_ptr<base::RunLoop> message_loop_runner_;
239 258
240 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver); 259 DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver);
241 }; 260 };
242 261
243 class HungJob : public net::URLRequestJob { 262 class HungJob : public net::URLRequestJob {
244 public: 263 public:
(...skipping 21 matching lines...) Expand all
266 private: 285 private:
267 DISALLOW_COPY_AND_ASSIGN(FaviconFilter); 286 DISALLOW_COPY_AND_ASSIGN(FaviconFilter);
268 }; 287 };
269 288
270 std::string EncodeQuery(const std::string& query) { 289 std::string EncodeQuery(const std::string& query) {
271 url::RawCanonOutputT<char> buffer; 290 url::RawCanonOutputT<char> buffer;
272 url::EncodeURIComponent(query.data(), query.size(), &buffer); 291 url::EncodeURIComponent(query.data(), query.size(), &buffer);
273 return std::string(buffer.data(), buffer.length()); 292 return std::string(buffer.data(), buffer.length());
274 } 293 }
275 294
295 // Returns the Sha256 hash of the SPKI of |cert|.
296 net::HashValue GetSPKIHash(net::X509Certificate* cert) {
297 std::string der_data;
298 EXPECT_TRUE(
299 net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_data));
300 base::StringPiece der_bytes(der_data);
301 base::StringPiece spki_bytes;
302 EXPECT_TRUE(net::asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes));
303 net::HashValue sha256(net::HASH_VALUE_SHA256);
304 crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length);
305 return sha256;
306 }
307
276 } // namespace 308 } // namespace
277 309
278 class SSLUITest : public InProcessBrowserTest { 310 class SSLUITest : public InProcessBrowserTest {
279 public: 311 public:
280 SSLUITest() 312 SSLUITest()
281 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), 313 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
282 https_server_expired_(net::EmbeddedTestServer::TYPE_HTTPS), 314 https_server_expired_(net::EmbeddedTestServer::TYPE_HTTPS),
283 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS), 315 https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS),
284 wss_server_expired_(net::SpawnedTestServer::TYPE_WSS, 316 wss_server_expired_(net::SpawnedTestServer::TYPE_WSS,
285 SSLOptions(SSLOptions::CERT_EXPIRED), 317 SSLOptions(SSLOptions::CERT_EXPIRED),
(...skipping 15 matching lines...) Expand all
301 // authentication state. To avoid this non-determinism, add an 333 // authentication state. To avoid this non-determinism, add an
302 // interceptor to hang all favicon requests. 334 // interceptor to hang all favicon requests.
303 std::unique_ptr<net::URLRequestInterceptor> interceptor(new FaviconFilter); 335 std::unique_ptr<net::URLRequestInterceptor> interceptor(new FaviconFilter);
304 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 336 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
305 "https", "127.0.0.1", std::move(interceptor)); 337 "https", "127.0.0.1", std::move(interceptor));
306 interceptor.reset(new FaviconFilter); 338 interceptor.reset(new FaviconFilter);
307 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( 339 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
308 "https", "localhost", std::move(interceptor)); 340 "https", "localhost", std::move(interceptor));
309 } 341 }
310 342
343 void SetUp() override {
344 InProcessBrowserTest::SetUp();
345 SSLErrorHandler::ResetConfigForTesting();
Ryan Sleevi 2017/02/02 02:24:36 I believe you also should do this in TearDown(), a
meacer 2017/02/06 23:39:17 Done.
346 }
347
311 void SetUpCommandLine(base::CommandLine* command_line) override { 348 void SetUpCommandLine(base::CommandLine* command_line) override {
312 // Browser will both run and display insecure content. 349 // Browser will both run and display insecure content.
313 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); 350 command_line->AppendSwitch(switches::kAllowRunningInsecureContent);
314 // Use process-per-site so that navigating to a same-site page in a 351 // Use process-per-site so that navigating to a same-site page in a
315 // new tab will use the same process. 352 // new tab will use the same process.
316 command_line->AppendSwitch(switches::kProcessPerSite); 353 command_line->AppendSwitch(switches::kProcessPerSite);
317 } 354 }
318 355
319 void CheckAuthenticatedState(WebContents* tab, 356 void CheckAuthenticatedState(WebContents* tab,
320 int expected_authentication_state) { 357 int expected_authentication_state) {
(...skipping 3557 matching lines...) Expand 10 before | Expand all | Expand 10 after
3878 IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreLocalhostCertErrors, 3915 IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreLocalhostCertErrors,
3879 NoCrashOnLoadWithNoNavigationEntry) { 3916 NoCrashOnLoadWithNoNavigationEntry) {
3880 ASSERT_TRUE(embedded_test_server()->Start()); 3917 ASSERT_TRUE(embedded_test_server()->Start());
3881 3918
3882 ui_test_utils::NavigateToURL( 3919 ui_test_utils::NavigateToURL(
3883 browser(), embedded_test_server()->GetURL("/ssl/google.html")); 3920 browser(), embedded_test_server()->GetURL("/ssl/google.html"));
3884 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 3921 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3885 ASSERT_TRUE(content::ExecuteScript(tab, "window.open()")); 3922 ASSERT_TRUE(content::ExecuteScript(tab, "window.open()"));
3886 } 3923 }
3887 3924
3925 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
3926
3927 IN_PROC_BROWSER_TEST_F(SSLUITest, CaptivePortalCertificateList_Disabled) {
estark 2017/02/03 07:24:07 optional nit: for this and the other tests, I like
meacer 2017/02/06 23:39:17 Done.
3928 base::test::ScopedFeatureList scoped_feature_list;
3929 scoped_feature_list.InitFromCommandLine(
estark 2017/02/03 07:24:07 optional nit: I'd find InitAndDisableFeature() a b
meacer 2017/02/06 23:39:17 I initially wanted to use it too, but it requires
3930 "" /* enabled */, "CaptivePortalCertificateList" /* disabled */);
3931
3932 ASSERT_TRUE(https_server_mismatched_.Start());
3933 base::HistogramTester histograms;
3934
3935 // Mark the server's cert as a captive portal cert.
3936 const net::HashValue server_spki_hash =
3937 GetSPKIHash(https_server_mismatched_.GetCertificate().get());
3938 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
3939 config_proto.add_captive_portal_cert()->set_sha256_hash(
3940 server_spki_hash.ToString());
3941 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
3942
3943 // Navigate to an unsafe page on the server. A normal SSL interstitial should
3944 // be displayed since CaptivePortalCertificateList feature is disabled.
3945 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3946 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
3947 ui_test_utils::NavigateToURL(
3948 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
3949 content::WaitForInterstitialAttach(tab);
3950
3951 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
3952 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
3953 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
3954 EXPECT_TRUE(interstitial_timer_observer.timer_started());
3955
3956 // Check that the histogram for the SSL interstitial was recorded.
3957 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
3958 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
3959 SSLErrorHandler::HANDLE_ALL, 1);
3960 histograms.ExpectBucketCount(
3961 SSLErrorHandler::GetHistogramNameForTesting(),
3962 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
3963 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
3964 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 0);
3965 }
3966
3967 IN_PROC_BROWSER_TEST_F(SSLUITest,
3968 CaptivePortalCertificateList_Enabled_FromProto) {
3969 base::test::ScopedFeatureList scoped_feature_list;
3970 scoped_feature_list.InitFromCommandLine(
3971 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
3972
3973 ASSERT_TRUE(https_server_mismatched_.Start());
3974 base::HistogramTester histograms;
3975
3976 // Mark the server's cert as a captive portal cert.
3977 const net::HashValue server_spki_hash =
3978 GetSPKIHash(https_server_mismatched_.GetCertificate().get());
3979 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
3980 config_proto.add_captive_portal_cert()->set_sha256_hash(
3981 server_spki_hash.ToString());
3982 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
3983
3984 // Navigate to an unsafe page on the server. The captive portal interstitial
3985 // should be displayed since CaptivePortalCertificateList feature is enabled.
3986 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
3987 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
3988 ui_test_utils::NavigateToURL(
3989 browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"));
3990 content::WaitForInterstitialAttach(tab);
3991
3992 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
3993 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
3994 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
3995 EXPECT_FALSE(interstitial_timer_observer.timer_started());
3996
3997 // Check that the histogram for the captive portal cert was recorded.
3998 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
3999 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4000 SSLErrorHandler::HANDLE_ALL, 1);
4001 histograms.ExpectBucketCount(
4002 SSLErrorHandler::GetHistogramNameForTesting(),
4003 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
4004 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4005 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
4006 }
4007
4008 namespace {
4009
4010 // Test class that mimics a URL request with a certificate whose SPKI hash is in
4011 // ssl_error_assistant.asciipb resource. A better way of testing the SPKI hashes
4012 // inside the resource bundle would be to serve the actual certificate from the
4013 // embeded test server, but the test server can only serve a limited number of
estark 2017/02/03 07:24:07 typo: embeded -> embedded
meacer 2017/02/06 23:39:17 Done.
4014 // predefined certificates.
Ryan Sleevi 2017/02/02 02:24:36 You could use a MockCertVerifyProc to return any c
estark 2017/02/03 07:24:07 I had originally suggested a MockCertVerifier to M
meacer 2017/02/06 23:39:17 Converted the tests to use MockCertVerifier.
4015 template <int net_error>
estark 2017/02/03 07:24:07 Just curious, why templatize the test fixture inst
meacer 2017/02/06 23:39:17 Parametrizing this class added complexity: - If w
4016 class SSLUICaptivePortalTest : public InProcessBrowserTest {
4017 public:
4018 SSLUICaptivePortalTest() : InProcessBrowserTest(), cert_(nullptr) {}
4019
4020 void SetUpOnMainThread() override {
4021 cert_ =
4022 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
4023 ASSERT_TRUE(cert_);
4024 content::BrowserThread::PostTask(
4025 content::BrowserThread::IO, FROM_HERE,
4026 base::Bind(&SSLUICaptivePortalTest::AddUrlHandler, cert_));
4027 }
4028
4029 static void AddUrlHandler(scoped_refptr<net::X509Certificate> cert) {
4030 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
4031 filter->AddHostnameInterceptor("https", kCaptivePortalHostname,
4032 std::unique_ptr<net::URLRequestInterceptor>(
4033 new CaptivePortalInterceptor(cert)));
4034 }
4035
4036 private:
4037 // A URLRequestJob that mocks a TLS connection with a certificate whose SPKI
4038 // hash is marked as a known captive portal certificate SPKI.
4039 class CaptivePortalURLRequestJob : public net::URLRequestJob {
4040 public:
4041 CaptivePortalURLRequestJob(net::URLRequest* request,
4042 net::NetworkDelegate* network_delegate,
4043 scoped_refptr<net::X509Certificate> cert)
4044 : net::URLRequestJob(request, network_delegate),
4045 cert_(std::move(cert)),
4046 weak_factory_(this) {}
4047
4048 // net::URLRequestJob method:
4049 void Start() override {
4050 net::SSLInfo ssl_info;
4051 ssl_info.SetCertError(net_error);
4052 ssl_info.cert = cert_;
4053
4054 // Set the SPKI hash to captive-portal.badssl.com leaf certificate. This
4055 // doesn't match the actual cert (ok_cert.pem) but is good enough for
4056 // testing.
4057 net::HashValue hash;
4058 ASSERT_TRUE(hash.FromString(
4059 "sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI="));
4060 ssl_info.public_key_hashes.push_back(hash);
4061
4062 base::ThreadTaskRunnerHandle::Get()->PostTask(
4063 FROM_HERE,
4064 base::Bind(&CaptivePortalURLRequestJob::NotifySSLCertificateError,
4065 weak_factory_.GetWeakPtr(), ssl_info, false));
4066 }
4067
4068 protected:
4069 ~CaptivePortalURLRequestJob() override {}
4070
4071 private:
4072 const scoped_refptr<net::X509Certificate> cert_;
4073 base::WeakPtrFactory<CaptivePortalURLRequestJob> weak_factory_;
4074
4075 DISALLOW_COPY_AND_ASSIGN(CaptivePortalURLRequestJob);
4076 };
4077
4078 // A URLRequestInterceptor that handles requests with
4079 // CaptivePortalURLRequestJob jobs.
4080 class CaptivePortalInterceptor : public net::URLRequestInterceptor {
4081 public:
4082 CaptivePortalInterceptor(scoped_refptr<net::X509Certificate> cert)
4083 : cert_(std::move(cert)) {}
4084
4085 ~CaptivePortalInterceptor() override {}
4086
4087 // net::URLRequestInterceptor method:
4088 net::URLRequestJob* MaybeInterceptRequest(
4089 net::URLRequest* request,
4090 net::NetworkDelegate* network_delegate) const override {
4091 return new CaptivePortalURLRequestJob(request, network_delegate, cert_);
4092 }
4093
4094 private:
4095 const scoped_refptr<net::X509Certificate> cert_;
4096
4097 DISALLOW_COPY_AND_ASSIGN(CaptivePortalInterceptor);
4098 };
4099
4100 scoped_refptr<net::X509Certificate> cert_;
4101 };
4102
4103 using SSLUICaptivePortalNameMismatchTest =
4104 SSLUICaptivePortalTest<net::ERR_CERT_COMMON_NAME_INVALID>;
4105 using SSLUICaptivePortalAuthorityInvalidTest =
4106 SSLUICaptivePortalTest<net::ERR_CERT_AUTHORITY_INVALID>;
4107
4108 } // namespace
4109
4110 // Same as CaptivePortalCertificateList_Enabled_FromProto, but this time the
4111 // cert's SPKI hash is listed in ssl_error_assistant.asciipb.
4112 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalNameMismatchTest,
4113 CaptivePortalCertificateList_Enabled_FromResource) {
4114 base::test::ScopedFeatureList scoped_feature_list;
4115 scoped_feature_list.InitFromCommandLine(
4116 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
4117
4118 base::HistogramTester histograms;
4119
4120 // Navigate to an unsafe page on the server. The captive portal interstitial
4121 // should be displayed since CaptivePortalCertificateList feature is enabled.
4122 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
4123 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
4124 ui_test_utils::NavigateToURL(
4125 browser(), GURL(std::string("https://") + kCaptivePortalHostname));
4126 content::WaitForInterstitialAttach(tab);
4127
4128 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4129 ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
4130 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4131 EXPECT_FALSE(interstitial_timer_observer.timer_started());
4132
4133 // Check that the histogram for the captive portal cert was recorded.
4134 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
4135 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4136 SSLErrorHandler::HANDLE_ALL, 1);
4137 histograms.ExpectBucketCount(
4138 SSLErrorHandler::GetHistogramNameForTesting(),
4139 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
4140 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4141 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
4142 }
4143
4144 // Same as SSLUICaptivePortalNameMismatchTest, but this time the error is
4145 // authority-invalid. Captive portal interstitial should not be shown.
4146 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalAuthorityInvalidTest,
4147 CaptivePortalCertificateList_Enabled_FromResource) {
4148 base::test::ScopedFeatureList scoped_feature_list;
4149 scoped_feature_list.InitFromCommandLine(
4150 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
4151
4152 // Set interstitial delay to zero.
4153 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
4154
4155 base::HistogramTester histograms;
4156 // Navigate to an unsafe page on the server. CaptivePortalCertificateList
4157 // feature is enabled but the error is not a name mismatch, so a generic SSL
4158 // interstitial should be displayed.
4159 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
4160 SSLInterstitialTimerObserver interstitial_timer_observer(tab);
4161 ui_test_utils::NavigateToURL(
4162 browser(), GURL(std::string("https://") + kCaptivePortalHostname));
4163 content::WaitForInterstitialAttach(tab);
4164
4165 InterstitialPage* interstitial_page = tab->GetInterstitialPage();
4166 ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
4167 interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
4168 EXPECT_TRUE(interstitial_timer_observer.timer_started());
4169
4170 // Check that the histogram for the captive portal cert was recorded.
4171 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
4172 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
4173 SSLErrorHandler::HANDLE_ALL, 1);
4174 histograms.ExpectBucketCount(
4175 SSLErrorHandler::GetHistogramNameForTesting(),
4176 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
4177 }
4178
4179 #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
4180
3888 // TODO(jcampan): more tests to do below. 4181 // TODO(jcampan): more tests to do below.
3889 4182
3890 // Visit a page over https that contains a frame with a redirect. 4183 // Visit a page over https that contains a frame with a redirect.
3891 4184
3892 // XMLHttpRequest insecure content in synchronous mode. 4185 // XMLHttpRequest insecure content in synchronous mode.
3893 4186
3894 // XMLHttpRequest insecure content in asynchronous mode. 4187 // XMLHttpRequest insecure content in asynchronous mode.
3895 4188
3896 // XMLHttpRequest over bad ssl in synchronous mode. 4189 // XMLHttpRequest over bad ssl in synchronous mode.
3897 4190
3898 // XMLHttpRequest over OK ssl in synchronous mode. 4191 // XMLHttpRequest over OK ssl in synchronous mode.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698