// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include "chrome/common/filter_policy.h" #include "chrome/common/pref_names.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/ui/ui_test.h" #include "net/base/ssl_test_util.h" #include "net/url_request/url_request_unittest.h" namespace { const wchar_t kDocRoot[] = L"chrome/test/data"; class SSLUITest : public UITest { protected: SSLUITest() { dom_automation_enabled_ = true; } TabProxy* GetActiveTabProxy() { scoped_ptr browser_proxy(automation()->GetBrowserWindow(0)); EXPECT_TRUE(browser_proxy.get()); return browser_proxy->GetActiveTab(); } void NavigateTab(TabProxy* tab_proxy, const GURL& url) { ASSERT_TRUE(tab_proxy->NavigateToURL(url)); } void AppendTab(const GURL& url) { scoped_ptr browser_proxy(automation()->GetBrowserWindow(0)); EXPECT_TRUE(browser_proxy.get()); EXPECT_TRUE(browser_proxy->AppendTab(url)); } scoped_refptr PlainServer() { return HTTPTestServer::CreateServer(kDocRoot, NULL); } scoped_refptr GoodCertServer() { return HTTPSTestServer::CreateGoodServer(kDocRoot); } scoped_refptr BadCertServer() { return HTTPSTestServer::CreateExpiredServer(kDocRoot); } protected: DISALLOW_COPY_AND_ASSIGN(SSLUITest); }; } // namespace // Visits a regular page over http. TEST_F(SSLUITest, TestHTTP) { scoped_refptr server = PlainServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), server->TestServerPageW(L"files/ssl/google.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visits a page over http which includes broken https resources (status should // be OK). TEST_F(SSLUITest, TestHTTPWithBrokenHTTPSResource) { scoped_refptr http_server = PlainServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab( tab.get(), http_server->TestServerPageW( L"files/ssl/page_with_unsafe_contents.html")); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visits a page over OK https: TEST_F(SSLUITest, TestOKHTTPS) { scoped_refptr https_server = GoodCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), https_server->TestServerPageW(L"files/ssl/google.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visits a page with https error and proceed: TEST_F(SSLUITest, TestHTTPSExpiredCertAndProceed) { scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), bad_https_server->TestServerPageW(L"files/ssl/google.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::INTERSTITIAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visits a page with https error and don't proceed (and ensure we can still // navigate at that point): TEST_F(SSLUITest, TestHTTPSExpiredCertAndDontProceed) { scoped_refptr http_server = PlainServer(); scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); // First navigate to an OK page. NavigateTab(tab.get(), good_https_server->TestServerPageW(L"files/ssl/google.html")); GURL cross_site_url = bad_https_server->TestServerPageW(L"files/ssl/google.html"); // Change the host name from 127.0.0.1 to localhost so it triggers a // cross-site navigation so we can test http://crbug.com/5800 is gone. ASSERT_EQ("127.0.0.1", cross_site_url.host()); GURL::Replacements replacements; std::string new_host("localhost"); replacements.SetHostStr(new_host); cross_site_url = cross_site_url.ReplaceComponents(replacements); // Now go to a bad HTTPS page. NavigateTab(tab.get(), cross_site_url); // An interstitial should be showing. NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::INTERSTITIAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Simulate user clicking "Take me back". EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(false)); // We should be back to the original good page. EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Try to navigate to a new page. (to make sure bug 5800 is fixed). NavigateTab(tab.get(), http_server->TestServerPageW(L"files/ssl/google.html")); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); } // // Mixed contents // // Visits a page with mixed content. TEST_F(SSLUITest, TestMixedContents) { scoped_refptr https_server = GoodCertServer(); scoped_refptr http_server = PlainServer(); // Load a page with mixed-content, the default behavior is to show the mixed // content. scoped_ptr tab(GetActiveTabProxy()); NavigateTab( tab.get(), https_server->TestServerPageW( L"files/ssl/page_with_mixed_contents.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::MIXED_CONTENT, mixed_content_state); // Now select the block mixed-content pref and reload the page. scoped_ptr browser_proxy(automation()->GetBrowserWindow(0)); EXPECT_TRUE(browser_proxy.get()); EXPECT_TRUE(browser_proxy->SetIntPreference(prefs::kMixedContentFiltering, FilterPolicy::FILTER_ALL)); EXPECT_TRUE(tab->Reload()); // The image should be filtered. int img_width; EXPECT_TRUE(tab->ExecuteAndExtractInt(L"", L"window.domAutomationController.send(ImageWidth());", &img_width)); // In order to check that the image was not loaded, we check its width. // The actual image (Google logo) is 114 pixels wide, we assume the broken // image is less than 100. EXPECT_GT(100, img_width); // The state should be OK since we are not showing the resource. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // There should be one info-bar to show the mixed-content. int info_bar_count = 0; EXPECT_TRUE(tab->GetSSLInfoBarCount(&info_bar_count)); EXPECT_EQ(1, info_bar_count); // Activate the link on the info-bar to show the mixed-content. EXPECT_TRUE(tab->ClickSSLInfoBarLink(0, true)); // The image should show now. EXPECT_TRUE(tab->ExecuteAndExtractInt(L"", L"window.domAutomationController.send(ImageWidth());", &img_width)); EXPECT_LT(100, img_width); // And our status should be mixed-content. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::MIXED_CONTENT, mixed_content_state); } // Visits a page with unsafe content and make sure that: // - frames content is replaced with warning // - images and scripts are filtered out entirely TEST_F(SSLUITest, TestUnsafeContents) { scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), good_https_server->TestServerPageW( L"files/ssl/page_with_unsafe_contents.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; // When the bad content is filtered, the state is expected to be // authenticated. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Because of cross-frame scripting restrictions, we cannot access the iframe // content. So to know if the frame was loaded, we just check if a popup was // opened (the iframe content opens one). // Note: because of bug 1115868, no constrained window is opened right now. // Once the bug is fixed, this will do the real check. int constrained_window_count = 0; EXPECT_TRUE(tab->GetConstrainedWindowCount(&constrained_window_count)); EXPECT_EQ(0, constrained_window_count); int img_width; EXPECT_TRUE(tab->ExecuteAndExtractInt(L"", L"window.domAutomationController.send(ImageWidth());", &img_width)); // In order to check that the image was not loaded, we check its width. // The actual image (Google logo) is 114 pixels wide, we assume the broken // image is less than 100. EXPECT_GT(100, img_width); bool js_result = false; EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(IsFooSet());", &js_result)); EXPECT_FALSE(js_result); } // Visits a page with mixed content loaded by JS (after the initial page load). TEST_F(SSLUITest, TestMixedContentsLoadedFromJS) { scoped_refptr https_server = GoodCertServer(); scoped_refptr http_server = PlainServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), https_server->TestServerPageW( L"files/ssl/page_with_dynamic_mixed_contents.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Load the insecure image. bool js_result = false; EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"loadBadImage();", &js_result)); EXPECT_TRUE(js_result); // We should now have mixed-contents. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::MIXED_CONTENT, mixed_content_state); } // Visits a page with an image over http. Visits another page over https // referencing that same image over http (hoping it is coming from the webcore // memory cache). TEST_F(SSLUITest, TestCachedMixedContents) { scoped_refptr https_server = GoodCertServer(); scoped_refptr http_server = PlainServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), http_server->TestServerPageW( L"files/ssl/page_with_mixed_contents.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Load again but over SSL. It should have mixed-contents (even though the // image comes from the WebCore memory cache). NavigateTab(tab.get(), https_server->TestServerPageW( L"files/ssl/page_with_mixed_contents.html")); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::MIXED_CONTENT, mixed_content_state); } // This test ensures the CN invalid status does not 'stick' to a certificate // (see bug #1044942) and that it depends on the host-name. // TODO(jcampan): this test is flacky and fails sometimes (bug #1065095) TEST_F(SSLUITest, DISABLED_TestCNInvalidStickiness) { const std::string kLocalHost = "localhost"; scoped_refptr https_server = HTTPSTestServer::CreateMismatchedServer(kDocRoot); ASSERT_TRUE(NULL != https_server.get()); // First we hit the server with hostname, this generates an invalid policy // error. scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), https_server->TestServerPageW( L"files/ssl/google.html")); // We get an interstitial page as a result. NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::INTERSTITIAL_PAGE, page_type); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_COMMON_NAME_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // We proceed through the interstitial page. EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); // Now we try again with the right host name this time. // Let's change the host-name in the url. GURL url = https_server->TestServerPageW(L"files/ssl/google.html"); std::string::size_type hostname_index = url.spec().find(kLocalHost); ASSERT_TRUE(hostname_index != std::string::npos); // Test sanity check. std::string new_url; new_url.append(url.spec().substr(0, hostname_index)); new_url.append(net::TestServerLauncher::kHostName); new_url.append(url.spec().substr(hostname_index + kLocalHost.size())); NavigateTab(tab.get(), GURL(new_url)); // Security state should be OK. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Now try again the broken one to make sure it is still broken. NavigateTab(tab.get(), https_server->TestServerPageW( L"files/ssl/google.html")); EXPECT_TRUE(tab->GetPageType(&page_type)); // Since we OKed the interstitial last time, we get right to the page. EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_COMMON_NAME_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Test that navigating to a #ref does not change a bad security state. TEST_F(SSLUITest, TestRefNavigation) { scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab( tab.get(), bad_https_server->TestServerPageW(L"files/ssl/page_with_refs.html")); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(page_type, NavigationEntry::INTERSTITIAL_PAGE); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(NavigationEntry::NORMAL_PAGE, page_type); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Now navigate to a ref in the page. NavigateTab(tab.get(), bad_https_server->TestServerPageW(L"files/ssl/page_with_refs.html#jp")); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Tests that closing a page that has a unsafe pop-up does not crash the browser // (bug #1966). // Disabled because flaky (bug #2136). TEST_F(SSLUITest, DISABLED_TestCloseTabWithUnsafePopup) { scoped_refptr http_server = PlainServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), http_server->TestServerPageW( L"files/ssl/page_with_unsafe_popup.html")); int popup_count = 0; EXPECT_TRUE(tab->GetConstrainedWindowCount(&popup_count)); EXPECT_EQ(1, popup_count); // Let's add another tab to make sure the browser does not exit when we close // the first tab. scoped_ptr browser_proxy(automation()->GetBrowserWindow(0)); EXPECT_TRUE(browser_proxy.get()); browser_proxy->AppendTab( http_server->TestServerPageW(L"files/ssl/google.html")); // Close the first tab. tab->Close(); } // Visit a page over bad https that is a redirect to a page with good https. TEST_F(SSLUITest, TestRedirectBadToGoodHTTPS) { scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); GURL url1 = bad_https_server->TestServerPageW(L"server-redirect?"); GURL url2 = good_https_server->TestServerPageW(L"files/ssl/google.html"); NavigateTab(tab.get(), GURL(url1.spec() + url2.spec())); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(page_type, NavigationEntry::INTERSTITIAL_PAGE); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); // We have been redirected to the good page. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); // No errors expected. EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visit a page over good https that is a redirect to a page with bad https. TEST_F(SSLUITest, TestRedirectGoodToBadHTTPS) { scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); GURL url1 = good_https_server->TestServerPageW(L"server-redirect?"); GURL url2 = bad_https_server->TestServerPageW(L"files/ssl/google.html"); NavigateTab(tab.get(), GURL(url1.spec() + url2.spec())); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(page_type, NavigationEntry::INTERSTITIAL_PAGE); EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visit a page over http that is a redirect to a page with https (good and // bad). TEST_F(SSLUITest, TestRedirectHTTPToHTTPS) { scoped_refptr http_server = PlainServer(); scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); // HTTP redirects to good HTTPS. scoped_ptr tab(GetActiveTabProxy()); GURL http_url = http_server->TestServerPageW(L"server-redirect?"); GURL good_https_url = good_https_server->TestServerPageW(L"files/ssl/google.html"); NavigateTab(tab.get(), GURL(http_url.spec() + good_https_url.spec())); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // HTTP redirects to bad HTTPS. GURL bad_https_url = bad_https_server->TestServerPageW(L"files/ssl/google.html"); NavigateTab(tab.get(), GURL(http_url.spec() + bad_https_url.spec())); NavigationEntry::PageType page_type; EXPECT_TRUE(tab->GetPageType(&page_type)); EXPECT_EQ(page_type, NavigationEntry::INTERSTITIAL_PAGE); // Continue on the interstitial. EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visit a page over https that is a redirect to a page with http (to make sure // we don't keep the secure state). TEST_F(SSLUITest, TestRedirectHTTPSToHTTP) { scoped_refptr http_server = PlainServer(); scoped_refptr https_server = GoodCertServer(); scoped_ptr tab(GetActiveTabProxy()); GURL https_url = https_server->TestServerPageW(L"server-redirect?"); GURL http_url = http_server->TestServerPageW(L"files/ssl/google.html"); NavigateTab(tab.get(), GURL(https_url.spec() + http_url.spec())); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // Visits a page to which we could not connect (bad port) over http and https // and make sure the security style is correct. TEST_F(SSLUITest, TestConnectToBadPort) { scoped_ptr tab(GetActiveTabProxy()); GURL http_url("http://localhost:17"); NavigateTab(tab.get(), http_url); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Same thing over HTTPS. GURL https_url("https://localhost:17"); NavigateTab(tab.get(), https_url); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // // Frame navigation // // From a good HTTPS top frame: // - navigate to an OK HTTPS frame // - navigate to a bad HTTPS (expect unsafe content and filtered frame), then // back // - navigate to HTTP (expect mixed content), then back TEST_F(SSLUITest, TestGoodFrameNavigation) { scoped_refptr http_server = PlainServer(); scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), good_https_server->TestServerPageW(L"files/ssl/top_frame.html")); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); bool success = false; // Now navigate inside the frame. int64 last_nav_time = 0; EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // We should still be fine. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Now let's hit a bad page. EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('badHTTPSLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // The security style should still be secure. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // And the frame should be blocked. bool is_content_evil = true; std::wstring content_frame_xpath(L"html/frameset/frame[2]"); std::wstring is_frame_evil_js( L"window.domAutomationController" L".send(document.getElementById('evilDiv') != null);"); EXPECT_TRUE(tab->ExecuteAndExtractBool(content_frame_xpath, is_frame_evil_js, &is_content_evil)); EXPECT_FALSE(is_content_evil); // Now go back, our state should return to OK. EXPECT_TRUE(tab->GoBack()); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Navigate to a page served over HTTP. EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('HTTPLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // Our state should be mixed-content. // Status should be "contains bad contents". EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::MIXED_CONTENT, mixed_content_state); // Go back, our state should be back to OK. EXPECT_TRUE(tab->GoBack()); EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // From a bad HTTPS top frame: // - navigate to an OK HTTPS frame (expected to be still authentication broken). TEST_F(SSLUITest, TestBadFrameNavigation) { scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), bad_https_server->TestServerPageW(L"files/ssl/top_frame.html")); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Continue on the interstitial. EXPECT_TRUE(tab->TakeActionOnSSLBlockingPage(true)); // Navigate to a good frame. bool success = false; int64 last_nav_time = 0; EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // We should still be authentication broken. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN, security_style); EXPECT_EQ(net::CERT_STATUS_DATE_INVALID, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); } // From an HTTP top frame, navigate to good and bad HTTPS (security state should // stay unauthenticated). TEST_F(SSLUITest, TestUnauthenticatedFrameNavigation) { scoped_refptr http_server = PlainServer(); scoped_refptr good_https_server = GoodCertServer(); scoped_refptr bad_https_server = BadCertServer(); scoped_ptr tab(GetActiveTabProxy()); NavigateTab(tab.get(), http_server->TestServerPageW(L"files/ssl/top_frame.html")); SecurityStyle security_style; int cert_status; int mixed_content_state; EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Now navigate inside the frame to a secure HTTPS frame. bool success = false; int64 last_nav_time = 0; EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('goodHTTPSLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // We should still be unauthenticated. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // Now navigate to a bad HTTPS frame. EXPECT_TRUE(tab->GetLastNavigationTime(&last_nav_time)); EXPECT_TRUE(tab->ExecuteAndExtractBool(L"", L"window.domAutomationController.send(clickLink('badHTTPSLink'));", &success)); EXPECT_TRUE(success); EXPECT_TRUE(tab->WaitForNavigation(last_nav_time)); // State should not have changed. EXPECT_TRUE(tab->GetSecurityState(&security_style, &cert_status, &mixed_content_state)); EXPECT_EQ(SECURITY_STYLE_UNAUTHENTICATED, security_style); EXPECT_EQ(0, cert_status & net::CERT_STATUS_ALL_ERRORS); EXPECT_EQ(NavigationEntry::SSLStatus::NORMAL_CONTENT, mixed_content_state); // And the frame should have been blocked (see bug #2316). bool is_content_evil = true; std::wstring content_frame_xpath(L"html/frameset/frame[2]"); std::wstring is_frame_evil_js( L"window.domAutomationController" L".send(document.getElementById('evilDiv') != null);"); EXPECT_TRUE(tab->ExecuteAndExtractBool(content_frame_xpath, is_frame_evil_js, &is_content_evil)); EXPECT_FALSE(is_content_evil); } // TODO(jcampan): more tests to do below. // Visit a page over https that contains a frame with a redirect. // XMLHttpRequest mixed in synchronous mode. // XMLHttpRequest mixed in asynchronous mode. // XMLHttpRequest over bad ssl in synchronous mode. // XMLHttpRequest over OK ssl in synchronous mode.