Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(546)

Side by Side Diff: net/base/multi_threaded_cert_verifier.cc

Issue 10556022: Consider the verification time as well as the expiration time when caching certificate verification… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment fixes Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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::ValidityRange::ValidityRange(const base::Time& now)
87 : verification_time(now),
88 expiration_time(now) {
89 }
90
91 MultiThreadedCertVerifier::ValidityRange::ValidityRange(
92 const base::Time& now,
93 const base::Time& expiration)
94 : verification_time(now),
95 expiration_time(expiration) {
96 }
97
86 // Represents the output and result callback of a request. 98 // Represents the output and result callback of a request.
87 class CertVerifierRequest { 99 class CertVerifierRequest {
88 public: 100 public:
89 CertVerifierRequest(const CompletionCallback& callback, 101 CertVerifierRequest(const CompletionCallback& callback,
90 CertVerifyResult* verify_result, 102 CertVerifyResult* verify_result,
91 const BoundNetLog& net_log) 103 const BoundNetLog& net_log)
92 : callback_(callback), 104 : callback_(callback),
93 verify_result_(verify_result), 105 verify_result_(verify_result),
94 net_log_(net_log) { 106 net_log_(net_log) {
95 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST); 107 net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 } 333 }
322 } 334 }
323 335
324 const base::TimeTicks start_time_; 336 const base::TimeTicks start_time_;
325 std::vector<CertVerifierRequest*> requests_; 337 std::vector<CertVerifierRequest*> requests_;
326 CertVerifierWorker* worker_; 338 CertVerifierWorker* worker_;
327 const BoundNetLog net_log_; 339 const BoundNetLog net_log_;
328 }; 340 };
329 341
330 MultiThreadedCertVerifier::MultiThreadedCertVerifier() 342 MultiThreadedCertVerifier::MultiThreadedCertVerifier()
331 : cache_(kMaxCacheEntries), 343 : cache_(kMaxCacheEntries,
344 &MultiThreadedCertVerifier::CompareValidityRange),
332 requests_(0), 345 requests_(0),
333 cache_hits_(0), 346 cache_hits_(0),
334 inflight_joins_(0), 347 inflight_joins_(0),
335 verify_proc_(CertVerifyProc::CreateDefault()) { 348 verify_proc_(CertVerifyProc::CreateDefault()) {
336 CertDatabase::AddObserver(this); 349 CertDatabase::AddObserver(this);
337 } 350 }
338 351
339 MultiThreadedCertVerifier::~MultiThreadedCertVerifier() { 352 MultiThreadedCertVerifier::~MultiThreadedCertVerifier() {
340 STLDeleteValues(&inflight_); 353 STLDeleteValues(&inflight_);
341 354
(...skipping 13 matching lines...) Expand all
355 if (callback.is_null() || !verify_result || hostname.empty()) { 368 if (callback.is_null() || !verify_result || hostname.empty()) {
356 *out_req = NULL; 369 *out_req = NULL;
357 return ERR_INVALID_ARGUMENT; 370 return ERR_INVALID_ARGUMENT;
358 } 371 }
359 372
360 requests_++; 373 requests_++;
361 374
362 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), 375 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
363 hostname, flags); 376 hostname, flags);
364 const CertVerifierCache::value_type* cached_entry = 377 const CertVerifierCache::value_type* cached_entry =
365 cache_.Get(key, base::TimeTicks::Now()); 378 cache_.Get(key, ValidityRange(base::Time::Now()));
366 if (cached_entry) { 379 if (cached_entry) {
367 ++cache_hits_; 380 ++cache_hits_;
368 *out_req = NULL; 381 *out_req = NULL;
369 *verify_result = cached_entry->result; 382 *verify_result = cached_entry->result;
370 return cached_entry->error; 383 return cached_entry->error;
371 } 384 }
372 385
373 // No cache hit. See if an identical request is currently in flight. 386 // No cache hit. See if an identical request is currently in flight.
374 CertVerifierJob* job; 387 CertVerifierJob* job;
375 std::map<RequestParams, CertVerifierJob*>::const_iterator j; 388 std::map<RequestParams, CertVerifierJob*>::const_iterator j;
(...skipping 28 matching lines...) Expand all
404 *out_req = request; 417 *out_req = request;
405 return ERR_IO_PENDING; 418 return ERR_IO_PENDING;
406 } 419 }
407 420
408 void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) { 421 void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) {
409 DCHECK(CalledOnValidThread()); 422 DCHECK(CalledOnValidThread());
410 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 423 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
411 request->Cancel(); 424 request->Cancel();
412 } 425 }
413 426
427 // static
428 bool MultiThreadedCertVerifier::CompareValidityRange(
429 const ValidityRange& now,
430 const ValidityRange& expiration) {
431 // |now| contains only a single time (verification_time), while |expiration|
432 // contains the validity range - both when the certificate was verified and
433 // when the verification should expire.
434 //
435 // If the user receives a "not yet valid" message, and adjusts their clock
436 // foward to the correct time, this will (typically) cause
437 // now.verification_time to advance past expiration.expiration_time, thus
438 // treating the cached result as an expired entry and re-verifying.
439 // If the user receives a "expired" message, and adjusts their clock backwards
440 // to the correct time, this will cause now.verification_time to be less than
441 // 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
442 // entry and re-verifying.
443 // If the user receives either of those messages, and does not adjust their
444 // clock, then the result will be (typically) be cached until the expiration
445 // TTL.
446 //
447 // This algorithm is only problematic if the user consistently keeps adjusting
448 // their clock backwards in increments smaller than the expiration TTL, in
449 // which case, cached elements continue to be added. However, because the
450 // cache has a fixed upper bound, if no entries are expired, a 'random' entry
451 // will be, thus keeping the memory constraints bounded over time.
452 return now.verification_time >= expiration.verification_time &&
cbentzel 2012/06/18 19:08:28 DCHECK that now.verification_time == now.expiratio
453 now.verification_time < expiration.expiration_time;
454 }
455
414 // HandleResult is called by CertVerifierWorker on the origin message loop. 456 // HandleResult is called by CertVerifierWorker on the origin message loop.
415 // It deletes CertVerifierJob. 457 // It deletes CertVerifierJob.
416 void MultiThreadedCertVerifier::HandleResult( 458 void MultiThreadedCertVerifier::HandleResult(
417 X509Certificate* cert, 459 X509Certificate* cert,
418 const std::string& hostname, 460 const std::string& hostname,
419 int flags, 461 int flags,
420 int error, 462 int error,
421 const CertVerifyResult& verify_result) { 463 const CertVerifyResult& verify_result) {
422 DCHECK(CalledOnValidThread()); 464 DCHECK(CalledOnValidThread());
423 465
424 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), 466 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(),
425 hostname, flags); 467 hostname, flags);
426 468
427 CachedResult cached_result; 469 CachedResult cached_result;
428 cached_result.error = error; 470 cached_result.error = error;
429 cached_result.result = verify_result; 471 cached_result.result = verify_result;
430 cache_.Put(key, cached_result, base::TimeTicks::Now(), 472 base::Time now = base::Time::Now();
431 base::TimeDelta::FromSeconds(kTTLSecs)); 473 cache_.Put(key, cached_result, ValidityRange(now),
474 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
432 475
433 std::map<RequestParams, CertVerifierJob*>::iterator j; 476 std::map<RequestParams, CertVerifierJob*>::iterator j;
434 j = inflight_.find(key); 477 j = inflight_.find(key);
435 if (j == inflight_.end()) { 478 if (j == inflight_.end()) {
436 NOTREACHED(); 479 NOTREACHED();
437 return; 480 return;
438 } 481 }
439 CertVerifierJob* job = j->second; 482 CertVerifierJob* job = j->second;
440 inflight_.erase(j); 483 inflight_.erase(j);
441 484
442 job->HandleResult(cached_result); 485 job->HandleResult(cached_result);
443 delete job; 486 delete job;
444 } 487 }
445 488
446 void MultiThreadedCertVerifier::OnCertTrustChanged( 489 void MultiThreadedCertVerifier::OnCertTrustChanged(
447 const X509Certificate* cert) { 490 const X509Certificate* cert) {
448 DCHECK(CalledOnValidThread()); 491 DCHECK(CalledOnValidThread());
449 492
450 ClearCache(); 493 ClearCache();
451 } 494 }
452 495
453 void MultiThreadedCertVerifier::SetCertVerifyProc(CertVerifyProc* verify_proc) { 496 void MultiThreadedCertVerifier::SetCertVerifyProc(CertVerifyProc* verify_proc) {
454 verify_proc_ = verify_proc; 497 verify_proc_ = verify_proc;
455 } 498 }
456 499
457 } // namespace net 500 } // namespace net
OLDNEW
« net/base/multi_threaded_cert_verifier.h ('K') | « net/base/multi_threaded_cert_verifier.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698