Chromium Code Reviews| 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 |