| Index: net/http/transport_security_state_unittest.cc
|
| diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
|
| index 009c7d64991b9e612ade248f6d19b7194d054994..f620c6642a81e4c58bc955e9baab0a2d9cdfd4e2 100644
|
| --- a/net/http/transport_security_state_unittest.cc
|
| +++ b/net/http/transport_security_state_unittest.cc
|
| @@ -26,6 +26,8 @@
|
| #include "net/cert/cert_verifier.h"
|
| #include "net/cert/cert_verify_result.h"
|
| #include "net/cert/ct_policy_status.h"
|
| +#include "net/cert/expect_staple_report.h"
|
| +#include "net/cert/internal/test_helpers.h"
|
| #include "net/cert/test_root_certs.h"
|
| #include "net/cert/x509_cert_types.h"
|
| #include "net/cert/x509_certificate.h"
|
| @@ -78,7 +80,11 @@ const char* const kBadPath[] = {
|
| nullptr,
|
| };
|
|
|
| -// A mock ReportSenderInterface that just remembers the latest report
|
| +const char kOCSPPathPrefix[] = "net/data/parse_ocsp_unittest/";
|
| +
|
| +const base::TimeDelta& kAgeTenYears = base::TimeDelta::FromDays(3650);
|
| +
|
| +// A mock ReportSender that just remembers the latest report
|
| // URI and report to be sent.
|
| class MockCertificateReportSender
|
| : public TransportSecurityState::ReportSenderInterface {
|
| @@ -1869,4 +1875,204 @@ TEST_F(TransportSecurityStateTest, ExpectCTReporter) {
|
| EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
|
| }
|
|
|
| +class MockExpectStapleReportSender : public MockCertificateReportSender {
|
| + public:
|
| + bool ReportSent() { return latest_report() != ""; }
|
| +};
|
| +
|
| +class ExpectStapleTest : public TransportSecurityStateTest {
|
| + public:
|
| + void SetUp() override {
|
| + TransportSecurityStateTest::SetUp();
|
| + security_state_.SetReportSender(&report_sender_);
|
| + EnableStaticExpectStaple(&security_state_);
|
| + verify_time_ = base::Time::Now();
|
| + }
|
| +
|
| + struct OCSPTest {
|
| + std::string response;
|
| + scoped_refptr<X509Certificate> certificate;
|
| + };
|
| +
|
| + static bool LoadOCSPFromFile(std::string file_name, OCSPTest* ocsp) {
|
| + std::string ca_data;
|
| + std::string cert_data;
|
| + const PemBlockMapping mappings[] = {
|
| + {"OCSP RESPONSE", &ocsp->response},
|
| + {"CA CERTIFICATE", &ca_data},
|
| + {"CERTIFICATE", &cert_data},
|
| + };
|
| + std::string full_path = std::string(kOCSPPathPrefix) + file_name;
|
| + if (!ReadTestDataFromPemFile(full_path, mappings))
|
| + return false;
|
| +
|
| + // Parse the server certificate
|
| + CertificateList server_cert_list =
|
| + X509Certificate::CreateCertificateListFromBytes(
|
| + cert_data.data(), cert_data.size(),
|
| + X509Certificate::FORMAT_SINGLE_CERTIFICATE);
|
| + ocsp->certificate = server_cert_list[0];
|
| + return true;
|
| + }
|
| +
|
| + static void CheckExpectStapleReport(
|
| + const std::string& serialized_report,
|
| + const HostPortPair& host_port,
|
| + const X509Certificate& served_certificate_chain,
|
| + const ExpectStapleReport& report) {
|
| + std::unique_ptr<base::Value> value(
|
| + base::JSONReader::Read(serialized_report));
|
| + ASSERT_TRUE(value);
|
| + ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
|
| +
|
| + base::DictionaryValue* report_dict;
|
| + ASSERT_TRUE(value->GetAsDictionary(&report_dict));
|
| + std::string report_hostname;
|
| + EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
|
| + EXPECT_EQ(host_port.host(), report_hostname);
|
| + int report_port;
|
| + EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
|
| + EXPECT_EQ(host_port.port(), report_port);
|
| +
|
| + // Check certificate chain.
|
| + const base::ListValue* report_served_certificate_chain = nullptr;
|
| + ASSERT_TRUE(report_dict->GetList("served-certificate-chain",
|
| + &report_served_certificate_chain));
|
| + std::vector<std::string> pem_encoded_chain;
|
| + served_certificate_chain.GetPEMEncodedChain(&pem_encoded_chain);
|
| + ASSERT_EQ(pem_encoded_chain.size(),
|
| + report_served_certificate_chain->GetSize());
|
| + for (size_t i = 0; i < pem_encoded_chain.size(); i++) {
|
| + std::string cert_pem;
|
| + ASSERT_TRUE(report_served_certificate_chain->GetString(i, &cert_pem));
|
| + EXPECT_EQ(pem_encoded_chain[i], cert_pem);
|
| + }
|
| +
|
| + // Check stapled responses.
|
| + const base::ListValue* report_ocsp_responses = nullptr;
|
| + ASSERT_TRUE(report_dict->GetList("ocsp-responses", &report_ocsp_responses));
|
| + const auto& ocsp_responses = report.stapled_responses();
|
| + ASSERT_EQ(ocsp_responses.size(), report_ocsp_responses->GetSize());
|
| + for (size_t i = 0; i < ocsp_responses.size(); i++) {
|
| + const base::DictionaryValue* report_ocsp_response = nullptr;
|
| + report_ocsp_responses->GetDictionary(i, &report_ocsp_response);
|
| + bool is_date_valid;
|
| + ASSERT_TRUE(
|
| + report_ocsp_response->GetBoolean("is-date-valid", &is_date_valid));
|
| + EXPECT_EQ(ocsp_responses[i].is_date_valid, is_date_valid);
|
| + bool is_correct_certificate;
|
| + ASSERT_TRUE(report_ocsp_response->GetBoolean("is-correct-certificate",
|
| + &is_correct_certificate));
|
| + EXPECT_EQ(ocsp_responses[i].is_correct_certificate,
|
| + is_correct_certificate);
|
| + }
|
| + }
|
| +
|
| + protected:
|
| + static bool SerializeExpectStapleReport(
|
| + const HostPortPair& host_port_pair,
|
| + const X509Certificate& unverified_certificate,
|
| + const ExpectStapleReport& report,
|
| + std::string* serialized_report) {
|
| + return TransportSecurityState::SerializeExpectStapleReport(
|
| + host_port_pair, unverified_certificate, report, serialized_report);
|
| + }
|
| +
|
| + TransportSecurityState security_state_;
|
| + MockExpectStapleReportSender report_sender_;
|
| + base::Time verify_time_;
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, NoReportGoodResponse) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("good_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate,
|
| + *ocsp_test.certificate, verify_time_,
|
| + kAgeTenYears, ocsp_test.response);
|
| + EXPECT_FALSE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, ReportMissingResponse) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("missing_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate,
|
| + *ocsp_test.certificate, verify_time_,
|
| + kAgeTenYears, ocsp_test.response);
|
| + EXPECT_TRUE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, ReportOldResponse) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("good_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(
|
| + host_port, *ocsp_test.certificate, *ocsp_test.certificate, verify_time_,
|
| + base::TimeDelta::FromDays(7), ocsp_test.response);
|
| + EXPECT_TRUE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, RevokedResponse) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("revoke_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate,
|
| + *ocsp_test.certificate, verify_time_,
|
| + kAgeTenYears, ocsp_test.response);
|
| + EXPECT_TRUE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, HasExtensions) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("has_extension.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate,
|
| + *ocsp_test.certificate, verify_time_,
|
| + kAgeTenYears, ocsp_test.response);
|
| + EXPECT_FALSE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, MultipleResponse) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("multiple_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + security_state_.CheckExpectStaple(host_port, *ocsp_test.certificate,
|
| + *ocsp_test.certificate, verify_time_,
|
| + kAgeTenYears, ocsp_test.response);
|
| + EXPECT_FALSE(report_sender_.ReportSent());
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, SerializeEmptyReport) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("missing_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + std::unique_ptr<ExpectStapleReport> report =
|
| + ExpectStapleReport::FromRawOCSPResponse(ocsp_test.response, verify_time_,
|
| + kAgeTenYears,
|
| + *ocsp_test.certificate);
|
| + ASSERT_TRUE(report);
|
| + std::string serialized_report;
|
| + ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate,
|
| + *report, &serialized_report));
|
| + ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport(
|
| + serialized_report, host_port, *ocsp_test.certificate, *report));
|
| +};
|
| +
|
| +TEST_F(ExpectStapleTest, SerializeMultipleResponses) {
|
| + OCSPTest ocsp_test;
|
| + ASSERT_TRUE(LoadOCSPFromFile("multiple_response.pem", &ocsp_test));
|
| + HostPortPair host_port(kExpectStapleStaticHostname, 443);
|
| + std::unique_ptr<ExpectStapleReport> report =
|
| + ExpectStapleReport::FromRawOCSPResponse(ocsp_test.response, verify_time_,
|
| + kAgeTenYears,
|
| + *ocsp_test.certificate);
|
| + ASSERT_TRUE(report);
|
| + std::string serialized_report;
|
| + ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate,
|
| + *report, &serialized_report));
|
| + ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport(
|
| + serialized_report, host_port, *ocsp_test.certificate, *report));
|
| +};
|
| +
|
| } // namespace net
|
|
|