| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web/session/session_certificate_policy_cache_impl.h" |
| |
| #import "base/functional/bind.h" |
| #import "base/test/ios/wait_util.h" |
| #import "base/time/time.h" |
| #import "ios/web/public/security/certificate_policy_cache.h" |
| #import "ios/web/public/session/proto/session.pb.h" |
| #import "ios/web/public/test/fakes/fake_browser_state.h" |
| #import "ios/web/public/test/web_task_environment.h" |
| #import "ios/web/public/thread/web_task_traits.h" |
| #import "ios/web/public/thread/web_thread.h" |
| #import "ios/web/session/session_certificate.h" |
| #import "net/cert/x509_certificate.h" |
| #import "net/test/cert_test_util.h" |
| #import "net/test/test_data_directory.h" |
| #import "testing/gtest_mac.h" |
| #import "testing/platform_test.h" |
| |
| using base::test::ios::WaitUntilConditionOrTimeout; |
| |
| namespace { |
| // Synchronously checks `cache` for the specified cert and returns the judgment. |
| web::CertPolicy::Judgment GetJudgmenet( |
| const scoped_refptr<web::CertificatePolicyCache>& cache, |
| const scoped_refptr<net::X509Certificate>& cert, |
| const std::string& host, |
| const net::CertStatus status) { |
| // Post a task to the IO thread and wait for a reply |
| __block web::CertPolicy::Judgment judgement = |
| web::CertPolicy::Judgment::UNKNOWN; |
| __block bool completed = false; |
| web::GetIOThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce(^{ |
| completed = true; |
| judgement = cache->QueryPolicy( |
| cert.get(), host, status); |
| })); |
| EXPECT_TRUE(WaitUntilConditionOrTimeout(base::Seconds(1), ^{ |
| return completed; |
| })); |
| return judgement; |
| } |
| |
| // Returns a test session certificate. |
| web::SessionCertificate CreateTestSessionCertificate( |
| const std::string& filename, |
| const std::string& host, |
| net::CertStatus status) { |
| auto cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), filename); |
| return web::SessionCertificate(cert, host, status); |
| } |
| |
| } // namespace |
| |
| // Test fixture to test SessionCertificatePolicyCacheImpl class. |
| class SessionCertificatePolicyCacheImplTest : public PlatformTest { |
| protected: |
| SessionCertificatePolicyCacheImplTest() |
| : task_environment_(web::WebTaskEnvironment::Options::REAL_IO_THREAD) {} |
| |
| web::WebTaskEnvironment task_environment_; |
| web::FakeBrowserState browser_state_; |
| }; |
| |
| // Tests that registering an allowed certificate will successfully create an |
| // accurate SessionCertificate in the allowed certs set. |
| TEST_F(SessionCertificatePolicyCacheImplTest, RegisterAllowedCertificate) { |
| const web::SessionCertificate cert = CreateTestSessionCertificate( |
| "ok_cert.pem", "test.com", net::CERT_STATUS_REVOKED); |
| |
| // Check that the default value for the CertPolicyJudgment in |
| // web::CertificatePolicyCache is UNKNOWN before registering it. |
| ASSERT_EQ(web::CertPolicy::Judgment::UNKNOWN, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| |
| // Check that creating the SessionCertificatePolicyCacheImpl does not |
| // register the certificate. |
| web::SessionCertificatePolicyCacheImpl cache(&browser_state_); |
| ASSERT_EQ(web::CertPolicy::Judgment::UNKNOWN, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| |
| // Verify that calling RegisterAllowedCertificate() register the certificate. |
| cache.RegisterAllowedCertificate(cert.certificate(), cert.host(), |
| cert.status()); |
| EXPECT_EQ(web::CertPolicy::Judgment::ALLOWED, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| |
| // Verify that there is one certificate in the serialisation, and that it |
| // corresponds to the registered certificate. |
| web::proto::CertificatesCacheStorage storage; |
| cache.SerializeToProto(storage); |
| |
| ASSERT_EQ(storage.certs_size(), 1); |
| const web::SessionCertificate decoded(storage.certs()[0]); |
| EXPECT_EQ(cert, decoded); |
| } |
| |
| // Tests that UpdateCertificatePolicyCache() successfully transfers the allowed |
| // certificate information to a CertificatePolicyCache. |
| TEST_F(SessionCertificatePolicyCacheImplTest, UpdateCertificatePolicyCache) { |
| const web::SessionCertificate cert = CreateTestSessionCertificate( |
| "ok_cert.pem", "test.com", net::CERT_STATUS_REVOKED); |
| |
| // Check that the default value for the CertPolicyJudgment in |
| // web::CertificatePolicyCache is UNKNOWN before registering it. |
| ASSERT_EQ(web::CertPolicy::Judgment::UNKNOWN, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| |
| // Create a fake serialised state. |
| web::proto::CertificatesCacheStorage storage; |
| cert.SerializeToProto(*storage.add_certs()); |
| |
| // Check that creating the SessionCertificatePolicyCacheImpl from |
| // serialized state does not register the certificate. |
| web::SessionCertificatePolicyCacheImpl cache(&browser_state_, storage); |
| ASSERT_EQ(web::CertPolicy::Judgment::UNKNOWN, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| |
| // Verify that calling RegisterAllowedCertificate() register the certificate. |
| cache.UpdateCertificatePolicyCache(); |
| EXPECT_EQ(web::CertPolicy::Judgment::ALLOWED, |
| GetJudgmenet( |
| web::BrowserState::GetCertificatePolicyCache(&browser_state_), |
| cert.certificate(), cert.host(), cert.status())); |
| } |