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

Side by Side Diff: chrome/browser/ssl/ssl_error_handler_unittest.cc

Issue 2620203003: Add initial version of captive portal list checking. (Closed)
Patch Set: More tests and rebase Created 3 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/ssl_error_handler.h" 5 #include "chrome/browser/ssl/ssl_error_handler.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
11 #include "base/run_loop.h" 11 #include "base/run_loop.h"
12 #include "base/test/histogram_tester.h" 12 #include "base/test/histogram_tester.h"
13 #include "base/test/scoped_feature_list.h"
13 #include "base/test/simple_test_clock.h" 14 #include "base/test/simple_test_clock.h"
14 #include "base/test/simple_test_tick_clock.h" 15 #include "base/test/simple_test_tick_clock.h"
15 #include "base/time/time.h" 16 #include "base/time/time.h"
16 #include "chrome/browser/captive_portal/captive_portal_service.h" 17 #include "chrome/browser/captive_portal/captive_portal_service.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ssl/common_name_mismatch_handler.h" 19 #include "chrome/browser/ssl/common_name_mismatch_handler.h"
20 #include "chrome/browser/ssl/ssl_error_assistant.pb.h"
19 #include "chrome/common/features.h" 21 #include "chrome/common/features.h"
20 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 22 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
21 #include "chrome/test/base/testing_profile.h" 23 #include "chrome/test/base/testing_profile.h"
22 #include "components/captive_portal/captive_portal_testing_utils.h" 24 #include "components/captive_portal/captive_portal_testing_utils.h"
23 #include "components/network_time/network_time_test_utils.h" 25 #include "components/network_time/network_time_test_utils.h"
24 #include "components/network_time/network_time_tracker.h" 26 #include "components/network_time/network_time_tracker.h"
25 #include "components/prefs/testing_pref_service.h" 27 #include "components/prefs/testing_pref_service.h"
26 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
28 #include "net/base/net_errors.h" 30 #include "net/base/net_errors.h"
29 #include "net/cert/cert_status_flags.h" 31 #include "net/cert/cert_status_flags.h"
30 #include "net/cert/x509_certificate.h" 32 #include "net/cert/x509_certificate.h"
31 #include "net/http/http_response_headers.h" 33 #include "net/http/http_response_headers.h"
32 #include "net/ssl/ssl_info.h" 34 #include "net/ssl/ssl_info.h"
33 #include "net/test/cert_test_util.h" 35 #include "net/test/cert_test_util.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h" 36 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "net/test/embedded_test_server/http_response.h" 37 #include "net/test/embedded_test_server/http_response.h"
36 #include "net/test/test_certificate_data.h" 38 #include "net/test/test_certificate_data.h"
37 #include "net/test/test_data_directory.h" 39 #include "net/test/test_data_directory.h"
38 #include "net/url_request/url_request_test_util.h" 40 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gtest/include/gtest/gtest.h" 41 #include "testing/gtest/include/gtest/gtest.h"
40 42
41 namespace { 43 namespace {
42 44
43 const char kCertDateErrorHistogram[] = 45 const char kCertDateErrorHistogram[] =
44 "interstitial.ssl_error_handler.cert_date_error_delay"; 46 "interstitial.ssl_error_handler.cert_date_error_delay";
45 47
48 const net::SHA256HashValue kCertPublicKeyHashValue = {{0x01, 0x02}};
49
46 // Runs |quit_closure| on the UI thread once a URL request has been 50 // Runs |quit_closure| on the UI thread once a URL request has been
47 // seen. Returns a request that hangs. 51 // seen. Returns a request that hangs.
48 std::unique_ptr<net::test_server::HttpResponse> WaitForRequest( 52 std::unique_ptr<net::test_server::HttpResponse> WaitForRequest(
49 const base::Closure& quit_closure, 53 const base::Closure& quit_closure,
50 const net::test_server::HttpRequest& request) { 54 const net::test_server::HttpRequest& request) {
51 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 55 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
52 quit_closure); 56 quit_closure);
53 return base::MakeUnique<net::test_server::HungResponse>(); 57 return base::MakeUnique<net::test_server::HungResponse>();
54 } 58 }
55 59
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 bool captive_portal_interstitial_shown_; 184 bool captive_portal_interstitial_shown_;
181 bool redirected_to_suggested_url_; 185 bool redirected_to_suggested_url_;
182 bool is_overridable_error_; 186 bool is_overridable_error_;
183 CommonNameMismatchHandler::CheckUrlCallback suggested_url_callback_; 187 CommonNameMismatchHandler::CheckUrlCallback suggested_url_callback_;
184 188
185 DISALLOW_COPY_AND_ASSIGN(TestSSLErrorHandlerDelegate); 189 DISALLOW_COPY_AND_ASSIGN(TestSSLErrorHandlerDelegate);
186 }; 190 };
187 191
188 } // namespace 192 } // namespace
189 193
190 class SSLErrorHandlerNameMismatchTest : public ChromeRenderViewHostTestHarness { 194 template <net::CertStatus kCertStatus>
Ryan Sleevi 2017/02/01 22:06:06 I haven't really seen template parameters follow t
meacer 2017/02/02 01:56:06 Wasn't sure about it either so I did a code search
195 class SSLErrorHandlerCertStatusTestBase
196 : public ChromeRenderViewHostTestHarness {
191 public: 197 public:
192 SSLErrorHandlerNameMismatchTest() : field_trial_list_(nullptr) {} 198 SSLErrorHandlerCertStatusTestBase() : field_trial_list_(nullptr) {}
193 199
194 void SetUp() override { 200 void SetUp() override {
195 ChromeRenderViewHostTestHarness::SetUp(); 201 ChromeRenderViewHostTestHarness::SetUp();
202 SSLErrorHandler::ResetConfigForTesting();
Ryan Sleevi 2017/02/01 22:06:06 Shouldn't you also be doing this in TearDown?
meacer 2017/02/02 01:56:06 Done.
196 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta()); 203 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
197 ssl_info_.cert = 204 ssl_info_.cert =
198 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); 205 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
199 ssl_info_.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID; 206 ssl_info_.cert_status = kCertStatus;
207 ssl_info_.public_key_hashes.push_back(
208 net::HashValue(kCertPublicKeyHashValue));
200 209
201 delegate_ = 210 delegate_ =
202 new TestSSLErrorHandlerDelegate(profile(), web_contents(), ssl_info_); 211 new TestSSLErrorHandlerDelegate(profile(), web_contents(), ssl_info_);
203 error_handler_.reset(new TestSSLErrorHandler( 212 error_handler_.reset(new TestSSLErrorHandler(
204 std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(), 213 std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(),
205 profile(), net::MapCertStatusToNetError(ssl_info_.cert_status), 214 profile(), net::MapCertStatusToNetError(ssl_info_.cert_status),
206 ssl_info_, 215 ssl_info_,
207 GURL(), // request_url 216 GURL(), // request_url
208 base::Callback<void(content::CertificateRequestResultType)>())); 217 base::Callback<void(content::CertificateRequestResultType)>()));
209 218
210 // Enable finch experiment for captive portal interstitials. 219 // Enable finch experiment for captive portal interstitials.
211 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 220 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
212 "CaptivePortalInterstitial", "Enabled")); 221 "CaptivePortalInterstitial", "Enabled"));
213 // Enable finch experiment for SSL common name mismatch handling. 222 // Enable finch experiment for SSL common name mismatch handling.
214 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 223 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
215 "SSLCommonNameMismatchHandling", "Enabled")); 224 "SSLCommonNameMismatchHandling", "Enabled"));
216 } 225 }
217 226
218 void TearDown() override { 227 void TearDown() override {
219 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); 228 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
220 error_handler_.reset(nullptr); 229 error_handler_.reset(nullptr);
221 ChromeRenderViewHostTestHarness::TearDown(); 230 ChromeRenderViewHostTestHarness::TearDown();
222 } 231 }
223 232
224 TestSSLErrorHandler* error_handler() { return error_handler_.get(); } 233 TestSSLErrorHandler* error_handler() { return error_handler_.get(); }
225 TestSSLErrorHandlerDelegate* delegate() { return delegate_; } 234 TestSSLErrorHandlerDelegate* delegate() { return delegate_; }
226 235
236 const net::SSLInfo& ssl_info() { return ssl_info_; }
237
227 private: 238 private:
228 net::SSLInfo ssl_info_; 239 net::SSLInfo ssl_info_;
229 std::unique_ptr<TestSSLErrorHandler> error_handler_; 240 std::unique_ptr<TestSSLErrorHandler> error_handler_;
230 TestSSLErrorHandlerDelegate* delegate_; 241 TestSSLErrorHandlerDelegate* delegate_;
231 base::FieldTrialList field_trial_list_; 242 base::FieldTrialList field_trial_list_;
232 243
233 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerNameMismatchTest); 244 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerCertStatusTestBase);
234 }; 245 };
235 246
247 using SSLErrorHandlerNameMismatchTest =
248 SSLErrorHandlerCertStatusTestBase<net::CERT_STATUS_COMMON_NAME_INVALID>;
249 using SSLErrorHandlerAuthorityInvalidTest =
250 SSLErrorHandlerCertStatusTestBase<net::CERT_STATUS_AUTHORITY_INVALID>;
251
236 class SSLErrorHandlerDateInvalidTest : public ChromeRenderViewHostTestHarness { 252 class SSLErrorHandlerDateInvalidTest : public ChromeRenderViewHostTestHarness {
237 public: 253 public:
238 SSLErrorHandlerDateInvalidTest() 254 SSLErrorHandlerDateInvalidTest()
239 : field_trial_test_(new network_time::FieldTrialTest()), 255 : field_trial_test_(new network_time::FieldTrialTest()),
240 clock_(new base::SimpleTestClock), 256 clock_(new base::SimpleTestClock),
241 tick_clock_(new base::SimpleTestTickClock), 257 tick_clock_(new base::SimpleTestTickClock),
242 test_server_(new net::EmbeddedTestServer) { 258 test_server_(new net::EmbeddedTestServer) {
243 SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD); 259 SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
244 network_time::NetworkTimeTracker::RegisterPrefs(pref_service_.registry()); 260 network_time::NetworkTimeTracker::RegisterPrefs(pref_service_.registry());
245 } 261 }
246 262
247 void SetUp() override { 263 void SetUp() override {
248 ChromeRenderViewHostTestHarness::SetUp(); 264 ChromeRenderViewHostTestHarness::SetUp();
265 SSLErrorHandler::ResetConfigForTesting();
Ryan Sleevi 2017/02/01 22:06:06 Shouldn't you also be doing this in TearDown?
meacer 2017/02/02 01:56:06 Done.
249 266
250 field_trial_test()->SetNetworkQueriesWithVariationsService( 267 field_trial_test()->SetNetworkQueriesWithVariationsService(
251 false, 0.0, 268 false, 0.0,
252 network_time::NetworkTimeTracker::FETCHES_IN_BACKGROUND_ONLY); 269 network_time::NetworkTimeTracker::FETCHES_IN_BACKGROUND_ONLY);
253 tracker_.reset(new network_time::NetworkTimeTracker( 270 tracker_.reset(new network_time::NetworkTimeTracker(
254 std::unique_ptr<base::Clock>(clock_), 271 std::unique_ptr<base::Clock>(clock_),
255 std::unique_ptr<base::TickClock>(tick_clock_), &pref_service_, 272 std::unique_ptr<base::TickClock>(tick_clock_), &pref_service_,
256 new net::TestURLRequestContextGetter( 273 new net::TestURLRequestContextGetter(
257 content::BrowserThread::GetTaskRunnerForThread( 274 content::BrowserThread::GetTaskRunnerForThread(
258 content::BrowserThread::IO)))); 275 content::BrowserThread::IO))));
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 // Check that the histogram for the delay was recorded. 689 // Check that the histogram for the delay was recorded.
673 histograms.ExpectTotalCount(kCertDateErrorHistogram, 1); 690 histograms.ExpectTotalCount(kCertDateErrorHistogram, 1);
674 691
675 // Clear the error handler to test that, when the request completes, 692 // Clear the error handler to test that, when the request completes,
676 // it doesn't try to call a callback on a deleted SSLErrorHandler. 693 // it doesn't try to call a callback on a deleted SSLErrorHandler.
677 ClearErrorHandler(); 694 ClearErrorHandler();
678 695
679 // Shut down the server to cancel the pending request. 696 // Shut down the server to cancel the pending request.
680 ASSERT_TRUE(test_server()->ShutdownAndWaitUntilComplete()); 697 ASSERT_TRUE(test_server()->ShutdownAndWaitUntilComplete());
681 } 698 }
699
700 // Tests that a certificate marked as a known captive portal certificate causes
701 // the captive portal interstitial to be shown.
702 TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Enabled) {
703 base::test::ScopedFeatureList scoped_feature_list;
704 scoped_feature_list.InitFromCommandLine(
705 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
706
707 base::HistogramTester histograms;
708
709 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
710 EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
711
712 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
713 config_proto.add_captive_portal_cert()->set_sha256_hash(
714 "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
715 config_proto.add_captive_portal_cert()->set_sha256_hash(
716 ssl_info().public_key_hashes[0].ToString());
717 config_proto.add_captive_portal_cert()->set_sha256_hash(
718 "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
719 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
720
721 error_handler()->StartHandlingError();
722
723 // Timer shouldn't start for a known captive portal certificate.
724 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
725 EXPECT_FALSE(delegate()->captive_portal_checked());
726 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
727 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
728 EXPECT_FALSE(delegate()->suggested_url_checked());
729
730 // A buggy SSL error handler might have incorrectly started the timer. Run to
731 // completion to ensure the timer is expired.
732 base::RunLoop().RunUntilIdle();
733
734 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
735 EXPECT_FALSE(delegate()->captive_portal_checked());
736 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
737 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
738 EXPECT_FALSE(delegate()->suggested_url_checked());
739
740 // Check that the histogram for the captive portal cert was recorded.
741 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
742 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
743 SSLErrorHandler::HANDLE_ALL, 1);
744 histograms.ExpectBucketCount(
745 SSLErrorHandler::GetHistogramNameForTesting(),
746 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
747 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
748 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
749 }
750
751 // Tests that a certificate marked as a known captive portal certificate does
752 // not cause the captive portal interstitial to be shown, if the feature is
753 // disabled.
754 TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Disabled) {
755 base::test::ScopedFeatureList scoped_feature_list;
756 scoped_feature_list.InitFromCommandLine(
757 "" /* enabled */, "CaptivePortalCertificateList" /* disabled */);
758
759 base::HistogramTester histograms;
760
761 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
762 EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
763
764 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
765 config_proto.add_captive_portal_cert()->set_sha256_hash(
766 "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
767 config_proto.add_captive_portal_cert()->set_sha256_hash(
768 ssl_info().public_key_hashes[0].ToString());
769 config_proto.add_captive_portal_cert()->set_sha256_hash(
770 "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
771 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
772
773 error_handler()->StartHandlingError();
774
775 // Timer shouldn't start for a known captive portal certificate.
776 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
777 EXPECT_TRUE(delegate()->captive_portal_checked());
778 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
779 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
780 EXPECT_FALSE(delegate()->suggested_url_checked());
781
782 // A buggy SSL error handler might have incorrectly started the timer. Run to
783 // completion to ensure the timer is expired.
784 base::RunLoop().RunUntilIdle();
785
786 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
787 EXPECT_TRUE(delegate()->captive_portal_checked());
788 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
789 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
790 EXPECT_FALSE(delegate()->suggested_url_checked());
791
792 // Check that the histogram for the captive portal cert was recorded.
793 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
794 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
795 SSLErrorHandler::HANDLE_ALL, 1);
796 histograms.ExpectBucketCount(
797 SSLErrorHandler::GetHistogramNameForTesting(),
798 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
799 }
800
801 // Tests that an error other than name mismatch does not cause a captive portal
802 // interstitial to be shown, even if the certificate is marked as a known
803 // captive portal certificate.
804 TEST_F(SSLErrorHandlerAuthorityInvalidTest,
805 CaptivePortalCertificateList_ShouldShowGenericInterstitial) {
806 base::test::ScopedFeatureList scoped_feature_list;
807 scoped_feature_list.InitFromCommandLine(
808 "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
809
810 base::HistogramTester histograms;
811
812 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
813 EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
814
815 chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
816 config_proto.add_captive_portal_cert()->set_sha256_hash(
817 "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
818 config_proto.add_captive_portal_cert()->set_sha256_hash(
819 ssl_info().public_key_hashes[0].ToString());
820 config_proto.add_captive_portal_cert()->set_sha256_hash(
821 "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
822 SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
823
824 error_handler()->StartHandlingError();
825
826 // Timer should start for captive portal detection.
827 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
828 EXPECT_TRUE(delegate()->captive_portal_checked());
829 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
830 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
831 EXPECT_FALSE(delegate()->suggested_url_checked());
832
833 base::RunLoop().RunUntilIdle();
834
835 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
836 EXPECT_TRUE(delegate()->captive_portal_checked());
837 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
838 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
839 EXPECT_FALSE(delegate()->suggested_url_checked());
840
841 // Check that the histogram for the captive portal cert was recorded.
842 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
843 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
844 SSLErrorHandler::HANDLE_ALL, 1);
845 histograms.ExpectBucketCount(
846 SSLErrorHandler::GetHistogramNameForTesting(),
847 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
848 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698