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 |
11 #include "base/base64.h" | 11 #include "base/base64.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
14 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
15 #include "base/sha1.h" | 15 #include "base/sha1.h" |
16 #include "base/strings/string_piece.h" | 16 #include "base/strings/string_piece.h" |
17 #include "base/values.h" | 17 #include "base/values.h" |
18 #include "crypto/sha2.h" | 18 #include "crypto/sha2.h" |
19 #include "net/base/host_port_pair.h" | 19 #include "net/base/host_port_pair.h" |
20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
21 #include "net/base/test_completion_callback.h" | 21 #include "net/base/test_completion_callback.h" |
22 #include "net/base/test_data_directory.h" | 22 #include "net/base/test_data_directory.h" |
23 #include "net/cert/asn1_util.h" | 23 #include "net/cert/asn1_util.h" |
24 #include "net/cert/cert_verifier.h" | 24 #include "net/cert/cert_verifier.h" |
25 #include "net/cert/cert_verify_result.h" | 25 #include "net/cert/cert_verify_result.h" |
| 26 #include "net/cert/ct_policy_status.h" |
26 #include "net/cert/test_root_certs.h" | 27 #include "net/cert/test_root_certs.h" |
27 #include "net/cert/x509_cert_types.h" | 28 #include "net/cert/x509_cert_types.h" |
28 #include "net/cert/x509_certificate.h" | 29 #include "net/cert/x509_certificate.h" |
29 #include "net/http/http_util.h" | 30 #include "net/http/http_util.h" |
30 #include "net/log/net_log.h" | 31 #include "net/log/net_log.h" |
31 #include "net/ssl/ssl_info.h" | 32 #include "net/ssl/ssl_info.h" |
32 #include "net/test/cert_test_util.h" | 33 #include "net/test/cert_test_util.h" |
33 #include "testing/gtest/include/gtest/gtest.h" | 34 #include "testing/gtest/include/gtest/gtest.h" |
34 | 35 |
35 #if defined(USE_OPENSSL) | 36 #if defined(USE_OPENSSL) |
36 #include "crypto/openssl_util.h" | 37 #include "crypto/openssl_util.h" |
37 #else | 38 #else |
38 #include "crypto/nss_util.h" | 39 #include "crypto/nss_util.h" |
39 #endif | 40 #endif |
40 | 41 |
41 namespace net { | 42 namespace net { |
42 | 43 |
43 namespace { | 44 namespace { |
44 | 45 |
45 const char kHost[] = "example.test"; | 46 const char kHost[] = "example.test"; |
46 const char kSubdomain[] = "foo.example.test"; | 47 const char kSubdomain[] = "foo.example.test"; |
47 const uint16_t kPort = 443; | 48 const uint16_t kPort = 443; |
48 const char kReportUri[] = "http://report-example.test/test"; | 49 const char kReportUri[] = "http://report-example.test/test"; |
| 50 const char kExpectCTStaticHostname[] = "preloaded-expect-ct.badssl.com"; |
| 51 const char kExpectCTStaticReportURI[] = "https://report.badssl.com/expect-ct"; |
49 | 52 |
50 // kGoodPath is blog.torproject.org. | 53 // kGoodPath is blog.torproject.org. |
51 const char* const kGoodPath[] = { | 54 const char* const kGoodPath[] = { |
52 "sha1/Yz4vayd/83rQfDXkDPn2yhzIScw=", | 55 "sha1/Yz4vayd/83rQfDXkDPn2yhzIScw=", |
53 "sha1/3lKvjNsfmrn+WmfDhvr2iVh/yRs=", | 56 "sha1/3lKvjNsfmrn+WmfDhvr2iVh/yRs=", |
54 "sha1/gzF+YoVCU9bXeDGQ7JGQVumRueM=", | 57 "sha1/gzF+YoVCU9bXeDGQ7JGQVumRueM=", |
55 "sha256/4osU79hfY3P2+WJGlT2mxmSL+5FIwLEVxTQcavyBNgQ=", | 58 "sha256/4osU79hfY3P2+WJGlT2mxmSL+5FIwLEVxTQcavyBNgQ=", |
56 "sha256/k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws=", | 59 "sha256/k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws=", |
57 "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=", | 60 "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=", |
58 nullptr, | 61 nullptr, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 } | 96 } |
94 | 97 |
95 const GURL& latest_report_uri() { return latest_report_uri_; } | 98 const GURL& latest_report_uri() { return latest_report_uri_; } |
96 const std::string& latest_report() { return latest_report_; } | 99 const std::string& latest_report() { return latest_report_; } |
97 | 100 |
98 private: | 101 private: |
99 GURL latest_report_uri_; | 102 GURL latest_report_uri_; |
100 std::string latest_report_; | 103 std::string latest_report_; |
101 }; | 104 }; |
102 | 105 |
| 106 // A mock ExpectCTReporter that remembers the latest violation that was |
| 107 // reported and the number of violations reported. |
| 108 class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { |
| 109 public: |
| 110 MockExpectCTReporter() : num_failures_(0) {} |
| 111 ~MockExpectCTReporter() override {} |
| 112 |
| 113 void OnExpectCTFailed(const HostPortPair& host_port_pair, |
| 114 const GURL& report_uri, |
| 115 const net::SSLInfo& ssl_info) override { |
| 116 num_failures_++; |
| 117 host_port_pair_ = host_port_pair; |
| 118 report_uri_ = report_uri; |
| 119 ssl_info_ = ssl_info; |
| 120 } |
| 121 |
| 122 const HostPortPair& host_port_pair() { return host_port_pair_; } |
| 123 const GURL& report_uri() { return report_uri_; } |
| 124 const SSLInfo& ssl_info() { return ssl_info_; } |
| 125 uint32_t num_failures() { return num_failures_; } |
| 126 |
| 127 private: |
| 128 HostPortPair host_port_pair_; |
| 129 GURL report_uri_; |
| 130 SSLInfo ssl_info_; |
| 131 uint32_t num_failures_; |
| 132 }; |
| 133 |
103 void CompareCertificateChainWithList( | 134 void CompareCertificateChainWithList( |
104 const scoped_refptr<X509Certificate>& cert_chain, | 135 const scoped_refptr<X509Certificate>& cert_chain, |
105 const base::ListValue* cert_list) { | 136 const base::ListValue* cert_list) { |
106 ASSERT_TRUE(cert_chain); | 137 ASSERT_TRUE(cert_chain); |
107 std::vector<std::string> pem_encoded_chain; | 138 std::vector<std::string> pem_encoded_chain; |
108 cert_chain->GetPEMEncodedChain(&pem_encoded_chain); | 139 cert_chain->GetPEMEncodedChain(&pem_encoded_chain); |
109 EXPECT_EQ(pem_encoded_chain.size(), cert_list->GetSize()); | 140 EXPECT_EQ(pem_encoded_chain.size(), cert_list->GetSize()); |
110 | 141 |
111 for (size_t i = 0; i < pem_encoded_chain.size(); i++) { | 142 for (size_t i = 0; i < pem_encoded_chain.size(); i++) { |
112 std::string list_cert; | 143 std::string list_cert; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 return spki_hashes; | 234 return spki_hashes; |
204 } | 235 } |
205 | 236 |
206 protected: | 237 protected: |
207 bool GetStaticDomainState(TransportSecurityState* state, | 238 bool GetStaticDomainState(TransportSecurityState* state, |
208 const std::string& host, | 239 const std::string& host, |
209 TransportSecurityState::STSState* sts_result, | 240 TransportSecurityState::STSState* sts_result, |
210 TransportSecurityState::PKPState* pkp_result) { | 241 TransportSecurityState::PKPState* pkp_result) { |
211 return state->GetStaticDomainState(host, sts_result, pkp_result); | 242 return state->GetStaticDomainState(host, sts_result, pkp_result); |
212 } | 243 } |
| 244 |
| 245 bool GetExpectCTState(TransportSecurityState* state, |
| 246 const std::string& host, |
| 247 TransportSecurityState::ExpectCTState* result) { |
| 248 return state->GetStaticExpectCTState(host, result); |
| 249 } |
213 }; | 250 }; |
214 | 251 |
215 TEST_F(TransportSecurityStateTest, DomainNameOddities) { | 252 TEST_F(TransportSecurityStateTest, DomainNameOddities) { |
216 TransportSecurityState state; | 253 TransportSecurityState state; |
217 const base::Time current_time(base::Time::Now()); | 254 const base::Time current_time(base::Time::Now()); |
218 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); | 255 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); |
219 | 256 |
220 // DNS suffix search tests. Some DNS resolvers allow a terminal "." to | 257 // DNS suffix search tests. Some DNS resolvers allow a terminal "." to |
221 // indicate not perform DNS suffix searching. Ensure that regardless | 258 // indicate not perform DNS suffix searching. Ensure that regardless |
222 // of how this is treated at the resolver layer, or at the URL/origin | 259 // of how this is treated at the resolver layer, or at the URL/origin |
(...skipping 1323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 report = mock_report_sender.latest_report(); | 1583 report = mock_report_sender.latest_report(); |
1547 ASSERT_FALSE(report.empty()); | 1584 ASSERT_FALSE(report.empty()); |
1548 ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost, | 1585 ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost, |
1549 cert1.get(), cert2.get(), | 1586 cert1.get(), cert2.get(), |
1550 good_hashes)); | 1587 good_hashes)); |
1551 mock_report_sender.Clear(); | 1588 mock_report_sender.Clear(); |
1552 } | 1589 } |
1553 | 1590 |
1554 // Tests that static (preloaded) expect CT state is read correctly. | 1591 // Tests that static (preloaded) expect CT state is read correctly. |
1555 TEST_F(TransportSecurityStateTest, PreloadedExpectCT) { | 1592 TEST_F(TransportSecurityStateTest, PreloadedExpectCT) { |
1556 const char kHostname[] = "preloaded-expect-ct.badssl.com"; | |
1557 TransportSecurityState state; | 1593 TransportSecurityState state; |
1558 TransportSecurityStateTest::EnableStaticExpectCT(&state); | 1594 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
1559 TransportSecurityState::ExpectCTState expect_ct_state; | 1595 TransportSecurityState::ExpectCTState expect_ct_state; |
1560 EXPECT_TRUE(state.GetStaticExpectCTState(kHostname, &expect_ct_state)); | 1596 EXPECT_TRUE( |
1561 EXPECT_EQ(kHostname, expect_ct_state.domain); | 1597 GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state)); |
1562 EXPECT_EQ(GURL("https://report.badssl.com/expect-ct"), | 1598 EXPECT_EQ(kExpectCTStaticHostname, expect_ct_state.domain); |
1563 expect_ct_state.report_uri); | 1599 EXPECT_EQ(GURL(kExpectCTStaticReportURI), expect_ct_state.report_uri); |
1564 EXPECT_FALSE(state.GetStaticExpectCTState("pinning-test.badssl.com", | 1600 EXPECT_FALSE( |
1565 &expect_ct_state)); | 1601 GetExpectCTState(&state, "pinning-test.badssl.com", &expect_ct_state)); |
| 1602 } |
| 1603 |
| 1604 // Tests that the Expect CT reporter is not notified for invalid or absent |
| 1605 // header values. |
| 1606 TEST_F(TransportSecurityStateTest, InvalidExpectCTHeader) { |
| 1607 HostPortPair host_port(kExpectCTStaticHostname, 443); |
| 1608 SSLInfo ssl_info; |
| 1609 ssl_info.ct_compliance_details_available = true; |
| 1610 ssl_info.ct_cert_policy_compliance = |
| 1611 ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
| 1612 ssl_info.is_issued_by_known_root = true; |
| 1613 |
| 1614 TransportSecurityState state; |
| 1615 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1616 MockExpectCTReporter reporter; |
| 1617 state.SetExpectCTReporter(&reporter); |
| 1618 state.ProcessExpectCTHeader("", host_port, ssl_info); |
| 1619 EXPECT_EQ(0u, reporter.num_failures()); |
| 1620 |
| 1621 state.ProcessExpectCTHeader("blah blah", host_port, ssl_info); |
| 1622 EXPECT_EQ(0u, reporter.num_failures()); |
| 1623 |
| 1624 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1625 EXPECT_EQ(1u, reporter.num_failures()); |
| 1626 } |
| 1627 |
| 1628 // Tests that the Expect CT reporter is only notified about certificates |
| 1629 // chaining to public roots. |
| 1630 TEST_F(TransportSecurityStateTest, ExpectCTNonPublicRoot) { |
| 1631 HostPortPair host_port(kExpectCTStaticHostname, 443); |
| 1632 SSLInfo ssl_info; |
| 1633 ssl_info.ct_compliance_details_available = true; |
| 1634 ssl_info.ct_cert_policy_compliance = |
| 1635 ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
| 1636 ssl_info.is_issued_by_known_root = false; |
| 1637 |
| 1638 TransportSecurityState state; |
| 1639 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1640 MockExpectCTReporter reporter; |
| 1641 state.SetExpectCTReporter(&reporter); |
| 1642 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1643 EXPECT_EQ(0u, reporter.num_failures()); |
| 1644 |
| 1645 ssl_info.is_issued_by_known_root = true; |
| 1646 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1647 EXPECT_EQ(1u, reporter.num_failures()); |
| 1648 } |
| 1649 |
| 1650 // Tests that the Expect CT reporter is not notified when compliance |
| 1651 // details aren't available. |
| 1652 TEST_F(TransportSecurityStateTest, ExpectCTComplianceNotAvailable) { |
| 1653 HostPortPair host_port(kExpectCTStaticHostname, 443); |
| 1654 SSLInfo ssl_info; |
| 1655 ssl_info.ct_compliance_details_available = false; |
| 1656 ssl_info.ct_cert_policy_compliance = |
| 1657 ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
| 1658 ssl_info.is_issued_by_known_root = true; |
| 1659 |
| 1660 TransportSecurityState state; |
| 1661 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1662 MockExpectCTReporter reporter; |
| 1663 state.SetExpectCTReporter(&reporter); |
| 1664 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1665 EXPECT_EQ(0u, reporter.num_failures()); |
| 1666 |
| 1667 ssl_info.ct_compliance_details_available = true; |
| 1668 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1669 EXPECT_EQ(1u, reporter.num_failures()); |
| 1670 } |
| 1671 |
| 1672 // Tests that the Expect CT reporter is not notified about compliant |
| 1673 // connections. |
| 1674 TEST_F(TransportSecurityStateTest, ExpectCTCompliantCert) { |
| 1675 HostPortPair host_port(kExpectCTStaticHostname, 443); |
| 1676 SSLInfo ssl_info; |
| 1677 ssl_info.ct_compliance_details_available = true; |
| 1678 ssl_info.ct_cert_policy_compliance = |
| 1679 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS; |
| 1680 ssl_info.is_issued_by_known_root = true; |
| 1681 |
| 1682 TransportSecurityState state; |
| 1683 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1684 MockExpectCTReporter reporter; |
| 1685 state.SetExpectCTReporter(&reporter); |
| 1686 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1687 EXPECT_EQ(0u, reporter.num_failures()); |
| 1688 |
| 1689 ssl_info.ct_cert_policy_compliance = |
| 1690 ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
| 1691 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1692 EXPECT_EQ(1u, reporter.num_failures()); |
| 1693 } |
| 1694 |
| 1695 // Tests that the Expect CT reporter is not notified for a site that |
| 1696 // isn't preloaded. |
| 1697 TEST_F(TransportSecurityStateTest, ExpectCTNotPreloaded) { |
| 1698 HostPortPair host_port("not-expect-ct-preloaded.test", 443); |
| 1699 SSLInfo ssl_info; |
| 1700 ssl_info.ct_compliance_details_available = true; |
| 1701 ssl_info.ct_cert_policy_compliance = |
| 1702 ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
| 1703 ssl_info.is_issued_by_known_root = true; |
| 1704 |
| 1705 TransportSecurityState state; |
| 1706 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1707 MockExpectCTReporter reporter; |
| 1708 state.SetExpectCTReporter(&reporter); |
| 1709 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1710 EXPECT_EQ(0u, reporter.num_failures()); |
| 1711 |
| 1712 host_port.set_host(kExpectCTStaticHostname); |
| 1713 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1714 EXPECT_EQ(1u, reporter.num_failures()); |
| 1715 } |
| 1716 |
| 1717 // Tests that the Expect CT reporter is notified for noncompliant |
| 1718 // connections. |
| 1719 TEST_F(TransportSecurityStateTest, ExpectCTReporter) { |
| 1720 HostPortPair host_port(kExpectCTStaticHostname, 443); |
| 1721 SSLInfo ssl_info; |
| 1722 ssl_info.ct_compliance_details_available = true; |
| 1723 ssl_info.ct_cert_policy_compliance = |
| 1724 ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
| 1725 ssl_info.is_issued_by_known_root = true; |
| 1726 |
| 1727 TransportSecurityState state; |
| 1728 TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| 1729 MockExpectCTReporter reporter; |
| 1730 state.SetExpectCTReporter(&reporter); |
| 1731 state.ProcessExpectCTHeader("preload", host_port, ssl_info); |
| 1732 EXPECT_EQ(1u, reporter.num_failures()); |
| 1733 EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available); |
| 1734 EXPECT_EQ(ssl_info.ct_cert_policy_compliance, |
| 1735 reporter.ssl_info().ct_cert_policy_compliance); |
| 1736 EXPECT_EQ(host_port.host(), reporter.host_port_pair().host()); |
| 1737 EXPECT_EQ(host_port.port(), reporter.host_port_pair().port()); |
| 1738 EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri()); |
1566 } | 1739 } |
1567 | 1740 |
1568 } // namespace net | 1741 } // namespace net |
OLD | NEW |