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