| 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 |