Chromium Code Reviews| Index: net/base/multi_threaded_cert_verifier.cc |
| diff --git a/net/base/multi_threaded_cert_verifier.cc b/net/base/multi_threaded_cert_verifier.cc |
| index 18122dd6627a09748f86707a623eb9456efff4f4..22170293a1bb90d5ddfa6fca94a3d2f00383cff4 100644 |
| --- a/net/base/multi_threaded_cert_verifier.cc |
| +++ b/net/base/multi_threaded_cert_verifier.cc |
| @@ -83,6 +83,18 @@ MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} |
| MultiThreadedCertVerifier::CachedResult::~CachedResult() {} |
| +MultiThreadedCertVerifier::ValidityRange::ValidityRange(const base::Time& now) |
| + : verification_time(now), |
| + expiration_time(now) { |
| +} |
| + |
| +MultiThreadedCertVerifier::ValidityRange::ValidityRange( |
| + const base::Time& now, |
| + const base::Time& expiration) |
| + : verification_time(now), |
| + expiration_time(expiration) { |
| +} |
| + |
| // Represents the output and result callback of a request. |
| class CertVerifierRequest { |
| public: |
| @@ -328,7 +340,8 @@ class CertVerifierJob { |
| }; |
| MultiThreadedCertVerifier::MultiThreadedCertVerifier() |
| - : cache_(kMaxCacheEntries), |
| + : cache_(kMaxCacheEntries, |
| + &MultiThreadedCertVerifier::CompareValidityRange), |
| requests_(0), |
| cache_hits_(0), |
| inflight_joins_(0), |
| @@ -362,7 +375,7 @@ int MultiThreadedCertVerifier::Verify(X509Certificate* cert, |
| const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), |
| hostname, flags); |
| const CertVerifierCache::value_type* cached_entry = |
| - cache_.Get(key, base::TimeTicks::Now()); |
| + cache_.Get(key, ValidityRange(base::Time::Now())); |
| if (cached_entry) { |
| ++cache_hits_; |
| *out_req = NULL; |
| @@ -411,6 +424,35 @@ void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) { |
| request->Cancel(); |
| } |
| +// static |
| +bool MultiThreadedCertVerifier::CompareValidityRange( |
| + const ValidityRange& now, |
| + const ValidityRange& expiration) { |
| + // |now| contains only a single time (verification_time), while |expiration| |
| + // contains the validity range - both when the certificate was verified and |
| + // when the verification should expire. |
| + // |
| + // If the user receives a "not yet valid" message, and adjusts their clock |
| + // foward to the correct time, this will (typically) cause |
| + // now.verification_time to advance past expiration.expiration_time, thus |
| + // treating the cached result as an expired entry and re-verifying. |
| + // If the user receives a "expired" message, and adjusts their clock backwards |
| + // to the correct time, this will cause now.verification_time to be less than |
| + // expiration_verification_time, thus treating the cached result as an expired |
|
cbentzel
2012/06/18 19:08:28
Unclear to me: Should now.verification_time < expi
Ryan Sleevi
2012/06/19 00:59:28
It's a cache expiration issue, but not a cert expi
|
| + // entry and re-verifying. |
| + // If the user receives either of those messages, and does not adjust their |
| + // clock, then the result will be (typically) be cached until the expiration |
| + // TTL. |
| + // |
| + // This algorithm is only problematic if the user consistently keeps adjusting |
| + // their clock backwards in increments smaller than the expiration TTL, in |
| + // which case, cached elements continue to be added. However, because the |
| + // cache has a fixed upper bound, if no entries are expired, a 'random' entry |
| + // will be, thus keeping the memory constraints bounded over time. |
| + return now.verification_time >= expiration.verification_time && |
|
cbentzel
2012/06/18 19:08:28
DCHECK that now.verification_time == now.expiratio
|
| + now.verification_time < expiration.expiration_time; |
| +} |
| + |
| // HandleResult is called by CertVerifierWorker on the origin message loop. |
| // It deletes CertVerifierJob. |
| void MultiThreadedCertVerifier::HandleResult( |
| @@ -427,8 +469,9 @@ void MultiThreadedCertVerifier::HandleResult( |
| CachedResult cached_result; |
| cached_result.error = error; |
| cached_result.result = verify_result; |
| - cache_.Put(key, cached_result, base::TimeTicks::Now(), |
| - base::TimeDelta::FromSeconds(kTTLSecs)); |
| + base::Time now = base::Time::Now(); |
| + cache_.Put(key, cached_result, ValidityRange(now), |
| + ValidityRange(now, now + base::TimeDelta::FromSeconds(kTTLSecs))); |
|
szym
2012/06/18 16:11:37
If the result is successful, shouldn't we take min
Ryan Sleevi
2012/06/18 18:00:46
Possibly. Definitely an edge case. Another edge ca
Ryan Sleevi
2012/06/19 17:57:34
In thinking about it, I think it's probably more c
szym
2012/06/19 18:01:13
This alone convinced me that it's better to leave
|
| std::map<RequestParams, CertVerifierJob*>::iterator j; |
| j = inflight_.find(key); |