xref: /aosp_15_r20/external/cronet/net/http/http_proxy_connect_job.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 The Chromium Authors
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 NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_
6 #define NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <string>
11 
12 #include "base/functional/callback_forward.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/time/time.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/base/net_export.h"
17 #include "net/base/network_anonymization_key.h"
18 #include "net/base/proxy_chain.h"
19 #include "net/base/request_priority.h"
20 #include "net/dns/public/resolve_error_info.h"
21 #include "net/dns/public/secure_dns_policy.h"
22 #include "net/http/http_auth.h"
23 #include "net/quic/quic_chromium_client_session.h"
24 #include "net/socket/connect_job.h"
25 #include "net/socket/connect_job_params.h"
26 #include "net/socket/ssl_client_socket.h"
27 #include "net/spdy/spdy_session_key.h"
28 #include "net/ssl/ssl_cert_request_info.h"
29 #include "net/traffic_annotation/network_traffic_annotation.h"
30 
31 namespace net {
32 
33 class HttpAuthController;
34 class HttpResponseInfo;
35 class NetworkQualityEstimator;
36 class SocketTag;
37 class ProxyClientSocket;
38 class SpdyStreamRequest;
39 class SSLSocketParams;
40 class TransportSocketParams;
41 class QuicSessionRequest;
42 
43 // HttpProxySocketParams only needs the socket params for one of the proxy
44 // types.  The other param must be NULL.  When using an HTTP proxy,
45 // `transport_params` must be set.  When using an HTTPS proxy, `ssl_params` must
46 // be set. When using a QUIC proxy, both must be `nullptr` but `quic_ssl_config`
47 // must be set.
48 
49 class NET_EXPORT_PRIVATE HttpProxySocketParams
50     : public base::RefCounted<HttpProxySocketParams> {
51  public:
52   // Construct an `HttpProxyConnectJob` over a transport or SSL connection
53   // defined by the `ConnectJobParams`.
54   HttpProxySocketParams(
55       ConnectJobParams nested_params,
56       const HostPortPair& endpoint,
57       const ProxyChain& proxy_chain,
58       size_t proxy_chain_index,
59       bool tunnel,
60       const NetworkTrafficAnnotationTag traffic_annotation,
61       const NetworkAnonymizationKey& network_anonymization_key,
62       SecureDnsPolicy secure_dns_policy);
63 
64   // Construct an `HttpProxyConnectJob` over a QUIC connection using the given
65   // SSL config.
66   HttpProxySocketParams(
67       SSLConfig quic_ssl_config,
68       const HostPortPair& endpoint,
69       const ProxyChain& proxy_chain,
70       size_t proxy_chain_index,
71       bool tunnel,
72       const NetworkTrafficAnnotationTag traffic_annotation,
73       const NetworkAnonymizationKey& network_anonymization_key,
74       SecureDnsPolicy secure_dns_policy);
75 
76   HttpProxySocketParams(const HttpProxySocketParams&) = delete;
77   HttpProxySocketParams& operator=(const HttpProxySocketParams&) = delete;
78 
is_over_transport()79   bool is_over_transport() const {
80     return nested_params_ && nested_params_->is_transport();
81   }
is_over_ssl()82   bool is_over_ssl() const {
83     return nested_params_ && nested_params_->is_ssl();
84   }
is_over_quic()85   bool is_over_quic() const { return quic_ssl_config_.has_value(); }
86 
87   // Get the nested transport params, or fail if not `is_over_transport()`.
transport_params()88   const scoped_refptr<TransportSocketParams>& transport_params() const {
89     return nested_params_->transport();
90   }
91 
92   // Get the nested SSL params, or fail if not `is_over_ssl()`.
ssl_params()93   const scoped_refptr<SSLSocketParams>& ssl_params() const {
94     return nested_params_->ssl();
95   }
96 
97   // Get the QUIC ssl config, or fail if not `is_over_quic()`.
quic_ssl_config()98   const std::optional<SSLConfig>& quic_ssl_config() const {
99     return quic_ssl_config_;
100   }
101 
endpoint()102   const HostPortPair& endpoint() const { return endpoint_; }
proxy_chain()103   const ProxyChain& proxy_chain() const { return proxy_chain_; }
proxy_server()104   const ProxyServer& proxy_server() const {
105     return proxy_chain_.GetProxyServer(proxy_chain_index_);
106   }
proxy_chain_index()107   size_t proxy_chain_index() const { return proxy_chain_index_; }
tunnel()108   bool tunnel() const { return tunnel_; }
network_anonymization_key()109   const NetworkAnonymizationKey& network_anonymization_key() const {
110     return network_anonymization_key_;
111   }
traffic_annotation()112   const NetworkTrafficAnnotationTag traffic_annotation() const {
113     return traffic_annotation_;
114   }
secure_dns_policy()115   SecureDnsPolicy secure_dns_policy() { return secure_dns_policy_; }
116 
117  private:
118   friend class base::RefCounted<HttpProxySocketParams>;
119   HttpProxySocketParams(
120       std::optional<ConnectJobParams> nested_params,
121       std::optional<SSLConfig> quic_ssl_config,
122       const HostPortPair& endpoint,
123       const ProxyChain& proxy_chain,
124       size_t proxy_chain_index,
125       bool tunnel,
126       const NetworkTrafficAnnotationTag traffic_annotation,
127       const NetworkAnonymizationKey& network_anonymization_key,
128       SecureDnsPolicy secure_dns_policy);
129   ~HttpProxySocketParams();
130 
131   const std::optional<ConnectJobParams> nested_params_;
132   const std::optional<SSLConfig> quic_ssl_config_;
133   const HostPortPair endpoint_;
134   const ProxyChain proxy_chain_;
135   const size_t proxy_chain_index_;
136   const bool tunnel_;
137   const NetworkAnonymizationKey network_anonymization_key_;
138   const NetworkTrafficAnnotationTag traffic_annotation_;
139   const SecureDnsPolicy secure_dns_policy_;
140 };
141 
142 // HttpProxyConnectJob optionally establishes a tunnel through the proxy
143 // server after connecting the underlying transport socket.
144 class NET_EXPORT_PRIVATE HttpProxyConnectJob : public ConnectJob,
145                                                public ConnectJob::Delegate {
146  public:
147   class NET_EXPORT_PRIVATE Factory {
148    public:
149     Factory() = default;
150     virtual ~Factory() = default;
151 
152     virtual std::unique_ptr<HttpProxyConnectJob> Create(
153         RequestPriority priority,
154         const SocketTag& socket_tag,
155         const CommonConnectJobParams* common_connect_job_params,
156         scoped_refptr<HttpProxySocketParams> params,
157         ConnectJob::Delegate* delegate,
158         const NetLogWithSource* net_log);
159   };
160 
161   HttpProxyConnectJob(RequestPriority priority,
162                       const SocketTag& socket_tag,
163                       const CommonConnectJobParams* common_connect_job_params,
164                       scoped_refptr<HttpProxySocketParams> params,
165                       ConnectJob::Delegate* delegate,
166                       const NetLogWithSource* net_log);
167 
168   HttpProxyConnectJob(const HttpProxyConnectJob&) = delete;
169   HttpProxyConnectJob& operator=(const HttpProxyConnectJob&) = delete;
170 
171   ~HttpProxyConnectJob() override;
172 
173   // A single priority is used for tunnels over H2 and QUIC, which can be shared
174   // by multiple requests of different priorities either in series (tunnels for
175   // HTTP/1.x requests) or simultaneously (tunnels for H2 requests). Changing
176   // the priority of the tunnel based on the current request also potentially
177   // leaks private data to the proxy.
178   static const RequestPriority kH2QuicTunnelPriority;
179 
180   // ConnectJob methods.
181   LoadState GetLoadState() const override;
182   bool HasEstablishedConnection() const override;
183   ResolveErrorInfo GetResolveErrorInfo() const override;
184   bool IsSSLError() const override;
185   scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo() override;
186 
187   // ConnectJob::Delegate implementation.
188   void OnConnectJobComplete(int result, ConnectJob* job) override;
189   void OnNeedsProxyAuth(const HttpResponseInfo& response,
190                         HttpAuthController* auth_controller,
191                         base::OnceClosure restart_with_auth_callback,
192                         ConnectJob* job) override;
193 
194   // In some cases, a timeout that's stricter than the TCP (+SSL, if applicable)
195   // is used for HTTP proxies during connection establishment and SSL
196   // negotiation for the connection to the proxy itself. In those cases, returns
197   // the connection timeout that will be used by a HttpProxyConnectJob created
198   // with the specified parameters, given current network conditions. Otherwise,
199   // returns base::TimeDelta().
200   static base::TimeDelta AlternateNestedConnectionTimeout(
201       const HttpProxySocketParams& params,
202       const NetworkQualityEstimator* network_quality_estimator);
203 
204   // Returns the timeout for establishing a tunnel after a connection has been
205   // established.
206   static base::TimeDelta TunnelTimeoutForTesting();
207 
208   // Updates the field trial parameters used in calculating timeouts.
209   static void UpdateFieldTrialParametersForTesting();
210 
211  private:
212   enum State {
213     STATE_BEGIN_CONNECT,
214     STATE_TRANSPORT_CONNECT,
215     STATE_TRANSPORT_CONNECT_COMPLETE,
216     STATE_HTTP_PROXY_CONNECT,
217     STATE_HTTP_PROXY_CONNECT_COMPLETE,
218     STATE_SPDY_PROXY_CREATE_STREAM,
219     STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE,
220     STATE_QUIC_PROXY_CREATE_SESSION,
221     STATE_QUIC_PROXY_CREATE_STREAM,
222     STATE_QUIC_PROXY_CREATE_STREAM_COMPLETE,
223     STATE_RESTART_WITH_AUTH,
224     STATE_RESTART_WITH_AUTH_COMPLETE,
225     STATE_NONE,
226   };
227 
228   // Begins the tcp connection and the optional Http proxy tunnel.  If the
229   // request is not immediately serviceable (likely), the request will return
230   // ERR_IO_PENDING. An OK return from this function or the callback means
231   // that the connection is established; ERR_PROXY_AUTH_REQUESTED means
232   // that the tunnel needs authentication credentials, the socket will be
233   // returned in this case, and must be released back to the pool; or
234   // a standard net error code will be returned.
235   int ConnectInternal() override;
236 
237   ProxyServer::Scheme GetProxyServerScheme() const;
238 
239   void OnIOComplete(int result);
240 
241   void RestartWithAuthCredentials();
242 
243   // Runs the state transition loop.
244   int DoLoop(int result);
245 
246   // Determine if need to go through TCP or SSL path.
247   int DoBeginConnect();
248   // Connecting to HTTP or HTTPS Proxy
249   int DoTransportConnect();
250   int DoTransportConnectComplete(int result);
251 
252   int DoHttpProxyConnect();
253   int DoHttpProxyConnectComplete(int result);
254 
255   int DoSpdyProxyCreateStream();
256   int DoSpdyProxyCreateStreamComplete(int result);
257 
258   int DoQuicProxyCreateSession();
259   int DoQuicProxyCreateStream(int result);
260   int DoQuicProxyCreateStreamComplete(int result);
261 
262   int DoRestartWithAuth();
263   int DoRestartWithAuthComplete(int result);
264 
265   // ConnectJob implementation.
266   void ChangePriorityInternal(RequestPriority priority) override;
267   void OnTimedOutInternal() override;
268 
269   void OnAuthChallenge();
270 
271   const HostPortPair& GetDestination() const;
272 
273   std::string GetUserAgent() const;
274 
275   SpdySessionKey CreateSpdySessionKey() const;
276 
277   scoped_refptr<HttpProxySocketParams> params_;
278 
279   scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;
280 
281   State next_state_ = STATE_NONE;
282 
283   bool has_restarted_ = false;
284 
285   // Set to true once a connection has been successfully established. Remains
286   // true even if a new socket is being connected to retry with auth.
287   bool has_established_connection_ = false;
288 
289   ResolveErrorInfo resolve_error_info_;
290 
291   std::unique_ptr<ConnectJob> nested_connect_job_;
292   std::unique_ptr<ProxyClientSocket> transport_socket_;
293 
294   std::unique_ptr<SpdyStreamRequest> spdy_stream_request_;
295 
296   std::unique_ptr<QuicSessionRequest> quic_session_request_;
297   std::unique_ptr<QuicChromiumClientSession::Handle> quic_session_;
298 
299   scoped_refptr<HttpAuthController> http_auth_controller_;
300 
301   NetErrorDetails quic_net_error_details_;
302 
303   // Time when the connection to the proxy was started.
304   base::TimeTicks connect_start_time_;
305 
306   base::WeakPtrFactory<HttpProxyConnectJob> weak_ptr_factory_{this};
307 };
308 
309 }  // namespace net
310 
311 #endif  // NET_HTTP_HTTP_PROXY_CONNECT_JOB_H_
312