cert_verifier.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_verifier.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/compiler_specific.h" 8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/lock.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/message_loop.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/stl_util-inl.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/worker_pool.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/x509_certificate.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(USE_NSS) 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <private/pprthred.h> // PR_DetachThread 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//////////////////////////////////////////////////////////////////////////// 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Life of a request: 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CertVerifier CertVerifierJob CertVerifierWorker Request 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | (origin loop) (worker loop) 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Verify() 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->-------------------<creates> 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->----<creates> 3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->---------------------------------------------------<creates> 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->--------------------Start 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | | 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | PostTask 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | <starts verifying> 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->-----AddRequest | 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Finish 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// PostTask 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// DoReply 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |----<-----------------------| 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HandleResult 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |---->-----HandleResult 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// | 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// |------>-----------------------------------Post 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// On a cache hit, CertVerifier::Verify() returns synchronously without 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// posting a task to a worker thread. 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The number of CachedCertVerifyResult objects that we'll cache. 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const unsigned kMaxCacheEntries = 256; 6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The number of seconds for which we'll cache a cache entry. 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const unsigned kTTLSecs = 1800; // 30 minutes. 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace { 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass DefaultTimeService : public CertVerifier::TimeService { 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CertVerifier::TimeService methods: 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual base::Time Now() { return base::Time::Now(); } 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCachedCertVerifyResult::CachedCertVerifyResult() : error(ERR_FAILED) { 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCachedCertVerifyResult::~CachedCertVerifyResult() {} 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool CachedCertVerifyResult::HasExpired(const base::Time current_time) const { 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return current_time >= expiry; 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Represents the output and result callback of a request. 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierRequest { 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierRequest(CompletionCallback* callback, 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult* verify_result) 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : callback_(callback), 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verify_result_(verify_result) { 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Ensures that the result callback will never be made. 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Cancel() { 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback_ = NULL; 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verify_result_ = NULL; 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Copies the contents of |verify_result| to the caller's 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CertVerifyResult and calls the callback. 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Post(const CachedCertVerifyResult& verify_result) { 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (callback_) { 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *verify_result_ = verify_result.result; 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback_->Run(verify_result.error); 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete this; 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback_; 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult* verify_result_; 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CertVerifierWorker runs on a worker thread and takes care of the blocking 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// process of performing the certificate verification. Deletes itself 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// eventually if Start() succeeds. 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierWorker { 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker(X509Certificate* cert, 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : cert_(cert), 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hostname_(hostname), 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags_(flags), 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen origin_loop_(MessageLoop::current()), 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_(cert_verifier), 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled_(false), 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_(ERR_FAILED) { 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool Start() { 13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return WorkerPool::PostTask( 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen true /* task is slow */); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cancel is called from the origin loop when the CertVerifier is getting 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // deleted. 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Cancel() { 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutoLock locked(lock_); 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled_ = true; 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Run() { 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Runs on a worker thread. 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = cert_->Verify(hostname_, flags_, &verify_result_); 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_NSS) 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Detach the thread from NSPR. 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Calling NSS functions attaches the thread to NSPR, which stores 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the NSPR thread ID in thread-specific data. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The threads in our thread pool terminate after we have called 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // segfaults on shutdown when the threads' thread-specific data 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // destructors run. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_DetachThread(); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Finish(); 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // DoReply runs on the origin thread. 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void DoReply() { 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen { 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We lock here because the worker thread could still be in Finished, 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // after the PostTask, but before unlocking |lock_|. If we do not lock in 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // this case, we will end up deleting a locked Lock, which can lead to 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // memory leaks or worse errors. 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutoLock locked(lock_); 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!canceled_) { 17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_->HandleResult(cert_, hostname_, flags_, 18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_, verify_result_); 18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete this; 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Finish() { 18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Runs on the worker thread. 18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We assume that the origin loop outlives the CertVerifier. If the 18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CertVerifier is deleted, it will call Cancel on us. If it does so 19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // before the Acquire, we'll delete ourselves and return. If it's trying to 19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // do so concurrently, then it'll block on the lock and we'll call PostTask 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // while the CertVerifier (and therefore the MessageLoop) is still alive. 19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If it does so after this function, we assume that the MessageLoop will 19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // process pending tasks. In which case we'll notice the |canceled_| flag 19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // in DoReply. 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool canceled; 19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen { 19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutoLock locked(lock_); 20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled = canceled_; 20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!canceled) { 20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen origin_loop_->PostTask( 20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply)); 20421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (canceled) 20821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete this; 20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<X509Certificate> cert_; 21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string hostname_; 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const int flags_; 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen MessageLoop* const origin_loop_; 21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* const cert_verifier_; 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // lock_ protects canceled_. 21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Lock lock_; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If canceled_ is true, 22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // * origin_loop_ cannot be accessed by the worker thread, 22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // * cert_verifier_ cannot be accessed by any thread. 22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool canceled_; 22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int error_; 22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult verify_result_; 22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); 22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It 23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// lives only on the CertVerifier's origin message loop. 23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierJob { 23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) { 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ~CertVerifierJob() { 23921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (worker_) 24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen worker_->Cancel(); 24121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void AddRequest(CertVerifierRequest* request) { 24421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_.push_back(request); 24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void HandleResult(const CachedCertVerifyResult& verify_result) { 24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen worker_ = NULL; 24921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PostAll(verify_result); 25021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void PostAll(const CachedCertVerifyResult& verify_result) { 25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<CertVerifierRequest*> requests; 25521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_.swap(requests); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::vector<CertVerifierRequest*>::iterator 25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen i = requests.begin(); i != requests.end(); i++) { 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (*i)->Post(verify_result); 26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Post() causes the CertVerifierRequest to delete itself. 26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<CertVerifierRequest*> requests_; 26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker* worker_; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier() 27021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : time_service_(new DefaultTimeService), 27121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_(0), 27221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_(0), 27321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_(0) { 27421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 27521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier(TimeService* time_service) 27721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : time_service_(time_service), 27821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_(0), 27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_(0), 28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_(0) { 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCertVerifier::~CertVerifier() { 28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen STLDeleteValues(&inflight_); 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint CertVerifier::Verify(X509Certificate* cert, 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& hostname, 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags, 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CertVerifyResult* verify_result, 29121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback, 29221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen RequestHandle* out_req) { 29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!callback || !verify_result || hostname.empty()) { 29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ERR_INVALID_ARGUMENT; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_++; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const RequestParams key = {cert->fingerprint(), hostname, flags}; 30321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // First check the cache. 30421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CachedCertVerifyResult>::iterator i; 30521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen i = cache_.find(key); 30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (i != cache_.end()) { 30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!i->second.HasExpired(time_service_->Now())) { 30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_++; 30921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *verify_result = i->second.result; 31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return i->second.error; 31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cache entry has expired. 31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(i); 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // No cache hit. See if an identical request is currently in flight. 31821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierJob* job; 31921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CertVerifierJob*>::const_iterator j; 32021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen j = inflight_.find(key); 32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (j != inflight_.end()) { 32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // An identical request is in flight already. We'll just attach our 32321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // callback. 32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_++; 32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job = j->second; 32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Need to make a new request. 32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, 32921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this); 33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job = new CertVerifierJob(worker); 33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_.insert(std::make_pair(key, job)); 33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!worker->Start()) { 33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_.erase(key); 33421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete job; 33521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete worker; 33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ERR_FAILED; // TODO(wtc): Log an error message. 33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierRequest* request = 34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new CertVerifierRequest(callback, verify_result); 34321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job->AddRequest(request); 34421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = request; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::CancelRequest(RequestHandle req) { 34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen request->Cancel(); 35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 35421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::ClearCache() { 35521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 35621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.clear(); 35821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Leaves inflight_ alone. 35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsensize_t CertVerifier::GetCacheSize() const { 36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return cache_.size(); 36521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 36621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 36721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HandleResult is called by CertVerifierWorker on the origin message loop. 36821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// It deletes CertVerifierJob. 36921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::HandleResult(X509Certificate* cert, 37021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 37121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 37221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int error, 37321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const CertVerifyResult& verify_result) { 37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const base::Time current_time(time_service_->Now()); 37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CachedCertVerifyResult cached_result; 37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.error = error; 38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.result = verify_result; 38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen uint32 ttl = kTTLSecs; 38221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl); 38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const RequestParams key = {cert->fingerprint(), hostname, flags}; 38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_GE(kMaxCacheEntries, 1u); 38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_LE(cache_.size(), kMaxCacheEntries); 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cache_.size() == kMaxCacheEntries) { 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Need to remove an element of the cache. 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur; 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (i = cache_.begin(); i != cache_.end(); ) { 39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur = i++; 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cur->second.HasExpired(current_time)) 39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(cur); 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cache_.size() == kMaxCacheEntries) { 39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If we didn't clear out any expired entries, we just remove the first 39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // element. Crummy but simple. 40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(cache_.begin()); 40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.insert(std::make_pair(key, cached_result)); 40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CertVerifierJob*>::iterator j; 40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen j = inflight_.find(key); 40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (j == inflight_.end()) { 40821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen NOTREACHED(); 40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierJob* job = j->second; 41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_.erase(j); 41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job->HandleResult(cached_result); 41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete job; 41621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen///////////////////////////////////////////////////////////////////// 41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 42021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::SingleRequestCertVerifier( 42121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : cert_verifier_(cert_verifier), 42321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_(NULL), 42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_(NULL), 42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST( 42621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) { 42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(cert_verifier_ != NULL); 42821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::~SingleRequestCertVerifier() { 43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cur_request_) { 43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_->CancelRequest(cur_request_); 43321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = NULL; 43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 43521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 43621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SingleRequestCertVerifier::Verify(X509Certificate* cert, 43821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 43921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 44021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult* verify_result, 44121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback) { 44221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Should not be already in use. 44321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!cur_request_ && !cur_request_callback_); 44421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Do a synchronous verification. 44621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!callback) 44721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return cert->Verify(hostname, flags, verify_result); 44821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 44921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier::RequestHandle request = NULL; 45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We need to be notified of completion before |callback| is called, so that 45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // we can clear out |cur_request_*|. 45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int rv = cert_verifier_->Verify( 45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert, hostname, flags, verify_result, &callback_, &request); 45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv == ERR_IO_PENDING) { 45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cleared in OnVerifyCompletion(). 45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = request; 45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_ = callback; 46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 46221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return rv; 46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SingleRequestCertVerifier::OnVerifyCompletion(int result) { 46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(cur_request_ && cur_request_callback_); 46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback = cur_request_callback_; 46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 47021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Clear the outstanding request information. 47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = NULL; 47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_ = NULL; 47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Call the user's original callback. 47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback->Run(result); 47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); 48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 482