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