blob: 6fb9180e875fbee9c293bf48638bba3371094f05 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/ssl/default_server_bound_cert_store.h"
6
7#include "base/bind.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +01008#include "base/message_loop/message_loop.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009#include "base/metrics/histogram.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010010#include "net/base/net_errors.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011
12namespace net {
13
14// --------------------------------------------------------------------------
15// Task
16class DefaultServerBoundCertStore::Task {
17 public:
18 virtual ~Task();
19
20 // Runs the task and invokes the client callback on the thread that
21 // originally constructed the task.
22 virtual void Run(DefaultServerBoundCertStore* store) = 0;
23
24 protected:
25 void InvokeCallback(base::Closure callback) const;
26};
27
28DefaultServerBoundCertStore::Task::~Task() {
29}
30
31void DefaultServerBoundCertStore::Task::InvokeCallback(
32 base::Closure callback) const {
33 if (!callback.is_null())
34 callback.Run();
35}
36
37// --------------------------------------------------------------------------
38// GetServerBoundCertTask
39class DefaultServerBoundCertStore::GetServerBoundCertTask
40 : public DefaultServerBoundCertStore::Task {
41 public:
42 GetServerBoundCertTask(const std::string& server_identifier,
43 const GetCertCallback& callback);
44 virtual ~GetServerBoundCertTask();
45 virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE;
46
47 private:
48 std::string server_identifier_;
49 GetCertCallback callback_;
50};
51
52DefaultServerBoundCertStore::GetServerBoundCertTask::GetServerBoundCertTask(
53 const std::string& server_identifier,
54 const GetCertCallback& callback)
55 : server_identifier_(server_identifier),
56 callback_(callback) {
57}
58
59DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() {
60}
61
62void DefaultServerBoundCertStore::GetServerBoundCertTask::Run(
63 DefaultServerBoundCertStore* store) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000064 base::Time expiration_time;
65 std::string private_key_result;
66 std::string cert_result;
Ben Murdochbb1529c2013-08-08 10:24:53 +010067 int err = store->GetServerBoundCert(
68 server_identifier_, &expiration_time, &private_key_result,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000069 &cert_result, GetCertCallback());
Ben Murdochbb1529c2013-08-08 10:24:53 +010070 DCHECK(err != ERR_IO_PENDING);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000071
Ben Murdochbb1529c2013-08-08 10:24:53 +010072 InvokeCallback(base::Bind(callback_, err, server_identifier_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000073 expiration_time, private_key_result, cert_result));
74}
75
76// --------------------------------------------------------------------------
77// SetServerBoundCertTask
78class DefaultServerBoundCertStore::SetServerBoundCertTask
79 : public DefaultServerBoundCertStore::Task {
80 public:
81 SetServerBoundCertTask(const std::string& server_identifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000082 base::Time creation_time,
83 base::Time expiration_time,
84 const std::string& private_key,
85 const std::string& cert);
86 virtual ~SetServerBoundCertTask();
87 virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE;
88
89 private:
90 std::string server_identifier_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000091 base::Time creation_time_;
92 base::Time expiration_time_;
93 std::string private_key_;
94 std::string cert_;
95};
96
97DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask(
98 const std::string& server_identifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000099 base::Time creation_time,
100 base::Time expiration_time,
101 const std::string& private_key,
102 const std::string& cert)
103 : server_identifier_(server_identifier),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000104 creation_time_(creation_time),
105 expiration_time_(expiration_time),
106 private_key_(private_key),
107 cert_(cert) {
108}
109
110DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() {
111}
112
113void DefaultServerBoundCertStore::SetServerBoundCertTask::Run(
114 DefaultServerBoundCertStore* store) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100115 store->SyncSetServerBoundCert(server_identifier_, creation_time_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000116 expiration_time_, private_key_, cert_);
117}
118
119// --------------------------------------------------------------------------
120// DeleteServerBoundCertTask
121class DefaultServerBoundCertStore::DeleteServerBoundCertTask
122 : public DefaultServerBoundCertStore::Task {
123 public:
124 DeleteServerBoundCertTask(const std::string& server_identifier,
125 const base::Closure& callback);
126 virtual ~DeleteServerBoundCertTask();
127 virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE;
128
129 private:
130 std::string server_identifier_;
131 base::Closure callback_;
132};
133
134DefaultServerBoundCertStore::DeleteServerBoundCertTask::
135 DeleteServerBoundCertTask(
136 const std::string& server_identifier,
137 const base::Closure& callback)
138 : server_identifier_(server_identifier),
139 callback_(callback) {
140}
141
142DefaultServerBoundCertStore::DeleteServerBoundCertTask::
143 ~DeleteServerBoundCertTask() {
144}
145
146void DefaultServerBoundCertStore::DeleteServerBoundCertTask::Run(
147 DefaultServerBoundCertStore* store) {
148 store->SyncDeleteServerBoundCert(server_identifier_);
149
150 InvokeCallback(callback_);
151}
152
153// --------------------------------------------------------------------------
154// DeleteAllCreatedBetweenTask
155class DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask
156 : public DefaultServerBoundCertStore::Task {
157 public:
158 DeleteAllCreatedBetweenTask(base::Time delete_begin,
159 base::Time delete_end,
160 const base::Closure& callback);
161 virtual ~DeleteAllCreatedBetweenTask();
162 virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE;
163
164 private:
165 base::Time delete_begin_;
166 base::Time delete_end_;
167 base::Closure callback_;
168};
169
170DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::
171 DeleteAllCreatedBetweenTask(
172 base::Time delete_begin,
173 base::Time delete_end,
174 const base::Closure& callback)
175 : delete_begin_(delete_begin),
176 delete_end_(delete_end),
177 callback_(callback) {
178}
179
180DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::
181 ~DeleteAllCreatedBetweenTask() {
182}
183
184void DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::Run(
185 DefaultServerBoundCertStore* store) {
186 store->SyncDeleteAllCreatedBetween(delete_begin_, delete_end_);
187
188 InvokeCallback(callback_);
189}
190
191// --------------------------------------------------------------------------
192// GetAllServerBoundCertsTask
193class DefaultServerBoundCertStore::GetAllServerBoundCertsTask
194 : public DefaultServerBoundCertStore::Task {
195 public:
196 explicit GetAllServerBoundCertsTask(const GetCertListCallback& callback);
197 virtual ~GetAllServerBoundCertsTask();
198 virtual void Run(DefaultServerBoundCertStore* store) OVERRIDE;
199
200 private:
201 std::string server_identifier_;
202 GetCertListCallback callback_;
203};
204
205DefaultServerBoundCertStore::GetAllServerBoundCertsTask::
206 GetAllServerBoundCertsTask(const GetCertListCallback& callback)
207 : callback_(callback) {
208}
209
210DefaultServerBoundCertStore::GetAllServerBoundCertsTask::
211 ~GetAllServerBoundCertsTask() {
212}
213
214void DefaultServerBoundCertStore::GetAllServerBoundCertsTask::Run(
215 DefaultServerBoundCertStore* store) {
216 ServerBoundCertList cert_list;
217 store->SyncGetAllServerBoundCerts(&cert_list);
218
219 InvokeCallback(base::Bind(callback_, cert_list));
220}
221
222// --------------------------------------------------------------------------
223// DefaultServerBoundCertStore
224
225// static
226const size_t DefaultServerBoundCertStore::kMaxCerts = 3300;
227
228DefaultServerBoundCertStore::DefaultServerBoundCertStore(
229 PersistentStore* store)
230 : initialized_(false),
231 loaded_(false),
232 store_(store),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100233 weak_ptr_factory_(this) {}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000234
Ben Murdochbb1529c2013-08-08 10:24:53 +0100235int DefaultServerBoundCertStore::GetServerBoundCert(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000236 const std::string& server_identifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000237 base::Time* expiration_time,
238 std::string* private_key_result,
239 std::string* cert_result,
240 const GetCertCallback& callback) {
241 DCHECK(CalledOnValidThread());
242 InitIfNecessary();
243
244 if (!loaded_) {
245 EnqueueTask(scoped_ptr<Task>(
246 new GetServerBoundCertTask(server_identifier, callback)));
Ben Murdochbb1529c2013-08-08 10:24:53 +0100247 return ERR_IO_PENDING;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248 }
249
250 ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier);
251
Ben Murdochbb1529c2013-08-08 10:24:53 +0100252 if (it == server_bound_certs_.end())
253 return ERR_FILE_NOT_FOUND;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000254
255 ServerBoundCert* cert = it->second;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000256 *expiration_time = cert->expiration_time();
257 *private_key_result = cert->private_key();
258 *cert_result = cert->cert();
259
Ben Murdochbb1529c2013-08-08 10:24:53 +0100260 return OK;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000261}
262
263void DefaultServerBoundCertStore::SetServerBoundCert(
264 const std::string& server_identifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000265 base::Time creation_time,
266 base::Time expiration_time,
267 const std::string& private_key,
268 const std::string& cert) {
269 RunOrEnqueueTask(scoped_ptr<Task>(new SetServerBoundCertTask(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100270 server_identifier, creation_time, expiration_time, private_key,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000271 cert)));
272}
273
274void DefaultServerBoundCertStore::DeleteServerBoundCert(
275 const std::string& server_identifier,
276 const base::Closure& callback) {
277 RunOrEnqueueTask(scoped_ptr<Task>(
278 new DeleteServerBoundCertTask(server_identifier, callback)));
279}
280
281void DefaultServerBoundCertStore::DeleteAllCreatedBetween(
282 base::Time delete_begin,
283 base::Time delete_end,
284 const base::Closure& callback) {
285 RunOrEnqueueTask(scoped_ptr<Task>(
286 new DeleteAllCreatedBetweenTask(delete_begin, delete_end, callback)));
287}
288
289void DefaultServerBoundCertStore::DeleteAll(
290 const base::Closure& callback) {
291 DeleteAllCreatedBetween(base::Time(), base::Time(), callback);
292}
293
294void DefaultServerBoundCertStore::GetAllServerBoundCerts(
295 const GetCertListCallback& callback) {
296 RunOrEnqueueTask(scoped_ptr<Task>(new GetAllServerBoundCertsTask(callback)));
297}
298
299int DefaultServerBoundCertStore::GetCertCount() {
300 DCHECK(CalledOnValidThread());
301
302 return server_bound_certs_.size();
303}
304
305void DefaultServerBoundCertStore::SetForceKeepSessionState() {
306 DCHECK(CalledOnValidThread());
307 InitIfNecessary();
308
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100309 if (store_.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000310 store_->SetForceKeepSessionState();
311}
312
313DefaultServerBoundCertStore::~DefaultServerBoundCertStore() {
314 DeleteAllInMemory();
315}
316
317void DefaultServerBoundCertStore::DeleteAllInMemory() {
318 DCHECK(CalledOnValidThread());
319
320 for (ServerBoundCertMap::iterator it = server_bound_certs_.begin();
321 it != server_bound_certs_.end(); ++it) {
322 delete it->second;
323 }
324 server_bound_certs_.clear();
325}
326
327void DefaultServerBoundCertStore::InitStore() {
328 DCHECK(CalledOnValidThread());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100329 DCHECK(store_.get()) << "Store must exist to initialize";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000330 DCHECK(!loaded_);
331
332 store_->Load(base::Bind(&DefaultServerBoundCertStore::OnLoaded,
333 weak_ptr_factory_.GetWeakPtr()));
334}
335
336void DefaultServerBoundCertStore::OnLoaded(
337 scoped_ptr<ScopedVector<ServerBoundCert> > certs) {
338 DCHECK(CalledOnValidThread());
339
340 for (std::vector<ServerBoundCert*>::const_iterator it = certs->begin();
341 it != certs->end(); ++it) {
342 DCHECK(server_bound_certs_.find((*it)->server_identifier()) ==
343 server_bound_certs_.end());
344 server_bound_certs_[(*it)->server_identifier()] = *it;
345 }
346 certs->weak_clear();
347
348 loaded_ = true;
349
350 base::TimeDelta wait_time;
351 if (!waiting_tasks_.empty())
352 wait_time = base::TimeTicks::Now() - waiting_tasks_start_time_;
353 DVLOG(1) << "Task delay " << wait_time.InMilliseconds();
354 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.TaskMaxWaitTime",
355 wait_time,
356 base::TimeDelta::FromMilliseconds(1),
357 base::TimeDelta::FromMinutes(1),
358 50);
359 UMA_HISTOGRAM_COUNTS_100("DomainBoundCerts.TaskWaitCount",
360 waiting_tasks_.size());
361
362
363 for (ScopedVector<Task>::iterator i = waiting_tasks_.begin();
364 i != waiting_tasks_.end(); ++i)
365 (*i)->Run(this);
366 waiting_tasks_.clear();
367}
368
369void DefaultServerBoundCertStore::SyncSetServerBoundCert(
370 const std::string& server_identifier,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000371 base::Time creation_time,
372 base::Time expiration_time,
373 const std::string& private_key,
374 const std::string& cert) {
375 DCHECK(CalledOnValidThread());
376 DCHECK(loaded_);
377
378 InternalDeleteServerBoundCert(server_identifier);
379 InternalInsertServerBoundCert(
380 server_identifier,
381 new ServerBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100382 server_identifier, creation_time, expiration_time, private_key,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000383 cert));
384}
385
386void DefaultServerBoundCertStore::SyncDeleteServerBoundCert(
387 const std::string& server_identifier) {
388 DCHECK(CalledOnValidThread());
389 DCHECK(loaded_);
390 InternalDeleteServerBoundCert(server_identifier);
391}
392
393void DefaultServerBoundCertStore::SyncDeleteAllCreatedBetween(
394 base::Time delete_begin,
395 base::Time delete_end) {
396 DCHECK(CalledOnValidThread());
397 DCHECK(loaded_);
398 for (ServerBoundCertMap::iterator it = server_bound_certs_.begin();
399 it != server_bound_certs_.end();) {
400 ServerBoundCertMap::iterator cur = it;
401 ++it;
402 ServerBoundCert* cert = cur->second;
403 if ((delete_begin.is_null() || cert->creation_time() >= delete_begin) &&
404 (delete_end.is_null() || cert->creation_time() < delete_end)) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100405 if (store_.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000406 store_->DeleteServerBoundCert(*cert);
407 delete cert;
408 server_bound_certs_.erase(cur);
409 }
410 }
411}
412
413void DefaultServerBoundCertStore::SyncGetAllServerBoundCerts(
414 ServerBoundCertList* cert_list) {
415 DCHECK(CalledOnValidThread());
416 DCHECK(loaded_);
417 for (ServerBoundCertMap::iterator it = server_bound_certs_.begin();
418 it != server_bound_certs_.end(); ++it)
419 cert_list->push_back(*it->second);
420}
421
422void DefaultServerBoundCertStore::EnqueueTask(scoped_ptr<Task> task) {
423 DCHECK(CalledOnValidThread());
424 DCHECK(!loaded_);
425 if (waiting_tasks_.empty())
426 waiting_tasks_start_time_ = base::TimeTicks::Now();
427 waiting_tasks_.push_back(task.release());
428}
429
430void DefaultServerBoundCertStore::RunOrEnqueueTask(scoped_ptr<Task> task) {
431 DCHECK(CalledOnValidThread());
432 InitIfNecessary();
433
434 if (!loaded_) {
435 EnqueueTask(task.Pass());
436 return;
437 }
438
439 task->Run(this);
440}
441
442void DefaultServerBoundCertStore::InternalDeleteServerBoundCert(
443 const std::string& server_identifier) {
444 DCHECK(CalledOnValidThread());
445 DCHECK(loaded_);
446
447 ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier);
448 if (it == server_bound_certs_.end())
449 return; // There is nothing to delete.
450
451 ServerBoundCert* cert = it->second;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100452 if (store_.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000453 store_->DeleteServerBoundCert(*cert);
454 server_bound_certs_.erase(it);
455 delete cert;
456}
457
458void DefaultServerBoundCertStore::InternalInsertServerBoundCert(
459 const std::string& server_identifier,
460 ServerBoundCert* cert) {
461 DCHECK(CalledOnValidThread());
462 DCHECK(loaded_);
463
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100464 if (store_.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000465 store_->AddServerBoundCert(*cert);
466 server_bound_certs_[server_identifier] = cert;
467}
468
469DefaultServerBoundCertStore::PersistentStore::PersistentStore() {}
470
471DefaultServerBoundCertStore::PersistentStore::~PersistentStore() {}
472
473} // namespace net