OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "chrome/browser/ssl/chrome_security_state_model_client.h" | 5 #include "chrome/browser/ssl/chrome_security_state_model_client.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
11 #include "base/strings/utf_string_conversions.h" | |
11 #include "chrome/browser/ssl/cert_verifier_browser_test.h" | 12 #include "chrome/browser/ssl/cert_verifier_browser_test.h" |
12 #include "chrome/browser/ssl/chrome_security_state_model_client.h" | 13 #include "chrome/browser/ssl/chrome_security_state_model_client.h" |
13 #include "chrome/browser/ssl/ssl_blocking_page.h" | 14 #include "chrome/browser/ssl/ssl_blocking_page.h" |
14 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/browser_commands.h" | |
15 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
16 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
17 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
18 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
21 #include "chrome/grit/generated_resources.h" | |
19 #include "chrome/test/base/in_process_browser_test.h" | 22 #include "chrome/test/base/in_process_browser_test.h" |
20 #include "chrome/test/base/ui_test_utils.h" | 23 #include "chrome/test/base/ui_test_utils.h" |
21 #include "components/prefs/pref_service.h" | 24 #include "components/prefs/pref_service.h" |
22 #include "content/public/browser/cert_store.h" | 25 #include "content/public/browser/cert_store.h" |
23 #include "content/public/browser/interstitial_page.h" | 26 #include "content/public/browser/interstitial_page.h" |
24 #include "content/public/browser/navigation_controller.h" | 27 #include "content/public/browser/navigation_controller.h" |
28 #include "content/public/browser/navigation_entry.h" | |
25 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
26 #include "content/public/browser/notification_types.h" | 30 #include "content/public/browser/notification_types.h" |
31 #include "content/public/browser/security_style_explanation.h" | |
32 #include "content/public/browser/security_style_explanations.h" | |
27 #include "content/public/browser/web_contents.h" | 33 #include "content/public/browser/web_contents.h" |
28 #include "content/public/common/referrer.h" | 34 #include "content/public/common/referrer.h" |
35 #include "content/public/common/ssl_status.h" | |
29 #include "content/public/test/browser_test_utils.h" | 36 #include "content/public/test/browser_test_utils.h" |
30 #include "net/base/net_errors.h" | 37 #include "net/base/net_errors.h" |
38 #include "net/base/test_data_directory.h" | |
31 #include "net/cert/cert_status_flags.h" | 39 #include "net/cert/cert_status_flags.h" |
32 #include "net/cert/cert_verify_result.h" | 40 #include "net/cert/cert_verify_result.h" |
33 #include "net/cert/mock_cert_verifier.h" | 41 #include "net/cert/mock_cert_verifier.h" |
34 #include "net/cert/x509_certificate.h" | 42 #include "net/cert/x509_certificate.h" |
43 #include "net/cert/x509_certificate.h" | |
msw
2016/05/18 17:20:24
nit: remove (duplicate of line above)
estark
2016/05/20 22:12:09
Done.
| |
35 #include "net/dns/mock_host_resolver.h" | 44 #include "net/dns/mock_host_resolver.h" |
45 #include "net/ssl/ssl_cipher_suite_names.h" | |
46 #include "net/ssl/ssl_connection_status_flags.h" | |
47 #include "net/test/cert_test_util.h" | |
36 #include "net/test/embedded_test_server/embedded_test_server.h" | 48 #include "net/test/embedded_test_server/embedded_test_server.h" |
37 #include "net/test/embedded_test_server/request_handler_util.h" | 49 #include "net/test/embedded_test_server/request_handler_util.h" |
38 #include "net/test/url_request/url_request_failed_job.h" | 50 #include "net/test/url_request/url_request_failed_job.h" |
51 #include "net/test/url_request/url_request_mock_http_job.h" | |
39 #include "net/url_request/url_request_filter.h" | 52 #include "net/url_request/url_request_filter.h" |
53 #include "net/url_request/url_request_test_util.h" | |
54 #include "ui/base/l10n/l10n_util.h" | |
40 | 55 |
41 using security_state::SecurityStateModel; | 56 using security_state::SecurityStateModel; |
42 | 57 |
43 namespace { | 58 namespace { |
44 | 59 |
60 enum CertificateStatus { VALID_CERTIFICATE, INVALID_CERTIFICATE }; | |
61 | |
45 const base::FilePath::CharType kDocRoot[] = | 62 const base::FilePath::CharType kDocRoot[] = |
46 FILE_PATH_LITERAL("chrome/test/data"); | 63 FILE_PATH_LITERAL("chrome/test/data"); |
47 | 64 |
65 // A WebContentsObserver useful for testing the SecurityStyleChanged() | |
66 // method: it keeps track of the latest security style and explanation | |
67 // that was fired. | |
68 class SecurityStyleTestObserver : public content::WebContentsObserver { | |
69 public: | |
70 explicit SecurityStyleTestObserver(content::WebContents* web_contents) | |
71 : content::WebContentsObserver(web_contents), | |
72 latest_security_style_(content::SECURITY_STYLE_UNKNOWN) {} | |
73 ~SecurityStyleTestObserver() override {} | |
74 | |
75 void SecurityStyleChanged(content::SecurityStyle security_style, | |
76 const content::SecurityStyleExplanations& | |
77 security_style_explanations) override { | |
78 latest_security_style_ = security_style; | |
79 latest_explanations_ = security_style_explanations; | |
80 } | |
81 | |
82 content::SecurityStyle latest_security_style() const { | |
83 return latest_security_style_; | |
84 } | |
85 | |
86 const content::SecurityStyleExplanations& latest_explanations() const { | |
87 return latest_explanations_; | |
88 } | |
89 | |
90 void ClearLatestSecurityStyleAndExplanations() { | |
91 latest_security_style_ = content::SECURITY_STYLE_UNKNOWN; | |
92 latest_explanations_ = content::SecurityStyleExplanations(); | |
93 } | |
94 | |
95 private: | |
96 content::SecurityStyle latest_security_style_; | |
97 content::SecurityStyleExplanations latest_explanations_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(SecurityStyleTestObserver); | |
100 }; | |
101 | |
102 // Check that |observer|'s latest event was for an expired certificate | |
103 // and that it saw the proper SecurityStyle and explanations. | |
104 void CheckBrokenSecurityStyle(const SecurityStyleTestObserver& observer, | |
105 int error, | |
106 Browser* browser) { | |
107 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, | |
108 observer.latest_security_style()); | |
109 | |
110 const content::SecurityStyleExplanations& expired_explanation = | |
111 observer.latest_explanations(); | |
112 EXPECT_EQ(0u, expired_explanation.unauthenticated_explanations.size()); | |
113 ASSERT_EQ(1u, expired_explanation.broken_explanations.size()); | |
114 | |
115 // Check that the summary and description are as expected. | |
116 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR), | |
117 expired_explanation.broken_explanations[0].summary); | |
118 | |
119 base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(error)); | |
120 EXPECT_EQ(l10n_util::GetStringFUTF8( | |
121 IDS_CERTIFICATE_CHAIN_ERROR_DESCRIPTION_FORMAT, error_string), | |
122 expired_explanation.broken_explanations[0].description); | |
123 | |
124 // Check the associated certificate id. | |
125 int cert_id = browser->tab_strip_model() | |
126 ->GetActiveWebContents() | |
127 ->GetController() | |
128 .GetActiveEntry() | |
129 ->GetSSL() | |
130 .cert_id; | |
131 EXPECT_EQ(cert_id, expired_explanation.broken_explanations[0].cert_id); | |
132 } | |
133 | |
134 // Checks that the given |secure_explanations| contains appropriate | |
135 // an appropriate explanation if the certificate status is valid. | |
136 void CheckSecureExplanations( | |
137 const std::vector<content::SecurityStyleExplanation>& secure_explanations, | |
138 CertificateStatus cert_status, | |
139 Browser* browser) { | |
140 ASSERT_EQ(cert_status == VALID_CERTIFICATE ? 2u : 1u, | |
141 secure_explanations.size()); | |
142 if (cert_status == VALID_CERTIFICATE) { | |
143 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE), | |
144 secure_explanations[0].summary); | |
145 EXPECT_EQ( | |
146 l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION), | |
147 secure_explanations[0].description); | |
148 int cert_id = browser->tab_strip_model() | |
149 ->GetActiveWebContents() | |
150 ->GetController() | |
151 .GetActiveEntry() | |
152 ->GetSSL() | |
153 .cert_id; | |
154 EXPECT_EQ(cert_id, secure_explanations[0].cert_id); | |
155 } | |
156 | |
157 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), | |
158 secure_explanations.back().summary); | |
159 EXPECT_EQ( | |
160 l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE_DESCRIPTION), | |
161 secure_explanations.back().description); | |
162 } | |
163 | |
48 void CheckSecurityInfoForSecure( | 164 void CheckSecurityInfoForSecure( |
49 content::WebContents* contents, | 165 content::WebContents* contents, |
50 SecurityStateModel::SecurityLevel expect_security_level, | 166 SecurityStateModel::SecurityLevel expect_security_level, |
51 SecurityStateModel::SHA1DeprecationStatus expect_sha1_status, | 167 SecurityStateModel::SHA1DeprecationStatus expect_sha1_status, |
52 SecurityStateModel::MixedContentStatus expect_mixed_content_status, | 168 SecurityStateModel::MixedContentStatus expect_mixed_content_status, |
53 bool expect_cert_error) { | 169 bool expect_cert_error) { |
54 ASSERT_TRUE(contents); | 170 ASSERT_TRUE(contents); |
55 | 171 |
56 ChromeSecurityStateModelClient* model_client = | 172 ChromeSecurityStateModelClient* model_client = |
57 ChromeSecurityStateModelClient::FromWebContents(contents); | 173 ChromeSecurityStateModelClient::FromWebContents(contents); |
(...skipping 27 matching lines...) Expand all Loading... | |
85 security_info.sha1_deprecation_status); | 201 security_info.sha1_deprecation_status); |
86 EXPECT_EQ(SecurityStateModel::NO_MIXED_CONTENT, | 202 EXPECT_EQ(SecurityStateModel::NO_MIXED_CONTENT, |
87 security_info.mixed_content_status); | 203 security_info.mixed_content_status); |
88 EXPECT_TRUE(security_info.sct_verify_statuses.empty()); | 204 EXPECT_TRUE(security_info.sct_verify_statuses.empty()); |
89 EXPECT_FALSE(security_info.scheme_is_cryptographic); | 205 EXPECT_FALSE(security_info.scheme_is_cryptographic); |
90 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status)); | 206 EXPECT_FALSE(net::IsCertStatusError(security_info.cert_status)); |
91 EXPECT_EQ(-1, security_info.security_bits); | 207 EXPECT_EQ(-1, security_info.security_bits); |
92 EXPECT_EQ(0, security_info.cert_id); | 208 EXPECT_EQ(0, security_info.cert_id); |
93 } | 209 } |
94 | 210 |
211 void SetUpMockCertVerifierForServer(net::MockCertVerifier* verifier, | |
212 const net::EmbeddedTestServer& server, | |
213 net::CertStatus cert_status, | |
214 int net_result) { | |
215 scoped_refptr<net::X509Certificate> cert(server.GetCertificate()); | |
216 net::CertVerifyResult verify_result; | |
217 verify_result.is_issued_by_known_root = true; | |
218 verify_result.verified_cert = cert; | |
219 verify_result.cert_status = cert_status; | |
220 | |
221 verifier->AddResultForCert(cert.get(), verify_result, net_result); | |
222 } | |
223 | |
95 class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { | 224 class ChromeSecurityStateModelClientTest : public CertVerifierBrowserTest { |
96 public: | 225 public: |
97 ChromeSecurityStateModelClientTest() | 226 ChromeSecurityStateModelClientTest() |
98 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { | 227 : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
99 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); | 228 https_server_.ServeFilesFromSourceDirectory(base::FilePath(kDocRoot)); |
100 } | 229 } |
101 | 230 |
102 void SetUpCommandLine(base::CommandLine* command_line) override { | 231 void SetUpCommandLine(base::CommandLine* command_line) override { |
103 // Browser will both run and display insecure content. | 232 // Browser will both run and display insecure content. |
104 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); | 233 command_line->AppendSwitch(switches::kAllowRunningInsecureContent); |
(...skipping 18 matching lines...) Expand all Loading... | |
123 base::StringPairs replacement_text; | 252 base::StringPairs replacement_text; |
124 replacement_text.push_back( | 253 replacement_text.push_back( |
125 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); | 254 make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString())); |
126 net::test_server::GetFilePathWithReplacements( | 255 net::test_server::GetFilePathWithReplacements( |
127 original_file_path, replacement_text, replacement_path); | 256 original_file_path, replacement_text, replacement_path); |
128 } | 257 } |
129 | 258 |
130 protected: | 259 protected: |
131 void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status, | 260 void SetUpMockCertVerifierForHttpsServer(net::CertStatus cert_status, |
132 int net_result) { | 261 int net_result) { |
133 scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate()); | 262 SetUpMockCertVerifierForServer(mock_cert_verifier(), https_server_, |
134 net::CertVerifyResult verify_result; | 263 cert_status, net_result); |
135 verify_result.is_issued_by_known_root = true; | |
136 verify_result.verified_cert = cert; | |
137 verify_result.cert_status = cert_status; | |
138 | |
139 mock_cert_verifier()->AddResultForCert(cert.get(), verify_result, | |
140 net_result); | |
141 } | 264 } |
142 | 265 |
143 net::EmbeddedTestServer https_server_; | 266 net::EmbeddedTestServer https_server_; |
144 | 267 |
145 private: | 268 private: |
146 DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest); | 269 DISALLOW_COPY_AND_ASSIGN(ChromeSecurityStateModelClientTest); |
147 }; | 270 }; |
148 | 271 |
149 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) { | 272 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, HttpPage) { |
150 ASSERT_TRUE(embedded_test_server()->Start()); | 273 ASSERT_TRUE(embedded_test_server()->Start()); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
528 false /* expect cert status error */); | 651 false /* expect cert status error */); |
529 | 652 |
530 browser()->tab_strip_model()->InsertWebContentsAt(0, new_contents, | 653 browser()->tab_strip_model()->InsertWebContentsAt(0, new_contents, |
531 TabStripModel::ADD_NONE); | 654 TabStripModel::ADD_NONE); |
532 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE, | 655 CheckSecurityInfoForSecure(new_contents, SecurityStateModel::SECURE, |
533 SecurityStateModel::NO_DEPRECATED_SHA1, | 656 SecurityStateModel::NO_DEPRECATED_SHA1, |
534 SecurityStateModel::NO_MIXED_CONTENT, | 657 SecurityStateModel::NO_MIXED_CONTENT, |
535 false /* expect cert status error */); | 658 false /* expect cert status error */); |
536 } | 659 } |
537 | 660 |
661 // Tests that the WebContentsObserver::SecurityStyleChanged event fires | |
662 // with the current style on HTTP, broken HTTPS, and valid HTTPS pages. | |
663 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, | |
664 SecurityStyleChangedObserver) { | |
665 ASSERT_TRUE(https_server_.Start()); | |
666 SetUpMockCertVerifierForHttpsServer(0, net::OK); | |
msw
2016/05/18 17:20:24
q: Is this necessary? It wasn't part of the old te
estark
2016/05/20 22:12:09
Ehh, I did it to be consistent with the rest of th
| |
667 | |
668 net::EmbeddedTestServer https_test_server_expired( | |
669 net::EmbeddedTestServer::TYPE_HTTPS); | |
670 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); | |
671 https_test_server_expired.ServeFilesFromSourceDirectory( | |
672 base::FilePath(kDocRoot)); | |
673 ASSERT_TRUE(https_test_server_expired.Start()); | |
674 SetUpMockCertVerifierForServer( | |
675 mock_cert_verifier(), https_test_server_expired, | |
676 net::CERT_STATUS_DATE_INVALID, net::ERR_CERT_DATE_INVALID); | |
677 | |
678 ASSERT_TRUE(embedded_test_server()->Start()); | |
679 | |
680 content::WebContents* web_contents = | |
681 browser()->tab_strip_model()->GetActiveWebContents(); | |
682 SecurityStyleTestObserver observer(web_contents); | |
683 | |
684 // Visit an HTTP url. | |
685 GURL http_url(embedded_test_server()->GetURL("/")); | |
686 ui_test_utils::NavigateToURL(browser(), http_url); | |
687 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, | |
688 observer.latest_security_style()); | |
689 EXPECT_EQ(0u, | |
690 observer.latest_explanations().unauthenticated_explanations.size()); | |
691 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); | |
692 EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size()); | |
693 EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic); | |
694 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
695 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
696 | |
697 // Visit an (otherwise valid) HTTPS page that displays mixed content. | |
698 std::string replacement_path; | |
699 GetFilePathWithHostAndPortReplacement( | |
700 "/ssl/page_displays_insecure_content.html", | |
701 embedded_test_server()->host_port_pair(), &replacement_path); | |
702 | |
703 GURL mixed_content_url(https_server_.GetURL(replacement_path)); | |
704 ui_test_utils::NavigateToURL(browser(), mixed_content_url); | |
705 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, | |
706 observer.latest_security_style()); | |
707 | |
708 const content::SecurityStyleExplanations& mixed_content_explanation = | |
709 observer.latest_explanations(); | |
710 ASSERT_EQ(0u, mixed_content_explanation.unauthenticated_explanations.size()); | |
711 ASSERT_EQ(0u, mixed_content_explanation.broken_explanations.size()); | |
712 CheckSecureExplanations(mixed_content_explanation.secure_explanations, | |
713 VALID_CERTIFICATE, browser()); | |
714 EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic); | |
715 EXPECT_TRUE(mixed_content_explanation.displayed_insecure_content); | |
716 EXPECT_FALSE(mixed_content_explanation.ran_insecure_content); | |
717 EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, | |
718 mixed_content_explanation.displayed_insecure_content_style); | |
719 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, | |
720 mixed_content_explanation.ran_insecure_content_style); | |
721 | |
722 // Visit a broken HTTPS url. | |
723 GURL expired_url(https_test_server_expired.GetURL(std::string("/"))); | |
724 ui_test_utils::NavigateToURL(browser(), expired_url); | |
725 | |
726 // An interstitial should show, and an event for the lock icon on the | |
727 // interstitial should fire. | |
728 content::WaitForInterstitialAttach(web_contents); | |
729 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); | |
730 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); | |
731 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
732 INVALID_CERTIFICATE, browser()); | |
733 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
734 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
735 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
736 | |
737 // Before clicking through, navigate to a different page, and then go | |
738 // back to the interstitial. | |
739 GURL valid_https_url(https_server_.GetURL(std::string("/"))); | |
740 ui_test_utils::NavigateToURL(browser(), valid_https_url); | |
741 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, | |
742 observer.latest_security_style()); | |
743 EXPECT_EQ(0u, | |
744 observer.latest_explanations().unauthenticated_explanations.size()); | |
745 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); | |
746 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
747 VALID_CERTIFICATE, browser()); | |
748 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
749 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
750 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
751 | |
752 // After going back to the interstitial, an event for a broken lock | |
753 // icon should fire again. | |
754 ui_test_utils::NavigateToURL(browser(), expired_url); | |
755 content::WaitForInterstitialAttach(web_contents); | |
756 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); | |
757 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); | |
758 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
759 INVALID_CERTIFICATE, browser()); | |
760 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
761 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
762 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
763 | |
764 // Since the next expected style is the same as the previous, clear | |
765 // the observer (to make sure that the event fires twice and we don't | |
766 // just see the previous event's style). | |
767 observer.ClearLatestSecurityStyleAndExplanations(); | |
768 | |
769 // Other conditions cannot be tested on this host after clicking | |
770 // through because once the interstitial is clicked through, all URLs | |
771 // for this host will remain in a broken state. | |
772 ProceedThroughInterstitial(web_contents); | |
773 CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser()); | |
774 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
775 INVALID_CERTIFICATE, browser()); | |
776 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
777 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
778 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
779 } | |
780 | |
781 // Visit a valid HTTPS page, then a broken HTTPS page, and then go back, | |
782 // and test that the observed security style matches. | |
783 IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, | |
784 SecurityStyleChangedObserverGoBack) { | |
785 ASSERT_TRUE(https_server_.Start()); | |
786 SetUpMockCertVerifierForHttpsServer(0, net::OK); | |
787 | |
788 net::EmbeddedTestServer https_test_server_expired( | |
789 net::EmbeddedTestServer::TYPE_HTTPS); | |
790 https_test_server_expired.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); | |
791 https_test_server_expired.ServeFilesFromSourceDirectory( | |
792 base::FilePath(kDocRoot)); | |
793 ASSERT_TRUE(https_test_server_expired.Start()); | |
794 SetUpMockCertVerifierForServer( | |
795 mock_cert_verifier(), https_test_server_expired, | |
796 net::CERT_STATUS_COMMON_NAME_INVALID, net::ERR_CERT_COMMON_NAME_INVALID); | |
797 | |
798 content::WebContents* web_contents = | |
799 browser()->tab_strip_model()->GetActiveWebContents(); | |
800 SecurityStyleTestObserver observer(web_contents); | |
801 | |
802 // Visit a valid HTTPS url. | |
803 GURL valid_https_url(https_server_.GetURL(std::string("/"))); | |
804 ui_test_utils::NavigateToURL(browser(), valid_https_url); | |
805 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, | |
806 observer.latest_security_style()); | |
807 EXPECT_EQ(0u, | |
808 observer.latest_explanations().unauthenticated_explanations.size()); | |
809 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); | |
810 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
811 VALID_CERTIFICATE, browser()); | |
812 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
813 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
814 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
815 | |
816 // Navigate to a bad HTTPS page on a different host, and then click | |
817 // Back to verify that the previous good security style is seen again. | |
818 GURL expired_https_url(https_test_server_expired.GetURL(std::string("/"))); | |
819 host_resolver()->AddRule("www.example_broken.test", "127.0.0.1"); | |
820 GURL::Replacements replace_host; | |
821 replace_host.SetHostStr("www.example_broken.test"); | |
822 GURL https_url_different_host = | |
823 expired_https_url.ReplaceComponents(replace_host); | |
824 | |
825 ui_test_utils::NavigateToURL(browser(), https_url_different_host); | |
826 | |
827 content::WaitForInterstitialAttach(web_contents); | |
828 EXPECT_TRUE(web_contents->ShowingInterstitialPage()); | |
829 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, | |
830 browser()); | |
831 ProceedThroughInterstitial(web_contents); | |
832 CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID, | |
833 browser()); | |
834 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
835 INVALID_CERTIFICATE, browser()); | |
836 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
837 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
838 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
839 | |
840 content::WindowedNotificationObserver back_nav_load_observer( | |
841 content::NOTIFICATION_LOAD_STOP, | |
842 content::Source<content::NavigationController>( | |
843 &web_contents->GetController())); | |
844 chrome::GoBack(browser(), CURRENT_TAB); | |
845 back_nav_load_observer.Wait(); | |
846 | |
847 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, | |
848 observer.latest_security_style()); | |
849 EXPECT_EQ(0u, | |
850 observer.latest_explanations().unauthenticated_explanations.size()); | |
851 EXPECT_EQ(0u, observer.latest_explanations().broken_explanations.size()); | |
852 CheckSecureExplanations(observer.latest_explanations().secure_explanations, | |
853 VALID_CERTIFICATE, browser()); | |
854 EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); | |
855 EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); | |
856 EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); | |
857 } | |
858 | |
859 // After AddNonsecureUrlHandler() is called, requests to this hostname | |
860 // will use obsolete TLS settings. | |
861 const char kMockNonsecureHostname[] = "example-nonsecure.test"; | |
862 | |
863 // A URLRequestMockHTTPJob that mocks a TLS connection with an obsolete | |
864 // protocol version. | |
865 class URLRequestObsoleteTLSJob : public net::URLRequestMockHTTPJob { | |
866 public: | |
867 URLRequestObsoleteTLSJob(net::URLRequest* request, | |
868 net::NetworkDelegate* network_delegate, | |
869 const base::FilePath& file_path, | |
870 scoped_refptr<net::X509Certificate> cert, | |
871 scoped_refptr<base::TaskRunner> task_runner) | |
872 : net::URLRequestMockHTTPJob(request, | |
873 network_delegate, | |
874 file_path, | |
875 task_runner), | |
876 cert_(std::move(cert)) {} | |
877 | |
878 void GetResponseInfo(net::HttpResponseInfo* info) override { | |
879 net::URLRequestMockHTTPJob::GetResponseInfo(info); | |
880 net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_1, | |
881 &info->ssl_info.connection_status); | |
882 const uint16_t kTlsEcdheRsaWithAes128CbcSha = 0xc013; | |
883 net::SSLConnectionStatusSetCipherSuite(kTlsEcdheRsaWithAes128CbcSha, | |
884 &info->ssl_info.connection_status); | |
885 info->ssl_info.cert = cert_; | |
886 } | |
887 | |
888 protected: | |
889 ~URLRequestObsoleteTLSJob() override {} | |
890 | |
891 private: | |
892 const scoped_refptr<net::X509Certificate> cert_; | |
893 | |
894 DISALLOW_COPY_AND_ASSIGN(URLRequestObsoleteTLSJob); | |
895 }; | |
896 | |
897 // A URLRequestInterceptor that handles requests with | |
898 // URLRequestObsoleteTLSJob jobs. | |
899 class URLRequestNonsecureInterceptor : public net::URLRequestInterceptor { | |
900 public: | |
901 URLRequestNonsecureInterceptor( | |
902 const base::FilePath& base_path, | |
903 scoped_refptr<base::SequencedWorkerPool> worker_pool, | |
904 scoped_refptr<net::X509Certificate> cert) | |
905 : base_path_(base_path), | |
906 worker_pool_(std::move(worker_pool)), | |
907 cert_(std::move(cert)) {} | |
908 | |
909 ~URLRequestNonsecureInterceptor() override {} | |
910 | |
911 // net::URLRequestInterceptor: | |
912 net::URLRequestJob* MaybeInterceptRequest( | |
913 net::URLRequest* request, | |
914 net::NetworkDelegate* network_delegate) const override { | |
915 return new URLRequestObsoleteTLSJob( | |
916 request, network_delegate, base_path_, cert_, | |
917 worker_pool_->GetTaskRunnerWithShutdownBehavior( | |
918 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | |
919 } | |
920 | |
921 private: | |
922 const base::FilePath base_path_; | |
923 const scoped_refptr<base::SequencedWorkerPool> worker_pool_; | |
924 const scoped_refptr<net::X509Certificate> cert_; | |
925 | |
926 DISALLOW_COPY_AND_ASSIGN(URLRequestNonsecureInterceptor); | |
927 }; | |
928 | |
929 // Installs a handler to serve HTTPS requests to | |
930 // |kMockNonsecureHostname| with connections that have obsolete TLS | |
931 // settings. | |
932 void AddNonsecureUrlHandler( | |
933 const base::FilePath& base_path, | |
934 scoped_refptr<net::X509Certificate> cert, | |
935 scoped_refptr<base::SequencedWorkerPool> worker_pool) { | |
936 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | |
937 filter->AddHostnameInterceptor( | |
938 "https", kMockNonsecureHostname, | |
939 std::unique_ptr<net::URLRequestInterceptor>( | |
940 new URLRequestNonsecureInterceptor(base_path, worker_pool, cert))); | |
941 } | |
942 | |
943 class BrowserTestNonsecureURLRequest : public CertVerifierBrowserTest { | |
944 public: | |
945 BrowserTestNonsecureURLRequest() | |
946 : CertVerifierBrowserTest(), cert_(nullptr) {} | |
947 | |
948 void SetUpInProcessBrowserTestFixture() override { | |
949 cert_ = | |
950 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); | |
951 ASSERT_TRUE(cert_); | |
952 } | |
953 | |
954 void SetUpOnMainThread() override { | |
955 base::FilePath serve_file; | |
956 PathService::Get(chrome::DIR_TEST_DATA, &serve_file); | |
957 serve_file = serve_file.Append(FILE_PATH_LITERAL("title1.html")); | |
958 content::BrowserThread::PostTask( | |
959 content::BrowserThread::IO, FROM_HERE, | |
960 base::Bind( | |
961 &AddNonsecureUrlHandler, serve_file, cert_, | |
962 make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); | |
963 } | |
964 | |
965 private: | |
966 scoped_refptr<net::X509Certificate> cert_; | |
967 | |
968 DISALLOW_COPY_AND_ASSIGN(BrowserTestNonsecureURLRequest); | |
969 }; | |
970 | |
971 // Tests that a connection with obsolete TLS settings does not get a | |
972 // secure connection explanation. | |
973 IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequest, | |
974 SecurityStyleChangedObserverNonsecureConnection) { | |
975 content::WebContents* web_contents = | |
976 browser()->tab_strip_model()->GetActiveWebContents(); | |
977 SecurityStyleTestObserver observer(web_contents); | |
978 | |
979 ui_test_utils::NavigateToURL( | |
980 browser(), GURL(std::string("https://") + kMockNonsecureHostname)); | |
981 | |
982 // The security style of the page doesn't get downgraded for obsolete | |
983 // TLS settings, so it should remain at SECURITY_STYLE_AUTHENTICATED. | |
984 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATED, | |
985 observer.latest_security_style()); | |
986 | |
987 // The messages explaining the security style do, however, get | |
988 // downgraded: SECURE_PROTOCOL_AND_CIPHERSUITE should not show up when | |
989 // the TLS settings are obsolete. | |
990 for (const auto& explanation : | |
991 observer.latest_explanations().secure_explanations) { | |
992 EXPECT_NE(l10n_util::GetStringUTF8(IDS_SECURE_PROTOCOL_AND_CIPHERSUITE), | |
993 explanation.summary); | |
994 } | |
995 } | |
996 | |
538 } // namespace | 997 } // namespace |
OLD | NEW |