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 #include "net/ssl/server_bound_cert_service.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/message_loop/message_loop_proxy.h" | |
14 #include "base/task_runner.h" | |
15 #include "crypto/ec_private_key.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/base/test_completion_callback.h" | |
18 #include "net/cert/asn1_util.h" | |
19 #include "net/cert/x509_certificate.h" | |
20 #include "net/ssl/default_server_bound_cert_store.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 namespace net { | |
24 | |
25 namespace { | |
26 | |
27 void FailTest(int /* result */) { | |
28 FAIL(); | |
29 } | |
30 | |
31 // Simple task runner that refuses to actually post any tasks. This simulates | |
32 // a TaskRunner that has been shutdown, by returning false for any attempt to | |
33 // add new tasks. | |
34 class FailingTaskRunner : public base::TaskRunner { | |
35 public: | |
36 FailingTaskRunner() {} | |
37 | |
38 virtual bool PostDelayedTask(const tracked_objects::Location& from_here, | |
39 const base::Closure& task, | |
40 base::TimeDelta delay) OVERRIDE { | |
41 return false; | |
42 } | |
43 | |
44 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { return true; } | |
45 | |
46 protected: | |
47 virtual ~FailingTaskRunner() {} | |
48 | |
49 private: | |
50 DISALLOW_COPY_AND_ASSIGN(FailingTaskRunner); | |
51 }; | |
52 | |
53 class MockServerBoundCertStoreWithAsyncGet | |
54 : public DefaultServerBoundCertStore { | |
55 public: | |
56 MockServerBoundCertStoreWithAsyncGet() | |
57 : DefaultServerBoundCertStore(NULL), cert_count_(0) {} | |
58 | |
59 virtual int GetServerBoundCert(const std::string& server_identifier, | |
60 base::Time* expiration_time, | |
61 std::string* private_key_result, | |
62 std::string* cert_result, | |
63 const GetCertCallback& callback) OVERRIDE; | |
64 | |
65 virtual void SetServerBoundCert(const std::string& server_identifier, | |
66 base::Time creation_time, | |
67 base::Time expiration_time, | |
68 const std::string& private_key, | |
69 const std::string& cert) OVERRIDE { | |
70 cert_count_ = 1; | |
71 } | |
72 | |
73 virtual int GetCertCount() OVERRIDE { return cert_count_; } | |
74 | |
75 void CallGetServerBoundCertCallbackWithResult(int err, | |
76 base::Time expiration_time, | |
77 const std::string& private_key, | |
78 const std::string& cert); | |
79 | |
80 private: | |
81 GetCertCallback callback_; | |
82 std::string server_identifier_; | |
83 int cert_count_; | |
84 }; | |
85 | |
86 int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert( | |
87 const std::string& server_identifier, | |
88 base::Time* expiration_time, | |
89 std::string* private_key_result, | |
90 std::string* cert_result, | |
91 const GetCertCallback& callback) { | |
92 server_identifier_ = server_identifier; | |
93 callback_ = callback; | |
94 // Reset the cert count, it'll get incremented in either SetServerBoundCert or | |
95 // CallGetServerBoundCertCallbackWithResult. | |
96 cert_count_ = 0; | |
97 // Do nothing else: the results to be provided will be specified through | |
98 // CallGetServerBoundCertCallbackWithResult. | |
99 return ERR_IO_PENDING; | |
100 } | |
101 | |
102 void | |
103 MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult( | |
104 int err, | |
105 base::Time expiration_time, | |
106 const std::string& private_key, | |
107 const std::string& cert) { | |
108 if (err == OK) | |
109 cert_count_ = 1; | |
110 base::MessageLoop::current()->PostTask(FROM_HERE, | |
111 base::Bind(callback_, | |
112 err, | |
113 server_identifier_, | |
114 expiration_time, | |
115 private_key, | |
116 cert)); | |
117 } | |
118 | |
119 class ServerBoundCertServiceTest : public testing::Test { | |
120 public: | |
121 ServerBoundCertServiceTest() | |
122 : service_(new ServerBoundCertService( | |
123 new DefaultServerBoundCertStore(NULL), | |
124 base::MessageLoopProxy::current())) { | |
125 } | |
126 | |
127 protected: | |
128 scoped_ptr<ServerBoundCertService> service_; | |
129 }; | |
130 | |
131 TEST_F(ServerBoundCertServiceTest, GetDomainForHost) { | |
132 EXPECT_EQ("google.com", | |
133 ServerBoundCertService::GetDomainForHost("google.com")); | |
134 EXPECT_EQ("google.com", | |
135 ServerBoundCertService::GetDomainForHost("www.google.com")); | |
136 EXPECT_EQ("foo.appspot.com", | |
137 ServerBoundCertService::GetDomainForHost("foo.appspot.com")); | |
138 EXPECT_EQ("bar.appspot.com", | |
139 ServerBoundCertService::GetDomainForHost("foo.bar.appspot.com")); | |
140 EXPECT_EQ("appspot.com", | |
141 ServerBoundCertService::GetDomainForHost("appspot.com")); | |
142 EXPECT_EQ("google.com", | |
143 ServerBoundCertService::GetDomainForHost("www.mail.google.com")); | |
144 EXPECT_EQ("goto", | |
145 ServerBoundCertService::GetDomainForHost("goto")); | |
146 EXPECT_EQ("127.0.0.1", | |
147 ServerBoundCertService::GetDomainForHost("127.0.0.1")); | |
148 } | |
149 | |
150 TEST_F(ServerBoundCertServiceTest, GetCacheMiss) { | |
151 std::string host("encrypted.google.com"); | |
152 | |
153 int error; | |
154 TestCompletionCallback callback; | |
155 ServerBoundCertService::RequestHandle request_handle; | |
156 | |
157 // Synchronous completion, because the store is initialized. | |
158 std::string private_key, der_cert; | |
159 EXPECT_EQ(0, service_->cert_count()); | |
160 error = service_->GetDomainBoundCert( | |
161 host, &private_key, &der_cert, callback.callback(), &request_handle); | |
162 EXPECT_EQ(ERR_FILE_NOT_FOUND, error); | |
163 EXPECT_FALSE(request_handle.is_active()); | |
164 EXPECT_EQ(0, service_->cert_count()); | |
165 EXPECT_TRUE(der_cert.empty()); | |
166 } | |
167 | |
168 TEST_F(ServerBoundCertServiceTest, CacheHit) { | |
169 std::string host("encrypted.google.com"); | |
170 | |
171 int error; | |
172 TestCompletionCallback callback; | |
173 ServerBoundCertService::RequestHandle request_handle; | |
174 | |
175 // Asynchronous completion. | |
176 std::string private_key_info1, der_cert1; | |
177 EXPECT_EQ(0, service_->cert_count()); | |
178 error = service_->GetOrCreateDomainBoundCert( | |
179 host, &private_key_info1, &der_cert1, | |
180 callback.callback(), &request_handle); | |
181 EXPECT_EQ(ERR_IO_PENDING, error); | |
182 EXPECT_TRUE(request_handle.is_active()); | |
183 error = callback.WaitForResult(); | |
184 EXPECT_EQ(OK, error); | |
185 EXPECT_EQ(1, service_->cert_count()); | |
186 EXPECT_FALSE(private_key_info1.empty()); | |
187 EXPECT_FALSE(der_cert1.empty()); | |
188 EXPECT_FALSE(request_handle.is_active()); | |
189 | |
190 // Synchronous completion. | |
191 std::string private_key_info2, der_cert2; | |
192 error = service_->GetOrCreateDomainBoundCert( | |
193 host, &private_key_info2, &der_cert2, | |
194 callback.callback(), &request_handle); | |
195 EXPECT_FALSE(request_handle.is_active()); | |
196 EXPECT_EQ(OK, error); | |
197 EXPECT_EQ(1, service_->cert_count()); | |
198 EXPECT_EQ(private_key_info1, private_key_info2); | |
199 EXPECT_EQ(der_cert1, der_cert2); | |
200 | |
201 // Synchronous get. | |
202 std::string private_key_info3, der_cert3; | |
203 error = service_->GetDomainBoundCert( | |
204 host, &private_key_info3, &der_cert3, callback.callback(), | |
205 &request_handle); | |
206 EXPECT_FALSE(request_handle.is_active()); | |
207 EXPECT_EQ(OK, error); | |
208 EXPECT_EQ(1, service_->cert_count()); | |
209 EXPECT_EQ(der_cert1, der_cert3); | |
210 EXPECT_EQ(private_key_info1, private_key_info3); | |
211 | |
212 EXPECT_EQ(3u, service_->requests()); | |
213 EXPECT_EQ(2u, service_->cert_store_hits()); | |
214 EXPECT_EQ(0u, service_->inflight_joins()); | |
215 } | |
216 | |
217 TEST_F(ServerBoundCertServiceTest, StoreCerts) { | |
218 int error; | |
219 TestCompletionCallback callback; | |
220 ServerBoundCertService::RequestHandle request_handle; | |
221 | |
222 std::string host1("encrypted.google.com"); | |
223 std::string private_key_info1, der_cert1; | |
224 EXPECT_EQ(0, service_->cert_count()); | |
225 error = service_->GetOrCreateDomainBoundCert( | |
226 host1, &private_key_info1, &der_cert1, | |
227 callback.callback(), &request_handle); | |
228 EXPECT_EQ(ERR_IO_PENDING, error); | |
229 EXPECT_TRUE(request_handle.is_active()); | |
230 error = callback.WaitForResult(); | |
231 EXPECT_EQ(OK, error); | |
232 EXPECT_EQ(1, service_->cert_count()); | |
233 | |
234 std::string host2("www.verisign.com"); | |
235 std::string private_key_info2, der_cert2; | |
236 error = service_->GetOrCreateDomainBoundCert( | |
237 host2, &private_key_info2, &der_cert2, | |
238 callback.callback(), &request_handle); | |
239 EXPECT_EQ(ERR_IO_PENDING, error); | |
240 EXPECT_TRUE(request_handle.is_active()); | |
241 error = callback.WaitForResult(); | |
242 EXPECT_EQ(OK, error); | |
243 EXPECT_EQ(2, service_->cert_count()); | |
244 | |
245 std::string host3("www.twitter.com"); | |
246 std::string private_key_info3, der_cert3; | |
247 error = service_->GetOrCreateDomainBoundCert( | |
248 host3, &private_key_info3, &der_cert3, | |
249 callback.callback(), &request_handle); | |
250 EXPECT_EQ(ERR_IO_PENDING, error); | |
251 EXPECT_TRUE(request_handle.is_active()); | |
252 error = callback.WaitForResult(); | |
253 EXPECT_EQ(OK, error); | |
254 EXPECT_EQ(3, service_->cert_count()); | |
255 | |
256 EXPECT_NE(private_key_info1, private_key_info2); | |
257 EXPECT_NE(der_cert1, der_cert2); | |
258 EXPECT_NE(private_key_info1, private_key_info3); | |
259 EXPECT_NE(der_cert1, der_cert3); | |
260 EXPECT_NE(private_key_info2, private_key_info3); | |
261 EXPECT_NE(der_cert2, der_cert3); | |
262 } | |
263 | |
264 // Tests an inflight join. | |
265 TEST_F(ServerBoundCertServiceTest, InflightJoin) { | |
266 std::string host("encrypted.google.com"); | |
267 int error; | |
268 | |
269 std::string private_key_info1, der_cert1; | |
270 TestCompletionCallback callback1; | |
271 ServerBoundCertService::RequestHandle request_handle1; | |
272 | |
273 std::string private_key_info2, der_cert2; | |
274 TestCompletionCallback callback2; | |
275 ServerBoundCertService::RequestHandle request_handle2; | |
276 | |
277 error = service_->GetOrCreateDomainBoundCert( | |
278 host, &private_key_info1, &der_cert1, | |
279 callback1.callback(), &request_handle1); | |
280 EXPECT_EQ(ERR_IO_PENDING, error); | |
281 EXPECT_TRUE(request_handle1.is_active()); | |
282 // Should join with the original request. | |
283 error = service_->GetOrCreateDomainBoundCert( | |
284 host, &private_key_info2, &der_cert2, | |
285 callback2.callback(), &request_handle2); | |
286 EXPECT_EQ(ERR_IO_PENDING, error); | |
287 EXPECT_TRUE(request_handle2.is_active()); | |
288 | |
289 error = callback1.WaitForResult(); | |
290 EXPECT_EQ(OK, error); | |
291 error = callback2.WaitForResult(); | |
292 EXPECT_EQ(OK, error); | |
293 | |
294 EXPECT_EQ(2u, service_->requests()); | |
295 EXPECT_EQ(0u, service_->cert_store_hits()); | |
296 EXPECT_EQ(1u, service_->inflight_joins()); | |
297 EXPECT_EQ(1u, service_->workers_created()); | |
298 } | |
299 | |
300 // Tests an inflight join of a Get request to a GetOrCreate request. | |
301 TEST_F(ServerBoundCertServiceTest, InflightJoinGetOrCreateAndGet) { | |
302 std::string host("encrypted.google.com"); | |
303 int error; | |
304 | |
305 std::string private_key_info1, der_cert1; | |
306 TestCompletionCallback callback1; | |
307 ServerBoundCertService::RequestHandle request_handle1; | |
308 | |
309 std::string private_key_info2; | |
310 std::string der_cert2; | |
311 TestCompletionCallback callback2; | |
312 ServerBoundCertService::RequestHandle request_handle2; | |
313 | |
314 error = service_->GetOrCreateDomainBoundCert( | |
315 host, &private_key_info1, &der_cert1, | |
316 callback1.callback(), &request_handle1); | |
317 EXPECT_EQ(ERR_IO_PENDING, error); | |
318 EXPECT_TRUE(request_handle1.is_active()); | |
319 // Should join with the original request. | |
320 error = service_->GetDomainBoundCert( | |
321 host, &private_key_info2, &der_cert2, callback2.callback(), | |
322 &request_handle2); | |
323 EXPECT_EQ(ERR_IO_PENDING, error); | |
324 EXPECT_TRUE(request_handle2.is_active()); | |
325 | |
326 error = callback1.WaitForResult(); | |
327 EXPECT_EQ(OK, error); | |
328 error = callback2.WaitForResult(); | |
329 EXPECT_EQ(OK, error); | |
330 EXPECT_EQ(der_cert1, der_cert2); | |
331 | |
332 EXPECT_EQ(2u, service_->requests()); | |
333 EXPECT_EQ(0u, service_->cert_store_hits()); | |
334 EXPECT_EQ(1u, service_->inflight_joins()); | |
335 EXPECT_EQ(1u, service_->workers_created()); | |
336 } | |
337 | |
338 TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) { | |
339 std::string host("encrypted.google.com"); | |
340 std::string private_key_info, der_cert; | |
341 int error; | |
342 TestCompletionCallback callback; | |
343 ServerBoundCertService::RequestHandle request_handle; | |
344 | |
345 error = service_->GetOrCreateDomainBoundCert( | |
346 host, &private_key_info, &der_cert, callback.callback(), | |
347 &request_handle); | |
348 EXPECT_EQ(ERR_IO_PENDING, error); | |
349 EXPECT_TRUE(request_handle.is_active()); | |
350 error = callback.WaitForResult(); | |
351 EXPECT_EQ(OK, error); | |
352 | |
353 base::StringPiece spki_piece; | |
354 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert, &spki_piece)); | |
355 std::vector<uint8> spki( | |
356 spki_piece.data(), | |
357 spki_piece.data() + spki_piece.size()); | |
358 | |
359 // Check that we can retrieve the key from the bytes. | |
360 std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end()); | |
361 scoped_ptr<crypto::ECPrivateKey> private_key( | |
362 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | |
363 ServerBoundCertService::kEPKIPassword, key_vec, spki)); | |
364 EXPECT_TRUE(private_key != NULL); | |
365 | |
366 // Check that we can retrieve the cert from the bytes. | |
367 scoped_refptr<X509Certificate> x509cert( | |
368 X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size())); | |
369 EXPECT_TRUE(x509cert.get() != NULL); | |
370 } | |
371 | |
372 // Tests that the callback of a canceled request is never made. | |
373 TEST_F(ServerBoundCertServiceTest, CancelRequest) { | |
374 std::string host("encrypted.google.com"); | |
375 std::string private_key_info, der_cert; | |
376 int error; | |
377 ServerBoundCertService::RequestHandle request_handle; | |
378 | |
379 error = service_->GetOrCreateDomainBoundCert(host, | |
380 &private_key_info, | |
381 &der_cert, | |
382 base::Bind(&FailTest), | |
383 &request_handle); | |
384 EXPECT_EQ(ERR_IO_PENDING, error); | |
385 EXPECT_TRUE(request_handle.is_active()); | |
386 request_handle.Cancel(); | |
387 EXPECT_FALSE(request_handle.is_active()); | |
388 | |
389 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the | |
390 // ServerBoundCertService. | |
391 base::MessageLoop::current()->RunUntilIdle(); | |
392 | |
393 // Even though the original request was cancelled, the service will still | |
394 // store the result, it just doesn't call the callback. | |
395 EXPECT_EQ(1, service_->cert_count()); | |
396 } | |
397 | |
398 // Tests that destructing the RequestHandle cancels the request. | |
399 TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) { | |
400 std::string host("encrypted.google.com"); | |
401 std::string private_key_info, der_cert; | |
402 int error; | |
403 { | |
404 ServerBoundCertService::RequestHandle request_handle; | |
405 | |
406 error = service_->GetOrCreateDomainBoundCert(host, | |
407 &private_key_info, | |
408 &der_cert, | |
409 base::Bind(&FailTest), | |
410 &request_handle); | |
411 EXPECT_EQ(ERR_IO_PENDING, error); | |
412 EXPECT_TRUE(request_handle.is_active()); | |
413 } | |
414 | |
415 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the | |
416 // ServerBoundCertService. | |
417 base::MessageLoop::current()->RunUntilIdle(); | |
418 | |
419 // Even though the original request was cancelled, the service will still | |
420 // store the result, it just doesn't call the callback. | |
421 EXPECT_EQ(1, service_->cert_count()); | |
422 } | |
423 | |
424 TEST_F(ServerBoundCertServiceTest, DestructionWithPendingRequest) { | |
425 std::string host("encrypted.google.com"); | |
426 std::string private_key_info, der_cert; | |
427 int error; | |
428 ServerBoundCertService::RequestHandle request_handle; | |
429 | |
430 error = service_->GetOrCreateDomainBoundCert(host, | |
431 &private_key_info, | |
432 &der_cert, | |
433 base::Bind(&FailTest), | |
434 &request_handle); | |
435 EXPECT_EQ(ERR_IO_PENDING, error); | |
436 EXPECT_TRUE(request_handle.is_active()); | |
437 | |
438 // Cancel request and destroy the ServerBoundCertService. | |
439 request_handle.Cancel(); | |
440 service_.reset(); | |
441 | |
442 // ServerBoundCertServiceWorker should not post anything back to the | |
443 // non-existent ServerBoundCertService, but run the loop just to be sure it | |
444 // doesn't. | |
445 base::MessageLoop::current()->RunUntilIdle(); | |
446 | |
447 // If we got here without crashing or a valgrind error, it worked. | |
448 } | |
449 | |
450 // Tests that shutting down the sequenced worker pool and then making new | |
451 // requests gracefully fails. | |
452 // This is a regression test for http://crbug.com/236387 | |
453 TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) { | |
454 scoped_refptr<FailingTaskRunner> task_runner(new FailingTaskRunner); | |
455 service_.reset(new ServerBoundCertService( | |
456 new DefaultServerBoundCertStore(NULL), task_runner)); | |
457 | |
458 // Make a request that will force synchronous completion. | |
459 std::string host("encrypted.google.com"); | |
460 std::string private_key_info, der_cert; | |
461 int error; | |
462 ServerBoundCertService::RequestHandle request_handle; | |
463 | |
464 error = service_->GetOrCreateDomainBoundCert(host, | |
465 &private_key_info, | |
466 &der_cert, | |
467 base::Bind(&FailTest), | |
468 &request_handle); | |
469 // If we got here without crashing or a valgrind error, it worked. | |
470 ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES, error); | |
471 EXPECT_FALSE(request_handle.is_active()); | |
472 } | |
473 | |
474 // Tests that simultaneous creation of different certs works. | |
475 TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { | |
476 int error; | |
477 | |
478 std::string host1("encrypted.google.com"); | |
479 std::string private_key_info1, der_cert1; | |
480 TestCompletionCallback callback1; | |
481 ServerBoundCertService::RequestHandle request_handle1; | |
482 | |
483 std::string host2("foo.com"); | |
484 std::string private_key_info2, der_cert2; | |
485 TestCompletionCallback callback2; | |
486 ServerBoundCertService::RequestHandle request_handle2; | |
487 | |
488 std::string host3("bar.com"); | |
489 std::string private_key_info3, der_cert3; | |
490 TestCompletionCallback callback3; | |
491 ServerBoundCertService::RequestHandle request_handle3; | |
492 | |
493 error = service_->GetOrCreateDomainBoundCert(host1, | |
494 &private_key_info1, | |
495 &der_cert1, | |
496 callback1.callback(), | |
497 &request_handle1); | |
498 EXPECT_EQ(ERR_IO_PENDING, error); | |
499 EXPECT_TRUE(request_handle1.is_active()); | |
500 | |
501 error = service_->GetOrCreateDomainBoundCert(host2, | |
502 &private_key_info2, | |
503 &der_cert2, | |
504 callback2.callback(), | |
505 &request_handle2); | |
506 EXPECT_EQ(ERR_IO_PENDING, error); | |
507 EXPECT_TRUE(request_handle2.is_active()); | |
508 | |
509 error = service_->GetOrCreateDomainBoundCert(host3, | |
510 &private_key_info3, | |
511 &der_cert3, | |
512 callback3.callback(), | |
513 &request_handle3); | |
514 EXPECT_EQ(ERR_IO_PENDING, error); | |
515 EXPECT_TRUE(request_handle3.is_active()); | |
516 | |
517 error = callback1.WaitForResult(); | |
518 EXPECT_EQ(OK, error); | |
519 EXPECT_FALSE(private_key_info1.empty()); | |
520 EXPECT_FALSE(der_cert1.empty()); | |
521 | |
522 error = callback2.WaitForResult(); | |
523 EXPECT_EQ(OK, error); | |
524 EXPECT_FALSE(private_key_info2.empty()); | |
525 EXPECT_FALSE(der_cert2.empty()); | |
526 | |
527 error = callback3.WaitForResult(); | |
528 EXPECT_EQ(OK, error); | |
529 EXPECT_FALSE(private_key_info3.empty()); | |
530 EXPECT_FALSE(der_cert3.empty()); | |
531 | |
532 EXPECT_NE(private_key_info1, private_key_info2); | |
533 EXPECT_NE(der_cert1, der_cert2); | |
534 | |
535 EXPECT_NE(private_key_info1, private_key_info3); | |
536 EXPECT_NE(der_cert1, der_cert3); | |
537 | |
538 EXPECT_NE(private_key_info2, private_key_info3); | |
539 EXPECT_NE(der_cert2, der_cert3); | |
540 | |
541 EXPECT_EQ(3, service_->cert_count()); | |
542 } | |
543 | |
544 TEST_F(ServerBoundCertServiceTest, Expiration) { | |
545 ServerBoundCertStore* store = service_->GetCertStore(); | |
546 base::Time now = base::Time::Now(); | |
547 store->SetServerBoundCert("good", | |
548 now, | |
549 now + base::TimeDelta::FromDays(1), | |
550 "a", | |
551 "b"); | |
552 store->SetServerBoundCert("expired", | |
553 now - base::TimeDelta::FromDays(2), | |
554 now - base::TimeDelta::FromDays(1), | |
555 "c", | |
556 "d"); | |
557 EXPECT_EQ(2, service_->cert_count()); | |
558 | |
559 int error; | |
560 TestCompletionCallback callback; | |
561 ServerBoundCertService::RequestHandle request_handle; | |
562 | |
563 // Cert is valid - synchronous completion. | |
564 std::string private_key_info1, der_cert1; | |
565 error = service_->GetOrCreateDomainBoundCert( | |
566 "good", &private_key_info1, &der_cert1, | |
567 callback.callback(), &request_handle); | |
568 EXPECT_EQ(OK, error); | |
569 EXPECT_FALSE(request_handle.is_active()); | |
570 EXPECT_EQ(2, service_->cert_count()); | |
571 EXPECT_STREQ("a", private_key_info1.c_str()); | |
572 EXPECT_STREQ("b", der_cert1.c_str()); | |
573 | |
574 // Expired cert is valid as well - synchronous completion. | |
575 std::string private_key_info2, der_cert2; | |
576 error = service_->GetOrCreateDomainBoundCert( | |
577 "expired", &private_key_info2, &der_cert2, | |
578 callback.callback(), &request_handle); | |
579 EXPECT_EQ(OK, error); | |
580 EXPECT_FALSE(request_handle.is_active()); | |
581 EXPECT_EQ(2, service_->cert_count()); | |
582 EXPECT_STREQ("c", private_key_info2.c_str()); | |
583 EXPECT_STREQ("d", der_cert2.c_str()); | |
584 } | |
585 | |
586 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOrCreateNoCertsInStore) { | |
587 MockServerBoundCertStoreWithAsyncGet* mock_store = | |
588 new MockServerBoundCertStoreWithAsyncGet(); | |
589 service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService( | |
590 mock_store, base::MessageLoopProxy::current())); | |
591 | |
592 std::string host("encrypted.google.com"); | |
593 | |
594 int error; | |
595 TestCompletionCallback callback; | |
596 ServerBoundCertService::RequestHandle request_handle; | |
597 | |
598 // Asynchronous completion with no certs in the store. | |
599 std::string private_key_info, der_cert; | |
600 EXPECT_EQ(0, service_->cert_count()); | |
601 error = service_->GetOrCreateDomainBoundCert( | |
602 host, &private_key_info, &der_cert, callback.callback(), &request_handle); | |
603 EXPECT_EQ(ERR_IO_PENDING, error); | |
604 EXPECT_TRUE(request_handle.is_active()); | |
605 | |
606 mock_store->CallGetServerBoundCertCallbackWithResult( | |
607 ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string()); | |
608 | |
609 error = callback.WaitForResult(); | |
610 EXPECT_EQ(OK, error); | |
611 EXPECT_EQ(1, service_->cert_count()); | |
612 EXPECT_FALSE(private_key_info.empty()); | |
613 EXPECT_FALSE(der_cert.empty()); | |
614 EXPECT_FALSE(request_handle.is_active()); | |
615 } | |
616 | |
617 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetNoCertsInStore) { | |
618 MockServerBoundCertStoreWithAsyncGet* mock_store = | |
619 new MockServerBoundCertStoreWithAsyncGet(); | |
620 service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService( | |
621 mock_store, base::MessageLoopProxy::current())); | |
622 | |
623 std::string host("encrypted.google.com"); | |
624 | |
625 int error; | |
626 TestCompletionCallback callback; | |
627 ServerBoundCertService::RequestHandle request_handle; | |
628 | |
629 // Asynchronous completion with no certs in the store. | |
630 std::string private_key, der_cert; | |
631 EXPECT_EQ(0, service_->cert_count()); | |
632 error = service_->GetDomainBoundCert( | |
633 host, &private_key, &der_cert, callback.callback(), &request_handle); | |
634 EXPECT_EQ(ERR_IO_PENDING, error); | |
635 EXPECT_TRUE(request_handle.is_active()); | |
636 | |
637 mock_store->CallGetServerBoundCertCallbackWithResult( | |
638 ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string()); | |
639 | |
640 error = callback.WaitForResult(); | |
641 EXPECT_EQ(ERR_FILE_NOT_FOUND, error); | |
642 EXPECT_EQ(0, service_->cert_count()); | |
643 EXPECT_EQ(0u, service_->workers_created()); | |
644 EXPECT_TRUE(der_cert.empty()); | |
645 EXPECT_FALSE(request_handle.is_active()); | |
646 } | |
647 | |
648 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOrCreateOneCertInStore) { | |
649 MockServerBoundCertStoreWithAsyncGet* mock_store = | |
650 new MockServerBoundCertStoreWithAsyncGet(); | |
651 service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService( | |
652 mock_store, base::MessageLoopProxy::current())); | |
653 | |
654 std::string host("encrypted.google.com"); | |
655 | |
656 int error; | |
657 TestCompletionCallback callback; | |
658 ServerBoundCertService::RequestHandle request_handle; | |
659 | |
660 // Asynchronous completion with a cert in the store. | |
661 std::string private_key_info, der_cert; | |
662 EXPECT_EQ(0, service_->cert_count()); | |
663 error = service_->GetOrCreateDomainBoundCert( | |
664 host, &private_key_info, &der_cert, callback.callback(), &request_handle); | |
665 EXPECT_EQ(ERR_IO_PENDING, error); | |
666 EXPECT_TRUE(request_handle.is_active()); | |
667 | |
668 mock_store->CallGetServerBoundCertCallbackWithResult( | |
669 OK, base::Time(), "ab", "cd"); | |
670 | |
671 error = callback.WaitForResult(); | |
672 EXPECT_EQ(OK, error); | |
673 EXPECT_EQ(1, service_->cert_count()); | |
674 EXPECT_EQ(1u, service_->requests()); | |
675 EXPECT_EQ(1u, service_->cert_store_hits()); | |
676 // Because the cert was found in the store, no new workers should have been | |
677 // created. | |
678 EXPECT_EQ(0u, service_->workers_created()); | |
679 EXPECT_STREQ("ab", private_key_info.c_str()); | |
680 EXPECT_STREQ("cd", der_cert.c_str()); | |
681 EXPECT_FALSE(request_handle.is_active()); | |
682 } | |
683 | |
684 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOneCertInStore) { | |
685 MockServerBoundCertStoreWithAsyncGet* mock_store = | |
686 new MockServerBoundCertStoreWithAsyncGet(); | |
687 service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService( | |
688 mock_store, base::MessageLoopProxy::current())); | |
689 | |
690 std::string host("encrypted.google.com"); | |
691 | |
692 int error; | |
693 TestCompletionCallback callback; | |
694 ServerBoundCertService::RequestHandle request_handle; | |
695 | |
696 // Asynchronous completion with a cert in the store. | |
697 std::string private_key, der_cert; | |
698 EXPECT_EQ(0, service_->cert_count()); | |
699 error = service_->GetDomainBoundCert( | |
700 host, &private_key, &der_cert, callback.callback(), &request_handle); | |
701 EXPECT_EQ(ERR_IO_PENDING, error); | |
702 EXPECT_TRUE(request_handle.is_active()); | |
703 | |
704 mock_store->CallGetServerBoundCertCallbackWithResult( | |
705 OK, base::Time(), "ab", "cd"); | |
706 | |
707 error = callback.WaitForResult(); | |
708 EXPECT_EQ(OK, error); | |
709 EXPECT_EQ(1, service_->cert_count()); | |
710 EXPECT_EQ(1u, service_->requests()); | |
711 EXPECT_EQ(1u, service_->cert_store_hits()); | |
712 // Because the cert was found in the store, no new workers should have been | |
713 // created. | |
714 EXPECT_EQ(0u, service_->workers_created()); | |
715 EXPECT_STREQ("cd", der_cert.c_str()); | |
716 EXPECT_FALSE(request_handle.is_active()); | |
717 } | |
718 | |
719 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetThenCreateNoCertsInStore) { | |
720 MockServerBoundCertStoreWithAsyncGet* mock_store = | |
721 new MockServerBoundCertStoreWithAsyncGet(); | |
722 service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService( | |
723 mock_store, base::MessageLoopProxy::current())); | |
724 | |
725 std::string host("encrypted.google.com"); | |
726 | |
727 int error; | |
728 | |
729 // Asynchronous get with no certs in the store. | |
730 TestCompletionCallback callback1; | |
731 ServerBoundCertService::RequestHandle request_handle1; | |
732 std::string private_key1, der_cert1; | |
733 EXPECT_EQ(0, service_->cert_count()); | |
734 error = service_->GetDomainBoundCert( | |
735 host, &private_key1, &der_cert1, callback1.callback(), &request_handle1); | |
736 EXPECT_EQ(ERR_IO_PENDING, error); | |
737 EXPECT_TRUE(request_handle1.is_active()); | |
738 | |
739 // Asynchronous get/create with no certs in the store. | |
740 TestCompletionCallback callback2; | |
741 ServerBoundCertService::RequestHandle request_handle2; | |
742 std::string private_key2, der_cert2; | |
743 EXPECT_EQ(0, service_->cert_count()); | |
744 error = service_->GetOrCreateDomainBoundCert( | |
745 host, &private_key2, &der_cert2, callback2.callback(), &request_handle2); | |
746 EXPECT_EQ(ERR_IO_PENDING, error); | |
747 EXPECT_TRUE(request_handle2.is_active()); | |
748 | |
749 mock_store->CallGetServerBoundCertCallbackWithResult( | |
750 ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string()); | |
751 | |
752 // Even though the first request didn't ask to create a cert, it gets joined | |
753 // by the second, which does, so both succeed. | |
754 error = callback1.WaitForResult(); | |
755 EXPECT_EQ(OK, error); | |
756 error = callback2.WaitForResult(); | |
757 EXPECT_EQ(OK, error); | |
758 | |
759 // One cert is created, one request is joined. | |
760 EXPECT_EQ(2U, service_->requests()); | |
761 EXPECT_EQ(1, service_->cert_count()); | |
762 EXPECT_EQ(1u, service_->workers_created()); | |
763 EXPECT_EQ(1u, service_->inflight_joins()); | |
764 EXPECT_FALSE(der_cert1.empty()); | |
765 EXPECT_EQ(der_cert1, der_cert2); | |
766 EXPECT_FALSE(private_key1.empty()); | |
767 EXPECT_EQ(private_key1, private_key2); | |
768 EXPECT_FALSE(request_handle1.is_active()); | |
769 EXPECT_FALSE(request_handle2.is_active()); | |
770 } | |
771 | |
772 } // namespace | |
773 | |
774 } // namespace net | |
OLD | NEW |