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

Unified Diff: chrome/browser/ssl/ssl_browser_tests.cc

Issue 1223233002: Common Name Mismatch Handler For WWW Subdomain Mismatch case (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Resolved comments, added UMA Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ssl/ssl_browser_tests.cc
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 31a3f6a13dbca0299249c2e0d90f7547f2626427..e7b3d03d18b4feb74202acbc12066788e95020cf 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -26,7 +26,9 @@
#include "chrome/browser/ssl/certificate_error_report.h"
#include "chrome/browser/ssl/certificate_reporting_test_utils.h"
#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
+#include "chrome/browser/ssl/common_name_mismatch_handler.h"
#include "chrome/browser/ssl/ssl_blocking_page.h"
+#include "chrome/browser/ssl/ssl_error_handler.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_navigator.h"
@@ -54,14 +56,17 @@
#include "content/public/common/ssl_status.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_renderer_host.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/test_data_directory.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/x509_certificate.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/ssl/ssl_info.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/test_certificate_data.h"
#include "net/url_request/url_request_context.h"
#if defined(USE_NSS_CERTS)
@@ -207,7 +212,15 @@ class SSLUITest
base::FilePath(kDocRoot)),
wss_server_expired_(net::SpawnedTestServer::TYPE_WSS,
SSLOptions(SSLOptions::CERT_EXPIRED),
- net::GetWebSocketTestDataDirectory()) {}
+ net::GetWebSocketTestDataDirectory()),
+ https_server_example_domain_(
+ net::SpawnedTestServer::TYPE_HTTPS,
+ SSLOptions(SSLOptions::CERT_EXAMPLE_DOMAIN),
+ base::FilePath(kDocRoot)),
+ https_server_www_example_domain_(
+ net::SpawnedTestServer::TYPE_HTTPS,
+ SSLOptions(SSLOptions::CERT_WWW_EXAMPLE_DOMAIN),
+ base::FilePath(kDocRoot)) {}
void SetUpCommandLine(base::CommandLine* command_line) override {
// Browser will both run and display insecure content.
@@ -426,6 +439,8 @@ class SSLUITest
net::SpawnedTestServer https_server_expired_;
net::SpawnedTestServer https_server_mismatched_;
net::SpawnedTestServer wss_server_expired_;
+ net::SpawnedTestServer https_server_example_domain_;
+ net::SpawnedTestServer https_server_www_example_domain_;
private:
typedef net::SpawnedTestServer::SSLOptions SSLOptions;
@@ -2224,6 +2239,302 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, BadCertFollowedByGoodCert) {
EXPECT_FALSE(state->HasAllowException(https_server_host));
}
+// Verifies that invoking the SSL Blocking page with a suggested URL displays
+// the common name mismatch interstitial with a link to suggested URL.
+IN_PROC_BROWSER_TEST_F(SSLUITest, SSLBlockingPageWithSuggestedURL) {
+ content::WebContents* contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ net::SSLInfo ssl_info;
+ ssl_info.cert = net::X509Certificate::CreateFromBytes(
+ reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ // Create a new SSL blocking page for https://example.com with
+ // https://www.example.com as the suggested URL.
+ SSLBlockingPage* blocking_page = new SSLBlockingPage(
+ contents, net::ERR_CERT_COMMON_NAME_INVALID, ssl_info,
+ GURL("https://example.com"), 0, base::Time::NowFromSystemTime(), nullptr,
+ base::Callback<void(bool)>(), GURL("https://www.example.com"));
+ blocking_page->Show();
+
+ WaitForInterstitialAttach(contents);
+
+ EXPECT_TRUE(
+ WaitForRenderFrameReady(contents->GetInterstitialPage()->GetMainFrame()));
+ // The interstitial should display a link to www.example.com
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "www.example.com"));
+ // Verify that the link has the text "suggest-link", the id of the
+ // link element displayed.
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "suggest-link"));
+}
+
+// Visit the URL www.example.com on a server that presents a valid certificate
+// for example.com. Verify that the common name mismatch interstitial is
+// displayed with a link to example.com. Click the suggested URL link
+// and make sure the page navigates to a non SSL page.
meacer 2015/07/30 19:40:21 "non SSL page" isn't correct, suggested url is an
Bhanu Dev 2015/07/31 00:07:16 Done.
+IN_PROC_BROWSER_TEST_F(SSLUITest, ShouldShowWWWSubdomainMismatchInterstitial) {
+ // Starts a server with a valid certificate for "example.com".
+ ASSERT_TRUE(https_server_example_domain_.Start());
+
+ host_resolver()->AddRule("example.com", "127.0.0.1");
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+
+ // The path does not matter.
+ GURL https_server_url =
+ https_server_example_domain_.GetURL("files/ssl/google.html?a=b");
+ GURL::Replacements replacements;
+ replacements.SetHostStr("www.example.com");
+ GURL https_server_mismatched_url =
+ https_server_url.ReplaceComponents(replacements);
+
+ ui_test_utils::NavigateToURL(browser(), https_server_mismatched_url);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ WaitForInterstitialAttach(contents);
+ // An interstitial should be displayed with a
+ // |CERT_STATUS_COMMON_NAME_INVALID| error.
+ CheckAuthenticationBrokenState(contents, net::CERT_STATUS_COMMON_NAME_INVALID,
+ AuthState::SHOWING_INTERSTITIAL);
+ EXPECT_EQ(SSLBlockingPage::kTypeForTesting, contents->GetInterstitialPage()
+ ->GetDelegateForTesting()
+ ->GetTypeForTesting());
+
+ content::RenderFrameHost* rfh =
+ contents->GetInterstitialPage()->GetMainFrame();
+ EXPECT_TRUE(WaitForRenderFrameReady(rfh));
+ // The interstitial should display a link to www.example.com
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "example.com"));
+ // Verify that the link has the text "suggest-link", the id of the
+ // link element displayed.
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "suggest-link"));
+
+ const char kClickConnectButtonJS[] =
meacer 2015/07/30 19:40:21 ConnectButton -> OpenSuggestedButton?
Bhanu Dev 2015/07/31 00:07:15 Done.
+ "document.getElementById('suggest-link').click();";
+
meacer 2015/07/30 19:40:21 Remove blank line. Just a single blank line before
Bhanu Dev 2015/07/31 00:07:15 Done.
+ content::TestNavigationObserver observer(contents, 1);
+ EXPECT_TRUE(content::ExecuteScript(rfh, kClickConnectButtonJS));
+ observer.Wait();
+
+ CheckAuthenticatedState(contents, AuthState::NONE);
+
meacer 2015/07/30 19:40:21 Remove blank line
Bhanu Dev 2015/07/31 00:07:16 Done.
+ replacements.SetHostStr("example.com");
+ GURL https_server_new_url = https_server_url.ReplaceComponents(replacements);
+ // Verify that the current URL is the suggested URL.
+ EXPECT_EQ(https_server_new_url.spec(),
+ contents->GetLastCommittedURL().spec());
+}
+
+// Visit the URL example.com on a server that presents a valid certificate
+// for www.example.com. Verify that the common name mismatch interstitial is
+// displayed with a link to www.example.com.
+IN_PROC_BROWSER_TEST_F(SSLUITest, CheckWWWSubdomainMismatchInverse) {
+ // Starts a server with a valid certificate for "example.com".
+ ASSERT_TRUE(https_server_www_example_domain_.Start());
+
+ host_resolver()->AddRule("example.com", "127.0.0.1");
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+
+ GURL https_server_url =
+ https_server_www_example_domain_.GetURL("files/ssl/google.html?a=b");
+ GURL::Replacements replacements;
+ replacements.SetHostStr("example.com");
+ GURL https_server_mismatched_url =
+ https_server_url.ReplaceComponents(replacements);
+
+ ui_test_utils::NavigateToURL(browser(), https_server_mismatched_url);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ WaitForInterstitialAttach(contents);
+ CheckAuthenticationBrokenState(contents, net::CERT_STATUS_COMMON_NAME_INVALID,
+ AuthState::SHOWING_INTERSTITIAL);
+ EXPECT_EQ(SSLBlockingPage::kTypeForTesting, contents->GetInterstitialPage()
+ ->GetDelegateForTesting()
+ ->GetTypeForTesting());
+
+ EXPECT_TRUE(
+ WaitForRenderFrameReady(contents->GetInterstitialPage()->GetMainFrame()));
+ // The interstitial should display a link to www.example.com
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "www.example.com"));
+ // Verify that the link has the text "suggest-link", the id of the
+ // link element displayed.
+ EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText(
+ contents->GetInterstitialPage(), "suggest-link"));
+}
+
+// This observer waits for the SSLErrorHandler to start an interstitial timer
+// for the given web contents.
+class SSLInterstitialTimerObserver {
+ public:
+ explicit SSLInterstitialTimerObserver(content::WebContents* web_contents);
+ ~SSLInterstitialTimerObserver();
+
+ // Waits until the interstitial delay timer in SSLErrorHandler is started.
+ void WaitForTimerStarted();
+
+ private:
+ void OnTimerStarted(content::WebContents* web_contents);
+
+ const content::WebContents* web_contents_;
+ SSLErrorHandler::TimerStartedCallback callback_;
+
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLInterstitialTimerObserver);
+};
+
+SSLInterstitialTimerObserver::SSLInterstitialTimerObserver(
+ content::WebContents* web_contents)
+ : web_contents_(web_contents),
+ message_loop_runner_(new content::MessageLoopRunner) {
+ callback_ = base::Bind(&SSLInterstitialTimerObserver::OnTimerStarted,
+ base::Unretained(this));
+ SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(&callback_);
+}
+
+SSLInterstitialTimerObserver::~SSLInterstitialTimerObserver() {
+ SSLErrorHandler::SetInterstitialTimerStartedCallbackForTest(nullptr);
+}
+
+void SSLInterstitialTimerObserver::WaitForTimerStarted() {
+ message_loop_runner_->Run();
+}
+
+void SSLInterstitialTimerObserver::OnTimerStarted(
+ content::WebContents* web_contents) {
+ if (web_contents_ == web_contents && message_loop_runner_.get())
+ message_loop_runner_->Quit();
+}
+
+// Tests this scenario:
+// - |CommonNameMismatchHandler| does not give a callback as it's set into the
+// state |IGNORE_REQUESTS_FOR_TESTING|. So no suggested URL check result can
+// arrive.
+// - A cert error triggers an interstitial timer with a very long timeout.
+// - No suggested URL check results arrive, causing the tab to appear as loading
+// indefinitely (also because the timer has a long timeout).
+// - Stopping the page load shouldn't result in any interstitials.
+IN_PROC_BROWSER_TEST_F(SSLUITest, InterstitialStopNavigationWhileLoading) {
+ // Starts a server with a valid certificate for "example.com".
+ ASSERT_TRUE(https_server_example_domain_.Start());
+
+ host_resolver()->AddRule("example.com", "127.0.0.1");
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+
+ GURL https_server_url =
+ https_server_example_domain_.GetURL("files/ssl/google.html?a=b");
+ GURL::Replacements replacements;
+ replacements.SetHostStr("www.example.com");
+ GURL https_server_mismatched_url =
+ https_server_url.ReplaceComponents(replacements);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ CommonNameMismatchHandler::set_state_for_testing(
+ CommonNameMismatchHandler::IGNORE_REQUESTS_FOR_TESTING);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_mismatched_url, CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+ contents->Stop();
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
+// Same as above, but instead of stopping, the loading page is reloaded. The end
+// result is the same. (i.e. page load stops, no interstitials shown)
+IN_PROC_BROWSER_TEST_F(SSLUITest, InterstitialReloadNavigationWhileLoading) {
+ // Starts a server with a valid certificate for "example.com".
+ ASSERT_TRUE(https_server_example_domain_.Start());
+
+ host_resolver()->AddRule("example.com", "127.0.0.1");
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+
+ GURL https_server_url =
+ https_server_example_domain_.GetURL("files/ssl/google.html?a=b");
+ GURL::Replacements replacements;
+ replacements.SetHostStr("www.example.com");
+ GURL https_server_mismatched_url =
+ https_server_url.ReplaceComponents(replacements);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ CommonNameMismatchHandler::set_state_for_testing(
+ CommonNameMismatchHandler::IGNORE_REQUESTS_FOR_TESTING);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_mismatched_url, CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::TestNavigationObserver observer(contents, 1);
+ chrome::Reload(browser(), CURRENT_TAB);
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
+// Same as above, but instead of reloading, the page is navigated away. The
+// new page should load, and no interstitials should be shown.
+IN_PROC_BROWSER_TEST_F(SSLUITest, InterstitialNavigateAwayWhileLoading) {
+ // Starts a server with a valid certificate for "example.com".
+ ASSERT_TRUE(https_server_example_domain_.Start());
+
+ host_resolver()->AddRule("example.com", "127.0.0.1");
+ host_resolver()->AddRule("www.example.com", "127.0.0.1");
+
+ GURL https_server_url =
+ https_server_example_domain_.GetURL("files/ssl/google.html?a=b");
+ GURL::Replacements replacements;
+ replacements.SetHostStr("www.example.com");
+ GURL https_server_mismatched_url =
+ https_server_url.ReplaceComponents(replacements);
+
+ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+ CommonNameMismatchHandler::set_state_for_testing(
+ CommonNameMismatchHandler::IGNORE_REQUESTS_FOR_TESTING);
+ SSLInterstitialTimerObserver interstitial_timer_observer(contents);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), https_server_mismatched_url, CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+ interstitial_timer_observer.WaitForTimerStarted();
+
+ EXPECT_TRUE(contents->IsLoading());
+ content::TestNavigationObserver observer(contents, 1);
+ browser()->OpenURL(content::OpenURLParams(GURL("https://google.com"),
+ content::Referrer(), CURRENT_TAB,
+ ui::PAGE_TRANSITION_TYPED, false));
+ observer.Wait();
+
+ SSLErrorHandler* ssl_error_handler =
+ SSLErrorHandler::FromWebContents(contents);
+ // Make sure that the |SSLErrorHandler| is deleted.
+ EXPECT_FALSE(ssl_error_handler);
+ EXPECT_FALSE(contents->ShowingInterstitialPage());
+ EXPECT_FALSE(contents->IsLoading());
+}
+
class SSLBlockingPageIDNTest : public SecurityInterstitialIDNTest {
protected:
// SecurityInterstitialIDNTest implementation
@@ -2233,9 +2544,10 @@ class SSLBlockingPageIDNTest : public SecurityInterstitialIDNTest {
net::SSLInfo ssl_info;
ssl_info.cert = new net::X509Certificate(
request_url.host(), "CA", base::Time::Max(), base::Time::Max());
- return new SSLBlockingPage(
- contents, net::ERR_CERT_CONTAINS_ERRORS, ssl_info, request_url, 0,
- base::Time::NowFromSystemTime(), nullptr, base::Callback<void(bool)>());
+ return new SSLBlockingPage(contents, net::ERR_CERT_CONTAINS_ERRORS,
+ ssl_info, request_url, 0,
+ base::Time::NowFromSystemTime(), nullptr,
+ base::Callback<void(bool)>(), GURL());
}
};

Powered by Google App Engine
This is Rietveld 408576698