Chromium Code Reviews| 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 <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/debug/leak_annotations.h" | 10 #include "base/debug/leak_annotations.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 }; | 60 }; |
| 61 | 61 |
| 62 class MockCertTrustAnchorProvider : public CertTrustAnchorProvider { | 62 class MockCertTrustAnchorProvider : public CertTrustAnchorProvider { |
| 63 public: | 63 public: |
| 64 MockCertTrustAnchorProvider() {} | 64 MockCertTrustAnchorProvider() {} |
| 65 virtual ~MockCertTrustAnchorProvider() {} | 65 virtual ~MockCertTrustAnchorProvider() {} |
| 66 | 66 |
| 67 MOCK_METHOD0(GetAdditionalTrustAnchors, const CertificateList&()); | 67 MOCK_METHOD0(GetAdditionalTrustAnchors, const CertificateList&()); |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 bool HashValueVectorEqual(const HashValueVector& a, const HashValueVector& b) { | |
| 71 size_t size = a.size(); | |
| 72 | |
| 73 if (size != b.size()) | |
| 74 return false; | |
| 75 | |
| 76 for (size_t i = 0; i < size; ++i) { | |
|
Ryan Sleevi
2016/05/13 20:18:13
alternative: return std::equal(a.begin(), a.end(),
| |
| 77 if (!a[i].Equals(b[i])) | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 return true; | |
| 82 } | |
| 83 | |
| 70 } // namespace | 84 } // namespace |
| 71 | 85 |
| 72 class MultiThreadedCertVerifierTest : public ::testing::Test { | 86 class MultiThreadedCertVerifierTest : public ::testing::Test { |
| 73 public: | 87 public: |
| 74 MultiThreadedCertVerifierTest() : verifier_(new MockCertVerifyProc()) {} | 88 MultiThreadedCertVerifierTest() : verifier_(new MockCertVerifyProc()) {} |
| 75 ~MultiThreadedCertVerifierTest() override {} | 89 ~MultiThreadedCertVerifierTest() override {} |
| 76 | 90 |
| 77 protected: | 91 protected: |
| 78 MultiThreadedCertVerifier verifier_; | 92 MultiThreadedCertVerifier verifier_; |
| 79 }; | 93 }; |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 ASSERT_TRUE(IsCertificateError(error)); | 521 ASSERT_TRUE(IsCertificateError(error)); |
| 508 error = callback4.WaitForResult(); | 522 error = callback4.WaitForResult(); |
| 509 ASSERT_TRUE(IsCertificateError(error)); | 523 ASSERT_TRUE(IsCertificateError(error)); |
| 510 | 524 |
| 511 // Let the other requests automatically cancel. | 525 // Let the other requests automatically cancel. |
| 512 ASSERT_EQ(5u, verifier_.requests()); | 526 ASSERT_EQ(5u, verifier_.requests()); |
| 513 ASSERT_EQ(0u, verifier_.cache_hits()); | 527 ASSERT_EQ(0u, verifier_.cache_hits()); |
| 514 ASSERT_EQ(2u, verifier_.inflight_joins()); | 528 ASSERT_EQ(2u, verifier_.inflight_joins()); |
| 515 } | 529 } |
| 516 | 530 |
| 531 TEST_F(MultiThreadedCertVerifierTest, CacheHitIterator) { | |
| 532 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 533 scoped_refptr<X509Certificate> test_cert( | |
| 534 ImportCertFromFile(certs_dir, "ok_cert.pem")); | |
| 535 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); | |
| 536 | |
| 537 std::string example_hostname("www.example.com"); | |
| 538 std::string ocsp_response; | |
| 539 int flags = 0; | |
| 540 base::Time start_time = base::Time::Now(); | |
| 541 int error; | |
| 542 CertVerifyResult verify_result; | |
| 543 TestCompletionCallback callback; | |
| 544 std::unique_ptr<CertVerifier::Request> request; | |
| 545 | |
| 546 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, | |
| 547 flags, NULL, &verify_result, callback.callback(), | |
| 548 &request, BoundNetLog()); | |
| 549 ASSERT_EQ(ERR_IO_PENDING, error); | |
| 550 EXPECT_TRUE(request); | |
| 551 error = callback.WaitForResult(); | |
| 552 ASSERT_TRUE(IsCertificateError(error)); | |
| 553 ASSERT_EQ(1u, verifier_.requests()); | |
| 554 ASSERT_EQ(0u, verifier_.cache_hits()); | |
| 555 ASSERT_EQ(0u, verifier_.inflight_joins()); | |
| 556 ASSERT_EQ(1u, verifier_.GetCacheSize()); | |
| 557 | |
| 558 // Verify Iterator returns the correct data. | |
| 559 base::Time curr_time = base::Time::Now(); | |
| 560 MultiThreadedCertVerifier::Iterator iterator(verifier_); | |
| 561 EXPECT_TRUE(iterator.HasNext()); | |
| 562 ASSERT_EQ(example_hostname, iterator.hostname()); | |
| 563 ASSERT_EQ(flags, iterator.flags()); | |
| 564 ASSERT_LE(start_time, iterator.start_time()); | |
| 565 ASSERT_GE(curr_time, iterator.start_time()); | |
| 566 ASSERT_EQ(error, iterator.error()); | |
| 567 const CertVerifyResult& result = iterator.result(); | |
| 568 ASSERT_EQ(verify_result.cert_status, result.cert_status); | |
| 569 ASSERT_EQ(verify_result.has_md2, result.has_md2); | |
| 570 ASSERT_EQ(verify_result.has_md4, result.has_md4); | |
| 571 ASSERT_EQ(verify_result.has_md5, result.has_md5); | |
| 572 ASSERT_EQ(verify_result.has_sha1, result.has_sha1); | |
| 573 ASSERT_EQ(verify_result.has_sha1_leaf, result.has_sha1_leaf); | |
| 574 ASSERT_EQ(verify_result.is_issued_by_known_root, | |
| 575 result.is_issued_by_known_root); | |
| 576 ASSERT_EQ(verify_result.is_issued_by_additional_trust_anchor, | |
| 577 result.is_issued_by_additional_trust_anchor); | |
| 578 ASSERT_EQ(verify_result.has_md2, result.has_md2); | |
| 579 ASSERT_EQ(verify_result.common_name_fallback_used, | |
| 580 result.common_name_fallback_used); | |
| 581 EXPECT_TRUE(HashValueVectorEqual(verify_result.public_key_hashes, | |
| 582 result.public_key_hashes)); | |
| 583 EXPECT_TRUE( | |
| 584 verify_result.verified_cert.get()->Equals(result.verified_cert.get())); | |
| 585 | |
| 586 ASSERT_LE(start_time, iterator.verification_time()); | |
| 587 ASSERT_GE(curr_time, iterator.verification_time()); | |
| 588 | |
| 589 // TODO(rtenneti): use |kTTLSecs| instead of hardcoded 1800ms. | |
| 590 base::Time expected_expiration_time = | |
| 591 curr_time + base::TimeDelta::FromSeconds(3600); | |
| 592 ASSERT_LE(start_time, iterator.expiration_time()); | |
| 593 ASSERT_GE(expected_expiration_time, iterator.expiration_time()); | |
| 594 | |
| 595 iterator.Advance(); | |
| 596 EXPECT_FALSE(iterator.HasNext()); | |
| 597 } | |
| 598 | |
| 599 TEST_F(MultiThreadedCertVerifierTest, AddCertResult) { | |
| 600 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 601 scoped_refptr<X509Certificate> test_cert( | |
| 602 ImportCertFromFile(certs_dir, "ok_cert.pem")); | |
| 603 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); | |
| 604 | |
| 605 std::string example_hostname("www.example.com"); | |
| 606 std::string ocsp_response; | |
| 607 int flags = 0; | |
| 608 CRLSet* crl_set = NULL; | |
| 609 int error; | |
| 610 CertVerifyResult verify_result; | |
| 611 TestCompletionCallback callback; | |
| 612 std::unique_ptr<CertVerifier::Request> request; | |
| 613 | |
| 614 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, | |
| 615 flags, crl_set, &verify_result, callback.callback(), | |
| 616 &request, BoundNetLog()); | |
| 617 ASSERT_EQ(ERR_IO_PENDING, error); | |
| 618 EXPECT_TRUE(request); | |
| 619 error = callback.WaitForResult(); | |
| 620 ASSERT_TRUE(IsCertificateError(error)); | |
| 621 ASSERT_EQ(1u, verifier_.requests()); | |
| 622 ASSERT_EQ(0u, verifier_.cache_hits()); | |
| 623 ASSERT_EQ(0u, verifier_.inflight_joins()); | |
| 624 ASSERT_EQ(1u, verifier_.GetCacheSize()); | |
| 625 | |
| 626 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, | |
| 627 flags, crl_set, &verify_result, callback.callback(), | |
| 628 &request, BoundNetLog()); | |
| 629 // Synchronous completion. | |
| 630 ASSERT_NE(ERR_IO_PENDING, error); | |
| 631 ASSERT_TRUE(IsCertificateError(error)); | |
| 632 ASSERT_FALSE(request); | |
| 633 ASSERT_EQ(2u, verifier_.requests()); | |
| 634 ASSERT_EQ(1u, verifier_.cache_hits()); | |
| 635 ASSERT_EQ(0u, verifier_.inflight_joins()); | |
| 636 ASSERT_EQ(1u, verifier_.GetCacheSize()); | |
| 637 | |
| 638 MultiThreadedCertVerifier::Iterator iterator(verifier_); | |
| 639 EXPECT_TRUE(iterator.HasNext()); | |
| 640 ASSERT_EQ(example_hostname, iterator.hostname()); | |
| 641 | |
| 642 std::vector<SHA1HashValue> dummp_hash_values; | |
| 643 // Invalid hostname. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 644 bool cert_result = verifier_.AddCertResult( | |
| 645 std::string(), iterator.flags(), iterator.hash_values(), | |
| 646 iterator.start_time(), iterator.error(), iterator.result(), | |
| 647 iterator.verification_time(), iterator.expiration_time()); | |
| 648 EXPECT_FALSE(cert_result); | |
| 649 // Invalid hash_values. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 650 cert_result = verifier_.AddCertResult( | |
| 651 iterator.hostname(), iterator.flags(), dummp_hash_values, | |
| 652 iterator.start_time(), iterator.error(), iterator.result(), | |
| 653 iterator.verification_time(), iterator.expiration_time()); | |
| 654 EXPECT_FALSE(cert_result); | |
| 655 // Invalid start_time. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 656 cert_result = verifier_.AddCertResult( | |
| 657 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 658 base::Time::Now(), iterator.error(), iterator.result(), | |
| 659 iterator.verification_time(), iterator.expiration_time()); | |
| 660 EXPECT_FALSE(cert_result); | |
| 661 // Corrupted start_time. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 662 cert_result = verifier_.AddCertResult( | |
| 663 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 664 iterator.start_time() + base::TimeDelta::FromSeconds(1), iterator.error(), | |
| 665 iterator.result(), iterator.verification_time(), | |
| 666 iterator.expiration_time()); | |
| 667 EXPECT_FALSE(cert_result); | |
| 668 // Corrupted verification_time. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 669 cert_result = verifier_.AddCertResult( | |
| 670 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 671 iterator.start_time(), iterator.error(), iterator.result(), | |
| 672 iterator.verification_time() + base::TimeDelta::FromSeconds(10), | |
| 673 iterator.expiration_time()); | |
| 674 EXPECT_FALSE(cert_result); | |
| 675 // Corrupted expired entry. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 676 cert_result = verifier_.AddCertResult( | |
| 677 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 678 iterator.start_time(), iterator.error(), iterator.result(), | |
| 679 iterator.verification_time(), | |
| 680 iterator.expiration_time() - base::TimeDelta::FromSeconds(10)); | |
| 681 EXPECT_FALSE(cert_result); | |
| 682 // Expired entry. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 683 cert_result = verifier_.AddCertResult( | |
| 684 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 685 iterator.start_time(), iterator.error(), iterator.result(), | |
| 686 iterator.verification_time(), base::Time::Now()); | |
| 687 EXPECT_FALSE(cert_result); | |
| 688 // Adding a duplicate entry. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 689 cert_result = verifier_.AddCertResult( | |
| 690 iterator.hostname(), iterator.flags(), iterator.hash_values(), | |
| 691 iterator.start_time(), iterator.error(), iterator.result(), | |
| 692 iterator.verification_time(), iterator.expiration_time()); | |
| 693 EXPECT_FALSE(cert_result); | |
| 694 | |
| 695 // Save the data before clearing the cache. | |
|
Ryan Sleevi
2016/05/13 20:18:13
Separate
| |
| 696 std::string hostname = iterator.hostname(); | |
| 697 flags = iterator.flags(); | |
| 698 std::vector<SHA1HashValue> hash_values = iterator.hash_values(); | |
| 699 base::Time start_time = iterator.start_time(); | |
| 700 error = iterator.error(); | |
| 701 CertVerifyResult result = iterator.result(); | |
| 702 base::Time verification_time = iterator.verification_time(); | |
| 703 base::Time expiration_time = iterator.expiration_time(); | |
| 704 | |
| 705 verifier_.ClearCache(); | |
| 706 ASSERT_EQ(0u, verifier_.GetCacheSize()); | |
| 707 | |
| 708 cert_result = | |
| 709 verifier_.AddCertResult(hostname, flags, hash_values, start_time, error, | |
| 710 result, verification_time, expiration_time); | |
| 711 EXPECT_TRUE(cert_result); | |
| 712 ASSERT_EQ(1u, verifier_.GetCacheSize()); | |
| 713 | |
| 714 error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, | |
| 715 flags, crl_set, &verify_result, callback.callback(), | |
| 716 &request, BoundNetLog()); | |
| 717 // Synchronous completion and verify that there is a cache hit. | |
| 718 ASSERT_NE(ERR_IO_PENDING, error); | |
| 719 ASSERT_TRUE(IsCertificateError(error)); | |
| 720 ASSERT_FALSE(request); | |
| 721 ASSERT_EQ(3u, verifier_.requests()); | |
| 722 ASSERT_EQ(2u, verifier_.cache_hits()); | |
| 723 ASSERT_EQ(0u, verifier_.inflight_joins()); | |
| 724 ASSERT_EQ(1u, verifier_.GetCacheSize()); | |
| 725 } | |
| 726 | |
| 517 } // namespace net | 727 } // namespace net |
| OLD | NEW |