Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 void CheckExpectStapleReport(const std::string& report, | |
| 244 const HostPortPair& host_port_pair, | |
| 245 const SSLInfo& ssl_info, | |
| 246 const std::string& ocsp_response, | |
| 247 const std::string& response_status, | |
| 248 const std::string& cert_status) { | |
| 249 std::unique_ptr<base::Value> value(base::JSONReader::Read(report)); | |
| 250 ASSERT_TRUE(value); | |
| 251 ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); | |
| 252 | |
| 253 base::DictionaryValue* report_dict; | |
| 254 ASSERT_TRUE(value->GetAsDictionary(&report_dict)); | |
| 255 | |
| 256 std::string report_hostname; | |
| 257 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); | |
| 258 EXPECT_EQ(host_port_pair.host(), report_hostname); | |
| 259 | |
| 260 int report_port; | |
| 261 EXPECT_TRUE(report_dict->GetInteger("port", &report_port)); | |
| 262 EXPECT_EQ(host_port_pair.port(), report_port); | |
| 263 | |
| 264 std::string report_response_status; | |
| 265 EXPECT_TRUE( | |
| 266 report_dict->GetString("response-status", &report_response_status)); | |
| 267 EXPECT_EQ(response_status, report_response_status); | |
| 268 | |
| 269 std::string report_ocsp_response; | |
| 270 bool has_ocsp_response = | |
| 271 report_dict->GetString("ocsp-response", &report_ocsp_response); | |
| 272 | |
| 273 if (!ocsp_response.empty()) { | |
| 274 EXPECT_TRUE(has_ocsp_response); | |
| 275 std::string decoded_ocsp_response; | |
| 276 EXPECT_TRUE( | |
| 277 base::Base64Decode(report_ocsp_response, &decoded_ocsp_response)); | |
| 278 EXPECT_EQ(ocsp_response, decoded_ocsp_response); | |
| 279 } else { | |
| 280 EXPECT_FALSE(has_ocsp_response); | |
| 281 } | |
| 282 | |
| 283 std::string report_cert_status; | |
| 284 bool has_cert_status = | |
| 285 report_dict->GetString("cert-status", &report_cert_status); | |
| 286 if (!cert_status.empty()) { | |
| 287 EXPECT_TRUE(has_cert_status); | |
| 288 EXPECT_EQ(cert_status, report_cert_status); | |
| 289 } else { | |
| 290 EXPECT_FALSE(has_cert_status); | |
| 291 } | |
| 292 | |
| 293 base::ListValue* report_served_certificate_chain; | |
| 294 bool has_served_chain = report_dict->GetList( | |
| 295 "served-certificate-chain", &report_served_certificate_chain); | |
| 296 | |
| 297 base::ListValue* report_validated_certificate_chain; | |
| 298 bool has_validated_chain = report_dict->GetList( | |
| 299 "validated-certificate-chain", &report_validated_certificate_chain); | |
| 300 | |
| 301 if (ssl_info.is_issued_by_known_root) { | |
| 302 EXPECT_TRUE(has_served_chain); | |
| 303 EXPECT_NO_FATAL_FAILURE(CompareCertificateChainWithList( | |
| 304 ssl_info.unverified_cert, report_served_certificate_chain)); | |
| 305 | |
| 306 EXPECT_TRUE(has_validated_chain); | |
| 307 EXPECT_NO_FATAL_FAILURE(CompareCertificateChainWithList( | |
| 308 ssl_info.cert, report_validated_certificate_chain)); | |
| 309 } else { | |
| 310 EXPECT_FALSE(has_served_chain); | |
| 311 EXPECT_FALSE(has_validated_chain); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 void CheckExpectStaple(TransportSecurityState* state, | |
| 316 MockCertificateReportSender* reporter, | |
| 317 const SSLInfo& ssl_info, | |
| 318 const std::string& ocsp_response, | |
| 319 const std::string& response_status, | |
| 320 const std::string& cert_status) { | |
| 321 HostPortPair host_port(kExpectStapleStaticHostname, 443); | |
|
Ryan Sleevi
2016/07/19 19:11:05
Where does this come from and why? The test lacks
dadrian
2016/07/19 21:21:46
Yup, it's baked into the preload list itself as a
| |
| 322 state->SetReportSender(reporter); | |
| 323 state->ProcessExpectStaple(host_port, ssl_info, ocsp_response); | |
| 324 EXPECT_EQ(GURL(kExpectStapleStaticReportURI), reporter->latest_report_uri()); | |
| 325 std::string serialized_report = reporter->latest_report(); | |
| 326 EXPECT_NO_FATAL_FAILURE( | |
| 327 CheckExpectStapleReport(serialized_report, host_port, ssl_info, | |
| 328 ocsp_response, response_status, cert_status)); | |
| 329 } | |
| 330 | |
| 243 } // namespace | 331 } // namespace |
| 244 | 332 |
| 245 class TransportSecurityStateTest : public testing::Test { | 333 class TransportSecurityStateTest : public testing::Test { |
| 246 public: | 334 public: |
| 247 void SetUp() override { | 335 void SetUp() override { |
| 248 crypto::EnsureOpenSSLInit(); | 336 crypto::EnsureOpenSSLInit(); |
| 249 } | 337 } |
| 250 | 338 |
| 251 static void DisableStaticPins(TransportSecurityState* state) { | 339 static void DisableStaticPins(TransportSecurityState* state) { |
| 252 state->enable_static_pins_ = false; | 340 state->enable_static_pins_ = false; |
| (...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1895 state.ProcessExpectCTHeader("preload", host_port, ssl_info); | 1983 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1896 EXPECT_EQ(1u, reporter.num_failures()); | 1984 EXPECT_EQ(1u, reporter.num_failures()); |
| 1897 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available); | 1985 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available); |
| 1898 EXPECT_EQ(ssl_info.ct_cert_policy_compliance, | 1986 EXPECT_EQ(ssl_info.ct_cert_policy_compliance, |
| 1899 reporter.ssl_info().ct_cert_policy_compliance); | 1987 reporter.ssl_info().ct_cert_policy_compliance); |
| 1900 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host()); | 1988 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host()); |
| 1901 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port()); | 1989 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port()); |
| 1902 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); | 1990 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); |
| 1903 } | 1991 } |
| 1904 | 1992 |
| 1993 static const struct ExpectStapleErrorResponseData { | |
| 1994 OCSPVerifyResult::ResponseStatus response_status; | |
| 1995 std::string response_status_string; | |
| 1996 } kExpectStapleReportData[] = { | |
| 1997 {OCSPVerifyResult::MISSING, "MISSING"}, | |
| 1998 {OCSPVerifyResult::ERROR_RESPONSE, "ERROR_RESPONSE"}, | |
| 1999 {OCSPVerifyResult::BAD_PRODUCED_AT, "BAD_PRODUCED_AT"}, | |
| 2000 {OCSPVerifyResult::NO_MATCHING_RESPONSE, "NO_MATCHING_RESPONSE"}, | |
| 2001 {OCSPVerifyResult::INVALID_DATE, "INVALID_DATE"}, | |
| 2002 {OCSPVerifyResult::PARSE_RESPONSE_ERROR, "PARSE_RESPONSE_ERROR"}, | |
| 2003 {OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR, "PARSE_RESPONSE_DATA_ERROR"}, | |
| 2004 }; | |
| 2005 | |
| 2006 class ExpectStapleErrorResponseTest | |
| 2007 : public TransportSecurityStateTest, | |
| 2008 public testing::WithParamInterface<ExpectStapleErrorResponseData> {}; | |
| 2009 | |
| 2010 TEST_P(ExpectStapleErrorResponseTest, CheckResponseStatusSerialization) { | |
|
Ryan Sleevi
2016/07/19 19:11:05
Improve high-level docs for the test
dadrian
2016/07/19 21:21:46
Done.
| |
| 2011 TransportSecurityState state; | |
| 2012 TransportSecurityStateTest::EnableStaticExpectStaple(&state); | |
| 2013 MockCertificateReportSender reporter; | |
| 2014 ExpectStapleErrorResponseData test = GetParam(); | |
| 2015 | |
| 2016 std::string ocsp_response; | |
| 2017 if (test.response_status != OCSPVerifyResult::MISSING) | |
| 2018 ocsp_response = "dummy_response"; | |
| 2019 | |
| 2020 // Two dummy certs to use as the server-sent and validated chains. The | |
| 2021 // contents don't matter. | |
| 2022 scoped_refptr<X509Certificate> cert1 = | |
| 2023 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); | |
| 2024 scoped_refptr<X509Certificate> cert2 = | |
| 2025 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); | |
| 2026 | |
| 2027 SSLInfo ssl_info; | |
| 2028 ssl_info.cert = cert1; | |
| 2029 ssl_info.unverified_cert = cert2; | |
| 2030 ssl_info.ocsp_result.response_status = test.response_status; | |
| 2031 | |
| 2032 ssl_info.is_issued_by_known_root = true; | |
| 2033 ASSERT_NO_FATAL_FAILURE( | |
| 2034 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response, | |
| 2035 test.response_status_string, std::string())); | |
| 2036 | |
| 2037 ssl_info.is_issued_by_known_root = false; | |
| 2038 ASSERT_NO_FATAL_FAILURE( | |
| 2039 CheckExpectStaple(&state, &reporter, ssl_info, ocsp_response, | |
| 2040 test.response_status_string, std::string())); | |
|
Ryan Sleevi
2016/07/19 19:11:05
These tests (2081 - 2089) could benefit from impro
dadrian
2016/07/19 21:21:46
Done.
| |
| 2041 } | |
| 2042 | |
| 2043 INSTANTIATE_TEST_CASE_P(ExpectStaple, | |
| 2044 ExpectStapleErrorResponseTest, | |
| 2045 testing::ValuesIn(kExpectStapleReportData)); | |
| 2046 | |
| 2047 static const struct ExpectStapleErrorCertStatusData { | |
| 2048 OCSPRevocationStatus revocation_status; | |
| 2049 std::string cert_status_string; | |
| 2050 } kExpectStapleErrorCertStatusData[] = { | |
| 2051 {OCSPRevocationStatus::REVOKED, "REVOKED"}, | |
| 2052 {OCSPRevocationStatus::UNKNOWN, "UNKNOWN"}, | |
| 2053 }; | |
| 2054 | |
| 2055 class ExpectStapleErrorCertStatusTest | |
| 2056 : public TransportSecurityStateTest, | |
| 2057 public testing::WithParamInterface<ExpectStapleErrorCertStatusData> {}; | |
| 2058 | |
| 2059 TEST_P(ExpectStapleErrorCertStatusTest, CheckCertStatusSerialization) { | |
|
Ryan Sleevi
2016/07/19 19:11:04
Improve high-level docs for the test
dadrian
2016/07/19 21:21:46
Done.
| |
| 2060 TransportSecurityState state; | |
| 2061 TransportSecurityStateTest::EnableStaticExpectStaple(&state); | |
| 2062 MockCertificateReportSender reporter; | |
| 2063 ExpectStapleErrorCertStatusData test = GetParam(); | |
| 2064 std::string ocsp_response = "dummy_response"; | |
| 2065 | |
| 2066 // Two dummy certs to use as the server-sent and validated chains. The | |
| 2067 // contents don't matter. | |
| 2068 scoped_refptr<X509Certificate> cert1 = | |
| 2069 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); | |
| 2070 scoped_refptr<X509Certificate> cert2 = | |
| 2071 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); | |
| 2072 | |
| 2073 SSLInfo ssl_info; | |
| 2074 ssl_info.cert = cert1; | |
| 2075 ssl_info.unverified_cert = cert2; | |
| 2076 // |response_status| must be set to PROVIDED for |revocation_status| to have | |
| 2077 // meaning. | |
| 2078 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED; | |
| 2079 ssl_info.ocsp_result.revocation_status = test.revocation_status; | |
| 2080 | |
| 2081 ssl_info.is_issued_by_known_root = true; | |
| 2082 ASSERT_NO_FATAL_FAILURE(CheckExpectStaple(&state, &reporter, ssl_info, | |
| 2083 ocsp_response, "PROVIDED", | |
| 2084 test.cert_status_string)); | |
| 2085 | |
| 2086 ssl_info.is_issued_by_known_root = false; | |
| 2087 ASSERT_NO_FATAL_FAILURE(CheckExpectStaple(&state, &reporter, ssl_info, | |
| 2088 ocsp_response, "PROVIDED", | |
| 2089 test.cert_status_string)); | |
| 2090 }; | |
| 2091 | |
| 2092 INSTANTIATE_TEST_CASE_P(ExpectStaple, | |
| 2093 ExpectStapleErrorCertStatusTest, | |
| 2094 testing::ValuesIn(kExpectStapleErrorCertStatusData)); | |
| 2095 | |
| 2096 TEST_F(TransportSecurityStateTest, ExpectStapleDoesNotReportValidStaple) { | |
| 2097 TransportSecurityState state; | |
| 2098 TransportSecurityStateTest::EnableStaticExpectStaple(&state); | |
| 2099 MockCertificateReportSender reporter; | |
| 2100 state.SetReportSender(&reporter); | |
| 2101 | |
| 2102 HostPortPair host_port(kExpectStapleStaticHostname, 443); | |
| 2103 | |
| 2104 // Two dummy certs to use as the server-sent and validated chains. The | |
| 2105 // contents don't matter. | |
| 2106 scoped_refptr<X509Certificate> cert1 = | |
| 2107 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); | |
| 2108 scoped_refptr<X509Certificate> cert2 = | |
| 2109 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); | |
| 2110 | |
| 2111 SSLInfo ssl_info; | |
| 2112 ssl_info.is_issued_by_known_root = true; | |
| 2113 ssl_info.cert = cert1; | |
| 2114 ssl_info.unverified_cert = cert2; | |
| 2115 ssl_info.ocsp_result.response_status = OCSPVerifyResult::PROVIDED; | |
| 2116 ssl_info.ocsp_result.revocation_status = OCSPRevocationStatus::GOOD; | |
| 2117 | |
| 2118 std::string ocsp_response = "dummy response"; | |
| 2119 | |
| 2120 state.ProcessExpectStaple(host_port, ssl_info, ocsp_response); | |
| 2121 EXPECT_EQ(GURL(), reporter.latest_report_uri()); | |
| 2122 EXPECT_TRUE(reporter.latest_report().empty()); | |
| 2123 } | |
| 2124 | |
| 2125 TEST_F(TransportSecurityStateTest, ExpectStapleRequiresPreload) { | |
| 2126 TransportSecurityState state; | |
| 2127 TransportSecurityStateTest::EnableStaticExpectStaple(&state); | |
| 2128 MockCertificateReportSender reporter; | |
| 2129 state.SetReportSender(&reporter); | |
| 2130 | |
| 2131 HostPortPair host_port("not-preloaded.badssl.com", 443); | |
|
Ryan Sleevi
2016/07/19 19:11:05
Similar to my remarks above (about it being preloa
dadrian
2016/07/19 21:21:46
Done.
| |
| 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.is_issued_by_known_root = true; | |
|
Ryan Sleevi
2016/07/19 19:11:05
By contrast with your other tests (and part of why
dadrian
2016/07/19 21:21:46
Done.
| |
| 2142 ssl_info.cert = cert1; | |
| 2143 ssl_info.unverified_cert = cert2; | |
| 2144 ssl_info.ocsp_result.response_status = OCSPVerifyResult::MISSING; | |
| 2145 | |
| 2146 // Empty response | |
| 2147 std::string ocsp_response; | |
| 2148 | |
| 2149 state.ProcessExpectStaple(host_port, ssl_info, ocsp_response); | |
| 2150 EXPECT_EQ(GURL(), reporter.latest_report_uri()); | |
| 2151 EXPECT_TRUE(reporter.latest_report().empty()); | |
| 2152 } | |
| 2153 | |
| 1905 // Tests that TransportSecurityState always consults the RequireCTDelegate, | 2154 // Tests that TransportSecurityState always consults the RequireCTDelegate, |
| 1906 // if supplied. | 2155 // if supplied. |
| 1907 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) { | 2156 TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) { |
| 1908 using ::testing::_; | 2157 using ::testing::_; |
| 1909 using ::testing::Return; | 2158 using ::testing::Return; |
| 1910 using CTRequirementLevel = | 2159 using CTRequirementLevel = |
| 1911 TransportSecurityState::RequireCTDelegate::CTRequirementLevel; | 2160 TransportSecurityState::RequireCTDelegate::CTRequirementLevel; |
| 1912 | 2161 |
| 1913 // Dummy cert to use as the validate chain. The contents do not matter. | 2162 // Dummy cert to use as the validate chain. The contents do not matter. |
| 1914 scoped_refptr<X509Certificate> cert = | 2163 scoped_refptr<X509Certificate> cert = |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2029 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots", | 2278 base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots", |
| 2030 "disabled"); | 2279 "disabled"); |
| 2031 | 2280 |
| 2032 EXPECT_FALSE( | 2281 EXPECT_FALSE( |
| 2033 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); | 2282 state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); |
| 2034 EXPECT_FALSE( | 2283 EXPECT_FALSE( |
| 2035 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); | 2284 state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); |
| 2036 } | 2285 } |
| 2037 | 2286 |
| 2038 } // namespace net | 2287 } // namespace net |
| OLD | NEW |