• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_chain.h"
18 #include "net/base/proxy_delegate.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 ProxyChain & proxy_chain,size_t proxy_chain_index,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 ProxyChain& proxy_chain,
39     size_t proxy_chain_index,
40     scoped_refptr<HttpAuthController> http_auth_controller,
41     ProxyDelegate* proxy_delegate,
42     const NetworkTrafficAnnotationTag& traffic_annotation)
43     : io_callback_(base::BindRepeating(&HttpProxyClientSocket::OnIOComplete,
44                                        base::Unretained(this))),
45       user_agent_(user_agent),
46       socket_(std::move(socket)),
47       endpoint_(endpoint),
48       auth_(std::move(http_auth_controller)),
49       proxy_chain_(proxy_chain),
50       proxy_chain_index_(proxy_chain_index),
51       proxy_delegate_(proxy_delegate),
52       traffic_annotation_(traffic_annotation),
53       net_log_(socket_->NetLog()) {
54   // Synthesize the bits of a request that are actually used.
55   request_.url = GURL("https://" + endpoint.ToString());
56   request_.method = "CONNECT";
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 }
132 
GetNegotiatedProtocol() const133 NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
134   // Do not delegate to `socket_`. While `socket_` may negotiate ALPN with the
135   // proxy, this object represents the tunneled TCP connection to the origin.
136   return kProtoUnknown;
137 }
138 
GetSSLInfo(SSLInfo * ssl_info)139 bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
140   // Do not delegate to `socket_`. While `socket_` may connect to the proxy with
141   // TLS, this object represents the tunneled TCP connection to the origin.
142   return false;
143 }
144 
GetTotalReceivedBytes() const145 int64_t HttpProxyClientSocket::GetTotalReceivedBytes() const {
146   return socket_->GetTotalReceivedBytes();
147 }
148 
ApplySocketTag(const SocketTag & tag)149 void HttpProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
150   return socket_->ApplySocketTag(tag);
151 }
152 
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)153 int HttpProxyClientSocket::Read(IOBuffer* buf,
154                                 int buf_len,
155                                 CompletionOnceCallback callback) {
156   DCHECK(user_callback_.is_null());
157   if (!CheckDone())
158     return ERR_TUNNEL_CONNECTION_FAILED;
159 
160   return socket_->Read(buf, buf_len, std::move(callback));
161 }
162 
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)163 int HttpProxyClientSocket::ReadIfReady(IOBuffer* buf,
164                                        int buf_len,
165                                        CompletionOnceCallback callback) {
166   DCHECK(user_callback_.is_null());
167   if (!CheckDone())
168     return ERR_TUNNEL_CONNECTION_FAILED;
169 
170   return socket_->ReadIfReady(buf, buf_len, std::move(callback));
171 }
172 
CancelReadIfReady()173 int HttpProxyClientSocket::CancelReadIfReady() {
174   return socket_->CancelReadIfReady();
175 }
176 
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)177 int HttpProxyClientSocket::Write(
178     IOBuffer* buf,
179     int buf_len,
180     CompletionOnceCallback callback,
181     const NetworkTrafficAnnotationTag& traffic_annotation) {
182   DCHECK_EQ(STATE_DONE, next_state_);
183   DCHECK(user_callback_.is_null());
184 
185   return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation);
186 }
187 
SetReceiveBufferSize(int32_t size)188 int HttpProxyClientSocket::SetReceiveBufferSize(int32_t size) {
189   return socket_->SetReceiveBufferSize(size);
190 }
191 
SetSendBufferSize(int32_t size)192 int HttpProxyClientSocket::SetSendBufferSize(int32_t size) {
193   return socket_->SetSendBufferSize(size);
194 }
195 
GetPeerAddress(IPEndPoint * address) const196 int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
197   return socket_->GetPeerAddress(address);
198 }
199 
GetLocalAddress(IPEndPoint * address) const200 int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
201   return socket_->GetLocalAddress(address);
202 }
203 
PrepareForAuthRestart()204 int HttpProxyClientSocket::PrepareForAuthRestart() {
205   if (!response_.headers.get())
206     return ERR_CONNECTION_RESET;
207 
208   // If the connection can't be reused, return
209   // ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH.  The request will be retried
210   // at a higher layer.
211   if (!response_.headers->IsKeepAlive() ||
212       !http_stream_parser_->CanFindEndOfResponse() || !socket_->IsConnected()) {
213     socket_->Disconnect();
214     return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
215   }
216 
217   // If the auth request had a body, need to drain it before reusing the socket.
218   if (!http_stream_parser_->IsResponseBodyComplete()) {
219     next_state_ = STATE_DRAIN_BODY;
220     drain_buf_ = base::MakeRefCounted<IOBufferWithSize>(kDrainBodyBufferSize);
221     return OK;
222   }
223 
224   return DidDrainBodyForAuthRestart();
225 }
226 
DidDrainBodyForAuthRestart()227 int HttpProxyClientSocket::DidDrainBodyForAuthRestart() {
228   // Can't reuse the socket if there's still unread data on it.
229   if (!socket_->IsConnectedAndIdle())
230     return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
231 
232   next_state_ = STATE_GENERATE_AUTH_TOKEN;
233   is_reused_ = true;
234 
235   // Reset the other member variables.
236   drain_buf_ = nullptr;
237   parser_buf_ = nullptr;
238   http_stream_parser_.reset();
239   request_line_.clear();
240   request_headers_.Clear();
241   response_ = HttpResponseInfo();
242   return OK;
243 }
244 
DoCallback(int result)245 void HttpProxyClientSocket::DoCallback(int result) {
246   DCHECK_NE(ERR_IO_PENDING, result);
247   DCHECK(!user_callback_.is_null());
248 
249   // Since Run() may result in Read being called,
250   // clear user_callback_ up front.
251   std::move(user_callback_).Run(result);
252 }
253 
OnIOComplete(int result)254 void HttpProxyClientSocket::OnIOComplete(int result) {
255   DCHECK_NE(STATE_NONE, next_state_);
256   DCHECK_NE(STATE_DONE, next_state_);
257   int rv = DoLoop(result);
258   if (rv != ERR_IO_PENDING)
259     DoCallback(rv);
260 }
261 
DoLoop(int last_io_result)262 int HttpProxyClientSocket::DoLoop(int last_io_result) {
263   DCHECK_NE(next_state_, STATE_NONE);
264   DCHECK_NE(next_state_, STATE_DONE);
265   int rv = last_io_result;
266   do {
267     State state = next_state_;
268     next_state_ = STATE_NONE;
269     switch (state) {
270       case STATE_GENERATE_AUTH_TOKEN:
271         DCHECK_EQ(OK, rv);
272         rv = DoGenerateAuthToken();
273         break;
274       case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
275         rv = DoGenerateAuthTokenComplete(rv);
276         break;
277       case STATE_SEND_REQUEST:
278         DCHECK_EQ(OK, rv);
279         net_log_.BeginEvent(
280             NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
281         rv = DoSendRequest();
282         break;
283       case STATE_SEND_REQUEST_COMPLETE:
284         rv = DoSendRequestComplete(rv);
285         net_log_.EndEventWithNetErrorCode(
286             NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
287         break;
288       case STATE_READ_HEADERS:
289         DCHECK_EQ(OK, rv);
290         net_log_.BeginEvent(
291             NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
292         rv = DoReadHeaders();
293         break;
294       case STATE_READ_HEADERS_COMPLETE:
295         rv = DoReadHeadersComplete(rv);
296         net_log_.EndEventWithNetErrorCode(
297             NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
298         break;
299       case STATE_DRAIN_BODY:
300         DCHECK_EQ(OK, rv);
301         rv = DoDrainBody();
302         break;
303       case STATE_DRAIN_BODY_COMPLETE:
304         rv = DoDrainBodyComplete(rv);
305         break;
306       case STATE_DONE:
307         break;
308       default:
309         NOTREACHED() << "bad state";
310     }
311   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
312            next_state_ != STATE_DONE);
313   return rv;
314 }
315 
DoGenerateAuthToken()316 int HttpProxyClientSocket::DoGenerateAuthToken() {
317   next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
318   return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_);
319 }
320 
DoGenerateAuthTokenComplete(int result)321 int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
322   DCHECK_NE(ERR_IO_PENDING, result);
323   if (result == OK)
324     next_state_ = STATE_SEND_REQUEST;
325   return result;
326 }
327 
DoSendRequest()328 int HttpProxyClientSocket::DoSendRequest() {
329   next_state_ = STATE_SEND_REQUEST_COMPLETE;
330 
331   // This is constructed lazily (instead of within our Start method), so that
332   // we have proxy info available.
333   if (request_line_.empty()) {
334     DCHECK(request_headers_.IsEmpty());
335 
336     HttpRequestHeaders extra_headers;
337     if (auth_->HaveAuth())
338       auth_->AddAuthorizationHeader(&extra_headers);
339     // AddAuthorizationHeader() might not have added the header even if
340     // HaveAuth().
341     response_.did_use_http_auth =
342         extra_headers.HasHeader(HttpRequestHeaders::kProxyAuthorization);
343 
344     if (proxy_delegate_) {
345       HttpRequestHeaders proxy_delegate_headers;
346       int result = proxy_delegate_->OnBeforeTunnelRequest(
347           proxy_chain_, proxy_chain_index_, &proxy_delegate_headers);
348       if (result < 0) {
349         return result;
350       }
351 
352       extra_headers.MergeFrom(proxy_delegate_headers);
353     }
354 
355     BuildTunnelRequest(endpoint_, extra_headers, user_agent_, &request_line_,
356                        &request_headers_);
357 
358     NetLogRequestHeaders(net_log_,
359                          NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
360                          request_line_, &request_headers_);
361   }
362 
363   parser_buf_ = base::MakeRefCounted<GrowableIOBuffer>();
364   http_stream_parser_ = std::make_unique<HttpStreamParser>(
365       socket_.get(), is_reused_, request_.url, request_.method,
366       /*upload_data_stream=*/nullptr, parser_buf_.get(), net_log_);
367   return http_stream_parser_->SendRequest(request_line_, request_headers_,
368                                           traffic_annotation_, &response_,
369                                           io_callback_);
370 }
371 
DoSendRequestComplete(int result)372 int HttpProxyClientSocket::DoSendRequestComplete(int result) {
373   if (result < 0)
374     return result;
375 
376   next_state_ = STATE_READ_HEADERS;
377   return OK;
378 }
379 
DoReadHeaders()380 int HttpProxyClientSocket::DoReadHeaders() {
381   next_state_ = STATE_READ_HEADERS_COMPLETE;
382   return http_stream_parser_->ReadResponseHeaders(io_callback_);
383 }
384 
DoReadHeadersComplete(int result)385 int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
386   if (result < 0)
387     return result;
388 
389   // Require the "HTTP/1.x" status line for SSL CONNECT.
390   if (response_.headers->GetHttpVersion() < HttpVersion(1, 0))
391     return ERR_TUNNEL_CONNECTION_FAILED;
392 
393   NetLogResponseHeaders(
394       net_log_, NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
395       response_.headers.get());
396 
397   if (proxy_delegate_) {
398     int rv = proxy_delegate_->OnTunnelHeadersReceived(
399         proxy_chain_, proxy_chain_index_, *response_.headers);
400     if (rv != OK) {
401       DCHECK_NE(ERR_IO_PENDING, rv);
402       return rv;
403     }
404   }
405 
406   switch (response_.headers->response_code()) {
407     case 200:  // OK
408       if (http_stream_parser_->IsMoreDataBuffered())
409         // The proxy sent extraneous data after the headers.
410         return ERR_TUNNEL_CONNECTION_FAILED;
411 
412       next_state_ = STATE_DONE;
413       return OK;
414 
415       // We aren't able to CONNECT to the remote host through the proxy.  We
416       // need to be very suspicious about the response because an active network
417       // attacker can force us into this state by masquerading as the proxy.
418       // The only safe thing to do here is to fail the connection because our
419       // client is expecting an SSL protected response.
420       // See http://crbug.com/7338.
421 
422     case 407:  // Proxy Authentication Required
423       // We need this status code to allow proxy authentication.  Our
424       // authentication code is smart enough to avoid being tricked by an
425       // active network attacker.
426       // The next state is intentionally not set as it should be STATE_NONE;
427       SanitizeProxyAuth(response_);
428       return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_);
429 
430     default:
431       // Ignore response to avoid letting the proxy impersonate the target
432       // server.  (See http://crbug.com/137891.)
433       // We lose something by doing this.  We have seen proxy 403, 404, and
434       // 501 response bodies that contain a useful error message.  For
435       // example, Squid uses a 404 response to report the DNS error: "The
436       // domain name does not exist."
437       return ERR_TUNNEL_CONNECTION_FAILED;
438   }
439 }
440 
DoDrainBody()441 int HttpProxyClientSocket::DoDrainBody() {
442   DCHECK(drain_buf_.get());
443   next_state_ = STATE_DRAIN_BODY_COMPLETE;
444   return http_stream_parser_->ReadResponseBody(
445       drain_buf_.get(), kDrainBodyBufferSize, io_callback_);
446 }
447 
DoDrainBodyComplete(int result)448 int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
449   if (result < 0)
450     return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
451 
452   if (!http_stream_parser_->IsResponseBodyComplete()) {
453     // Keep draining.
454     next_state_ = STATE_DRAIN_BODY;
455     return OK;
456   }
457 
458   return DidDrainBodyForAuthRestart();
459 }
460 
CheckDone()461 bool HttpProxyClientSocket::CheckDone() {
462   if (next_state_ != STATE_DONE) {
463     // We're trying to read the body of the response but we're still trying
464     // to establish an SSL tunnel through the proxy.  We can't read these
465     // bytes when establishing a tunnel because they might be controlled by
466     // an active network attacker.  We don't worry about this for HTTP
467     // because an active network attacker can already control HTTP sessions.
468     // We reach this case when the user cancels a 407 proxy auth prompt.
469     // See http://crbug.com/8473.
470     DCHECK_EQ(407, response_.headers->response_code());
471 
472     return false;
473   }
474   return true;
475 }
476 
477 //----------------------------------------------------------------
478 
479 }  // namespace net
480