summaryrefslogtreecommitdiffstats
path: root/net/ssl/default_server_bound_cert_store.h
blob: 8ec680562ca71caad11ce429dcc1d7b68c54f829 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_SSL_DEFAULT_SERVER_BOUND_CERT_STORE_H_
#define NET_SSL_DEFAULT_SERVER_BOUND_CERT_STORE_H_

#include <map>
#include <string>
#include <vector>

#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "net/base/net_export.h"
#include "net/ssl/server_bound_cert_store.h"

namespace net {

// This class is the system for storing and retrieving server bound certs.
// Modeled after the CookieMonster class, it has an in-memory cert store,
// and synchronizes server bound certs to an optional permanent storage that
// implements the PersistentStore interface. The use case is described in
// http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html
class NET_EXPORT DefaultServerBoundCertStore : public ServerBoundCertStore {
 public:
  class PersistentStore;

  // The key for each ServerBoundCert* in ServerBoundCertMap is the
  // corresponding server.
  typedef std::map<std::string, ServerBoundCert*> ServerBoundCertMap;

  // The store passed in should not have had Init() called on it yet. This
  // class will take care of initializing it. The backing store is NOT owned by
  // this class, but it must remain valid for the duration of the
  // DefaultServerBoundCertStore's existence. If |store| is NULL, then no
  // backing store will be updated.
  explicit DefaultServerBoundCertStore(PersistentStore* store);

  virtual ~DefaultServerBoundCertStore();

  // ServerBoundCertStore implementation.
  virtual bool GetServerBoundCert(
      const std::string& server_identifier,
      SSLClientCertType* type,
      base::Time* expiration_time,
      std::string* private_key_result,
      std::string* cert_result,
      const GetCertCallback& callback) OVERRIDE;
  virtual void SetServerBoundCert(
      const std::string& server_identifier,
      SSLClientCertType type,
      base::Time creation_time,
      base::Time expiration_time,
      const std::string& private_key,
      const std::string& cert) OVERRIDE;
  virtual void DeleteServerBoundCert(
      const std::string& server_identifier,
      const base::Closure& callback) OVERRIDE;
  virtual void DeleteAllCreatedBetween(
      base::Time delete_begin,
      base::Time delete_end,
      const base::Closure& callback) OVERRIDE;
  virtual void DeleteAll(const base::Closure& callback) OVERRIDE;
  virtual void GetAllServerBoundCerts(
      const GetCertListCallback& callback) OVERRIDE;
  virtual int GetCertCount() OVERRIDE;
  virtual void SetForceKeepSessionState() OVERRIDE;

 private:
  class Task;
  class GetServerBoundCertTask;
  class SetServerBoundCertTask;
  class DeleteServerBoundCertTask;
  class DeleteAllCreatedBetweenTask;
  class GetAllServerBoundCertsTask;

  static const size_t kMaxCerts;

  // Deletes all of the certs. Does not delete them from |store_|.
  void DeleteAllInMemory();

  // Called by all non-static functions to ensure that the cert store has
  // been initialized.
  // TODO(mattm): since we load asynchronously now, maybe we should start
  // loading immediately on construction, or provide some method to initiate
  // loading?
  void InitIfNecessary() {
    if (!initialized_) {
      if (store_.get()) {
        InitStore();
      } else {
        loaded_ = true;
      }
      initialized_ = true;
    }
  }

  // Initializes the backing store and reads existing certs from it.
  // Should only be called by InitIfNecessary().
  void InitStore();

  // Callback for backing store loading completion.
  void OnLoaded(scoped_ptr<ScopedVector<ServerBoundCert> > certs);

  // Syncronous methods which do the actual work. Can only be called after
  // initialization is complete.
  void SyncSetServerBoundCert(
      const std::string& server_identifier,
      SSLClientCertType type,
      base::Time creation_time,
      base::Time expiration_time,
      const std::string& private_key,
      const std::string& cert);
  void SyncDeleteServerBoundCert(const std::string& server_identifier);
  void SyncDeleteAllCreatedBetween(base::Time delete_begin,
                                   base::Time delete_end);
  void SyncGetAllServerBoundCerts(ServerBoundCertList* cert_list);

  // Add |task| to |waiting_tasks_|.
  void EnqueueTask(scoped_ptr<Task> task);
  // If already initialized, run |task| immediately. Otherwise add it to
  // |waiting_tasks_|.
  void RunOrEnqueueTask(scoped_ptr<Task> task);

  // Deletes the cert for the specified server, if such a cert exists, from the
  // in-memory store. Deletes it from |store_| if |store_| is not NULL.
  void InternalDeleteServerBoundCert(const std::string& server);

  // Takes ownership of *cert.
  // Adds the cert for the specified server to the in-memory store. Deletes it
  // from |store_| if |store_| is not NULL.
  void InternalInsertServerBoundCert(const std::string& server_identifier,
                                     ServerBoundCert* cert);

  // Indicates whether the cert store has been initialized. This happens
  // lazily in InitIfNecessary().
  bool initialized_;

  // Indicates whether loading from the backend store is completed and
  // calls may be immediately processed.
  bool loaded_;

  // Tasks that are waiting to be run once we finish loading.
  ScopedVector<Task> waiting_tasks_;
  base::TimeTicks waiting_tasks_start_time_;

  scoped_refptr<PersistentStore> store_;

  ServerBoundCertMap server_bound_certs_;

  base::WeakPtrFactory<DefaultServerBoundCertStore> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(DefaultServerBoundCertStore);
};

typedef base::RefCountedThreadSafe<DefaultServerBoundCertStore::PersistentStore>
    RefcountedPersistentStore;

class NET_EXPORT DefaultServerBoundCertStore::PersistentStore
    : public RefcountedPersistentStore {
 public:
  typedef base::Callback<void(scoped_ptr<ScopedVector<ServerBoundCert> >)>
      LoadedCallback;

  // Initializes the store and retrieves the existing certs. This will be
  // called only once at startup. Note that the certs are individually allocated
  // and that ownership is transferred to the caller upon return.
  // The |loaded_callback| must not be called synchronously.
  virtual void Load(const LoadedCallback& loaded_callback) = 0;

  virtual void AddServerBoundCert(const ServerBoundCert& cert) = 0;

  virtual void DeleteServerBoundCert(const ServerBoundCert& cert) = 0;

  // When invoked, instructs the store to keep session related data on
  // destruction.
  virtual void SetForceKeepSessionState() = 0;

 protected:
  friend class base::RefCountedThreadSafe<PersistentStore>;

  PersistentStore();
  virtual ~PersistentStore();

 private:
  DISALLOW_COPY_AND_ASSIGN(PersistentStore);
};

}  // namespace net

#endif  // NET_SSL_DEFAULT_SERVER_BOUND_CERT_STORE_H_