| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/scoped_ptr.h" | 7 #include "base/scoped_ptr.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/field_trial.h" | 9 #include "base/field_trial.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "net/http/http_util.h" | 28 #include "net/http/http_util.h" |
| 29 | 29 |
| 30 using base::Time; | 30 using base::Time; |
| 31 | 31 |
| 32 namespace net { | 32 namespace net { |
| 33 | 33 |
| 34 //----------------------------------------------------------------------------- | 34 //----------------------------------------------------------------------------- |
| 35 | 35 |
| 36 HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session, | 36 HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session, |
| 37 ClientSocketFactory* csf) | 37 ClientSocketFactory* csf) |
| 38 : ALLOW_THIS_IN_INITIALIZER_LIST( | 38 : pending_auth_target_(HttpAuth::AUTH_NONE), |
| 39 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 39 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)), | 40 io_callback_(this, &HttpNetworkTransaction::OnIOComplete)), |
| 40 user_callback_(NULL), | 41 user_callback_(NULL), |
| 41 session_(session), | 42 session_(session), |
| 42 request_(NULL), | 43 request_(NULL), |
| 43 pac_request_(NULL), | 44 pac_request_(NULL), |
| 44 socket_factory_(csf), | 45 socket_factory_(csf), |
| 45 connection_(session->connection_pool()), | 46 connection_(session->connection_pool()), |
| 46 reused_socket_(false), | 47 reused_socket_(false), |
| 47 using_ssl_(false), | 48 using_ssl_(false), |
| 48 using_proxy_(false), | 49 using_proxy_(false), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 int rv = DoLoop(OK); | 86 int rv = DoLoop(OK); |
| 86 if (rv == ERR_IO_PENDING) | 87 if (rv == ERR_IO_PENDING) |
| 87 user_callback_ = callback; | 88 user_callback_ = callback; |
| 88 return rv; | 89 return rv; |
| 89 } | 90 } |
| 90 | 91 |
| 91 int HttpNetworkTransaction::RestartWithAuth( | 92 int HttpNetworkTransaction::RestartWithAuth( |
| 92 const std::wstring& username, | 93 const std::wstring& username, |
| 93 const std::wstring& password, | 94 const std::wstring& password, |
| 94 CompletionCallback* callback) { | 95 CompletionCallback* callback) { |
| 96 HttpAuth::Target target = pending_auth_target_; |
| 97 if (target == HttpAuth::AUTH_NONE) { |
| 98 NOTREACHED(); |
| 99 return ERR_UNEXPECTED; |
| 100 } |
| 95 | 101 |
| 96 DCHECK(NeedAuth(HttpAuth::AUTH_PROXY) || | 102 pending_auth_target_ = HttpAuth::AUTH_NONE; |
| 97 NeedAuth(HttpAuth::AUTH_SERVER)); | |
| 98 | 103 |
| 99 // Figure out whether this username password is for proxy or server. | 104 DCHECK(auth_identity_[target].invalid || |
| 100 // Proxy gets set first, then server. | 105 (username.empty() && password.empty())); |
| 101 HttpAuth::Target target = NeedAuth(HttpAuth::AUTH_PROXY) ? | |
| 102 HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER; | |
| 103 | 106 |
| 104 // Update the username/password. | 107 if (auth_identity_[target].invalid) { |
| 105 auth_identity_[target].source = HttpAuth::IDENT_SRC_EXTERNAL; | 108 // Update the username/password. |
| 106 auth_identity_[target].invalid = false; | 109 auth_identity_[target].source = HttpAuth::IDENT_SRC_EXTERNAL; |
| 107 auth_identity_[target].username = username; | 110 auth_identity_[target].invalid = false; |
| 108 auth_identity_[target].password = password; | 111 auth_identity_[target].username = username; |
| 112 auth_identity_[target].password = password; |
| 113 } |
| 109 | 114 |
| 110 PrepareForAuthRestart(target); | 115 PrepareForAuthRestart(target); |
| 111 | 116 |
| 112 DCHECK(user_callback_ == NULL); | 117 DCHECK(user_callback_ == NULL); |
| 113 int rv = DoLoop(OK); | 118 int rv = DoLoop(OK); |
| 114 if (rv == ERR_IO_PENDING) | 119 if (rv == ERR_IO_PENDING) |
| 115 user_callback_ = callback; | 120 user_callback_ = callback; |
| 116 | 121 |
| 117 return rv; | 122 return rv; |
| 118 } | 123 } |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1087 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { | 1092 response_.headers->HasHeaderValue("Transfer-Encoding", "chunked")) { |
| 1088 chunked_decoder_.reset(new HttpChunkedDecoder()); | 1093 chunked_decoder_.reset(new HttpChunkedDecoder()); |
| 1089 } else { | 1094 } else { |
| 1090 response_body_length_ = response_.headers->GetContentLength(); | 1095 response_body_length_ = response_.headers->GetContentLength(); |
| 1091 // If response_body_length_ is still -1, then we have to wait for the | 1096 // If response_body_length_ is still -1, then we have to wait for the |
| 1092 // server to close the connection. | 1097 // server to close the connection. |
| 1093 } | 1098 } |
| 1094 } | 1099 } |
| 1095 | 1100 |
| 1096 int rv = HandleAuthChallenge(); | 1101 int rv = HandleAuthChallenge(); |
| 1097 if (rv == WILL_RESTART_TRANSACTION) | |
| 1098 return OK; | |
| 1099 if (rv != OK) | 1102 if (rv != OK) |
| 1100 return rv; | 1103 return rv; |
| 1101 | 1104 |
| 1102 if (using_ssl_ && !establishing_tunnel_) { | 1105 if (using_ssl_ && !establishing_tunnel_) { |
| 1103 SSLClientSocket* ssl_socket = | 1106 SSLClientSocket* ssl_socket = |
| 1104 reinterpret_cast<SSLClientSocket*>(connection_.socket()); | 1107 reinterpret_cast<SSLClientSocket*>(connection_.socket()); |
| 1105 ssl_socket->GetSSLInfo(&response_.ssl_info); | 1108 ssl_socket->GetSSLInfo(&response_.ssl_info); |
| 1106 } | 1109 } |
| 1107 | 1110 |
| 1108 return OK; | 1111 return OK; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1172 case ERR_CONNECTION_CLOSED: | 1175 case ERR_CONNECTION_CLOSED: |
| 1173 case ERR_CONNECTION_ABORTED: | 1176 case ERR_CONNECTION_ABORTED: |
| 1174 if (ShouldResendRequest()) | 1177 if (ShouldResendRequest()) |
| 1175 error = OK; | 1178 error = OK; |
| 1176 break; | 1179 break; |
| 1177 } | 1180 } |
| 1178 return error; | 1181 return error; |
| 1179 } | 1182 } |
| 1180 | 1183 |
| 1181 void HttpNetworkTransaction::ResetStateForRestart() { | 1184 void HttpNetworkTransaction::ResetStateForRestart() { |
| 1185 pending_auth_target_ = HttpAuth::AUTH_NONE; |
| 1182 header_buf_.reset(); | 1186 header_buf_.reset(); |
| 1183 header_buf_capacity_ = 0; | 1187 header_buf_capacity_ = 0; |
| 1184 header_buf_len_ = 0; | 1188 header_buf_len_ = 0; |
| 1185 header_buf_body_offset_ = -1; | 1189 header_buf_body_offset_ = -1; |
| 1186 header_buf_http_offset_ = -1; | 1190 header_buf_http_offset_ = -1; |
| 1187 response_body_length_ = -1; | 1191 response_body_length_ = -1; |
| 1188 response_body_read_ = 0; | 1192 response_body_read_ = 0; |
| 1189 read_buf_ = NULL; | 1193 read_buf_ = NULL; |
| 1190 read_buf_len_ = 0; | 1194 read_buf_len_ = 0; |
| 1191 request_headers_.clear(); | 1195 request_headers_.clear(); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1463 // active network attacker could control its contents. Instead, we just | 1467 // active network attacker could control its contents. Instead, we just |
| 1464 // fail to establish the tunnel. | 1468 // fail to establish the tunnel. |
| 1465 DCHECK(target == HttpAuth::AUTH_PROXY); | 1469 DCHECK(target == HttpAuth::AUTH_PROXY); |
| 1466 return ERR_PROXY_AUTH_REQUESTED; | 1470 return ERR_PROXY_AUTH_REQUESTED; |
| 1467 } | 1471 } |
| 1468 // We found no supported challenge -- let the transaction continue | 1472 // We found no supported challenge -- let the transaction continue |
| 1469 // so we end up displaying the error page. | 1473 // so we end up displaying the error page. |
| 1470 return OK; | 1474 return OK; |
| 1471 } | 1475 } |
| 1472 | 1476 |
| 1473 bool has_identity_to_try; | |
| 1474 if (auth_handler_[target]->NeedsIdentity()) { | 1477 if (auth_handler_[target]->NeedsIdentity()) { |
| 1475 // Pick a new auth identity to try, by looking to the URL and auth cache. | 1478 // Pick a new auth identity to try, by looking to the URL and auth cache. |
| 1476 // If an identity to try is found, it is saved to auth_identity_[target]. | 1479 // If an identity to try is found, it is saved to auth_identity_[target]. |
| 1477 has_identity_to_try = SelectNextAuthIdentityToTry(target); | 1480 SelectNextAuthIdentityToTry(target); |
| 1478 } else { | 1481 } else { |
| 1479 // Proceed with a null identity. | 1482 // Proceed with a null identity. |
| 1480 // | 1483 // |
| 1481 // TODO(wtc): Add a safeguard against infinite transaction restarts, if | 1484 // TODO(wtc): Add a safeguard against infinite transaction restarts, if |
| 1482 // the server keeps returning "NTLM". | 1485 // the server keeps returning "NTLM". |
| 1483 auth_identity_[target].source = HttpAuth::IDENT_SRC_NONE; | 1486 auth_identity_[target].source = HttpAuth::IDENT_SRC_NONE; |
| 1484 auth_identity_[target].invalid = false; | 1487 auth_identity_[target].invalid = false; |
| 1485 auth_identity_[target].username.clear(); | 1488 auth_identity_[target].username.clear(); |
| 1486 auth_identity_[target].password.clear(); | 1489 auth_identity_[target].password.clear(); |
| 1487 has_identity_to_try = true; | |
| 1488 } | |
| 1489 DCHECK(has_identity_to_try == !auth_identity_[target].invalid); | |
| 1490 | |
| 1491 if (has_identity_to_try) { | |
| 1492 DCHECK(user_callback_); | |
| 1493 PrepareForAuthRestart(target); | |
| 1494 return WILL_RESTART_TRANSACTION; | |
| 1495 } | 1490 } |
| 1496 | 1491 |
| 1497 // We have exhausted all identity possibilities, all we can do now is | 1492 // Make a note that we are waiting for auth. This variable is inspected |
| 1498 // pass the challenge information back to the client. | 1493 // when the client calls RestartWithAuth() to pick up where we left off. |
| 1499 PopulateAuthChallenge(target); | 1494 pending_auth_target_ = target; |
| 1495 |
| 1496 if (auth_identity_[target].invalid) { |
| 1497 // We have exhausted all identity possibilities, all we can do now is |
| 1498 // pass the challenge information back to the client. |
| 1499 PopulateAuthChallenge(target); |
| 1500 } |
| 1500 return OK; | 1501 return OK; |
| 1501 } | 1502 } |
| 1502 | 1503 |
| 1503 void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target) { | 1504 void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target) { |
| 1504 // Populates response_.auth_challenge with the authentication challenge info. | 1505 // Populates response_.auth_challenge with the authentication challenge info. |
| 1505 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). | 1506 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). |
| 1506 | 1507 |
| 1507 AuthChallengeInfo* auth_info = new AuthChallengeInfo; | 1508 AuthChallengeInfo* auth_info = new AuthChallengeInfo; |
| 1508 auth_info->is_proxy = target == HttpAuth::AUTH_PROXY; | 1509 auth_info->is_proxy = target == HttpAuth::AUTH_PROXY; |
| 1509 auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme()); | 1510 auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme()); |
| 1510 // TODO(eroman): decode realm according to RFC 2047. | 1511 // TODO(eroman): decode realm according to RFC 2047. |
| 1511 auth_info->realm = ASCIIToWide(auth_handler_[target]->realm()); | 1512 auth_info->realm = ASCIIToWide(auth_handler_[target]->realm()); |
| 1512 if (target == HttpAuth::AUTH_PROXY) { | 1513 if (target == HttpAuth::AUTH_PROXY) { |
| 1513 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); | 1514 auth_info->host = ASCIIToWide(proxy_info_.proxy_server().host_and_port()); |
| 1514 } else { | 1515 } else { |
| 1515 DCHECK(target == HttpAuth::AUTH_SERVER); | 1516 DCHECK(target == HttpAuth::AUTH_SERVER); |
| 1516 auth_info->host = ASCIIToWide(request_->url.host()); | 1517 auth_info->host = ASCIIToWide(request_->url.host()); |
| 1517 } | 1518 } |
| 1518 response_.auth_challenge = auth_info; | 1519 response_.auth_challenge = auth_info; |
| 1519 } | 1520 } |
| 1520 | 1521 |
| 1521 } // namespace net | 1522 } // namespace net |
| OLD | NEW |