| OLD | NEW |
| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { | 60 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) { |
| 61 if (overridable) { | 61 if (overridable) { |
| 62 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, | 62 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event, |
| 63 UNUSED_INTERSTITIAL_CAUSE_ENTRY); | 63 UNUSED_INTERSTITIAL_CAUSE_ENTRY); |
| 64 } else { | 64 } else { |
| 65 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, | 65 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.nonoverridable", event, |
| 66 UNUSED_INTERSTITIAL_CAUSE_ENTRY); | 66 UNUSED_INTERSTITIAL_CAUSE_ENTRY); |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Returns the Levenshtein distance between |str1| and |str2|. | |
| 71 // Which is the minimum number of single-character edits (i.e. insertions, | |
| 72 // deletions or substitutions) required to change one word into the other. | |
| 73 // https://en.wikipedia.org/wiki/Levenshtein_distance | |
| 74 size_t GetLevenshteinDistance(const std::string& str1, | |
| 75 const std::string& str2) { | |
| 76 if (str1 == str2) | |
| 77 return 0; | |
| 78 if (str1.size() == 0) | |
| 79 return str2.size(); | |
| 80 if (str2.size() == 0) | |
| 81 return str1.size(); | |
| 82 std::vector<size_t> kFirstRow(str2.size() + 1, 0); | |
| 83 std::vector<size_t> kSecondRow(str2.size() + 1, 0); | |
| 84 | |
| 85 for (size_t i = 0; i < kFirstRow.size(); ++i) | |
| 86 kFirstRow[i] = i; | |
| 87 for (size_t i = 0; i < str1.size(); ++i) { | |
| 88 kSecondRow[0] = i + 1; | |
| 89 for (size_t j = 0; j < str2.size(); ++j) { | |
| 90 int cost = str1[i] == str2[j] ? 0 : 1; | |
| 91 kSecondRow[j + 1] = | |
| 92 std::min(std::min(kSecondRow[j] + 1, kFirstRow[j + 1] + 1), | |
| 93 kFirstRow[j] + cost); | |
| 94 } | |
| 95 for (size_t j = 0; j < kFirstRow.size(); j++) | |
| 96 kFirstRow[j] = kSecondRow[j]; | |
| 97 } | |
| 98 return kSecondRow[str2.size()]; | |
| 99 } | |
| 100 | |
| 101 std::vector<HostnameTokens> GetTokenizedDNSNames( | 70 std::vector<HostnameTokens> GetTokenizedDNSNames( |
| 102 const std::vector<std::string>& dns_names) { | 71 const std::vector<std::string>& dns_names) { |
| 103 std::vector<HostnameTokens> dns_name_tokens; | 72 std::vector<HostnameTokens> dns_name_tokens; |
| 104 for (const auto& dns_name : dns_names) { | 73 for (const auto& dns_name : dns_names) { |
| 105 HostnameTokens dns_name_token_single; | 74 HostnameTokens dns_name_token_single; |
| 106 if (dns_name.empty() || dns_name.find('\0') != std::string::npos || | 75 if (dns_name.empty() || dns_name.find('\0') != std::string::npos || |
| 107 !(IsHostNameKnownTLD(dns_name))) { | 76 !(IsHostNameKnownTLD(dns_name))) { |
| 108 dns_name_token_single.push_back(std::string()); | 77 dns_name_token_single.push_back(std::string()); |
| 109 } else { | 78 } else { |
| 110 dns_name_token_single = Tokenize(dns_name); | 79 dns_name_token_single = Tokenize(dns_name); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 std::vector<std::string> dns_names; | 111 std::vector<std::string> dns_names; |
| 143 cert.GetDNSNames(&dns_names); | 112 cert.GetDNSNames(&dns_names); |
| 144 return GetWWWSubDomainMatch(request_url, dns_names, &www_host); | 113 return GetWWWSubDomainMatch(request_url, dns_names, &www_host); |
| 145 } | 114 } |
| 146 | 115 |
| 147 // The time to use when doing build time operations in browser tests. | 116 // The time to use when doing build time operations in browser tests. |
| 148 base::LazyInstance<base::Time> g_testing_build_time = LAZY_INSTANCE_INITIALIZER; | 117 base::LazyInstance<base::Time> g_testing_build_time = LAZY_INSTANCE_INITIALIZER; |
| 149 | 118 |
| 150 } // namespace | 119 } // namespace |
| 151 | 120 |
| 121 // Returns the Levenshtein distance between |str1| and |str2|. |
| 122 // Which is the minimum number of single-character edits (i.e. insertions, |
| 123 // deletions or substitutions) required to change one word into the other. |
| 124 // https://en.wikipedia.org/wiki/Levenshtein_distance |
| 125 size_t GetLevenshteinDistance(const std::string& str1, |
| 126 const std::string& str2) { |
| 127 if (str1 == str2) |
| 128 return 0; |
| 129 if (str1.size() == 0) |
| 130 return str2.size(); |
| 131 if (str2.size() == 0) |
| 132 return str1.size(); |
| 133 |
| 134 std::vector<size_t> row(str2.size() + 1); |
| 135 for (size_t i = 0; i < row.size(); ++i) |
| 136 row[i] = i; |
| 137 |
| 138 for (size_t i = 0; i < str1.size(); ++i) { |
| 139 row[0] = i + 1; |
| 140 size_t previous = i; |
| 141 for (size_t j = 0; j < str2.size(); ++j) { |
| 142 size_t old_row = row[j + 1]; |
| 143 int cost = str1[i] == str2[j] ? 0 : 1; |
| 144 row[j + 1] = std::min(std::min(row[j], row[j + 1]) + 1, previous + cost); |
| 145 previous = old_row; |
| 146 } |
| 147 } |
| 148 return row[str2.size()]; |
| 149 } |
| 150 |
| 151 |
| 152 void RecordUMAStatistics(bool overridable, | 152 void RecordUMAStatistics(bool overridable, |
| 153 const base::Time& current_time, | 153 const base::Time& current_time, |
| 154 const GURL& request_url, | 154 const GURL& request_url, |
| 155 int cert_error, | 155 int cert_error, |
| 156 const net::X509Certificate& cert) { | 156 const net::X509Certificate& cert) { |
| 157 ssl_errors::ErrorInfo::ErrorType type = | 157 ssl_errors::ErrorInfo::ErrorType type = |
| 158 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); | 158 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); |
| 159 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", type, | 159 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", type, |
| 160 ssl_errors::ErrorInfo::END_OF_ENUM); | 160 ssl_errors::ErrorInfo::END_OF_ENUM); |
| 161 switch (type) { | 161 switch (type) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 static const int kDistinctNameThreshold = 5; | 381 static const int kDistinctNameThreshold = 5; |
| 382 if (dns_names_size > kDistinctNameThreshold) | 382 if (dns_names_size > kDistinctNameThreshold) |
| 383 return true; | 383 return true; |
| 384 | 384 |
| 385 // Heuristic - The edit distance between all the strings should be at least 5 | 385 // Heuristic - The edit distance between all the strings should be at least 5 |
| 386 // for it to be counted as a shared SSLCertificate. If even one pair of | 386 // for it to be counted as a shared SSLCertificate. If even one pair of |
| 387 // strings edit distance is below 5 then the certificate is no longer | 387 // strings edit distance is below 5 then the certificate is no longer |
| 388 // considered as a shared certificate. Include the host name in the URL also | 388 // considered as a shared certificate. Include the host name in the URL also |
| 389 // while comparing. | 389 // while comparing. |
| 390 dns_names.push_back(host_name); | 390 dns_names.push_back(host_name); |
| 391 static const size_t kMinimumEditDsitance = 5; | 391 static const size_t kMinimumEditDistance = 5; |
| 392 for (size_t i = 0; i < dns_names_size; ++i) { | 392 for (size_t i = 0; i < dns_names_size; ++i) { |
| 393 for (size_t j = i + 1; j < dns_names_size; ++j) { | 393 for (size_t j = i + 1; j < dns_names_size; ++j) { |
| 394 size_t edit_distance = GetLevenshteinDistance(dns_names[i], dns_names[j]); | 394 size_t edit_distance = GetLevenshteinDistance(dns_names[i], dns_names[j]); |
| 395 if (edit_distance < kMinimumEditDsitance) | 395 if (edit_distance < kMinimumEditDistance) |
| 396 return false; | 396 return false; |
| 397 } | 397 } |
| 398 } | 398 } |
| 399 return true; | 399 return true; |
| 400 } | 400 } |
| 401 | 401 |
| 402 bool IsCertLikelyFromSameDomain(const GURL& request_url, | 402 bool IsCertLikelyFromSameDomain(const GURL& request_url, |
| 403 const net::X509Certificate& cert) { | 403 const net::X509Certificate& cert) { |
| 404 std::string host_name = request_url.host(); | 404 std::string host_name = request_url.host(); |
| 405 std::vector<std::string> dns_names; | 405 std::vector<std::string> dns_names; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 422 return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, | 422 return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, |
| 423 host_name_domain) != dns_names_domain.end() - 1; | 423 host_name_domain) != dns_names_domain.end() - 1; |
| 424 } | 424 } |
| 425 | 425 |
| 426 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { | 426 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { |
| 427 return net::IsHostnameNonUnique(hostname) || | 427 return net::IsHostnameNonUnique(hostname) || |
| 428 hostname.find('.') == std::string::npos; | 428 hostname.find('.') == std::string::npos; |
| 429 } | 429 } |
| 430 | 430 |
| 431 } // namespace ssl_errors | 431 } // namespace ssl_errors |
| OLD | NEW |