| 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 ee444e10b774b24f561bb50bf656c51b20075a06..e7f082f610e3bfbd71933e6757faf9c38a9d84e2 100644
|
| --- a/chrome/browser/ssl/ssl_browser_tests.cc
|
| +++ b/chrome/browser/ssl/ssl_browser_tests.cc
|
| @@ -106,6 +106,7 @@
|
| #include "net/ssl/ssl_info.h"
|
| #include "net/test/cert_test_util.h"
|
| #include "net/test/embedded_test_server/embedded_test_server.h"
|
| +#include "net/test/embedded_test_server/http_request.h"
|
| #include "net/test/embedded_test_server/request_handler_util.h"
|
| #include "net/test/spawned_test_server/spawned_test_server.h"
|
| #include "net/test/test_certificate_data.h"
|
| @@ -3603,10 +3604,56 @@ IN_PROC_BROWSER_TEST_F(SSLNetworkTimeBrowserTest,
|
| TriggerTimeResponse();
|
| }
|
|
|
| +namespace {
|
| +
|
| +// Fails with a CHECK for all requests over HTTP except for favicons. This is to
|
| +// ensure that name mismatch redirect feature's suggest URL ping stops on
|
| +// redirects and never hits an HTTP URL.
|
| +class HttpNameMismatchPingInterceptor : public net::URLRequestInterceptor {
|
| + public:
|
| + HttpNameMismatchPingInterceptor() {}
|
| + ~HttpNameMismatchPingInterceptor() override {}
|
| +
|
| + net::URLRequestJob* MaybeInterceptRequest(
|
| + net::URLRequest* request,
|
| + net::NetworkDelegate* delegate) const override {
|
| + if (request->url().path() == "/favicon.ico") {
|
| + // When a page doesn't list a favicon, a favicon request is automatically
|
| + // made over HTTP. These are harmless and don't leak the original page's
|
| + // URL, so ignore them.
|
| + return nullptr;
|
| + }
|
| +
|
| + EXPECT_TRUE(false)
|
| + << "Name mismatch pings must never be over HTTP. This request was for "
|
| + << request->url();
|
| + return nullptr;
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(HttpNameMismatchPingInterceptor);
|
| +};
|
| +
|
| +void SetUpHttpNameMismatchPingInterceptorOnIOThread() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + // Add interceptors for HTTP versions of example.org and www.example.org.
|
| + // These are the hostnames used in the tests, and we never want them to be
|
| + // contacted over HTTP.
|
| + net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
|
| + "http", "example.org",
|
| + std::unique_ptr<HttpNameMismatchPingInterceptor>(
|
| + new HttpNameMismatchPingInterceptor()));
|
| + net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
|
| + "http", "www.example.org",
|
| + std::unique_ptr<HttpNameMismatchPingInterceptor>(
|
| + new HttpNameMismatchPingInterceptor()));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| class CommonNameMismatchBrowserTest : public CertVerifierBrowserTest {
|
| public:
|
| CommonNameMismatchBrowserTest() : CertVerifierBrowserTest() {}
|
| - ~CommonNameMismatchBrowserTest() override {}
|
|
|
| void SetUpCommandLine(base::CommandLine* command_line) override {
|
| // Enable finch experiment for SSL common name mismatch handling.
|
| @@ -3617,6 +3664,15 @@ class CommonNameMismatchBrowserTest : public CertVerifierBrowserTest {
|
| void SetUpOnMainThread() override {
|
| CertVerifierBrowserTest::SetUpOnMainThread();
|
| host_resolver()->AddRule("*", "127.0.0.1");
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&SetUpHttpNameMismatchPingInterceptorOnIOThread));
|
| + }
|
| +
|
| + void TearDownOnMainThread() override {
|
| + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&CleanUpOnIOThread));
|
| + CertVerifierBrowserTest::TearDownOnMainThread();
|
| }
|
| };
|
|
|
| @@ -3625,14 +3681,14 @@ class CommonNameMismatchBrowserTest : public CertVerifierBrowserTest {
|
| // mail.example.com.
|
| IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| ShouldShowWWWSubdomainMismatchInterstitial) {
|
| - net::EmbeddedTestServer https_server_example_domain_(
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| net::EmbeddedTestServer::TYPE_HTTPS);
|
| - https_server_example_domain_.ServeFilesFromSourceDirectory(
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| base::FilePath(kDocRoot));
|
| - ASSERT_TRUE(https_server_example_domain_.Start());
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
|
|
| scoped_refptr<net::X509Certificate> cert =
|
| - https_server_example_domain_.GetCertificate();
|
| + https_server_example_domain.GetCertificate();
|
|
|
| // Use the "spdy_pooling.pem" cert which has "mail.example.com"
|
| // as one of its SANs.
|
| @@ -3656,11 +3712,11 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
|
|
| // Use a complex URL to ensure the path, etc., are preserved. The path itself
|
| // does not matter.
|
| - GURL https_server_url =
|
| - https_server_example_domain_.GetURL("/ssl/google.html?a=b#anchor");
|
| + const GURL https_server_url =
|
| + https_server_example_domain.GetURL("/ssl/google.html?a=b#anchor");
|
| GURL::Replacements replacements;
|
| replacements.SetHostStr("www.mail.example.com");
|
| - GURL https_server_mismatched_url =
|
| + const GURL https_server_mismatched_url =
|
| https_server_url.ReplaceComponents(replacements);
|
|
|
| WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
| @@ -3685,14 +3741,14 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| // for www.example.org. Verify that the page redirects to www.example.org.
|
| IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| CheckWWWSubdomainMismatchInverse) {
|
| - net::EmbeddedTestServer https_server_example_domain_(
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| net::EmbeddedTestServer::TYPE_HTTPS);
|
| - https_server_example_domain_.ServeFilesFromSourceDirectory(
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| base::FilePath(kDocRoot));
|
| - ASSERT_TRUE(https_server_example_domain_.Start());
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
|
|
| scoped_refptr<net::X509Certificate> cert =
|
| - https_server_example_domain_.GetCertificate();
|
| + https_server_example_domain.GetCertificate();
|
|
|
| net::CertVerifyResult verify_result;
|
| verify_result.verified_cert =
|
| @@ -3709,11 +3765,11 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| mock_cert_verifier()->AddResultForCertAndHost(cert.get(), "www.example.org",
|
| verify_result_valid, net::OK);
|
|
|
| - GURL https_server_url =
|
| - https_server_example_domain_.GetURL("/ssl/google.html?a=b");
|
| + const GURL https_server_url =
|
| + https_server_example_domain.GetURL("/ssl/google.html?a=b");
|
| GURL::Replacements replacements;
|
| replacements.SetHostStr("example.org");
|
| - GURL https_server_mismatched_url =
|
| + const GURL https_server_mismatched_url =
|
| https_server_url.ReplaceComponents(replacements);
|
|
|
| WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
| @@ -3729,6 +3785,85 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| AuthState::NONE);
|
| }
|
|
|
| +namespace {
|
| +// Redirects incoming request to http://example.org.
|
| +std::unique_ptr<net::test_server::HttpResponse> HTTPSToHTTPRedirectHandler(
|
| + const net::EmbeddedTestServer* test_server,
|
| + const net::test_server::HttpRequest& request) {
|
| + GURL::Replacements replacements;
|
| + replacements.SetHostStr("example.org");
|
| + replacements.SetSchemeStr("http");
|
| + const GURL redirect_url =
|
| + test_server->base_url().ReplaceComponents(replacements);
|
| +
|
| + std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
|
| + new net::test_server::BasicHttpResponse);
|
| + http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
|
| + http_response->AddCustomHeader("Location", redirect_url.spec());
|
| + return std::move(http_response);
|
| +}
|
| +} // namespace
|
| +
|
| +// Common name mismatch handling feature should ignore redirects when pinging
|
| +// the suggested hostname. Visit the URL example.org on a server that presents a
|
| +// valid certificate for www.example.org. In this case, www.example.org
|
| +// redirects to http://example.org, and the SSL error should not be redirected
|
| +// to this URL.
|
| +IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| + WWWSubdomainMismatch_StopOnRedirects) {
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| + net::EmbeddedTestServer::TYPE_HTTPS);
|
| +
|
| + // Redirect all URLs to http://example.org. Since this test will trigger only
|
| + // one request to check the suggested URL, redirecting all requests is OK.
|
| + // We would normally use content::SetupCrossSiteRedirector here, but that
|
| + // function does not support https to http redirects.
|
| + // This must be done before ServeFilesFromSourceDirectory(), otherwise the
|
| + // test server will serve files instead of redirecting requests to them.
|
| + https_server_example_domain.RegisterRequestHandler(
|
| + base::Bind(&HTTPSToHTTPRedirectHandler, &https_server_example_domain));
|
| +
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| + base::FilePath(kDocRoot));
|
| +
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
| +
|
| + scoped_refptr<net::X509Certificate> cert =
|
| + https_server_example_domain.GetCertificate();
|
| +
|
| + net::CertVerifyResult verify_result;
|
| + verify_result.verified_cert =
|
| + net::ImportCertFromFile(net::GetTestCertsDirectory(), "spdy_pooling.pem");
|
| + verify_result.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
|
| +
|
| + mock_cert_verifier()->AddResultForCertAndHost(
|
| + cert.get(), "example.org", verify_result,
|
| + net::ERR_CERT_COMMON_NAME_INVALID);
|
| +
|
| + net::CertVerifyResult verify_result_valid;
|
| + verify_result_valid.verified_cert =
|
| + net::ImportCertFromFile(net::GetTestCertsDirectory(), "spdy_pooling.pem");
|
| + mock_cert_verifier()->AddResultForCertAndHost(cert.get(), "www.example.org",
|
| + verify_result_valid, net::OK);
|
| +
|
| + // The user will visit https://example.org:port/ssl/blank.html.
|
| + GURL::Replacements replacements;
|
| + replacements.SetHostStr("example.org");
|
| + const GURL https_server_mismatched_url =
|
| + https_server_example_domain.GetURL("/ssl/blank.html")
|
| + .ReplaceComponents(replacements);
|
| +
|
| + // Should simply show an interstitial, because the suggested URL
|
| + // (https://www.example.org) redirected to http://example.org.
|
| + WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
| + ui_test_utils::NavigateToURL(browser(), https_server_mismatched_url);
|
| + WaitForInterstitialAttach(contents);
|
| +
|
| + CheckSecurityState(contents, net::CERT_STATUS_COMMON_NAME_INVALID,
|
| + security_state::DANGEROUS,
|
| + AuthState::SHOWING_INTERSTITIAL);
|
| +}
|
| +
|
| // 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
|
| @@ -3739,14 +3874,14 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| // - Stopping the page load shouldn't result in any interstitials.
|
| IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| InterstitialStopNavigationWhileLoading) {
|
| - net::EmbeddedTestServer https_server_example_domain_(
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| net::EmbeddedTestServer::TYPE_HTTPS);
|
| - https_server_example_domain_.ServeFilesFromSourceDirectory(
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| base::FilePath(kDocRoot));
|
| - ASSERT_TRUE(https_server_example_domain_.Start());
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
|
|
| scoped_refptr<net::X509Certificate> cert =
|
| - https_server_example_domain_.GetCertificate();
|
| + https_server_example_domain.GetCertificate();
|
|
|
| net::CertVerifyResult verify_result;
|
| verify_result.verified_cert =
|
| @@ -3763,11 +3898,11 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| mock_cert_verifier()->AddResultForCertAndHost(cert.get(), "mail.example.com",
|
| verify_result_valid, net::OK);
|
|
|
| - GURL https_server_url =
|
| - https_server_example_domain_.GetURL("/ssl/google.html?a=b");
|
| + const GURL https_server_url =
|
| + https_server_example_domain.GetURL("/ssl/google.html?a=b");
|
| GURL::Replacements replacements;
|
| replacements.SetHostStr("www.mail.example.com");
|
| - GURL https_server_mismatched_url =
|
| + const GURL https_server_mismatched_url =
|
| https_server_url.ReplaceComponents(replacements);
|
|
|
| WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
| @@ -3802,14 +3937,14 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| // result is the same. (i.e. page load stops, no interstitials shown)
|
| IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| InterstitialReloadNavigationWhileLoading) {
|
| - net::EmbeddedTestServer https_server_example_domain_(
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| net::EmbeddedTestServer::TYPE_HTTPS);
|
| - https_server_example_domain_.ServeFilesFromSourceDirectory(
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| base::FilePath(kDocRoot));
|
| - ASSERT_TRUE(https_server_example_domain_.Start());
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
|
|
| scoped_refptr<net::X509Certificate> cert =
|
| - https_server_example_domain_.GetCertificate();
|
| + https_server_example_domain.GetCertificate();
|
|
|
| net::CertVerifyResult verify_result;
|
| verify_result.verified_cert =
|
| @@ -3826,11 +3961,11 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| mock_cert_verifier()->AddResultForCertAndHost(cert.get(), "mail.example.com",
|
| verify_result_valid, net::OK);
|
|
|
| - GURL https_server_url =
|
| - https_server_example_domain_.GetURL("/ssl/google.html?a=b");
|
| + const GURL https_server_url =
|
| + https_server_example_domain.GetURL("/ssl/google.html?a=b");
|
| GURL::Replacements replacements;
|
| replacements.SetHostStr("www.mail.example.com");
|
| - GURL https_server_mismatched_url =
|
| + const GURL https_server_mismatched_url =
|
| https_server_url.ReplaceComponents(replacements);
|
|
|
| WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
| @@ -3863,14 +3998,14 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| // new page should load, and no interstitials should be shown.
|
| IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| InterstitialNavigateAwayWhileLoading) {
|
| - net::EmbeddedTestServer https_server_example_domain_(
|
| + net::EmbeddedTestServer https_server_example_domain(
|
| net::EmbeddedTestServer::TYPE_HTTPS);
|
| - https_server_example_domain_.ServeFilesFromSourceDirectory(
|
| + https_server_example_domain.ServeFilesFromSourceDirectory(
|
| base::FilePath(kDocRoot));
|
| - ASSERT_TRUE(https_server_example_domain_.Start());
|
| + ASSERT_TRUE(https_server_example_domain.Start());
|
|
|
| scoped_refptr<net::X509Certificate> cert =
|
| - https_server_example_domain_.GetCertificate();
|
| + https_server_example_domain.GetCertificate();
|
|
|
| net::CertVerifyResult verify_result;
|
| verify_result.verified_cert =
|
| @@ -3887,11 +4022,11 @@ IN_PROC_BROWSER_TEST_F(CommonNameMismatchBrowserTest,
|
| mock_cert_verifier()->AddResultForCertAndHost(cert.get(), "mail.example.com",
|
| verify_result_valid, net::OK);
|
|
|
| - GURL https_server_url =
|
| - https_server_example_domain_.GetURL("/ssl/google.html?a=b");
|
| + const GURL https_server_url =
|
| + https_server_example_domain.GetURL("/ssl/google.html?a=b");
|
| GURL::Replacements replacements;
|
| replacements.SetHostStr("www.mail.example.com");
|
| - GURL https_server_mismatched_url =
|
| + const GURL https_server_mismatched_url =
|
| https_server_url.ReplaceComponents(replacements);
|
|
|
| WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
|
|
|