OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/multi_threaded_cert_verifier.h" | 5 #include "net/cert/multi_threaded_cert_verifier.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/leak_annotations.h" | 8 #include "base/debug/leak_annotations.h" |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 case 1: | 372 case 1: |
373 EXPECT_FALSE(key1 < key2); | 373 EXPECT_FALSE(key1 < key2); |
374 EXPECT_TRUE(key2 < key1); | 374 EXPECT_TRUE(key2 < key1); |
375 break; | 375 break; |
376 default: | 376 default: |
377 FAIL() << "Invalid expectation. Can be only -1, 0, 1"; | 377 FAIL() << "Invalid expectation. Can be only -1, 0, 1"; |
378 } | 378 } |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
| 382 TEST_F(MultiThreadedCertVerifierTest, PersistRequestParams) { |
| 383 SHA1HashValue a_key; |
| 384 memset(a_key.data, 'a', sizeof(a_key.data)); |
| 385 |
| 386 const CertificateList empty_list; |
| 387 CertificateList test_list; |
| 388 test_list.push_back( |
| 389 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); |
| 390 |
| 391 // Key to test. |
| 392 MultiThreadedCertVerifier::RequestParams key(a_key, a_key, "www.example.test", |
| 393 std::string(), 0, test_list); |
| 394 |
| 395 // Restoring invalid pickled data should fail. |
| 396 base::Pickle pickle; |
| 397 EXPECT_TRUE(pickle.WriteString(std::string())); |
| 398 base::PickleIterator corrupt_iter(pickle); |
| 399 MultiThreadedCertVerifier::RequestParams key1; |
| 400 EXPECT_FALSE(MultiThreadedCertVerifier::RequestParams::CreateFromPickle( |
| 401 &corrupt_iter, &key1)); |
| 402 |
| 403 // Persisting and restoring valid object should succeed. |
| 404 base::Pickle pickle1; |
| 405 EXPECT_TRUE(key.Persist(&pickle1)); |
| 406 base::PickleIterator iter(pickle1); |
| 407 EXPECT_TRUE( |
| 408 MultiThreadedCertVerifier::RequestParams::CreateFromPickle(&iter, &key1)); |
| 409 |
| 410 EXPECT_EQ(key.hostname, key1.hostname); |
| 411 EXPECT_EQ(key.flags, key1.flags); |
| 412 EXPECT_EQ(key.hash_values.size(), key1.hash_values.size()); |
| 413 for (size_t i = 0; i < key.hash_values.size(); ++i) |
| 414 EXPECT_TRUE(key.hash_values[i].Equals(key1.hash_values[i])); |
| 415 } |
| 416 |
382 TEST_F(MultiThreadedCertVerifierTest, CertTrustAnchorProvider) { | 417 TEST_F(MultiThreadedCertVerifierTest, CertTrustAnchorProvider) { |
383 MockCertTrustAnchorProvider trust_provider; | 418 MockCertTrustAnchorProvider trust_provider; |
384 verifier_.SetCertTrustAnchorProvider(&trust_provider); | 419 verifier_.SetCertTrustAnchorProvider(&trust_provider); |
385 | 420 |
386 scoped_refptr<X509Certificate> test_cert( | 421 scoped_refptr<X509Certificate> test_cert( |
387 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | 422 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); |
388 ASSERT_TRUE(test_cert.get()); | 423 ASSERT_TRUE(test_cert.get()); |
389 | 424 |
390 const CertificateList empty_cert_list; | 425 const CertificateList empty_cert_list; |
391 CertificateList cert_list; | 426 CertificateList cert_list; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 ASSERT_TRUE(IsCertificateError(error)); | 540 ASSERT_TRUE(IsCertificateError(error)); |
506 error = callback4.WaitForResult(); | 541 error = callback4.WaitForResult(); |
507 ASSERT_TRUE(IsCertificateError(error)); | 542 ASSERT_TRUE(IsCertificateError(error)); |
508 | 543 |
509 // Let the other requests automatically cancel. | 544 // Let the other requests automatically cancel. |
510 ASSERT_EQ(5u, verifier_.requests()); | 545 ASSERT_EQ(5u, verifier_.requests()); |
511 ASSERT_EQ(0u, verifier_.cache_hits()); | 546 ASSERT_EQ(0u, verifier_.cache_hits()); |
512 ASSERT_EQ(2u, verifier_.inflight_joins()); | 547 ASSERT_EQ(2u, verifier_.inflight_joins()); |
513 } | 548 } |
514 | 549 |
| 550 TEST_F(MultiThreadedCertVerifierTest, PersistCache) { |
| 551 base::FilePath certs_dir = GetTestCertsDirectory(); |
| 552 scoped_refptr<X509Certificate> test_cert( |
| 553 ImportCertFromFile(certs_dir, "ok_cert.pem")); |
| 554 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); |
| 555 |
| 556 std::string example_hostname("www.example.com"); |
| 557 std::string ocsp_response; |
| 558 int flags = 0; |
| 559 CRLSet* crl_set = NULL; |
| 560 int error; |
| 561 CertVerifyResult verify_result; |
| 562 TestCompletionCallback callback; |
| 563 scoped_ptr<CertVerifier::Request> request; |
| 564 |
| 565 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 566 flags, crl_set, &verify_result, callback.callback(), |
| 567 &request, BoundNetLog()); |
| 568 ASSERT_EQ(ERR_IO_PENDING, error); |
| 569 EXPECT_TRUE(request); |
| 570 error = callback.WaitForResult(); |
| 571 ASSERT_TRUE(IsCertificateError(error)); |
| 572 ASSERT_EQ(1u, verifier_.requests()); |
| 573 ASSERT_EQ(0u, verifier_.cache_hits()); |
| 574 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 575 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 576 |
| 577 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 578 flags, crl_set, &verify_result, callback.callback(), |
| 579 &request, BoundNetLog()); |
| 580 // Synchronous completion. |
| 581 ASSERT_NE(ERR_IO_PENDING, error); |
| 582 ASSERT_TRUE(IsCertificateError(error)); |
| 583 ASSERT_FALSE(request); |
| 584 ASSERT_EQ(2u, verifier_.requests()); |
| 585 ASSERT_EQ(1u, verifier_.cache_hits()); |
| 586 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 587 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 588 |
| 589 base::Pickle pickle(sizeof(base::Pickle::Header)); |
| 590 EXPECT_TRUE(verifier_.SerializeCache(&pickle)); |
| 591 |
| 592 // Clear the cache. |
| 593 verifier_.ClearCache(); |
| 594 ASSERT_EQ(0u, verifier_.GetCacheSize()); |
| 595 |
| 596 // Restore the cache from the pickled data. |
| 597 base::PickleIterator iter(pickle); |
| 598 EXPECT_TRUE(MultiThreadedCertVerifier::CreateFromPickle(&iter, &verifier_)); |
| 599 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 600 |
| 601 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 602 flags, crl_set, &verify_result, callback.callback(), |
| 603 &request, BoundNetLog()); |
| 604 // Synchronous completion. |
| 605 ASSERT_NE(ERR_IO_PENDING, error); |
| 606 ASSERT_TRUE(IsCertificateError(error)); |
| 607 ASSERT_FALSE(request); |
| 608 ASSERT_EQ(3u, verifier_.requests()); |
| 609 ASSERT_EQ(2u, verifier_.cache_hits()); |
| 610 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 611 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 612 } |
| 613 |
| 614 TEST_F(MultiThreadedCertVerifierTest, PersistCacheExpiredEntry) { |
| 615 base::FilePath certs_dir = GetTestCertsDirectory(); |
| 616 scoped_refptr<X509Certificate> test_cert( |
| 617 ImportCertFromFile(certs_dir, "ok_cert.pem")); |
| 618 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); |
| 619 |
| 620 std::string example_hostname("www.example.com"); |
| 621 std::string ocsp_response; |
| 622 int flags = 0; |
| 623 CRLSet* crl_set = NULL; |
| 624 int error; |
| 625 CertVerifyResult verify_result; |
| 626 TestCompletionCallback callback; |
| 627 scoped_ptr<CertVerifier::Request> request; |
| 628 |
| 629 // Verify that there is no cache hit. |
| 630 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 631 flags, crl_set, &verify_result, callback.callback(), |
| 632 &request, BoundNetLog()); |
| 633 ASSERT_EQ(ERR_IO_PENDING, error); |
| 634 EXPECT_TRUE(request); |
| 635 error = callback.WaitForResult(); |
| 636 ASSERT_TRUE(IsCertificateError(error)); |
| 637 ASSERT_EQ(1u, verifier_.requests()); |
| 638 ASSERT_EQ(0u, verifier_.cache_hits()); |
| 639 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 640 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 641 |
| 642 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 643 flags, crl_set, &verify_result, callback.callback(), |
| 644 &request, BoundNetLog()); |
| 645 // Synchronous completion and verify that there is a cache hit. |
| 646 ASSERT_NE(ERR_IO_PENDING, error); |
| 647 ASSERT_TRUE(IsCertificateError(error)); |
| 648 ASSERT_FALSE(request); |
| 649 ASSERT_EQ(2u, verifier_.requests()); |
| 650 ASSERT_EQ(1u, verifier_.cache_hits()); // cache hit. |
| 651 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 652 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 653 |
| 654 // Test cache expiration, by adding expired data. |
| 655 const CertificateList empty_cert_list; |
| 656 const CertificateList& additional_trust_anchors = |
| 657 verifier_.trust_anchor_provider_ |
| 658 ? verifier_.trust_anchor_provider_->GetAdditionalTrustAnchors() |
| 659 : empty_cert_list; |
| 660 const MultiThreadedCertVerifier::RequestParams key( |
| 661 test_cert->fingerprint(), test_cert->ca_fingerprint(), example_hostname, |
| 662 ocsp_response, flags, additional_trust_anchors); |
| 663 const MultiThreadedCertVerifier::CertVerifierCache::value_type* cached_entry = |
| 664 verifier_.cache_.Get(key, MultiThreadedCertVerifier::CacheValidityPeriod( |
| 665 base::Time::Now())); |
| 666 // TODO(rtenneti): use |kTTLSecs| instead of hardcoded 1800ms. |
| 667 base::Time start_time = |
| 668 base::Time::Now() - base::TimeDelta::FromSeconds(3600); |
| 669 verifier_.cache_.Put( |
| 670 key, *cached_entry, |
| 671 MultiThreadedCertVerifier::CacheValidityPeriod(start_time), |
| 672 MultiThreadedCertVerifier::CacheValidityPeriod( |
| 673 start_time, start_time + base::TimeDelta::FromSeconds(1800))); |
| 674 |
| 675 // Persist the data. |
| 676 base::Pickle pickle(sizeof(base::Pickle::Header)); |
| 677 EXPECT_TRUE(verifier_.SerializeCache(&pickle)); |
| 678 |
| 679 // Clear the cache. |
| 680 verifier_.ClearCache(); |
| 681 ASSERT_EQ(0u, verifier_.GetCacheSize()); |
| 682 |
| 683 // Restore the persisted data. |
| 684 base::PickleIterator iter(pickle); |
| 685 EXPECT_TRUE(MultiThreadedCertVerifier::CreateFromPickle(&iter, &verifier_)); |
| 686 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 687 |
| 688 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
| 689 flags, crl_set, &verify_result, callback.callback(), |
| 690 &request, BoundNetLog()); |
| 691 ASSERT_EQ(ERR_IO_PENDING, error); |
| 692 // Verify the entry is evicted from the cache. |
| 693 ASSERT_EQ(0u, verifier_.GetCacheSize()); |
| 694 ASSERT_TRUE(request); |
| 695 error = callback.WaitForResult(); |
| 696 ASSERT_TRUE(IsCertificateError(error)); |
| 697 ASSERT_EQ(3u, verifier_.requests()); |
| 698 // Verify number of cache hits hasn't increased. |
| 699 ASSERT_EQ(1u, verifier_.cache_hits()); |
| 700 ASSERT_EQ(0u, verifier_.inflight_joins()); |
| 701 ASSERT_EQ(1u, verifier_.GetCacheSize()); |
| 702 } |
| 703 |
515 } // namespace net | 704 } // namespace net |
OLD | NEW |