Home | History | Annotate | Download | only in ssl
      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