1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
#define CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
#include <string>
#include <vector>
#include "base/time/time.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "net/cert/x509_certificate.h"
#include "url/gurl.h"
namespace content {
class WebContents;
}
// This class classifies characteristics of SSL errors, including information
// about captive portal detection.
//
// This class should only be used on the UI thread because its
// implementation uses captive_portal::CaptivePortalService which can only be
// accessed on the UI thread.
class SSLErrorClassification : public content::NotificationObserver {
public:
SSLErrorClassification(content::WebContents* web_contents,
const base::Time& current_time,
const GURL& url,
int cert_error,
const net::X509Certificate& cert);
~SSLErrorClassification() override;
// Returns true if the system time is in the past.
static bool IsUserClockInThePast(const base::Time& time_now);
// Returns true if the system time is too far in the future or the user is
// using a version of Chrome which is more than 1 year old.
static bool IsUserClockInTheFuture(const base::Time& time_now);
// Returns true if the Windows platform is likely to not have SHA-256 support.
// On other platforms, returns false always.
static bool MaybeWindowsLacksSHA256Support();
// Returns true if any one of the following conditions hold:
// 1.|hostname| is an IP Address in an IANA-reserved range.
// 2.|hostname| is a not-yet-assigned by ICANN gTLD.
// 3.|hostname| is a dotless domain.
static bool IsHostnameNonUniqueOrDotless(const std::string& hostname);
// A function which calculates the severity score when the ssl error is
// |CERT_DATE_INVALID|. The calculated score is between 0.0 and 1.0, higher
// being more severe, indicating how severe the certificate's
// date invalid error is.
void InvalidDateSeverityScore();
// A function which calculates the severity score when the ssl error is
// |CERT_COMMON_NAME_INVALID|. The calculated score is between 0.0 and 1.0,
// higher being more severe, indicating how severe the certificate's common
// name invalid error is.
void InvalidCommonNameSeverityScore();
// A function which calculates the severity score when the ssl error is
// |CERT_AUTHORITY_INVALID|, returns a score between 0.0 and 1.0, higher
// values being more severe, indicating how severe the certificate's
// authority invalid error is.
void InvalidAuthoritySeverityScore();
void RecordUMAStatistics(bool overridable) const;
void RecordCaptivePortalUMAStatistics(bool overridable) const;
base::TimeDelta TimePassedSinceExpiry() const;
private:
FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest, TestDateInvalidScore);
FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest, TestNameMismatch);
FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest,
TestHostNameHasKnownTLD);
typedef std::vector<std::string> Tokens;
// Returns true if the hostname has a known Top Level Domain.
static bool IsHostNameKnownTLD(const std::string& host_name);
// Returns true if the site's hostname differs from one of the DNS
// names in the certificate (CN or SANs) only by the presence or
// absence of the single-label prefix "www". E.g.:
//
// www.example.com ~ example.com -> true
// example.com ~ www.example.com -> true
// www.food.example.com ~ example.com -> false
// mail.example.com ~ example.com -> false
bool IsWWWSubDomainMatch() const;
// Returns true if |child| is a subdomain of any of the |potential_parents|.
bool NameUnderAnyNames(const Tokens& child,
const std::vector<Tokens>& potential_parents) const;
// Returns true if any of the |potential_children| is a subdomain of the
// |parent|. The inverse case should be treated carefully as this is most
// likely a MITM attack. We don't want foo.appspot.com to be able to MITM for
// appspot.com.
bool AnyNamesUnderName(const std::vector<Tokens>& potential_children,
const Tokens& parent) const;
// Returns true if |hostname| is too broad for the scope of a wildcard
// certificate. E.g.:
//
// a.b.example.com ~ *.example.com --> true
// b.example.com ~ *.example.com --> false
bool IsSubDomainOutsideWildcard(const Tokens& hostname) const;
// Returns true if the certificate is a shared certificate. Note - This
// function should be used with caution (only for UMA histogram) as an
// attacker could easily get a certificate with more than 5 names in the SAN
// fields.
bool IsCertLikelyFromMultiTenantHosting() const;
static std::vector<Tokens> GetTokenizedDNSNames(
const std::vector<std::string>& dns_names);
// If |potential_subdomain| is a subdomain of |parent|, returns the
// number of DNS labels by which |potential_subdomain| is under
// |parent|. Otherwise, returns 0.
//
// For example,
//
// FindSubDomainDifference(Tokenize("a.b.example.com"),
// Tokenize("example.com"))
// --> 2.
size_t FindSubDomainDifference(const Tokens& potential_subdomain,
const Tokens& parent) const;
static Tokens Tokenize(const std::string& name);
float CalculateScoreTimePassedSinceExpiry() const;
float CalculateScoreEnvironments() const;
// content::NotificationObserver:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
content::WebContents* web_contents_;
// This stores the current time.
base::Time current_time_;
const GURL request_url_;
int cert_error_;
// This stores the certificate.
const net::X509Certificate& cert_;
// Is captive portal detection enabled?
bool captive_portal_detection_enabled_;
// Did the probe complete before the interstitial was closed?
bool captive_portal_probe_completed_;
// Did the captive portal probe receive an error or get a non-HTTP response?
bool captive_portal_no_response_;
// Was a captive portal detected?
bool captive_portal_detected_;
content::NotificationRegistrar registrar_;
};
#endif // CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
|