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

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.
agl 2011/08/08 22:36:27 Should this file be included in the CL?
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.
wtc 2011/08/09 00:43:34 Perhaps "fields" should be changed to "output argu
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), 83 serial_number_(base::RandInt(0, std::numeric_limits<int>::max())),
130 hostname_(hostname),
131 flags_(flags),
132 origin_loop_(MessageLoop::current()), 84 origin_loop_(MessageLoop::current()),
133 cert_verifier_(cert_verifier), 85 origin_bound_cert_service_(origin_bound_cert_service),
134 canceled_(false), 86 canceled_(false),
135 error_(ERR_FAILED) { 87 error_(ERR_FAILED) {
136 } 88 }
137 89
138 bool Start() { 90 bool Start() {
139 DCHECK_EQ(MessageLoop::current(), origin_loop_); 91 DCHECK_EQ(MessageLoop::current(), origin_loop_);
140 92
141 return base::WorkerPool::PostTask( 93 return base::WorkerPool::PostTask(
142 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), 94 FROM_HERE,
95 NewRunnableMethod(this, &OriginBoundCertServiceWorker::Run),
143 true /* task is slow */); 96 true /* task is slow */);
144 } 97 }
145 98
146 // Cancel is called from the origin loop when the CertVerifier is getting 99 // Cancel is called from the origin loop when the OriginBoundCertService is
147 // deleted. 100 // getting deleted.
148 void Cancel() { 101 void Cancel() {
149 DCHECK_EQ(MessageLoop::current(), origin_loop_); 102 DCHECK_EQ(MessageLoop::current(), origin_loop_);
150 base::AutoLock locked(lock_); 103 base::AutoLock locked(lock_);
151 canceled_ = true; 104 canceled_ = true;
152 } 105 }
153 106
154 private: 107 private:
155 void Run() { 108 void Run() {
156 // Runs on a worker thread. 109 // Runs on a worker thread.
157 error_ = cert_->Verify(hostname_, flags_, &verify_result_); 110 error_ = OriginBoundCertService::GenerateCert(origin_,
111 serial_number_,
112 &private_key_,
113 &cert_);
wtc 2011/08/09 00:43:34 Fix the indentation of the function arguments. se
rkn 2011/08/09 03:25:38 Isn't the problem that the entire "Run()" function
wtc 2011/08/09 18:09:47 You are right. I am confused. It may be worthwhi
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_);
wtc 2011/08/09 00:43:34 Nit: I think it's better to format this as: orig
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_; 170 uint32 serial_number_;
215 const int flags_;
216 MessageLoop* const origin_loop_; 171 MessageLoop* const origin_loop_;
217 CertVerifier* const cert_verifier_; 172 OriginBoundCertService* const origin_bound_cert_service_;
218 173
219 // lock_ protects canceled_. 174 // lock_ protects canceled_.
220 base::Lock lock_; 175 base::Lock lock_;
221 176
222 // If canceled_ is true, 177 // If canceled_ is true,
223 // * origin_loop_ cannot be accessed by the worker thread, 178 // * origin_loop_ cannot be accessed by the worker thread,
224 // * cert_verifier_ cannot be accessed by any thread. 179 // * origin_bound_cert_service_ cannot be accessed by any thread.
225 bool canceled_; 180 bool canceled_;
226 181
227 int error_; 182 int error_;
228 CertVerifyResult verify_result_; 183 std::string private_key_;
184 std::string cert_;
229 185
230 DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); 186 DISALLOW_COPY_AND_ASSIGN(OriginBoundCertServiceWorker);
231 }; 187 };
232 188
233 // A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It 189 // An OriginBoundCertServiceJob is a one-to-one counterpart of an
234 // lives only on the CertVerifier's origin message loop. 190 // OriginBoundCertServiceWorker. It lives only on the OriginBoundCertService's
235 class CertVerifierJob { 191 // origin message loop.
192 class OriginBoundCertServiceJob {
236 public: 193 public:
237 explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) { 194 explicit OriginBoundCertServiceJob(OriginBoundCertServiceWorker* worker)
195 : worker_(worker) {
238 } 196 }
239 197
240 ~CertVerifierJob() { 198 ~OriginBoundCertServiceJob() {
241 if (worker_) { 199 if (worker_) {
242 worker_->Cancel(); 200 worker_->Cancel();
243 DeleteAllCanceled(); 201 DeleteAllCanceled();
244 } 202 }
245 } 203 }
246 204
247 void AddRequest(CertVerifierRequest* request) { 205 void AddRequest(OriginBoundCertServiceRequest* request) {
248 requests_.push_back(request); 206 requests_.push_back(request);
249 } 207 }
250 208
251 void HandleResult(const CachedCertVerifyResult& verify_result) { 209 void HandleResult(int error,
210 const std::string& private_key,
211 const std::string& cert) {
252 worker_ = NULL; 212 worker_ = NULL;
253 PostAll(verify_result); 213 PostAll(error, private_key, cert);
254 } 214 }
255 215
256 private: 216 private:
257 void PostAll(const CachedCertVerifyResult& verify_result) { 217 void PostAll(int error,
258 std::vector<CertVerifierRequest*> requests; 218 const std::string& private_key,
219 const std::string& cert) {
220 std::vector<OriginBoundCertServiceRequest*> requests;
259 requests_.swap(requests); 221 requests_.swap(requests);
260 222
261 for (std::vector<CertVerifierRequest*>::iterator 223 for (std::vector<OriginBoundCertServiceRequest*>::iterator
262 i = requests.begin(); i != requests.end(); i++) { 224 i = requests.begin(); i != requests.end(); i++) {
263 (*i)->Post(verify_result); 225 (*i)->Post(error, private_key, cert);
264 // Post() causes the CertVerifierRequest to delete itself. 226 // Post() causes the OriginBoundCertServiceRequest to delete itself.
265 } 227 }
266 } 228 }
267 229
268 void DeleteAllCanceled() { 230 void DeleteAllCanceled() {
269 for (std::vector<CertVerifierRequest*>::iterator 231 for (std::vector<OriginBoundCertServiceRequest*>::iterator
270 i = requests_.begin(); i != requests_.end(); i++) { 232 i = requests_.begin(); i != requests_.end(); i++) {
271 if ((*i)->canceled()) { 233 if ((*i)->canceled()) {
272 delete *i; 234 delete *i;
273 } else { 235 } else {
274 LOG(DFATAL) << "CertVerifierRequest leaked!"; 236 LOG(DFATAL) << "OriginBoundCertServiceRequest leaked!";
275 } 237 }
276 } 238 }
277 } 239 }
278 240
279 std::vector<CertVerifierRequest*> requests_; 241 std::vector<OriginBoundCertServiceRequest*> requests_;
280 CertVerifierWorker* worker_; 242 OriginBoundCertServiceWorker* worker_;
281 }; 243 };
282 244
283 245 OriginBoundCertService::OriginBoundCertService(
284 CertVerifier::CertVerifier() 246 OriginBoundCertStore* origin_bound_cert_store)
285 : time_service_(new DefaultTimeService), 247 : origin_bound_cert_store_(origin_bound_cert_store),
286 requests_(0), 248 requests_(0),
287 cache_hits_(0), 249 cache_hits_(0),
288 inflight_joins_(0) { 250 inflight_joins_(0) {}
289 CertDatabase::AddObserver(this); 251
252 OriginBoundCertService::~OriginBoundCertService() {
253 STLDeleteValues(&inflight_);
290 } 254 }
291 255
292 CertVerifier::CertVerifier(TimeService* time_service) 256 int OriginBoundCertService::GetOriginBoundCert(const std::string& origin,
293 : time_service_(time_service), 257 std::string* private_key,
294 requests_(0), 258 std::string* cert,
295 cache_hits_(0), 259 CompletionCallback* callback,
296 inflight_joins_(0) { 260 RequestHandle* out_req) {
297 CertDatabase::AddObserver(this);
298 }
299 261
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()); 262 DCHECK(CalledOnValidThread());
313 263
314 if (!callback || !verify_result || hostname.empty()) { 264 if (!callback || !private_key || !cert || origin.empty()) {
315 *out_req = NULL; 265 *out_req = NULL;
316 return ERR_INVALID_ARGUMENT; 266 return ERR_INVALID_ARGUMENT;
317 } 267 }
318 268
319 requests_++; 269 requests_++;
320 270
321 const RequestParams key = {cert->fingerprint(), hostname, flags}; 271 // Check if an origin bound cert already exists for this origin.
322 // First check the cache. 272 if (origin_bound_cert_store_->GetOriginBoundCert(origin,
323 std::map<RequestParams, CachedCertVerifyResult>::iterator i; 273 private_key,
324 i = cache_.find(key); 274 cert)) {
325 if (i != cache_.end()) { 275 cache_hits_++;
326 if (!i->second.HasExpired(time_service_->Now())) { 276 *out_req = NULL;
327 cache_hits_++; 277 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 } 278 }
335 279
336 // No cache hit. See if an identical request is currently in flight. 280 // No cache hit. See if an identical request is currently in flight.
337 CertVerifierJob* job; 281 OriginBoundCertServiceJob* job;
338 std::map<RequestParams, CertVerifierJob*>::const_iterator j; 282 std::map<std::string, OriginBoundCertServiceJob*>::const_iterator j;
339 j = inflight_.find(key); 283 j = inflight_.find(origin);
340 if (j != inflight_.end()) { 284 if (j != inflight_.end()) {
341 // An identical request is in flight already. We'll just attach our 285 // An identical request is in flight already. We'll just attach our
342 // callback. 286 // callback.
343 inflight_joins_++; 287 inflight_joins_++;
344 job = j->second; 288 job = j->second;
345 } else { 289 } else {
346 // Need to make a new request. 290 // Need to make a new request.
347 CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, 291 OriginBoundCertServiceWorker* worker =
348 this); 292 new OriginBoundCertServiceWorker(origin, this);
349 job = new CertVerifierJob(worker); 293 job = new OriginBoundCertServiceJob(worker);
350 if (!worker->Start()) { 294 if (!worker->Start()) {
351 delete job; 295 delete job;
352 delete worker; 296 delete worker;
353 *out_req = NULL; 297 *out_req = NULL;
354 // TODO(wtc): log to the NetLog. 298 // TODO(rkn): Log to the NetLog.
355 LOG(ERROR) << "CertVerifierWorker couldn't be started."; 299 LOG(ERROR) << "OriginBoundCertServiceWorker couldn't be started.";
356 return ERR_INSUFFICIENT_RESOURCES; // Just a guess. 300 return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
357 } 301 }
358 inflight_.insert(std::make_pair(key, job)); 302 inflight_[origin] = job;
359 } 303 }
360 304
361 CertVerifierRequest* request = 305 OriginBoundCertServiceRequest* request =
362 new CertVerifierRequest(callback, verify_result); 306 new OriginBoundCertServiceRequest(callback, private_key, cert);
363 job->AddRequest(request); 307 job->AddRequest(request);
364 *out_req = request; 308 *out_req = request;
365 return ERR_IO_PENDING; 309 return ERR_IO_PENDING;
366 } 310 }
367 311
368 void CertVerifier::CancelRequest(RequestHandle req) { 312 // static
313 int OriginBoundCertService::GenerateCert(const std::string& origin,
314 uint32 serial_number,
315 std::string* private_key,
316 std::string* cert) {
317 std::string subject = "CN=OBC";
318 scoped_ptr<crypto::RSAPrivateKey> key(
319 crypto::RSAPrivateKey::Create(kKeySizeInBits));
320 if (!key.get()) {
321 LOG(WARNING) << "Unable to create key pair for client";
322 return ERR_KEY_PAIR_GENERATION_FAILED;
323 }
324
325 scoped_refptr<X509Certificate> x509_cert = X509Certificate::CreateSelfSigned(
326 key.get(),
327 subject,
328 serial_number,
329 base::TimeDelta::FromDays(kValidityPeriodInDays));
330 if (!x509_cert) {
331 LOG(WARNING) << "Unable to create x509 cert for client";
332 return ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
333 }
334
335 std::vector<uint8> private_key_info;
336 if (!key->ExportPrivateKey(&private_key_info)) {
337 LOG(WARNING) << "Unable to export private key";
338 return ERR_PRIVATE_KEY_EXPORT_FAILED;
339 }
340 // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
341 // std::string* to prevent this copying.
342 std::string key_out(private_key_info.begin(), private_key_info.end());
343
344 std::string der_cert;
345 if (!x509_cert->GetDEREncoded(&der_cert)) {
346 LOG(WARNING) << "Unable to get DER-encoded cert";
347 return ERR_GET_DER_CERT_FAILED;
348 }
349
350 private_key->swap(key_out);
351 cert->swap(der_cert);
352 return OK;
353 }
354
355 void OriginBoundCertService::CancelRequest(RequestHandle req) {
369 DCHECK(CalledOnValidThread()); 356 DCHECK(CalledOnValidThread());
370 CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req); 357 OriginBoundCertServiceRequest* request =
358 reinterpret_cast<OriginBoundCertServiceRequest*>(req);
371 request->Cancel(); 359 request->Cancel();
372 } 360 }
373 361
374 void CertVerifier::ClearCache() { 362 // HandleResult is called by OriginBoundCertServiceWorker on the origin message
363 // loop. It deletes OriginBoundCertServiceJob.
364 void OriginBoundCertService::HandleResult(const std::string& origin,
365 int error,
366 const std::string& private_key,
367 const std::string& cert) {
375 DCHECK(CalledOnValidThread()); 368 DCHECK(CalledOnValidThread());
376 369
377 cache_.clear(); 370 origin_bound_cert_store_->SetOriginBoundCert(origin, private_key, cert);
378 // Leaves inflight_ alone.
379 }
380 371
381 size_t CertVerifier::GetCacheSize() const { 372 std::map<std::string, OriginBoundCertServiceJob*>::iterator j;
382 DCHECK(CalledOnValidThread()); 373 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()) { 374 if (j == inflight_.end()) {
428 NOTREACHED(); 375 NOTREACHED();
429 return; 376 return;
430 } 377 }
431 CertVerifierJob* job = j->second; 378 OriginBoundCertServiceJob* job = j->second;
432 inflight_.erase(j); 379 inflight_.erase(j);
433 380
434 job->HandleResult(cached_result); 381 job->HandleResult(error, private_key, cert);
435 delete job; 382 delete job;
436 } 383 }
437 384
438 void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) { 385 int OriginBoundCertService::get_cert_count() {
439 DCHECK(CalledOnValidThread()); 386 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 } 387 }
503 388
504 } // namespace net 389 } // namespace net
505 390
506 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); 391 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::OriginBoundCertServiceWorker);
rkn 2011/08/08 22:08:32 The only requirement for this macro is that the Or
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698