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

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: Make switch statements Android/ChromeOS friendly 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
« no previous file with comments | « net/http/transport_security_state.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Checks the following hold for |report| such that it is a valid Expect-Staple
244 // report:
245 // 1. |report| is a JSON dictionary.
246 // 2. The "hostname" and "port" fields match |host_port_pair|.
247 // 3. The "response-status" field matches |response_status|
248 // 4. The "ocsp-response" field is a base64-encoded verson of |ocsp_response|,
249 // and is not present when |ocsp_response| is empty.
250 // 5. The "cert-status" field matches |cert_status|, and is not present when
251 // |cert_status| is empty.
252 // 6. The "validated-chain" and "serverd-chain" fields match those in
253 // |ssl_info|, and are only present when |ssl_info.is_issued_by_known_root|
254 // is true.
255 void CheckSerializedExpectStapleReport(const std::string& report,
256 const HostPortPair& host_port_pair,
257 const SSLInfo& ssl_info,
258 const std::string& ocsp_response,
259 const std::string& response_status,
260 const std::string& cert_status) {
261 std::unique_ptr<base::Value> value(base::JSONReader::Read(report));
262 ASSERT_TRUE(value);
263 ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
264
265 base::DictionaryValue* report_dict;
266 ASSERT_TRUE(value->GetAsDictionary(&report_dict));
267
268 std::string report_hostname;
269 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
270 EXPECT_EQ(host_port_pair.host(), report_hostname);
271
272 int report_port;
273 EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
274 EXPECT_EQ(host_port_pair.port(), report_port);
275
276 std::string report_response_status;
277 EXPECT_TRUE(
278 report_dict->GetString("response-status", &report_response_status));
279 EXPECT_EQ(response_status, report_response_status);
280
281 std::string report_ocsp_response;
282 bool has_ocsp_response =
283 report_dict->GetString("ocsp-response", &report_ocsp_response);
284
285 if (!ocsp_response.empty()) {
286 EXPECT_TRUE(has_ocsp_response);
287 std::string decoded_ocsp_response;
288 EXPECT_TRUE(
289 base::Base64Decode(report_ocsp_response, &decoded_ocsp_response));
290 EXPECT_EQ(ocsp_response, decoded_ocsp_response);
291 } else {
292 EXPECT_FALSE(has_ocsp_response);
293 }
294
295 std::string report_cert_status;
296 bool has_cert_status =
297 report_dict->GetString("cert-status", &report_cert_status);
298 if (!cert_status.empty()) {
299 EXPECT_TRUE(has_cert_status);
300 EXPECT_EQ(cert_status, report_cert_status);
301 } else {
302 EXPECT_FALSE(has_cert_status);
303 }
304
305 base::ListValue* report_served_certificate_chain;
306 bool has_served_chain = report_dict->GetList(
307 "served-certificate-chain", &report_served_certificate_chain);
308
309 base::ListValue* report_validated_certificate_chain;
310 bool has_validated_chain = report_dict->GetList(
311 "validated-certificate-chain", &report_validated_certificate_chain);
312
313 if (ssl_info.is_issued_by_known_root) {
314 EXPECT_TRUE(has_served_chain);
315 EXPECT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
316 ssl_info.unverified_cert, report_served_certificate_chain));
317
318 EXPECT_TRUE(has_validated_chain);
319 EXPECT_NO_FATAL_FAILURE(CompareCertificateChainWithList(
320 ssl_info.cert, report_validated_certificate_chain));
321 } else {
322 EXPECT_FALSE(has_served_chain);
323 EXPECT_FALSE(has_validated_chain);
324 }
325 }
326
327 // Set up |state| for ExpectStaple, call CheckExpectStaple(), and verify the
328 // serialized report caught by |reporter|.
329 void CheckExpectStapleReport(TransportSecurityState* state,
330 MockCertificateReportSender* reporter,
331 const SSLInfo& ssl_info,
332 const std::string& ocsp_response,
333 const std::string& response_status,
334 const std::string& cert_status) {
335 // Expect-Staple is preload list based, so we use the baked-in test hostname
336 // from the list ("preloaded-expect-staple.badssl.com").
337 HostPortPair host_port(kExpectStapleStaticHostname, 443);
338 state->SetReportSender(reporter);
339 state->CheckExpectStaple(host_port, ssl_info, ocsp_response);
340 EXPECT_EQ(GURL(kExpectStapleStaticReportURI), reporter->latest_report_uri());
341 std::string serialized_report = reporter->latest_report();
342 EXPECT_NO_FATAL_FAILURE(CheckSerializedExpectStapleReport(
343 serialized_report, host_port, ssl_info, ocsp_response, response_status,
344 cert_status));
345 }
346
243 } // namespace 347 } // namespace
244 348
245 class TransportSecurityStateTest : public testing::Test { 349 class TransportSecurityStateTest : public testing::Test {
246 public: 350 public:
247 void SetUp() override { 351 void SetUp() override {
248 crypto::EnsureOpenSSLInit(); 352 crypto::EnsureOpenSSLInit();
249 } 353 }
250 354
251 static void DisableStaticPins(TransportSecurityState* state) { 355 static void DisableStaticPins(TransportSecurityState* state) {
252 state->enable_static_pins_ = false; 356 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); 1999 state.ProcessExpectCTHeader("preload", host_port, ssl_info);
1896 EXPECT_EQ(1u, reporter.num_failures()); 2000 EXPECT_EQ(1u, reporter.num_failures());
1897 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available); 2001 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available);
1898 EXPECT_EQ(ssl_info.ct_cert_policy_compliance, 2002 EXPECT_EQ(ssl_info.ct_cert_policy_compliance,
1899 reporter.ssl_info().ct_cert_policy_compliance); 2003 reporter.ssl_info().ct_cert_policy_compliance);
1900 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host()); 2004 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host());
1901 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port()); 2005 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port());
1902 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); 2006 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
1903 } 2007 }
1904 2008
2009 static const struct ExpectStapleErrorResponseData {
2010 OCSPVerifyResult::ResponseStatus response_status;
2011 std::string response_status_string;
2012 } kExpectStapleReportData[] = {
2013 {OCSPVerifyResult::MISSING, "MISSING"},
2014 {OCSPVerifyResult::ERROR_RESPONSE, "ERROR_RESPONSE"},
2015 {OCSPVerifyResult::BAD_PRODUCED_AT, "BAD_PRODUCED_AT"},
2016 {OCSPVerifyResult::NO_MATCHING_RESPONSE, "NO_MATCHING_RESPONSE"},
2017 {OCSPVerifyResult::INVALID_DATE, "INVALID_DATE"},
2018 {OCSPVerifyResult::PARSE_RESPONSE_ERROR, "PARSE_RESPONSE_ERROR"},
2019 {OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR, "PARSE_RESPONSE_DATA_ERROR"},
2020 };
2021
2022 class ExpectStapleErrorResponseTest
2023 : public TransportSecurityStateTest,
2024 public testing::WithParamInterface<ExpectStapleErrorResponseData> {};
2025
2026 // For every |response_status| indicating an OCSP response was provided, but had
2027 // some sort of parsing/validation error, test that the ExpectStaple report is
2028 // serialized correctly.
2029 TEST_P(ExpectStapleErrorResponseTest, CheckResponseStatusSerialization) {
2030 TransportSecurityState state;
2031 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2032 MockCertificateReportSender reporter;
2033 ExpectStapleErrorResponseData test = GetParam();
2034
2035 std::string ocsp_response;
2036 if (test.response_status != OCSPVerifyResult::MISSING)
2037 ocsp_response = "dummy_response";
2038
2039 // Two dummy certs to use as the server-sent and validated chains. The
2040 // contents don't matter.
2041 scoped_refptr<X509Certificate> cert1 =
2042 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2043 scoped_refptr<X509Certificate> cert2 =
2044 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2045
2046 SSLInfo ssl_info;
2047 ssl_info.cert = cert1;
2048 ssl_info.unverified_cert = cert2;
2049 ssl_info.ocsp_result.response_status = test.response_status;
2050
2051 // Certificate chains should only be included when |is_issued_by_known_root|
2052 // is true.
2053 ssl_info.is_issued_by_known_root = true;
2054 ASSERT_NO_FATAL_FAILURE(
2055 CheckExpectStapleReport(&state, &reporter, ssl_info, ocsp_response,
2056 test.response_status_string, std::string()));
2057
2058 // No certificate chains should be included in the report.
2059 ssl_info.is_issued_by_known_root = false;
2060 ASSERT_NO_FATAL_FAILURE(
2061 CheckExpectStapleReport(&state, &reporter, ssl_info, ocsp_response,
2062 test.response_status_string, std::string()));
2063 }
2064
2065 INSTANTIATE_TEST_CASE_P(ExpectStaple,
2066 ExpectStapleErrorResponseTest,
2067 testing::ValuesIn(kExpectStapleReportData));
2068
2069 static const struct ExpectStapleErrorCertStatusData {
2070 OCSPRevocationStatus revocation_status;
2071 std::string cert_status_string;
2072 } kExpectStapleErrorCertStatusData[] = {
2073 {OCSPRevocationStatus::REVOKED, "REVOKED"},
2074 {OCSPRevocationStatus::UNKNOWN, "UNKNOWN"},
2075 };
2076
2077 class ExpectStapleErrorCertStatusTest
2078 : public TransportSecurityStateTest,
2079 public testing::WithParamInterface<ExpectStapleErrorCertStatusData> {};
2080
2081 // Test that |revocation_status| is serialized into the |cert-status| field of
2082 // the Expect-Staple report whenever |response_status| is PROVIDED and
2083 // |revocation_status| != GOOD.
2084 TEST_P(ExpectStapleErrorCertStatusTest, CheckCertStatusSerialization) {
2085 TransportSecurityState state;
2086 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2087 MockCertificateReportSender reporter;
2088 ExpectStapleErrorCertStatusData test = GetParam();
2089 std::string ocsp_response = "dummy_response";
2090
2091 // Two dummy certs to use as the server-sent and validated chains. The
2092 // contents don't matter.
2093 scoped_refptr<X509Certificate> cert1 =
2094 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2095 scoped_refptr<X509Certificate> cert2 =
2096 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2097
2098 SSLInfo ssl_info;
2099 ssl_info.cert = cert1;
2100 ssl_info.unverified_cert = cert2;
2101 // |response_status| must be set to PROVIDED for |revocation_status| to have
2102 // meaning.
2103 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED;
2104 ssl_info.ocsp_result.revocation_status = test.revocation_status;
2105
2106 // Certificate chains should only be included when |is_issued_by_known_root|
2107 // is true.
2108 ssl_info.is_issued_by_known_root = true;
2109 ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport(&state, &reporter, ssl_info,
2110 ocsp_response, "PROVIDED",
2111 test.cert_status_string));
2112
2113 // No certificate chains should be included in the report.
2114 ssl_info.is_issued_by_known_root = false;
2115 ASSERT_NO_FATAL_FAILURE(CheckExpectStapleReport(&state, &reporter, ssl_info,
2116 ocsp_response, "PROVIDED",
2117 test.cert_status_string));
2118 };
2119
2120 INSTANTIATE_TEST_CASE_P(ExpectStaple,
2121 ExpectStapleErrorCertStatusTest,
2122 testing::ValuesIn(kExpectStapleErrorCertStatusData));
2123
2124 TEST_F(TransportSecurityStateTest, ExpectStapleDoesNotReportValidStaple) {
2125 TransportSecurityState state;
2126 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2127 MockCertificateReportSender reporter;
2128 state.SetReportSender(&reporter);
2129
2130 // Baked-in preloaded Expect-Staple test hosts.
2131 HostPortPair host_port(kExpectStapleStaticHostname, 443);
2132
2133 // Two dummy certs to use as the server-sent and validated chains. The
2134 // contents don't matter.
2135 scoped_refptr<X509Certificate> cert1 =
2136 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2137 scoped_refptr<X509Certificate> cert2 =
2138 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2139
2140 SSLInfo ssl_info;
2141 ssl_info.cert = cert1;
2142 ssl_info.unverified_cert = cert2;
2143 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED;
2144 ssl_info.ocsp_result.revocation_status = OCSPRevocationStatus::GOOD;
2145
2146 std::string ocsp_response = "dummy response";
2147
2148 ssl_info.is_issued_by_known_root = true;
2149 state.CheckExpectStaple(host_port, ssl_info, ocsp_response);
2150 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2151 EXPECT_TRUE(reporter.latest_report().empty());
2152
2153 ssl_info.is_issued_by_known_root = false;
2154 state.CheckExpectStaple(host_port, ssl_info, ocsp_response);
2155 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2156 EXPECT_TRUE(reporter.latest_report().empty());
2157 }
2158
2159 TEST_F(TransportSecurityStateTest, ExpectStapleRequiresPreload) {
2160 TransportSecurityState state;
2161 TransportSecurityStateTest::EnableStaticExpectStaple(&state);
2162 MockCertificateReportSender reporter;
2163 state.SetReportSender(&reporter);
2164
2165 HostPortPair host_port("not-preloaded.host.example", 443);
2166
2167 // Two dummy certs to use as the server-sent and validated chains. The
2168 // contents don't matter.
2169 scoped_refptr<X509Certificate> cert1 =
2170 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
2171 scoped_refptr<X509Certificate> cert2 =
2172 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
2173
2174 SSLInfo ssl_info;
2175 ssl_info.cert = cert1;
2176 ssl_info.unverified_cert = cert2;
2177 ssl_info.ocsp_result.response_status = OCSPVerifyResult::MISSING;
2178
2179 // Empty response
2180 std::string ocsp_response;
2181
2182 ssl_info.is_issued_by_known_root = true;
2183 state.CheckExpectStaple(host_port, ssl_info, ocsp_response);
2184 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2185 EXPECT_TRUE(reporter.latest_report().empty());
2186
2187 ssl_info.is_issued_by_known_root = false;
2188 state.CheckExpectStaple(host_port, ssl_info, ocsp_response);
2189 EXPECT_EQ(GURL(), reporter.latest_report_uri());
2190 EXPECT_TRUE(reporter.latest_report().empty());
2191 }
2192
1905 // Tests that TransportSecurityState always consults the RequireCTDelegate, 2193 // Tests that TransportSecurityState always consults the RequireCTDelegate,
1906 // if supplied. 2194 // if supplied.
1907 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) { 2195 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) {
1908 using ::testing::_; 2196 using ::testing::_;
1909 using ::testing::Return; 2197 using ::testing::Return;
1910 using CTRequirementLevel = 2198 using CTRequirementLevel =
1911 TransportSecurityState::RequireCTDelegate::CTRequirementLevel; 2199 TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
1912 2200
1913 // Dummy cert to use as the validate chain. The contents do not matter. 2201 // Dummy cert to use as the validate chain. The contents do not matter.
1914 scoped_refptr<X509Certificate> cert = 2202 scoped_refptr<X509Certificate> cert =
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2029 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots", 2317 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots",
2030 "disabled"); 2318 "disabled");
2031 2319
2032 EXPECT_FALSE( 2320 EXPECT_FALSE(
2033 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); 2321 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes));
2034 EXPECT_FALSE( 2322 EXPECT_FALSE(
2035 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); 2323 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes));
2036 } 2324 }
2037 2325
2038 } // namespace net 2326 } // namespace net
OLDNEW
« no previous file with comments | « net/http/transport_security_state.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698