1 // Copyright 2012 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 #include "net/http/http_proxy_client_socket.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_helpers.h"
12 #include "base/strings/string_util.h"
13 #include "base/values.h"
14 #include "net/base/auth.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/proxy_delegate.h"
18 #include "net/base/proxy_server.h"
19 #include "net/http/http_basic_stream.h"
20 #include "net/http/http_log_util.h"
21 #include "net/http/http_network_session.h"
22 #include "net/http/http_request_info.h"
23 #include "net/http/http_response_headers.h"
24 #include "net/http/http_stream_parser.h"
25 #include "net/log/net_log.h"
26 #include "net/log/net_log_event_type.h"
27 #include "net/socket/stream_socket.h"
28 #include "url/gurl.h"
29
30 namespace net {
31
32 const int HttpProxyClientSocket::kDrainBodyBufferSize;
33
HttpProxyClientSocket(std::unique_ptr<StreamSocket> socket,const std::string & user_agent,const HostPortPair & endpoint,const ProxyServer & proxy_server,scoped_refptr<HttpAuthController> http_auth_controller,ProxyDelegate * proxy_delegate,const NetworkTrafficAnnotationTag & traffic_annotation)34 HttpProxyClientSocket::HttpProxyClientSocket(
35 std::unique_ptr<StreamSocket> socket,
36 const std::string& user_agent,
37 const HostPortPair& endpoint,
38 const ProxyServer& proxy_server,
39 scoped_refptr<HttpAuthController> http_auth_controller,
40 ProxyDelegate* proxy_delegate,
41 const NetworkTrafficAnnotationTag& traffic_annotation)
42 : io_callback_(base::BindRepeating(&HttpProxyClientSocket::OnIOComplete,
43 base::Unretained(this))),
44 socket_(std::move(socket)),
45 endpoint_(endpoint),
46 auth_(std::move(http_auth_controller)),
47 proxy_server_(proxy_server),
48 proxy_delegate_(proxy_delegate),
49 traffic_annotation_(traffic_annotation),
50 net_log_(socket_->NetLog()) {
51 // Synthesize the bits of a request that are actually used.
52 request_.url = GURL("https://" + endpoint.ToString());
53 request_.method = "CONNECT";
54 if (!user_agent.empty())
55 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
56 user_agent);
57 }
58
~HttpProxyClientSocket()59 HttpProxyClientSocket::~HttpProxyClientSocket() {
60 Disconnect();
61 }
62
RestartWithAuth(CompletionOnceCallback callback)63 int HttpProxyClientSocket::RestartWithAuth(CompletionOnceCallback callback) {
64 DCHECK_EQ(STATE_NONE, next_state_);
65 DCHECK(user_callback_.is_null());
66
67 int rv = PrepareForAuthRestart();
68 if (rv != OK)
69 return rv;
70
71 rv = DoLoop(OK);
72 if (rv == ERR_IO_PENDING) {
73 if (!callback.is_null())
74 user_callback_ = std::move(callback);
75 }
76
77 return rv;
78 }
79
80 const scoped_refptr<HttpAuthController>&
GetAuthController() const81 HttpProxyClientSocket::GetAuthController() const {
82 return auth_;
83 }
84
GetConnectResponseInfo() const85 const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
86 return response_.headers.get() ? &response_ : nullptr;
87 }
88
Connect(CompletionOnceCallback callback)89 int HttpProxyClientSocket::Connect(CompletionOnceCallback callback) {
90 DCHECK(socket_);
91 DCHECK(user_callback_.is_null());
92
93 if (next_state_ == STATE_DONE)
94 return OK;
95
96 DCHECK_EQ(STATE_NONE, next_state_);
97 next_state_ = STATE_GENERATE_AUTH_TOKEN;
98
99 int rv = DoLoop(OK);
100 if (rv == ERR_IO_PENDING)
101 user_callback_ = std::move(callback);
102 return rv;
103 }
104
Disconnect()105 void HttpProxyClientSocket::Disconnect() {
106 if (socket_)
107 socket_->Disconnect();
108
109 // Reset other states to make sure they aren't mistakenly used later.
110 // These are the states initialized by Connect().
111 next_state_ = STATE_NONE;
112 user_callback_.Reset();
113 }
114
IsConnected() const115 bool HttpProxyClientSocket::IsConnected() const {
116 return next_state_ == STATE_DONE && socket_->IsConnected();
117 }
118
IsConnectedAndIdle() const119 bool HttpProxyClientSocket::IsConnectedAndIdle() const {
120 return next_state_ == STATE_DONE && socket_->IsConnectedAndIdle();
121 }
122
NetLog() const123 const NetLogWithSource& HttpProxyClientSocket::NetLog() const {
124 return net_log_;
125 }
126
WasEverUsed() const127 bool HttpProxyClientSocket::WasEverUsed() const {
128 if (socket_)
129 return socket_->WasEverUsed();
130 NOTREACHED();
131 return false;
132 }
133
WasAlpnNegotiated() const134 bool HttpProxyClientSocket::WasAlpnNegotiated() const {
135 // Do not delegate to `socket_`. While `socket_` may negotiate ALPN with the
136 // proxy, this object represents the tunneled TCP connection to the origin.
137 return false;
138 }
139
GetNegotiatedProtocol() const140 NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
141 // Do not delegate to `socket_`. While `socket_` may negotiate ALPN with the
142 // proxy, this object represents the tunneled TCP connection to the origin.
143 return kProtoUnknown;
144 }
145
GetSSLInfo(SSLInfo * ssl_info)146 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
147 // Do not delegate to `socket_`. While `socket_` may connect to the proxy with
148 // TLS, this object represents the tunneled TCP connection to the origin.
149 return false;
150 }
151
GetTotalReceivedBytes() const152 int64_t HttpProxyClientSocket::GetTotalReceivedBytes() const {
153 return socket_->GetTotalReceivedBytes();
154 }
155
ApplySocketTag(const SocketTag & tag)156 void HttpProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
157 return socket_->ApplySocketTag(tag);
158 }
159
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)160 int HttpProxyClientSocket::Read(IOBuffer* buf,
161 int buf_len,
162 CompletionOnceCallback callback) {
163 DCHECK(user_callback_.is_null());
164 if (!CheckDone())
165 return ERR_TUNNEL_CONNECTION_FAILED;
166
167 return socket_->Read(buf, buf_len, std::move(callback));
168 }
169
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)170 int HttpProxyClientSocket::ReadIfReady(IOBuffer* buf,
171 int buf_len,
172 CompletionOnceCallback callback) {
173 DCHECK(user_callback_.is_null());
174 if (!CheckDone())
175 return ERR_TUNNEL_CONNECTION_FAILED;
176
177 return socket_->ReadIfReady(buf, buf_len, std::move(callback));
178 }
179
CancelReadIfReady()180 int HttpProxyClientSocket::CancelReadIfReady() {
181 return socket_->CancelReadIfReady();
182 }
183
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)184 int HttpProxyClientSocket::Write(
185 IOBuffer* buf,
186 int buf_len,
187 CompletionOnceCallback callback,
188 const NetworkTrafficAnnotationTag& traffic_annotation) {
189 DCHECK_EQ(STATE_DONE, next_state_);
190 DCHECK(user_callback_.is_null());
191
192 return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation);
193 }
194
SetReceiveBufferSize(int32_t size)195 int HttpProxyClientSocket::SetReceiveBufferSize(int32_t size) {
196 return socket_->SetReceiveBufferSize(size);
197 }
198
SetSendBufferSize(int32_t size)199 int HttpProxyClientSocket::SetSendBufferSize(int32_t size) {
200 return socket_->SetSendBufferSize(size);
201 }
202
GetPeerAddress(IPEndPoint * address) const203 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
204 return socket_->GetPeerAddress(address);
205 }
206
GetLocalAddress(IPEndPoint * address) const207 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
208 return socket_->GetLocalAddress(address);
209 }
210
PrepareForAuthRestart()211 int HttpProxyClientSocket::PrepareForAuthRestart() {
212 if (!response_.headers.get())
213 return ERR_CONNECTION_RESET;
214
215 // If the connection can't be reused, return
216 // ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH. The request will be retried
217 // at a higher layer.
218 if (!response_.headers->IsKeepAlive() ||
219 !http_stream_parser_->CanFindEndOfResponse() || !socket_->IsConnected()) {
220 socket_->Disconnect();
221 return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
222 }
223
224 // If the auth request had a body, need to drain it before reusing the socket.
225 if (!http_stream_parser_->IsResponseBodyComplete()) {
226 next_state_ = STATE_DRAIN_BODY;
227 drain_buf_ = base::MakeRefCounted<IOBuffer>(kDrainBodyBufferSize);
228 return OK;
229 }
230
231 return DidDrainBodyForAuthRestart();
232 }
233
DidDrainBodyForAuthRestart()234 int HttpProxyClientSocket::DidDrainBodyForAuthRestart() {
235 // Can't reuse the socket if there's still unread data on it.
236 if (!socket_->IsConnectedAndIdle())
237 return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
238
239 next_state_ = STATE_GENERATE_AUTH_TOKEN;
240 is_reused_ = true;
241
242 // Reset the other member variables.
243 drain_buf_ = nullptr;
244 parser_buf_ = nullptr;
245 http_stream_parser_.reset();
246 request_line_.clear();
247 request_headers_.Clear();
248 response_ = HttpResponseInfo();
249 return OK;
250 }
251
DoCallback(int result)252 void HttpProxyClientSocket::DoCallback(int result) {
253 DCHECK_NE(ERR_IO_PENDING, result);
254 DCHECK(!user_callback_.is_null());
255
256 // Since Run() may result in Read being called,
257 // clear user_callback_ up front.
258 std::move(user_callback_).Run(result);
259 }
260
OnIOComplete(int result)261 void HttpProxyClientSocket::OnIOComplete(int result) {
262 DCHECK_NE(STATE_NONE, next_state_);
263 DCHECK_NE(STATE_DONE, next_state_);
264 int rv = DoLoop(result);
265 if (rv != ERR_IO_PENDING)
266 DoCallback(rv);
267 }
268
DoLoop(int last_io_result)269 int HttpProxyClientSocket::DoLoop(int last_io_result) {
270 DCHECK_NE(next_state_, STATE_NONE);
271 DCHECK_NE(next_state_, STATE_DONE);
272 int rv = last_io_result;
273 do {
274 State state = next_state_;
275 next_state_ = STATE_NONE;
276 switch (state) {
277 case STATE_GENERATE_AUTH_TOKEN:
278 DCHECK_EQ(OK, rv);
279 rv = DoGenerateAuthToken();
280 break;
281 case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
282 rv = DoGenerateAuthTokenComplete(rv);
283 break;
284 case STATE_SEND_REQUEST:
285 DCHECK_EQ(OK, rv);
286 net_log_.BeginEvent(
287 NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
288 rv = DoSendRequest();
289 break;
290 case STATE_SEND_REQUEST_COMPLETE:
291 rv = DoSendRequestComplete(rv);
292 net_log_.EndEventWithNetErrorCode(
293 NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
294 break;
295 case STATE_READ_HEADERS:
296 DCHECK_EQ(OK, rv);
297 net_log_.BeginEvent(
298 NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
299 rv = DoReadHeaders();
300 break;
301 case STATE_READ_HEADERS_COMPLETE:
302 rv = DoReadHeadersComplete(rv);
303 net_log_.EndEventWithNetErrorCode(
304 NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
305 break;
306 case STATE_DRAIN_BODY:
307 DCHECK_EQ(OK, rv);
308 rv = DoDrainBody();
309 break;
310 case STATE_DRAIN_BODY_COMPLETE:
311 rv = DoDrainBodyComplete(rv);
312 break;
313 case STATE_DONE:
314 break;
315 default:
316 NOTREACHED() << "bad state";
317 rv = ERR_UNEXPECTED;
318 break;
319 }
320 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
321 next_state_ != STATE_DONE);
322 return rv;
323 }
324
DoGenerateAuthToken()325 int HttpProxyClientSocket::DoGenerateAuthToken() {
326 next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
327 return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_);
328 }
329
DoGenerateAuthTokenComplete(int result)330 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
331 DCHECK_NE(ERR_IO_PENDING, result);
332 if (result == OK)
333 next_state_ = STATE_SEND_REQUEST;
334 return result;
335 }
336
DoSendRequest()337 int HttpProxyClientSocket::DoSendRequest() {
338 next_state_ = STATE_SEND_REQUEST_COMPLETE;
339
340 // This is constructed lazily (instead of within our Start method), so that
341 // we have proxy info available.
342 if (request_line_.empty()) {
343 DCHECK(request_headers_.IsEmpty());
344
345 HttpRequestHeaders extra_headers;
346 if (auth_->HaveAuth())
347 auth_->AddAuthorizationHeader(&extra_headers);
348 // AddAuthorizationHeader() might not have added the header even if
349 // HaveAuth().
350 response_.did_use_http_auth =
351 extra_headers.HasHeader(HttpRequestHeaders::kProxyAuthorization);
352
353 if (proxy_delegate_) {
354 HttpRequestHeaders proxy_delegate_headers;
355 proxy_delegate_->OnBeforeTunnelRequest(proxy_server_,
356 &proxy_delegate_headers);
357 extra_headers.MergeFrom(proxy_delegate_headers);
358 }
359
360 std::string user_agent;
361 if (!request_.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent,
362 &user_agent)) {
363 user_agent.clear();
364 }
365 BuildTunnelRequest(endpoint_, extra_headers, user_agent, &request_line_,
366 &request_headers_);
367
368 NetLogRequestHeaders(net_log_,
369 NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
370 request_line_, &request_headers_);
371 }
372
373 parser_buf_ = base::MakeRefCounted<GrowableIOBuffer>();
374 http_stream_parser_ = std::make_unique<HttpStreamParser>(
375 socket_.get(), is_reused_, &request_, parser_buf_.get(), net_log_);
376 return http_stream_parser_->SendRequest(request_line_, request_headers_,
377 traffic_annotation_, &response_,
378 io_callback_);
379 }
380
DoSendRequestComplete(int result)381 int HttpProxyClientSocket::DoSendRequestComplete(int result) {
382 if (result < 0)
383 return result;
384
385 next_state_ = STATE_READ_HEADERS;
386 return OK;
387 }
388
DoReadHeaders()389 int HttpProxyClientSocket::DoReadHeaders() {
390 next_state_ = STATE_READ_HEADERS_COMPLETE;
391 return http_stream_parser_->ReadResponseHeaders(io_callback_);
392 }
393
DoReadHeadersComplete(int result)394 int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
395 if (result < 0)
396 return result;
397
398 // Require the "HTTP/1.x" status line for SSL CONNECT.
399 if (response_.headers->GetHttpVersion() < HttpVersion(1, 0))
400 return ERR_TUNNEL_CONNECTION_FAILED;
401
402 NetLogResponseHeaders(
403 net_log_, NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
404 response_.headers.get());
405
406 if (proxy_delegate_) {
407 int rv = proxy_delegate_->OnTunnelHeadersReceived(proxy_server_,
408 *response_.headers);
409 if (rv != OK) {
410 DCHECK_NE(ERR_IO_PENDING, rv);
411 return rv;
412 }
413 }
414
415 switch (response_.headers->response_code()) {
416 case 200: // OK
417 if (http_stream_parser_->IsMoreDataBuffered())
418 // The proxy sent extraneous data after the headers.
419 return ERR_TUNNEL_CONNECTION_FAILED;
420
421 next_state_ = STATE_DONE;
422 return OK;
423
424 // We aren't able to CONNECT to the remote host through the proxy. We
425 // need to be very suspicious about the response because an active network
426 // attacker can force us into this state by masquerading as the proxy.
427 // The only safe thing to do here is to fail the connection because our
428 // client is expecting an SSL protected response.
429 // See http://crbug.com/7338.
430
431 case 407: // Proxy Authentication Required
432 // We need this status code to allow proxy authentication. Our
433 // authentication code is smart enough to avoid being tricked by an
434 // active network attacker.
435 // The next state is intentionally not set as it should be STATE_NONE;
436 SanitizeProxyAuth(response_);
437 return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_);
438
439 default:
440 // Ignore response to avoid letting the proxy impersonate the target
441 // server. (See http://crbug.com/137891.)
442 // We lose something by doing this. We have seen proxy 403, 404, and
443 // 501 response bodies that contain a useful error message. For
444 // example, Squid uses a 404 response to report the DNS error: "The
445 // domain name does not exist."
446 return ERR_TUNNEL_CONNECTION_FAILED;
447 }
448 }
449
DoDrainBody()450 int HttpProxyClientSocket::DoDrainBody() {
451 DCHECK(drain_buf_.get());
452 next_state_ = STATE_DRAIN_BODY_COMPLETE;
453 return http_stream_parser_->ReadResponseBody(
454 drain_buf_.get(), kDrainBodyBufferSize, io_callback_);
455 }
456
DoDrainBodyComplete(int result)457 int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
458 if (result < 0)
459 return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
460
461 if (!http_stream_parser_->IsResponseBodyComplete()) {
462 // Keep draining.
463 next_state_ = STATE_DRAIN_BODY;
464 return OK;
465 }
466
467 return DidDrainBodyForAuthRestart();
468 }
469
CheckDone()470 bool HttpProxyClientSocket::CheckDone() {
471 if (next_state_ != STATE_DONE) {
472 // We're trying to read the body of the response but we're still trying
473 // to establish an SSL tunnel through the proxy. We can't read these
474 // bytes when establishing a tunnel because they might be controlled by
475 // an active network attacker. We don't worry about this for HTTP
476 // because an active network attacker can already control HTTP sessions.
477 // We reach this case when the user cancels a 407 proxy auth prompt.
478 // See http://crbug.com/8473.
479 DCHECK_EQ(407, response_.headers->response_code());
480
481 return false;
482 }
483 return true;
484 }
485
486 //----------------------------------------------------------------
487
488 } // namespace net
489