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.
5 #include "net/ssl/default_server_bound_cert_store.h"
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 void CallCounter(int* counter
) {
27 ADD_FAILURE() << "Unexpected callback execution.";
30 void GetCertCallbackNotCalled(const std::string
& server_identifier
,
31 SSLClientCertType type
,
32 base::Time expiration_time
,
33 const std::string
& private_key_result
,
34 const std::string
& cert_result
) {
35 ADD_FAILURE() << "Unexpected callback execution.";
38 class AsyncGetCertHelper
{
40 AsyncGetCertHelper() : called_(false) {}
42 void Callback(const std::string
& server_identifier
,
43 SSLClientCertType type
,
44 base::Time expiration_time
,
45 const std::string
& private_key_result
,
46 const std::string
& cert_result
) {
47 server_identifier_
= server_identifier
;
49 expiration_time_
= expiration_time
;
50 private_key_
= private_key_result
;
55 std::string server_identifier_
;
56 SSLClientCertType type_
;
57 base::Time expiration_time_
;
58 std::string private_key_
;
64 ServerBoundCertStore::ServerBoundCertList
* dest
,
65 const ServerBoundCertStore::ServerBoundCertList
& result
) {
69 class MockPersistentStore
70 : public DefaultServerBoundCertStore::PersistentStore
{
72 MockPersistentStore();
74 // DefaultServerBoundCertStore::PersistentStore implementation.
75 virtual void Load(const LoadedCallback
& loaded_callback
) OVERRIDE
;
76 virtual void AddServerBoundCert(
77 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) OVERRIDE
;
78 virtual void DeleteServerBoundCert(
79 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) OVERRIDE
;
80 virtual void SetForceKeepSessionState() OVERRIDE
;
83 virtual ~MockPersistentStore();
86 typedef std::map
<std::string
, DefaultServerBoundCertStore::ServerBoundCert
>
89 ServerBoundCertMap origin_certs_
;
92 MockPersistentStore::MockPersistentStore() {}
94 void MockPersistentStore::Load(const LoadedCallback
& loaded_callback
) {
95 scoped_ptr
<ScopedVector
<DefaultServerBoundCertStore::ServerBoundCert
> >
96 certs(new ScopedVector
<DefaultServerBoundCertStore::ServerBoundCert
>());
97 ServerBoundCertMap::iterator it
;
99 for (it
= origin_certs_
.begin(); it
!= origin_certs_
.end(); ++it
) {
101 new DefaultServerBoundCertStore::ServerBoundCert(it
->second
));
104 MessageLoop::current()->PostTask(
105 FROM_HERE
, base::Bind(loaded_callback
, base::Passed(&certs
)));
108 void MockPersistentStore::AddServerBoundCert(
109 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) {
110 origin_certs_
[cert
.server_identifier()] = cert
;
113 void MockPersistentStore::DeleteServerBoundCert(
114 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) {
115 origin_certs_
.erase(cert
.server_identifier());
118 void MockPersistentStore::SetForceKeepSessionState() {}
120 MockPersistentStore::~MockPersistentStore() {}
124 TEST(DefaultServerBoundCertStoreTest
, TestLoading
) {
125 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
127 persistent_store
->AddServerBoundCert(
128 DefaultServerBoundCertStore::ServerBoundCert(
130 CLIENT_CERT_RSA_SIGN
,
134 persistent_store
->AddServerBoundCert(
135 DefaultServerBoundCertStore::ServerBoundCert(
137 CLIENT_CERT_ECDSA_SIGN
,
142 // Make sure certs load properly.
143 DefaultServerBoundCertStore
store(persistent_store
.get());
144 // Load has not occurred yet.
145 EXPECT_EQ(0, store
.GetCertCount());
146 store
.SetServerBoundCert(
148 CLIENT_CERT_RSA_SIGN
,
152 // Wait for load & queued set task.
153 MessageLoop::current()->RunUntilIdle();
154 EXPECT_EQ(2, store
.GetCertCount());
155 store
.SetServerBoundCert(
157 CLIENT_CERT_RSA_SIGN
,
161 // Set should be synchronous now that load is done.
162 EXPECT_EQ(3, store
.GetCertCount());
165 //TODO(mattm): add more tests of without a persistent store?
166 TEST(DefaultServerBoundCertStoreTest
, TestSettingAndGetting
) {
167 // No persistent store, all calls will be synchronous.
168 DefaultServerBoundCertStore
store(NULL
);
169 SSLClientCertType type
;
170 base::Time expiration_time
;
171 std::string private_key
, cert
;
172 EXPECT_EQ(0, store
.GetCertCount());
173 EXPECT_TRUE(store
.GetServerBoundCert("verisign.com",
178 base::Bind(&GetCertCallbackNotCalled
)));
179 EXPECT_EQ(CLIENT_CERT_INVALID_TYPE
, type
);
180 EXPECT_TRUE(private_key
.empty());
181 EXPECT_TRUE(cert
.empty());
182 store
.SetServerBoundCert(
184 CLIENT_CERT_RSA_SIGN
,
185 base::Time::FromInternalValue(123),
186 base::Time::FromInternalValue(456),
188 EXPECT_TRUE(store
.GetServerBoundCert("verisign.com",
193 base::Bind(&GetCertCallbackNotCalled
)));
194 EXPECT_EQ(CLIENT_CERT_RSA_SIGN
, type
);
195 EXPECT_EQ(456, expiration_time
.ToInternalValue());
196 EXPECT_EQ("i", private_key
);
197 EXPECT_EQ("j", cert
);
200 TEST(DefaultServerBoundCertStoreTest
, TestDuplicateCerts
) {
201 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
202 DefaultServerBoundCertStore
store(persistent_store
.get());
204 SSLClientCertType type
;
205 base::Time expiration_time
;
206 std::string private_key
, cert
;
207 EXPECT_EQ(0, store
.GetCertCount());
208 store
.SetServerBoundCert(
210 CLIENT_CERT_RSA_SIGN
,
211 base::Time::FromInternalValue(123),
212 base::Time::FromInternalValue(1234),
214 store
.SetServerBoundCert(
216 CLIENT_CERT_ECDSA_SIGN
,
217 base::Time::FromInternalValue(456),
218 base::Time::FromInternalValue(4567),
221 // Wait for load & queued set tasks.
222 MessageLoop::current()->RunUntilIdle();
223 EXPECT_EQ(1, store
.GetCertCount());
224 EXPECT_TRUE(store
.GetServerBoundCert("verisign.com",
229 base::Bind(&GetCertCallbackNotCalled
)));
230 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type
);
231 EXPECT_EQ(4567, expiration_time
.ToInternalValue());
232 EXPECT_EQ("c", private_key
);
233 EXPECT_EQ("d", cert
);
236 TEST(DefaultServerBoundCertStoreTest
, TestAsyncGet
) {
237 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
238 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
240 CLIENT_CERT_RSA_SIGN
,
241 base::Time::FromInternalValue(123),
242 base::Time::FromInternalValue(1234),
245 DefaultServerBoundCertStore
store(persistent_store
.get());
246 AsyncGetCertHelper helper
;
247 SSLClientCertType type
;
248 base::Time expiration_time
;
249 std::string private_key
;
250 std::string cert
= "not set";
251 EXPECT_EQ(0, store
.GetCertCount());
252 EXPECT_FALSE(store
.GetServerBoundCert(
253 "verisign.com", &type
, &expiration_time
, &private_key
, &cert
,
254 base::Bind(&AsyncGetCertHelper::Callback
, base::Unretained(&helper
))));
256 // Wait for load & queued get tasks.
257 MessageLoop::current()->RunUntilIdle();
258 EXPECT_EQ(1, store
.GetCertCount());
259 EXPECT_EQ("not set", cert
);
260 EXPECT_TRUE(helper
.called_
);
261 EXPECT_EQ("verisign.com", helper
.server_identifier_
);
262 EXPECT_EQ(CLIENT_CERT_RSA_SIGN
, helper
.type_
);
263 EXPECT_EQ(1234, helper
.expiration_time_
.ToInternalValue());
264 EXPECT_EQ("a", helper
.private_key_
);
265 EXPECT_EQ("b", helper
.cert_
);
268 TEST(DefaultServerBoundCertStoreTest
, TestDeleteAll
) {
269 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
270 DefaultServerBoundCertStore
store(persistent_store
.get());
272 store
.SetServerBoundCert(
274 CLIENT_CERT_RSA_SIGN
,
278 store
.SetServerBoundCert(
280 CLIENT_CERT_RSA_SIGN
,
284 store
.SetServerBoundCert(
286 CLIENT_CERT_RSA_SIGN
,
290 // Wait for load & queued set tasks.
291 MessageLoop::current()->RunUntilIdle();
293 EXPECT_EQ(3, store
.GetCertCount());
294 int delete_finished
= 0;
295 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
296 ASSERT_EQ(1, delete_finished
);
297 EXPECT_EQ(0, store
.GetCertCount());
300 TEST(DefaultServerBoundCertStoreTest
, TestAsyncGetAndDeleteAll
) {
301 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
302 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
304 CLIENT_CERT_RSA_SIGN
,
308 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
310 CLIENT_CERT_RSA_SIGN
,
315 ServerBoundCertStore::ServerBoundCertList pre_certs
;
316 ServerBoundCertStore::ServerBoundCertList post_certs
;
317 int delete_finished
= 0;
318 DefaultServerBoundCertStore
store(persistent_store
.get());
320 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &pre_certs
));
321 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
322 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &post_certs
));
323 // Tasks have not run yet.
324 EXPECT_EQ(0u, pre_certs
.size());
325 // Wait for load & queued tasks.
326 MessageLoop::current()->RunUntilIdle();
327 EXPECT_EQ(0, store
.GetCertCount());
328 EXPECT_EQ(2u, pre_certs
.size());
329 EXPECT_EQ(0u, post_certs
.size());
332 TEST(DefaultServerBoundCertStoreTest
, TestDelete
) {
333 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
334 DefaultServerBoundCertStore
store(persistent_store
.get());
336 SSLClientCertType type
;
337 base::Time expiration_time
;
338 std::string private_key
, cert
;
339 EXPECT_EQ(0, store
.GetCertCount());
340 store
.SetServerBoundCert(
342 CLIENT_CERT_RSA_SIGN
,
346 // Wait for load & queued set task.
347 MessageLoop::current()->RunUntilIdle();
349 store
.SetServerBoundCert(
351 CLIENT_CERT_ECDSA_SIGN
,
356 EXPECT_EQ(2, store
.GetCertCount());
357 int delete_finished
= 0;
358 store
.DeleteServerBoundCert("verisign.com",
359 base::Bind(&CallCounter
, &delete_finished
));
360 ASSERT_EQ(1, delete_finished
);
361 EXPECT_EQ(1, store
.GetCertCount());
362 EXPECT_TRUE(store
.GetServerBoundCert("verisign.com",
367 base::Bind(&GetCertCallbackNotCalled
)));
368 EXPECT_EQ(CLIENT_CERT_INVALID_TYPE
, type
);
369 EXPECT_TRUE(store
.GetServerBoundCert("google.com",
374 base::Bind(&GetCertCallbackNotCalled
)));
375 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type
);
376 int delete2_finished
= 0;
377 store
.DeleteServerBoundCert("google.com",
378 base::Bind(&CallCounter
, &delete2_finished
));
379 ASSERT_EQ(1, delete2_finished
);
380 EXPECT_EQ(0, store
.GetCertCount());
381 EXPECT_TRUE(store
.GetServerBoundCert("google.com",
386 base::Bind(&GetCertCallbackNotCalled
)));
387 EXPECT_EQ(CLIENT_CERT_INVALID_TYPE
, type
);
390 TEST(DefaultServerBoundCertStoreTest
, TestAsyncDelete
) {
391 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
392 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
394 CLIENT_CERT_RSA_SIGN
,
395 base::Time::FromInternalValue(1),
396 base::Time::FromInternalValue(2),
398 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
400 CLIENT_CERT_RSA_SIGN
,
401 base::Time::FromInternalValue(3),
402 base::Time::FromInternalValue(4),
404 DefaultServerBoundCertStore
store(persistent_store
.get());
405 int delete_finished
= 0;
406 store
.DeleteServerBoundCert("a.com",
407 base::Bind(&CallCounter
, &delete_finished
));
409 AsyncGetCertHelper a_helper
;
410 AsyncGetCertHelper b_helper
;
411 SSLClientCertType type
;
412 base::Time expiration_time
;
413 std::string private_key
;
414 std::string cert
= "not set";
415 EXPECT_EQ(0, store
.GetCertCount());
416 EXPECT_FALSE(store
.GetServerBoundCert(
417 "a.com", &type
, &expiration_time
, &private_key
, &cert
,
418 base::Bind(&AsyncGetCertHelper::Callback
, base::Unretained(&a_helper
))));
419 EXPECT_FALSE(store
.GetServerBoundCert(
420 "b.com", &type
, &expiration_time
, &private_key
, &cert
,
421 base::Bind(&AsyncGetCertHelper::Callback
, base::Unretained(&b_helper
))));
423 EXPECT_EQ(0, delete_finished
);
424 EXPECT_FALSE(a_helper
.called_
);
425 EXPECT_FALSE(b_helper
.called_
);
426 // Wait for load & queued tasks.
427 MessageLoop::current()->RunUntilIdle();
428 EXPECT_EQ(1, delete_finished
);
429 EXPECT_EQ(1, store
.GetCertCount());
430 EXPECT_EQ("not set", cert
);
431 EXPECT_TRUE(a_helper
.called_
);
432 EXPECT_EQ("a.com", a_helper
.server_identifier_
);
433 EXPECT_EQ(CLIENT_CERT_INVALID_TYPE
, a_helper
.type_
);
434 EXPECT_EQ(0, a_helper
.expiration_time_
.ToInternalValue());
435 EXPECT_EQ("", a_helper
.private_key_
);
436 EXPECT_EQ("", a_helper
.cert_
);
437 EXPECT_TRUE(b_helper
.called_
);
438 EXPECT_EQ("b.com", b_helper
.server_identifier_
);
439 EXPECT_EQ(CLIENT_CERT_RSA_SIGN
, b_helper
.type_
);
440 EXPECT_EQ(4, b_helper
.expiration_time_
.ToInternalValue());
441 EXPECT_EQ("c", b_helper
.private_key_
);
442 EXPECT_EQ("d", b_helper
.cert_
);
445 TEST(DefaultServerBoundCertStoreTest
, TestGetAll
) {
446 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
447 DefaultServerBoundCertStore
store(persistent_store
.get());
449 EXPECT_EQ(0, store
.GetCertCount());
450 store
.SetServerBoundCert(
452 CLIENT_CERT_RSA_SIGN
,
456 store
.SetServerBoundCert(
458 CLIENT_CERT_ECDSA_SIGN
,
462 store
.SetServerBoundCert(
464 CLIENT_CERT_RSA_SIGN
,
468 store
.SetServerBoundCert(
470 CLIENT_CERT_RSA_SIGN
,
474 // Wait for load & queued set tasks.
475 MessageLoop::current()->RunUntilIdle();
477 EXPECT_EQ(4, store
.GetCertCount());
478 ServerBoundCertStore::ServerBoundCertList certs
;
479 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
480 EXPECT_EQ(4u, certs
.size());
483 TEST(DefaultServerBoundCertStoreTest
, TestInitializeFrom
) {
484 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
485 DefaultServerBoundCertStore
store(persistent_store
.get());
487 store
.SetServerBoundCert(
489 CLIENT_CERT_RSA_SIGN
,
493 store
.SetServerBoundCert(
495 CLIENT_CERT_ECDSA_SIGN
,
499 // Wait for load & queued set tasks.
500 MessageLoop::current()->RunUntilIdle();
501 EXPECT_EQ(2, store
.GetCertCount());
503 ServerBoundCertStore::ServerBoundCertList source_certs
;
504 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
506 CLIENT_CERT_RSA_SIGN
,
509 // Key differs from above to test that existing entries are overwritten.
511 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
513 CLIENT_CERT_RSA_SIGN
,
517 store
.InitializeFrom(source_certs
);
518 EXPECT_EQ(3, store
.GetCertCount());
520 ServerBoundCertStore::ServerBoundCertList certs
;
521 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
522 ASSERT_EQ(3u, certs
.size());
524 ServerBoundCertStore::ServerBoundCertList::iterator cert
= certs
.begin();
525 EXPECT_EQ("both.com", cert
->server_identifier());
526 EXPECT_EQ("e", cert
->private_key());
529 EXPECT_EQ("copied.com", cert
->server_identifier());
530 EXPECT_EQ("g", cert
->private_key());
533 EXPECT_EQ("preexisting.com", cert
->server_identifier());
534 EXPECT_EQ("a", cert
->private_key());
537 TEST(DefaultServerBoundCertStoreTest
, TestAsyncInitializeFrom
) {
538 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
539 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
541 CLIENT_CERT_RSA_SIGN
,
545 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
547 CLIENT_CERT_RSA_SIGN
,
552 DefaultServerBoundCertStore
store(persistent_store
.get());
553 ServerBoundCertStore::ServerBoundCertList source_certs
;
554 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
556 CLIENT_CERT_RSA_SIGN
,
559 // Key differs from above to test that existing entries are overwritten.
561 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
563 CLIENT_CERT_RSA_SIGN
,
567 store
.InitializeFrom(source_certs
);
568 EXPECT_EQ(0, store
.GetCertCount());
569 // Wait for load & queued tasks.
570 MessageLoop::current()->RunUntilIdle();
571 EXPECT_EQ(3, store
.GetCertCount());
573 ServerBoundCertStore::ServerBoundCertList certs
;
574 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
575 ASSERT_EQ(3u, certs
.size());
577 ServerBoundCertStore::ServerBoundCertList::iterator cert
= certs
.begin();
578 EXPECT_EQ("both.com", cert
->server_identifier());
579 EXPECT_EQ("e", cert
->private_key());
582 EXPECT_EQ("copied.com", cert
->server_identifier());
583 EXPECT_EQ("g", cert
->private_key());
586 EXPECT_EQ("preexisting.com", cert
->server_identifier());
587 EXPECT_EQ("a", cert
->private_key());