1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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" 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/message_loop.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/stl_util-inl.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/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 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool canceled() const { return !callback_; } 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback_; 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult* verify_result_; 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CertVerifierWorker runs on a worker thread and takes care of the blocking 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// process of performing the certificate verification. Deletes itself 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// eventually if Start() succeeds. 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierWorker { 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker(X509Certificate* cert, 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : cert_(cert), 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hostname_(hostname), 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags_(flags), 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen origin_loop_(MessageLoop::current()), 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_(cert_verifier), 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled_(false), 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_(ERR_FAILED) { 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool Start() { 13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return base::WorkerPool::PostTask( 1423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), 1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen true /* task is slow */); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cancel is called from the origin loop when the CertVerifier is getting 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // deleted. 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Cancel() { 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock locked(lock_); 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled_ = true; 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Run() { 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Runs on a worker thread. 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_ = cert_->Verify(hostname_, flags_, &verify_result_); 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_NSS) 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Detach the thread from NSPR. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Calling NSS functions attaches the thread to NSPR, which stores 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the NSPR thread ID in thread-specific data. 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The threads in our thread pool terminate after we have called 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // segfaults on shutdown when the threads' thread-specific data 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // destructors run. 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PR_DetachThread(); 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Finish(); 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // DoReply runs on the origin thread. 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void DoReply() { 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(MessageLoop::current(), origin_loop_); 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen { 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We lock here because the worker thread could still be in Finished, 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // after the PostTask, but before unlocking |lock_|. If we do not lock in 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // this case, we will end up deleting a locked Lock, which can lead to 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // memory leaks or worse errors. 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock locked(lock_); 18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!canceled_) { 18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_->HandleResult(cert_, hostname_, flags_, 18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen error_, verify_result_); 18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete this; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void Finish() { 18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Runs on the worker thread. 19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We assume that the origin loop outlives the CertVerifier. If the 19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CertVerifier is deleted, it will call Cancel on us. If it does so 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // before the Acquire, we'll delete ourselves and return. If it's trying to 19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // do so concurrently, then it'll block on the lock and we'll call PostTask 19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // while the CertVerifier (and therefore the MessageLoop) is still alive. 19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If it does so after this function, we assume that the MessageLoop will 19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // process pending tasks. In which case we'll notice the |canceled_| flag 19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // in DoReply. 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool canceled; 20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen { 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock locked(lock_); 20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen canceled = canceled_; 20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!canceled) { 20421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen origin_loop_->PostTask( 20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply)); 20621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 20721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (canceled) 21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete this; 21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<X509Certificate> cert_; 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string hostname_; 21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const int flags_; 21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen MessageLoop* const origin_loop_; 21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* const cert_verifier_; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // lock_ protects canceled_. 22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock lock_; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If canceled_ is true, 22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // * origin_loop_ cannot be accessed by the worker thread, 22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // * cert_verifier_ cannot be accessed by any thread. 22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool canceled_; 22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int error_; 22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult verify_result_; 22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); 23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It 23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// lives only on the CertVerifier's origin message loop. 23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass CertVerifierJob { 23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 23721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) { 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ~CertVerifierJob() { 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (worker_) { 24221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen worker_->Cancel(); 24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DeleteAllCanceled(); 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void AddRequest(CertVerifierRequest* request) { 24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_.push_back(request); 24921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void HandleResult(const CachedCertVerifyResult& verify_result) { 25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen worker_ = NULL; 25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PostAll(verify_result); 25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 25721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void PostAll(const CachedCertVerifyResult& verify_result) { 25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<CertVerifierRequest*> requests; 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_.swap(requests); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::vector<CertVerifierRequest*>::iterator 26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen i = requests.begin(); i != requests.end(); i++) { 26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (*i)->Post(verify_result); 26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Post() causes the CertVerifierRequest to delete itself. 26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void DeleteAllCanceled() { 26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::vector<CertVerifierRequest*>::iterator 27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen i = requests_.begin(); i != requests_.end(); i++) { 27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if ((*i)->canceled()) { 27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete *i; 27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(DFATAL) << "CertVerifierRequest leaked!"; 27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<CertVerifierRequest*> requests_; 28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker* worker_; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier() 28521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : time_service_(new DefaultTimeService), 28621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_(0), 28721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_(0), 28821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_(0) { 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CertDatabase::AddObserver(this); 29021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 29121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 29221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenCertVerifier::CertVerifier(TimeService* time_service) 29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : time_service_(time_service), 29421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_(0), 29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_(0), 29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_(0) { 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CertDatabase::AddObserver(this); 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCertVerifier::~CertVerifier() { 30121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen STLDeleteValues(&inflight_); 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CertDatabase::RemoveObserver(this); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint CertVerifier::Verify(X509Certificate* cert, 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& hostname, 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags, 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CertVerifyResult* verify_result, 31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback, 31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen RequestHandle* out_req) { 31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!callback || !verify_result || hostname.empty()) { 31521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ERR_INVALID_ARGUMENT; 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen requests_++; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const RequestParams key = {cert->fingerprint(), hostname, flags}; 32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // First check the cache. 32321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CachedCertVerifyResult>::iterator i; 32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen i = cache_.find(key); 32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (i != cache_.end()) { 32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!i->second.HasExpired(time_service_->Now())) { 32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_hits_++; 32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 32921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *verify_result = i->second.result; 33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return i->second.error; 33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cache entry has expired. 33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(i); 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // No cache hit. See if an identical request is currently in flight. 33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierJob* job; 33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CertVerifierJob*>::const_iterator j; 33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen j = inflight_.find(key); 34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (j != inflight_.end()) { 34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // An identical request is in flight already. We'll just attach our 34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // callback. 34321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_joins_++; 34421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job = j->second; 34521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } else { 34621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Need to make a new request. 34721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, 34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this); 34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job = new CertVerifierJob(worker); 35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!worker->Start()) { 35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete job; 35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete worker; 35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = NULL; 35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(wtc): log to the NetLog. 35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "CertVerifierWorker couldn't be started."; 35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_INSUFFICIENT_RESOURCES; // Just a guess. 35721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen inflight_.insert(std::make_pair(key, job)); 35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierRequest* request = 36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new CertVerifierRequest(callback, verify_result); 36321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job->AddRequest(request); 36421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *out_req = request; 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::CancelRequest(RequestHandle req) { 36921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 37021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 37121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen request->Cancel(); 37221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 37321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 37421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::ClearCache() { 37521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.clear(); 37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Leaves inflight_ alone. 37921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 38021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsensize_t CertVerifier::GetCacheSize() const { 38221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return cache_.size(); 38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 38721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HandleResult is called by CertVerifierWorker on the origin message loop. 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// It deletes CertVerifierJob. 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid CertVerifier::HandleResult(X509Certificate* cert, 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int error, 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const CertVerifyResult& verify_result) { 39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(CalledOnValidThread()); 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const base::Time current_time(time_service_->Now()); 39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CachedCertVerifyResult cached_result; 39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.error = error; 40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.result = verify_result; 40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen uint32 ttl = kTTLSecs; 40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl); 40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const RequestParams key = {cert->fingerprint(), hostname, flags}; 40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_GE(kMaxCacheEntries, 1u); 40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_LE(cache_.size(), kMaxCacheEntries); 40821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cache_.size() == kMaxCacheEntries) { 40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Need to remove an element of the cache. 41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur; 41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (i = cache_.begin(); i != cache_.end(); ) { 41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur = i++; 41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cur->second.HasExpired(current_time)) 41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(cur); 41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 41621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cache_.size() == kMaxCacheEntries) { 41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If we didn't clear out any expired entries, we just remove the first 41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // element. Crummy but simple. 42021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.erase(cache_.begin()); 42121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 42321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cache_.insert(std::make_pair(key, cached_result)); 42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::map<RequestParams, CertVerifierJob*>::iterator j; 42621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen j = inflight_.find(key); 42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (j == inflight_.end()) { 42821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen NOTREACHED(); 42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifierJob* job = j->second; 43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen inflight_.erase(j); 43321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen job->HandleResult(cached_result); 43521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen delete job; 43621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CertVerifier::OnCertTrustChanged(const X509Certificate* cert) { 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(CalledOnValidThread()); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ClearCache(); 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 44421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen///////////////////////////////////////////////////////////////////// 44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 44621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::SingleRequestCertVerifier( 44721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 44821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : cert_verifier_(cert_verifier), 44921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_(NULL), 45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_(NULL), 45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST( 45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) { 45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(cert_verifier_ != NULL); 45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSingleRequestCertVerifier::~SingleRequestCertVerifier() { 45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (cur_request_) { 45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_->CancelRequest(cur_request_); 45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = NULL; 46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 46221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SingleRequestCertVerifier::Verify(X509Certificate* cert, 46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hostname, 46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int flags, 46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifyResult* verify_result, 46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback) { 46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Should not be already in use. 46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!cur_request_ && !cur_request_callback_); 47021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Do a synchronous verification. 47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!callback) 47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return cert->Verify(hostname, flags, verify_result); 47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier::RequestHandle request = NULL; 47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We need to be notified of completion before |callback| is called, so that 47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // we can clear out |cur_request_*|. 47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int rv = cert_verifier_->Verify( 48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert, hostname, flags, verify_result, &callback_, &request); 48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv == ERR_IO_PENDING) { 48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cleared in OnVerifyCompletion(). 48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = request; 48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_ = callback; 48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 48721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 48821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return rv; 48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SingleRequestCertVerifier::OnVerifyCompletion(int result) { 49221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(cur_request_ && cur_request_callback_); 49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CompletionCallback* callback = cur_request_callback_; 49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Clear the outstanding request information. 49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_ = NULL; 49821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cur_request_callback_ = NULL; 49921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Call the user's original callback. 50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen callback->Run(result); 50221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 50321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 50521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 50621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); 507