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

Side by Side Diff: net/base/origin_bound_cert_service.temp.cc

Issue 7565023: Gave the GetOriginBoundCertificate an asynchronous interface because certificate (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/cert_verifier.h" 5 #include "net/base/origin_bound_cert_service.h"
6
7 #include <limits>
6 8
7 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/rand_util.h"
9 #include "base/stl_util.h" 15 #include "base/stl_util.h"
10 #include "base/synchronization/lock.h"
11 #include "base/threading/worker_pool.h" 16 #include "base/threading/worker_pool.h"
17 #include "crypto/rsa_private_key.h"
12 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/origin_bound_cert_store.h"
13 #include "net/base/x509_certificate.h" 20 #include "net/base/x509_certificate.h"
14 21
15 #if defined(USE_NSS) 22 #if defined(USE_NSS)
16 #include <private/pprthred.h> // PR_DetachThread 23 #include <private/pprthred.h> // PR_DetachThread
17 #endif 24 #endif
18 25
19 namespace net { 26 namespace net {
20 27
21 ////////////////////////////////////////////////////////////////////////////
22
23 // Life of a request:
24 //
25 // CertVerifier CertVerifierJob CertVerifierWorker Request
26 // | (origin loop) (worker loop)
27 // |
28 // Verify()
29 // |---->-------------------<creates>
30 // |
31 // |---->----<creates>
32 // |
33 // |---->---------------------------------------------------<creates>
34 // |
35 // |---->--------------------Start
36 // | |
37 // | PostTask
38 // |
39 // | <starts verifying>
40 // |---->-----AddRequest |
41 // |
42 // |
43 // |
44 // Finish
45 // |
46 // PostTask
47 //
48 // |
49 // DoReply
50 // |----<-----------------------|
51 // HandleResult
52 // |
53 // |---->-----HandleResult
54 // |
55 // |------>-----------------------------------Post
56 //
57 //
58 //
59 // On a cache hit, CertVerifier::Verify() returns synchronously without
60 // posting a task to a worker thread.
61
62 // The number of CachedCertVerifyResult objects that we'll cache.
63 static const unsigned kMaxCacheEntries = 256;
64
65 // The number of seconds for which we'll cache a cache entry.
66 static const unsigned kTTLSecs = 1800; // 30 minutes.
67
68 namespace { 28 namespace {
69 29
70 class DefaultTimeService : public CertVerifier::TimeService { 30 const int kKeySizeInBits = 1024;
71 public: 31 const int kValidityPeriodInDays = 365;
72 // CertVerifier::TimeService methods:
73 virtual base::Time Now() { return base::Time::Now(); }
74 };
75 32
76 } // namespace 33 } // namespace
77 34
78 CachedCertVerifyResult::CachedCertVerifyResult() : error(ERR_FAILED) {
79 }
80
81 CachedCertVerifyResult::~CachedCertVerifyResult() {}
82
83 bool CachedCertVerifyResult::HasExpired(const base::Time current_time) const {
84 return current_time >= expiry;
85 }
86
87 // Represents the output and result callback of a request. 35 // Represents the output and result callback of a request.
88 class CertVerifierRequest { 36 class OriginBoundCertServiceRequest {
89 public: 37 public:
90 CertVerifierRequest(CompletionCallback* callback, 38 OriginBoundCertServiceRequest(CompletionCallback* callback,
91 CertVerifyResult* verify_result) 39 std::string* private_key,
40 std::string* cert)
92 : callback_(callback), 41 : callback_(callback),
93 verify_result_(verify_result) { 42 private_key_(private_key),
43 cert_(cert) {
94 } 44 }
95 45
96 // Ensures that the result callback will never be made. 46 // Ensures that the result callback will never be made.
97 void Cancel() { 47 void Cancel() {
98 callback_ = NULL; 48 callback_ = NULL;
99 verify_result_ = NULL; 49 private_key_ = NULL;
50 cert_ = NULL;
100 } 51 }
101 52
102 // Copies the contents of |verify_result| to the caller's 53 // Copies the contents of |private_key| and |cert| to the caller's fields
103 // CertVerifyResult and calls the callback. 54 // and calls the callback.
104 void Post(const CachedCertVerifyResult& verify_result) { 55 void Post(int error,
56 const std::string& private_key,
57 const std::string& cert) {
105 if (callback_) { 58 if (callback_) {
106 *verify_result_ = verify_result.result; 59 *private_key_ = private_key;
107 callback_->Run(verify_result.error); 60 *cert_ = cert;
61 callback_->Run(error);
108 } 62 }
109 delete this; 63 delete this;
110 } 64 }
111 65
112 bool canceled() const { return !callback_; } 66 bool canceled() const { return !callback_; }
113 67
114 private: 68 private:
115 CompletionCallback* callback_; 69 CompletionCallback* callback_;
116 CertVerifyResult* verify_result_; 70 std::string* private_key_;
71 std::string* cert_;
117 }; 72 };
118 73
119 74 // OriginBoundCertServiceWorker runs on a worker thread and takes care of the
120 // CertVerifierWorker runs on a worker thread and takes care of the blocking 75 // blocking process of performing key generation. Deletes itself eventually
121 // process of performing the certificate verification. Deletes itself 76 // if Start() succeeds.
122 // eventually if Start() succeeds. 77 class OriginBoundCertServiceWorker {
123 class CertVerifierWorker {
124 public: 78 public:
125 CertVerifierWorker(X509Certificate* cert, 79 OriginBoundCertServiceWorker(
126 const std::string& hostname, 80 const std::string& origin,
127 int flags, 81 OriginBoundCertService* origin_bound_cert_service)
128 CertVerifier* cert_verifier) 82 : origin_(origin),
129 : cert_(cert),
130 hostname_(hostname),
131 flags_(flags),
132 origin_loop_(MessageLoop::current()), 83 origin_loop_(MessageLoop::current()),
133 cert_verifier_(cert_verifier), 84 origin_bound_cert_service_(origin_bound_cert_service),
134 canceled_(false), 85 canceled_(false),
135 error_(ERR_FAILED) { 86 error_(ERR_FAILED) {
136 } 87 }
137 88
138 bool Start() { 89 bool Start() {
139 DCHECK_EQ(MessageLoop::current(), origin_loop_); 90 DCHECK_EQ(MessageLoop::current(), origin_loop_);
140 91
141 return base::WorkerPool::PostTask( 92 return base::WorkerPool::PostTask(
142 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), 93 FROM_HERE,
94 NewRunnableMethod(this, &OriginBoundCertServiceWorker::Run),
143 true /* task is slow */); 95 true /* task is slow */);
144 } 96 }
145 97
146 // Cancel is called from the origin loop when the CertVerifier is getting 98 // Cancel is called from the origin loop when the OriginBoundCertService is
147 // deleted. 99 // getting deleted.
148 void Cancel() { 100 void Cancel() {
149 DCHECK_EQ(MessageLoop::current(), origin_loop_); 101 DCHECK_EQ(MessageLoop::current(), origin_loop_);
150 base::AutoLock locked(lock_); 102 base::AutoLock locked(lock_);
151 canceled_ = true; 103 canceled_ = true;
152 } 104 }
153 105
154 private: 106 private:
155 void Run() { 107 void Run() {
108 uint32 serial_number = base::RandInt(0, std::numeric_limits<int>::max());
156 // Runs on a worker thread. 109 // Runs on a worker thread.
157 error_ = cert_->Verify(hostname_, flags_, &verify_result_); 110 error_ = origin_bound_cert_service_->GenerateCert(origin_,
111 serial_number,
112 &private_key_,
113 &cert_);
158 #if defined(USE_NSS) 114 #if defined(USE_NSS)
159 // Detach the thread from NSPR. 115 // Detach the thread from NSPR.
160 // Calling NSS functions attaches the thread to NSPR, which stores 116 // Calling NSS functions attaches the thread to NSPR, which stores
161 // the NSPR thread ID in thread-specific data. 117 // the NSPR thread ID in thread-specific data.
162 // The threads in our thread pool terminate after we have called 118 // The threads in our thread pool terminate after we have called
163 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets 119 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
164 // segfaults on shutdown when the threads' thread-specific data 120 // segfaults on shutdown when the threads' thread-specific data
165 // destructors run. 121 // destructors run.
166 PR_DetachThread(); 122 PR_DetachThread();
167 #endif 123 #endif
168 Finish(); 124 Finish();
169 } 125 }
170 126
171 // DoReply runs on the origin thread. 127 // DoReply runs on the origin thread.
172 void DoReply() { 128 void DoReply() {
173 DCHECK_EQ(MessageLoop::current(), origin_loop_); 129 DCHECK_EQ(MessageLoop::current(), origin_loop_);
174 { 130 {
175 // We lock here because the worker thread could still be in Finished, 131 // We lock here because the worker thread could still be in Finished,
176 // after the PostTask, but before unlocking |lock_|. If we do not lock in 132 // after the PostTask, but before unlocking |lock_|. If we do not lock in
177 // this case, we will end up deleting a locked Lock, which can lead to 133 // this case, we will end up deleting a locked Lock, which can lead to
178 // memory leaks or worse errors. 134 // memory leaks or worse errors.
179 base::AutoLock locked(lock_); 135 base::AutoLock locked(lock_);
180 if (!canceled_) { 136 if (!canceled_) {
181 cert_verifier_->HandleResult(cert_, hostname_, flags_, 137 origin_bound_cert_service_->HandleResult(
182 error_, verify_result_); 138 origin_, error_, private_key_, cert_);
183 } 139 }
184 } 140 }
185 delete this; 141 delete this;
186 } 142 }
187 143
188 void Finish() { 144 void Finish() {
189 // Runs on the worker thread. 145 // Runs on the worker thread.
190 // We assume that the origin loop outlives the CertVerifier. If the 146 // We assume that the origin loop outlives the OriginBoundCertService. If
191 // CertVerifier is deleted, it will call Cancel on us. If it does so 147 // the OriginBoundCertService is deleted, it will call Cancel on us. If it
192 // before the Acquire, we'll delete ourselves and return. If it's trying to 148 // does so before the Acquire, we'll delete ourselves and return. If it's
193 // do so concurrently, then it'll block on the lock and we'll call PostTask 149 // trying to do so concurrently, then it'll block on the lock and we'll
194 // while the CertVerifier (and therefore the MessageLoop) is still alive. 150 // call PostTask while the OriginBoundCertService (and therefore the
195 // If it does so after this function, we assume that the MessageLoop will 151 // MessageLoop) is still alive. If it does so after this function, we
196 // process pending tasks. In which case we'll notice the |canceled_| flag 152 // assume that the MessageLoop will process pending tasks. In which case
197 // in DoReply. 153 // we'll notice the |canceled_| flag in DoReply.
198 154
199 bool canceled; 155 bool canceled;
200 { 156 {
201 base::AutoLock locked(lock_); 157 base::AutoLock locked(lock_);
202 canceled = canceled_; 158 canceled = canceled_;
203 if (!canceled) { 159 if (!canceled) {
204 origin_loop_->PostTask( 160 origin_loop_->PostTask(
205 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply)); 161 FROM_HERE,
162 NewRunnableMethod(this, &OriginBoundCertServiceWorker::DoReply));
206 } 163 }
207 } 164 }
208
209 if (canceled) 165 if (canceled)
210 delete this; 166 delete this;
211 } 167 }
212 168
213 scoped_refptr<X509Certificate> cert_; 169 const std::string origin_;
214 const std::string hostname_;
215 const int flags_;
216 MessageLoop* const origin_loop_; 170 MessageLoop* const origin_loop_;
217 CertVerifier* const cert_verifier_; 171 OriginBoundCertService* const origin_bound_cert_service_;
218 172
219 // lock_ protects canceled_. 173 // lock_ protects canceled_.
220 base::Lock lock_; 174 base::Lock lock_;
221 175
222 // If canceled_ is true, 176 // If canceled_ is true,
223 // * origin_loop_ cannot be accessed by the worker thread, 177 // * origin_loop_ cannot be accessed by the worker thread,
224 // * cert_verifier_ cannot be accessed by any thread. 178 // * origin_bound_cert_service_ cannot be accessed by any thread.
225 bool canceled_; 179 bool canceled_;
226 180
227 int error_; 181 int error_;
228 CertVerifyResult verify_result_; 182 std::string private_key_;
183 std::string cert_;
229 184
230 DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); 185 DISALLOW_COPY_AND_ASSIGN(OriginBoundCertServiceWorker);
231 }; 186 };
232 187
233 // A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It 188 // An OriginBoundCertServiceJob is a one-to-one counterpart of an
234 // lives only on the CertVerifier's origin message loop. 189 // OriginBoundCertServiceWorker. It lives only on the OriginBoundCertService's
235 class CertVerifierJob { 190 // origin message loop.
191 class OriginBoundCertServiceJob {
236 public: 192 public:
237 explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) { 193 explicit OriginBoundCertServiceJob(OriginBoundCertServiceWorker* worker)
194 : worker_(worker) {
238 } 195 }
239 196
240 ~CertVerifierJob() { 197 ~OriginBoundCertServiceJob() {
241 if (worker_) { 198 if (worker_) {
242 worker_->Cancel(); 199 worker_->Cancel();
243 DeleteAllCanceled(); 200 DeleteAllCanceled();
244 } 201 }
245 } 202 }
246 203
247 void AddRequest(CertVerifierRequest* request) { 204 void AddRequest(OriginBoundCertServiceRequest* request) {
248 requests_.push_back(request); 205 requests_.push_back(request);
249 } 206 }
250 207
251 void HandleResult(const CachedCertVerifyResult& verify_result) { 208 void HandleResult(int error,
209 const std::string& private_key,
210 const std::string& cert) {
252 worker_ = NULL; 211 worker_ = NULL;
253 PostAll(verify_result); 212 PostAll(error, private_key, cert);
254 } 213 }
255 214
256 private: 215 private:
257 void PostAll(const CachedCertVerifyResult& verify_result) { 216 void PostAll(int error,
258 std::vector<CertVerifierRequest*> requests; 217 const std::string& private_key,
218 const std::string& cert) {
219 std::vector<OriginBoundCertServiceRequest*> requests;
259 requests_.swap(requests); 220 requests_.swap(requests);
260 221
261 for (std::vector<CertVerifierRequest*>::iterator 222 for (std::vector<OriginBoundCertServiceRequest*>::iterator
262 i = requests.begin(); i != requests.end(); i++) { 223 i = requests.begin(); i != requests.end(); i++) {
263 (*i)->Post(verify_result); 224 (*i)->Post(error, private_key, cert);
264 // Post() causes the CertVerifierRequest to delete itself. 225 // Post() causes the OriginBoundCertServiceRequest to delete itself.
265 } 226 }
266 } 227 }
267 228
268 void DeleteAllCanceled() { 229 void DeleteAllCanceled() {
269 for (std::vector<CertVerifierRequest*>::iterator 230 for (std::vector<OriginBoundCertServiceRequest*>::iterator
270 i = requests_.begin(); i != requests_.end(); i++) { 231 i = requests_.begin(); i != requests_.end(); i++) {
271 if ((*i)->canceled()) { 232 if ((*i)->canceled()) {
272 delete *i; 233 delete *i;
273 } else { 234 } else {
274 LOG(DFATAL) << "CertVerifierRequest leaked!"; 235 LOG(DFATAL) << "OriginBoundCertServiceRequest leaked!";
275 } 236 }
276 } 237 }
277 } 238 }
278 239
279 std::vector<CertVerifierRequest*> requests_; 240 std::vector<OriginBoundCertServiceRequest*> requests_;
280 CertVerifierWorker* worker_; 241 OriginBoundCertServiceWorker* worker_;
281 }; 242 };
282 243
283 244 OriginBoundCertService::OriginBoundCertService(
284 CertVerifier::CertVerifier() 245 OriginBoundCertStore* origin_bound_cert_store)
285 : time_service_(new DefaultTimeService), 246 : origin_bound_cert_store_(origin_bound_cert_store),
286 requests_(0), 247 requests_(0),
287 cache_hits_(0), 248 cache_hits_(0),
288 inflight_joins_(0) { 249 inflight_joins_(0) {}
289 CertDatabase::AddObserver(this); 250
251 OriginBoundCertService::~OriginBoundCertService() {
252 STLDeleteValues(&inflight_);
290 } 253 }
291 254
292 CertVerifier::CertVerifier(TimeService* time_service) 255 int OriginBoundCertService::GetOriginBoundCert(const std::string& origin,
293 : time_service_(time_service), 256 std::string* private_key,
294 requests_(0), 257 std::string* cert,
295 cache_hits_(0), 258 CompletionCallback* callback,
296 inflight_joins_(0) { 259 RequestHandle* out_req) {
297 CertDatabase::AddObserver(this);
298 }
299 260
300 CertVerifier::~CertVerifier() {
301 STLDeleteValues(&inflight_);
302
303 CertDatabase::RemoveObserver(this);
304 }
305
306 int CertVerifier::Verify(X509Certificate* cert,
307 const std::string& hostname,
308 int flags,
309 CertVerifyResult* verify_result,
310 CompletionCallback* callback,
311 RequestHandle* out_req) {
312 DCHECK(CalledOnValidThread()); 261 DCHECK(CalledOnValidThread());
313 262
314 if (!callback || !verify_result || hostname.empty()) { 263 if (!callback || !private_key || !cert || origin.empty()) {
315 *out_req = NULL; 264 *out_req = NULL;
316 return ERR_INVALID_ARGUMENT; 265 return ERR_INVALID_ARGUMENT;
317 } 266 }
318 267
319 requests_++; 268 requests_++;
320 269
321 const RequestParams key = {cert->fingerprint(), hostname, flags}; 270 // Check if an origin bound cert already exists for this origin.
322 // First check the cache. 271 if (origin_bound_cert_store_->GetOriginBoundCert(origin,
323 std::map<RequestParams, CachedCertVerifyResult>::iterator i; 272 private_key,
324 i = cache_.find(key); 273 cert)) {
325 if (i != cache_.end()) { 274 cache_hits_++;
326 if (!i->second.HasExpired(time_service_->Now())) { 275 *out_req = NULL;
327 cache_hits_++; 276 return OK;
328 *out_req = NULL;
329 *verify_result = i->second.result;
330 return i->second.error;
331 }
332 // Cache entry has expired.
333 cache_.erase(i);
334 } 277 }
335 278
336 // No cache hit. See if an identical request is currently in flight. 279 // No cache hit. See if an identical request is currently in flight.
337 CertVerifierJob* job; 280 OriginBoundCertServiceJob* job;
338 std::map<RequestParams, CertVerifierJob*>::const_iterator j; 281 std::map<std::string, OriginBoundCertServiceJob*>::const_iterator j;
339 j = inflight_.find(key); 282 j = inflight_.find(origin);
340 if (j != inflight_.end()) { 283 if (j != inflight_.end()) {
341 // An identical request is in flight already. We'll just attach our 284 // An identical request is in flight already. We'll just attach our
342 // callback. 285 // callback.
343 inflight_joins_++; 286 inflight_joins_++;
344 job = j->second; 287 job = j->second;
345 } else { 288 } else {
346 // Need to make a new request. 289 // Need to make a new request.
347 CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, 290 OriginBoundCertServiceWorker* worker =
348 this); 291 new OriginBoundCertServiceWorker(origin, this);
349 job = new CertVerifierJob(worker); 292 job = new OriginBoundCertServiceJob(worker);
350 if (!worker->Start()) { 293 if (!worker->Start()) {
351 delete job; 294 delete job;
352 delete worker; 295 delete worker;
353 *out_req = NULL; 296 *out_req = NULL;
354 // TODO(wtc): log to the NetLog. 297 // TODO(rkn): Log to the NetLog.
355 LOG(ERROR) << "CertVerifierWorker couldn't be started."; 298 LOG(ERROR) << "OriginBoundCertServiceWorker couldn't be started.";
356 return ERR_INSUFFICIENT_RESOURCES; // Just a guess. 299 return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
357 } 300 }
358 inflight_.insert(std::make_pair(key, job)); 301 inflight_[origin] = job;
359 } 302 }
360 303
361 CertVerifierRequest* request = 304 OriginBoundCertServiceRequest* request =
362 new CertVerifierRequest(callback, verify_result); 305 new OriginBoundCertServiceRequest(callback, private_key, cert);
363 job->AddRequest(request); 306 job->AddRequest(request);
364 *out_req = request; 307 *out_req = request;
365 return ERR_IO_PENDING; 308 return ERR_IO_PENDING;
366 } 309 }
367 310
368 void CertVerifier::CancelRequest(RequestHandle req) { 311 int OriginBoundCertService::GenerateCert(const std::string& origin,
312 uint32 serial_number,
313 std::string* private_key,
314 std::string* cert) {
315 std::string subject = "CN=OBC";
316 scoped_ptr<crypto::RSAPrivateKey> key(
317 crypto::RSAPrivateKey::Create(kKeySizeInBits));
318 if (!key.get()) {
319 LOG(WARNING) << "Unable to create key pair for client";
320 return ERR_FAILED;
321 }
322
323 scoped_refptr<X509Certificate> x509_cert = X509Certificate::CreateSelfSigned(
324 key.get(),
325 subject,
326 serial_number,
327 base::TimeDelta::FromDays(kValidityPeriodInDays));
328 if (!x509_cert) {
329 LOG(WARNING) << "Unable to create x509 cert for client";
330 return ERR_FAILED;
331 }
332
333 std::vector<uint8> private_key_info;
334 if (!key->ExportPrivateKey(&private_key_info)) {
335 LOG(WARNING) << "Unable to export private key";
336 return ERR_FAILED;
337 }
338 // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
339 // std::string* to prevent this copying.
340 std::string key_out(private_key_info.begin(), private_key_info.end());
341
342 std::string der_cert;
343 if (!x509_cert->GetDEREncoded(&der_cert)) {
344 LOG(WARNING) << "Unable to get DER-enconded cert";
345 return ERR_FAILED;
346 }
347
348 private_key->swap(key_out);
349 cert->swap(der_cert);
350 return OK;
351 }
352
353 void OriginBoundCertService::CancelRequest(RequestHandle req) {
369 DCHECK(CalledOnValidThread()); 354 DCHECK(CalledOnValidThread());
370 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 355 OriginBoundCertServiceRequest* request =
356 reinterpret_cast<OriginBoundCertServiceRequest*>(req);
371 request->Cancel(); 357 request->Cancel();
372 } 358 }
373 359
374 void CertVerifier::ClearCache() { 360 // HandleResult is called by OriginBoundCertServiceWorker on the origin message
361 // loop. It deletes OriginBoundCertServiceJob.
362 void OriginBoundCertService::HandleResult(const std::string& origin,
363 int error,
364 const std::string& private_key,
365 const std::string& cert) {
375 DCHECK(CalledOnValidThread()); 366 DCHECK(CalledOnValidThread());
376 367
377 cache_.clear(); 368 origin_bound_cert_store_->SetOriginBoundCert(origin, private_key, cert);
378 // Leaves inflight_ alone.
379 }
380 369
381 size_t CertVerifier::GetCacheSize() const { 370 std::map<std::string, OriginBoundCertServiceJob*>::iterator j;
382 DCHECK(CalledOnValidThread()); 371 j = inflight_.find(origin);
383
384 return cache_.size();
385 }
386
387 // HandleResult is called by CertVerifierWorker on the origin message loop.
388 // It deletes CertVerifierJob.
389 void CertVerifier::HandleResult(X509Certificate* cert,
390 const std::string& hostname,
391 int flags,
392 int error,
393 const CertVerifyResult& verify_result) {
394 DCHECK(CalledOnValidThread());
395
396 const base::Time current_time(time_service_->Now());
397
398 CachedCertVerifyResult cached_result;
399 cached_result.error = error;
400 cached_result.result = verify_result;
401 uint32 ttl = kTTLSecs;
402 cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl);
403
404 const RequestParams key = {cert->fingerprint(), hostname, flags};
405
406 DCHECK_GE(kMaxCacheEntries, 1u);
407 DCHECK_LE(cache_.size(), kMaxCacheEntries);
408 if (cache_.size() == kMaxCacheEntries) {
409 // Need to remove an element of the cache.
410 std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur;
411 for (i = cache_.begin(); i != cache_.end(); ) {
412 cur = i++;
413 if (cur->second.HasExpired(current_time))
414 cache_.erase(cur);
415 }
416 }
417 if (cache_.size() == kMaxCacheEntries) {
418 // If we didn't clear out any expired entries, we just remove the first
419 // element. Crummy but simple.
420 cache_.erase(cache_.begin());
421 }
422
423 cache_.insert(std::make_pair(key, cached_result));
424
425 std::map<RequestParams, CertVerifierJob*>::iterator j;
426 j = inflight_.find(key);
427 if (j == inflight_.end()) { 372 if (j == inflight_.end()) {
428 NOTREACHED(); 373 NOTREACHED();
429 return; 374 return;
430 } 375 }
431 CertVerifierJob* job = j->second; 376 OriginBoundCertServiceJob* job = j->second;
432 inflight_.erase(j); 377 inflight_.erase(j);
433 378
434 job->HandleResult(cached_result); 379 job->HandleResult(error, private_key, cert);
435 delete job; 380 delete job;
436 } 381 }
437 382
438 void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) { 383 int OriginBoundCertService::GetCertCount() {
439 DCHECK(CalledOnValidThread()); 384 return origin_bound_cert_store_->GetCertCount();
440
441 ClearCache();
442 }
443
444 /////////////////////////////////////////////////////////////////////
445
446 SingleRequestCertVerifier::SingleRequestCertVerifier(
447 CertVerifier* cert_verifier)
448 : cert_verifier_(cert_verifier),
449 cur_request_(NULL),
450 cur_request_callback_(NULL),
451 ALLOW_THIS_IN_INITIALIZER_LIST(
452 callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) {
453 DCHECK(cert_verifier_ != NULL);
454 }
455
456 SingleRequestCertVerifier::~SingleRequestCertVerifier() {
457 if (cur_request_) {
458 cert_verifier_->CancelRequest(cur_request_);
459 cur_request_ = NULL;
460 }
461 }
462
463 int SingleRequestCertVerifier::Verify(X509Certificate* cert,
464 const std::string& hostname,
465 int flags,
466 CertVerifyResult* verify_result,
467 CompletionCallback* callback) {
468 // Should not be already in use.
469 DCHECK(!cur_request_ && !cur_request_callback_);
470
471 // Do a synchronous verification.
472 if (!callback)
473 return cert->Verify(hostname, flags, verify_result);
474
475 CertVerifier::RequestHandle request = NULL;
476
477 // We need to be notified of completion before |callback| is called, so that
478 // we can clear out |cur_request_*|.
479 int rv = cert_verifier_->Verify(
480 cert, hostname, flags, verify_result, &callback_, &request);
481
482 if (rv == ERR_IO_PENDING) {
483 // Cleared in OnVerifyCompletion().
484 cur_request_ = request;
485 cur_request_callback_ = callback;
486 }
487
488 return rv;
489 }
490
491 void SingleRequestCertVerifier::OnVerifyCompletion(int result) {
492 DCHECK(cur_request_ && cur_request_callback_);
493
494 CompletionCallback* callback = cur_request_callback_;
495
496 // Clear the outstanding request information.
497 cur_request_ = NULL;
498 cur_request_callback_ = NULL;
499
500 // Call the user's original callback.
501 callback->Run(result);
502 } 385 }
503 386
504 } // namespace net 387 } // namespace net
505 388
506 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); 389 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::OriginBoundCertServiceWorker);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698