Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: net/http/transport_security_state_unittest.cc

Issue 2144693004: Add the ability to send Expect-Staple reports. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ocsp-verify-result
Patch Set: Compile after rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/http/transport_security_state.h" 5 #include "net/http/transport_security_state.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( 233 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
234 served_certificate_chain, report_served_certificate_chain)); 234 served_certificate_chain, report_served_certificate_chain));
235 235
236 base::ListValue* report_validated_certificate_chain; 236 base::ListValue* report_validated_certificate_chain;
237 EXPECT_TRUE(report_dict->GetList("validated-certificate-chain", 237 EXPECT_TRUE(report_dict->GetList("validated-certificate-chain",
238 &report_validated_certificate_chain)); 238 &report_validated_certificate_chain));
239 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( 239 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
240 validated_certificate_chain, report_validated_certificate_chain)); 240 validated_certificate_chain, report_validated_certificate_chain));
241 } 241 }
242 242
243 bool ResponseStatusFromString(std::string in,
Ryan Sleevi 2016/07/19 00:02:49 From a testing design standpoint, it doesn't seem
dadrian 2016/07/19 00:18:54 I did it this way since the reverse function is in
Ryan Sleevi 2016/07/19 01:17:22 Unfortunately, I'm having a lot of trouble underst
dadrian 2016/07/19 18:48:40 I reworked the tests to be table-driven with TEST_
244 OCSPVerifyResult::ResponseStatus* status) {
245 if (in == "MISSING") {
246 *status = OCSPVerifyResult::MISSING;
247 } else if (in == "PROVIDED") {
248 *status = OCSPVerifyResult::PROVIDED;
249 } else if (in == "ERROR_RESPONSE") {
250 *status = OCSPVerifyResult::ERROR_RESPONSE;
251 } else if (in == "BAD_PRODUCED_AT") {
252 *status = OCSPVerifyResult::BAD_PRODUCED_AT;
253 } else if (in == "NO_MATCHING_RESPONSE") {
254 *status = OCSPVerifyResult::NO_MATCHING_RESPONSE;
255 } else if (in == "INVALID_DATE") {
256 *status = OCSPVerifyResult::INVALID_DATE;
257 } else if (in == "PARSE_RESPONSE_ERROR") {
258 *status = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
259 } else if (in == "PARSE_RESPONSE_DATA_ERROR") {
260 *status = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
261 } else {
262 return false;
263 }
264 return true;
265 }
266
267 bool RevocationStatusFromString(std::string in, OCSPRevocationStatus* status) {
Ryan Sleevi 2016/07/19 00:02:49 Same remarks
dadrian 2016/07/19 18:48:39 Done.
268 if (in == "GOOD") {
269 *status = OCSPRevocationStatus::GOOD;
270 } else if (in == "REVOKED") {
271 *status = OCSPRevocationStatus::REVOKED;
272 } else if (in == "UNKNOWN") {
273 *status = OCSPRevocationStatus::UNKNOWN;
274 } else {
275 return false;
276 }
277 return true;
278 }
279
280 void CheckExpectStapleReport(const std::string& report,
281 const HostPortPair& host_port_pair,
282 const SSLInfo& ssl_info,
283 const std::string& ocsp_response) {
284 std::unique_ptr<base::Value> value(base::JSONReader::Read(report));
285 ASSERT_TRUE(value);
286 ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
287
288 base::DictionaryValue* report_dict;
289 ASSERT_TRUE(value->GetAsDictionary(&report_dict));
290
291 std::string report_hostname;
292 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
293 EXPECT_EQ(host_port_pair.host(), report_hostname);
294
295 int report_port;
296 EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
297 EXPECT_EQ(host_port_pair.port(), report_port);
298
299 std::string report_response_status;
300 EXPECT_TRUE(
301 report_dict->GetString("response-status", &report_response_status));
302 OCSPVerifyResult::ResponseStatus response_status;
303 EXPECT_TRUE(
304 ResponseStatusFromString(report_response_status, &response_status));
305 EXPECT_EQ(ssl_info.ocsp_result.response_status, response_status);
306
307 std::string report_ocsp_response;
308 bool has_ocsp_response =
309 report_dict->GetString("ocsp-response", &report_ocsp_response);
310
311 if (!ocsp_response.empty()) {
312 EXPECT_TRUE(has_ocsp_response);
313 std::string decoded_ocsp_response;
314 EXPECT_TRUE(
315 base::Base64Decode(report_ocsp_response, &decoded_ocsp_response));
316 EXPECT_EQ(ocsp_response, decoded_ocsp_response);
317 } else {
318 EXPECT_FALSE(has_ocsp_response);
319 }
320
321 std::string report_cert_status;
322 bool has_cert_status =
323 report_dict->GetString("cert-status", &report_cert_status);
324 if (ssl_info.ocsp_result.response_status == OCSPVerifyResult::PROVIDED) {
325 EXPECT_TRUE(has_cert_status);
326 OCSPRevocationStatus revocation_status;
327 EXPECT_TRUE(
328 RevocationStatusFromString(report_cert_status, &revocation_status));
329 EXPECT_EQ(ssl_info.ocsp_result.revocation_status, revocation_status);
330 } else {
331 EXPECT_FALSE(has_cert_status);
332 }
333
334 base::ListValue* report_served_certificate_chain;
335 bool has_served_chain = report_dict->GetList(
336 "served-certificate-chain", &report_served_certificate_chain);
337
338 base::ListValue* report_validated_certificate_chain;
339 bool has_validated_chain = report_dict->GetList(
340 "validated-certificate-chain", &report_validated_certificate_chain);
341
342 if (ssl_info.is_issued_by_known_root) {
343 EXPECT_TRUE(has_served_chain);
344 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
345 ssl_info.unverified_cert, report_served_certificate_chain));
346
347 EXPECT_TRUE(has_validated_chain);
348 ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
349 ssl_info.cert, report_validated_certificate_chain));
350 } else {
351 EXPECT_FALSE(has_served_chain);
352 EXPECT_FALSE(has_validated_chain);
353 }
354 }
355
356 void CheckExpectStaple(TransportSecurityState* state,
357 MockCertificateReportSender* reporter,
358 const SSLInfo& ssl_info,
359 const std::string ocsp_response) {
360 HostPortPair host_port(kExpectStapleStaticHostname, 443);
361 state->SetReportSender(reporter);
362 state->ProcessExpectStaple(host_port, ssl_info, ocsp_response);
363 EXPECT_EQ(GURL(kExpectStapleStaticReportURI), reporter->latest_report_uri());
364 std::string serialized_report = reporter->latest_report();
365 EXPECT_NO_FATAL_FAILURE(CheckExpectStapleReport(serialized_report, host_port,
366 ssl_info, ocsp_response));
367 }
368
243 } // namespace 369 } // namespace
244 370
245 class TransportSecurityStateTest : public testing::Test { 371 class TransportSecurityStateTest : public testing::Test {
246 public: 372 public:
247 void SetUp() override { 373 void SetUp() override {
248 crypto::EnsureOpenSSLInit(); 374 crypto::EnsureOpenSSLInit();
249 } 375 }
250 376
251 static void DisableStaticPins(TransportSecurityState* state) { 377 static void DisableStaticPins(TransportSecurityState* state) {
252 state->enable_static_pins_ = false; 378 state->enable_static_pins_ = false;
(...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after
1895 state.ProcessExpectCTHeader("preload", host_port, ssl_info); 2021 state.ProcessExpectCTHeader("preload", host_port, ssl_info);
1896 EXPECT_EQ(1u, reporter.num_failures()); 2022 EXPECT_EQ(1u, reporter.num_failures());
1897 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available); 2023 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available);
1898 EXPECT_EQ(ssl_info.ct_cert_policy_compliance, 2024 EXPECT_EQ(ssl_info.ct_cert_policy_compliance,
1899 reporter.ssl_info().ct_cert_policy_compliance); 2025 reporter.ssl_info().ct_cert_policy_compliance);
1900 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host()); 2026 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host());
1901 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port()); 2027 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port());
1902 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); 2028 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
1903 } 2029 }
1904 2030
2031 TEST_F(TransportSecurityStateTest, ExpectStapleReporter) {
2032 TransportSecurityState state;
2033 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2034 MockCertificateReportSender reporter;
2035
2036 std::string ocsp_response;
2037
2038 // Two dummy certs to use as the server-sent and validated chains. The
2039 // contents don't matter.
2040 scoped_refptr<X509Certificate> cert1 =
2041 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2042 scoped_refptr<X509Certificate> cert2 =
2043 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2044
2045 SSLInfo ssl_info;
2046 ssl_info.is_issued_by_known_root = true;
2047 ssl_info.cert = cert1;
2048 ssl_info.unverified_cert = cert2;
2049 ssl_info.ocsp_result.response_status = OCSPVerifyResult::MISSING;
2050
2051 ASSERT_NO_FATAL_FAILURE(
2052 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response));
2053
2054 // Certs should not be included for non-public roots.
2055 ssl_info.is_issued_by_known_root = false;
2056 ASSERT_NO_FATAL_FAILURE(
2057 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response));
2058
2059 // Check response statuses that correspond with a stapled response, but not
2060 // revocation status.
2061 ocsp_response = "dummy response";
2062 ssl_info.is_issued_by_known_root = true;
2063 std::vector<OCSPVerifyResult::ResponseStatus> response_statuses{
2064 OCSPVerifyResult::ERROR_RESPONSE,
2065 OCSPVerifyResult::BAD_PRODUCED_AT,
2066 OCSPVerifyResult::NO_MATCHING_RESPONSE,
2067 OCSPVerifyResult::INVALID_DATE,
2068 OCSPVerifyResult::PARSE_RESPONSE_ERROR,
2069 OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR,
2070 };
2071 for (const auto& response_status : response_statuses) {
2072 ssl_info.ocsp_result.response_status = response_status;
2073 ASSERT_NO_FATAL_FAILURE(
2074 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response));
2075 }
2076
2077 // Check each revocation status that should trigger a report.
2078 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED;
2079 std::vector<OCSPRevocationStatus> cert_statuses{
2080 OCSPRevocationStatus::REVOKED, OCSPRevocationStatus::UNKNOWN,
2081 };
2082 for (const auto& cert_status : cert_statuses) {
2083 ssl_info.ocsp_result.revocation_status = cert_status;
2084 ASSERT_NO_FATAL_FAILURE(
2085 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response));
2086 }
2087 }
2088
2089 TEST_F(TransportSecurityStateTest, ExpectStapleDoesNotReportValidStaple) {
2090 TransportSecurityState state;
2091 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2092 MockCertificateReportSender reporter;
2093 state.SetReportSender(&reporter);
2094
2095 HostPortPair host_port(kExpectStapleStaticHostname, 443);
2096
2097 // Two dummy certs to use as the server-sent and validated chains. The
2098 // contents don't matter.
2099 scoped_refptr<X509Certificate> cert1 =
2100 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2101 scoped_refptr<X509Certificate> cert2 =
2102 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2103
2104 SSLInfo ssl_info;
2105 ssl_info.is_issued_by_known_root = true;
2106 ssl_info.cert = cert1;
2107 ssl_info.unverified_cert = cert2;
2108 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED;
2109 ssl_info.ocsp_result.revocation_status = OCSPRevocationStatus::GOOD;
2110
2111 std::string ocsp_response = "dummy response";
2112
2113 state.ProcessExpectStaple(host_port, ssl_info, ocsp_response);
2114 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2115 EXPECT_TRUE(reporter.latest_report().empty());
2116 }
2117
2118 TEST_F(TransportSecurityStateTest, ExpectStapleRequiresPreload) {
2119 TransportSecurityState state;
2120 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2121 MockCertificateReportSender reporter;
2122 state.SetReportSender(&reporter);
2123
2124 HostPortPair host_port("not-preloaded.badssl.com", 443);
2125
2126 // Two dummy certs to use as the server-sent and validated chains. The
2127 // contents don't matter.
2128 scoped_refptr<X509Certificate> cert1 =
2129 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2130 scoped_refptr<X509Certificate> cert2 =
2131 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2132
2133 SSLInfo ssl_info;
2134 ssl_info.is_issued_by_known_root = true;
2135 ssl_info.cert = cert1;
2136 ssl_info.unverified_cert = cert2;
2137 ssl_info.ocsp_result.response_status = OCSPVerifyResult::MISSING;
2138
2139 // Empty response
2140 std::string ocsp_response;
2141
2142 state.ProcessExpectStaple(host_port, ssl_info, ocsp_response);
2143 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2144 EXPECT_TRUE(reporter.latest_report().empty());
2145 }
2146
1905 // Tests that TransportSecurityState always consults the RequireCTDelegate, 2147 // Tests that TransportSecurityState always consults the RequireCTDelegate,
1906 // if supplied. 2148 // if supplied.
1907 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) { 2149 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) {
1908 using ::testing::_; 2150 using ::testing::_;
1909 using ::testing::Return; 2151 using ::testing::Return;
1910 using CTRequirementLevel = 2152 using CTRequirementLevel =
1911 TransportSecurityState::RequireCTDelegate::CTRequirementLevel; 2153 TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
1912 2154
1913 // Dummy cert to use as the validate chain. The contents do not matter. 2155 // Dummy cert to use as the validate chain. The contents do not matter.
1914 scoped_refptr<X509Certificate> cert = 2156 scoped_refptr<X509Certificate> cert =
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2029 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots", 2271 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots",
2030 "disabled"); 2272 "disabled");
2031 2273
2032 EXPECT_FALSE( 2274 EXPECT_FALSE(
2033 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); 2275 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes));
2034 EXPECT_FALSE( 2276 EXPECT_FALSE(
2035 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); 2277 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes));
2036 } 2278 }
2037 2279
2038 } // namespace net 2280 } // namespace net
OLDNEW
« net/http/transport_security_state.cc ('K') | « net/http/transport_security_state.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698