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

Side by Side Diff: components/ssl_errors/error_classification.cc

Issue 2777383002: Update SSL error handling code to account for Subject CN deprecation (Closed)
Patch Set: Update build script Created 3 years, 8 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/ssl_errors/error_classification.h" 5 #include "components/ssl_errors/error_classification.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <vector> 10 #include <vector>
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 return -1; 97 return -1;
98 98
99 int diff_size = static_cast<int>(potential_subdomain.size() - parent.size()); 99 int diff_size = static_cast<int>(potential_subdomain.size() - parent.size());
100 for (size_t i = 0; i < parent.size(); i++) { 100 for (size_t i = 0; i < parent.size(); i++) {
101 if (parent[i] != potential_subdomain[i + diff_size]) 101 if (parent[i] != potential_subdomain[i + diff_size])
102 return -1; 102 return -1;
103 } 103 }
104 return diff_size; 104 return diff_size;
105 } 105 }
106 106
107 // We accept the inverse case for www for historical reasons.
108 bool IsWWWSubDomainMatch(const GURL& request_url,
109 const net::X509Certificate& cert) {
110 std::string www_host;
111 std::vector<std::string> dns_names;
112 cert.GetDNSNames(&dns_names);
113 return GetWWWSubDomainMatch(request_url, dns_names, &www_host);
114 }
115
116 // The time to use when doing build time operations in browser tests. 107 // The time to use when doing build time operations in browser tests.
117 base::LazyInstance<base::Time>::DestructorAtExit g_testing_build_time = 108 base::LazyInstance<base::Time>::DestructorAtExit g_testing_build_time =
118 LAZY_INSTANCE_INITIALIZER; 109 LAZY_INSTANCE_INITIALIZER;
119 110
120 } // namespace 111 } // namespace
121 112
122 static ssl_errors::ErrorInfo::ErrorType RecordErrorType(int cert_error) { 113 static ssl_errors::ErrorInfo::ErrorType RecordErrorType(int cert_error) {
123 ssl_errors::ErrorInfo::ErrorType error_type = 114 ssl_errors::ErrorInfo::ErrorType error_type =
124 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); 115 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error);
125 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", error_type, 116 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", error_type,
(...skipping 23 matching lines...) Expand all
149 } 140 }
150 case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: { 141 case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: {
151 std::string host_name = request_url.host(); 142 std::string host_name = request_url.host();
152 if (HostNameHasKnownTLD(host_name)) { 143 if (HostNameHasKnownTLD(host_name)) {
153 HostnameTokens host_name_tokens = Tokenize(host_name); 144 HostnameTokens host_name_tokens = Tokenize(host_name);
154 if (IsWWWSubDomainMatch(request_url, cert)) 145 if (IsWWWSubDomainMatch(request_url, cert))
155 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); 146 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH);
156 if (IsSubDomainOutsideWildcard(request_url, cert)) 147 if (IsSubDomainOutsideWildcard(request_url, cert))
157 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD); 148 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD);
158 std::vector<std::string> dns_names; 149 std::vector<std::string> dns_names;
159 cert.GetDNSNames(&dns_names); 150 cert.GetSubjectAltName(&dns_names, NULL);
Ryan Sleevi 2017/03/31 14:51:33 nit: nullptr
elawrence 2017/03/31 16:09:41 Done.
160 std::vector<HostnameTokens> dns_name_tokens = 151 std::vector<HostnameTokens> dns_name_tokens =
161 GetTokenizedDNSNames(dns_names); 152 GetTokenizedDNSNames(dns_names);
162 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens)) 153 if (NameUnderAnyNames(host_name_tokens, dns_name_tokens))
163 RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH); 154 RecordSSLInterstitialCause(overridable, SUBDOMAIN_MATCH);
164 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens)) 155 if (AnyNamesUnderName(dns_name_tokens, host_name_tokens))
165 RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH); 156 RecordSSLInterstitialCause(overridable, SUBDOMAIN_INVERSE_MATCH);
166 if (IsCertLikelyFromMultiTenantHosting(request_url, cert)) 157 if (IsCertLikelyFromMultiTenantHosting(request_url, cert))
167 RecordSSLInterstitialCause(overridable, LIKELY_MULTI_TENANT_HOSTING); 158 RecordSSLInterstitialCause(overridable, LIKELY_MULTI_TENANT_HOSTING);
168 if (IsCertLikelyFromSameDomain(request_url, cert)) 159 if (IsCertLikelyFromSameDomain(request_url, cert))
169 RecordSSLInterstitialCause(overridable, LIKELY_SAME_DOMAIN); 160 RecordSSLInterstitialCause(overridable, LIKELY_SAME_DOMAIN);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 return net::registry_controlled_domains::HostHasRegistryControlledDomain( 274 return net::registry_controlled_domains::HostHasRegistryControlledDomain(
284 host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 275 host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
285 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); 276 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
286 } 277 }
287 278
288 HostnameTokens Tokenize(const std::string& name) { 279 HostnameTokens Tokenize(const std::string& name) {
289 return base::SplitString(name, ".", base::KEEP_WHITESPACE, 280 return base::SplitString(name, ".", base::KEEP_WHITESPACE,
290 base::SPLIT_WANT_ALL); 281 base::SPLIT_WANT_ALL);
291 } 282 }
292 283
284 // We accept the inverse case for www for historical reasons.
285 bool IsWWWSubDomainMatch(const GURL& request_url,
286 const net::X509Certificate& cert) {
287 std::string www_host;
288 std::vector<std::string> dns_names;
289 cert.GetSubjectAltName(&dns_names, NULL);
Ryan Sleevi 2017/03/31 14:51:33 nit: nullptr
elawrence 2017/03/31 16:09:41 Done.
290 return GetWWWSubDomainMatch(request_url, dns_names, &www_host);
291 }
292
293 bool GetWWWSubDomainMatch(const GURL& request_url, 293 bool GetWWWSubDomainMatch(const GURL& request_url,
294 const std::vector<std::string>& dns_names, 294 const std::vector<std::string>& dns_names,
295 std::string* www_match_host_name) { 295 std::string* www_match_host_name) {
296 const std::string& host_name = request_url.host(); 296 const std::string& host_name = request_url.host();
297 297
298 if (HostNameHasKnownTLD(host_name)) { 298 if (HostNameHasKnownTLD(host_name)) {
299 // Need to account for all possible domains given in the SSL certificate. 299 // Need to account for all possible domains given in the SSL certificate.
300 for (const auto& dns_name : dns_names) { 300 for (const auto& dns_name : dns_names) {
301 if (dns_name.empty() || dns_name.find('\0') != std::string::npos || 301 if (dns_name.empty() || dns_name.find('\0') != std::string::npos ||
302 dns_name.length() == host_name.length() || 302 dns_name.length() == host_name.length() ||
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 376 }
377 } 377 }
378 return row[str2.size()]; 378 return row[str2.size()];
379 } 379 }
380 380
381 bool IsSubDomainOutsideWildcard(const GURL& request_url, 381 bool IsSubDomainOutsideWildcard(const GURL& request_url,
382 const net::X509Certificate& cert) { 382 const net::X509Certificate& cert) {
383 std::string host_name = request_url.host(); 383 std::string host_name = request_url.host();
384 HostnameTokens host_name_tokens = Tokenize(host_name); 384 HostnameTokens host_name_tokens = Tokenize(host_name);
385 std::vector<std::string> dns_names; 385 std::vector<std::string> dns_names;
386 cert.GetDNSNames(&dns_names); 386 cert.GetSubjectAltName(&dns_names, NULL);
Ryan Sleevi 2017/03/31 14:51:33 nit: nullptr
elawrence 2017/03/31 16:09:41 Done.
387 bool result = false; 387 bool result = false;
388 388
389 // This method requires that the host name be longer than the dns name on 389 // This method requires that the host name be longer than the dns name on
390 // the certificate. 390 // the certificate.
391 for (const auto& dns_name : dns_names) { 391 for (const auto& dns_name : dns_names) {
392 if (dns_name.length() < 2 || dns_name.length() >= host_name.length() || 392 if (dns_name.length() < 2 || dns_name.length() >= host_name.length() ||
393 dns_name.find('\0') != std::string::npos || 393 dns_name.find('\0') != std::string::npos ||
394 !HostNameHasKnownTLD(dns_name) || dns_name[0] != '*' || 394 !HostNameHasKnownTLD(dns_name) || dns_name[0] != '*' ||
395 dns_name[1] != '.') { 395 dns_name[1] != '.') {
396 continue; 396 continue;
397 } 397 }
398 398
399 // Move past the "*.". 399 // Move past the "*.".
400 std::string extracted_dns_name = dns_name.substr(2); 400 std::string extracted_dns_name = dns_name.substr(2);
401 if (FindSubdomainDifference(host_name_tokens, 401 if (FindSubdomainDifference(host_name_tokens,
402 Tokenize(extracted_dns_name)) == 2) { 402 Tokenize(extracted_dns_name)) == 2) {
403 return true; 403 return true;
404 } 404 }
405 } 405 }
406 return result; 406 return result;
407 } 407 }
408 408
409 bool IsCertLikelyFromMultiTenantHosting(const GURL& request_url, 409 bool IsCertLikelyFromMultiTenantHosting(const GURL& request_url,
410 const net::X509Certificate& cert) { 410 const net::X509Certificate& cert) {
411 std::string host_name = request_url.host(); 411 std::string host_name = request_url.host();
412 std::vector<std::string> dns_names; 412 std::vector<std::string> dns_names;
413 std::vector<std::string> dns_names_domain; 413 std::vector<std::string> dns_names_domain;
414 cert.GetDNSNames(&dns_names); 414 cert.GetSubjectAltName(&dns_names, NULL);
Ryan Sleevi 2017/03/31 14:51:33 nit: nullptr
elawrence 2017/03/31 16:09:41 Done.
415 size_t dns_names_size = dns_names.size(); 415 size_t dns_names_size = dns_names.size();
416 416
417 // If there is only 1 DNS name then it is definitely not a shared certificate. 417 // If there is only 1 DNS name then it is definitely not a shared certificate.
418 if (dns_names_size == 0 || dns_names_size == 1) 418 if (dns_names_size == 0 || dns_names_size == 1)
419 return false; 419 return false;
420 420
421 // Check to see if all the domains in the SAN field in the SSL certificate are 421 // Check to see if all the domains in the SAN field in the SSL certificate are
422 // the same or not. 422 // the same or not.
423 for (size_t i = 0; i < dns_names_size; ++i) { 423 for (size_t i = 0; i < dns_names_size; ++i) {
424 dns_names_domain.push_back( 424 dns_names_domain.push_back(
(...skipping 26 matching lines...) Expand all
451 return false; 451 return false;
452 } 452 }
453 } 453 }
454 return true; 454 return true;
455 } 455 }
456 456
457 bool IsCertLikelyFromSameDomain(const GURL& request_url, 457 bool IsCertLikelyFromSameDomain(const GURL& request_url,
458 const net::X509Certificate& cert) { 458 const net::X509Certificate& cert) {
459 std::string host_name = request_url.host(); 459 std::string host_name = request_url.host();
460 std::vector<std::string> dns_names; 460 std::vector<std::string> dns_names;
461 cert.GetDNSNames(&dns_names); 461 cert.GetSubjectAltName(&dns_names, NULL);
Ryan Sleevi 2017/03/31 14:51:34 nit: nullptr
elawrence 2017/03/31 16:09:41 Done.
462 if (dns_names.empty())
463 return false;
462 464
463 dns_names.push_back(host_name); 465 dns_names.push_back(host_name);
464 std::vector<std::string> dns_names_domain; 466 std::vector<std::string> dns_names_domain;
465 467
466 for (const std::string& dns_name : dns_names) { 468 for (const std::string& dns_name : dns_names) {
467 dns_names_domain.push_back( 469 dns_names_domain.push_back(
468 net::registry_controlled_domains::GetDomainAndRegistry( 470 net::registry_controlled_domains::GetDomainAndRegistry(
469 dns_name, 471 dns_name,
470 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)); 472 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
471 } 473 }
472 474
473 DCHECK(!dns_names_domain.empty()); 475 DCHECK(!dns_names_domain.empty());
474 const std::string& host_name_domain = dns_names_domain.back(); 476 const std::string& host_name_domain = dns_names_domain.back();
475 477
476 // Last element is the original domain. So, excluding it. 478 // Last element is the original domain. So, excluding it.
477 return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, 479 return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1,
478 host_name_domain) != dns_names_domain.end() - 1; 480 host_name_domain) != dns_names_domain.end() - 1;
479 } 481 }
480 482
481 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { 483 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) {
482 return net::IsHostnameNonUnique(hostname) || 484 return net::IsHostnameNonUnique(hostname) ||
483 hostname.find('.') == std::string::npos; 485 hostname.find('.') == std::string::npos;
484 } 486 }
485 487
486 } // namespace ssl_errors 488 } // namespace ssl_errors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698