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