1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/network/expect_ct_reporter.h"
6 
7 #include <string>
8 
9 #include "base/base64.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/json/json_reader.h"
14 #include "base/run_loop.h"
15 #include "base/test/metrics/histogram_tester.h"
16 #include "base/test/scoped_feature_list.h"
17 #include "base/test/task_environment.h"
18 #include "base/values.h"
19 #include "net/cert/ct_serialization.h"
20 #include "net/cert/signed_certificate_timestamp_and_status.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
23 #include "net/test/embedded_test_server/http_request.h"
24 #include "net/test/embedded_test_server/http_response.h"
25 #include "net/test/test_data_directory.h"
26 #include "net/test/url_request/url_request_failed_job.h"
27 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
28 #include "net/url_request/report_sender.h"
29 #include "net/url_request/url_request_filter.h"
30 #include "net/url_request/url_request_test_util.h"
31 #include "services/network/public/cpp/features.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "url/gurl.h"
34 
35 namespace network {
36 namespace {
37 
38 const char kSendHistogramName[] = "SSL.ExpectCTReportSendingAttempt";
39 const char kFailureHistogramName[] = "SSL.ExpectCTReportFailure2";
40 
41 // A test ReportSender that exposes the latest report URI and
42 // serialized report to be sent.
43 class TestCertificateReportSender : public net::ReportSender {
44  public:
TestCertificateReportSender()45   TestCertificateReportSender()
46       : ReportSender(nullptr, TRAFFIC_ANNOTATION_FOR_TESTS) {}
~TestCertificateReportSender()47   ~TestCertificateReportSender() override {}
48 
Send(const GURL & report_uri,base::StringPiece content_type,base::StringPiece serialized_report,const base::RepeatingCallback<void ()> & success_callback,const base::RepeatingCallback<void (const GURL &,int,int)> & error_callback)49   void Send(const GURL& report_uri,
50             base::StringPiece content_type,
51             base::StringPiece serialized_report,
52             const base::RepeatingCallback<void()>& success_callback,
53             const base::RepeatingCallback<void(const GURL&, int, int)>&
54                 error_callback) override {
55     sent_report_count_++;
56     latest_report_uri_ = report_uri;
57     latest_serialized_report_.assign(serialized_report.data(),
58                                      serialized_report.size());
59     latest_content_type_.assign(content_type.data(), content_type.size());
60     if (!report_callback_.is_null()) {
61       EXPECT_EQ(expected_report_uri_, latest_report_uri_);
62       std::move(report_callback_).Run();
63     }
64   }
65 
sent_report_count() const66   int sent_report_count() const { return sent_report_count_; }
67 
latest_report_uri() const68   const GURL& latest_report_uri() const { return latest_report_uri_; }
69 
latest_content_type() const70   const std::string& latest_content_type() const {
71     return latest_content_type_;
72   }
73 
latest_serialized_report() const74   const std::string& latest_serialized_report() const {
75     return latest_serialized_report_;
76   }
77 
78   // Can be called to wait for a single report, which is expected to be sent to
79   // |report_uri|. Returns immediately if a report has already been sent in the
80   // past.
WaitForReport(const GURL & report_uri)81   void WaitForReport(const GURL& report_uri) {
82     if (!latest_report_uri_.is_empty()) {
83       EXPECT_EQ(report_uri, latest_report_uri_);
84       return;
85     }
86     base::RunLoop run_loop;
87     report_callback_ = run_loop.QuitClosure();
88     expected_report_uri_ = report_uri;
89     run_loop.Run();
90   }
91 
92  private:
93   int sent_report_count_ = 0;
94   GURL latest_report_uri_;
95   std::string latest_content_type_;
96   std::string latest_serialized_report_;
97   base::OnceClosure report_callback_;
98   GURL expected_report_uri_;
99 };
100 
101 // Constructs a net::SignedCertificateTimestampAndStatus with the given
102 // information and appends it to |sct_list|.
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::Origin origin,const std::string & log_id,const std::string & extensions,const std::string & signature_data,const base::Time & timestamp,net::ct::SCTVerifyStatus status,net::SignedCertificateTimestampAndStatusList * sct_list)103 void MakeTestSCTAndStatus(
104     net::ct::SignedCertificateTimestamp::Origin origin,
105     const std::string& log_id,
106     const std::string& extensions,
107     const std::string& signature_data,
108     const base::Time& timestamp,
109     net::ct::SCTVerifyStatus status,
110     net::SignedCertificateTimestampAndStatusList* sct_list) {
111   scoped_refptr<net::ct::SignedCertificateTimestamp> sct(
112       new net::ct::SignedCertificateTimestamp());
113   sct->version = net::ct::SignedCertificateTimestamp::V1;
114   sct->log_id = log_id;
115   sct->extensions = extensions;
116   sct->timestamp = timestamp;
117   sct->signature.signature_data = signature_data;
118   sct->origin = origin;
119   sct_list->push_back(net::SignedCertificateTimestampAndStatus(sct, status));
120 }
121 
122 // Checks that |expected_cert| matches the PEM-encoded certificate chain
123 // in |chain|.
CheckReportCertificateChain(const scoped_refptr<net::X509Certificate> & expected_cert,const base::ListValue & chain)124 void CheckReportCertificateChain(
125     const scoped_refptr<net::X509Certificate>& expected_cert,
126     const base::ListValue& chain) {
127   std::vector<std::string> pem_encoded_chain;
128   expected_cert->GetPEMEncodedChain(&pem_encoded_chain);
129   ASSERT_EQ(pem_encoded_chain.size(), chain.GetSize());
130 
131   for (size_t i = 0; i < pem_encoded_chain.size(); i++) {
132     std::string cert_pem;
133     ASSERT_TRUE(chain.GetString(i, &cert_pem));
134     EXPECT_EQ(pem_encoded_chain[i], cert_pem);
135   }
136 }
137 
138 // Converts the string value of a reported SCT's origin to a
139 // net::ct::SignedCertificateTimestamp::Origin value.
SCTOriginStringToOrigin(const std::string & origin_string)140 net::ct::SignedCertificateTimestamp::Origin SCTOriginStringToOrigin(
141     const std::string& origin_string) {
142   if (origin_string == "embedded")
143     return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED;
144   if (origin_string == "tls-extension")
145     return net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION;
146   if (origin_string == "ocsp")
147     return net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE;
148   NOTREACHED();
149   return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED;
150 }
151 
152 // Checks that an SCT |sct| appears with status |status| in |report_list|, a
153 // list of SCTs from an Expect-CT report.
FindSCTInReportList(const scoped_refptr<net::ct::SignedCertificateTimestamp> & expected_sct,net::ct::SCTVerifyStatus expected_status,const base::ListValue & report_list)154 ::testing::AssertionResult FindSCTInReportList(
155     const scoped_refptr<net::ct::SignedCertificateTimestamp>& expected_sct,
156     net::ct::SCTVerifyStatus expected_status,
157     const base::ListValue& report_list) {
158   std::string expected_serialized_sct;
159   if (!net::ct::EncodeSignedCertificateTimestamp(expected_sct,
160                                                  &expected_serialized_sct)) {
161     return ::testing::AssertionFailure() << "Failed to serialize SCT";
162   }
163 
164   for (size_t i = 0; i < report_list.GetSize(); i++) {
165     const base::DictionaryValue* report_sct;
166     if (!report_list.GetDictionary(i, &report_sct)) {
167       return ::testing::AssertionFailure()
168              << "Failed to get dictionary value from report SCT list";
169     }
170 
171     std::string serialized_sct;
172     EXPECT_TRUE(report_sct->GetString("serialized_sct", &serialized_sct));
173     std::string decoded_serialized_sct;
174     EXPECT_TRUE(base::Base64Decode(serialized_sct, &decoded_serialized_sct));
175     if (decoded_serialized_sct != expected_serialized_sct)
176       continue;
177 
178     std::string source;
179     EXPECT_TRUE(report_sct->GetString("source", &source));
180     EXPECT_EQ(expected_sct->origin, SCTOriginStringToOrigin(source));
181 
182     std::string report_status;
183     EXPECT_TRUE(report_sct->GetString("status", &report_status));
184     switch (expected_status) {
185       case net::ct::SCT_STATUS_LOG_UNKNOWN:
186         EXPECT_EQ("unknown", report_status);
187         break;
188       case net::ct::SCT_STATUS_INVALID_SIGNATURE:
189       case net::ct::SCT_STATUS_INVALID_TIMESTAMP: {
190         EXPECT_EQ("invalid", report_status);
191         break;
192       }
193       case net::ct::SCT_STATUS_OK: {
194         EXPECT_EQ("valid", report_status);
195         break;
196       }
197       case net::ct::SCT_STATUS_NONE:
198         NOTREACHED();
199     }
200     return ::testing::AssertionSuccess();
201   }
202 
203   return ::testing::AssertionFailure() << "Failed to find SCT in report list";
204 }
205 
206 // Checks that all |expected_scts| appears in the given lists of SCTs
207 // from an Expect CT report.
CheckReportSCTs(const net::SignedCertificateTimestampAndStatusList & expected_scts,const base::ListValue & scts)208 void CheckReportSCTs(
209     const net::SignedCertificateTimestampAndStatusList& expected_scts,
210     const base::ListValue& scts) {
211   EXPECT_EQ(expected_scts.size(), scts.GetSize());
212   for (const auto& expected_sct : expected_scts) {
213     ASSERT_TRUE(
214         FindSCTInReportList(expected_sct.sct, expected_sct.status, scts));
215   }
216 }
217 
218 // Checks that the |serialized_report| deserializes properly and
219 // contains the correct information (hostname, port, served and
220 // validated certificate chains, SCTs) for the given |host_port| and
221 // |ssl_info|.
CheckExpectCTReport(const std::string & serialized_report,const net::HostPortPair & host_port,const std::string & expiration,const net::SSLInfo & ssl_info)222 void CheckExpectCTReport(const std::string& serialized_report,
223                          const net::HostPortPair& host_port,
224                          const std::string& expiration,
225                          const net::SSLInfo& ssl_info) {
226   std::unique_ptr<base::Value> value(
227       base::JSONReader::ReadDeprecated(serialized_report));
228   ASSERT_TRUE(value);
229   ASSERT_TRUE(value->is_dict());
230 
231   base::DictionaryValue* outer_report_dict;
232   ASSERT_TRUE(value->GetAsDictionary(&outer_report_dict));
233 
234   base::DictionaryValue* report_dict;
235   ASSERT_TRUE(
236       outer_report_dict->GetDictionary("expect-ct-report", &report_dict));
237 
238   std::string report_hostname;
239   EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
240   EXPECT_EQ(host_port.host(), report_hostname);
241   int report_port;
242   EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
243   EXPECT_EQ(host_port.port(), report_port);
244 
245   std::string report_expiration;
246   EXPECT_TRUE(
247       report_dict->GetString("effective-expiration-date", &report_expiration));
248   EXPECT_EQ(expiration, report_expiration);
249 
250   const base::ListValue* report_served_certificate_chain = nullptr;
251   ASSERT_TRUE(report_dict->GetList("served-certificate-chain",
252                                    &report_served_certificate_chain));
253   ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain(
254       ssl_info.unverified_cert, *report_served_certificate_chain));
255 
256   const base::ListValue* report_validated_certificate_chain = nullptr;
257   ASSERT_TRUE(report_dict->GetList("validated-certificate-chain",
258                                    &report_validated_certificate_chain));
259   ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain(
260       ssl_info.cert, *report_validated_certificate_chain));
261 
262   const base::ListValue* report_scts = nullptr;
263   ASSERT_TRUE(report_dict->GetList("scts", &report_scts));
264 
265   ASSERT_NO_FATAL_FAILURE(
266       CheckReportSCTs(ssl_info.signed_certificate_timestamps, *report_scts));
267 }
268 
269 // A test network delegate that allows the user to specify a callback to
270 // be run whenever a net::URLRequest is destroyed.
271 class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl {
272  public:
TestExpectCTNetworkDelegate()273   TestExpectCTNetworkDelegate()
274       : url_request_destroyed_callback_(base::NullCallback()) {}
275 
set_url_request_destroyed_callback(const base::RepeatingClosure & callback)276   void set_url_request_destroyed_callback(
277       const base::RepeatingClosure& callback) {
278     url_request_destroyed_callback_ = callback;
279   }
280 
281   // net::NetworkDelegateImpl:
OnURLRequestDestroyed(net::URLRequest * request)282   void OnURLRequestDestroyed(net::URLRequest* request) override {
283     url_request_destroyed_callback_.Run();
284   }
285 
286  private:
287   base::RepeatingClosure url_request_destroyed_callback_;
288 
289   DISALLOW_COPY_AND_ASSIGN(TestExpectCTNetworkDelegate);
290 };
291 
292 // A test fixture that allows tests to send a report and wait until the
293 // net::URLRequest that sent the report is destroyed.
294 class ExpectCTReporterWaitTest : public ::testing::Test {
295  public:
ExpectCTReporterWaitTest()296   ExpectCTReporterWaitTest()
297       : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
298 
SetUp()299   void SetUp() override {
300     // Initializes URLRequestContext after the thread is set up.
301     context_.reset(new net::TestURLRequestContext(true));
302     context_->set_network_delegate(&network_delegate_);
303     context_->Init();
304     net::URLRequestFailedJob::AddUrlHandler();
305   }
306 
TearDown()307   void TearDown() override {
308     net::URLRequestFilter::GetInstance()->ClearHandlers();
309   }
310 
context()311   net::TestURLRequestContext* context() { return context_.get(); }
312 
313  protected:
SendReport(ExpectCTReporter * reporter,const net::HostPortPair & host_port,const GURL & report_uri,base::Time expiration,const net::SSLInfo & ssl_info)314   void SendReport(ExpectCTReporter* reporter,
315                   const net::HostPortPair& host_port,
316                   const GURL& report_uri,
317                   base::Time expiration,
318                   const net::SSLInfo& ssl_info) {
319     base::RunLoop run_loop;
320     network_delegate_.set_url_request_destroyed_callback(
321         run_loop.QuitClosure());
322     reporter->OnExpectCTFailed(
323         host_port, report_uri, expiration, ssl_info.cert.get(),
324         ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
325     run_loop.Run();
326   }
327 
328  private:
329   TestExpectCTNetworkDelegate network_delegate_;
330   std::unique_ptr<net::TestURLRequestContext> context_;
331   base::test::TaskEnvironment task_environment_;
332 
333   DISALLOW_COPY_AND_ASSIGN(ExpectCTReporterWaitTest);
334 };
335 
ReplyToPostWith200(const net::test_server::HttpRequest & request)336 std::unique_ptr<net::test_server::HttpResponse> ReplyToPostWith200(
337     const net::test_server::HttpRequest& request) {
338   if (request.method != net::test_server::METHOD_POST)
339     return nullptr;
340 
341   auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
342   http_response->set_code(net::HTTP_OK);
343   return http_response;
344 }
345 
HandleReportPreflight(const std::map<std::string,std::string> & cors_headers,base::RepeatingClosure callback,const net::test_server::HttpRequest & request)346 std::unique_ptr<net::test_server::HttpResponse> HandleReportPreflight(
347     const std::map<std::string, std::string>& cors_headers,
348     base::RepeatingClosure callback,
349     const net::test_server::HttpRequest& request) {
350   if (request.method != net::test_server::METHOD_OPTIONS)
351     return nullptr;
352 
353   auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
354   http_response->set_code(net::HTTP_OK);
355   for (const auto& cors_header : cors_headers) {
356     http_response->AddCustomHeader(cors_header.first, cors_header.second);
357   }
358 
359   if (!callback.is_null()) {
360     callback.Run();
361   }
362 
363   return http_response;
364 }
365 
HandleReportPreflightForPath(const std::string & path,const std::map<std::string,std::string> & cors_headers,base::RepeatingClosure callback,const net::test_server::HttpRequest & request)366 std::unique_ptr<net::test_server::HttpResponse> HandleReportPreflightForPath(
367     const std::string& path,
368     const std::map<std::string, std::string>& cors_headers,
369     base::RepeatingClosure callback,
370     const net::test_server::HttpRequest& request) {
371   if (request.relative_url != path)
372     return nullptr;
373   return HandleReportPreflight(cors_headers, callback, request);
374 }
375 
376 // A test fixture that responds properly to CORS preflights so that reports can
377 // be successfully sent to test_server().
378 class ExpectCTReporterTest : public ::testing::Test {
379  public:
380   const std::map<std::string, std::string> kGoodCorsHeaders{
381       {"Access-Control-Allow-Origin", "*"},
382       {"Access-Control-Allow-Methods", "GET,POST"},
383       {"Access-Control-Allow-Headers", "content-type,another-header"}};
384 
ExpectCTReporterTest()385   ExpectCTReporterTest()
386       : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
~ExpectCTReporterTest()387   ~ExpectCTReporterTest() override {}
388 
389  protected:
test_server()390   net::EmbeddedTestServer& test_server() { return report_server_; }
391 
392   // Tests that reports are not sent when the CORS preflight request returns the
393   // header field |preflight_header_name| with value given by
394   // |preflight_header_bad_value|, and that reports are successfully sent when
395   // it has value given by |preflight_header_good_value|.
TestForReportPreflightFailure(ExpectCTReporter * reporter,TestCertificateReportSender * sender,const net::HostPortPair & host_port,const net::SSLInfo & ssl_info,const std::string & preflight_header_name,const std::string & preflight_header_bad_value,const std::string & preflight_header_good_value)396   void TestForReportPreflightFailure(
397       ExpectCTReporter* reporter,
398       TestCertificateReportSender* sender,
399       const net::HostPortPair& host_port,
400       const net::SSLInfo& ssl_info,
401       const std::string& preflight_header_name,
402       const std::string& preflight_header_bad_value,
403       const std::string& preflight_header_good_value) {
404     const std::string fail_path = "/report1";
405     const std::string successful_path = "/report2";
406 
407     std::map<std::string, std::string> bad_cors_headers = kGoodCorsHeaders;
408     bad_cors_headers[preflight_header_name] = preflight_header_bad_value;
409     std::map<std::string, std::string> good_cors_headers = kGoodCorsHeaders;
410     good_cors_headers[preflight_header_name] = preflight_header_good_value;
411 
412     base::RunLoop bad_cors_run_loop;
413     report_server_.RegisterRequestHandler(
414         base::BindRepeating(&HandleReportPreflightForPath, fail_path,
415                             bad_cors_headers, bad_cors_run_loop.QuitClosure()));
416     report_server_.RegisterRequestHandler(
417         base::BindRepeating(&HandleReportPreflightForPath, successful_path,
418                             good_cors_headers, base::RepeatingClosure()));
419     ASSERT_TRUE(report_server_.Start());
420 
421     const GURL fail_report_uri = test_server().GetURL(fail_path);
422     const GURL successful_report_uri = test_server().GetURL(successful_path);
423 
424     reporter->OnExpectCTFailed(
425         host_port, fail_report_uri, base::Time(), ssl_info.cert.get(),
426         ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
427     bad_cors_run_loop.Run();
428     // The CORS preflight response may not even have been received yet, so
429     // these expectations are mostly aspirational.
430     EXPECT_TRUE(sender->latest_report_uri().is_empty());
431     EXPECT_TRUE(sender->latest_serialized_report().empty());
432 
433     // Send a report to the url with good CORS headers. The test will fail
434     // if the previous OnExpectCTFailed() call unexpectedly resulted in a
435     // report, as WaitForReport() would see the previous report to /report1
436     // instead of the expected report to /report2, or sent_report_count() will
437     // be 2.
438     reporter->OnExpectCTFailed(
439         host_port, successful_report_uri, base::Time(), ssl_info.cert.get(),
440         ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
441     sender->WaitForReport(successful_report_uri);
442     EXPECT_EQ(successful_report_uri, sender->latest_report_uri());
443     EXPECT_EQ(1, sender->sent_report_count());
444   }
445 
446  private:
447   base::test::TaskEnvironment task_environment_;
448   net::EmbeddedTestServer report_server_;
449 };
450 
451 }  // namespace
452 
453 // Test that no report is sent when the feature is not enabled.
TEST_F(ExpectCTReporterTest,FeatureDisabled)454 TEST_F(ExpectCTReporterTest, FeatureDisabled) {
455   test_server().RegisterRequestHandler(base::BindRepeating(
456       &HandleReportPreflight, kGoodCorsHeaders, base::RepeatingClosure()));
457   ASSERT_TRUE(test_server().Start());
458 
459   base::HistogramTester histograms;
460   histograms.ExpectTotalCount(kSendHistogramName, 0);
461 
462   TestCertificateReportSender* sender = new TestCertificateReportSender();
463   net::TestURLRequestContext context;
464   ExpectCTReporter reporter(&context, base::NullCallback(),
465                             base::NullCallback());
466   reporter.report_sender_.reset(sender);
467   EXPECT_TRUE(sender->latest_report_uri().is_empty());
468   EXPECT_TRUE(sender->latest_serialized_report().empty());
469 
470   net::SSLInfo ssl_info;
471   ssl_info.cert =
472       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
473   ssl_info.unverified_cert = net::ImportCertFromFile(
474       net::GetTestCertsDirectory(), "localhost_cert.pem");
475 
476   net::HostPortPair host_port("example.test", 443);
477 
478   {
479     const GURL report_uri = test_server().GetURL("/report1");
480     base::test::ScopedFeatureList scoped_feature_list;
481     scoped_feature_list.InitAndDisableFeature(features::kExpectCTReporting);
482 
483     reporter.OnExpectCTFailed(
484         host_port, report_uri, base::Time(), ssl_info.cert.get(),
485         ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
486     EXPECT_TRUE(sender->latest_report_uri().is_empty());
487     EXPECT_TRUE(sender->latest_serialized_report().empty());
488 
489     histograms.ExpectTotalCount(kSendHistogramName, 0);
490   }
491 
492   // Enable the feature and send a dummy report. The test will fail if the
493   // previous OnExpectCTFailed() call unexpectedly resulted in a report, as the
494   // WaitForReport() would see the previous report to /report1 instead of the
495   // expected report to /report2.
496   {
497     const GURL report_uri = test_server().GetURL("/report2");
498     base::test::ScopedFeatureList scoped_feature_list;
499     scoped_feature_list.InitAndEnableFeature(features::kExpectCTReporting);
500     reporter.OnExpectCTFailed(
501         host_port, report_uri, base::Time(), ssl_info.cert.get(),
502         ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
503     sender->WaitForReport(report_uri);
504     EXPECT_EQ(report_uri, sender->latest_report_uri());
505     EXPECT_EQ(1, sender->sent_report_count());
506   }
507 }
508 
509 // Test that no report is sent if the report URI is empty.
TEST_F(ExpectCTReporterTest,EmptyReportURI)510 TEST_F(ExpectCTReporterTest, EmptyReportURI) {
511   base::HistogramTester histograms;
512   histograms.ExpectTotalCount(kSendHistogramName, 0);
513 
514   TestCertificateReportSender* sender = new TestCertificateReportSender();
515   net::TestURLRequestContext context;
516   ExpectCTReporter reporter(&context, base::NullCallback(),
517                             base::NullCallback());
518   reporter.report_sender_.reset(sender);
519   EXPECT_TRUE(sender->latest_report_uri().is_empty());
520   EXPECT_TRUE(sender->latest_serialized_report().empty());
521 
522   reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), base::Time(), nullptr,
523                             nullptr,
524                             net::SignedCertificateTimestampAndStatusList());
525   EXPECT_TRUE(sender->latest_report_uri().is_empty());
526   EXPECT_TRUE(sender->latest_serialized_report().empty());
527 
528   histograms.ExpectTotalCount(kSendHistogramName, 0);
529 }
530 
531 // Test that if a report fails to send, the UMA metric is recorded.
TEST_F(ExpectCTReporterWaitTest,SendReportFailure)532 TEST_F(ExpectCTReporterWaitTest, SendReportFailure) {
533   base::HistogramTester histograms;
534   histograms.ExpectTotalCount(kFailureHistogramName, 0);
535   histograms.ExpectTotalCount(kSendHistogramName, 0);
536 
537   ExpectCTReporter reporter(context(), base::NullCallback(),
538                             base::NullCallback());
539 
540   net::SSLInfo ssl_info;
541   ssl_info.cert =
542       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
543   ssl_info.unverified_cert = net::ImportCertFromFile(
544       net::GetTestCertsDirectory(), "localhost_cert.pem");
545 
546   net::HostPortPair host_port("example.test", 443);
547   GURL report_uri(
548       net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED));
549 
550   SendReport(&reporter, host_port, report_uri, base::Time(), ssl_info);
551 
552   histograms.ExpectTotalCount(kFailureHistogramName, 1);
553   histograms.ExpectBucketCount(kFailureHistogramName,
554                                -net::ERR_CONNECTION_FAILED, 1);
555   histograms.ExpectTotalCount(kSendHistogramName, 1);
556   histograms.ExpectBucketCount(kSendHistogramName, true, 1);
557 }
558 
559 // Test that if a report fails to send, the failure callback is called.
TEST_F(ExpectCTReporterWaitTest,SendReportFailureCallback)560 TEST_F(ExpectCTReporterWaitTest, SendReportFailureCallback) {
561   base::RunLoop run_loop;
562   ExpectCTReporter reporter(context(), base::NullCallback(),
563                             run_loop.QuitClosure());
564 
565   net::SSLInfo ssl_info;
566   ssl_info.cert =
567       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
568   ssl_info.unverified_cert = net::ImportCertFromFile(
569       net::GetTestCertsDirectory(), "localhost_cert.pem");
570 
571   net::HostPortPair host_port("example.test", 443);
572   GURL report_uri(
573       net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED));
574 
575   SendReport(&reporter, host_port, report_uri, base::Time(), ssl_info);
576 
577   // Wait to make sure the failure callback is called.
578   run_loop.Run();
579 }
580 
581 // Test that a sent report has the right format.
TEST_F(ExpectCTReporterTest,SendReport)582 TEST_F(ExpectCTReporterTest, SendReport) {
583   base::HistogramTester histograms;
584   histograms.ExpectTotalCount(kFailureHistogramName, 0);
585   histograms.ExpectTotalCount(kSendHistogramName, 0);
586 
587   TestCertificateReportSender* sender = new TestCertificateReportSender();
588   net::TestURLRequestContext context;
589   ExpectCTReporter reporter(&context, base::NullCallback(),
590                             base::NullCallback());
591   reporter.report_sender_.reset(sender);
592   EXPECT_TRUE(sender->latest_report_uri().is_empty());
593   EXPECT_TRUE(sender->latest_serialized_report().empty());
594 
595   net::SSLInfo ssl_info;
596   ssl_info.cert =
597       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
598   ssl_info.unverified_cert = net::ImportCertFromFile(
599       net::GetTestCertsDirectory(), "localhost_cert.pem");
600 
601   base::Time now = base::Time::Now();
602 
603   // Append a variety of SCTs: two of each possible status, with a
604   // mixture of different origins.
605 
606   // The particular value of the log ID doesn't matter; it just has to be the
607   // correct length.
608   const unsigned char kTestLogId[] = {
609       0xdf, 0x1c, 0x2e, 0xc1, 0x15, 0x00, 0x94, 0x52, 0x47, 0xa9, 0x61,
610       0x68, 0x32, 0x5d, 0xdc, 0x5c, 0x79, 0x59, 0xe8, 0xf7, 0xc6, 0xd3,
611       0x88, 0xfc, 0x00, 0x2e, 0x0b, 0xbd, 0x3f, 0x74, 0xd7, 0x01};
612   const std::string log_id(reinterpret_cast<const char*>(kTestLogId),
613                            sizeof(kTestLogId));
614   // The values of the extensions and signature data don't matter
615   // either. However, each SCT has to be unique for the test expectation to be
616   // checked properly in CheckExpectCTReport(), so each SCT has a unique
617   // extensions value to make sure the serialized SCTs are unique.
618   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
619                        log_id, "extensions1", "signature1", now,
620                        net::ct::SCT_STATUS_LOG_UNKNOWN,
621                        &ssl_info.signed_certificate_timestamps);
622   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
623                        log_id, "extensions2", "signature2", now,
624                        net::ct::SCT_STATUS_LOG_UNKNOWN,
625                        &ssl_info.signed_certificate_timestamps);
626 
627   MakeTestSCTAndStatus(
628       net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, log_id,
629       "extensions3", "signature1", now, net::ct::SCT_STATUS_INVALID_TIMESTAMP,
630       &ssl_info.signed_certificate_timestamps);
631 
632   MakeTestSCTAndStatus(
633       net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, log_id,
634       "extensions4", "signature1", now, net::ct::SCT_STATUS_INVALID_SIGNATURE,
635       &ssl_info.signed_certificate_timestamps);
636 
637   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
638                        log_id, "extensions5", "signature2", now,
639                        net::ct::SCT_STATUS_INVALID_SIGNATURE,
640                        &ssl_info.signed_certificate_timestamps);
641 
642   MakeTestSCTAndStatus(
643       net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, log_id,
644       "extensions6", "signature1", now, net::ct::SCT_STATUS_OK,
645       &ssl_info.signed_certificate_timestamps);
646   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
647                        log_id, "extensions7", "signature2", now,
648                        net::ct::SCT_STATUS_OK,
649                        &ssl_info.signed_certificate_timestamps);
650 
651   const char kExpirationTimeStr[] = "2017-01-01T00:00:00.000Z";
652   base::Time expiration;
653   ASSERT_TRUE(
654       base::Time::FromUTCExploded({2017, 1, 0, 1, 0, 0, 0, 0}, &expiration));
655 
656   const std::string report_path = "/report";
657   base::RunLoop cors_run_loop;
658   test_server().RegisterRequestHandler(
659       base::BindRepeating(&HandleReportPreflightForPath, report_path,
660                           kGoodCorsHeaders, cors_run_loop.QuitClosure()));
661   ASSERT_TRUE(test_server().Start());
662   const GURL report_uri = test_server().GetURL(report_path);
663 
664   // Check that the report is sent and contains the correct information.
665   reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
666                             expiration, ssl_info.cert.get(),
667                             ssl_info.unverified_cert.get(),
668                             ssl_info.signed_certificate_timestamps);
669 
670   // A CORS preflight request should be sent before the actual report.
671   cors_run_loop.Run();
672   sender->WaitForReport(report_uri);
673 
674   EXPECT_EQ(report_uri, sender->latest_report_uri());
675   EXPECT_FALSE(sender->latest_serialized_report().empty());
676   EXPECT_EQ("application/expect-ct-report+json; charset=utf-8",
677             sender->latest_content_type());
678   ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport(
679       sender->latest_serialized_report(),
680       net::HostPortPair::FromURL(report_uri), kExpirationTimeStr, ssl_info));
681 
682   histograms.ExpectTotalCount(kFailureHistogramName, 0);
683   histograms.ExpectTotalCount(kSendHistogramName, 1);
684   histograms.ExpectBucketCount(kSendHistogramName, true, 1);
685 }
686 
687 // Test that the success callback is called when a report is successfully sent.
TEST_F(ExpectCTReporterTest,SendReportSuccessCallback)688 TEST_F(ExpectCTReporterTest, SendReportSuccessCallback) {
689   test_server().RegisterRequestHandler(base::BindRepeating(
690       &HandleReportPreflight, kGoodCorsHeaders, base::RepeatingClosure()));
691   // This test actually sends the report to the testserver, so register a
692   // handler that will return OK.
693   test_server().RegisterRequestHandler(
694       base::BindRepeating(&ReplyToPostWith200));
695   ASSERT_TRUE(test_server().Start());
696 
697   base::RunLoop run_loop;
698 
699   net::TestURLRequestContext context;
700   ExpectCTReporter reporter(&context, run_loop.QuitClosure(),
701                             base::NullCallback());
702 
703   net::SSLInfo ssl_info;
704   ssl_info.cert =
705       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
706   ssl_info.unverified_cert = net::ImportCertFromFile(
707       net::GetTestCertsDirectory(), "localhost_cert.pem");
708 
709   // The particular value of the log ID doesn't matter; it just has to be the
710   // correct length.
711   const unsigned char kTestLogId[] = {
712       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
713       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
714       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
715   const std::string log_id(reinterpret_cast<const char*>(kTestLogId),
716                            sizeof(kTestLogId));
717   MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
718                        log_id, "extensions1", "signature1", base::Time::Now(),
719                        net::ct::SCT_STATUS_LOG_UNKNOWN,
720                        &ssl_info.signed_certificate_timestamps);
721 
722   base::Time expiration;
723   ASSERT_TRUE(
724       base::Time::FromUTCExploded({2017, 1, 0, 1, 0, 0, 0, 0}, &expiration));
725 
726   const GURL report_uri = test_server().GetURL("/report");
727 
728   reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
729                             expiration, ssl_info.cert.get(),
730                             ssl_info.unverified_cert.get(),
731                             ssl_info.signed_certificate_timestamps);
732 
733   // Wait to check that the success callback is run.
734   run_loop.Run();
735 }
736 
737 // Test that report preflight responses can contain whitespace.
TEST_F(ExpectCTReporterTest,PreflightContainsWhitespace)738 TEST_F(ExpectCTReporterTest, PreflightContainsWhitespace) {
739   const std::string report_path = "/report";
740   std::map<std::string, std::string> cors_headers = kGoodCorsHeaders;
741   cors_headers["Access-Control-Allow-Methods"] = "GET, POST";
742   base::RunLoop cors_run_loop;
743   test_server().RegisterRequestHandler(
744       base::BindRepeating(&HandleReportPreflightForPath, report_path,
745                           cors_headers, cors_run_loop.QuitClosure()));
746   ASSERT_TRUE(test_server().Start());
747 
748   TestCertificateReportSender* sender = new TestCertificateReportSender();
749   net::TestURLRequestContext context;
750   ExpectCTReporter reporter(&context, base::NullCallback(),
751                             base::NullCallback());
752   reporter.report_sender_.reset(sender);
753   EXPECT_TRUE(sender->latest_report_uri().is_empty());
754   EXPECT_TRUE(sender->latest_serialized_report().empty());
755 
756   net::SSLInfo ssl_info;
757   ssl_info.cert =
758       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
759   ssl_info.unverified_cert = net::ImportCertFromFile(
760       net::GetTestCertsDirectory(), "localhost_cert.pem");
761 
762   const GURL report_uri = test_server().GetURL(report_path);
763   reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
764                             base::Time::Now(), ssl_info.cert.get(),
765                             ssl_info.unverified_cert.get(),
766                             ssl_info.signed_certificate_timestamps);
767 
768   // A CORS preflight request should be sent before the actual report.
769   cors_run_loop.Run();
770   sender->WaitForReport(report_uri);
771 
772   EXPECT_EQ(report_uri, sender->latest_report_uri());
773   EXPECT_FALSE(sender->latest_serialized_report().empty());
774 }
775 
776 // Test that no report is sent when the CORS preflight returns an invalid
777 // Access-Control-Allow-Origin.
TEST_F(ExpectCTReporterTest,BadCorsPreflightResponseOrigin)778 TEST_F(ExpectCTReporterTest, BadCorsPreflightResponseOrigin) {
779   TestCertificateReportSender* sender = new TestCertificateReportSender();
780   net::TestURLRequestContext context;
781   ExpectCTReporter reporter(&context, base::NullCallback(),
782                             base::NullCallback());
783   reporter.report_sender_.reset(sender);
784   EXPECT_TRUE(sender->latest_report_uri().is_empty());
785   EXPECT_TRUE(sender->latest_serialized_report().empty());
786 
787   net::SSLInfo ssl_info;
788   ssl_info.cert =
789       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
790   ssl_info.unverified_cert = net::ImportCertFromFile(
791       net::GetTestCertsDirectory(), "localhost_cert.pem");
792 
793   base::test::ScopedFeatureList scoped_feature_list;
794   scoped_feature_list.InitAndEnableFeature(features::kExpectCTReporting);
795   EXPECT_TRUE(sender->latest_serialized_report().empty());
796   ASSERT_NO_FATAL_FAILURE(TestForReportPreflightFailure(
797       &reporter, sender, net::HostPortPair("example.test", 443), ssl_info,
798       "Access-Control-Allow-Origin", "https://another-origin.test", "null"));
799 }
800 
801 // Test that no report is sent when the CORS preflight returns an invalid
802 // Access-Control-Allow-Methods.
TEST_F(ExpectCTReporterTest,BadCorsPreflightResponseMethods)803 TEST_F(ExpectCTReporterTest, BadCorsPreflightResponseMethods) {
804   TestCertificateReportSender* sender = new TestCertificateReportSender();
805   net::TestURLRequestContext context;
806   ExpectCTReporter reporter(&context, base::NullCallback(),
807                             base::NullCallback());
808   reporter.report_sender_.reset(sender);
809   EXPECT_TRUE(sender->latest_report_uri().is_empty());
810   EXPECT_TRUE(sender->latest_serialized_report().empty());
811 
812   net::SSLInfo ssl_info;
813   ssl_info.cert =
814       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
815   ssl_info.unverified_cert = net::ImportCertFromFile(
816       net::GetTestCertsDirectory(), "localhost_cert.pem");
817 
818   base::test::ScopedFeatureList scoped_feature_list;
819   scoped_feature_list.InitAndEnableFeature(features::kExpectCTReporting);
820   EXPECT_TRUE(sender->latest_serialized_report().empty());
821   ASSERT_NO_FATAL_FAILURE(TestForReportPreflightFailure(
822       &reporter, sender, net::HostPortPair("example.test", 443), ssl_info,
823       "Access-Control-Allow-Methods", "GET,HEAD,POSSSST", "POST"));
824 }
825 
826 // Test that no report is sent when the CORS preflight returns an invalid
827 // Access-Control-Allow-Headers.
TEST_F(ExpectCTReporterTest,BadCorsPreflightResponseHeaders)828 TEST_F(ExpectCTReporterTest, BadCorsPreflightResponseHeaders) {
829   TestCertificateReportSender* sender = new TestCertificateReportSender();
830   net::TestURLRequestContext context;
831   ExpectCTReporter reporter(&context, base::NullCallback(),
832                             base::NullCallback());
833   reporter.report_sender_.reset(sender);
834   EXPECT_TRUE(sender->latest_report_uri().is_empty());
835   EXPECT_TRUE(sender->latest_serialized_report().empty());
836 
837   net::SSLInfo ssl_info;
838   ssl_info.cert =
839       net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
840   ssl_info.unverified_cert = net::ImportCertFromFile(
841       net::GetTestCertsDirectory(), "localhost_cert.pem");
842 
843   base::test::ScopedFeatureList scoped_feature_list;
844   scoped_feature_list.InitAndEnableFeature(features::kExpectCTReporting);
845   EXPECT_TRUE(sender->latest_serialized_report().empty());
846   ASSERT_NO_FATAL_FAILURE(TestForReportPreflightFailure(
847       &reporter, sender, net::HostPortPair("example.test", 443), ssl_info,
848       "Access-Control-Allow-Headers", "Not-Content-Type", "Content-Type"));
849 }
850 
851 }  // namespace network
852