OLD | NEW |
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 <stdint.h> | 7 #include <stdint.h> |
8 #include <unordered_set> | 8 #include <unordered_set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 const base::Feature kCaptivePortalInterstitial{ | 52 const base::Feature kCaptivePortalInterstitial{ |
53 "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT}; | 53 "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT}; |
54 | 54 |
55 const base::Feature kCaptivePortalCertificateList{ | 55 const base::Feature kCaptivePortalCertificateList{ |
56 "CaptivePortalCertificateList", base::FEATURE_DISABLED_BY_DEFAULT}; | 56 "CaptivePortalCertificateList", base::FEATURE_DISABLED_BY_DEFAULT}; |
57 #endif | 57 #endif |
58 | 58 |
59 const base::Feature kSSLCommonNameMismatchHandling{ | 59 const base::Feature kSSLCommonNameMismatchHandling{ |
60 "SSLCommonNameMismatchHandling", base::FEATURE_ENABLED_BY_DEFAULT}; | 60 "SSLCommonNameMismatchHandling", base::FEATURE_ENABLED_BY_DEFAULT}; |
61 | 61 |
| 62 const base::Feature kSuperfishInterstitial{"SuperfishInterstitial", |
| 63 base::FEATURE_DISABLED_BY_DEFAULT}; |
| 64 |
62 // Default delay in milliseconds before displaying the SSL interstitial. | 65 // Default delay in milliseconds before displaying the SSL interstitial. |
63 // This can be changed in tests. | 66 // This can be changed in tests. |
64 // - If there is a name mismatch and a suggested URL available result arrives | 67 // - If there is a name mismatch and a suggested URL available result arrives |
65 // during this time, the user is redirected to the suggester URL. | 68 // during this time, the user is redirected to the suggester URL. |
66 // - If a "captive portal detected" result arrives during this time, | 69 // - If a "captive portal detected" result arrives during this time, |
67 // a captive portal interstitial is displayed. | 70 // a captive portal interstitial is displayed. |
68 // - Otherwise, an SSL interstitial is displayed. | 71 // - Otherwise, an SSL interstitial is displayed. |
69 const int64_t kInterstitialDelayInMilliseconds = 3000; | 72 const int64_t kInterstitialDelayInMilliseconds = 3000; |
70 | 73 |
71 const char kHistogram[] = "interstitial.ssl_error_handler"; | 74 const char kHistogram[] = "interstitial.ssl_error_handler"; |
72 | 75 |
73 // Records an UMA histogram for whether the Superfish SPKI was present in the | 76 bool IsSuperfish(const scoped_refptr<net::X509Certificate>& cert) { |
74 // certificate chain. | 77 // This is the fingerprint of the well-known Superfish certificate at |
75 void RecordSuperfishUMA(const net::HashValueVector& public_key_hashes) { | 78 // https://pastebin.com/WcXv8QcG. Superfish is identified by certificate |
76 // This is the SPKI hash of the well-known Superfish certificate at | 79 // fingerprint rather than SPKI because net::SSLInfo does not guarantee |
77 // https://pastebin.com/WcXv8QcG. | 80 // |public_key_hashes| (the SPKIs) to be populated if the certificate doesn't |
78 const char kSuperfishSPKI[] = | 81 // verify successfully. It so happens that Superfish uses the same certificate |
79 "sha256/S7jzW6HhJvjd4bDEIGJe2G3OYae92tveqauleP8TFF4="; | 82 // universally (not just the same public key), and calculating the fingerprint |
80 net::HashValue superfish_spki_hash_value; | 83 // is more convenient here than calculating the SPKI. |
81 if (!superfish_spki_hash_value.FromString(kSuperfishSPKI)) { | 84 const net::SHA256HashValue kSuperfishFingerprint{ |
82 NOTREACHED(); | 85 {0xB6, 0xFE, 0x91, 0x51, 0x40, 0x2B, 0xAD, 0x1C, 0x06, 0xD7, 0xE6, |
83 } | 86 0x6D, 0xB6, 0x7A, 0x26, 0xAA, 0x73, 0x56, 0xF2, 0xE6, 0xC6, 0x44, |
84 bool found_superfish = false; | 87 0xDB, 0xCF, 0x9F, 0x98, 0x96, 0x8F, 0xF6, 0x32, 0xE1, 0xB7}}; |
85 for (const auto& hash : public_key_hashes) { | 88 for (const net::X509Certificate::OSCertHandle& intermediate : |
86 if (hash == superfish_spki_hash_value) { | 89 cert->GetIntermediateCertificates()) { |
87 found_superfish = true; | 90 net::SHA256HashValue hash = |
88 break; | 91 net::X509Certificate::CalculateFingerprint256(intermediate); |
| 92 if (hash == kSuperfishFingerprint) { |
| 93 return true; |
89 } | 94 } |
90 } | 95 } |
| 96 return false; |
| 97 } |
| 98 |
| 99 // Records an UMA histogram for whether the Superfish certificate was present in |
| 100 // the certificate chain. |
| 101 void RecordSuperfishUMA(const scoped_refptr<net::X509Certificate>& cert) { |
91 UMA_HISTOGRAM_BOOLEAN("interstitial.ssl_error_handler.superfish", | 102 UMA_HISTOGRAM_BOOLEAN("interstitial.ssl_error_handler.superfish", |
92 found_superfish); | 103 IsSuperfish(cert)); |
93 } | 104 } |
94 | 105 |
95 // Adds a message to console after navigation commits and then, deletes itself. | 106 // Adds a message to console after navigation commits and then, deletes itself. |
96 // Also deletes itself if the navigation is stopped. | 107 // Also deletes itself if the navigation is stopped. |
97 class CommonNameMismatchRedirectObserver | 108 class CommonNameMismatchRedirectObserver |
98 : public content::WebContentsObserver, | 109 : public content::WebContentsObserver, |
99 public content::WebContentsUserData<CommonNameMismatchRedirectObserver> { | 110 public content::WebContentsUserData<CommonNameMismatchRedirectObserver> { |
100 public: | 111 public: |
101 ~CommonNameMismatchRedirectObserver() override {} | 112 ~CommonNameMismatchRedirectObserver() override {} |
102 | 113 |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 std::move(ssl_cert_reporter_), ssl_info_, | 451 std::move(ssl_cert_reporter_), ssl_info_, |
441 callback_)) | 452 callback_)) |
442 ->Show(); | 453 ->Show(); |
443 #else | 454 #else |
444 NOTREACHED(); | 455 NOTREACHED(); |
445 #endif | 456 #endif |
446 } | 457 } |
447 | 458 |
448 void SSLErrorHandlerDelegateImpl::ShowSSLInterstitial() { | 459 void SSLErrorHandlerDelegateImpl::ShowSSLInterstitial() { |
449 // Show SSL blocking page. The interstitial owns the blocking page. | 460 // Show SSL blocking page. The interstitial owns the blocking page. |
450 (SSLBlockingPage::Create(web_contents_, cert_error_, ssl_info_, request_url_, | 461 (SSLBlockingPage::Create( |
451 options_mask_, base::Time::NowFromSystemTime(), | 462 web_contents_, cert_error_, ssl_info_, request_url_, options_mask_, |
452 std::move(ssl_cert_reporter_), callback_)) | 463 base::Time::NowFromSystemTime(), std::move(ssl_cert_reporter_), |
| 464 base::FeatureList::IsEnabled(kSuperfishInterstitial) && |
| 465 IsSuperfish(ssl_info_.cert), |
| 466 callback_)) |
453 ->Show(); | 467 ->Show(); |
454 } | 468 } |
455 | 469 |
456 void SSLErrorHandlerDelegateImpl::ShowBadClockInterstitial( | 470 void SSLErrorHandlerDelegateImpl::ShowBadClockInterstitial( |
457 const base::Time& now, | 471 const base::Time& now, |
458 ssl_errors::ClockState clock_state) { | 472 ssl_errors::ClockState clock_state) { |
459 // Show bad clock page. The interstitial owns the blocking page. | 473 // Show bad clock page. The interstitial owns the blocking page. |
460 (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, | 474 (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, |
461 now, clock_state, std::move(ssl_cert_reporter_), | 475 now, clock_state, std::move(ssl_cert_reporter_), |
462 callback_)) | 476 callback_)) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 request_url_(request_url), | 570 request_url_(request_url), |
557 callback_(callback), | 571 callback_(callback), |
558 weak_ptr_factory_(this) {} | 572 weak_ptr_factory_(this) {} |
559 | 573 |
560 SSLErrorHandler::~SSLErrorHandler() { | 574 SSLErrorHandler::~SSLErrorHandler() { |
561 } | 575 } |
562 | 576 |
563 void SSLErrorHandler::StartHandlingError() { | 577 void SSLErrorHandler::StartHandlingError() { |
564 RecordUMA(HANDLE_ALL); | 578 RecordUMA(HANDLE_ALL); |
565 | 579 |
566 RecordSuperfishUMA(ssl_info_.public_key_hashes); | 580 RecordSuperfishUMA(ssl_info_.cert); |
567 | 581 |
568 if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) == | 582 if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) == |
569 ssl_errors::ErrorInfo::CERT_DATE_INVALID) { | 583 ssl_errors::ErrorInfo::CERT_DATE_INVALID) { |
570 HandleCertDateInvalidError(); | 584 HandleCertDateInvalidError(); |
571 return; | 585 return; |
572 } | 586 } |
573 | 587 |
574 const net::CertStatus non_name_mismatch_errors = | 588 const net::CertStatus non_name_mismatch_errors = |
575 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID; | 589 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID; |
576 const bool only_error_is_name_mismatch = | 590 const bool only_error_is_name_mismatch = |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 network_time::NetworkTimeTracker* tracker = | 809 network_time::NetworkTimeTracker* tracker = |
796 g_config.Pointer()->network_time_tracker(); | 810 g_config.Pointer()->network_time_tracker(); |
797 ssl_errors::ClockState clock_state = ssl_errors::GetClockState(now, tracker); | 811 ssl_errors::ClockState clock_state = ssl_errors::GetClockState(now, tracker); |
798 if (clock_state == ssl_errors::CLOCK_STATE_FUTURE || | 812 if (clock_state == ssl_errors::CLOCK_STATE_FUTURE || |
799 clock_state == ssl_errors::CLOCK_STATE_PAST) { | 813 clock_state == ssl_errors::CLOCK_STATE_PAST) { |
800 ShowBadClockInterstitial(now, clock_state); | 814 ShowBadClockInterstitial(now, clock_state); |
801 return; // |this| is deleted after showing the interstitial. | 815 return; // |this| is deleted after showing the interstitial. |
802 } | 816 } |
803 ShowSSLInterstitial(); | 817 ShowSSLInterstitial(); |
804 } | 818 } |
OLD | NEW |