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
3 // found in the LICENSE file.
4
5 #include "components/security_interstitials/content/ssl_error_handler.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/macros.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/run_loop.h"
14 #include "base/task/post_task.h"
15 #include "base/test/metrics/histogram_tester.h"
16 #include "base/test/scoped_feature_list.h"
17 #include "base/test/simple_test_clock.h"
18 #include "base/test/simple_test_tick_clock.h"
19 #include "base/time/time.h"
20 #include "build/build_config.h"
21 #include "build/chromecast_buildflags.h"
22 #include "components/captive_portal/content/captive_portal_service.h"
23 #include "components/captive_portal/core/buildflags.h"
24 #include "components/captive_portal/core/captive_portal_testing_utils.h"
25 #include "components/embedder_support/pref_names.h"
26 #include "components/network_time/network_time_test_utils.h"
27 #include "components/network_time/network_time_tracker.h"
28 #include "components/prefs/pref_registry_simple.h"
29 #include "components/prefs/testing_pref_service.h"
30 #include "components/security_interstitials/content/common_name_mismatch_handler.h"
31 #include "components/security_interstitials/content/ssl_error_assistant.h"
32 #include "components/security_interstitials/content/ssl_error_assistant.pb.h"
33 #include "components/security_interstitials/content/ssl_error_handler.h"
34 #include "components/security_interstitials/core/ssl_error_options_mask.h"
35 #include "components/security_interstitials/core/ssl_error_ui.h"
36 #include "content/public/browser/browser_task_traits.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/test/test_renderer_host.h"
39 #include "net/base/net_errors.h"
40 #include "net/cert/cert_status_flags.h"
41 #include "net/cert/x509_certificate.h"
42 #include "net/http/http_response_headers.h"
43 #include "net/ssl/ssl_info.h"
44 #include "net/test/cert_test_util.h"
45 #include "net/test/embedded_test_server/embedded_test_server.h"
46 #include "net/test/embedded_test_server/http_response.h"
47 #include "net/test/test_certificate_data.h"
48 #include "net/test/test_data_directory.h"
49 #include "net/url_request/url_request_test_util.h"
50 #include "services/network/test/test_shared_url_loader_factory.h"
51 #include "testing/gtest/include/gtest/gtest.h"
52
53 namespace {
54
55 const char kCertDateErrorHistogram[] =
56 "interstitial.ssl_error_handler.cert_date_error_delay";
57
58 const net::SHA256HashValue kCertPublicKeyHashValue = {{0x01, 0x02}};
59
60 const char kOkayCertName[] = "ok_cert.pem";
61
62 const uint32_t kLargeVersionId = 0xFFFFFFu;
63
64 // These certificates are self signed certificates with relevant issuer common
65 // names generated using the following openssl command:
66 // openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
67
68 // Common name: "Misconfigured Firewall_4GHPOS5412EF"
69 // Organization name: "Misconfigured Firewall"
70 const char kMisconfiguredFirewallCert[] =
71 "-----BEGIN CERTIFICATE-----\n"
72 "MIIEKTCCAxGgAwIBAgIJAOxA1g2otzdHMA0GCSqGSIb3DQEBCwUAMIGqMQswCQYD\n"
73 "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n"
74 "aXNjbzEfMB0GA1UECgwWTWlzY29uZmlndXJlZCBGaXJld2FsbDEsMCoGA1UEAwwj\n"
75 "TWlzY29uZmlndXJlZCBGaXJld2FsbF80R0hQT1M1NDEyRUYxHzAdBgkqhkiG9w0B\n"
76 "CQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMTcwODE4MjM1MjI4WhcNMTgwODE4MjM1\n"
77 "MjI4WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV\n"
78 "BAcMDVNhbiBGcmFuY2lzY28xHzAdBgNVBAoMFk1pc2NvbmZpZ3VyZWQgRmlyZXdh\n"
79 "bGwxLDAqBgNVBAMMI01pc2NvbmZpZ3VyZWQgRmlyZXdhbGxfNEdIUE9TNTQxMkVG\n"
80 "MR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B\n"
81 "AQEFAAOCAQ8AMIIBCgKCAQEAtxh4PZ9dbqeXubutRBFSL4FschunDX/vRFzhlQdz\n"
82 "3fqzIfmN2PjvwBsoX1oDaWdTTefCLad7pX08UVyX2pS0UeqYwUJL+ihXuupW0pBV\n"
83 "M2VZ/soDgze7Vl9dUU43NLoODOzwvKt92QdyfS7toPEEmwFLrI4/UnzxX+QlS8qq\n"
84 "naWD5ny2XZOZdNizBX1UQlvkvfYJM0wUmBZ/VUj/QQxxNHZaEBcl64t3h5jHiq1c\n"
85 "gWDgp0zeYy+PbJk/LMSvF64qqMFDtujUQcniYC6HwWJ9YT7PFX2b7X9Mq4b3gtpV\n"
86 "6jGXXUJqg+SfLW7XisZcWVMfHZDaVfdd35vNm61XY4sg1wIDAQABo1AwTjAdBgNV\n"
87 "HQ4EFgQUmUhF2RL+A4QAEel9JiEYNbPyU+AwHwYDVR0jBBgwFoAUmUhF2RL+A4QA\n"
88 "Eel9JiEYNbPyU+AwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAO+kk\n"
89 "Uin9uKD2iTkUtuoAckt+kcctmvHcP3zLe+J0m25f9HOyrjhutgIYZDwt2LiAnOTA\n"
90 "CQHg3t5YyDQHove39M6I1vWhoAy9jOi0Qn+lTKkVu5H4g5ZiauO3coneqFw/dPe+\n"
91 "kYye/bPKV4jNlhEYXF5+Pa7PYde0sxf7AmlDJb9NZh01xRKNFt6ScDpirhJIFdzg\n"
92 "ZKram+yJyIbcZI+yd7mjzu9dSCS0NbnsZDL7xqThFFZsbhZyO98kzdDS+crip6y5\n"
93 "rz3+AJpJvlGcf898Y4ibAPmeX62j6pug55TGfAdsqSVUiaQX1HcwwbmlSOYrhYTm\n"
94 "lMEx5QP9TqgGU0nGwQ==\n"
95 "-----END CERTIFICATE-----";
96
97 // Common name: None
98 // Organization name: None
99 const char kCertWithoutOrganizationOrCommonName[] =
100 "-----BEGIN CERTIFICATE-----\n"
101 "MIIDzzCCAregAwIBAgIJAJfHNOMLXbc4MA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\n"
102 "BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp\n"
103 "c2NvMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxHzAdBgkqhkiG\n"
104 "9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMTcwODE5MDAwNTMyWhcNMTgwODE5\n"
105 "MDAwNTMyWjB+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\n"
106 "A1UEBwwNU2FuIEZyYW5jaXNjbzEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ\n"
107 "dHkgTHRkMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkq\n"
108 "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28iX7cIS5XS+hU/0OreJXfVmEWDPVRX1\n"
109 "n05AlX+ETRunnYevZOAhbSFuUeJi2cGgW4cpD6fGKrf05PpNM9GQ4yswIPlVsemR\n"
110 "ickSmg8vVemPs/Hz3y0dYnRoTwzzVESh4OIVGe+rrhCUdWVHE+/HOdmHAXoBI6m1\n"
111 "OhN2GgtvnEEMYzTaMRGNqb5VhRKYHwLNp8zqLtrHIbo61mi8Wl7E4NZdaVk4cTNK\n"
112 "w93Y8RqlwzzpbWT9RH74JPCM+wSg0rCK+h59sa86W4yPvhXyYIGXM8WhWkMW68Ej\n"
113 "jqfE0lQlEuxKPeCYZn6oC+AVRLxHCwncVxZaUtGUovMzBdV3WzsLPwIDAQABo1Aw\n"
114 "TjAdBgNVHQ4EFgQUlkC11ZD66sKrb25g4mH4sob4e3MwHwYDVR0jBBgwFoAUlkC1\n"
115 "1ZD66sKrb25g4mH4sob4e3MwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n"
116 "AQEAUHQZmeZdAV86TIWviPNWNqhPD+/OEGnOwgjUrBmSrQkc5hPZUhQ8the7ewNE\n"
117 "V/eGjDNF72tiQqPQP7Zrhdf7i1p1Q3ufcDHpOOFbEdKd6m2DeCLg83jOLqLr/jTB\n"
118 "CC7GyyWOyt+CFVRGC0yovSl3+Vxaso6DZjelO3IP5K7bT5U1f3cUZnYTpYfslh1t\n"
119 "dUmxh9/MaKxnRaHkr0HDVGpWS4ZMoZUyyC6D9ZfCQ5aGJJubQEPxADc2tXHXOL73\n"
120 "dspwZ8CTOlcXnfdeRIjvgxnMZLax+OFEMJdY8sgyrI9c+rk2EfOUj5JVqFDvcsYy\n"
121 "ejdBhjdieIv5dTbSjIXz+ljOOA==\n"
122 "-----END CERTIFICATE-----";
123
124 // Runs |quit_closure| on the UI thread once a URL request has been
125 // seen. Returns a request that hangs.
WaitForRequest(const base::Closure & quit_closure,const net::test_server::HttpRequest & request)126 std::unique_ptr<net::test_server::HttpResponse> WaitForRequest(
127 const base::Closure& quit_closure,
128 const net::test_server::HttpRequest& request) {
129 base::PostTask(FROM_HERE, {content::BrowserThread::UI}, quit_closure);
130 return std::make_unique<net::test_server::HungResponse>();
131 }
132
133 class TestSSLErrorHandler : public SSLErrorHandler {
134 public:
TestSSLErrorHandler(std::unique_ptr<Delegate> delegate,content::WebContents * web_contents,int cert_error,const net::SSLInfo & ssl_info,network_time::NetworkTimeTracker * network_time_tracker,const GURL & request_url,captive_portal::CaptivePortalService * captive_portal_service)135 TestSSLErrorHandler(
136 std::unique_ptr<Delegate> delegate,
137 content::WebContents* web_contents,
138 int cert_error,
139 const net::SSLInfo& ssl_info,
140 network_time::NetworkTimeTracker* network_time_tracker,
141 const GURL& request_url,
142 captive_portal::CaptivePortalService* captive_portal_service)
143 : SSLErrorHandler(std::move(delegate),
144 web_contents,
145 cert_error,
146 ssl_info,
147 network_time_tracker,
148 captive_portal_service,
149 request_url) {}
150
151 using SSLErrorHandler::StartHandlingError;
152 };
153
154 class TestSSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
155 public:
TestSSLErrorHandlerDelegate(content::WebContents * web_contents,const net::SSLInfo & ssl_info)156 TestSSLErrorHandlerDelegate(content::WebContents* web_contents,
157 const net::SSLInfo& ssl_info)
158 : captive_portal_checked_(false),
159 os_reports_captive_portal_(false),
160 suggested_url_exists_(false),
161 suggested_url_checked_(false),
162 ssl_interstitial_shown_(false),
163 bad_clock_interstitial_shown_(false),
164 captive_portal_interstitial_shown_(false),
165 mitm_software_interstitial_shown_(false),
166 blocked_interception_interstitial_shown_(false),
167 redirected_to_suggested_url_(false),
168 is_overridable_error_(true),
169 has_blocked_interception_(false),
170 legacy_tls_interstitial_shown_(false) {}
171
SendSuggestedUrlCheckResult(const CommonNameMismatchHandler::SuggestedUrlCheckResult & result,const GURL & suggested_url)172 void SendSuggestedUrlCheckResult(
173 const CommonNameMismatchHandler::SuggestedUrlCheckResult& result,
174 const GURL& suggested_url) {
175 suggested_url_callback_.Run(result, suggested_url);
176 }
177
captive_portal_checked() const178 int captive_portal_checked() const { return captive_portal_checked_; }
ssl_interstitial_shown() const179 int ssl_interstitial_shown() const { return ssl_interstitial_shown_; }
captive_portal_interstitial_shown() const180 int captive_portal_interstitial_shown() const {
181 return captive_portal_interstitial_shown_;
182 }
mitm_software_interstitial_shown() const183 int mitm_software_interstitial_shown() const {
184 return mitm_software_interstitial_shown_;
185 }
bad_clock_interstitial_shown() const186 bool bad_clock_interstitial_shown() const {
187 return bad_clock_interstitial_shown_;
188 }
blocked_interception_interstitial_shown() const189 bool blocked_interception_interstitial_shown() const {
190 return blocked_interception_interstitial_shown_;
191 }
suggested_url_checked() const192 bool suggested_url_checked() const { return suggested_url_checked_; }
redirected_to_suggested_url() const193 bool redirected_to_suggested_url() const {
194 return redirected_to_suggested_url_;
195 }
legacy_tls_interstitial_shown() const196 bool legacy_tls_interstitial_shown() const {
197 return legacy_tls_interstitial_shown_;
198 }
199
set_suggested_url_exists()200 void set_suggested_url_exists() { suggested_url_exists_ = true; }
set_non_overridable_error()201 void set_non_overridable_error() { is_overridable_error_ = false; }
set_os_reports_captive_portal()202 void set_os_reports_captive_portal() { os_reports_captive_portal_ = true; }
set_has_blocked_interception()203 void set_has_blocked_interception() { has_blocked_interception_ = true; }
set_has_legacy_tls()204 void set_has_legacy_tls() { has_legacy_tls_ = true; }
205
ClearSeenOperations()206 void ClearSeenOperations() {
207 captive_portal_checked_ = false;
208 os_reports_captive_portal_ = false;
209 suggested_url_exists_ = false;
210 suggested_url_checked_ = false;
211 ssl_interstitial_shown_ = false;
212 bad_clock_interstitial_shown_ = false;
213 captive_portal_interstitial_shown_ = false;
214 mitm_software_interstitial_shown_ = false;
215 redirected_to_suggested_url_ = false;
216 has_blocked_interception_ = false;
217 legacy_tls_interstitial_shown_ = false;
218 has_legacy_tls_ = false;
219 }
220
221 private:
CheckForCaptivePortal()222 void CheckForCaptivePortal() override { captive_portal_checked_ = true; }
223
DoesOSReportCaptivePortal()224 bool DoesOSReportCaptivePortal() override {
225 return os_reports_captive_portal_;
226 }
227
GetSuggestedUrl(const std::vector<std::string> & dns_names,GURL * suggested_url) const228 bool GetSuggestedUrl(const std::vector<std::string>& dns_names,
229 GURL* suggested_url) const override {
230 if (!suggested_url_exists_)
231 return false;
232 *suggested_url = GURL("www.example.com");
233 return true;
234 }
235
ShowSSLInterstitial(const GURL & support_url=GURL ())236 void ShowSSLInterstitial(const GURL& support_url = GURL()) override {
237 ssl_interstitial_shown_ = true;
238 }
239
ShowBadClockInterstitial(const base::Time & now,ssl_errors::ClockState clock_state)240 void ShowBadClockInterstitial(const base::Time& now,
241 ssl_errors::ClockState clock_state) override {
242 bad_clock_interstitial_shown_ = true;
243 }
244
ShowCaptivePortalInterstitial(const GURL & landing_url)245 void ShowCaptivePortalInterstitial(const GURL& landing_url) override {
246 captive_portal_interstitial_shown_ = true;
247 }
248
ShowMITMSoftwareInterstitial(const std::string & mitm_software_name)249 void ShowMITMSoftwareInterstitial(
250 const std::string& mitm_software_name) override {
251 mitm_software_interstitial_shown_ = true;
252 }
253
ShowBlockedInterceptionInterstitial()254 void ShowBlockedInterceptionInterstitial() override {
255 blocked_interception_interstitial_shown_ = true;
256 }
257
ShowLegacyTLSInterstitial()258 void ShowLegacyTLSInterstitial() override {
259 legacy_tls_interstitial_shown_ = true;
260 }
261
CheckSuggestedUrl(const GURL & suggested_url,const CommonNameMismatchHandler::CheckUrlCallback & callback)262 void CheckSuggestedUrl(
263 const GURL& suggested_url,
264 const CommonNameMismatchHandler::CheckUrlCallback& callback) override {
265 DCHECK(suggested_url_callback_.is_null());
266 suggested_url_checked_ = true;
267 suggested_url_callback_ = callback;
268 }
269
NavigateToSuggestedURL(const GURL & suggested_url)270 void NavigateToSuggestedURL(const GURL& suggested_url) override {
271 redirected_to_suggested_url_ = true;
272 }
273
IsErrorOverridable() const274 bool IsErrorOverridable() const override { return is_overridable_error_; }
275
ReportNetworkConnectivity(base::OnceClosure callback)276 void ReportNetworkConnectivity(base::OnceClosure callback) override {}
277
HasBlockedInterception() const278 bool HasBlockedInterception() const override {
279 return has_blocked_interception_;
280 }
281
HasLegacyTLS() const282 bool HasLegacyTLS() const override { return has_legacy_tls_; }
283
284 bool captive_portal_checked_;
285 bool os_reports_captive_portal_;
286 bool suggested_url_exists_;
287 bool suggested_url_checked_;
288 bool ssl_interstitial_shown_;
289 bool bad_clock_interstitial_shown_;
290 bool captive_portal_interstitial_shown_;
291 bool mitm_software_interstitial_shown_;
292 bool blocked_interception_interstitial_shown_;
293 bool redirected_to_suggested_url_;
294 bool is_overridable_error_;
295 bool has_blocked_interception_;
296 bool legacy_tls_interstitial_shown_;
297 bool has_legacy_tls_;
298 CommonNameMismatchHandler::CheckUrlCallback suggested_url_callback_;
299
300 DISALLOW_COPY_AND_ASSIGN(TestSSLErrorHandlerDelegate);
301 };
302
303 } // namespace
304
305 // A class to test name mismatch errors. Creates an error handler with a name
306 // mismatch error.
307 class SSLErrorHandlerNameMismatchTest
308 : public content::RenderViewHostTestHarness {
309 public:
SSLErrorHandlerNameMismatchTest()310 SSLErrorHandlerNameMismatchTest() {}
~SSLErrorHandlerNameMismatchTest()311 ~SSLErrorHandlerNameMismatchTest() override {}
312
SetUp()313 void SetUp() override {
314 content::RenderViewHostTestHarness::SetUp();
315 SSLErrorHandler::ResetConfigForTesting();
316 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
317 ssl_info_.cert = GetCertificate();
318 ssl_info_.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
319 ssl_info_.public_key_hashes.push_back(
320 net::HashValue(kCertPublicKeyHashValue));
321
322 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
323 pref_service_.registry()->RegisterBooleanPref(
324 embedder_support::kAlternateErrorPagesEnabled, true);
325 captive_portal_service_ =
326 std::make_unique<captive_portal::CaptivePortalService>(
327 web_contents()->GetBrowserContext(), &pref_service_);
328 #endif
329
330 delegate_ = new TestSSLErrorHandlerDelegate(web_contents(), ssl_info_);
331 error_handler_.reset(new TestSSLErrorHandler(
332 std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(),
333 net::MapCertStatusToNetError(ssl_info_.cert_status), ssl_info_,
334 /*network_time_tracker=*/nullptr, GURL() /*request_url*/,
335 captive_portal_service_.get()));
336 }
337
TearDown()338 void TearDown() override {
339 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
340 captive_portal_service_.reset();
341 error_handler_.reset(nullptr);
342 SSLErrorHandler::ResetConfigForTesting();
343 content::RenderViewHostTestHarness::TearDown();
344 }
345
error_handler()346 TestSSLErrorHandler* error_handler() { return error_handler_.get(); }
delegate()347 TestSSLErrorHandlerDelegate* delegate() { return delegate_; }
348
ssl_info()349 const net::SSLInfo& ssl_info() { return ssl_info_; }
350
351 private:
352 // Returns a certificate for the test. Virtual to allow derived fixtures to
353 // use a certificate with different characteristics.
GetCertificate()354 virtual scoped_refptr<net::X509Certificate> GetCertificate() {
355 return net::ImportCertFromFile(net::GetTestCertsDirectory(),
356 "subjectAltName_www_example_com.pem");
357 }
358
359 net::SSLInfo ssl_info_;
360 TestingPrefServiceSimple pref_service_;
361 std::unique_ptr<captive_portal::CaptivePortalService> captive_portal_service_;
362 std::unique_ptr<TestSSLErrorHandler> error_handler_;
363 TestSSLErrorHandlerDelegate* delegate_;
364
365 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerNameMismatchTest);
366 };
367
368 // A class to test name mismatch errors, where the certificate lacks a
369 // SubjectAltName. Creates an error handler with a name mismatch error.
370 class SSLErrorHandlerNameMismatchNoSANTest
371 : public SSLErrorHandlerNameMismatchTest {
372 public:
SSLErrorHandlerNameMismatchNoSANTest()373 SSLErrorHandlerNameMismatchNoSANTest() {}
374
375 private:
376 // Return a certificate that contains no SubjectAltName field.
GetCertificate()377 scoped_refptr<net::X509Certificate> GetCertificate() override {
378 return net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
379 }
380
381 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerNameMismatchNoSANTest);
382 };
383
384 // A class to test the captive portal certificate list feature. Creates an error
385 // handler with a name mismatch error by default. The error handler can be
386 // recreated by calling ResetErrorHandler() with an appropriate cert status.
387 class SSLErrorAssistantProtoTest : public content::RenderViewHostTestHarness {
388 public:
SetUp()389 void SetUp() override {
390 content::RenderViewHostTestHarness::SetUp();
391
392 pref_service_.registry()->RegisterBooleanPref(
393 embedder_support::kAlternateErrorPagesEnabled, true);
394
395 SSLErrorHandler::ResetConfigForTesting();
396 SSLErrorHandler::SetErrorAssistantProto(
397 SSLErrorAssistant::GetErrorAssistantProtoFromResourceBundle());
398
399 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
400 ResetErrorHandlerFromFile(kOkayCertName,
401 net::CERT_STATUS_COMMON_NAME_INVALID);
402 }
403
TearDown()404 void TearDown() override {
405 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
406 captive_portal_service_.reset();
407 error_handler_.reset(nullptr);
408 SSLErrorHandler::ResetConfigForTesting();
409 content::RenderViewHostTestHarness::TearDown();
410 }
411
error_handler()412 TestSSLErrorHandler* error_handler() { return error_handler_.get(); }
delegate()413 TestSSLErrorHandlerDelegate* delegate() { return delegate_; }
414
ssl_info()415 const net::SSLInfo& ssl_info() { return ssl_info_; }
416
417 protected:
SSLErrorAssistantProtoTest()418 SSLErrorAssistantProtoTest() {}
~SSLErrorAssistantProtoTest()419 ~SSLErrorAssistantProtoTest() override {}
420
SetCaptivePortalFeatureEnabled(bool enabled)421 void SetCaptivePortalFeatureEnabled(bool enabled) {
422 if (enabled)
423 scoped_feature_list_.InitAndEnableFeature(kCaptivePortalCertificateList);
424 else
425 scoped_feature_list_.InitAndDisableFeature(kCaptivePortalCertificateList);
426 }
427
SetMITMSoftwareFeatureEnabled(bool enabled)428 void SetMITMSoftwareFeatureEnabled(bool enabled) {
429 if (enabled)
430 scoped_feature_list_.InitAndEnableFeature(kMITMSoftwareInterstitial);
431 else
432 scoped_feature_list_.InitAndDisableFeature(kMITMSoftwareInterstitial);
433 }
434
ResetErrorHandlerFromString(const std::string & cert_data,net::CertStatus cert_status)435 void ResetErrorHandlerFromString(const std::string& cert_data,
436 net::CertStatus cert_status) {
437 net::CertificateList certs =
438 net::X509Certificate::CreateCertificateListFromBytes(
439 cert_data.data(), cert_data.size(),
440 net::X509Certificate::FORMAT_AUTO);
441 ASSERT_FALSE(certs.empty());
442 ResetErrorHandler(certs[0], cert_status);
443 }
444
ResetErrorHandlerFromFile(const std::string & cert_name,net::CertStatus cert_status)445 void ResetErrorHandlerFromFile(const std::string& cert_name,
446 net::CertStatus cert_status) {
447 ResetErrorHandler(
448 net::ImportCertFromFile(net::GetTestCertsDirectory(), cert_name),
449 cert_status);
450 }
451
452 // Set up an error assistant proto with mock captive portal hash data and
453 // begin handling the certificate error.
RunCaptivePortalTest()454 void RunCaptivePortalTest() {
455 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
456 EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
457
458 auto config_proto =
459 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
460 config_proto->set_version_id(kLargeVersionId);
461
462 config_proto->add_captive_portal_cert()->set_sha256_hash(
463 "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
464 config_proto->add_captive_portal_cert()->set_sha256_hash(
465 ssl_info().public_key_hashes[0].ToString());
466 config_proto->add_captive_portal_cert()->set_sha256_hash(
467 "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
468 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
469
470 error_handler()->StartHandlingError();
471 }
472
TestNoCaptivePortalInterstitial()473 void TestNoCaptivePortalInterstitial() {
474 base::HistogramTester histograms;
475
476 RunCaptivePortalTest();
477
478 #if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMECAST)
479 // On platforms where captive portal detection is enabled, timer should
480 // start for captive portal detection.
481 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
482 EXPECT_TRUE(delegate()->captive_portal_checked());
483 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
484 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
485 EXPECT_FALSE(delegate()->suggested_url_checked());
486
487 base::RunLoop().RunUntilIdle();
488
489 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
490
491 // Captive portal should be checked on non-Android platforms.
492 EXPECT_TRUE(delegate()->captive_portal_checked());
493 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
494 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
495 EXPECT_FALSE(delegate()->suggested_url_checked());
496 #else
497 // On Android and Chromecast there is no custom captive portal detection
498 // logic, so the timer should not start and an SSL interstitial should be
499 // shown immediately.
500 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
501 EXPECT_FALSE(delegate()->captive_portal_checked());
502 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
503 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
504 EXPECT_FALSE(delegate()->suggested_url_checked());
505
506 base::RunLoop().RunUntilIdle();
507
508 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
509 EXPECT_FALSE(delegate()->captive_portal_checked());
510 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
511 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
512 EXPECT_FALSE(delegate()->suggested_url_checked());
513 #endif
514
515 // Check that the histogram for the captive portal cert was recorded.
516 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
517 2);
518 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
519 SSLErrorHandler::HANDLE_ALL, 1);
520 histograms.ExpectBucketCount(
521 SSLErrorHandler::GetHistogramNameForTesting(),
522 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
523 }
524
525 // Set up a mock SSL Error Assistant config with regexes that match the
526 // outdated antivirus and misconfigured firewall certificate.
InitMITMSoftwareList()527 void InitMITMSoftwareList() {
528 auto config_proto =
529 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
530 config_proto->set_version_id(kLargeVersionId);
531
532 chrome_browser_ssl::MITMSoftware* filter =
533 config_proto->add_mitm_software();
534 filter->set_name("Misconfigured Firewall");
535 filter->set_issuer_common_name_regex("Misconfigured Firewall_[A-Z0-9]+");
536 filter->set_issuer_organization_regex("Misconfigured Firewall");
537
538 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
539 }
540
TestMITMSoftwareInterstitial()541 void TestMITMSoftwareInterstitial() {
542 base::HistogramTester histograms;
543
544 delegate()->set_non_overridable_error();
545 error_handler()->StartHandlingError();
546 base::RunLoop().RunUntilIdle();
547
548 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
549 EXPECT_TRUE(delegate()->mitm_software_interstitial_shown());
550 EXPECT_FALSE(delegate()->suggested_url_checked());
551
552 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
553 2);
554 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
555 SSLErrorHandler::HANDLE_ALL, 1);
556 histograms.ExpectBucketCount(
557 SSLErrorHandler::GetHistogramNameForTesting(),
558 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 0);
559 histograms.ExpectBucketCount(
560 SSLErrorHandler::GetHistogramNameForTesting(),
561 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 0);
562 histograms.ExpectBucketCount(
563 SSLErrorHandler::GetHistogramNameForTesting(),
564 SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL, 1);
565 }
566
TestNoMITMSoftwareInterstitial()567 void TestNoMITMSoftwareInterstitial() {
568 base::HistogramTester histograms;
569
570 delegate()->set_non_overridable_error();
571 error_handler()->StartHandlingError();
572 base::RunLoop().RunUntilIdle();
573
574 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
575 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
576 EXPECT_FALSE(delegate()->mitm_software_interstitial_shown());
577 EXPECT_FALSE(delegate()->suggested_url_checked());
578
579 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
580 2);
581 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
582 SSLErrorHandler::HANDLE_ALL, 1);
583 histograms.ExpectBucketCount(
584 SSLErrorHandler::GetHistogramNameForTesting(),
585 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 1);
586 histograms.ExpectBucketCount(
587 SSLErrorHandler::GetHistogramNameForTesting(),
588 SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL, 0);
589 }
590
591 private:
ResetErrorHandler(scoped_refptr<net::X509Certificate> cert,net::CertStatus cert_status)592 void ResetErrorHandler(scoped_refptr<net::X509Certificate> cert,
593 net::CertStatus cert_status) {
594 ssl_info_.Reset();
595 ssl_info_.cert = cert;
596 ssl_info_.cert_status = cert_status;
597 ssl_info_.public_key_hashes.push_back(
598 net::HashValue(kCertPublicKeyHashValue));
599
600 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
601 captive_portal_service_ =
602 std::make_unique<captive_portal::CaptivePortalService>(
603 web_contents()->GetBrowserContext(), &pref_service_);
604 #endif
605
606 delegate_ = new TestSSLErrorHandlerDelegate(web_contents(), ssl_info_);
607 error_handler_.reset(new TestSSLErrorHandler(
608 std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(),
609 net::MapCertStatusToNetError(ssl_info_.cert_status), ssl_info_,
610 /*network_time_tracker=*/nullptr, GURL() /*request_url*/,
611 captive_portal_service_.get()));
612 }
613
614 net::SSLInfo ssl_info_;
615 TestingPrefServiceSimple pref_service_;
616 std::unique_ptr<captive_portal::CaptivePortalService> captive_portal_service_;
617 std::unique_ptr<TestSSLErrorHandler> error_handler_;
618 TestSSLErrorHandlerDelegate* delegate_;
619 base::test::ScopedFeatureList scoped_feature_list_;
620
621 DISALLOW_COPY_AND_ASSIGN(SSLErrorAssistantProtoTest);
622 };
623
624 class SSLErrorHandlerDateInvalidTest
625 : public content::RenderViewHostTestHarness {
626 public:
SSLErrorHandlerDateInvalidTest()627 SSLErrorHandlerDateInvalidTest()
628 : content::RenderViewHostTestHarness(
629 content::BrowserTaskEnvironment::REAL_IO_THREAD),
630 field_trial_test_(new network_time::FieldTrialTest()),
631 clock_(new base::SimpleTestClock),
632 tick_clock_(new base::SimpleTestTickClock),
633 test_server_(new net::EmbeddedTestServer) {
634 network_time::NetworkTimeTracker::RegisterPrefs(pref_service_.registry());
635
636 field_trial_test()->SetNetworkQueriesWithVariationsService(
637 false, 0.0,
638 network_time::NetworkTimeTracker::FETCHES_IN_BACKGROUND_ONLY);
639 }
640
SetUp()641 void SetUp() override {
642 content::RenderViewHostTestHarness::SetUp();
643 SSLErrorHandler::ResetConfigForTesting();
644
645 base::RunLoop run_loop;
646 std::unique_ptr<network::PendingSharedURLLoaderFactory>
647 pending_url_loader_factory;
648 base::PostTaskAndReply(
649 FROM_HERE, {content::BrowserThread::IO},
650 base::BindOnce(CreateURLLoaderFactory, &pending_url_loader_factory),
651 run_loop.QuitClosure());
652 run_loop.Run();
653
654 shared_url_loader_factory_ = network::SharedURLLoaderFactory::Create(
655 std::move(pending_url_loader_factory));
656
657 tracker_.reset(new network_time::NetworkTimeTracker(
658 std::unique_ptr<base::Clock>(clock_),
659 std::unique_ptr<base::TickClock>(tick_clock_), &pref_service_,
660 shared_url_loader_factory_));
661 // Do this to be sure that |is_null| returns false.
662 clock_->Advance(base::TimeDelta::FromDays(111));
663 tick_clock_->Advance(base::TimeDelta::FromDays(222));
664
665 SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
666 ssl_info_.cert =
667 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
668 ssl_info_.cert_status = net::CERT_STATUS_DATE_INVALID;
669
670 delegate_ = new TestSSLErrorHandlerDelegate(web_contents(), ssl_info_);
671 error_handler_.reset(new TestSSLErrorHandler(
672 std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(),
673 net::MapCertStatusToNetError(ssl_info_.cert_status), ssl_info_,
674 tracker_.get(), GURL() /*request_url*/,
675 /*captive_portal_service=*/nullptr));
676
677 // Fix flakiness in case system time is off and triggers a bad clock
678 // interstitial. https://crbug.com/666821#c50
679 ssl_errors::SetBuildTimeForTesting(base::Time::Now());
680 }
681
TearDown()682 void TearDown() override {
683 // Release the reference on TestSharedURLLoaderFactory before the test
684 // thread bundle flushes the IO thread so that it's destructed.
685 shared_url_loader_factory_ = nullptr;
686
687 if (error_handler()) {
688 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
689 error_handler_.reset(nullptr);
690 }
691 SSLErrorHandler::ResetConfigForTesting();
692
693 // content::RenderViewHostTestHarness::TearDown() simulates shutdown and as
694 // such destroys parts of the task environment required in these
695 // destructors.
696 test_server_.reset();
697 tracker_.reset();
698
699 content::RenderViewHostTestHarness::TearDown();
700 }
701
error_handler()702 TestSSLErrorHandler* error_handler() { return error_handler_.get(); }
delegate()703 TestSSLErrorHandlerDelegate* delegate() { return delegate_; }
704
field_trial_test()705 network_time::FieldTrialTest* field_trial_test() {
706 return field_trial_test_.get();
707 }
708
tracker()709 network_time::NetworkTimeTracker* tracker() { return tracker_.get(); }
710
test_server()711 net::EmbeddedTestServer* test_server() { return test_server_.get(); }
712
ClearErrorHandler()713 void ClearErrorHandler() { error_handler_.reset(nullptr); }
714
715 private:
CreateURLLoaderFactory(std::unique_ptr<network::PendingSharedURLLoaderFactory> * pending_url_loader_factory)716 static void CreateURLLoaderFactory(
717 std::unique_ptr<network::PendingSharedURLLoaderFactory>*
718 pending_url_loader_factory) {
719 scoped_refptr<network::TestSharedURLLoaderFactory> factory =
720 base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
721 // Holds a reference to |factory|.
722 *pending_url_loader_factory = factory->Clone();
723 }
724
725 net::SSLInfo ssl_info_;
726 std::unique_ptr<TestSSLErrorHandler> error_handler_;
727 TestSSLErrorHandlerDelegate* delegate_;
728
729 std::unique_ptr<network_time::FieldTrialTest> field_trial_test_;
730 base::SimpleTestClock* clock_;
731 base::SimpleTestTickClock* tick_clock_;
732 TestingPrefServiceSimple pref_service_;
733 scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
734 std::unique_ptr<network_time::NetworkTimeTracker> tracker_;
735 std::unique_ptr<net::EmbeddedTestServer> test_server_;
736
737 DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDateInvalidTest);
738 };
739
740 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
741
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowSSLInterstitialOnTimerExpired)742 TEST_F(SSLErrorHandlerNameMismatchTest,
743 ShouldShowSSLInterstitialOnTimerExpired) {
744 base::HistogramTester histograms;
745 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
746 error_handler()->StartHandlingError();
747
748 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
749 EXPECT_TRUE(delegate()->captive_portal_checked());
750 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
751 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
752
753 delegate()->ClearSeenOperations();
754 base::RunLoop().RunUntilIdle();
755
756 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
757 EXPECT_FALSE(delegate()->captive_portal_checked());
758 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
759 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
760
761 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
762 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
763 SSLErrorHandler::HANDLE_ALL, 1);
764 histograms.ExpectBucketCount(
765 SSLErrorHandler::GetHistogramNameForTesting(),
766 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
767 }
768
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowCustomInterstitialOnCaptivePortalResult)769 TEST_F(SSLErrorHandlerNameMismatchTest,
770 ShouldShowCustomInterstitialOnCaptivePortalResult) {
771 base::HistogramTester histograms;
772 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
773 error_handler()->StartHandlingError();
774
775 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
776 EXPECT_TRUE(delegate()->captive_portal_checked());
777 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
778 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
779 // Fake a captive portal result.
780 delegate()->ClearSeenOperations();
781
782 captive_portal::CaptivePortalService::Results results;
783 results.previous_result = captive_portal::RESULT_INTERNET_CONNECTED;
784 results.result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
785
786 error_handler()->Observe(results);
787 base::RunLoop().RunUntilIdle();
788
789 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
790 EXPECT_FALSE(delegate()->captive_portal_checked());
791 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
792 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
793
794 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
795 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
796 SSLErrorHandler::HANDLE_ALL, 1);
797 histograms.ExpectBucketCount(
798 SSLErrorHandler::GetHistogramNameForTesting(),
799 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
800 }
801
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowSSLInterstitialOnNoCaptivePortalResult)802 TEST_F(SSLErrorHandlerNameMismatchTest,
803 ShouldShowSSLInterstitialOnNoCaptivePortalResult) {
804 base::HistogramTester histograms;
805 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
806 error_handler()->StartHandlingError();
807
808 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
809 EXPECT_TRUE(delegate()->captive_portal_checked());
810 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
811 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
812 // Fake a "connected to internet" result for the captive portal check.
813 // This should immediately trigger an SSL interstitial without waiting for
814 // the timer to expire.
815 delegate()->ClearSeenOperations();
816
817 captive_portal::CaptivePortalService::Results results;
818 results.previous_result = captive_portal::RESULT_INTERNET_CONNECTED;
819 results.result = captive_portal::RESULT_INTERNET_CONNECTED;
820
821 error_handler()->Observe(results);
822 base::RunLoop().RunUntilIdle();
823
824 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
825 EXPECT_FALSE(delegate()->captive_portal_checked());
826 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
827 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
828
829 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
830 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
831 SSLErrorHandler::HANDLE_ALL, 1);
832 histograms.ExpectBucketCount(
833 SSLErrorHandler::GetHistogramNameForTesting(),
834 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
835 }
836
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldNotCheckSuggestedUrlIfNoSuggestedUrl)837 TEST_F(SSLErrorHandlerNameMismatchTest,
838 ShouldNotCheckSuggestedUrlIfNoSuggestedUrl) {
839 base::HistogramTester histograms;
840 error_handler()->StartHandlingError();
841
842 EXPECT_TRUE(delegate()->captive_portal_checked());
843 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
844 EXPECT_FALSE(delegate()->suggested_url_checked());
845 base::RunLoop().RunUntilIdle();
846
847 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
848 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
849
850 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
851 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
852 SSLErrorHandler::HANDLE_ALL, 1);
853 histograms.ExpectBucketCount(
854 SSLErrorHandler::GetHistogramNameForTesting(),
855 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
856 }
857
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldNotCheckCaptivePortalIfSuggestedUrlExists)858 TEST_F(SSLErrorHandlerNameMismatchTest,
859 ShouldNotCheckCaptivePortalIfSuggestedUrlExists) {
860 base::HistogramTester histograms;
861 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
862 delegate()->set_suggested_url_exists();
863 error_handler()->StartHandlingError();
864
865 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
866 EXPECT_TRUE(delegate()->suggested_url_checked());
867 EXPECT_FALSE(delegate()->captive_portal_checked());
868 base::RunLoop().RunUntilIdle();
869
870 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
871 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
872
873 // Note that the suggested URL check is never completed, so there is no entry
874 // for WWW_MISMATCH_URL_AVAILABLE or WWW_MISMATCH_URL_NOT_AVAILABLE.
875 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
876 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
877 SSLErrorHandler::HANDLE_ALL, 1);
878 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
879 SSLErrorHandler::WWW_MISMATCH_FOUND_IN_SAN, 1);
880 histograms.ExpectBucketCount(
881 SSLErrorHandler::GetHistogramNameForTesting(),
882 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
883 }
884
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldNotHandleNameMismatchOnNonOverridableError)885 TEST_F(SSLErrorHandlerNameMismatchTest,
886 ShouldNotHandleNameMismatchOnNonOverridableError) {
887 base::HistogramTester histograms;
888 delegate()->set_non_overridable_error();
889 delegate()->set_suggested_url_exists();
890 error_handler()->StartHandlingError();
891
892 EXPECT_FALSE(delegate()->suggested_url_checked());
893 EXPECT_TRUE(delegate()->captive_portal_checked());
894 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
895 base::RunLoop().RunUntilIdle();
896
897 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
898 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
899
900 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
901 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
902 SSLErrorHandler::HANDLE_ALL, 1);
903 histograms.ExpectBucketCount(
904 SSLErrorHandler::GetHistogramNameForTesting(),
905 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 1);
906 }
907
908 #else // #if !BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
909
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowSSLInterstitialOnCaptivePortalDetectionDisabled)910 TEST_F(SSLErrorHandlerNameMismatchTest,
911 ShouldShowSSLInterstitialOnCaptivePortalDetectionDisabled) {
912 base::HistogramTester histograms;
913 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
914 error_handler()->StartHandlingError();
915 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
916 EXPECT_FALSE(delegate()->captive_portal_checked());
917 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
918 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
919
920 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
921 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
922 SSLErrorHandler::HANDLE_ALL, 1);
923 histograms.ExpectBucketCount(
924 SSLErrorHandler::GetHistogramNameForTesting(),
925 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
926 }
927
928 #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
929
930 // Test that a captive portal interstitial is shown if the OS reports a portal.
TEST_F(SSLErrorHandlerNameMismatchTest,OSReportsCaptivePortal)931 TEST_F(SSLErrorHandlerNameMismatchTest, OSReportsCaptivePortal) {
932 base::HistogramTester histograms;
933 delegate()->set_os_reports_captive_portal();
934
935 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
936 error_handler()->StartHandlingError();
937 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
938 EXPECT_FALSE(delegate()->captive_portal_checked());
939 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
940 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
941
942 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
943 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
944 SSLErrorHandler::HANDLE_ALL, 1);
945 histograms.ExpectBucketCount(
946 SSLErrorHandler::GetHistogramNameForTesting(),
947 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
948 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
949 SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 1);
950 }
951
952 // Test that a captive portal interstitial isn't shown if the OS reports a
953 // portal but CaptivePortalInterstitial feature is disabled.
TEST_F(SSLErrorHandlerNameMismatchTest,OSReportsCaptivePortal_FeatureDisabled)954 TEST_F(SSLErrorHandlerNameMismatchTest,
955 OSReportsCaptivePortal_FeatureDisabled) {
956 base::test::ScopedFeatureList scoped_feature_list;
957 scoped_feature_list.InitAndDisableFeature(kCaptivePortalInterstitial);
958
959 base::HistogramTester histograms;
960 delegate()->set_os_reports_captive_portal();
961
962 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
963 error_handler()->StartHandlingError();
964 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
965 EXPECT_FALSE(delegate()->captive_portal_checked());
966 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
967 EXPECT_FALSE(delegate()->captive_portal_interstitial_shown());
968
969 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
970 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
971 SSLErrorHandler::HANDLE_ALL, 1);
972 histograms.ExpectBucketCount(
973 SSLErrorHandler::GetHistogramNameForTesting(),
974 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
975 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
976 SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 0);
977 }
978
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowSSLInterstitialOnTimerExpiredWhenSuggestedUrlExists)979 TEST_F(SSLErrorHandlerNameMismatchTest,
980 ShouldShowSSLInterstitialOnTimerExpiredWhenSuggestedUrlExists) {
981 base::HistogramTester histograms;
982 delegate()->set_suggested_url_exists();
983 error_handler()->StartHandlingError();
984
985 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
986 EXPECT_TRUE(delegate()->suggested_url_checked());
987 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
988 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
989
990 base::RunLoop().RunUntilIdle();
991
992 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
993 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
994 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
995
996 // Note that the suggested URL check is never completed, so there is no entry
997 // for WWW_MISMATCH_URL_AVAILABLE or WWW_MISMATCH_URL_NOT_AVAILABLE.
998 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
999 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1000 SSLErrorHandler::HANDLE_ALL, 1);
1001 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1002 SSLErrorHandler::WWW_MISMATCH_FOUND_IN_SAN, 1);
1003 histograms.ExpectBucketCount(
1004 SSLErrorHandler::GetHistogramNameForTesting(),
1005 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
1006 }
1007
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldRedirectOnSuggestedUrlCheckResult)1008 TEST_F(SSLErrorHandlerNameMismatchTest,
1009 ShouldRedirectOnSuggestedUrlCheckResult) {
1010 base::HistogramTester histograms;
1011 delegate()->set_suggested_url_exists();
1012 error_handler()->StartHandlingError();
1013
1014 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
1015 EXPECT_TRUE(delegate()->suggested_url_checked());
1016 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
1017 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
1018 // Fake a valid suggested URL check result.
1019 // The URL returned by |SuggestedUrlCheckResult| can be different from
1020 // |suggested_url|, if there is a redirect.
1021 delegate()->SendSuggestedUrlCheckResult(
1022 CommonNameMismatchHandler::SuggestedUrlCheckResult::
1023 SUGGESTED_URL_AVAILABLE,
1024 GURL("https://random.example.com"));
1025
1026 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1027 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
1028 EXPECT_TRUE(delegate()->redirected_to_suggested_url());
1029
1030 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
1031 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1032 SSLErrorHandler::HANDLE_ALL, 1);
1033 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1034 SSLErrorHandler::WWW_MISMATCH_FOUND_IN_SAN, 1);
1035 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1036 SSLErrorHandler::WWW_MISMATCH_URL_AVAILABLE, 1);
1037 }
1038
1039 // No suggestions should be requested if certificate lacks a SubjectAltName.
TEST_F(SSLErrorHandlerNameMismatchNoSANTest,SSLCommonNameMismatchHandlingRequiresSubjectAltName)1040 TEST_F(SSLErrorHandlerNameMismatchNoSANTest,
1041 SSLCommonNameMismatchHandlingRequiresSubjectAltName) {
1042 base::HistogramTester histograms;
1043 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1044 delegate()->set_suggested_url_exists();
1045 error_handler()->StartHandlingError();
1046
1047 EXPECT_FALSE(delegate()->suggested_url_checked());
1048 base::RunLoop().RunUntilIdle();
1049
1050 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
1051 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
1052
1053 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
1054 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1055 SSLErrorHandler::HANDLE_ALL, 1);
1056 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1057 SSLErrorHandler::WWW_MISMATCH_FOUND_IN_SAN, 0);
1058 histograms.ExpectBucketCount(
1059 SSLErrorHandler::GetHistogramNameForTesting(),
1060 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
1061 }
1062
TEST_F(SSLErrorHandlerNameMismatchTest,ShouldShowSSLInterstitialOnInvalidUrlCheckResult)1063 TEST_F(SSLErrorHandlerNameMismatchTest,
1064 ShouldShowSSLInterstitialOnInvalidUrlCheckResult) {
1065 base::HistogramTester histograms;
1066 delegate()->set_suggested_url_exists();
1067 error_handler()->StartHandlingError();
1068
1069 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
1070 EXPECT_TRUE(delegate()->suggested_url_checked());
1071 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
1072 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
1073 // Fake an Invalid Suggested URL Check result.
1074 delegate()->SendSuggestedUrlCheckResult(
1075 CommonNameMismatchHandler::SuggestedUrlCheckResult::
1076 SUGGESTED_URL_NOT_AVAILABLE,
1077 GURL());
1078
1079 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1080 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
1081 EXPECT_FALSE(delegate()->redirected_to_suggested_url());
1082
1083 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 4);
1084 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1085 SSLErrorHandler::HANDLE_ALL, 1);
1086 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1087 SSLErrorHandler::WWW_MISMATCH_FOUND_IN_SAN, 1);
1088 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1089 SSLErrorHandler::WWW_MISMATCH_URL_NOT_AVAILABLE,
1090 1);
1091 histograms.ExpectBucketCount(
1092 SSLErrorHandler::GetHistogramNameForTesting(),
1093 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
1094 }
1095
1096 // Flakily fails on linux_chromium_tsan_rel_ng. http://crbug.com/989128
1097 #if defined(OS_LINUX) && defined(THREAD_SANITIZER)
1098 #define MAYBE_TimeQueryStarted DISABLED_TimeQueryStarted
1099 #else
1100 #define MAYBE_TimeQueryStarted TimeQueryStarted
1101 #endif
TEST_F(SSLErrorHandlerDateInvalidTest,MAYBE_TimeQueryStarted)1102 TEST_F(SSLErrorHandlerDateInvalidTest, MAYBE_TimeQueryStarted) {
1103 base::HistogramTester histograms;
1104 base::Time network_time;
1105 base::TimeDelta uncertainty;
1106 SSLErrorHandler::SetInterstitialDelayForTesting(
1107 base::TimeDelta::FromHours(1));
1108 EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
1109 tracker()->GetNetworkTime(&network_time, &uncertainty));
1110
1111 // Enable network time queries and handle the error. A bad clock interstitial
1112 // should be shown.
1113 test_server()->RegisterRequestHandler(
1114 base::Bind(&network_time::GoodTimeResponseHandler));
1115 EXPECT_TRUE(test_server()->Start());
1116 tracker()->SetTimeServerURLForTesting(test_server()->GetURL("/"));
1117 field_trial_test()->SetNetworkQueriesWithVariationsService(
1118 true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY);
1119 error_handler()->StartHandlingError();
1120
1121 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
1122 tracker()->WaitForFetchForTesting(123123123);
1123 base::RunLoop().RunUntilIdle();
1124
1125 EXPECT_TRUE(delegate()->bad_clock_interstitial_shown());
1126 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1127 // Check that the histogram for the delay was recorded.
1128 histograms.ExpectTotalCount(kCertDateErrorHistogram, 1);
1129 }
1130
1131 // Tests that an SSL interstitial is shown if the accuracy of the system
1132 // clock can't be determined because network time is unavailable.
1133
1134 // Flakily fails on linux_chromium_tsan_rel_ng. http://crbug.com/989225
1135 #if defined(OS_LINUX) && defined(THREAD_SANITIZER)
1136 #define MAYBE_NoTimeQueries DISABLED_NoTimeQueries
1137 #else
1138 #define MAYBE_NoTimeQueries NoTimeQueries
1139 #endif
TEST_F(SSLErrorHandlerDateInvalidTest,MAYBE_NoTimeQueries)1140 TEST_F(SSLErrorHandlerDateInvalidTest, MAYBE_NoTimeQueries) {
1141 base::HistogramTester histograms;
1142 base::Time network_time;
1143 base::TimeDelta uncertainty;
1144 EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
1145 tracker()->GetNetworkTime(&network_time, &uncertainty));
1146
1147 // Handle the error without enabling time queries. A bad clock interstitial
1148 // should not be shown.
1149 error_handler()->StartHandlingError();
1150
1151 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1152 EXPECT_FALSE(delegate()->bad_clock_interstitial_shown());
1153 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
1154 // Check that the histogram for the delay was recorded.
1155 histograms.ExpectTotalCount(kCertDateErrorHistogram, 1);
1156 }
1157
1158 // Tests that an SSL interstitial is shown if determing the accuracy of
1159 // the system clock times out (e.g. because a network time query hangs).
1160
1161 // Flakily fails on linux_chromium_tsan_rel_ng. http://crbug.com/989289
1162 #if defined(OS_LINUX) && defined(THREAD_SANITIZER)
1163 #define MAYBE_TimeQueryHangs DISABLED_TimeQueryHangs
1164 #else
1165 #define MAYBE_TimeQueryHangs TimeQueryHangs
1166 #endif
TEST_F(SSLErrorHandlerDateInvalidTest,MAYBE_TimeQueryHangs)1167 TEST_F(SSLErrorHandlerDateInvalidTest, MAYBE_TimeQueryHangs) {
1168 base::HistogramTester histograms;
1169 base::Time network_time;
1170 base::TimeDelta uncertainty;
1171 EXPECT_EQ(network_time::NetworkTimeTracker::NETWORK_TIME_NO_SYNC_ATTEMPT,
1172 tracker()->GetNetworkTime(&network_time, &uncertainty));
1173
1174 // Enable network time queries and handle the error. Because the
1175 // network time cannot be determined before the timer elapses, an SSL
1176 // interstitial should be shown.
1177 base::RunLoop wait_for_time_query_loop;
1178 test_server()->RegisterRequestHandler(
1179 base::Bind(&WaitForRequest, wait_for_time_query_loop.QuitClosure()));
1180 EXPECT_TRUE(test_server()->Start());
1181 tracker()->SetTimeServerURLForTesting(test_server()->GetURL("/"));
1182 field_trial_test()->SetNetworkQueriesWithVariationsService(
1183 true, 0.0, network_time::NetworkTimeTracker::FETCHES_ON_DEMAND_ONLY);
1184 error_handler()->StartHandlingError();
1185 EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
1186 wait_for_time_query_loop.Run();
1187 base::RunLoop().RunUntilIdle();
1188
1189 EXPECT_FALSE(delegate()->bad_clock_interstitial_shown());
1190 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
1191 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1192
1193 // Check that the histogram for the delay was recorded.
1194 histograms.ExpectTotalCount(kCertDateErrorHistogram, 1);
1195
1196 // Clear the error handler to test that, when the request completes,
1197 // it doesn't try to call a callback on a deleted SSLErrorHandler.
1198 ClearErrorHandler();
1199
1200 // Shut down the server to cancel the pending request.
1201 ASSERT_TRUE(test_server()->ShutdownAndWaitUntilComplete());
1202 }
1203
1204 // Tests that a certificate marked as a known captive portal certificate causes
1205 // the captive portal interstitial to be shown.
TEST_F(SSLErrorAssistantProtoTest,CaptivePortal_FeatureEnabled)1206 TEST_F(SSLErrorAssistantProtoTest, CaptivePortal_FeatureEnabled) {
1207 SetCaptivePortalFeatureEnabled(true);
1208
1209 base::HistogramTester histograms;
1210
1211 RunCaptivePortalTest();
1212
1213 // Timer shouldn't start for a known captive portal certificate.
1214 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1215 EXPECT_FALSE(delegate()->captive_portal_checked());
1216 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
1217 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
1218 EXPECT_FALSE(delegate()->suggested_url_checked());
1219
1220 // A buggy SSL error handler might have incorrectly started the timer. Run
1221 // to completion to ensure the timer is expired.
1222 base::RunLoop().RunUntilIdle();
1223
1224 EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
1225 EXPECT_FALSE(delegate()->captive_portal_checked());
1226 EXPECT_FALSE(delegate()->ssl_interstitial_shown());
1227 EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
1228 EXPECT_FALSE(delegate()->suggested_url_checked());
1229
1230 // Check that the histogram for the captive portal cert was recorded.
1231 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 3);
1232 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1233 SSLErrorHandler::HANDLE_ALL, 1);
1234 histograms.ExpectBucketCount(
1235 SSLErrorHandler::GetHistogramNameForTesting(),
1236 SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
1237 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1238 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
1239 }
1240
1241 // Tests that a certificate marked as a known captive portal certificate does
1242 // not cause the captive portal interstitial to be shown, if the feature is
1243 // disabled.
TEST_F(SSLErrorAssistantProtoTest,CaptivePortal_FeatureDisabled)1244 TEST_F(SSLErrorAssistantProtoTest, CaptivePortal_FeatureDisabled) {
1245 SetCaptivePortalFeatureEnabled(false);
1246
1247 // Default error for SSLErrorHandlerNameMismatchTest tests is name mismatch.
1248 TestNoCaptivePortalInterstitial();
1249 }
1250
1251 // Tests that an error other than name mismatch does not cause a captive portal
1252 // interstitial to be shown, even if the certificate is marked as a known
1253 // captive portal certificate.
TEST_F(SSLErrorAssistantProtoTest,CaptivePortal_AuthorityInvalidError_NoInterstitial)1254 TEST_F(SSLErrorAssistantProtoTest,
1255 CaptivePortal_AuthorityInvalidError_NoInterstitial) {
1256 SetCaptivePortalFeatureEnabled(true);
1257
1258 ResetErrorHandlerFromFile(kOkayCertName, net::CERT_STATUS_AUTHORITY_INVALID);
1259 TestNoCaptivePortalInterstitial();
1260 }
1261
1262 // Tests that an authority invalid error in addition to name mismatch error does
1263 // not cause a captive portal interstitial to be shown, even if the certificate
1264 // is marked as a known captive portal certificate. The resulting error is
1265 // authority-invalid.
TEST_F(SSLErrorAssistantProtoTest,CaptivePortal_TwoErrors_NoInterstitial)1266 TEST_F(SSLErrorAssistantProtoTest, CaptivePortal_TwoErrors_NoInterstitial) {
1267 SetCaptivePortalFeatureEnabled(true);
1268
1269 const net::CertStatus cert_status =
1270 net::CERT_STATUS_COMMON_NAME_INVALID | net::CERT_STATUS_AUTHORITY_INVALID;
1271 // Sanity check that AUTHORITY_INVALID is seen as the net error.
1272 ASSERT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
1273 net::MapCertStatusToNetError(cert_status));
1274 ResetErrorHandlerFromFile(kOkayCertName, cert_status);
1275 TestNoCaptivePortalInterstitial();
1276 }
1277
1278 // Tests that another error in addition to name mismatch error does not cause a
1279 // captive portal interstitial to be shown, even if the certificate is marked as
1280 // a known captive portal certificate. Similar to
1281 // NameMismatchAndAuthorityInvalid, except the resulting error is name mismatch.
TEST_F(SSLErrorAssistantProtoTest,CaptivePortal_TwoErrorsIncludingNameMismatch_NoInterstitial)1282 TEST_F(SSLErrorAssistantProtoTest,
1283 CaptivePortal_TwoErrorsIncludingNameMismatch_NoInterstitial) {
1284 SetCaptivePortalFeatureEnabled(true);
1285
1286 const net::CertStatus cert_status =
1287 net::CERT_STATUS_COMMON_NAME_INVALID | net::CERT_STATUS_WEAK_KEY;
1288 // Sanity check that COMMON_NAME_INVALID is seen as the net error, since the
1289 // test is designed to verify that SSLErrorHandler notices other errors in the
1290 // CertStatus even when COMMON_NAME_INVALID is the net error.
1291 ASSERT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
1292 net::MapCertStatusToNetError(cert_status));
1293 ResetErrorHandlerFromFile(kOkayCertName, cert_status);
1294 TestNoCaptivePortalInterstitial();
1295 }
1296
1297 // Tests that if a certificate matches the issuer common name regex of a MITM
1298 // software entry but not the issuer organization name a MITM software
1299 // interstitial will not be displayed.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateDoesNotMatchOrganizationName_NoInterstitial)1300 TEST_F(SSLErrorAssistantProtoTest,
1301 MITMSoftware_CertificateDoesNotMatchOrganizationName_NoInterstitial) {
1302 SetMITMSoftwareFeatureEnabled(true);
1303
1304 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1305 net::CERT_STATUS_AUTHORITY_INVALID);
1306
1307 auto config_proto =
1308 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1309 config_proto->set_version_id(kLargeVersionId);
1310
1311 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1312 filter->set_name("Misconfigured Firewall");
1313 filter->set_issuer_common_name_regex("Misconfigured Firewall_[A-Z0-9]+");
1314 filter->set_issuer_organization_regex("Non-Matching Organization Name");
1315 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1316 TestNoMITMSoftwareInterstitial();
1317 }
1318
1319 // Tests that if a certificate matches the issuer organization name regex of a
1320 // MITM software entry but not the issuer common name a MITM software
1321 // interstitial will not be displayed.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateDoesNotMatchCommonName_NoInterstitial)1322 TEST_F(SSLErrorAssistantProtoTest,
1323 MITMSoftware_CertificateDoesNotMatchCommonName_NoInterstitial) {
1324 SetMITMSoftwareFeatureEnabled(true);
1325
1326 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1327 net::CERT_STATUS_AUTHORITY_INVALID);
1328
1329 auto config_proto =
1330 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1331 config_proto->set_version_id(kLargeVersionId);
1332
1333 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1334 filter->set_name("Misconfigured Firewall");
1335 filter->set_issuer_common_name_regex("Non-Matching Issuer Common Name");
1336 filter->set_issuer_organization_regex("Misconfigured Firewall");
1337 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1338 TestNoMITMSoftwareInterstitial();
1339 }
1340
1341 // Tests that a certificate with no organization name or common name will not
1342 // trigger a MITM software interstitial.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateWithNoOrganizationOrCommonName_NoInterstitial)1343 TEST_F(SSLErrorAssistantProtoTest,
1344 MITMSoftware_CertificateWithNoOrganizationOrCommonName_NoInterstitial) {
1345 SetMITMSoftwareFeatureEnabled(true);
1346
1347 ResetErrorHandlerFromString(kCertWithoutOrganizationOrCommonName,
1348 net::CERT_STATUS_AUTHORITY_INVALID);
1349 InitMITMSoftwareList();
1350 TestNoMITMSoftwareInterstitial();
1351 }
1352
1353 // Tests that when everything else is in order, a matching MITM software
1354 // certificate will trigger the MITM software interstitial.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateMatchesCommonNameAndOrganizationName)1355 TEST_F(SSLErrorAssistantProtoTest,
1356 MITMSoftware_CertificateMatchesCommonNameAndOrganizationName) {
1357 SetMITMSoftwareFeatureEnabled(true);
1358
1359 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1360 net::CERT_STATUS_AUTHORITY_INVALID);
1361 InitMITMSoftwareList();
1362 TestMITMSoftwareInterstitial();
1363 }
1364
1365 // Tests that a known MITM software entry in the SSL error assistant proto that
1366 // has a common name regex but not an organization name regex can still trigger
1367 // a MITM software interstitial.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateMatchesCommonName)1368 TEST_F(SSLErrorAssistantProtoTest, MITMSoftware_CertificateMatchesCommonName) {
1369 SetMITMSoftwareFeatureEnabled(true);
1370 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1371 net::CERT_STATUS_AUTHORITY_INVALID);
1372 // Register a MITM Software entry in the SSL error assistant proto that has a
1373 // common name regex but not an organization name regex.
1374 auto config_proto =
1375 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1376 config_proto->set_version_id(kLargeVersionId);
1377
1378 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1379 filter->set_name("Misconfigured Firewall");
1380 filter->set_issuer_common_name_regex("Misconfigured Firewall_[A-Z0-9]+");
1381 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1382 TestMITMSoftwareInterstitial();
1383 }
1384
1385 // Tests that a known MITM software entry in the SSL error assistant proto that
1386 // has an organization name regex but not a common name name regex can still
1387 // trigger a MITM software interstitial.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_CertificateMatchesOrganizationName)1388 TEST_F(SSLErrorAssistantProtoTest,
1389 MITMSoftware_CertificateMatchesOrganizationName) {
1390 SetMITMSoftwareFeatureEnabled(true);
1391 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1392 net::CERT_STATUS_AUTHORITY_INVALID);
1393 // Register a MITM Software entry in the SSL error assistant proto that has an
1394 // organization name regex, but not a common name regex.
1395 auto config_proto =
1396 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1397 config_proto->set_version_id(kLargeVersionId);
1398
1399 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1400 filter->set_name("Misconfigured Firewall");
1401 filter->set_issuer_organization_regex("Misconfigured Firewall");
1402 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1403 TestMITMSoftwareInterstitial();
1404 }
1405
1406 // Tests that only a full regex match will trigger the MITM software
1407 // interstitial. For example, a common name regex "Match" should not trigger the
1408 // MITM software interstitial on a certificate that's common name is
1409 // "Full Match".
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_PartialRegexMatch_NoInterstitial)1410 TEST_F(SSLErrorAssistantProtoTest,
1411 MITMSoftware_PartialRegexMatch_NoInterstitial) {
1412 SetMITMSoftwareFeatureEnabled(true);
1413 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1414 net::CERT_STATUS_AUTHORITY_INVALID);
1415 // Register a MITM software entry with common name and organization name
1416 // regexes that will match part of each the certificate's common name and
1417 // organization name fields but not the entire field.
1418 auto config_proto =
1419 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1420 config_proto->set_version_id(kLargeVersionId);
1421
1422 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1423 filter->set_name("Misconfigured Firewall");
1424 filter->set_issuer_common_name_regex("Misconfigured");
1425 filter->set_issuer_organization_regex("Misconfigured");
1426 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1427 TestNoMITMSoftwareInterstitial();
1428 }
1429
1430 // Tests that a MITM software interstitial is not triggered when neither the
1431 // common name or the organization name match.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_NonMatchingCertificate_NoInterstitial)1432 TEST_F(SSLErrorAssistantProtoTest,
1433 MITMSoftware_NonMatchingCertificate_NoInterstitial) {
1434 SetMITMSoftwareFeatureEnabled(true);
1435
1436 ResetErrorHandlerFromFile(kOkayCertName, net::CERT_STATUS_AUTHORITY_INVALID);
1437 InitMITMSoftwareList();
1438 TestNoMITMSoftwareInterstitial();
1439 }
1440
1441 // Tests that the MITM software interstitial is not triggered when the feature
1442 // is disabled by Finch.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_FeatureDisabled)1443 TEST_F(SSLErrorAssistantProtoTest, MITMSoftware_FeatureDisabled) {
1444 SetMITMSoftwareFeatureEnabled(false);
1445
1446 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1447 net::CERT_STATUS_AUTHORITY_INVALID);
1448 InitMITMSoftwareList();
1449 TestNoMITMSoftwareInterstitial();
1450 }
1451
1452 // Tests that the MITM software interstitial is not triggered when an error
1453 // other than net::CERT_STATUS_AUTHORITY_INVALID is thrown.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_WrongError_NoInterstitial)1454 TEST_F(SSLErrorAssistantProtoTest, MITMSoftware_WrongError_NoInterstitial) {
1455 SetMITMSoftwareFeatureEnabled(true);
1456
1457 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1458 net::CERT_STATUS_COMMON_NAME_INVALID);
1459 InitMITMSoftwareList();
1460 TestNoMITMSoftwareInterstitial();
1461 }
1462
1463 // Tests that the MITM software interstitial is not triggered when more than one
1464 // error is thrown.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_TwoErrors_NoInterstitial)1465 TEST_F(SSLErrorAssistantProtoTest, MITMSoftware_TwoErrors_NoInterstitial) {
1466 SetMITMSoftwareFeatureEnabled(true);
1467
1468 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1469 net::CERT_STATUS_AUTHORITY_INVALID |
1470 net::CERT_STATUS_COMMON_NAME_INVALID);
1471 InitMITMSoftwareList();
1472 TestNoMITMSoftwareInterstitial();
1473 }
1474
1475 // Tests that the MITM software interstitial is not triggered if the error
1476 // thrown is overridable.
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_Overridable_NoInterstitial)1477 TEST_F(SSLErrorAssistantProtoTest, MITMSoftware_Overridable_NoInterstitial) {
1478 base::HistogramTester histograms;
1479
1480 SetMITMSoftwareFeatureEnabled(true);
1481 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1482 net::CERT_STATUS_AUTHORITY_INVALID);
1483 InitMITMSoftwareList();
1484 error_handler()->StartHandlingError();
1485 base::RunLoop().RunUntilIdle();
1486
1487 EXPECT_TRUE(delegate()->ssl_interstitial_shown());
1488 EXPECT_FALSE(delegate()->mitm_software_interstitial_shown());
1489 EXPECT_FALSE(delegate()->suggested_url_checked());
1490
1491 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
1492 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1493 SSLErrorHandler::HANDLE_ALL, 1);
1494 histograms.ExpectBucketCount(
1495 SSLErrorHandler::GetHistogramNameForTesting(),
1496 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 0);
1497 histograms.ExpectBucketCount(
1498 SSLErrorHandler::GetHistogramNameForTesting(),
1499 SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
1500 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1501 SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL,
1502 0);
1503 }
1504
TEST_F(SSLErrorAssistantProtoTest,MITMSoftware_IgnoreDynamicUpdateWithSmallVersionId)1505 TEST_F(SSLErrorAssistantProtoTest,
1506 MITMSoftware_IgnoreDynamicUpdateWithSmallVersionId) {
1507 SetMITMSoftwareFeatureEnabled(true);
1508 ResetErrorHandlerFromString(kMisconfiguredFirewallCert,
1509 net::CERT_STATUS_AUTHORITY_INVALID);
1510
1511 // Register a MITM Software entry in the SSL error assistant proto that has a
1512 // common name regex but not an organization name regex. This should normally
1513 // trigger a MITM software interstitial, but the version_id is zero which is
1514 // less than the version_id of the local resource bundle, so the dynamic
1515 // update will be ignored.
1516 auto config_proto =
1517 std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
1518 config_proto->set_version_id(0u);
1519
1520 chrome_browser_ssl::MITMSoftware* filter = config_proto->add_mitm_software();
1521 filter->set_name("Misconfigured Firewall");
1522 filter->set_issuer_common_name_regex("Misconfigured Firewall_[A-Z0-9]+");
1523 SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
1524
1525 TestNoMITMSoftwareInterstitial();
1526 }
1527
1528 using SSLErrorHandlerTest = content::RenderViewHostTestHarness;
1529
1530 // Test that a blocked interception interstitial is shown. It would be nicer to
1531 // set the SSLInfo properly so that the cert is blocked at net level rather than
1532 // because of set_has_blocked_interception(), but that code path is already
1533 // executed in net unit tests and SSL browser tests. This test mainly checks
1534 // histogram accuracy.
TEST_F(SSLErrorHandlerTest,BlockedInterceptionInterstitial)1535 TEST_F(SSLErrorHandlerTest, BlockedInterceptionInterstitial) {
1536 net::SSLInfo ssl_info;
1537 ssl_info.cert =
1538 net::ImportCertFromFile(net::GetTestCertsDirectory(), kOkayCertName);
1539 ssl_info.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
1540 ssl_info.public_key_hashes.push_back(net::HashValue(kCertPublicKeyHashValue));
1541
1542 std::unique_ptr<TestSSLErrorHandlerDelegate> delegate(
1543 new TestSSLErrorHandlerDelegate(web_contents(), ssl_info));
1544
1545 TestSSLErrorHandlerDelegate* delegate_ptr = delegate.get();
1546 TestSSLErrorHandler error_handler(
1547 std::move(delegate), web_contents(),
1548 net::MapCertStatusToNetError(ssl_info.cert_status), ssl_info,
1549 /*network_time_tracker=*/nullptr, GURL() /*request_url*/,
1550 /*captive_portal_service=*/nullptr);
1551
1552 base::HistogramTester histograms;
1553 delegate_ptr->set_has_blocked_interception();
1554
1555 EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
1556 error_handler.StartHandlingError();
1557 EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
1558 EXPECT_FALSE(delegate_ptr->captive_portal_checked());
1559 EXPECT_FALSE(delegate_ptr->ssl_interstitial_shown());
1560 EXPECT_FALSE(delegate_ptr->captive_portal_interstitial_shown());
1561 EXPECT_TRUE(delegate_ptr->blocked_interception_interstitial_shown());
1562
1563 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
1564 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1565 SSLErrorHandler::HANDLE_ALL, 1);
1566 histograms.ExpectBucketCount(
1567 SSLErrorHandler::GetHistogramNameForTesting(),
1568 SSLErrorHandler::SHOW_BLOCKED_INTERCEPTION_INTERSTITIAL, 1);
1569 }
1570
1571 // Tests that a legacy TLS interstitial is shown. This test mainly checks
1572 // histogram accuracy (see BlockedInterceptionInterstitial test above).
TEST_F(SSLErrorHandlerTest,LegacyTLSInterstitial)1573 TEST_F(SSLErrorHandlerTest, LegacyTLSInterstitial) {
1574 net::SSLInfo ssl_info;
1575 ssl_info.cert =
1576 net::ImportCertFromFile(net::GetTestCertsDirectory(), kOkayCertName);
1577 ssl_info.cert_status = net::CERT_STATUS_LEGACY_TLS;
1578 ssl_info.public_key_hashes.push_back(net::HashValue(kCertPublicKeyHashValue));
1579
1580 std::unique_ptr<TestSSLErrorHandlerDelegate> delegate(
1581 new TestSSLErrorHandlerDelegate(web_contents(), ssl_info));
1582
1583 TestSSLErrorHandlerDelegate* delegate_ptr = delegate.get();
1584 TestSSLErrorHandler error_handler(
1585 std::move(delegate), web_contents(),
1586 net::MapCertStatusToNetError(ssl_info.cert_status), ssl_info,
1587 /*network_time_tracker=*/nullptr, /*request_url=*/GURL(),
1588 /*captive_portal_service=*/nullptr);
1589
1590 base::HistogramTester histograms;
1591 delegate_ptr->set_has_legacy_tls();
1592
1593 EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
1594 error_handler.StartHandlingError();
1595 EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
1596 EXPECT_FALSE(delegate_ptr->captive_portal_checked());
1597 EXPECT_FALSE(delegate_ptr->ssl_interstitial_shown());
1598 EXPECT_FALSE(delegate_ptr->captive_portal_interstitial_shown());
1599 EXPECT_TRUE(delegate_ptr->legacy_tls_interstitial_shown());
1600
1601 histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
1602 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1603 SSLErrorHandler::HANDLE_ALL, 1);
1604 histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
1605 SSLErrorHandler::SHOW_LEGACY_TLS_INTERSTITIAL,
1606 1);
1607 }
1608