| 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
|
| + // 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 &&
|
| + 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)));
|
|
|
| std::map<RequestParams, CertVerifierJob*>::iterator j;
|
| j = inflight_.find(key);
|
|
|