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

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

Issue 2808020: Create HttpAuthController. (Closed)
Patch Set: Fix mem leak Created 10 years, 6 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
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_network_transaction.h" 5 #include "net/http/http_network_transaction.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/field_trial.h" 8 #include "base/field_trial.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/histogram.h" 10 #include "base/histogram.h"
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 pac_request_(NULL), 289 pac_request_(NULL),
290 connection_(new ClientSocketHandle), 290 connection_(new ClientSocketHandle),
291 reused_socket_(false), 291 reused_socket_(false),
292 headers_valid_(false), 292 headers_valid_(false),
293 logged_response_time_(false), 293 logged_response_time_(false),
294 using_ssl_(false), 294 using_ssl_(false),
295 using_spdy_(false), 295 using_spdy_(false),
296 alternate_protocol_mode_( 296 alternate_protocol_mode_(
297 g_use_alternate_protocols ? kUnspecified : 297 g_use_alternate_protocols ? kUnspecified :
298 kDoNotUseAlternateProtocol), 298 kDoNotUseAlternateProtocol),
299 embedded_identity_used_(false),
300 default_credentials_used_(false),
301 read_buf_len_(0), 299 read_buf_len_(0),
302 next_state_(STATE_NONE) { 300 next_state_(STATE_NONE) {
303 session->ssl_config_service()->GetSSLConfig(&ssl_config_); 301 session->ssl_config_service()->GetSSLConfig(&ssl_config_);
304 if (g_next_protos) 302 if (g_next_protos)
305 ssl_config_.next_protos = *g_next_protos; 303 ssl_config_.next_protos = *g_next_protos;
306 if (!g_tls_intolerant_servers) 304 if (!g_tls_intolerant_servers)
307 g_tls_intolerant_servers = new std::set<std::string>; 305 g_tls_intolerant_servers = new std::set<std::string>;
308 } 306 }
309 307
310 // static 308 // static
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 388
391 int HttpNetworkTransaction::RestartWithAuth( 389 int HttpNetworkTransaction::RestartWithAuth(
392 const std::wstring& username, 390 const std::wstring& username,
393 const std::wstring& password, 391 const std::wstring& password,
394 CompletionCallback* callback) { 392 CompletionCallback* callback) {
395 HttpAuth::Target target = pending_auth_target_; 393 HttpAuth::Target target = pending_auth_target_;
396 if (target == HttpAuth::AUTH_NONE) { 394 if (target == HttpAuth::AUTH_NONE) {
397 NOTREACHED(); 395 NOTREACHED();
398 return ERR_UNEXPECTED; 396 return ERR_UNEXPECTED;
399 } 397 }
400
401 pending_auth_target_ = HttpAuth::AUTH_NONE; 398 pending_auth_target_ = HttpAuth::AUTH_NONE;
402 399
403 DCHECK(auth_identity_[target].invalid || 400 auth_controllers_[target]->ResetAuth(username, password);
404 (username.empty() && password.empty()));
405
406 if (auth_identity_[target].invalid) {
407 // Update the username/password.
408 auth_identity_[target].source = HttpAuth::IDENT_SRC_EXTERNAL;
409 auth_identity_[target].invalid = false;
410 auth_identity_[target].username = username;
411 auth_identity_[target].password = password;
412 }
413 401
414 PrepareForAuthRestart(target); 402 PrepareForAuthRestart(target);
415 403
416 DCHECK(user_callback_ == NULL); 404 DCHECK(user_callback_ == NULL);
417 int rv = DoLoop(OK); 405 int rv = DoLoop(OK);
418 if (rv == ERR_IO_PENDING) 406 if (rv == ERR_IO_PENDING)
419 user_callback_ = callback; 407 user_callback_ = callback;
420 408
421 return rv; 409 return rv;
422 } 410 }
423 411
424 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { 412 void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
425 DCHECK(HaveAuth(target)); 413 DCHECK(HaveAuth(target));
426 DCHECK(auth_identity_[target].source != HttpAuth::IDENT_SRC_PATH_LOOKUP);
427
428 // Add the auth entry to the cache before restarting. We don't know whether
429 // the identity is valid yet, but if it is valid we want other transactions
430 // to know about it. If an entry for (origin, handler->realm()) already
431 // exists, we update it.
432 //
433 // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE or
434 // HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS, auth_identity_[target] contains
435 // no identity because identity is not required yet or we're using default
436 // credentials.
437 //
438 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
439 // round 1 and round 2, which is redundant but correct. It would be nice
440 // to add an auth entry to the cache only once, preferrably in round 1.
441 // See http://crbug.com/21015.
442 switch (auth_identity_[target].source) {
443 case HttpAuth::IDENT_SRC_NONE:
444 case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS:
445 break;
446 default:
447 session_->auth_cache()->Add(
448 AuthOrigin(target),
449 auth_handler_[target]->realm(),
450 auth_handler_[target]->scheme(),
451 auth_handler_[target]->challenge(),
452 auth_identity_[target].username,
453 auth_identity_[target].password,
454 AuthPath(target));
455 break;
456 }
457
458 bool keep_alive = false; 414 bool keep_alive = false;
459 // Even if the server says the connection is keep-alive, we have to be 415 // Even if the server says the connection is keep-alive, we have to be
460 // able to find the end of each response in order to reuse the connection. 416 // able to find the end of each response in order to reuse the connection.
461 if (GetResponseHeaders()->IsKeepAlive() && 417 if (GetResponseHeaders()->IsKeepAlive() &&
462 http_stream_->CanFindEndOfResponse()) { 418 http_stream_->CanFindEndOfResponse()) {
463 // If the response body hasn't been completely read, we need to drain 419 // If the response body hasn't been completely read, we need to drain
464 // it first. 420 // it first.
465 if (!http_stream_->IsResponseBodyComplete()) { 421 if (!http_stream_->IsResponseBodyComplete()) {
466 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART; 422 next_state_ = STATE_DRAIN_BODY_FOR_AUTH_RESTART;
467 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket. 423 read_buf_ = new IOBuffer(kDrainBodyBufferSize); // A bit bucket.
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 } 805 }
850 806
851 next_state_ = STATE_INIT_CONNECTION; 807 next_state_ = STATE_INIT_CONNECTION;
852 return OK; 808 return OK;
853 } 809 }
854 810
855 int HttpNetworkTransaction::DoInitConnection() { 811 int HttpNetworkTransaction::DoInitConnection() {
856 DCHECK(!connection_->is_initialized()); 812 DCHECK(!connection_->is_initialized());
857 DCHECK(proxy_info_.proxy_server().is_valid()); 813 DCHECK(proxy_info_.proxy_server().is_valid());
858 814
815 // Now that the proxy server has been resolved, create the auth_controllers_.
816 for (int i = 0; i < HttpAuth::AUTH_NUM_TARGETS; i++) {
817 HttpAuth::Target target = static_cast<HttpAuth::Target>(i);
818 if (!auth_controllers_[target].get())
819 auth_controllers_[target].reset(new HttpAuthController(target,
820 AuthURL(target),
821 session_,
822 net_log_));
823 }
824
859 next_state_ = STATE_INIT_CONNECTION_COMPLETE; 825 next_state_ = STATE_INIT_CONNECTION_COMPLETE;
860 826
861 using_ssl_ = request_->url.SchemeIs("https") || 827 using_ssl_ = request_->url.SchemeIs("https") ||
862 (alternate_protocol_mode_ == kUsingAlternateProtocol && 828 (alternate_protocol_mode_ == kUsingAlternateProtocol &&
863 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1); 829 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_1);
864 830
865 using_spdy_ = false; 831 using_spdy_ = false;
866 832
867 // Build the string used to uniquely identify connections of this type. 833 // Build the string used to uniquely identify connections of this type.
868 // Determine the host and port to connect to. 834 // Determine the host and port to connect to.
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 962
997 void HttpNetworkTransaction::ClearTunnelState() { 963 void HttpNetworkTransaction::ClearTunnelState() {
998 http_stream_.reset(); 964 http_stream_.reset();
999 request_headers_.clear(); 965 request_headers_.clear();
1000 response_ = HttpResponseInfo(); 966 response_ = HttpResponseInfo();
1001 headers_valid_ = false; 967 headers_valid_ = false;
1002 } 968 }
1003 969
1004 int HttpNetworkTransaction::DoTunnelGenerateAuthToken() { 970 int HttpNetworkTransaction::DoTunnelGenerateAuthToken() {
1005 next_state_ = STATE_TUNNEL_GENERATE_AUTH_TOKEN_COMPLETE; 971 next_state_ = STATE_TUNNEL_GENERATE_AUTH_TOKEN_COMPLETE;
1006 return MaybeGenerateAuthToken(HttpAuth::AUTH_PROXY); 972 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
973 request_, &io_callback_);
1007 } 974 }
1008 975
1009 int HttpNetworkTransaction::DoTunnelGenerateAuthTokenComplete(int rv) { 976 int HttpNetworkTransaction::DoTunnelGenerateAuthTokenComplete(int rv) {
1010 DCHECK_NE(ERR_IO_PENDING, rv); 977 DCHECK_NE(ERR_IO_PENDING, rv);
1011 if (rv == OK) 978 if (rv == OK)
1012 next_state_ = STATE_TUNNEL_SEND_REQUEST; 979 next_state_ = STATE_TUNNEL_SEND_REQUEST;
1013 return rv; 980 return rv;
1014 } 981 }
1015 982
1016 int HttpNetworkTransaction::DoTunnelSendRequest() { 983 int HttpNetworkTransaction::DoTunnelSendRequest() {
1017 next_state_ = STATE_TUNNEL_SEND_REQUEST_COMPLETE; 984 next_state_ = STATE_TUNNEL_SEND_REQUEST_COMPLETE;
1018 985
1019 // This is constructed lazily (instead of within our Start method), so that 986 // This is constructed lazily (instead of within our Start method), so that
1020 // we have proxy info available. 987 // we have proxy info available.
1021 if (request_headers_.empty()) { 988 if (request_headers_.empty()) {
1022 HttpRequestHeaders authorization_headers; 989 HttpRequestHeaders authorization_headers;
1023 if (HaveAuth(HttpAuth::AUTH_PROXY)) 990 if (HaveAuth(HttpAuth::AUTH_PROXY))
1024 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); 991 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
992 &authorization_headers);
1025 std::string request_line; 993 std::string request_line;
1026 HttpRequestHeaders request_headers; 994 HttpRequestHeaders request_headers;
1027 BuildTunnelRequest(request_, authorization_headers, endpoint_, 995 BuildTunnelRequest(request_, authorization_headers, endpoint_,
1028 &request_line, &request_headers); 996 &request_line, &request_headers);
1029 if (net_log_.HasListener()) { 997 if (net_log_.HasListener()) {
1030 net_log_.AddEvent( 998 net_log_.AddEvent(
1031 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 999 NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1032 new NetLogHttpRequestParameter( 1000 new NetLogHttpRequestParameter(
1033 request_line, request_headers)); 1001 request_line, request_headers));
1034 } 1002 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 } else { 1174 } else {
1207 result = HandleSSLHandshakeError(result); 1175 result = HandleSSLHandshakeError(result);
1208 } 1176 }
1209 return result; 1177 return result;
1210 } 1178 }
1211 1179
1212 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { 1180 int HttpNetworkTransaction::DoGenerateProxyAuthToken() {
1213 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; 1181 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE;
1214 if (!ShouldApplyProxyAuth()) 1182 if (!ShouldApplyProxyAuth())
1215 return OK; 1183 return OK;
1216 return MaybeGenerateAuthToken(HttpAuth::AUTH_PROXY); 1184 return auth_controllers_[HttpAuth::AUTH_PROXY]->MaybeGenerateAuthToken(
1185 request_, &io_callback_);
1217 } 1186 }
1218 1187
1219 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) { 1188 int HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(int rv) {
1220 DCHECK_NE(ERR_IO_PENDING, rv); 1189 DCHECK_NE(ERR_IO_PENDING, rv);
1221 if (rv == OK) 1190 if (rv == OK)
1222 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN; 1191 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN;
1223 return rv; 1192 return rv;
1224 } 1193 }
1225 1194
1226 int HttpNetworkTransaction::DoGenerateServerAuthToken() { 1195 int HttpNetworkTransaction::DoGenerateServerAuthToken() {
1227 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE; 1196 next_state_ = STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE;
1228 if (!ShouldApplyServerAuth()) 1197 if (!ShouldApplyServerAuth())
1229 return OK; 1198 return OK;
1230 return MaybeGenerateAuthToken(HttpAuth::AUTH_SERVER); 1199 return auth_controllers_[HttpAuth::AUTH_SERVER]->MaybeGenerateAuthToken(
1200 request_, &io_callback_);
1231 } 1201 }
1232 1202
1233 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) { 1203 int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
1234 DCHECK_NE(ERR_IO_PENDING, rv); 1204 DCHECK_NE(ERR_IO_PENDING, rv);
1235 if (rv == OK) 1205 if (rv == OK)
1236 next_state_ = STATE_SEND_REQUEST; 1206 next_state_ = STATE_SEND_REQUEST;
1237 return rv; 1207 return rv;
1238 } 1208 }
1239 1209
1240 int HttpNetworkTransaction::DoSendRequest() { 1210 int HttpNetworkTransaction::DoSendRequest() {
(...skipping 11 matching lines...) Expand all
1252 // we have proxy info available. 1222 // we have proxy info available.
1253 if (request_headers_.empty()) { 1223 if (request_headers_.empty()) {
1254 // Figure out if we can/should add Proxy-Authentication & Authentication 1224 // Figure out if we can/should add Proxy-Authentication & Authentication
1255 // headers. 1225 // headers.
1256 HttpRequestHeaders authorization_headers; 1226 HttpRequestHeaders authorization_headers;
1257 bool have_proxy_auth = (ShouldApplyProxyAuth() && 1227 bool have_proxy_auth = (ShouldApplyProxyAuth() &&
1258 HaveAuth(HttpAuth::AUTH_PROXY)); 1228 HaveAuth(HttpAuth::AUTH_PROXY));
1259 bool have_server_auth = (ShouldApplyServerAuth() && 1229 bool have_server_auth = (ShouldApplyServerAuth() &&
1260 HaveAuth(HttpAuth::AUTH_SERVER)); 1230 HaveAuth(HttpAuth::AUTH_SERVER));
1261 if (have_proxy_auth) 1231 if (have_proxy_auth)
1262 AddAuthorizationHeader(HttpAuth::AUTH_PROXY, &authorization_headers); 1232 auth_controllers_[HttpAuth::AUTH_PROXY]->AddAuthorizationHeader(
1233 &authorization_headers);
1263 if (have_server_auth) 1234 if (have_server_auth)
1264 AddAuthorizationHeader(HttpAuth::AUTH_SERVER, &authorization_headers); 1235 auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader(
1236 &authorization_headers);
1265 std::string request_line; 1237 std::string request_line;
1266 HttpRequestHeaders request_headers; 1238 HttpRequestHeaders request_headers;
1267 BuildRequestHeaders(request_, authorization_headers, request_body, 1239 BuildRequestHeaders(request_, authorization_headers, request_body,
1268 !using_ssl_ && proxy_info_.is_http(), &request_line, 1240 !using_ssl_ && proxy_info_.is_http(), &request_line,
1269 &request_headers); 1241 &request_headers);
1270 1242
1271 if (session_->network_delegate()) 1243 if (session_->network_delegate())
1272 session_->network_delegate()->OnSendHttpRequest(&request_headers); 1244 session_->network_delegate()->OnSendHttpRequest(&request_headers);
1273 1245
1274 if (net_log_.HasListener()) { 1246 if (net_log_.HasListener()) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 SSLClientSocket* ssl_socket = 1374 SSLClientSocket* ssl_socket =
1403 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1375 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1404 ssl_socket->GetSSLInfo(&response_.ssl_info); 1376 ssl_socket->GetSSLInfo(&response_.ssl_info);
1405 } 1377 }
1406 1378
1407 headers_valid_ = true; 1379 headers_valid_ = true;
1408 return OK; 1380 return OK;
1409 } 1381 }
1410 1382
1411 int HttpNetworkTransaction::DoResolveCanonicalName() { 1383 int HttpNetworkTransaction::DoResolveCanonicalName() {
1412 DCHECK(auth_handler_[pending_auth_target_].get()); 1384 DCHECK(auth_controllers_[pending_auth_target_].get());
1413 next_state_ = STATE_RESOLVE_CANONICAL_NAME_COMPLETE; 1385 next_state_ = STATE_RESOLVE_CANONICAL_NAME_COMPLETE;
1414 return auth_handler_[pending_auth_target_]-> 1386 return auth_controllers_[pending_auth_target_]->ResolveCanonicalName(
1415 ResolveCanonicalName(session_->host_resolver(), &io_callback_); 1387 &io_callback_);
1416 } 1388 }
1417 1389
1418 int HttpNetworkTransaction::DoResolveCanonicalNameComplete(int result) { 1390 int HttpNetworkTransaction::DoResolveCanonicalNameComplete(int result) {
1419 // The STATE_RESOLVE_CANONICAL_NAME state ends the Start sequence when the 1391 // The STATE_RESOLVE_CANONICAL_NAME state ends the Start sequence when the
1420 // canonical name of the server needs to be determined. Normally 1392 // canonical name of the server needs to be determined. Normally
1421 // DoReadHeadersComplete completes the sequence. The next state is 1393 // DoReadHeadersComplete completes the sequence. The next state is
1422 // intentionally not set as it should be STATE_NONE; 1394 // intentionally not set as it should be STATE_NONE;
1423 DCHECK_EQ(STATE_NONE, next_state_); 1395 DCHECK_EQ(STATE_NONE, next_state_);
1424 return result; 1396 return result;
1425 } 1397 }
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1964 } 1936 }
1965 1937
1966 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { 1938 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const {
1967 return !using_ssl_ && proxy_info_.is_http(); 1939 return !using_ssl_ && proxy_info_.is_http();
1968 } 1940 }
1969 1941
1970 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { 1942 bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
1971 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); 1943 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
1972 } 1944 }
1973 1945
1974 int HttpNetworkTransaction::MaybeGenerateAuthToken(HttpAuth::Target target) {
1975 bool needs_auth = HaveAuth(target) || SelectPreemptiveAuth(target);
1976 if (!needs_auth)
1977 return OK;
1978 const std::wstring* username = NULL;
1979 const std::wstring* password = NULL;
1980 const HttpAuth::Identity& identity = auth_identity_[target];
1981 if (identity.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) {
1982 username = &identity.username;
1983 password = &identity.password;
1984 }
1985 DCHECK(auth_token_[target].empty());
1986 return auth_handler_[target]->GenerateAuthToken(
1987 username, password, request_, &io_callback_, &auth_token_[target]);
1988 }
1989
1990 void HttpNetworkTransaction::AddAuthorizationHeader(
1991 HttpAuth::Target target, HttpRequestHeaders* authorization_headers) {
1992 DCHECK(HaveAuth(target));
1993 DCHECK(!auth_token_[target].empty());
1994 authorization_headers->SetHeader(
1995 HttpAuth::GetAuthorizationHeaderName(target),
1996 auth_token_[target]);
1997 auth_token_[target].clear();
1998 }
1999
2000 GURL HttpNetworkTransaction::AuthOrigin(HttpAuth::Target target) const {
2001 GURL origin = PossiblyInvalidAuthOrigin(target);
2002 DCHECK(origin.is_valid());
2003 return origin;
2004 }
2005
2006 GURL HttpNetworkTransaction::PossiblyInvalidAuthOrigin(
2007 HttpAuth::Target target) const {
2008 switch (target) {
2009 case HttpAuth::AUTH_PROXY:
2010 if (!proxy_info_.proxy_server().is_valid() ||
2011 proxy_info_.proxy_server().is_direct()) {
2012 return GURL(); // There is no proxy server.
2013 }
2014 return GURL("http://" + proxy_info_.proxy_server().host_and_port());
2015 case HttpAuth::AUTH_SERVER:
2016 return request_->url.GetOrigin();
2017 default:
2018 return GURL();
2019 }
2020 }
2021
2022 std::string HttpNetworkTransaction::AuthPath(HttpAuth::Target target)
2023 const {
2024 // Proxy authentication realms apply to all paths. So we will use
2025 // empty string in place of an absolute path.
2026 return target == HttpAuth::AUTH_PROXY ?
2027 std::string() : request_->url.path();
2028 }
2029
2030 // static
2031 std::string HttpNetworkTransaction::AuthTargetString(
2032 HttpAuth::Target target) {
2033 return target == HttpAuth::AUTH_PROXY ? "proxy" : "server";
2034 }
2035
2036 void HttpNetworkTransaction::InvalidateRejectedAuthFromCache(
2037 HttpAuth::Target target,
2038 const GURL& auth_origin) {
2039 DCHECK(HaveAuth(target));
2040
2041 // TODO(eroman): this short-circuit can be relaxed. If the realm of
2042 // the preemptively used auth entry matches the realm of the subsequent
2043 // challenge, then we can invalidate the preemptively used entry.
2044 // Otherwise as-is we may send the failed credentials one extra time.
2045 if (auth_identity_[target].source == HttpAuth::IDENT_SRC_PATH_LOOKUP)
2046 return;
2047
2048 // Clear the cache entry for the identity we just failed on.
2049 // Note: we require the username/password to match before invalidating
2050 // since the entry in the cache may be newer than what we used last time.
2051 session_->auth_cache()->Remove(auth_origin,
2052 auth_handler_[target]->realm(),
2053 auth_handler_[target]->scheme(),
2054 auth_identity_[target].username,
2055 auth_identity_[target].password);
2056 }
2057
2058 bool HttpNetworkTransaction::SelectPreemptiveAuth(HttpAuth::Target target) {
2059 DCHECK(!HaveAuth(target));
2060
2061 // Don't do preemptive authorization if the URL contains a username/password,
2062 // since we must first be challenged in order to use the URL's identity.
2063 if (request_->url.has_username())
2064 return false;
2065
2066 // SelectPreemptiveAuth() is on the critical path for each request, so it
2067 // is expected to be fast. LookupByPath() is fast in the common case, since
2068 // the number of http auth cache entries is expected to be very small.
2069 // (For most users in fact, it will be 0.)
2070 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath(
2071 AuthOrigin(target), AuthPath(target));
2072 if (!entry)
2073 return false;
2074
2075 // Try to create a handler using the previous auth challenge.
2076 scoped_ptr<HttpAuthHandler> handler_preemptive;
2077 int rv_create = session_->http_auth_handler_factory()->
2078 CreatePreemptiveAuthHandlerFromString(
2079 entry->auth_challenge(), target, AuthOrigin(target),
2080 entry->IncrementNonceCount(), net_log_, &handler_preemptive);
2081 if (rv_create != OK)
2082 return false;
2083
2084 // Set the state
2085 auth_identity_[target].source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
2086 auth_identity_[target].invalid = false;
2087 auth_identity_[target].username = entry->username();
2088 auth_identity_[target].password = entry->password();
2089 auth_handler_[target].swap(handler_preemptive);
2090 return true;
2091 }
2092
2093 bool HttpNetworkTransaction::SelectNextAuthIdentityToTry(
2094 HttpAuth::Target target,
2095 const GURL& auth_origin) {
2096 DCHECK(auth_handler_[target].get());
2097 DCHECK(auth_identity_[target].invalid);
2098
2099 // Try to use the username/password encoded into the URL first.
2100 if (target == HttpAuth::AUTH_SERVER && request_->url.has_username() &&
2101 !embedded_identity_used_) {
2102 auth_identity_[target].source = HttpAuth::IDENT_SRC_URL;
2103 auth_identity_[target].invalid = false;
2104 // Extract the username:password from the URL.
2105 GetIdentityFromURL(request_->url,
2106 &auth_identity_[target].username,
2107 &auth_identity_[target].password);
2108 embedded_identity_used_ = true;
2109 // TODO(eroman): If the password is blank, should we also try combining
2110 // with a password from the cache?
2111 return true;
2112 }
2113
2114 // Check the auth cache for a realm entry.
2115 HttpAuthCache::Entry* entry =
2116 session_->auth_cache()->Lookup(auth_origin, auth_handler_[target]->realm(),
2117 auth_handler_[target]->scheme());
2118
2119 if (entry) {
2120 auth_identity_[target].source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
2121 auth_identity_[target].invalid = false;
2122 auth_identity_[target].username = entry->username();
2123 auth_identity_[target].password = entry->password();
2124 return true;
2125 }
2126
2127 // Use default credentials (single sign on) if this is the first attempt
2128 // at identity. Do not allow multiple times as it will infinite loop.
2129 // We use default credentials after checking the auth cache so that if
2130 // single sign-on doesn't work, we won't try default credentials for future
2131 // transactions.
2132 if (!default_credentials_used_ &&
2133 auth_handler_[target]->AllowsDefaultCredentials()) {
2134 auth_identity_[target].source = HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS;
2135 auth_identity_[target].invalid = false;
2136 default_credentials_used_ = true;
2137 return true;
2138 }
2139
2140 return false;
2141 }
2142
2143 std::string HttpNetworkTransaction::AuthChallengeLogMessage() const {
2144 std::string msg;
2145 std::string header_val;
2146 void* iter = NULL;
2147 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
2148 while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) {
2149 msg.append("\n Has header Proxy-Authenticate: ");
2150 msg.append(header_val);
2151 }
2152
2153 iter = NULL;
2154 while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) {
2155 msg.append("\n Has header WWW-Authenticate: ");
2156 msg.append(header_val);
2157 }
2158
2159 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate
2160 // authentication with a "Proxy-Support: Session-Based-Authentication"
2161 // response header.
2162 iter = NULL;
2163 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) {
2164 msg.append("\n Has header Proxy-Support: ");
2165 msg.append(header_val);
2166 }
2167
2168 return msg;
2169 }
2170
2171 int HttpNetworkTransaction::HandleAuthChallenge(bool establishing_tunnel) { 1946 int HttpNetworkTransaction::HandleAuthChallenge(bool establishing_tunnel) {
2172 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders(); 1947 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
2173 DCHECK(headers); 1948 DCHECK(headers);
2174 1949
2175 int status = headers->response_code(); 1950 int status = headers->response_code();
2176 if (status != 401 && status != 407) 1951 if (status != 401 && status != 407)
2177 return OK; 1952 return OK;
2178 HttpAuth::Target target = status == 407 ? 1953 HttpAuth::Target target = status == 407 ?
2179 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; 1954 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
2180 GURL auth_origin = PossiblyInvalidAuthOrigin(target);
2181
2182 LOG(INFO) << "The " << AuthTargetString(target) << " "
2183 << auth_origin << " requested auth"
2184 << AuthChallengeLogMessage();
2185
2186 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct()) 1955 if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
2187 return ERR_UNEXPECTED_PROXY_AUTH; 1956 return ERR_UNEXPECTED_PROXY_AUTH;
2188 DCHECK(auth_origin.is_valid());
2189 1957
2190 // The auth we tried just failed, hence it can't be valid. Remove it from 1958 int rv = auth_controllers_[target]->HandleAuthChallenge(headers,
2191 // the cache so it won't be used again. 1959 request_->load_flags,
2192 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round 1960 establishing_tunnel);
2193 // auth sequence, the server may fail the auth in round 1 if our first 1961 if (auth_controllers_[target]->HaveAuthHandler())
2194 // authorization header is broken. We should inspect response_.headers to 1962 pending_auth_target_ = target;
2195 // determine if the server already failed the auth or wants us to continue. 1963
2196 // See http://crbug.com/21015. 1964 scoped_refptr<AuthChallengeInfo> auth_info =
2197 if (HaveAuth(target) && auth_handler_[target]->IsFinalRound()) { 1965 auth_controllers_[target]->auth_info();
2198 InvalidateRejectedAuthFromCache(target, auth_origin); 1966 if (auth_info.get())
2199 auth_handler_[target].reset(); 1967 response_.auth_challenge = auth_info;
2200 auth_identity_[target] = HttpAuth::Identity(); 1968
1969 if (rv == ERR_AUTH_NEEDS_CANONICAL_NAME) {
1970 next_state_ = STATE_RESOLVE_CANONICAL_NAME;
1971 rv = OK;
2201 } 1972 }
2202 1973
2203 auth_identity_[target].invalid = true; 1974 return rv;
2204
2205 if (target != HttpAuth::AUTH_SERVER ||
2206 !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA)) {
2207 // Find the best authentication challenge that we support.
2208 HttpAuth::ChooseBestChallenge(session_->http_auth_handler_factory(),
2209 headers, target, auth_origin, net_log_,
2210 &auth_handler_[target]);
2211 }
2212
2213 if (!auth_handler_[target].get()) {
2214 if (establishing_tunnel) {
2215 LOG(ERROR) << "Can't perform auth to the " << AuthTargetString(target)
2216 << " " << auth_origin << " when establishing a tunnel"
2217 << AuthChallengeLogMessage();
2218
2219 // We are establishing a tunnel, we can't show the error page because an
2220 // active network attacker could control its contents. Instead, we just
2221 // fail to establish the tunnel.
2222 DCHECK(target == HttpAuth::AUTH_PROXY);
2223 return ERR_PROXY_AUTH_REQUESTED;
2224 }
2225 // We found no supported challenge -- let the transaction continue
2226 // so we end up displaying the error page.
2227 return OK;
2228 }
2229
2230 if (auth_handler_[target]->NeedsIdentity()) {
2231 // Pick a new auth identity to try, by looking to the URL and auth cache.
2232 // If an identity to try is found, it is saved to auth_identity_[target].
2233 SelectNextAuthIdentityToTry(target, auth_origin);
2234 } else {
2235 // Proceed with the existing identity or a null identity.
2236 //
2237 // TODO(wtc): Add a safeguard against infinite transaction restarts, if
2238 // the server keeps returning "NTLM".
2239 auth_identity_[target].invalid = false;
2240 }
2241
2242 // Make a note that we are waiting for auth. This variable is inspected
2243 // when the client calls RestartWithAuth() to pick up where we left off.
2244 pending_auth_target_ = target;
2245
2246 if (auth_identity_[target].invalid) {
2247 // We have exhausted all identity possibilities, all we can do now is
2248 // pass the challenge information back to the client.
2249 PopulateAuthChallenge(target, auth_origin);
2250 }
2251
2252 // SPN determination (for Negotiate) requires a DNS lookup to find the
2253 // canonical name. This needs to be done asynchronously to prevent blocking
2254 // the IO thread.
2255 if (auth_handler_[target]->NeedsCanonicalName())
2256 next_state_ = STATE_RESOLVE_CANONICAL_NAME;
2257
2258 return OK;
2259 } 1975 }
2260 1976
2261 void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target, 1977 GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
2262 const GURL& auth_origin) { 1978 switch (target) {
2263 // Populates response_.auth_challenge with the authentication challenge info. 1979 case HttpAuth::AUTH_PROXY:
2264 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). 1980 if (!proxy_info_.proxy_server().is_valid() ||
2265 1981 proxy_info_.proxy_server().is_direct()) {
2266 AuthChallengeInfo* auth_info = new AuthChallengeInfo; 1982 return GURL(); // There is no proxy server.
2267 auth_info->is_proxy = target == HttpAuth::AUTH_PROXY; 1983 }
2268 auth_info->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin)); 1984 return GURL("http://" + proxy_info_.proxy_server().host_and_port());
2269 auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme()); 1985 case HttpAuth::AUTH_SERVER:
2270 // TODO(eroman): decode realm according to RFC 2047. 1986 return request_->url;
2271 auth_info->realm = ASCIIToWide(auth_handler_[target]->realm()); 1987 default:
2272 response_.auth_challenge = auth_info; 1988 return GURL();
1989 }
2273 } 1990 }
2274 1991
2275 void HttpNetworkTransaction::MarkBrokenAlternateProtocolAndFallback() { 1992 void HttpNetworkTransaction::MarkBrokenAlternateProtocolAndFallback() {
2276 // We have to: 1993 // We have to:
2277 // * Reset the endpoint to be the unmodified URL specified destination. 1994 // * Reset the endpoint to be the unmodified URL specified destination.
2278 // * Mark the endpoint as broken so we don't try again. 1995 // * Mark the endpoint as broken so we don't try again.
2279 // * Set the alternate protocol mode to kDoNotUseAlternateProtocol so we 1996 // * Set the alternate protocol mode to kDoNotUseAlternateProtocol so we
2280 // ignore future Alternate-Protocol headers from the HostPortPair. 1997 // ignore future Alternate-Protocol headers from the HostPortPair.
2281 // * Reset the connection and go back to STATE_INIT_CONNECTION. 1998 // * Reset the connection and go back to STATE_INIT_CONNECTION.
2282 1999
2283 endpoint_ = HostPortPair(request_->url.HostNoBrackets(), 2000 endpoint_ = HostPortPair(request_->url.HostNoBrackets(),
2284 request_->url.EffectiveIntPort()); 2001 request_->url.EffectiveIntPort());
2285 2002
2286 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor( 2003 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
2287 endpoint_); 2004 endpoint_);
2288 2005
2289 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; 2006 alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
2290 if (connection_->socket()) 2007 if (connection_->socket())
2291 connection_->socket()->Disconnect(); 2008 connection_->socket()->Disconnect();
2292 connection_->Reset(); 2009 connection_->Reset();
2293 next_state_ = STATE_INIT_CONNECTION; 2010 next_state_ = STATE_INIT_CONNECTION;
2294 } 2011 }
2295 2012
2296 } // namespace net 2013 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698