expect_ct_reporter_unittest.cc 40 KB

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