ignore_errors_cert_verifier_unittest.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2017 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. #include "services/network/ignore_errors_cert_verifier.h"
  5. #include "base/base64.h"
  6. #include "base/files/file_path.h"
  7. #include "base/memory/ptr_util.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/strings/string_piece.h"
  11. #include "base/strings/string_util.h"
  12. #include "crypto/sha2.h"
  13. #include "net/base/net_errors.h"
  14. #include "net/base/test_completion_callback.h"
  15. #include "net/cert/asn1_util.h"
  16. #include "net/cert/mock_cert_verifier.h"
  17. #include "net/cert/x509_certificate.h"
  18. #include "net/cert/x509_util.h"
  19. #include "net/log/net_log_with_source.h"
  20. #include "net/test/cert_test_util.h"
  21. #include "net/test/gtest_util.h"
  22. #include "net/test/test_data_directory.h"
  23. #include "services/network/public/cpp/network_switches.h"
  24. #include "services/network/public/cpp/spki_hash_set.h"
  25. #include "testing/gmock/include/gmock/gmock.h"
  26. #include "testing/gtest/include/gtest/gtest.h"
  27. using net::CertVerifier;
  28. using net::MockCertVerifier;
  29. using net::HashValue;
  30. using net::SHA256HashValue;
  31. using net::X509Certificate;
  32. using net::TestCompletionCallback;
  33. using net::CertVerifyResult;
  34. using net::NetLogWithSource;
  35. using net::ERR_CERT_INVALID;
  36. using net::ERR_IO_PENDING;
  37. using net::OK;
  38. using net::test::IsError;
  39. using net::test::IsOk;
  40. namespace network {
  41. static const char kTestUserDataDirSwitch[] = "test-user-data-dir";
  42. static std::vector<std::string> MakeAllowlist() {
  43. base::FilePath certs_dir = net::GetTestCertsDirectory();
  44. net::CertificateList certs = net::CreateCertificateListFromFile(
  45. certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO);
  46. std::string hash_base64;
  47. base::StringPiece cert_spki;
  48. SHA256HashValue hash;
  49. net::asn1::ExtractSPKIFromDERCert(
  50. net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer()),
  51. &cert_spki);
  52. crypto::SHA256HashString(cert_spki, &hash, sizeof(SHA256HashValue));
  53. base::Base64Encode(base::StringPiece(reinterpret_cast<const char*>(hash.data),
  54. sizeof(hash.data)),
  55. &hash_base64);
  56. return {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", "foobar", hash_base64,
  57. "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="};
  58. }
  59. class IgnoreErrorsCertVerifierTest : public ::testing::Test {
  60. public:
  61. IgnoreErrorsCertVerifierTest()
  62. : mock_verifier_(new MockCertVerifier()),
  63. verifier_(base::WrapUnique(mock_verifier_.get()), SPKIHashSet()) {}
  64. ~IgnoreErrorsCertVerifierTest() override {}
  65. protected:
  66. void SetUp() override {
  67. verifier_.SetAllowlistForTesting(CreateSPKIHashSet(MakeAllowlist()));
  68. }
  69. // The wrapped CertVerifier. Defaults to returning ERR_CERT_INVALID. Owned by
  70. // |verifier_|.
  71. raw_ptr<MockCertVerifier> mock_verifier_;
  72. IgnoreErrorsCertVerifier verifier_;
  73. };
  74. static void GetNonAllowlistedTestCert(scoped_refptr<X509Certificate>* out) {
  75. base::FilePath certs_dir = net::GetTestCertsDirectory();
  76. scoped_refptr<X509Certificate> test_cert(
  77. net::ImportCertFromFile(certs_dir, "ok_cert.pem"));
  78. ASSERT_TRUE(test_cert);
  79. out->swap(test_cert);
  80. }
  81. static CertVerifier::RequestParams MakeRequestParams(
  82. const scoped_refptr<X509Certificate>& cert) {
  83. return CertVerifier::RequestParams(cert, "example.com", /*flags=*/0,
  84. /*ocsp_response=*/std::string(),
  85. /*sct_list=*/std::string());
  86. }
  87. static void GetAllowlistedTestCert(scoped_refptr<X509Certificate>* out) {
  88. base::FilePath certs_dir = net::GetTestCertsDirectory();
  89. *out = net::CreateCertificateChainFromFile(
  90. certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO);
  91. ASSERT_TRUE(*out);
  92. ASSERT_EQ(2U, (*out)->intermediate_buffers().size());
  93. }
  94. TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertOk) {
  95. mock_verifier_->set_default_result(OK);
  96. scoped_refptr<X509Certificate> test_cert;
  97. ASSERT_NO_FATAL_FAILURE(GetNonAllowlistedTestCert(&test_cert));
  98. CertVerifyResult verify_result;
  99. TestCompletionCallback callback;
  100. std::unique_ptr<CertVerifier::Request> request;
  101. EXPECT_THAT(callback.GetResult(verifier_.Verify(
  102. MakeRequestParams(test_cert), &verify_result,
  103. callback.callback(), &request, NetLogWithSource())),
  104. IsOk());
  105. }
  106. TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertError) {
  107. scoped_refptr<X509Certificate> test_cert;
  108. ASSERT_NO_FATAL_FAILURE(GetNonAllowlistedTestCert(&test_cert));
  109. CertVerifyResult verify_result;
  110. TestCompletionCallback callback;
  111. std::unique_ptr<CertVerifier::Request> request;
  112. EXPECT_THAT(callback.GetResult(verifier_.Verify(
  113. MakeRequestParams(test_cert), &verify_result,
  114. callback.callback(), &request, NetLogWithSource())),
  115. IsError(ERR_CERT_INVALID));
  116. }
  117. TEST_F(IgnoreErrorsCertVerifierTest, TestMatch) {
  118. scoped_refptr<X509Certificate> test_cert;
  119. ASSERT_NO_FATAL_FAILURE(GetAllowlistedTestCert(&test_cert));
  120. CertVerifyResult verify_result;
  121. TestCompletionCallback callback;
  122. std::unique_ptr<CertVerifier::Request> request;
  123. EXPECT_THAT(callback.GetResult(verifier_.Verify(
  124. MakeRequestParams(test_cert), &verify_result,
  125. callback.callback(), &request, NetLogWithSource())),
  126. IsOk());
  127. }
  128. class IgnoreCertificateErrorsSPKIListFlagTest
  129. : public ::testing::TestWithParam<bool> {
  130. public:
  131. IgnoreCertificateErrorsSPKIListFlagTest() {
  132. base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
  133. if (GetParam()) {
  134. command_line.AppendSwitchASCII(kTestUserDataDirSwitch, "/foo/bar/baz");
  135. }
  136. command_line.AppendSwitchASCII(switches::kIgnoreCertificateErrorsSPKIList,
  137. base::JoinString(MakeAllowlist(), ","));
  138. auto mock_verifier = std::make_unique<MockCertVerifier>();
  139. mock_verifier->set_default_result(ERR_CERT_INVALID);
  140. verifier_ = IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
  141. command_line, kTestUserDataDirSwitch, std::move(mock_verifier));
  142. }
  143. ~IgnoreCertificateErrorsSPKIListFlagTest() override {}
  144. protected:
  145. std::unique_ptr<CertVerifier> verifier_;
  146. };
  147. // Only if both --user-data-dir and --ignore-certificate-errors-from-spki-list
  148. // are present, certificate verification is bypassed.
  149. TEST_P(IgnoreCertificateErrorsSPKIListFlagTest, TestUserDataDirSwitchRequired) {
  150. scoped_refptr<X509Certificate> test_cert;
  151. ASSERT_NO_FATAL_FAILURE(GetAllowlistedTestCert(&test_cert));
  152. CertVerifyResult verify_result;
  153. TestCompletionCallback callback;
  154. std::unique_ptr<CertVerifier::Request> request;
  155. if (GetParam()) {
  156. EXPECT_THAT(callback.GetResult(verifier_->Verify(
  157. MakeRequestParams(test_cert), &verify_result,
  158. callback.callback(), &request, NetLogWithSource())),
  159. IsOk());
  160. } else {
  161. EXPECT_THAT(callback.GetResult(verifier_->Verify(
  162. MakeRequestParams(test_cert), &verify_result,
  163. callback.callback(), &request, NetLogWithSource())),
  164. IsError(ERR_CERT_INVALID));
  165. }
  166. }
  167. INSTANTIATE_TEST_SUITE_P(WithUserDataDirSwitchPresent,
  168. IgnoreCertificateErrorsSPKIListFlagTest,
  169. ::testing::Bool());
  170. } // namespace network