| 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> | 
| 11 | 11 | 
| 12 #include "base/build_time.h" | 12 #include "base/build_time.h" | 
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" | 
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" | 
| 15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" | 
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" | 
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" | 
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" | 
|  | 19 #include "components/network_time/network_time_tracker.h" | 
| 19 #include "components/ssl_errors/error_info.h" | 20 #include "components/ssl_errors/error_info.h" | 
| 20 #include "components/url_formatter/url_formatter.h" | 21 #include "components/url_formatter/url_formatter.h" | 
| 21 #include "net/base/network_change_notifier.h" | 22 #include "net/base/network_change_notifier.h" | 
| 22 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 23 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 
| 23 #include "net/base/url_util.h" | 24 #include "net/base/url_util.h" | 
| 24 #include "net/cert/x509_cert_types.h" | 25 #include "net/cert/x509_cert_types.h" | 
| 25 #include "net/cert/x509_certificate.h" | 26 #include "net/cert/x509_certificate.h" | 
| 26 #include "url/gurl.h" | 27 #include "url/gurl.h" | 
| 27 | 28 | 
| 28 #if defined(OS_WIN) | 29 #if defined(OS_WIN) | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 110   std::vector<std::string> dns_names; | 111   std::vector<std::string> dns_names; | 
| 111   cert.GetDNSNames(&dns_names); | 112   cert.GetDNSNames(&dns_names); | 
| 112   return GetWWWSubDomainMatch(request_url, dns_names, &www_host); | 113   return GetWWWSubDomainMatch(request_url, dns_names, &www_host); | 
| 113 } | 114 } | 
| 114 | 115 | 
| 115 // 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. | 
| 116 base::LazyInstance<base::Time> g_testing_build_time = LAZY_INSTANCE_INITIALIZER; | 117 base::LazyInstance<base::Time> g_testing_build_time = LAZY_INSTANCE_INITIALIZER; | 
| 117 | 118 | 
| 118 }  // namespace | 119 }  // namespace | 
| 119 | 120 | 
|  | 121 static ssl_errors::ErrorInfo::ErrorType RecordErrorType(int cert_error) { | 
|  | 122   ssl_errors::ErrorInfo::ErrorType error_type = | 
|  | 123       ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); | 
|  | 124   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", error_type, | 
|  | 125                             ssl_errors::ErrorInfo::END_OF_ENUM); | 
|  | 126   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.connection_type", | 
|  | 127                             net::NetworkChangeNotifier::GetConnectionType(), | 
|  | 128                             net::NetworkChangeNotifier::CONNECTION_LAST); | 
|  | 129   return error_type; | 
|  | 130 } | 
|  | 131 | 
| 120 void RecordUMAStatistics(bool overridable, | 132 void RecordUMAStatistics(bool overridable, | 
| 121                          const base::Time& current_time, | 133                          const base::Time& current_time, | 
| 122                          const GURL& request_url, | 134                          const GURL& request_url, | 
| 123                          int cert_error, | 135                          int cert_error, | 
| 124                          const net::X509Certificate& cert) { | 136                          const net::X509Certificate& cert) { | 
| 125   ssl_errors::ErrorInfo::ErrorType type = | 137   ssl_errors::ErrorInfo::ErrorType error_type = RecordErrorType(cert_error); | 
| 126       ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); | 138 | 
| 127   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", type, | 139   switch (error_type) { | 
| 128                             ssl_errors::ErrorInfo::END_OF_ENUM); |  | 
| 129   switch (type) { |  | 
| 130     case ssl_errors::ErrorInfo::CERT_DATE_INVALID: { | 140     case ssl_errors::ErrorInfo::CERT_DATE_INVALID: { | 
| 131       if (IsUserClockInThePast(base::Time::NowFromSystemTime())) { | 141       // Note: not reached when displaying the bad clock interstitial. | 
| 132         RecordSSLInterstitialCause(overridable, CLOCK_PAST); | 142       // See |RecordUMAStatisticsForClockInterstitial| below. | 
| 133       } else if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) { | 143       if (cert.HasExpired() && | 
| 134         RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); | 144           (current_time - cert.valid_expiry()).InDays() < 28) { | 
| 135       } else if (cert.HasExpired() && |  | 
| 136                  (current_time - cert.valid_expiry()).InDays() < 28) { |  | 
| 137         RecordSSLInterstitialCause(overridable, EXPIRED_RECENTLY); | 145         RecordSSLInterstitialCause(overridable, EXPIRED_RECENTLY); | 
| 138       } | 146       } | 
| 139       break; | 147       break; | 
| 140     } | 148     } | 
| 141     case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: { | 149     case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: { | 
| 142       std::string host_name = request_url.host(); | 150       std::string host_name = request_url.host(); | 
| 143       if (IsHostNameKnownTLD(host_name)) { | 151       if (IsHostNameKnownTLD(host_name)) { | 
| 144         HostnameTokens host_name_tokens = Tokenize(host_name); | 152         HostnameTokens host_name_tokens = Tokenize(host_name); | 
| 145         if (IsWWWSubDomainMatch(request_url, cert)) | 153         if (IsWWWSubDomainMatch(request_url, cert)) | 
| 146           RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); | 154           RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 169         RecordSSLInterstitialCause(overridable, LOCALHOST); | 177         RecordSSLInterstitialCause(overridable, LOCALHOST); | 
| 170       if (IsHostnameNonUniqueOrDotless(hostname)) | 178       if (IsHostnameNonUniqueOrDotless(hostname)) | 
| 171         RecordSSLInterstitialCause(overridable, PRIVATE_URL); | 179         RecordSSLInterstitialCause(overridable, PRIVATE_URL); | 
| 172       if (net::X509Certificate::IsSelfSigned(cert.os_cert_handle())) | 180       if (net::X509Certificate::IsSelfSigned(cert.os_cert_handle())) | 
| 173         RecordSSLInterstitialCause(overridable, SELF_SIGNED); | 181         RecordSSLInterstitialCause(overridable, SELF_SIGNED); | 
| 174       break; | 182       break; | 
| 175     } | 183     } | 
| 176     default: | 184     default: | 
| 177       break; | 185       break; | 
| 178   } | 186   } | 
| 179   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.connection_type", |  | 
| 180                             net::NetworkChangeNotifier::GetConnectionType(), |  | 
| 181                             net::NetworkChangeNotifier::CONNECTION_LAST); |  | 
| 182 } | 187 } | 
| 183 | 188 | 
| 184 bool IsUserClockInThePast(const base::Time& time_now) { | 189 void RecordUMAStatisticsForClockInterstitial(bool overridable, | 
| 185   base::Time build_time; | 190                                              ssl_errors::ClockState clock_state, | 
| 186   if (!g_testing_build_time.Get().is_null()) { | 191                                              int cert_error) { | 
| 187     build_time = g_testing_build_time.Get(); | 192   ssl_errors::ErrorInfo::ErrorType error_type = RecordErrorType(cert_error); | 
|  | 193   DCHECK(error_type == ssl_errors::ErrorInfo::CERT_DATE_INVALID); | 
|  | 194 | 
|  | 195   if (clock_state == ssl_errors::CLOCK_STATE_FUTURE) { | 
|  | 196     RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); | 
|  | 197   } else if (clock_state == ssl_errors::CLOCK_STATE_PAST) { | 
|  | 198     RecordSSLInterstitialCause(overridable, CLOCK_PAST); | 
| 188   } else { | 199   } else { | 
| 189     build_time = base::GetBuildTime(); | 200     NOTREACHED(); | 
|  | 201   } | 
|  | 202 } | 
|  | 203 | 
|  | 204 ClockState GetClockState( | 
|  | 205     const base::Time& now_system, | 
|  | 206     const network_time::NetworkTimeTracker* network_time_tracker) { | 
|  | 207   base::Time now_network; | 
|  | 208   base::TimeDelta uncertainty; | 
|  | 209   const base::TimeDelta kNetworkTimeFudge = base::TimeDelta::FromMinutes(5); | 
|  | 210   ClockState network_state = CLOCK_STATE_UNKNOWN; | 
|  | 211   if (network_time_tracker->GetNetworkTime(&now_network, &uncertainty)) { | 
|  | 212     if (now_system < now_network - uncertainty - kNetworkTimeFudge) { | 
|  | 213       network_state = CLOCK_STATE_PAST; | 
|  | 214     } else if (now_system > now_network + uncertainty + kNetworkTimeFudge) { | 
|  | 215       network_state = CLOCK_STATE_FUTURE; | 
|  | 216     } else { | 
|  | 217       network_state = CLOCK_STATE_OK; | 
|  | 218     } | 
| 190   } | 219   } | 
| 191 | 220 | 
| 192   if (time_now < build_time - base::TimeDelta::FromDays(2)) | 221   ClockState build_time_state = CLOCK_STATE_UNKNOWN; | 
| 193     return true; | 222   base::Time build_time = g_testing_build_time.Get().is_null() | 
| 194   return false; | 223                               ? base::GetBuildTime() | 
| 195 } | 224                               : g_testing_build_time.Get(); | 
| 196 | 225   if (now_system < build_time - base::TimeDelta::FromDays(2)) { | 
| 197 bool IsUserClockInTheFuture(const base::Time& time_now) { | 226     build_time_state = CLOCK_STATE_PAST; | 
| 198   base::Time build_time; | 227   } else if (now_system > build_time + base::TimeDelta::FromDays(365)) { | 
| 199   if (!g_testing_build_time.Get().is_null()) { | 228     build_time_state = CLOCK_STATE_FUTURE; | 
| 200     build_time = g_testing_build_time.Get(); |  | 
| 201   } else { |  | 
| 202     build_time = base::GetBuildTime(); |  | 
| 203   } | 229   } | 
| 204 | 230 | 
| 205   if (time_now > build_time + base::TimeDelta::FromDays(365)) | 231   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.clockstate.network", | 
| 206     return true; | 232                             network_state, CLOCK_STATE_MAX); | 
| 207   return false; | 233   UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.clockstate.build_time", | 
|  | 234                             build_time_state, CLOCK_STATE_MAX); | 
|  | 235 | 
|  | 236   return network_state == CLOCK_STATE_UNKNOWN ? build_time_state | 
|  | 237                                               : network_state; | 
| 208 } | 238 } | 
| 209 | 239 | 
| 210 void SetBuildTimeForTesting(const base::Time& testing_time) { | 240 void SetBuildTimeForTesting(const base::Time& testing_time) { | 
| 211   g_testing_build_time.Get() = testing_time; | 241   g_testing_build_time.Get() = testing_time; | 
| 212 } | 242 } | 
| 213 | 243 | 
| 214 bool IsHostNameKnownTLD(const std::string& host_name) { | 244 bool IsHostNameKnownTLD(const std::string& host_name) { | 
| 215   size_t tld_length = net::registry_controlled_domains::GetRegistryLength( | 245   size_t tld_length = net::registry_controlled_domains::GetRegistryLength( | 
| 216       host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | 246       host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | 
| 217       net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | 247       net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | 
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 412   return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, | 442   return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, | 
| 413                    host_name_domain) != dns_names_domain.end() - 1; | 443                    host_name_domain) != dns_names_domain.end() - 1; | 
| 414 } | 444 } | 
| 415 | 445 | 
| 416 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { | 446 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { | 
| 417   return net::IsHostnameNonUnique(hostname) || | 447   return net::IsHostnameNonUnique(hostname) || | 
| 418          hostname.find('.') == std::string::npos; | 448          hostname.find('.') == std::string::npos; | 
| 419 } | 449 } | 
| 420 | 450 | 
| 421 }  // namespace ssl_errors | 451 }  // namespace ssl_errors | 
| OLD | NEW | 
|---|