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

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

Issue 1081913003: Route OCSP stapling through CertVerifier. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@boringnss
Patch Set: yet another CrOS-only Verify call Created 5 years, 7 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
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/cert/multi_threaded_cert_verifier.h" 5 #include "net/cert/multi_threaded_cert_verifier.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/profiler/scoped_tracker.h" 14 #include "base/profiler/scoped_tracker.h"
15 #include "base/sha1.h"
15 #include "base/stl_util.h" 16 #include "base/stl_util.h"
16 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
17 #include "base/threading/worker_pool.h" 18 #include "base/threading/worker_pool.h"
18 #include "base/time/time.h" 19 #include "base/time/time.h"
19 #include "base/values.h" 20 #include "base/values.h"
20 #include "net/base/hash_value.h" 21 #include "net/base/hash_value.h"
21 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
22 #include "net/cert/cert_trust_anchor_provider.h" 23 #include "net/cert/cert_trust_anchor_provider.h"
23 #include "net/cert/cert_verify_proc.h" 24 #include "net/cert/cert_verify_proc.h"
24 #include "net/cert/crl_set.h" 25 #include "net/cert/crl_set.h"
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 212
212 213
213 // CertVerifierWorker runs on a worker thread and takes care of the blocking 214 // CertVerifierWorker runs on a worker thread and takes care of the blocking
214 // process of performing the certificate verification. Deletes itself 215 // process of performing the certificate verification. Deletes itself
215 // eventually if Start() succeeds. 216 // eventually if Start() succeeds.
216 class CertVerifierWorker { 217 class CertVerifierWorker {
217 public: 218 public:
218 CertVerifierWorker(CertVerifyProc* verify_proc, 219 CertVerifierWorker(CertVerifyProc* verify_proc,
219 X509Certificate* cert, 220 X509Certificate* cert,
220 const std::string& hostname, 221 const std::string& hostname,
222 const std::string& ocsp_response,
221 int flags, 223 int flags,
222 CRLSet* crl_set, 224 CRLSet* crl_set,
223 const CertificateList& additional_trust_anchors, 225 const CertificateList& additional_trust_anchors,
224 MultiThreadedCertVerifier* cert_verifier) 226 MultiThreadedCertVerifier* cert_verifier)
225 : verify_proc_(verify_proc), 227 : verify_proc_(verify_proc),
226 cert_(cert), 228 cert_(cert),
227 hostname_(hostname), 229 hostname_(hostname),
230 ocsp_response_(ocsp_response),
228 flags_(flags), 231 flags_(flags),
229 crl_set_(crl_set), 232 crl_set_(crl_set),
230 additional_trust_anchors_(additional_trust_anchors), 233 additional_trust_anchors_(additional_trust_anchors),
231 origin_loop_(base::MessageLoop::current()), 234 origin_loop_(base::MessageLoop::current()),
232 cert_verifier_(cert_verifier), 235 cert_verifier_(cert_verifier),
233 canceled_(false), 236 canceled_(false),
234 error_(ERR_FAILED) { 237 error_(ERR_FAILED) {}
235 }
236 238
237 // Returns the certificate being verified. May only be called /before/ 239 // Returns the certificate being verified. May only be called /before/
238 // Start() is called. 240 // Start() is called.
239 X509Certificate* certificate() const { return cert_.get(); } 241 X509Certificate* certificate() const { return cert_.get(); }
240 242
241 bool Start() { 243 bool Start() {
242 DCHECK_EQ(base::MessageLoop::current(), origin_loop_); 244 DCHECK_EQ(base::MessageLoop::current(), origin_loop_);
243 245
244 return base::WorkerPool::PostTask( 246 return base::WorkerPool::PostTask(
245 FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)), 247 FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)),
246 true /* task is slow */); 248 true /* task is slow */);
247 } 249 }
248 250
249 // Cancel is called from the origin loop when the MultiThreadedCertVerifier is 251 // Cancel is called from the origin loop when the MultiThreadedCertVerifier is
250 // getting deleted. 252 // getting deleted.
251 void Cancel() { 253 void Cancel() {
252 DCHECK_EQ(base::MessageLoop::current(), origin_loop_); 254 DCHECK_EQ(base::MessageLoop::current(), origin_loop_);
253 base::AutoLock locked(lock_); 255 base::AutoLock locked(lock_);
254 canceled_ = true; 256 canceled_ = true;
255 } 257 }
256 258
257 private: 259 private:
258 void Run() { 260 void Run() {
259 // Runs on a worker thread. 261 // Runs on a worker thread.
260 error_ = verify_proc_->Verify(cert_.get(), 262 error_ = verify_proc_->Verify(cert_.get(), hostname_, ocsp_response_,
261 hostname_, 263 flags_, crl_set_.get(),
262 flags_, 264 additional_trust_anchors_, &verify_result_);
263 crl_set_.get(),
264 additional_trust_anchors_,
265 &verify_result_);
266 #if defined(USE_NSS_CERTS) || defined(OS_IOS) 265 #if defined(USE_NSS_CERTS) || defined(OS_IOS)
267 // Detach the thread from NSPR. 266 // Detach the thread from NSPR.
268 // Calling NSS functions attaches the thread to NSPR, which stores 267 // Calling NSS functions attaches the thread to NSPR, which stores
269 // the NSPR thread ID in thread-specific data. 268 // the NSPR thread ID in thread-specific data.
270 // The threads in our thread pool terminate after we have called 269 // The threads in our thread pool terminate after we have called
271 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets 270 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
272 // segfaults on shutdown when the threads' thread-specific data 271 // segfaults on shutdown when the threads' thread-specific data
273 // destructors run. 272 // destructors run.
274 PR_DetachThread(); 273 PR_DetachThread();
275 #endif 274 #endif
276 Finish(); 275 Finish();
277 } 276 }
278 277
279 // DoReply runs on the origin thread. 278 // DoReply runs on the origin thread.
280 void DoReply() { 279 void DoReply() {
281 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is 280 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is
282 // fixed. 281 // fixed.
283 tracked_objects::ScopedTracker tracking_profile( 282 tracked_objects::ScopedTracker tracking_profile(
284 FROM_HERE_WITH_EXPLICIT_FUNCTION("477117 CertVerifierWorker::DoReply")); 283 FROM_HERE_WITH_EXPLICIT_FUNCTION("477117 CertVerifierWorker::DoReply"));
285 DCHECK_EQ(base::MessageLoop::current(), origin_loop_); 284 DCHECK_EQ(base::MessageLoop::current(), origin_loop_);
286 { 285 {
287 // We lock here because the worker thread could still be in Finished, 286 // We lock here because the worker thread could still be in Finished,
288 // after the PostTask, but before unlocking |lock_|. If we do not lock in 287 // after the PostTask, but before unlocking |lock_|. If we do not lock in
289 // this case, we will end up deleting a locked Lock, which can lead to 288 // this case, we will end up deleting a locked Lock, which can lead to
290 // memory leaks or worse errors. 289 // memory leaks or worse errors.
291 base::AutoLock locked(lock_); 290 base::AutoLock locked(lock_);
292 if (!canceled_) { 291 if (!canceled_) {
293 cert_verifier_->HandleResult(cert_.get(), 292 cert_verifier_->HandleResult(cert_.get(), hostname_, ocsp_response_,
294 hostname_, 293 flags_, additional_trust_anchors_, error_,
295 flags_,
296 additional_trust_anchors_,
297 error_,
298 verify_result_); 294 verify_result_);
299 } 295 }
300 } 296 }
301 delete this; 297 delete this;
302 } 298 }
303 299
304 void Finish() { 300 void Finish() {
305 // Runs on the worker thread. 301 // Runs on the worker thread.
306 // We assume that the origin loop outlives the MultiThreadedCertVerifier. If 302 // We assume that the origin loop outlives the MultiThreadedCertVerifier. If
307 // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If 303 // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If
(...skipping 16 matching lines...) Expand all
324 } 320 }
325 } 321 }
326 322
327 if (canceled) 323 if (canceled)
328 delete this; 324 delete this;
329 } 325 }
330 326
331 scoped_refptr<CertVerifyProc> verify_proc_; 327 scoped_refptr<CertVerifyProc> verify_proc_;
332 scoped_refptr<X509Certificate> cert_; 328 scoped_refptr<X509Certificate> cert_;
333 const std::string hostname_; 329 const std::string hostname_;
330 const std::string ocsp_response_;
334 const int flags_; 331 const int flags_;
335 scoped_refptr<CRLSet> crl_set_; 332 scoped_refptr<CRLSet> crl_set_;
336 const CertificateList additional_trust_anchors_; 333 const CertificateList additional_trust_anchors_;
337 base::MessageLoop* const origin_loop_; 334 base::MessageLoop* const origin_loop_;
338 MultiThreadedCertVerifier* const cert_verifier_; 335 MultiThreadedCertVerifier* const cert_verifier_;
339 336
340 // lock_ protects canceled_. 337 // lock_ protects canceled_.
341 base::Lock lock_; 338 base::Lock lock_;
342 339
343 // If canceled_ is true, 340 // If canceled_ is true,
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 450 }
454 451
455 void MultiThreadedCertVerifier::SetCertTrustAnchorProvider( 452 void MultiThreadedCertVerifier::SetCertTrustAnchorProvider(
456 CertTrustAnchorProvider* trust_anchor_provider) { 453 CertTrustAnchorProvider* trust_anchor_provider) {
457 DCHECK(CalledOnValidThread()); 454 DCHECK(CalledOnValidThread());
458 trust_anchor_provider_ = trust_anchor_provider; 455 trust_anchor_provider_ = trust_anchor_provider;
459 } 456 }
460 457
461 int MultiThreadedCertVerifier::Verify(X509Certificate* cert, 458 int MultiThreadedCertVerifier::Verify(X509Certificate* cert,
462 const std::string& hostname, 459 const std::string& hostname,
460 const std::string& ocsp_response,
463 int flags, 461 int flags,
464 CRLSet* crl_set, 462 CRLSet* crl_set,
465 CertVerifyResult* verify_result, 463 CertVerifyResult* verify_result,
466 const CompletionCallback& callback, 464 const CompletionCallback& callback,
467 RequestHandle* out_req, 465 RequestHandle* out_req,
468 const BoundNetLog& net_log) { 466 const BoundNetLog& net_log) {
469 DCHECK(CalledOnValidThread()); 467 DCHECK(CalledOnValidThread());
470 468
471 if (callback.is_null() || !verify_result || hostname.empty()) { 469 if (callback.is_null() || !verify_result || hostname.empty()) {
472 *out_req = NULL; 470 *out_req = NULL;
473 return ERR_INVALID_ARGUMENT; 471 return ERR_INVALID_ARGUMENT;
474 } 472 }
475 473
476 requests_++; 474 requests_++;
477 475
478 const CertificateList empty_cert_list; 476 const CertificateList empty_cert_list;
479 const CertificateList& additional_trust_anchors = 477 const CertificateList& additional_trust_anchors =
480 trust_anchor_provider_ ? 478 trust_anchor_provider_ ?
481 trust_anchor_provider_->GetAdditionalTrustAnchors() : empty_cert_list; 479 trust_anchor_provider_->GetAdditionalTrustAnchors() : empty_cert_list;
482 480
483 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), 481 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), hostname,
484 hostname, flags, additional_trust_anchors); 482 ocsp_response, flags, additional_trust_anchors);
485 const CertVerifierCache::value_type* cached_entry = 483 const CertVerifierCache::value_type* cached_entry =
486 cache_.Get(key, CacheValidityPeriod(base::Time::Now())); 484 cache_.Get(key, CacheValidityPeriod(base::Time::Now()));
487 if (cached_entry) { 485 if (cached_entry) {
488 ++cache_hits_; 486 ++cache_hits_;
489 *out_req = NULL; 487 *out_req = NULL;
490 *verify_result = cached_entry->result; 488 *verify_result = cached_entry->result;
491 return cached_entry->error; 489 return cached_entry->error;
492 } 490 }
493 491
494 // No cache hit. See if an identical request is currently in flight. 492 // No cache hit. See if an identical request is currently in flight.
495 CertVerifierJob* job; 493 CertVerifierJob* job;
496 std::map<RequestParams, CertVerifierJob*>::const_iterator j; 494 std::map<RequestParams, CertVerifierJob*>::const_iterator j;
497 j = inflight_.find(key); 495 j = inflight_.find(key);
498 if (j != inflight_.end()) { 496 if (j != inflight_.end()) {
499 // An identical request is in flight already. We'll just attach our 497 // An identical request is in flight already. We'll just attach our
500 // callback. 498 // callback.
501 inflight_joins_++; 499 inflight_joins_++;
502 job = j->second; 500 job = j->second;
503 } else { 501 } else {
504 // Need to make a new request. 502 // Need to make a new request.
505 CertVerifierWorker* worker = 503 CertVerifierWorker* worker = new CertVerifierWorker(
506 new CertVerifierWorker(verify_proc_.get(), 504 verify_proc_.get(), cert, hostname, ocsp_response, flags, crl_set,
507 cert, 505 additional_trust_anchors, this);
508 hostname,
509 flags,
510 crl_set,
511 additional_trust_anchors,
512 this);
513 job = new CertVerifierJob( 506 job = new CertVerifierJob(
514 worker, 507 worker,
515 BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB)); 508 BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB));
516 if (!worker->Start()) { 509 if (!worker->Start()) {
517 delete job; 510 delete job;
518 delete worker; 511 delete worker;
519 *out_req = NULL; 512 *out_req = NULL;
520 // TODO(wtc): log to the NetLog. 513 // TODO(wtc): log to the NetLog.
521 LOG(ERROR) << "CertVerifierWorker couldn't be started."; 514 LOG(ERROR) << "CertVerifierWorker couldn't be started.";
522 return ERR_INSUFFICIENT_RESOURCES; // Just a guess. 515 return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
(...skipping 11 matching lines...) Expand all
534 *out_req = request; 527 *out_req = request;
535 return ERR_IO_PENDING; 528 return ERR_IO_PENDING;
536 } 529 }
537 530
538 void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) { 531 void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) {
539 DCHECK(CalledOnValidThread()); 532 DCHECK(CalledOnValidThread());
540 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 533 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
541 request->Cancel(); 534 request->Cancel();
542 } 535 }
543 536
537 bool MultiThreadedCertVerifier::SupportsOCSPStapling() {
538 return verify_proc_->SupportsOCSPStapling();
539 }
540
544 MultiThreadedCertVerifier::RequestParams::RequestParams( 541 MultiThreadedCertVerifier::RequestParams::RequestParams(
545 const SHA1HashValue& cert_fingerprint_arg, 542 const SHA1HashValue& cert_fingerprint_arg,
546 const SHA1HashValue& ca_fingerprint_arg, 543 const SHA1HashValue& ca_fingerprint_arg,
547 const std::string& hostname_arg, 544 const std::string& hostname_arg,
545 const std::string& ocsp_response_arg,
548 int flags_arg, 546 int flags_arg,
549 const CertificateList& additional_trust_anchors) 547 const CertificateList& additional_trust_anchors)
550 : hostname(hostname_arg), 548 : hostname(hostname_arg), flags(flags_arg) {
551 flags(flags_arg) { 549 hash_values.reserve(3 + additional_trust_anchors.size());
552 hash_values.reserve(2 + additional_trust_anchors.size()); 550 SHA1HashValue ocsp_hash;
551 base::SHA1HashBytes(
552 reinterpret_cast<const unsigned char*>(ocsp_response_arg.data()),
553 ocsp_response_arg.size(), ocsp_hash.data);
554 hash_values.push_back(ocsp_hash);
553 hash_values.push_back(cert_fingerprint_arg); 555 hash_values.push_back(cert_fingerprint_arg);
554 hash_values.push_back(ca_fingerprint_arg); 556 hash_values.push_back(ca_fingerprint_arg);
555 for (size_t i = 0; i < additional_trust_anchors.size(); ++i) 557 for (size_t i = 0; i < additional_trust_anchors.size(); ++i)
556 hash_values.push_back(additional_trust_anchors[i]->fingerprint()); 558 hash_values.push_back(additional_trust_anchors[i]->fingerprint());
557 } 559 }
558 560
559 MultiThreadedCertVerifier::RequestParams::~RequestParams() {} 561 MultiThreadedCertVerifier::RequestParams::~RequestParams() {}
560 562
561 bool MultiThreadedCertVerifier::RequestParams::operator<( 563 bool MultiThreadedCertVerifier::RequestParams::operator<(
562 const RequestParams& other) const { 564 const RequestParams& other) const {
563 // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and 565 // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|,
564 // |hostname| under assumption that integer comparisons are faster than 566 // |hostname|, and |ocsp_response|, under assumption that integer comparisons
565 // memory and string comparisons. 567 // are faster than memory and string comparisons.
566 if (flags != other.flags) 568 if (flags != other.flags)
567 return flags < other.flags; 569 return flags < other.flags;
568 if (hostname != other.hostname) 570 if (hostname != other.hostname)
569 return hostname < other.hostname; 571 return hostname < other.hostname;
570 return std::lexicographical_compare( 572 return std::lexicographical_compare(
571 hash_values.begin(), hash_values.end(), other.hash_values.begin(), 573 hash_values.begin(), hash_values.end(), other.hash_values.begin(),
572 other.hash_values.end(), SHA1HashValueLessThan()); 574 other.hash_values.end(), SHA1HashValueLessThan());
573 } 575 }
574 576
575 // HandleResult is called by CertVerifierWorker on the origin message loop. 577 // HandleResult is called by CertVerifierWorker on the origin message loop.
576 // It deletes CertVerifierJob. 578 // It deletes CertVerifierJob.
577 void MultiThreadedCertVerifier::HandleResult( 579 void MultiThreadedCertVerifier::HandleResult(
578 X509Certificate* cert, 580 X509Certificate* cert,
579 const std::string& hostname, 581 const std::string& hostname,
582 const std::string& ocsp_response,
580 int flags, 583 int flags,
581 const CertificateList& additional_trust_anchors, 584 const CertificateList& additional_trust_anchors,
582 int error, 585 int error,
583 const CertVerifyResult& verify_result) { 586 const CertVerifyResult& verify_result) {
584 DCHECK(CalledOnValidThread()); 587 DCHECK(CalledOnValidThread());
585 588
586 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), 589 const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), hostname,
587 hostname, flags, additional_trust_anchors); 590 ocsp_response, flags, additional_trust_anchors);
588 591
589 CachedResult cached_result; 592 CachedResult cached_result;
590 cached_result.error = error; 593 cached_result.error = error;
591 cached_result.result = verify_result; 594 cached_result.result = verify_result;
592 base::Time now = base::Time::Now(); 595 base::Time now = base::Time::Now();
593 cache_.Put( 596 cache_.Put(
594 key, cached_result, CacheValidityPeriod(now), 597 key, cached_result, CacheValidityPeriod(now),
595 CacheValidityPeriod(now, now + base::TimeDelta::FromSeconds(kTTLSecs))); 598 CacheValidityPeriod(now, now + base::TimeDelta::FromSeconds(kTTLSecs)));
596 599
597 std::map<RequestParams, CertVerifierJob*>::iterator j; 600 std::map<RequestParams, CertVerifierJob*>::iterator j;
(...skipping 16 matching lines...) Expand all
614 617
615 void MultiThreadedCertVerifier::OnCACertChanged( 618 void MultiThreadedCertVerifier::OnCACertChanged(
616 const X509Certificate* cert) { 619 const X509Certificate* cert) {
617 DCHECK(CalledOnValidThread()); 620 DCHECK(CalledOnValidThread());
618 621
619 ClearCache(); 622 ClearCache();
620 } 623 }
621 624
622 } // namespace net 625 } // namespace net
623 626
OLDNEW
« no previous file with comments | « net/cert/multi_threaded_cert_verifier.h ('k') | net/cert/multi_threaded_cert_verifier_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698