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