Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(551)

Side by Side Diff: net/http/http_proxy_client_socket.cc

Issue 9148011: Allow chrome to handle 407 auth challenges to CONNECT requests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_proxy_client_socket.h" 5 #include "net/http/http_proxy_client_socket.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
(...skipping 13 matching lines...) Expand all
24 #include "net/socket/client_socket_handle.h" 24 #include "net/socket/client_socket_handle.h"
25 25
26 namespace net { 26 namespace net {
27 27
28 HttpProxyClientSocket::HttpProxyClientSocket( 28 HttpProxyClientSocket::HttpProxyClientSocket(
29 ClientSocketHandle* transport_socket, 29 ClientSocketHandle* transport_socket,
30 const GURL& request_url, 30 const GURL& request_url,
31 const std::string& user_agent, 31 const std::string& user_agent,
32 const HostPortPair& endpoint, 32 const HostPortPair& endpoint,
33 const HostPortPair& proxy_server, 33 const HostPortPair& proxy_server,
34 HttpAuthCache* http_auth_cache, 34 HttpAuthController* http_auth_controller,
35 HttpAuthHandlerFactory* http_auth_handler_factory,
36 bool tunnel, 35 bool tunnel,
37 bool using_spdy, 36 bool using_spdy,
38 SSLClientSocket::NextProto protocol_negotiated, 37 SSLClientSocket::NextProto protocol_negotiated,
39 bool is_https_proxy) 38 bool is_https_proxy)
40 : ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 39 : ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
41 base::Bind(&HttpProxyClientSocket::OnIOComplete, 40 base::Bind(&HttpProxyClientSocket::OnIOComplete,
42 base::Unretained(this)))), 41 base::Unretained(this)))),
43 next_state_(STATE_NONE), 42 next_state_(STATE_NONE),
44 transport_(transport_socket), 43 transport_(transport_socket),
45 endpoint_(endpoint), 44 endpoint_(endpoint),
46 auth_(tunnel ? 45 auth_(http_auth_controller),
47 new HttpAuthController(HttpAuth::AUTH_PROXY,
48 GURL((is_https_proxy ? "https://" : "http://")
49 + proxy_server.ToString()),
50 http_auth_cache,
51 http_auth_handler_factory)
52 : NULL),
53 tunnel_(tunnel), 46 tunnel_(tunnel),
54 using_spdy_(using_spdy), 47 using_spdy_(using_spdy),
55 protocol_negotiated_(protocol_negotiated), 48 protocol_negotiated_(protocol_negotiated),
56 is_https_proxy_(is_https_proxy), 49 is_https_proxy_(is_https_proxy),
57 net_log_(transport_socket->socket()->NetLog()) { 50 net_log_(transport_socket->socket()->NetLog()) {
58 // Synthesize the bits of a request that we actually use. 51 // Synthesize the bits of a request that we actually use.
59 request_.url = request_url; 52 request_.url = request_url;
60 request_.method = "GET"; 53 request_.method = "GET";
61 if (!user_agent.empty()) 54 if (!user_agent.empty())
62 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 55 request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
63 user_agent); 56 user_agent);
64 } 57 }
65 58
66 HttpProxyClientSocket::~HttpProxyClientSocket() { 59 HttpProxyClientSocket::~HttpProxyClientSocket() {
67 Disconnect(); 60 Disconnect();
68 } 61 }
69 62
63 const
64 scoped_refptr<HttpAuthController>& HttpProxyClientSocket::auth_controller() {
65 return auth_;
66 }
67
70 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) { 68 int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) {
71 DCHECK_EQ(STATE_NONE, next_state_); 69 DCHECK_EQ(STATE_NONE, next_state_);
72 DCHECK(user_callback_.is_null()); 70 DCHECK(user_callback_.is_null());
73 71
74 int rv = PrepareForAuthRestart(); 72 int rv = PrepareForAuthRestart();
75 if (rv != OK) 73 if (rv != OK || next_state_ == STATE_NONE)
76 return rv; 74 return rv;
77 75
78 rv = DoLoop(OK); 76 rv = DoLoop(OK);
79 if (rv == ERR_IO_PENDING) { 77 if (rv == ERR_IO_PENDING) {
80 if (!callback.is_null()) 78 if (!callback.is_null())
81 user_callback_ = callback; 79 user_callback_ = callback;
82 } 80 }
83 81
84 return rv; 82 return rv;
85 } 83 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 // We don't need to drain the response body, so we act as if we had drained 249 // We don't need to drain the response body, so we act as if we had drained
252 // the response body. 250 // the response body.
253 return DidDrainBodyForAuthRestart(keep_alive); 251 return DidDrainBodyForAuthRestart(keep_alive);
254 } 252 }
255 253
256 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) { 254 int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
257 if (keep_alive && transport_->socket()->IsConnectedAndIdle()) { 255 if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
258 next_state_ = STATE_GENERATE_AUTH_TOKEN; 256 next_state_ = STATE_GENERATE_AUTH_TOKEN;
259 transport_->set_is_reused(true); 257 transport_->set_is_reused(true);
260 } else { 258 } else {
261 // This assumes that the underlying transport socket is a TCP socket, 259 next_state_ = STATE_NONE;
vandebo (ex-Chrome) 2012/01/19 20:12:49 Seems like in this case we want to make the functi
Ryan Hamilton 2012/01/19 23:11:19 Done.
262 // since only TCP sockets are restartable.
263 next_state_ = STATE_TCP_RESTART;
vandebo (ex-Chrome) 2012/01/19 20:12:49 You should also tear out the TCP_RESTART states.
Ryan Hamilton 2012/01/19 23:11:19 Done.
264 transport_->socket()->Disconnect();
265 } 260 }
266 261
267 // Reset the other member variables. 262 // Reset the other member variables.
268 drain_buf_ = NULL; 263 drain_buf_ = NULL;
269 parser_buf_ = NULL; 264 parser_buf_ = NULL;
270 http_stream_parser_.reset(); 265 http_stream_parser_.reset();
271 request_line_.clear(); 266 request_line_.clear();
272 request_headers_.Clear(); 267 request_headers_.Clear();
273 response_ = HttpResponseInfo(); 268 response_ = HttpResponseInfo();
274 return OK; 269 return OK;
275 } 270 }
276 271
277 int HttpProxyClientSocket::HandleAuthChallenge() {
278 DCHECK(response_.headers);
279
280 int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
281 response_.auth_challenge = auth_->auth_info();
282 if (rv == OK)
283 return ERR_PROXY_AUTH_REQUESTED;
284
285 return rv;
286 }
287
288 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const { 272 void HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
289 LOG(WARNING) << "Blocked proxy response with status " << response_code 273 LOG(WARNING) << "Blocked proxy response with status " << response_code
290 << " to CONNECT request for " 274 << " to CONNECT request for "
291 << GetHostAndPort(request_.url) << "."; 275 << GetHostAndPort(request_.url) << ".";
292 } 276 }
293 277
294 void HttpProxyClientSocket::DoCallback(int result) { 278 void HttpProxyClientSocket::DoCallback(int result) {
295 DCHECK_NE(ERR_IO_PENDING, result); 279 DCHECK_NE(ERR_IO_PENDING, result);
296 DCHECK(!user_callback_.is_null()); 280 DCHECK(!user_callback_.is_null());
297 281
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 // need to be very suspicious about the response because an active network 436 // need to be very suspicious about the response because an active network
453 // attacker can force us into this state by masquerading as the proxy. 437 // attacker can force us into this state by masquerading as the proxy.
454 // The only safe thing to do here is to fail the connection because our 438 // The only safe thing to do here is to fail the connection because our
455 // client is expecting an SSL protected response. 439 // client is expecting an SSL protected response.
456 // See http://crbug.com/7338. 440 // See http://crbug.com/7338.
457 case 407: // Proxy Authentication Required 441 case 407: // Proxy Authentication Required
458 // We need this status code to allow proxy authentication. Our 442 // We need this status code to allow proxy authentication. Our
459 // authentication code is smart enough to avoid being tricked by an 443 // authentication code is smart enough to avoid being tricked by an
460 // active network attacker. 444 // active network attacker.
461 // The next state is intentionally not set as it should be STATE_NONE; 445 // The next state is intentionally not set as it should be STATE_NONE;
462 return HandleAuthChallenge(); 446 return HandleAuthChallenge(auth_, &response_, net_log_);
463 447
464 default: 448 default:
465 if (is_https_proxy_) 449 if (is_https_proxy_)
466 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE; 450 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
467 // For all other status codes, we conservatively fail the CONNECT 451 // For all other status codes, we conservatively fail the CONNECT
468 // request. 452 // request.
469 // We lose something by doing this. We have seen proxy 403, 404, and 453 // We lose something by doing this. We have seen proxy 403, 404, and
470 // 501 response bodies that contain a useful error message. For 454 // 501 response bodies that contain a useful error message. For
471 // example, Squid uses a 404 response to report the DNS error: "The 455 // example, Squid uses a 404 response to report the DNS error: "The
472 // domain name does not exist." 456 // domain name does not exist."
(...skipping 30 matching lines...) Expand all
503 487
504 int HttpProxyClientSocket::DoTCPRestartComplete(int result) { 488 int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
505 if (result != OK) 489 if (result != OK)
506 return result; 490 return result;
507 491
508 next_state_ = STATE_GENERATE_AUTH_TOKEN; 492 next_state_ = STATE_GENERATE_AUTH_TOKEN;
509 return result; 493 return result;
510 } 494 }
511 495
512 } // namespace net 496 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698