Chromium Code Reviews| 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..5528485f79ad2fc0ff8467132d7a71cc92b59c93 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& kOCSPResponseMaxAge = 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,228 @@ TEST_F(TransportSecurityStateTest, ExpectCTReporter) { |
| EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); |
| } |
| +class MockExpectStapleReportSender : public MockCertificateReportSender { |
| + public: |
| + bool ReportSent() { return latest_report() != ""; } |
|
Ryan Sleevi
2016/06/16 21:49:30
return !latest_report().empty()
|
| +}; |
| + |
| +class ExpectStapleTest : public TransportSecurityStateTest { |
| + public: |
| + void SetUp() override { |
|
Ryan Sleevi
2016/06/16 21:49:30
https://github.com/google/googletest/blob/master/g
|
| + 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) { |
|
Ryan Sleevi
2016/06/16 21:49:29
Why static?
dadrian
2016/06/17 17:26:55
Matching other tests, and this doesn't/shouldn't n
|
| + 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( |
|
Ryan Sleevi
2016/06/16 21:49:30
Why static?
|
| + const std::string& serialized_report, |
| + const HostPortPair& host_port, |
| + const X509Certificate& served_certificate_chain, |
| + bool is_issued_by_known_root, |
| + 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; |
| + if (is_issued_by_known_root) { |
| + 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); |
| + } |
| + } else { |
| + EXPECT_FALSE(report_dict->GetList("served-certificate-chain", |
| + &report_served_certificate_chain)); |
| + } |
| + |
| + // 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( |
|
Ryan Sleevi
2016/06/16 21:49:29
Why static?
|
| + const HostPortPair& host_port_pair, |
| + const X509Certificate& unverified_certificate, |
| + bool is_issued_by_known_root, |
| + const ExpectStapleReport& report, |
| + std::string* serialized_report) { |
| + return TransportSecurityState::SerializeExpectStapleReport( |
| + host_port_pair, unverified_certificate, is_issued_by_known_root, 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, true, verify_time_, |
| + kOCSPResponseMaxAge, 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, true, verify_time_, |
| + kOCSPResponseMaxAge, 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, true, |
| + 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, true, verify_time_, |
| + kOCSPResponseMaxAge, 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, true, verify_time_, |
| + kOCSPResponseMaxAge, 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, true, verify_time_, |
| + kOCSPResponseMaxAge, 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_, |
| + kOCSPResponseMaxAge, |
| + *ocsp_test.certificate); |
| + ASSERT_TRUE(report); |
| + std::string serialized_report; |
| + ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate, |
| + true, *report, &serialized_report)); |
| + ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport( |
| + serialized_report, host_port, *ocsp_test.certificate, true, *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_, |
| + kOCSPResponseMaxAge, |
| + *ocsp_test.certificate); |
| + ASSERT_TRUE(report); |
| + std::string serialized_report; |
| + ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate, |
| + true, *report, &serialized_report)); |
| + ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport( |
| + serialized_report, host_port, *ocsp_test.certificate, true, *report)); |
| +}; |
| + |
| +TEST_F(ExpectStapleTest, SerializeMultipleResponsesPrivateRoot) { |
| + 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_, |
| + kOCSPResponseMaxAge, |
| + *ocsp_test.certificate); |
| + ASSERT_TRUE(report); |
| + std::string serialized_report; |
| + ASSERT_TRUE(SerializeExpectStapleReport(host_port, *ocsp_test.certificate, |
| + false, *report, &serialized_report)); |
| + ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport( |
| + serialized_report, host_port, *ocsp_test.certificate, false, *report)); |
| +}; |
| + |
| } // namespace net |