forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel_id_service.h
191 lines (157 loc) · 6.77 KB
/
channel_id_service.h
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
// Copyright 2014 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_CHANNEL_ID_SERVICE_H_
#define NET_SSL_CHANNEL_ID_SERVICE_H_
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
#include "net/ssl/channel_id_store.h"
namespace base {
class TaskRunner;
} // namespace base
namespace crypto {
class ECPrivateKey;
} // namespace crypto
namespace net {
class ChannelIDServiceJob;
class ChannelIDServiceWorker;
// A class for creating and fetching Channel IDs.
// Inherits from NonThreadSafe in order to use the function
// |CalledOnValidThread|.
class NET_EXPORT ChannelIDService
: NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
class NET_EXPORT Request {
public:
Request();
~Request();
// Cancel the request. Does nothing if the request finished or was already
// cancelled.
void Cancel();
bool is_active() const { return !callback_.is_null(); }
private:
friend class ChannelIDService;
friend class ChannelIDServiceJob;
void RequestStarted(ChannelIDService* service,
base::TimeTicks request_start,
const CompletionCallback& callback,
scoped_ptr<crypto::ECPrivateKey>* key,
ChannelIDServiceJob* job);
void Post(int error, scoped_ptr<crypto::ECPrivateKey> key);
ChannelIDService* service_;
base::TimeTicks request_start_;
CompletionCallback callback_;
scoped_ptr<crypto::ECPrivateKey>* key_;
ChannelIDServiceJob* job_;
};
// Password used on EncryptedPrivateKeyInfo data stored in EC private_key
// values. (This is not used to provide any security, but to workaround NSS
// being unable to import unencrypted PrivateKeyInfo for EC keys.)
static const char kEPKIPassword[];
// This object owns |channel_id_store|. |task_runner| will
// be used to post channel ID generation worker tasks. The tasks are
// safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN.
ChannelIDService(
ChannelIDStore* channel_id_store,
const scoped_refptr<base::TaskRunner>& task_runner);
~ChannelIDService();
// Returns the domain to be used for |host|. The domain is the
// "registry controlled domain", or the "ETLD + 1" where one exists, or
// the origin otherwise.
static std::string GetDomainForHost(const std::string& host);
// Fetches the channel ID for the specified host if one exists and
// creates one otherwise. Returns OK if successful or an error code upon
// failure.
//
// On successful completion, |key| holds the ECDSA keypair used for this
// channel ID.
//
// |callback| must not be null. ERR_IO_PENDING is returned if the operation
// could not be completed immediately, in which case the result code will
// be passed to the callback when available.
//
// |*out_req| will be initialized with a handle to the async request.
int GetOrCreateChannelID(const std::string& host,
scoped_ptr<crypto::ECPrivateKey>* key,
const CompletionCallback& callback,
Request* out_req);
// Fetches the channel ID for the specified host if one exists.
// Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error
// code upon failure.
//
// On successful completion, |key| holds the ECDSA keypair used for this
// channel ID.
//
// |callback| must not be null. ERR_IO_PENDING is returned if the operation
// could not be completed immediately, in which case the result code will
// be passed to the callback when available. If an in-flight
// GetChannelID is pending, and a new GetOrCreateChannelID
// request arrives for the same domain, the GetChannelID request will
// not complete until a new channel ID is created.
//
// |*out_req| will be initialized with a handle to the async request.
int GetChannelID(const std::string& host,
scoped_ptr<crypto::ECPrivateKey>* key,
const CompletionCallback& callback,
Request* out_req);
// Returns the backing ChannelIDStore.
ChannelIDStore* GetChannelIDStore();
// Public only for unit testing.
int channel_id_count();
uint64_t requests() const { return requests_; }
uint64_t key_store_hits() const { return key_store_hits_; }
uint64_t inflight_joins() const { return inflight_joins_; }
uint64_t workers_created() const { return workers_created_; }
private:
void GotChannelID(int err,
const std::string& server_identifier,
scoped_ptr<crypto::ECPrivateKey> key);
void GeneratedChannelID(
const std::string& server_identifier,
int error,
scoped_ptr<ChannelIDStore::ChannelID> channel_id);
void HandleResult(int error,
const std::string& server_identifier,
scoped_ptr<crypto::ECPrivateKey> key);
// Searches for an in-flight request for the same domain. If found,
// attaches to the request and returns true. Returns false if no in-flight
// request is found.
bool JoinToInFlightRequest(const base::TimeTicks& request_start,
const std::string& domain,
scoped_ptr<crypto::ECPrivateKey>* key,
bool create_if_missing,
const CompletionCallback& callback,
Request* out_req);
// Looks for the channel ID for |domain| in this service's store.
// Returns OK if it can be found synchronously, ERR_IO_PENDING if the
// result cannot be obtained synchronously, or a network error code on
// failure (including failure to find a channel ID of |domain|).
int LookupChannelID(const base::TimeTicks& request_start,
const std::string& domain,
scoped_ptr<crypto::ECPrivateKey>* key,
bool create_if_missing,
const CompletionCallback& callback,
Request* out_req);
scoped_ptr<ChannelIDStore> channel_id_store_;
scoped_refptr<base::TaskRunner> task_runner_;
// inflight_ maps from a server to an active generation which is taking
// place.
std::map<std::string, ChannelIDServiceJob*> inflight_;
uint64_t requests_;
uint64_t key_store_hits_;
uint64_t inflight_joins_;
uint64_t workers_created_;
base::WeakPtrFactory<ChannelIDService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ChannelIDService);
};
} // namespace net
#endif // NET_SSL_CHANNEL_ID_SERVICE_H_