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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
120 void RecordUMAStatistics(bool overridable, | 121 void RecordUMAStatistics(bool overridable, |
121 const base::Time& current_time, | 122 const base::Time& current_time, |
123 const network_time::NetworkTimeTracker* network_time, | |
122 const GURL& request_url, | 124 const GURL& request_url, |
123 int cert_error, | 125 int cert_error, |
124 const net::X509Certificate& cert) { | 126 const net::X509Certificate& cert) { |
125 ssl_errors::ErrorInfo::ErrorType type = | 127 ssl_errors::ErrorInfo::ErrorType type = |
126 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); | 128 ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error); |
127 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", type, | 129 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", type, |
128 ssl_errors::ErrorInfo::END_OF_ENUM); | 130 ssl_errors::ErrorInfo::END_OF_ENUM); |
129 switch (type) { | 131 switch (type) { |
130 case ssl_errors::ErrorInfo::CERT_DATE_INVALID: { | 132 case ssl_errors::ErrorInfo::CERT_DATE_INVALID: { |
131 if (IsUserClockInThePast(base::Time::NowFromSystemTime())) { | 133 // TODO(mab): Why doesn't this just use |current_time|? |
estark
2016/03/11 22:00:05
Can you please file a bug at include the URL (http
mab
2016/03/11 23:12:50
Before I do that, let's ask felt, since she's on t
estark
2016/03/11 23:15:23
Yeah, that's fine with me.
| |
132 RecordSSLInterstitialCause(overridable, CLOCK_PAST); | 134 switch (GetClockState(base::Time::NowFromSystemTime(), network_time)) { |
133 } else if (IsUserClockInTheFuture(base::Time::NowFromSystemTime())) { | 135 case CLOCK_STATE_NETWORK_PAST: |
134 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); | 136 case CLOCK_STATE_BUILD_PAST: |
135 } else if (cert.HasExpired() && | 137 RecordSSLInterstitialCause(overridable, CLOCK_PAST); |
136 (current_time - cert.valid_expiry()).InDays() < 28) { | 138 break; |
137 RecordSSLInterstitialCause(overridable, EXPIRED_RECENTLY); | 139 case CLOCK_STATE_NETWORK_FUTURE: |
140 case CLOCK_STATE_BUILD_FUTURE: | |
141 RecordSSLInterstitialCause(overridable, CLOCK_FUTURE); | |
142 break; | |
143 case CLOCK_STATE_UNKNOWN: | |
144 // Fall through, but, would it be better to break here? Not | |
145 // sure it makes sense to record |EXPIRED_RECENTLY| in this | |
146 // case. UNKNOWN means that network time is unavailable and | |
147 // that the system clock is within a 367-day bound around | |
148 // the build time. That's a lot of slop. | |
149 case CLOCK_STATE_NETWORK_OK: | |
150 if (cert.HasExpired() && | |
151 (current_time - cert.valid_expiry()).InDays() < 28) { | |
152 RecordSSLInterstitialCause(overridable, EXPIRED_RECENTLY); | |
153 } | |
154 break; | |
138 } | 155 } |
139 break; | |
140 } | 156 } |
141 case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: { | 157 case ssl_errors::ErrorInfo::CERT_COMMON_NAME_INVALID: { |
142 std::string host_name = request_url.host(); | 158 std::string host_name = request_url.host(); |
143 if (IsHostNameKnownTLD(host_name)) { | 159 if (IsHostNameKnownTLD(host_name)) { |
144 HostnameTokens host_name_tokens = Tokenize(host_name); | 160 HostnameTokens host_name_tokens = Tokenize(host_name); |
145 if (IsWWWSubDomainMatch(request_url, cert)) | 161 if (IsWWWSubDomainMatch(request_url, cert)) |
146 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); | 162 RecordSSLInterstitialCause(overridable, WWW_SUBDOMAIN_MATCH); |
147 if (IsSubDomainOutsideWildcard(request_url, cert)) | 163 if (IsSubDomainOutsideWildcard(request_url, cert)) |
148 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD); | 164 RecordSSLInterstitialCause(overridable, SUBDOMAIN_OUTSIDE_WILDCARD); |
149 std::vector<std::string> dns_names; | 165 std::vector<std::string> dns_names; |
(...skipping 24 matching lines...) Expand all Loading... | |
174 break; | 190 break; |
175 } | 191 } |
176 default: | 192 default: |
177 break; | 193 break; |
178 } | 194 } |
179 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.connection_type", | 195 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.connection_type", |
180 net::NetworkChangeNotifier::GetConnectionType(), | 196 net::NetworkChangeNotifier::GetConnectionType(), |
181 net::NetworkChangeNotifier::CONNECTION_LAST); | 197 net::NetworkChangeNotifier::CONNECTION_LAST); |
182 } | 198 } |
183 | 199 |
184 bool IsUserClockInThePast(const base::Time& time_now) { | 200 ClockState GetClockState( |
185 base::Time build_time; | 201 const base::Time& now_system, |
186 if (!g_testing_build_time.Get().is_null()) { | 202 const network_time::NetworkTimeTracker* network_time_tracker) { |
187 build_time = g_testing_build_time.Get(); | 203 base::Time now_network; |
188 } else { | 204 base::TimeDelta uncertainty; |
189 build_time = base::GetBuildTime(); | 205 const base::TimeDelta kNetworkTimeFudge = base::TimeDelta::FromMinutes(5); |
206 if (network_time_tracker->GetNetworkTime(&now_network, &uncertainty)) { | |
207 if (now_system < now_network - uncertainty - kNetworkTimeFudge) { | |
estark
2016/03/11 22:00:05
nit: other code is this file doesn't use curly bra
mab
2016/03/11 23:12:50
I kinda think this is how "goto fail" happened, bu
estark
2016/03/11 23:15:23
I know, I hate it too. But, when in Rome...
| |
208 return CLOCK_STATE_NETWORK_PAST; | |
209 } | |
210 if (now_system > now_network + uncertainty + kNetworkTimeFudge) { | |
estark
2016/03/11 22:00:05
same nit about the curly braces
mab
2016/03/11 23:12:50
Done.
| |
211 return CLOCK_STATE_NETWORK_FUTURE; | |
212 } | |
213 return CLOCK_STATE_NETWORK_OK; | |
190 } | 214 } |
191 | 215 |
192 if (time_now < build_time - base::TimeDelta::FromDays(2)) | 216 base::Time build_time = g_testing_build_time.Get().is_null() |
193 return true; | 217 ? base::GetBuildTime() |
194 return false; | 218 : g_testing_build_time.Get(); |
195 } | 219 if (now_system < build_time - base::TimeDelta::FromDays(2)) { |
estark
2016/03/11 22:00:05
ditto
mab
2016/03/11 23:12:50
Done.
| |
196 | 220 return CLOCK_STATE_BUILD_PAST; |
197 bool IsUserClockInTheFuture(const base::Time& time_now) { | 221 } |
198 base::Time build_time; | 222 if (now_system > build_time + base::TimeDelta::FromDays(365)) { |
estark
2016/03/11 22:00:06
ditto
mab
2016/03/11 23:12:50
Done.
| |
199 if (!g_testing_build_time.Get().is_null()) { | 223 return CLOCK_STATE_BUILD_FUTURE; |
200 build_time = g_testing_build_time.Get(); | |
201 } else { | |
202 build_time = base::GetBuildTime(); | |
203 } | 224 } |
204 | 225 |
205 if (time_now > build_time + base::TimeDelta::FromDays(365)) | 226 return CLOCK_STATE_UNKNOWN; |
206 return true; | |
207 return false; | |
208 } | 227 } |
209 | 228 |
210 void SetBuildTimeForTesting(const base::Time& testing_time) { | 229 void SetBuildTimeForTesting(const base::Time& testing_time) { |
211 g_testing_build_time.Get() = testing_time; | 230 g_testing_build_time.Get() = testing_time; |
212 } | 231 } |
213 | 232 |
214 bool IsHostNameKnownTLD(const std::string& host_name) { | 233 bool IsHostNameKnownTLD(const std::string& host_name) { |
215 size_t tld_length = net::registry_controlled_domains::GetRegistryLength( | 234 size_t tld_length = net::registry_controlled_domains::GetRegistryLength( |
216 host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | 235 host_name, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, |
217 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | 236 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, | 431 return std::find(dns_names_domain.begin(), dns_names_domain.end() - 1, |
413 host_name_domain) != dns_names_domain.end() - 1; | 432 host_name_domain) != dns_names_domain.end() - 1; |
414 } | 433 } |
415 | 434 |
416 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { | 435 bool IsHostnameNonUniqueOrDotless(const std::string& hostname) { |
417 return net::IsHostnameNonUnique(hostname) || | 436 return net::IsHostnameNonUnique(hostname) || |
418 hostname.find('.') == std::string::npos; | 437 hostname.find('.') == std::string::npos; |
419 } | 438 } |
420 | 439 |
421 } // namespace ssl_errors | 440 } // namespace ssl_errors |
OLD | NEW |