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

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

Issue 2949003003: Implement a skeleton of the Superfish interstitial (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ssl/ssl_error_handler.h" 5 #include "chrome/browser/ssl/ssl_error_handler.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <unordered_set> 8 #include <unordered_set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/feature_list.h" 12 #include "base/feature_list.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/time/clock.h" 19 #include "base/time/clock.h"
20 #include "base/time/time.h" 20 #include "base/time/time.h"
21 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ssl/bad_clock_blocking_page.h" 23 #include "chrome/browser/ssl/bad_clock_blocking_page.h"
24 #include "chrome/browser/ssl/ssl_blocking_page.h" 24 #include "chrome/browser/ssl/ssl_blocking_page.h"
25 #include "chrome/browser/ssl/ssl_cert_reporter.h" 25 #include "chrome/browser/ssl/ssl_cert_reporter.h"
26 #include "chrome/browser/ssl/ssl_error_assistant.pb.h" 26 #include "chrome/browser/ssl/ssl_error_assistant.pb.h"
27 #include "chrome/browser/ssl/superfish_blocking_page.h"
27 #include "chrome/common/features.h" 28 #include "chrome/common/features.h"
28 #include "chrome/grit/browser_resources.h" 29 #include "chrome/grit/browser_resources.h"
29 #include "components/network_time/network_time_tracker.h" 30 #include "components/network_time/network_time_tracker.h"
30 #include "components/ssl_errors/error_classification.h" 31 #include "components/ssl_errors/error_classification.h"
31 #include "components/ssl_errors/error_info.h" 32 #include "components/ssl_errors/error_info.h"
32 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/navigation_handle.h" 34 #include "content/public/browser/navigation_handle.h"
34 #include "content/public/browser/notification_service.h" 35 #include "content/public/browser/notification_service.h"
35 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/notification_source.h"
36 #include "content/public/browser/render_frame_host.h" 37 #include "content/public/browser/render_frame_host.h"
(...skipping 15 matching lines...) Expand all
52 const base::Feature kCaptivePortalInterstitial{ 53 const base::Feature kCaptivePortalInterstitial{
53 "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT}; 54 "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT};
54 55
55 const base::Feature kCaptivePortalCertificateList{ 56 const base::Feature kCaptivePortalCertificateList{
56 "CaptivePortalCertificateList", base::FEATURE_DISABLED_BY_DEFAULT}; 57 "CaptivePortalCertificateList", base::FEATURE_DISABLED_BY_DEFAULT};
57 #endif 58 #endif
58 59
59 const base::Feature kSSLCommonNameMismatchHandling{ 60 const base::Feature kSSLCommonNameMismatchHandling{
60 "SSLCommonNameMismatchHandling", base::FEATURE_ENABLED_BY_DEFAULT}; 61 "SSLCommonNameMismatchHandling", base::FEATURE_ENABLED_BY_DEFAULT};
61 62
63 const base::Feature kSuperfishInterstitial{"SuperfishInterstitial",
64 base::FEATURE_DISABLED_BY_DEFAULT};
65
62 // Default delay in milliseconds before displaying the SSL interstitial. 66 // Default delay in milliseconds before displaying the SSL interstitial.
63 // This can be changed in tests. 67 // This can be changed in tests.
64 // - If there is a name mismatch and a suggested URL available result arrives 68 // - 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. 69 // during this time, the user is redirected to the suggester URL.
66 // - If a "captive portal detected" result arrives during this time, 70 // - If a "captive portal detected" result arrives during this time,
67 // a captive portal interstitial is displayed. 71 // a captive portal interstitial is displayed.
68 // - Otherwise, an SSL interstitial is displayed. 72 // - Otherwise, an SSL interstitial is displayed.
69 const int64_t kInterstitialDelayInMilliseconds = 3000; 73 const int64_t kInterstitialDelayInMilliseconds = 3000;
70 74
71 const char kHistogram[] = "interstitial.ssl_error_handler"; 75 const char kHistogram[] = "interstitial.ssl_error_handler";
72 76
73 // Records an UMA histogram for whether the Superfish SPKI was present in the 77 bool IsSuperfish(const scoped_refptr<net::X509Certificate>& cert) {
74 // certificate chain. 78 // This is the fingerprint of the well-known Superfish certificate at
75 void RecordSuperfishUMA(const net::HashValueVector& public_key_hashes) { 79 // https://pastebin.com/WcXv8QcG. Superfish is identified by certificate
76 // This is the SPKI hash of the well-known Superfish certificate at 80 // fingerprint rather than SPKI because net::SSLInfo does not guarantee
77 // https://pastebin.com/WcXv8QcG. 81 // |public_key_hashes| (the SPKIs) to be populated if the certificate doesn't
78 const char kSuperfishSPKI[] = 82 // verify successfully. It so happens that Superfish uses the same certificate
79 "sha256/S7jzW6HhJvjd4bDEIGJe2G3OYae92tveqauleP8TFF4="; 83 // universally (not just the same public key), and calculating the fingerprint
80 net::HashValue superfish_spki_hash_value; 84 // is more convenient here than calculating the SPKI.
81 if (!superfish_spki_hash_value.FromString(kSuperfishSPKI)) { 85 const net::SHA256HashValue kSuperfishFingerprint{
82 NOTREACHED(); 86 {0xB6, 0xFE, 0x91, 0x51, 0x40, 0x2B, 0xAD, 0x1C, 0x06, 0xD7, 0xE6,
83 } 87 0x6D, 0xB6, 0x7A, 0x26, 0xAA, 0x73, 0x56, 0xF2, 0xE6, 0xC6, 0x44,
84 bool found_superfish = false; 88 0xDB, 0xCF, 0x9F, 0x98, 0x96, 0x8F, 0xF6, 0x32, 0xE1, 0xB7}};
85 for (const auto& hash : public_key_hashes) { 89 for (const net::X509Certificate::OSCertHandle& intermediate :
86 if (hash == superfish_spki_hash_value) { 90 cert->GetIntermediateCertificates()) {
87 found_superfish = true; 91 net::SHA256HashValue hash =
88 break; 92 net::X509Certificate::CalculateFingerprint256(intermediate);
93 if (hash == kSuperfishFingerprint) {
94 return true;
89 } 95 }
90 } 96 }
97 return false;
98 }
99
100 // Records an UMA histogram for whether the Superfish certificate was present in
101 // the certificate chain.
102 void RecordSuperfishUMA(const scoped_refptr<net::X509Certificate>& cert) {
91 UMA_HISTOGRAM_BOOLEAN("interstitial.ssl_error_handler.superfish", 103 UMA_HISTOGRAM_BOOLEAN("interstitial.ssl_error_handler.superfish",
92 found_superfish); 104 IsSuperfish(cert));
93 } 105 }
94 106
95 // Adds a message to console after navigation commits and then, deletes itself. 107 // Adds a message to console after navigation commits and then, deletes itself.
96 // Also deletes itself if the navigation is stopped. 108 // Also deletes itself if the navigation is stopped.
97 class CommonNameMismatchRedirectObserver 109 class CommonNameMismatchRedirectObserver
98 : public content::WebContentsObserver, 110 : public content::WebContentsObserver,
99 public content::WebContentsUserData<CommonNameMismatchRedirectObserver> { 111 public content::WebContentsUserData<CommonNameMismatchRedirectObserver> {
100 public: 112 public:
101 ~CommonNameMismatchRedirectObserver() override {} 113 ~CommonNameMismatchRedirectObserver() override {}
102 114
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 std::move(ssl_cert_reporter_), ssl_info_, 452 std::move(ssl_cert_reporter_), ssl_info_,
441 callback_)) 453 callback_))
442 ->Show(); 454 ->Show();
443 #else 455 #else
444 NOTREACHED(); 456 NOTREACHED();
445 #endif 457 #endif
446 } 458 }
447 459
448 void SSLErrorHandlerDelegateImpl::ShowSSLInterstitial() { 460 void SSLErrorHandlerDelegateImpl::ShowSSLInterstitial() {
449 // Show SSL blocking page. The interstitial owns the blocking page. 461 // Show SSL blocking page. The interstitial owns the blocking page.
450 (SSLBlockingPage::Create(web_contents_, cert_error_, ssl_info_, request_url_, 462 if (base::FeatureList::IsEnabled(kSuperfishInterstitial) &&
451 options_mask_, base::Time::NowFromSystemTime(), 463 IsSuperfish(ssl_info_.cert)) {
452 std::move(ssl_cert_reporter_), callback_)) 464 (SuperfishBlockingPage::Create(web_contents_, cert_error_, ssl_info_,
453 ->Show(); 465 request_url_, options_mask_,
466 base::Time::NowFromSystemTime(),
467 std::move(ssl_cert_reporter_), callback_))
468 ->Show();
meacer 2017/06/22 19:06:18 nit: return early here, and remove the else to get
estark 2017/06/22 22:01:05 n/a
469 } else {
470 (SSLBlockingPage::Create(web_contents_, cert_error_, ssl_info_,
471 request_url_, options_mask_,
472 base::Time::NowFromSystemTime(),
473 std::move(ssl_cert_reporter_), callback_))
474 ->Show();
475 }
454 } 476 }
455 477
456 void SSLErrorHandlerDelegateImpl::ShowBadClockInterstitial( 478 void SSLErrorHandlerDelegateImpl::ShowBadClockInterstitial(
457 const base::Time& now, 479 const base::Time& now,
458 ssl_errors::ClockState clock_state) { 480 ssl_errors::ClockState clock_state) {
459 // Show bad clock page. The interstitial owns the blocking page. 481 // Show bad clock page. The interstitial owns the blocking page.
460 (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, 482 (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
461 now, clock_state, std::move(ssl_cert_reporter_), 483 now, clock_state, std::move(ssl_cert_reporter_),
462 callback_)) 484 callback_))
463 ->Show(); 485 ->Show();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 request_url_(request_url), 578 request_url_(request_url),
557 callback_(callback), 579 callback_(callback),
558 weak_ptr_factory_(this) {} 580 weak_ptr_factory_(this) {}
559 581
560 SSLErrorHandler::~SSLErrorHandler() { 582 SSLErrorHandler::~SSLErrorHandler() {
561 } 583 }
562 584
563 void SSLErrorHandler::StartHandlingError() { 585 void SSLErrorHandler::StartHandlingError() {
564 RecordUMA(HANDLE_ALL); 586 RecordUMA(HANDLE_ALL);
565 587
566 RecordSuperfishUMA(ssl_info_.public_key_hashes); 588 RecordSuperfishUMA(ssl_info_.cert);
567 589
568 if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) == 590 if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) ==
569 ssl_errors::ErrorInfo::CERT_DATE_INVALID) { 591 ssl_errors::ErrorInfo::CERT_DATE_INVALID) {
570 HandleCertDateInvalidError(); 592 HandleCertDateInvalidError();
571 return; 593 return;
572 } 594 }
573 595
574 const net::CertStatus non_name_mismatch_errors = 596 const net::CertStatus non_name_mismatch_errors =
575 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID; 597 ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID;
576 const bool only_error_is_name_mismatch = 598 const bool only_error_is_name_mismatch =
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 network_time::NetworkTimeTracker* tracker = 817 network_time::NetworkTimeTracker* tracker =
796 g_config.Pointer()->network_time_tracker(); 818 g_config.Pointer()->network_time_tracker();
797 ssl_errors::ClockState clock_state = ssl_errors::GetClockState(now, tracker); 819 ssl_errors::ClockState clock_state = ssl_errors::GetClockState(now, tracker);
798 if (clock_state == ssl_errors::CLOCK_STATE_FUTURE || 820 if (clock_state == ssl_errors::CLOCK_STATE_FUTURE ||
799 clock_state == ssl_errors::CLOCK_STATE_PAST) { 821 clock_state == ssl_errors::CLOCK_STATE_PAST) {
800 ShowBadClockInterstitial(now, clock_state); 822 ShowBadClockInterstitial(now, clock_state);
801 return; // |this| is deleted after showing the interstitial. 823 return; // |this| is deleted after showing the interstitial.
802 } 824 }
803 ShowSSLInterstitial(); 825 ShowSSLInterstitial();
804 } 826 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698