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 #ifndef SERVICES_NETWORK_EXPECT_CT_REPORTER_H_
6 #define SERVICES_NETWORK_EXPECT_CT_REPORTER_H_
7
8 #include <map>
9 #include <memory>
10
11 #include "base/component_export.h"
12 #include "base/macros.h"
13 #include "net/http/transport_security_state.h"
14 #include "net/url_request/url_request.h"
15
16 namespace net {
17 class ReportSender;
18 class URLRequestContext;
19 } // namespace net
20
21 namespace network {
22
23 // This class monitors for violations of CT policy and sends reports
24 // about failures for sites that have opted in. Must be deleted before
25 // the URLRequestContext that is passed to the constructor, so that it
26 // can cancel its requests.
27 //
28 // Since reports are sent with a non-CORS-whitelisted Content-Type, this class
29 // sends CORS preflight requests before sending reports. Expect-CT is not
30 // evaluated with a particular frame or request as context, so the preflight
31 // request contains an `Origin: null` header instead of a particular origin.
COMPONENT_EXPORT(NETWORK_SERVICE)32 class COMPONENT_EXPORT(NETWORK_SERVICE) ExpectCTReporter
33 : public net::TransportSecurityState::ExpectCTReporter,
34 net::URLRequest::Delegate {
35 public:
36 // Constructs a ExpectCTReporter that sends reports with the given
37 // |request_context|. |success_callback| is called whenever a report sends
38 // successfully, and |failure_callback| whenever a report fails to send.
39 ExpectCTReporter(net::URLRequestContext* request_context,
40 const base::RepeatingClosure& success_callback,
41 const base::RepeatingClosure& failure_callback);
42 ~ExpectCTReporter() override;
43
44 // net::TransportSecurityState::ExpectCTReporter:
45 void OnExpectCTFailed(const net::HostPortPair& host_port_pair,
46 const GURL& report_uri,
47 base::Time expiration,
48 const net::X509Certificate* validated_certificate_chain,
49 const net::X509Certificate* served_certificate_chain,
50 const net::SignedCertificateTimestampAndStatusList&
51 signed_certificate_timestamps) override;
52
53 // net::URLRequest::Delegate:
54 void OnResponseStarted(net::URLRequest* request, int net_error) override;
55 void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
56
57 private:
58 // Used to keep track of in-flight CORS preflight requests. When |request|
59 // completes successfully and the CORS check passes, |serialized_report| will
60 // be sent to |report_uri| using |report_sender_|.
61 struct PreflightInProgress {
62 PreflightInProgress(std::unique_ptr<net::URLRequest> request,
63 const std::string& serialized_report,
64 const GURL& report_uri);
65 ~PreflightInProgress();
66 // The preflight request.
67 const std::unique_ptr<net::URLRequest> request;
68 // |serialized_report| should be sent to |report_uri| if the preflight
69 // succeeds.
70 const std::string serialized_report;
71 const GURL report_uri;
72 };
73
74 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, FeatureDisabled);
75 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, EmptyReportURI);
76 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, SendReport);
77 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, PreflightContainsWhitespace);
78 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest,
79 BadCorsPreflightResponseOrigin);
80 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest,
81 BadCorsPreflightResponseMethods);
82 FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest,
83 BadCorsPreflightResponseHeaders);
84
85 // Starts a CORS preflight request to obtain permission from the server to
86 // send a report with Content-Type: application/expect-ct-report+json. The
87 // preflight result is checked in OnResponseStarted(), and an actual report is
88 // sent with |report_sender_| if the preflight succeeds.
89 void SendPreflight(const GURL& report_uri,
90 const std::string& serialized_report);
91
92 // When a report fails to send, this method records an UMA histogram and calls
93 // |failure_callback_|.
94 void OnReportFailure(const GURL& report_uri,
95 int net_error,
96 int http_response_code);
97
98 std::unique_ptr<net::ReportSender> report_sender_;
99
100 net::URLRequestContext* request_context_;
101
102 base::RepeatingClosure success_callback_;
103 base::RepeatingClosure failure_callback_;
104
105 // The CORS preflight requests, with corresponding report information, that
106 // are currently in-flight. Entries in this map are deleted when the
107 // preflight's OnResponseStarted() is called.
108 std::map<net::URLRequest*, std::unique_ptr<PreflightInProgress>>
109 inflight_preflights_;
110
111 DISALLOW_COPY_AND_ASSIGN(ExpectCTReporter);
112 };
113
114 } // namespace network
115
116 #endif // SERVICES_NETWORK_EXPECT_CT_REPORTER_H_
117