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