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

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

Issue 1213783005: Send HPKP violation reports when a pin check fails (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
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/rand_util.h" 14 #include "base/rand_util.h"
14 #include "base/sha1.h" 15 #include "base/sha1.h"
15 #include "base/strings/string_piece.h" 16 #include "base/strings/string_piece.h"
17 #include "base/values.h"
16 #include "crypto/sha2.h" 18 #include "crypto/sha2.h"
17 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h" 20 #include "net/base/test_completion_callback.h"
19 #include "net/base/test_data_directory.h" 21 #include "net/base/test_data_directory.h"
20 #include "net/cert/asn1_util.h" 22 #include "net/cert/asn1_util.h"
21 #include "net/cert/cert_verifier.h" 23 #include "net/cert/cert_verifier.h"
22 #include "net/cert/cert_verify_result.h" 24 #include "net/cert/cert_verify_result.h"
23 #include "net/cert/test_root_certs.h" 25 #include "net/cert/test_root_certs.h"
24 #include "net/cert/x509_cert_types.h" 26 #include "net/cert/x509_cert_types.h"
25 #include "net/cert/x509_certificate.h" 27 #include "net/cert/x509_certificate.h"
28 #include "net/http/certificate_report_sender.h"
26 #include "net/http/http_util.h" 29 #include "net/http/http_util.h"
30 #include "net/http/transport_security_reporter.h"
27 #include "net/log/net_log.h" 31 #include "net/log/net_log.h"
28 #include "net/ssl/ssl_info.h" 32 #include "net/ssl/ssl_info.h"
29 #include "net/test/cert_test_util.h" 33 #include "net/test/cert_test_util.h"
30 #include "testing/gtest/include/gtest/gtest.h" 34 #include "testing/gtest/include/gtest/gtest.h"
31 35
32 #if defined(USE_OPENSSL) 36 #if defined(USE_OPENSSL)
33 #include "crypto/openssl_util.h" 37 #include "crypto/openssl_util.h"
34 #else 38 #else
35 #include "crypto/nss_util.h" 39 #include "crypto/nss_util.h"
36 #endif 40 #endif
37 41
42 namespace {
43
44 // A mock CertificateReportSender that just remembers the latest report
45 // URI and report to be sent.
46 class MockCertificateReportSender : public net::CertificateReportSender {
47 public:
48 MockCertificateReportSender() {}
49 ~MockCertificateReportSender() override {}
50
51 void Send(const GURL& report_uri, const std::string& report) override {
52 latest_report_uri_ = report_uri;
53 latest_report_ = report;
54 }
55
56 const GURL& latest_report_uri() { return latest_report_uri_; }
57 const std::string& latest_report() { return latest_report_; }
58
59 private:
60 GURL latest_report_uri_;
61 std::string latest_report_;
62 };
63
64 void CompareCertificateChainWithList(
65 const scoped_refptr<net::X509Certificate>& cert_chain,
66 const base::ListValue* cert_list) {
67 ASSERT_TRUE(cert_chain);
68 std::vector<std::string> pem_encoded_chain;
69 cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
70 EXPECT_EQ(pem_encoded_chain.size(), cert_list->GetSize());
71
72 for (size_t i = 0; i < pem_encoded_chain.size(); i++) {
73 std::string list_cert;
74 ASSERT_TRUE(cert_list->GetString(i, &list_cert));
75 EXPECT_EQ(pem_encoded_chain[i], list_cert);
76 }
77 }
78
79 void CheckHPKPReport(
80 const std::string& report,
81 const std::string& hostname,
82 uint16_t port,
83 const base::Time& expiry,
84 bool include_subdomains,
85 const std::string& noted_hostname,
86 const scoped_refptr<net::X509Certificate>& served_certificate_chain,
87 const scoped_refptr<net::X509Certificate>& validated_certificate_chain,
88 const net::HashValueVector& known_pins) {
89 // TODO(estark): check time in RFC3339 format.
90
91 scoped_ptr<base::Value> value(base::JSONReader::Read(report));
92 ASSERT_TRUE(value);
93 ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
94
95 scoped_ptr<base::DictionaryValue> report_dict(
96 static_cast<base::DictionaryValue*>(value.release()));
97
98 std::string report_hostname;
99 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
100 EXPECT_EQ(hostname, report_hostname);
101
102 int report_port;
103 EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
104 EXPECT_EQ(port, report_port);
105
106 bool report_include_subdomains;
107 EXPECT_TRUE(report_dict->GetBoolean("include-subdomains",
108 &report_include_subdomains));
109 EXPECT_EQ(include_subdomains, report_include_subdomains);
110
111 std::string report_noted_hostname;
112 EXPECT_TRUE(report_dict->GetString("hostname", &report_noted_hostname));
113 EXPECT_EQ(hostname, report_noted_hostname);
114
115 base::ListValue* report_served_certificate_chain;
116 EXPECT_TRUE(report_dict->GetList("served-certificate-chain",
117 &report_served_certificate_chain));
118 CompareCertificateChainWithList(served_certificate_chain,
Ryan Sleevi 2015/06/26 20:22:19 BUG: You ASSERT_TRUE() in CompareCertificateChainW
estark 2015/07/09 22:18:41 Done.
119 report_served_certificate_chain);
120
121 base::ListValue* report_validated_certificate_chain;
122 EXPECT_TRUE(report_dict->GetList("validated-certificate-chain",
123 &report_validated_certificate_chain));
124 CompareCertificateChainWithList(validated_certificate_chain,
125 report_validated_certificate_chain);
126 }
127
128 } // namespace
129
38 namespace net { 130 namespace net {
39 131
40 class TransportSecurityStateTest : public testing::Test { 132 class TransportSecurityStateTest : public testing::Test {
41 public: 133 public:
42 void SetUp() override { 134 void SetUp() override {
43 #if defined(USE_OPENSSL) 135 #if defined(USE_OPENSSL)
44 crypto::EnsureOpenSSLInit(); 136 crypto::EnsureOpenSSLInit();
45 #else 137 #else
46 crypto::EnsureNSSInit(); 138 crypto::EnsureNSSInit();
47 #endif 139 #endif
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 1164
1073 // These hosts used to only be HSTS when SNI was available. 1165 // These hosts used to only be HSTS when SNI was available.
1074 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 1166 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
1075 "gmail.com")); 1167 "gmail.com"));
1076 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 1168 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
1077 "googlegroups.com")); 1169 "googlegroups.com"));
1078 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty( 1170 EXPECT_TRUE(TransportSecurityState::IsGooglePinnedProperty(
1079 "www.googlegroups.com")); 1171 "www.googlegroups.com"));
1080 } 1172 }
1081 1173
1174 TEST_F(TransportSecurityStateTest, HPKPReporting) {
1175 const char kHost[] = "example.com";
1176 const char kSubdomain[] = "foo.example.com";
1177 const uint16_t kPort = 443;
1178 GURL report_uri("http://www.example.com/report");
1179 // Two dummy certs to use as the server-sent and validated chains. The
1180 // contents don't matter.
1181 scoped_refptr<X509Certificate> cert1 =
1182 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
1183 scoped_refptr<X509Certificate> cert2 =
1184 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
1185 ASSERT_TRUE(cert1);
1186 ASSERT_TRUE(cert2);
1187
1188 // kGoodPath is blog.torproject.org.
1189 static const char* const kGoodPath[] = {
1190 "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=",
1191 "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=",
1192 "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=",
1193 NULL,
1194 };
1195
1196 // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for
1197 // torproject.org.
1198 static const char* const kBadPath[] = {
1199 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
1200 "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=",
1201 "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
1202 NULL,
1203 };
1204
1205 HashValueVector good_hashes, bad_hashes;
1206
1207 for (size_t i = 0; kGoodPath[i]; i++) {
1208 EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes));
1209 }
Ryan Sleevi 2015/06/26 20:22:19 no braces
estark 2015/07/09 22:18:41 Done.
1210 for (size_t i = 0; kBadPath[i]; i++) {
1211 EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
1212 }
1213
1214 TransportSecurityState state;
1215 MockCertificateReportSender* mock_report_sender =
1216 new MockCertificateReportSender();
1217 TransportSecurityReporter reporter(
1218 &state, scoped_ptr<CertificateReportSender>(mock_report_sender));
1219
1220 const base::Time current_time(base::Time::Now());
1221 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
1222 state.AddHPKP(kHost, expiry, true, good_hashes, report_uri.spec());
1223
1224 EXPECT_EQ(GURL(), mock_report_sender->latest_report_uri());
1225 EXPECT_EQ(std::string(), mock_report_sender->latest_report());
1226
1227 std::string failure_log;
1228 EXPECT_FALSE(state.CheckPublicKeyPins(
1229 kHost, true, bad_hashes, kPort, cert1, cert2,
1230 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
1231
1232 // No report should have been sent because of the DO_NOT_SEND_REPORT
1233 // argument.
1234 EXPECT_EQ(GURL(), mock_report_sender->latest_report_uri());
1235 EXPECT_EQ(std::string(), mock_report_sender->latest_report());
1236
1237 EXPECT_TRUE(state.CheckPublicKeyPins(
1238 kHost, true, good_hashes, kPort, cert1, cert2,
1239 TransportSecurityState::SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
1240
1241 // No report should have been sent because there was no violation.
1242 EXPECT_EQ(GURL(), mock_report_sender->latest_report_uri());
1243 EXPECT_EQ(std::string(), mock_report_sender->latest_report());
1244
1245 EXPECT_FALSE(state.CheckPublicKeyPins(
1246 kHost, true, bad_hashes, kPort, cert1, cert2,
1247 TransportSecurityState::SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
1248
1249 // Now a report should have been sent. Check that it contains the
1250 // right information.
1251 EXPECT_EQ(report_uri, mock_report_sender->latest_report_uri());
1252 std::string report = mock_report_sender->latest_report();
1253 ASSERT_FALSE(report.empty());
1254 CheckHPKPReport(report, kHost, kPort, expiry, true, kHost, cert1, cert2,
Ryan Sleevi 2015/06/26 20:22:20 You don't propogate failures here either - re: ASS
estark 2015/07/09 22:18:41 Done.
1255 good_hashes);
1256
1257 EXPECT_FALSE(state.CheckPublicKeyPins(
1258 kSubdomain, true, bad_hashes, kPort, cert1, cert2,
1259 TransportSecurityState::SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
1260
1261 // Now a report should have been sent for the subdomain. Check that it
1262 // contains the
1263 // right information.
1264 EXPECT_EQ(report_uri, mock_report_sender->latest_report_uri());
1265 report = mock_report_sender->latest_report();
1266 ASSERT_FALSE(report.empty());
1267 CheckHPKPReport(report, kSubdomain, kPort, expiry, true, kHost, cert1, cert2,
1268 good_hashes);
1269 }
1270
1082 } // namespace net 1271 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698