OLD | NEW |
| (Empty) |
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 #ifndef NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ | |
6 #define NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ | |
7 | |
8 #include <map> | |
9 #include <string> | |
10 #include <vector> | |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "base/memory/weak_ptr.h" | |
15 #include "base/threading/non_thread_safe.h" | |
16 #include "base/time/time.h" | |
17 #include "net/base/completion_callback.h" | |
18 #include "net/base/net_export.h" | |
19 #include "net/ssl/server_bound_cert_store.h" | |
20 | |
21 namespace base { | |
22 class TaskRunner; | |
23 } | |
24 | |
25 namespace net { | |
26 | |
27 class ServerBoundCertServiceJob; | |
28 class ServerBoundCertServiceRequest; | |
29 class ServerBoundCertServiceWorker; | |
30 | |
31 // A class for creating and fetching server bound certs. These certs are used | |
32 // to identify users' machines; their public keys are used as channel IDs in | |
33 // http://tools.ietf.org/html/draft-balfanz-tls-channelid-00. | |
34 // As a result although certs are set to be invalid after one year, we don't | |
35 // actually expire them. Once generated, certs are valid as long as the users | |
36 // want. Users can delete existing certs, and new certs will be generated | |
37 // automatically. | |
38 | |
39 // Inherits from NonThreadSafe in order to use the function | |
40 // |CalledOnValidThread|. | |
41 class NET_EXPORT ServerBoundCertService | |
42 : NON_EXPORTED_BASE(public base::NonThreadSafe) { | |
43 public: | |
44 class NET_EXPORT RequestHandle { | |
45 public: | |
46 RequestHandle(); | |
47 ~RequestHandle(); | |
48 | |
49 // Cancel the request. Does nothing if the request finished or was already | |
50 // cancelled. | |
51 void Cancel(); | |
52 | |
53 bool is_active() const { return request_ != NULL; } | |
54 | |
55 private: | |
56 friend class ServerBoundCertService; | |
57 | |
58 void RequestStarted(ServerBoundCertService* service, | |
59 ServerBoundCertServiceRequest* request, | |
60 const CompletionCallback& callback); | |
61 | |
62 void OnRequestComplete(int result); | |
63 | |
64 ServerBoundCertService* service_; | |
65 ServerBoundCertServiceRequest* request_; | |
66 CompletionCallback callback_; | |
67 }; | |
68 | |
69 // Password used on EncryptedPrivateKeyInfo data stored in EC private_key | |
70 // values. (This is not used to provide any security, but to workaround NSS | |
71 // being unable to import unencrypted PrivateKeyInfo for EC keys.) | |
72 static const char kEPKIPassword[]; | |
73 | |
74 // This object owns |server_bound_cert_store|. |task_runner| will | |
75 // be used to post certificate generation worker tasks. The tasks are | |
76 // safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN. | |
77 ServerBoundCertService( | |
78 ServerBoundCertStore* server_bound_cert_store, | |
79 const scoped_refptr<base::TaskRunner>& task_runner); | |
80 | |
81 ~ServerBoundCertService(); | |
82 | |
83 // Returns the domain to be used for |host|. The domain is the | |
84 // "registry controlled domain", or the "ETLD + 1" where one exists, or | |
85 // the origin otherwise. | |
86 static std::string GetDomainForHost(const std::string& host); | |
87 | |
88 // Tests whether the system time is within the supported range for | |
89 // certificate generation. This value is cached when ServerBoundCertService | |
90 // is created, so if the system time is changed by a huge amount, this may no | |
91 // longer hold. | |
92 bool IsSystemTimeValid() const { return is_system_time_valid_; } | |
93 | |
94 // Fetches the domain bound cert for the specified host if one exists and | |
95 // creates one otherwise. Returns OK if successful or an error code upon | |
96 // failure. | |
97 // | |
98 // On successful completion, |private_key| stores a DER-encoded | |
99 // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. | |
100 // The PrivateKeyInfo is always an ECDSA private key. | |
101 // | |
102 // |callback| must not be null. ERR_IO_PENDING is returned if the operation | |
103 // could not be completed immediately, in which case the result code will | |
104 // be passed to the callback when available. | |
105 // | |
106 // |*out_req| will be initialized with a handle to the async request. This | |
107 // RequestHandle object must be cancelled or destroyed before the | |
108 // ServerBoundCertService is destroyed. | |
109 int GetOrCreateDomainBoundCert( | |
110 const std::string& host, | |
111 std::string* private_key, | |
112 std::string* cert, | |
113 const CompletionCallback& callback, | |
114 RequestHandle* out_req); | |
115 | |
116 // Fetches the domain bound cert for the specified host if one exists. | |
117 // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error | |
118 // code upon failure. | |
119 // | |
120 // On successful completion, |private_key| stores a DER-encoded | |
121 // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. | |
122 // The PrivateKeyInfo is always an ECDSA private key. | |
123 // | |
124 // |callback| must not be null. ERR_IO_PENDING is returned if the operation | |
125 // could not be completed immediately, in which case the result code will | |
126 // be passed to the callback when available. If an in-flight | |
127 // GetDomainBoundCert is pending, and a new GetOrCreateDomainBoundCert | |
128 // request arrives for the same domain, the GetDomainBoundCert request will | |
129 // not complete until a new cert is created. | |
130 // | |
131 // |*out_req| will be initialized with a handle to the async request. This | |
132 // RequestHandle object must be cancelled or destroyed before the | |
133 // ServerBoundCertService is destroyed. | |
134 int GetDomainBoundCert( | |
135 const std::string& host, | |
136 std::string* private_key, | |
137 std::string* cert, | |
138 const CompletionCallback& callback, | |
139 RequestHandle* out_req); | |
140 | |
141 // Returns the backing ServerBoundCertStore. | |
142 ServerBoundCertStore* GetCertStore(); | |
143 | |
144 // Public only for unit testing. | |
145 int cert_count(); | |
146 uint64 requests() const { return requests_; } | |
147 uint64 cert_store_hits() const { return cert_store_hits_; } | |
148 uint64 inflight_joins() const { return inflight_joins_; } | |
149 uint64 workers_created() const { return workers_created_; } | |
150 | |
151 private: | |
152 // Cancels the specified request. |req| is the handle stored by | |
153 // GetDomainBoundCert(). After a request is canceled, its completion | |
154 // callback will not be called. | |
155 void CancelRequest(ServerBoundCertServiceRequest* req); | |
156 | |
157 void GotServerBoundCert(int err, | |
158 const std::string& server_identifier, | |
159 base::Time expiration_time, | |
160 const std::string& key, | |
161 const std::string& cert); | |
162 void GeneratedServerBoundCert( | |
163 const std::string& server_identifier, | |
164 int error, | |
165 scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert); | |
166 void HandleResult(int error, | |
167 const std::string& server_identifier, | |
168 const std::string& private_key, | |
169 const std::string& cert); | |
170 | |
171 // Searches for an in-flight request for the same domain. If found, | |
172 // attaches to the request and returns true. Returns false if no in-flight | |
173 // request is found. | |
174 bool JoinToInFlightRequest(const base::TimeTicks& request_start, | |
175 const std::string& domain, | |
176 std::string* private_key, | |
177 std::string* cert, | |
178 bool create_if_missing, | |
179 const CompletionCallback& callback, | |
180 RequestHandle* out_req); | |
181 | |
182 // Looks for the domain bound cert for |domain| in this service's store. | |
183 // Returns OK if it can be found synchronously, ERR_IO_PENDING if the | |
184 // result cannot be obtained synchronously, or a network error code on | |
185 // failure (including failure to find a domain-bound cert of |domain|). | |
186 int LookupDomainBoundCert(const base::TimeTicks& request_start, | |
187 const std::string& domain, | |
188 std::string* private_key, | |
189 std::string* cert, | |
190 bool create_if_missing, | |
191 const CompletionCallback& callback, | |
192 RequestHandle* out_req); | |
193 | |
194 scoped_ptr<ServerBoundCertStore> server_bound_cert_store_; | |
195 scoped_refptr<base::TaskRunner> task_runner_; | |
196 | |
197 // inflight_ maps from a server to an active generation which is taking | |
198 // place. | |
199 std::map<std::string, ServerBoundCertServiceJob*> inflight_; | |
200 | |
201 uint64 requests_; | |
202 uint64 cert_store_hits_; | |
203 uint64 inflight_joins_; | |
204 uint64 workers_created_; | |
205 | |
206 bool is_system_time_valid_; | |
207 | |
208 base::WeakPtrFactory<ServerBoundCertService> weak_ptr_factory_; | |
209 | |
210 DISALLOW_COPY_AND_ASSIGN(ServerBoundCertService); | |
211 }; | |
212 | |
213 } // namespace net | |
214 | |
215 #endif // NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ | |
OLD | NEW |