1 // 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" 8 #include "base/message_loop/message_loop.h" 9 #include "base/metrics/histogram.h" 10 #include "net/base/net_errors.h" 11 12 namespace net { 13 14 // -------------------------------------------------------------------------- 15 // Task 16 class 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 28 DefaultServerBoundCertStore::Task::~Task() { 29 } 30 31 void DefaultServerBoundCertStore::Task::InvokeCallback( 32 base::Closure callback) const { 33 if (!callback.is_null()) 34 callback.Run(); 35 } 36 37 // -------------------------------------------------------------------------- 38 // GetServerBoundCertTask 39 class 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 52 DefaultServerBoundCertStore::GetServerBoundCertTask::GetServerBoundCertTask( 53 const std::string& server_identifier, 54 const GetCertCallback& callback) 55 : server_identifier_(server_identifier), 56 callback_(callback) { 57 } 58 59 DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() { 60 } 61 62 void DefaultServerBoundCertStore::GetServerBoundCertTask::Run( 63 DefaultServerBoundCertStore* store) { 64 base::Time expiration_time; 65 std::string private_key_result; 66 std::string cert_result; 67 int err = store->GetServerBoundCert( 68 server_identifier_, &expiration_time, &private_key_result, 69 &cert_result, GetCertCallback()); 70 DCHECK(err != ERR_IO_PENDING); 71 72 InvokeCallback(base::Bind(callback_, err, server_identifier_, 73 expiration_time, private_key_result, cert_result)); 74 } 75 76 // -------------------------------------------------------------------------- 77 // SetServerBoundCertTask 78 class DefaultServerBoundCertStore::SetServerBoundCertTask 79 : public DefaultServerBoundCertStore::Task { 80 public: 81 SetServerBoundCertTask(const std::string& server_identifier, 82 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_; 91 base::Time creation_time_; 92 base::Time expiration_time_; 93 std::string private_key_; 94 std::string cert_; 95 }; 96 97 DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask( 98 const std::string& server_identifier, 99 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), 104 creation_time_(creation_time), 105 expiration_time_(expiration_time), 106 private_key_(private_key), 107 cert_(cert) { 108 } 109 110 DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() { 111 } 112 113 void DefaultServerBoundCertStore::SetServerBoundCertTask::Run( 114 DefaultServerBoundCertStore* store) { 115 store->SyncSetServerBoundCert(server_identifier_, creation_time_, 116 expiration_time_, private_key_, cert_); 117 } 118 119 // -------------------------------------------------------------------------- 120 // DeleteServerBoundCertTask 121 class 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 134 DefaultServerBoundCertStore::DeleteServerBoundCertTask:: 135 DeleteServerBoundCertTask( 136 const std::string& server_identifier, 137 const base::Closure& callback) 138 : server_identifier_(server_identifier), 139 callback_(callback) { 140 } 141 142 DefaultServerBoundCertStore::DeleteServerBoundCertTask:: 143 ~DeleteServerBoundCertTask() { 144 } 145 146 void DefaultServerBoundCertStore::DeleteServerBoundCertTask::Run( 147 DefaultServerBoundCertStore* store) { 148 store->SyncDeleteServerBoundCert(server_identifier_); 149 150 InvokeCallback(callback_); 151 } 152 153 // -------------------------------------------------------------------------- 154 // DeleteAllCreatedBetweenTask 155 class 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 170 DefaultServerBoundCertStore::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 180 DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask:: 181 ~DeleteAllCreatedBetweenTask() { 182 } 183 184 void DefaultServerBoundCertStore::DeleteAllCreatedBetweenTask::Run( 185 DefaultServerBoundCertStore* store) { 186 store->SyncDeleteAllCreatedBetween(delete_begin_, delete_end_); 187 188 InvokeCallback(callback_); 189 } 190 191 // -------------------------------------------------------------------------- 192 // GetAllServerBoundCertsTask 193 class 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 205 DefaultServerBoundCertStore::GetAllServerBoundCertsTask:: 206 GetAllServerBoundCertsTask(const GetCertListCallback& callback) 207 : callback_(callback) { 208 } 209 210 DefaultServerBoundCertStore::GetAllServerBoundCertsTask:: 211 ~GetAllServerBoundCertsTask() { 212 } 213 214 void 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 226 const size_t DefaultServerBoundCertStore::kMaxCerts = 3300; 227 228 DefaultServerBoundCertStore::DefaultServerBoundCertStore( 229 PersistentStore* store) 230 : initialized_(false), 231 loaded_(false), 232 store_(store), 233 weak_ptr_factory_(this) {} 234 235 int DefaultServerBoundCertStore::GetServerBoundCert( 236 const std::string& server_identifier, 237 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))); 247 return ERR_IO_PENDING; 248 } 249 250 ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier); 251 252 if (it == server_bound_certs_.end()) 253 return ERR_FILE_NOT_FOUND; 254 255 ServerBoundCert* cert = it->second; 256 *expiration_time = cert->expiration_time(); 257 *private_key_result = cert->private_key(); 258 *cert_result = cert->cert(); 259 260 return OK; 261 } 262 263 void DefaultServerBoundCertStore::SetServerBoundCert( 264 const std::string& server_identifier, 265 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( 270 server_identifier, creation_time, expiration_time, private_key, 271 cert))); 272 } 273 274 void 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 281 void 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 289 void DefaultServerBoundCertStore::DeleteAll( 290 const base::Closure& callback) { 291 DeleteAllCreatedBetween(base::Time(), base::Time(), callback); 292 } 293 294 void DefaultServerBoundCertStore::GetAllServerBoundCerts( 295 const GetCertListCallback& callback) { 296 RunOrEnqueueTask(scoped_ptr<Task>(new GetAllServerBoundCertsTask(callback))); 297 } 298 299 int DefaultServerBoundCertStore::GetCertCount() { 300 DCHECK(CalledOnValidThread()); 301 302 return server_bound_certs_.size(); 303 } 304 305 void DefaultServerBoundCertStore::SetForceKeepSessionState() { 306 DCHECK(CalledOnValidThread()); 307 InitIfNecessary(); 308 309 if (store_.get()) 310 store_->SetForceKeepSessionState(); 311 } 312 313 DefaultServerBoundCertStore::~DefaultServerBoundCertStore() { 314 DeleteAllInMemory(); 315 } 316 317 void 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 327 void DefaultServerBoundCertStore::InitStore() { 328 DCHECK(CalledOnValidThread()); 329 DCHECK(store_.get()) << "Store must exist to initialize"; 330 DCHECK(!loaded_); 331 332 store_->Load(base::Bind(&DefaultServerBoundCertStore::OnLoaded, 333 weak_ptr_factory_.GetWeakPtr())); 334 } 335 336 void 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 369 void DefaultServerBoundCertStore::SyncSetServerBoundCert( 370 const std::string& server_identifier, 371 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( 382 server_identifier, creation_time, expiration_time, private_key, 383 cert)); 384 } 385 386 void DefaultServerBoundCertStore::SyncDeleteServerBoundCert( 387 const std::string& server_identifier) { 388 DCHECK(CalledOnValidThread()); 389 DCHECK(loaded_); 390 InternalDeleteServerBoundCert(server_identifier); 391 } 392 393 void 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)) { 405 if (store_.get()) 406 store_->DeleteServerBoundCert(*cert); 407 delete cert; 408 server_bound_certs_.erase(cur); 409 } 410 } 411 } 412 413 void 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 422 void 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 430 void 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 442 void 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; 452 if (store_.get()) 453 store_->DeleteServerBoundCert(*cert); 454 server_bound_certs_.erase(it); 455 delete cert; 456 } 457 458 void DefaultServerBoundCertStore::InternalInsertServerBoundCert( 459 const std::string& server_identifier, 460 ServerBoundCert* cert) { 461 DCHECK(CalledOnValidThread()); 462 DCHECK(loaded_); 463 464 if (store_.get()) 465 store_->AddServerBoundCert(*cert); 466 server_bound_certs_[server_identifier] = cert; 467 } 468 469 DefaultServerBoundCertStore::PersistentStore::PersistentStore() {} 470 471 DefaultServerBoundCertStore::PersistentStore::~PersistentStore() {} 472 473 } // namespace net 474