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

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

Issue 400323002: Refactor the captive portal code to move from the ssl_blocking_page class to the ssl_error_classific (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase-Update Created 6 years, 4 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 <vector> 5 #include <vector>
6 6
7 #include "chrome/browser/ssl/ssl_error_classification.h" 7 #include "chrome/browser/ssl/ssl_error_classification.h"
8 8
9 #include "base/build_time.h" 9 #include "base/build_time.h"
10 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ssl/ssl_error_info.h" 18 #include "chrome/browser/ssl/ssl_error_info.h"
19 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/web_contents.h"
16 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
17 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 22 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
18 #include "net/cert/x509_cert_types.h" 23 #include "net/cert/x509_cert_types.h"
19 #include "net/cert/x509_certificate.h" 24 #include "net/cert/x509_certificate.h"
20 #include "url/gurl.h" 25 #include "url/gurl.h"
21 26
22 using base::Time; 27 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
23 using base::TimeTicks; 28 #include "chrome/browser/captive_portal/captive_portal_service.h"
24 using base::TimeDelta; 29 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
30 #endif
25 31
26 #if defined(OS_WIN) 32 #if defined(OS_WIN)
27 #include "base/win/windows_version.h" 33 #include "base/win/windows_version.h"
28 #endif 34 #endif
29 35
36 using base::Time;
37 using base::TimeTicks;
38 using base::TimeDelta;
39
30 namespace { 40 namespace {
31 41
32 // Events for UMA. Do not reorder or change! 42 // Events for UMA. Do not reorder or change!
33 enum SSLInterstitialCause { 43 enum SSLInterstitialCause {
34 CLOCK_PAST, 44 CLOCK_PAST,
35 CLOCK_FUTURE, 45 CLOCK_FUTURE,
36 WWW_SUBDOMAIN_MATCH, 46 WWW_SUBDOMAIN_MATCH,
37 SUBDOMAIN_MATCH, 47 SUBDOMAIN_MATCH,
38 SUBDOMAIN_INVERSE_MATCH, 48 SUBDOMAIN_INVERSE_MATCH,
39 SUBDOMAIN_OUTSIDE_WILDCARD, 49 SUBDOMAIN_OUTSIDE_WILDCARD,
40 HOST_NAME_NOT_KNOWN_TLD, 50 HOST_NAME_NOT_KNOWN_TLD,
51 LIKELY_MULTI_TENANT_HOSTING,
41 UNUSED_INTERSTITIAL_CAUSE_ENTRY, 52 UNUSED_INTERSTITIAL_CAUSE_ENTRY,
42 }; 53 };
43 54
55 // Events for UMA. Do not reorder or change!
56 enum SSLInterstitialCauseCaptivePortal {
57 CAPTIVE_PORTAL_DETECTION_ENABLED,
58 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
59 CAPTIVE_PORTAL_PROBE_COMPLETED,
60 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
61 CAPTIVE_PORTAL_NO_RESPONSE,
62 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
63 CAPTIVE_PORTAL_DETECTED,
64 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
65 UNUSED_CAPTIVE_PORTAL_EVENT,
66 };
67
44 // Scores/weights which will be constant through all the SSL error types. 68 // Scores/weights which will be constant through all the SSL error types.
45 static const float kServerWeight = 0.5f; 69 static const float kServerWeight = 0.5f;
46 static const float kClientWeight = 0.5f; 70 static const float kClientWeight = 0.5f;
47 71
48 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { 72 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
49 if (overridable) { 73 if (overridable) {
50 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, 74 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
51 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 75 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
52 } else { 76 } else {
53 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, 77 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event,
54 UNUSED_INTERSTITIAL_CAUSE_ENTRY); 78 UNUSED_INTERSTITIAL_CAUSE_ENTRY);
55 } 79 }
56 } 80 }
57 81
82 void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
83 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal",
84 event,
85 UNUSED_CAPTIVE_PORTAL_EVENT);
86 }
87
88 int GetLevensteinDistance(const std::string& str1,
89 const std::string& str2) {
90 if (str1 == str2)
91 return 0;
92 if (str1.size() == 0)
93 return str2.size();
94 if (str2.size() == 0)
95 return str1.size();
96 std::vector<int> kFirstRow(str2.size() + 1, 0);
97 std::vector<int> kSecondRow(str2.size() + 1, 0);
98
99 for (size_t i = 0; i < kFirstRow.size(); ++i)
100 kFirstRow[i] = i;
101 for (size_t i = 0; i < str1.size(); ++i) {
102 kSecondRow[0] = i + 1;
103 for (size_t j = 0; j < str2.size(); ++j) {
104 int cost = str1[i] == str2[j] ? 0 : 1;
105 kSecondRow[j+1] = std::min(std::min(
106 kSecondRow[j] + 1, kFirstRow[j + 1] + 1), kFirstRow[j] + cost);
107 }
108 for (size_t j = 0; j < kFirstRow.size(); j++)
109 kFirstRow[j] = kSecondRow[j];
110 }
111 return kSecondRow[str2.size()];
112 }
113
58 } // namespace 114 } // namespace
59 115
60 SSLErrorClassification::SSLErrorClassification( 116 SSLErrorClassification::SSLErrorClassification(
117 content::WebContents* web_contents,
61 const base::Time& current_time, 118 const base::Time& current_time,
62 const GURL& url, 119 const GURL& url,
120 int cert_error,
63 const net::X509Certificate& cert) 121 const net::X509Certificate& cert)
64 : current_time_(current_time), 122 : web_contents_(web_contents),
123 current_time_(current_time),
65 request_url_(url), 124 request_url_(url),
66 cert_(cert) { } 125 cert_error_(cert_error),
126 cert_(cert),
127 captive_portal_detection_enabled_(false),
128 captive_portal_probe_completed_(false),
129 captive_portal_no_response_(false),
130 captive_portal_detected_(false) {
131 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
132 Profile* profile = Profile::FromBrowserContext(
133 web_contents_->GetBrowserContext());
134 CaptivePortalService* captive_portal_service =
135 CaptivePortalServiceFactory::GetForProfile(profile);
136 captive_portal_detection_enabled_ = captive_portal_service->enabled();
137 captive_portal_service->DetectCaptivePortal();
138 registrar_.Add(this,
139 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
140 content::Source<Profile>(profile));
141 #endif
142 }
67 143
68 SSLErrorClassification::~SSLErrorClassification() { } 144 SSLErrorClassification::~SSLErrorClassification() { }
69 145
70 float SSLErrorClassification::InvalidDateSeverityScore( 146 void SSLErrorClassification::RecordCaptivePortalUMAStatistics(
71 int cert_error) const { 147 bool overridable) const {
148 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
149 if (captive_portal_detection_enabled_)
150 RecordCaptivePortalEventStats(
151 overridable ?
152 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
153 CAPTIVE_PORTAL_DETECTION_ENABLED);
154 if (captive_portal_probe_completed_)
155 RecordCaptivePortalEventStats(
156 overridable ?
157 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
158 CAPTIVE_PORTAL_PROBE_COMPLETED);
159 // Log only one of portal detected and no response results.
160 if (captive_portal_detected_)
161 RecordCaptivePortalEventStats(
162 overridable ?
163 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
164 CAPTIVE_PORTAL_DETECTED);
165 else if (captive_portal_no_response_)
166 RecordCaptivePortalEventStats(
167 overridable ?
168 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
169 CAPTIVE_PORTAL_NO_RESPONSE);
170 #endif
171 }
172
173 void SSLErrorClassification::InvalidDateSeverityScore() {
72 SSLErrorInfo::ErrorType type = 174 SSLErrorInfo::ErrorType type =
73 SSLErrorInfo::NetErrorToErrorType(cert_error); 175 SSLErrorInfo::NetErrorToErrorType(cert_error_);
74 DCHECK(type == SSLErrorInfo::CERT_DATE_INVALID); 176 DCHECK(type == SSLErrorInfo::CERT_DATE_INVALID);
177
75 // Client-side characteristics. Check whether or not the system's clock is 178 // Client-side characteristics. Check whether or not the system's clock is
76 // wrong and whether or not the user has already encountered this error 179 // wrong and whether or not the user has encountered this error before.
77 // before.
78 float severity_date_score = 0.0f; 180 float severity_date_score = 0.0f;
79 181
80 static const float kCertificateExpiredWeight = 0.3f; 182 static const float kCertificateExpiredWeight = 0.3f;
81 static const float kNotYetValidWeight = 0.2f; 183 static const float kNotYetValidWeight = 0.2f;
82 184
83 static const float kSystemClockWeight = 0.75f; 185 static const float kSystemClockWeight = 0.75f;
84 static const float kSystemClockWrongWeight = 0.1f; 186 static const float kSystemClockWrongWeight = 0.1f;
85 static const float kSystemClockRightWeight = 1.0f; 187 static const float kSystemClockRightWeight = 1.0f;
86 188
87 if (IsUserClockInThePast(current_time_) || 189 if (IsUserClockInThePast(current_time_) ||
88 IsUserClockInTheFuture(current_time_)) { 190 IsUserClockInTheFuture(current_time_)) {
89 severity_date_score += kClientWeight * kSystemClockWeight * 191 severity_date_score += kClientWeight * kSystemClockWeight *
90 kSystemClockWrongWeight; 192 kSystemClockWrongWeight;
91 } else { 193 } else {
92 severity_date_score += kClientWeight * kSystemClockWeight * 194 severity_date_score += kClientWeight * kSystemClockWeight *
93 kSystemClockRightWeight; 195 kSystemClockRightWeight;
94 } 196 }
95 // TODO(radhikabhar): (crbug.com/393262) Check website settings. 197 // TODO(radhikabhar): (crbug.com/393262) Check website settings.
96 198
97 // Server-side characteristics. Check whether the certificate has expired or 199 // Server-side characteristics. Check whether the certificate has expired or
98 // is not yet valid. If the certificate has expired then factor the time which 200 // is not yet valid. If the certificate has expired then factor the time which
99 // has passed since expiry. 201 // has passed since expiry.
100 if (cert_.HasExpired()) { 202 if (cert_.HasExpired()) {
101 severity_date_score += kServerWeight * kCertificateExpiredWeight * 203 severity_date_score += kServerWeight * kCertificateExpiredWeight *
102 CalculateScoreTimePassedSinceExpiry(); 204 CalculateScoreTimePassedSinceExpiry();
103 } 205 }
104 if (current_time_ < cert_.valid_start()) 206 if (current_time_ < cert_.valid_start())
105 severity_date_score += kServerWeight * kNotYetValidWeight; 207 severity_date_score += kServerWeight * kNotYetValidWeight;
106 return severity_date_score; 208 // TODO(radhikabhar): Record the severity score in a histogram. This will be
209 // in the next CL - just called the function in ssl_blocking_page.cc.
107 } 210 }
108 211
109 float SSLErrorClassification::InvalidCommonNameSeverityScore( 212 void SSLErrorClassification::InvalidCommonNameSeverityScore() {
110 int cert_error) const {
111 SSLErrorInfo::ErrorType type = 213 SSLErrorInfo::ErrorType type =
112 SSLErrorInfo::NetErrorToErrorType(cert_error); 214 SSLErrorInfo::NetErrorToErrorType(cert_error_);
113 DCHECK(type == SSLErrorInfo::CERT_COMMON_NAME_INVALID); 215 DCHECK(type == SSLErrorInfo::CERT_COMMON_NAME_INVALID);
114 float severity_name_score = 0.0f; 216 float severity_name_score = 0.0f;
115 217
116 static const float kWWWDifferenceWeight = 0.3f; 218 static const float kWWWDifferenceWeight = 0.3f;
117 static const float kSubDomainWeight = 0.2f; 219 static const float kNameUnderAnyNamesWeight = 0.2f;
118 static const float kSubDomainInverseWeight = 1.0f; 220 static const float kAnyNamesUnderNamesWeight = 1.0f;
221 static const float kLikelyMultiTenantHostingWeight = 0.1f;
119 222
120 std::string host_name = request_url_.host(); 223 std::string host_name = request_url_.host();
121 if (IsHostNameKnownTLD(host_name)) { 224 if (IsHostNameKnownTLD(host_name)) {
122 Tokens host_name_tokens = Tokenize(host_name); 225 Tokens host_name_tokens = Tokenize(host_name);
123 if (IsWWWSubDomainMatch()) 226 if (IsWWWSubDomainMatch())
124 severity_name_score += kServerWeight * kWWWDifferenceWeight; 227 severity_name_score += kServerWeight * kWWWDifferenceWeight;
125 if (IsSubDomainOutsideWildcard(host_name_tokens)) 228 if (IsSubDomainOutsideWildcard(host_name_tokens))
126 severity_name_score += kServerWeight * kWWWDifferenceWeight; 229 severity_name_score += kServerWeight * kWWWDifferenceWeight;
127 230
128 std::vector<std::string> dns_names; 231 std::vector<std::string> dns_names;
129 cert_.GetDNSNames(&dns_names); 232 cert_.GetDNSNames(&dns_names);
130 std::vector<Tokens> dns_name_tokens = GetTokenizedDNSNames(dns_names); 233 std::vector<Tokens> dns_name_tokens = GetTokenizedDNSNames(dns_names);
131 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens)) 234 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens))
132 severity_name_score += kServerWeight * kSubDomainWeight; 235 severity_name_score += kServerWeight * kNameUnderAnyNamesWeight;
133 // Inverse case is more likely to be a MITM attack. 236 // Inverse case is more likely to be a MITM attack.
134 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens)) 237 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens))
135 severity_name_score += kServerWeight * kSubDomainInverseWeight; 238 severity_name_score += kServerWeight * kAnyNamesUnderNamesWeight;
239 if (IsCertLikelyFromMultiTenantHosting())
240 severity_name_score += kServerWeight * kLikelyMultiTenantHostingWeight;
136 } 241 }
137 return severity_name_score; 242
243 static const float kEnvironmentWeight = 0.25f;
244
245 severity_name_score += kClientWeight * kEnvironmentWeight *
246 CalculateScoreEnvironments();
247 // TODO(radhikabhar): Record the severity score in a histogram. Same as above
248 // - this will be in the next CL. So just called the function in the
249 // ssl_blocking_page.cc.
138 } 250 }
139 251
140 void SSLErrorClassification::RecordUMAStatistics(bool overridable, 252 void SSLErrorClassification::RecordUMAStatistics(
141 int cert_error) { 253 bool overridable) const {
142 SSLErrorInfo::ErrorType type = 254 SSLErrorInfo::ErrorType type =
143 SSLErrorInfo::NetErrorToErrorType(cert_error); 255 SSLErrorInfo::NetErrorToErrorType(cert_error_);
144 switch (type) { 256 switch (type) {
145 case SSLErrorInfo::CERT_DATE_INVALID: { 257 case SSLErrorInfo::CERT_DATE_INVALID: {
146 if (IsUserClockInThePast(base::Time::NowFromSystemTime())) 258 if (IsUserClockInThePast(base::Time::NowFromSystemTime()))
147 RecordSSLInterstitialCause(overridable, CLOCK_PAST); 259 RecordSSLInterstitialCause(overridable, CLOCK_PAST);
148 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) 260 if (IsUserClockInTheFuture(base::Time::NowFromSystemTime()))
149 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); 261 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE);
150 break; 262 break;
151 } 263 }
152 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: { 264 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: {
153 std::string host_name = request_url_.host(); 265 std::string host_name = request_url_.host();
154 if (IsHostNameKnownTLD(host_name)) { 266 if (IsHostNameKnownTLD(host_name)) {
155 Tokens host_name_tokens = Tokenize(host_name); 267 Tokens host_name_tokens = Tokenize(host_name);
156 if (IsWWWSubDomainMatch()) 268 if (IsWWWSubDomainMatch())
157 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); 269 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH);
158 if (IsSubDomainOutsideWildcard(host_name_tokens)) 270 if (IsSubDomainOutsideWildcard(host_name_tokens))
159 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD); 271 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD);
160 std::vector<std::string> dns_names; 272 std::vector<std::string> dns_names;
161 cert_.GetDNSNames(&dns_names); 273 cert_.GetDNSNames(&dns_names);
162 std::vector<Tokens> dns_name_tokens = GetTokenizedDNSNames(dns_names); 274 std::vector<Tokens> dns_name_tokens = GetTokenizedDNSNames(dns_names);
163 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens)) 275 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens))
164 RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH); 276 RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH);
165 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens)) 277 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens))
166 RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH); 278 RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH);
279 if (IsCertLikelyFromMultiTenantHosting())
280 RecordSSLInterstitialCause(overridable, LIKELY_MULTI_TENANT_HOSTING);
167 } else { 281 } else {
168 RecordSSLInterstitialCause(overridable, HOST_NAME_NOT_KNOWN_TLD); 282 RecordSSLInterstitialCause(overridable, HOST_NAME_NOT_KNOWN_TLD);
169 } 283 }
170 break; 284 break;
171 } 285 }
172 default: { 286 default: {
173 break; 287 break;
174 } 288 }
175 } 289 }
176 } 290 }
(...skipping 12 matching lines...) Expand all
189 static const float kMediumThresholdWeight = 0.3f; 303 static const float kMediumThresholdWeight = 0.3f;
190 static const float kLowThresholdWeight = 0.2f; 304 static const float kLowThresholdWeight = 0.2f;
191 if (time_passed >= kHighThreshold) 305 if (time_passed >= kHighThreshold)
192 return kHighThresholdWeight; 306 return kHighThresholdWeight;
193 else if (time_passed >= kLowThreshold) 307 else if (time_passed >= kLowThreshold)
194 return kMediumThresholdWeight; 308 return kMediumThresholdWeight;
195 else 309 else
196 return kLowThresholdWeight; 310 return kLowThresholdWeight;
197 } 311 }
198 312
313 float SSLErrorClassification::CalculateScoreEnvironments() const {
314 static const float kWifiWeight = 0.7f;
315 static const float kCellularWeight = 0.7f;
316 static const float kHotspotWeight = 0.2f;
317 static const float kEthernetWeight = 0.7f;
318 static const float kOtherWeight = 0.7f;
319 net::NetworkChangeNotifier::ConnectionType type =
320 net::NetworkChangeNotifier::GetConnectionType();
321 if (type == net::NetworkChangeNotifier::CONNECTION_WIFI)
322 return kWifiWeight;
323 if (type == net::NetworkChangeNotifier::CONNECTION_2G ||
324 type == net::NetworkChangeNotifier::CONNECTION_3G ||
325 type == net::NetworkChangeNotifier::CONNECTION_4G ) {
326 return kCellularWeight;
327 }
328 if (type == net::NetworkChangeNotifier::CONNECTION_ETHERNET)
329 return kEthernetWeight;
330 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
331 // Assume if captive portals are detected then the user is connected using a
332 // hot spot.
333 if (captive_portal_probe_completed_ && captive_portal_detected_)
334 return kHotspotWeight;
335 #endif
336 return kOtherWeight;
337 }
338
199 bool SSLErrorClassification::IsUserClockInThePast(const base::Time& time_now) { 339 bool SSLErrorClassification::IsUserClockInThePast(const base::Time& time_now) {
200 base::Time build_time = base::GetBuildTime(); 340 base::Time build_time = base::GetBuildTime();
201 if (time_now < build_time - base::TimeDelta::FromDays(2)) 341 if (time_now < build_time - base::TimeDelta::FromDays(2))
202 return true; 342 return true;
203 return false; 343 return false;
204 } 344 }
205 345
206 bool SSLErrorClassification::IsUserClockInTheFuture( 346 bool SSLErrorClassification::IsUserClockInTheFuture(
207 const base::Time& time_now) { 347 const base::Time& time_now) {
208 base::Time build_time = base::GetBuildTime(); 348 base::Time build_time = base::GetBuildTime();
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 499
360 // Move past the "*.". 500 // Move past the "*.".
361 std::string extracted_dns_name = name.substr(2); 501 std::string extracted_dns_name = name.substr(2);
362 if (FindSubDomainDifference( 502 if (FindSubDomainDifference(
363 host_name_tokens, Tokenize(extracted_dns_name)) == 2) { 503 host_name_tokens, Tokenize(extracted_dns_name)) == 2) {
364 return true; 504 return true;
365 } 505 }
366 } 506 }
367 return result; 507 return result;
368 } 508 }
509
510 bool SSLErrorClassification::IsCertLikelyFromMultiTenantHosting() const {
511 std::string host_name = request_url_.host();
512 std::vector<std::string> dns_names;
513 std::vector<std::string> dns_names_domain;
514 cert_.GetDNSNames(&dns_names);
515 size_t dns_names_size = dns_names.size();
516
517 // If there is only 1 DNS name then it is definitely not a shared certificate.
518 if (dns_names_size == 0 || dns_names_size == 1)
519 return false;
520
521 // Check to see if all the domains in the SAN field in the SSL certificate are
522 // the same or not.
523 for (size_t i = 0; i < dns_names_size; ++i) {
524 dns_names_domain.push_back(
525 net::registry_controlled_domains::
526 GetDomainAndRegistry(
527 dns_names[i],
528 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
529 }
530 for (size_t i = 1; i < dns_names_domain.size(); ++i) {
531 if (dns_names_domain[i] != dns_names_domain[0])
532 return false;
533 }
534
535 // If the number of DNS names is more than 5 then assume that it is a shared
536 // certificate.
537 static const int kDistinctNameThreshold = 5;
538 if (dns_names_size > kDistinctNameThreshold)
539 return true;
540
541 // Heuristic - The edit distance between all the strings should be at least 5
542 // for it to be counted as a shared SSLCertificate. If even one pair of
543 // strings edit distance is below 5 then the certificate is no longer
544 // considered as a shared certificate. Include the host name in the URL also
545 // while comparing.
546 dns_names.push_back(host_name);
547 static const int kMinimumEditDsitance = 5;
548 for (size_t i = 0; i < dns_names_size; ++i) {
549 for (size_t j = i + 1; j < dns_names_size; ++j) {
550 int edit_distance = GetLevensteinDistance(dns_names[i], dns_names[j]);
551 if (edit_distance < kMinimumEditDsitance)
552 return false;
553 }
554 }
555 return true;
556 }
557
558
559 void SSLErrorClassification::Observe(
560 int type,
561 const content::NotificationSource& source,
562 const content::NotificationDetails& details) {
563 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
564 // When detection is disabled, captive portal service always sends
565 // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
566 if (!captive_portal_detection_enabled_)
567 return;
568 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
569 captive_portal_probe_completed_ = true;
570 CaptivePortalService::Results* results =
571 content::Details<CaptivePortalService::Results>(
572 details).ptr();
573 // If a captive portal was detected at any point when the interstitial was
574 // displayed, assume that the interstitial was caused by a captive portal.
575 // Example scenario:
576 // 1- Interstitial displayed and captive portal detected, setting the flag.
577 // 2- Captive portal detection automatically opens portal login page.
578 // 3- User logs in on the portal login page.
579 // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
580 // sure we don't clear the captive protal flag, since the interstitial was
581 // potentially caused by the captive portal.
582 captive_portal_detected_ = captive_portal_detected_ ||
583 (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
584 // Also keep track of non-HTTP portals and error cases.
585 captive_portal_no_response_ = captive_portal_no_response_ ||
586 (results->result == captive_portal::RESULT_NO_RESPONSE);
587 }
588 #endif
589 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698