| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/base/multi_threaded_cert_verifier.h" | 5 #include "net/base/multi_threaded_cert_verifier.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 | 76 |
| 77 // The number of seconds for which we'll cache a cache entry. | 77 // The number of seconds for which we'll cache a cache entry. |
| 78 const unsigned kTTLSecs = 1800; // 30 minutes. | 78 const unsigned kTTLSecs = 1800; // 30 minutes. |
| 79 | 79 |
| 80 } // namespace | 80 } // namespace |
| 81 | 81 |
| 82 MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} | 82 MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} |
| 83 | 83 |
| 84 MultiThreadedCertVerifier::CachedResult::~CachedResult() {} | 84 MultiThreadedCertVerifier::CachedResult::~CachedResult() {} |
| 85 | 85 |
| 86 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( |
| 87 const base::Time& now) |
| 88 : verification_time(now), |
| 89 expiration_time(now) { |
| 90 } |
| 91 |
| 92 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( |
| 93 const base::Time& now, |
| 94 const base::Time& expiration) |
| 95 : verification_time(now), |
| 96 expiration_time(expiration) { |
| 97 } |
| 98 |
| 99 bool MultiThreadedCertVerifier::CacheExpirationFunctor::operator()( |
| 100 const CacheValidityPeriod& now, |
| 101 const CacheValidityPeriod& expiration) const { |
| 102 // Ensure this functor is being used for expiration only, and not strict |
| 103 // weak ordering/sorting. |now| should only ever contain a single |
| 104 // base::Time. |
| 105 // Note: DCHECK_EQ is not used due to operator<< overloading requirements. |
| 106 DCHECK(now.verification_time == now.expiration_time); |
| 107 |
| 108 // |now| contains only a single time (verification_time), while |expiration| |
| 109 // contains the validity range - both when the certificate was verified and |
| 110 // when the verification result should expire. |
| 111 // |
| 112 // If the user receives a "not yet valid" message, and adjusts their clock |
| 113 // foward to the correct time, this will (typically) cause |
| 114 // now.verification_time to advance past expiration.expiration_time, thus |
| 115 // treating the cached result as an expired entry and re-verifying. |
| 116 // If the user receives a "expired" message, and adjusts their clock |
| 117 // backwards to the correct time, this will cause now.verification_time to |
| 118 // be less than expiration_verification_time, thus treating the cached |
| 119 // result as an expired entry and re-verifying. |
| 120 // If the user receives either of those messages, and does not adjust their |
| 121 // clock, then the result will be (typically) be cached until the expiration |
| 122 // TTL. |
| 123 // |
| 124 // This algorithm is only problematic if the user consistently keeps |
| 125 // adjusting their clock backwards in increments smaller than the expiration |
| 126 // TTL, in which case, cached elements continue to be added. However, |
| 127 // because the cache has a fixed upper bound, if no entries are expired, a |
| 128 // 'random' entry will be, thus keeping the memory constraints bounded over |
| 129 // time. |
| 130 return now.verification_time >= expiration.verification_time && |
| 131 now.verification_time < expiration.expiration_time; |
| 132 }; |
| 133 |
| 134 |
| 86 // Represents the output and result callback of a request. | 135 // Represents the output and result callback of a request. |
| 87 class CertVerifierRequest { | 136 class CertVerifierRequest { |
| 88 public: | 137 public: |
| 89 CertVerifierRequest(const CompletionCallback& callback, | 138 CertVerifierRequest(const CompletionCallback& callback, |
| 90 CertVerifyResult* verify_result, | 139 CertVerifyResult* verify_result, |
| 91 const BoundNetLog& net_log) | 140 const BoundNetLog& net_log) |
| 92 : callback_(callback), | 141 : callback_(callback), |
| 93 verify_result_(verify_result), | 142 verify_result_(verify_result), |
| 94 net_log_(net_log) { | 143 net_log_(net_log) { |
| 95 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST); | 144 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST); |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 if (callback.is_null() || !verify_result || hostname.empty()) { | 404 if (callback.is_null() || !verify_result || hostname.empty()) { |
| 356 *out_req = NULL; | 405 *out_req = NULL; |
| 357 return ERR_INVALID_ARGUMENT; | 406 return ERR_INVALID_ARGUMENT; |
| 358 } | 407 } |
| 359 | 408 |
| 360 requests_++; | 409 requests_++; |
| 361 | 410 |
| 362 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), | 411 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), |
| 363 hostname, flags); | 412 hostname, flags); |
| 364 const CertVerifierCache::value_type* cached_entry = | 413 const CertVerifierCache::value_type* cached_entry = |
| 365 cache_.Get(key, base::TimeTicks::Now()); | 414 cache_.Get(key, CacheValidityPeriod(base::Time::Now())); |
| 366 if (cached_entry) { | 415 if (cached_entry) { |
| 367 ++cache_hits_; | 416 ++cache_hits_; |
| 368 *out_req = NULL; | 417 *out_req = NULL; |
| 369 *verify_result = cached_entry->result; | 418 *verify_result = cached_entry->result; |
| 370 return cached_entry->error; | 419 return cached_entry->error; |
| 371 } | 420 } |
| 372 | 421 |
| 373 // No cache hit. See if an identical request is currently in flight. | 422 // No cache hit. See if an identical request is currently in flight. |
| 374 CertVerifierJob* job; | 423 CertVerifierJob* job; |
| 375 std::map<RequestParams, CertVerifierJob*>::const_iterator j; | 424 std::map<RequestParams, CertVerifierJob*>::const_iterator j; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 int error, | 469 int error, |
| 421 const CertVerifyResult& verify_result) { | 470 const CertVerifyResult& verify_result) { |
| 422 DCHECK(CalledOnValidThread()); | 471 DCHECK(CalledOnValidThread()); |
| 423 | 472 |
| 424 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), | 473 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), |
| 425 hostname, flags); | 474 hostname, flags); |
| 426 | 475 |
| 427 CachedResult cached_result; | 476 CachedResult cached_result; |
| 428 cached_result.error = error; | 477 cached_result.error = error; |
| 429 cached_result.result = verify_result; | 478 cached_result.result = verify_result; |
| 430 cache_.Put(key, cached_result, base::TimeTicks::Now(), | 479 base::Time now = base::Time::Now(); |
| 431 base::TimeDelta::FromSeconds(kTTLSecs)); | 480 cache_.Put( |
| 481 key, cached_result, CacheValidityPeriod(now), |
| 482 CacheValidityPeriod(now, now + base::TimeDelta::FromSeconds(kTTLSecs))); |
| 432 | 483 |
| 433 std::map<RequestParams, CertVerifierJob*>::iterator j; | 484 std::map<RequestParams, CertVerifierJob*>::iterator j; |
| 434 j = inflight_.find(key); | 485 j = inflight_.find(key); |
| 435 if (j == inflight_.end()) { | 486 if (j == inflight_.end()) { |
| 436 NOTREACHED(); | 487 NOTREACHED(); |
| 437 return; | 488 return; |
| 438 } | 489 } |
| 439 CertVerifierJob* job = j->second; | 490 CertVerifierJob* job = j->second; |
| 440 inflight_.erase(j); | 491 inflight_.erase(j); |
| 441 | 492 |
| 442 job->HandleResult(cached_result); | 493 job->HandleResult(cached_result); |
| 443 delete job; | 494 delete job; |
| 444 } | 495 } |
| 445 | 496 |
| 446 void MultiThreadedCertVerifier::OnCertTrustChanged( | 497 void MultiThreadedCertVerifier::OnCertTrustChanged( |
| 447 const X509Certificate* cert) { | 498 const X509Certificate* cert) { |
| 448 DCHECK(CalledOnValidThread()); | 499 DCHECK(CalledOnValidThread()); |
| 449 | 500 |
| 450 ClearCache(); | 501 ClearCache(); |
| 451 } | 502 } |
| 452 | 503 |
| 453 void MultiThreadedCertVerifier::SetCertVerifyProc(CertVerifyProc* verify_proc) { | 504 void MultiThreadedCertVerifier::SetCertVerifyProc(CertVerifyProc* verify_proc) { |
| 454 verify_proc_ = verify_proc; | 505 verify_proc_ = verify_proc; |
| 455 } | 506 } |
| 456 | 507 |
| 457 } // namespace net | 508 } // namespace net |
| OLD | NEW |