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/message_loop.h"
16 #include "net/base/net_errors.h"
17 #include "testing/gtest/include/gtest/gtest.h"
23 void CallCounter(int* counter
) {
27 void GetCertCallbackNotCalled(int err
,
28 const std::string
& server_identifier
,
29 base::Time expiration_time
,
30 const std::string
& private_key_result
,
31 const std::string
& cert_result
) {
32 ADD_FAILURE() << "Unexpected callback execution.";
35 class AsyncGetCertHelper
{
37 AsyncGetCertHelper() : called_(false) {}
39 void Callback(int err
,
40 const std::string
& server_identifier
,
41 base::Time expiration_time
,
42 const std::string
& private_key_result
,
43 const std::string
& cert_result
) {
45 server_identifier_
= server_identifier
;
46 expiration_time_
= expiration_time
;
47 private_key_
= private_key_result
;
53 std::string server_identifier_
;
54 base::Time expiration_time_
;
55 std::string private_key_
;
61 ServerBoundCertStore::ServerBoundCertList
* dest
,
62 const ServerBoundCertStore::ServerBoundCertList
& result
) {
66 class MockPersistentStore
67 : public DefaultServerBoundCertStore::PersistentStore
{
69 MockPersistentStore();
71 // DefaultServerBoundCertStore::PersistentStore implementation.
72 virtual void Load(const LoadedCallback
& loaded_callback
) OVERRIDE
;
73 virtual void AddServerBoundCert(
74 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) OVERRIDE
;
75 virtual void DeleteServerBoundCert(
76 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) OVERRIDE
;
77 virtual void SetForceKeepSessionState() OVERRIDE
;
80 virtual ~MockPersistentStore();
83 typedef std::map
<std::string
, DefaultServerBoundCertStore::ServerBoundCert
>
86 ServerBoundCertMap origin_certs_
;
89 MockPersistentStore::MockPersistentStore() {}
91 void MockPersistentStore::Load(const LoadedCallback
& loaded_callback
) {
92 scoped_ptr
<ScopedVector
<DefaultServerBoundCertStore::ServerBoundCert
> >
93 certs(new ScopedVector
<DefaultServerBoundCertStore::ServerBoundCert
>());
94 ServerBoundCertMap::iterator it
;
96 for (it
= origin_certs_
.begin(); it
!= origin_certs_
.end(); ++it
) {
98 new DefaultServerBoundCertStore::ServerBoundCert(it
->second
));
101 base::MessageLoop::current()->PostTask(
102 FROM_HERE
, base::Bind(loaded_callback
, base::Passed(&certs
)));
105 void MockPersistentStore::AddServerBoundCert(
106 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) {
107 origin_certs_
[cert
.server_identifier()] = cert
;
110 void MockPersistentStore::DeleteServerBoundCert(
111 const DefaultServerBoundCertStore::ServerBoundCert
& cert
) {
112 origin_certs_
.erase(cert
.server_identifier());
115 void MockPersistentStore::SetForceKeepSessionState() {}
117 MockPersistentStore::~MockPersistentStore() {}
121 TEST(DefaultServerBoundCertStoreTest
, TestLoading
) {
122 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
124 persistent_store
->AddServerBoundCert(
125 DefaultServerBoundCertStore::ServerBoundCert(
130 persistent_store
->AddServerBoundCert(
131 DefaultServerBoundCertStore::ServerBoundCert(
137 // Make sure certs load properly.
138 DefaultServerBoundCertStore
store(persistent_store
.get());
139 // Load has not occurred yet.
140 EXPECT_EQ(0, store
.GetCertCount());
141 store
.SetServerBoundCert(
146 // Wait for load & queued set task.
147 base::MessageLoop::current()->RunUntilIdle();
148 EXPECT_EQ(2, store
.GetCertCount());
149 store
.SetServerBoundCert(
154 // Set should be synchronous now that load is done.
155 EXPECT_EQ(3, store
.GetCertCount());
158 //TODO(mattm): add more tests of without a persistent store?
159 TEST(DefaultServerBoundCertStoreTest
, TestSettingAndGetting
) {
160 // No persistent store, all calls will be synchronous.
161 DefaultServerBoundCertStore
store(NULL
);
162 base::Time expiration_time
;
163 std::string private_key
, cert
;
164 EXPECT_EQ(0, store
.GetCertCount());
165 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
166 store
.GetServerBoundCert("verisign.com",
170 base::Bind(&GetCertCallbackNotCalled
)));
171 EXPECT_TRUE(private_key
.empty());
172 EXPECT_TRUE(cert
.empty());
173 store
.SetServerBoundCert(
175 base::Time::FromInternalValue(123),
176 base::Time::FromInternalValue(456),
179 store
.GetServerBoundCert("verisign.com",
183 base::Bind(&GetCertCallbackNotCalled
)));
184 EXPECT_EQ(456, expiration_time
.ToInternalValue());
185 EXPECT_EQ("i", private_key
);
186 EXPECT_EQ("j", cert
);
189 TEST(DefaultServerBoundCertStoreTest
, TestDuplicateCerts
) {
190 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
191 DefaultServerBoundCertStore
store(persistent_store
.get());
193 base::Time expiration_time
;
194 std::string private_key
, cert
;
195 EXPECT_EQ(0, store
.GetCertCount());
196 store
.SetServerBoundCert(
198 base::Time::FromInternalValue(123),
199 base::Time::FromInternalValue(1234),
201 store
.SetServerBoundCert(
203 base::Time::FromInternalValue(456),
204 base::Time::FromInternalValue(4567),
207 // Wait for load & queued set tasks.
208 base::MessageLoop::current()->RunUntilIdle();
209 EXPECT_EQ(1, store
.GetCertCount());
211 store
.GetServerBoundCert("verisign.com",
215 base::Bind(&GetCertCallbackNotCalled
)));
216 EXPECT_EQ(4567, expiration_time
.ToInternalValue());
217 EXPECT_EQ("c", private_key
);
218 EXPECT_EQ("d", cert
);
221 TEST(DefaultServerBoundCertStoreTest
, TestAsyncGet
) {
222 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
223 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
225 base::Time::FromInternalValue(123),
226 base::Time::FromInternalValue(1234),
229 DefaultServerBoundCertStore
store(persistent_store
.get());
230 AsyncGetCertHelper helper
;
231 base::Time expiration_time
;
232 std::string private_key
;
233 std::string cert
= "not set";
234 EXPECT_EQ(0, store
.GetCertCount());
235 EXPECT_EQ(ERR_IO_PENDING
,
236 store
.GetServerBoundCert("verisign.com",
240 base::Bind(&AsyncGetCertHelper::Callback
,
241 base::Unretained(&helper
))));
243 // Wait for load & queued get tasks.
244 base::MessageLoop::current()->RunUntilIdle();
245 EXPECT_EQ(1, store
.GetCertCount());
246 EXPECT_EQ("not set", cert
);
247 EXPECT_TRUE(helper
.called_
);
248 EXPECT_EQ(OK
, helper
.err_
);
249 EXPECT_EQ("verisign.com", helper
.server_identifier_
);
250 EXPECT_EQ(1234, helper
.expiration_time_
.ToInternalValue());
251 EXPECT_EQ("a", helper
.private_key_
);
252 EXPECT_EQ("b", helper
.cert_
);
255 TEST(DefaultServerBoundCertStoreTest
, TestDeleteAll
) {
256 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
257 DefaultServerBoundCertStore
store(persistent_store
.get());
259 store
.SetServerBoundCert(
264 store
.SetServerBoundCert(
269 store
.SetServerBoundCert(
274 // Wait for load & queued set tasks.
275 base::MessageLoop::current()->RunUntilIdle();
277 EXPECT_EQ(3, store
.GetCertCount());
278 int delete_finished
= 0;
279 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
280 ASSERT_EQ(1, delete_finished
);
281 EXPECT_EQ(0, store
.GetCertCount());
284 TEST(DefaultServerBoundCertStoreTest
, TestAsyncGetAndDeleteAll
) {
285 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
286 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
291 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
297 ServerBoundCertStore::ServerBoundCertList pre_certs
;
298 ServerBoundCertStore::ServerBoundCertList post_certs
;
299 int delete_finished
= 0;
300 DefaultServerBoundCertStore
store(persistent_store
.get());
302 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &pre_certs
));
303 store
.DeleteAll(base::Bind(&CallCounter
, &delete_finished
));
304 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &post_certs
));
305 // Tasks have not run yet.
306 EXPECT_EQ(0u, pre_certs
.size());
307 // Wait for load & queued tasks.
308 base::MessageLoop::current()->RunUntilIdle();
309 EXPECT_EQ(0, store
.GetCertCount());
310 EXPECT_EQ(2u, pre_certs
.size());
311 EXPECT_EQ(0u, post_certs
.size());
314 TEST(DefaultServerBoundCertStoreTest
, TestDelete
) {
315 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
316 DefaultServerBoundCertStore
store(persistent_store
.get());
318 base::Time expiration_time
;
319 std::string private_key
, cert
;
320 EXPECT_EQ(0, store
.GetCertCount());
321 store
.SetServerBoundCert(
326 // Wait for load & queued set task.
327 base::MessageLoop::current()->RunUntilIdle();
329 store
.SetServerBoundCert(
335 EXPECT_EQ(2, store
.GetCertCount());
336 int delete_finished
= 0;
337 store
.DeleteServerBoundCert("verisign.com",
338 base::Bind(&CallCounter
, &delete_finished
));
339 ASSERT_EQ(1, delete_finished
);
340 EXPECT_EQ(1, store
.GetCertCount());
341 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
342 store
.GetServerBoundCert("verisign.com",
346 base::Bind(&GetCertCallbackNotCalled
)));
348 store
.GetServerBoundCert("google.com",
352 base::Bind(&GetCertCallbackNotCalled
)));
353 int delete2_finished
= 0;
354 store
.DeleteServerBoundCert("google.com",
355 base::Bind(&CallCounter
, &delete2_finished
));
356 ASSERT_EQ(1, delete2_finished
);
357 EXPECT_EQ(0, store
.GetCertCount());
358 EXPECT_EQ(ERR_FILE_NOT_FOUND
,
359 store
.GetServerBoundCert("google.com",
363 base::Bind(&GetCertCallbackNotCalled
)));
366 TEST(DefaultServerBoundCertStoreTest
, TestAsyncDelete
) {
367 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
368 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
370 base::Time::FromInternalValue(1),
371 base::Time::FromInternalValue(2),
373 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
375 base::Time::FromInternalValue(3),
376 base::Time::FromInternalValue(4),
378 DefaultServerBoundCertStore
store(persistent_store
.get());
379 int delete_finished
= 0;
380 store
.DeleteServerBoundCert("a.com",
381 base::Bind(&CallCounter
, &delete_finished
));
383 AsyncGetCertHelper a_helper
;
384 AsyncGetCertHelper b_helper
;
385 base::Time expiration_time
;
386 std::string private_key
;
387 std::string cert
= "not set";
388 EXPECT_EQ(0, store
.GetCertCount());
389 EXPECT_EQ(ERR_IO_PENDING
,
390 store
.GetServerBoundCert(
391 "a.com", &expiration_time
, &private_key
, &cert
,
392 base::Bind(&AsyncGetCertHelper::Callback
,
393 base::Unretained(&a_helper
))));
394 EXPECT_EQ(ERR_IO_PENDING
,
395 store
.GetServerBoundCert(
396 "b.com", &expiration_time
, &private_key
, &cert
,
397 base::Bind(&AsyncGetCertHelper::Callback
,
398 base::Unretained(&b_helper
))));
400 EXPECT_EQ(0, delete_finished
);
401 EXPECT_FALSE(a_helper
.called_
);
402 EXPECT_FALSE(b_helper
.called_
);
403 // Wait for load & queued tasks.
404 base::MessageLoop::current()->RunUntilIdle();
405 EXPECT_EQ(1, delete_finished
);
406 EXPECT_EQ(1, store
.GetCertCount());
407 EXPECT_EQ("not set", cert
);
408 EXPECT_TRUE(a_helper
.called_
);
409 EXPECT_EQ(ERR_FILE_NOT_FOUND
, a_helper
.err_
);
410 EXPECT_EQ("a.com", a_helper
.server_identifier_
);
411 EXPECT_EQ(0, a_helper
.expiration_time_
.ToInternalValue());
412 EXPECT_EQ("", a_helper
.private_key_
);
413 EXPECT_EQ("", a_helper
.cert_
);
414 EXPECT_TRUE(b_helper
.called_
);
415 EXPECT_EQ(OK
, b_helper
.err_
);
416 EXPECT_EQ("b.com", b_helper
.server_identifier_
);
417 EXPECT_EQ(4, b_helper
.expiration_time_
.ToInternalValue());
418 EXPECT_EQ("c", b_helper
.private_key_
);
419 EXPECT_EQ("d", b_helper
.cert_
);
422 TEST(DefaultServerBoundCertStoreTest
, TestGetAll
) {
423 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
424 DefaultServerBoundCertStore
store(persistent_store
.get());
426 EXPECT_EQ(0, store
.GetCertCount());
427 store
.SetServerBoundCert(
432 store
.SetServerBoundCert(
437 store
.SetServerBoundCert(
442 store
.SetServerBoundCert(
447 // Wait for load & queued set tasks.
448 base::MessageLoop::current()->RunUntilIdle();
450 EXPECT_EQ(4, store
.GetCertCount());
451 ServerBoundCertStore::ServerBoundCertList certs
;
452 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
453 EXPECT_EQ(4u, certs
.size());
456 TEST(DefaultServerBoundCertStoreTest
, TestInitializeFrom
) {
457 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
458 DefaultServerBoundCertStore
store(persistent_store
.get());
460 store
.SetServerBoundCert(
465 store
.SetServerBoundCert(
470 // Wait for load & queued set tasks.
471 base::MessageLoop::current()->RunUntilIdle();
472 EXPECT_EQ(2, store
.GetCertCount());
474 ServerBoundCertStore::ServerBoundCertList source_certs
;
475 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
479 // Key differs from above to test that existing entries are overwritten.
481 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
486 store
.InitializeFrom(source_certs
);
487 EXPECT_EQ(3, store
.GetCertCount());
489 ServerBoundCertStore::ServerBoundCertList certs
;
490 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
491 ASSERT_EQ(3u, certs
.size());
493 ServerBoundCertStore::ServerBoundCertList::iterator cert
= certs
.begin();
494 EXPECT_EQ("both.com", cert
->server_identifier());
495 EXPECT_EQ("e", cert
->private_key());
498 EXPECT_EQ("copied.com", cert
->server_identifier());
499 EXPECT_EQ("g", cert
->private_key());
502 EXPECT_EQ("preexisting.com", cert
->server_identifier());
503 EXPECT_EQ("a", cert
->private_key());
506 TEST(DefaultServerBoundCertStoreTest
, TestAsyncInitializeFrom
) {
507 scoped_refptr
<MockPersistentStore
> persistent_store(new MockPersistentStore
);
508 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
513 persistent_store
->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert(
519 DefaultServerBoundCertStore
store(persistent_store
.get());
520 ServerBoundCertStore::ServerBoundCertList source_certs
;
521 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
525 // Key differs from above to test that existing entries are overwritten.
527 source_certs
.push_back(ServerBoundCertStore::ServerBoundCert(
532 store
.InitializeFrom(source_certs
);
533 EXPECT_EQ(0, store
.GetCertCount());
534 // Wait for load & queued tasks.
535 base::MessageLoop::current()->RunUntilIdle();
536 EXPECT_EQ(3, store
.GetCertCount());
538 ServerBoundCertStore::ServerBoundCertList certs
;
539 store
.GetAllServerBoundCerts(base::Bind(GetAllCallback
, &certs
));
540 ASSERT_EQ(3u, certs
.size());
542 ServerBoundCertStore::ServerBoundCertList::iterator cert
= certs
.begin();
543 EXPECT_EQ("both.com", cert
->server_identifier());
544 EXPECT_EQ("e", cert
->private_key());
547 EXPECT_EQ("copied.com", cert
->server_identifier());
548 EXPECT_EQ("g", cert
->private_key());
551 EXPECT_EQ("preexisting.com", cert
->server_identifier());
552 EXPECT_EQ("a", cert
->private_key());