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