| Index: net/http/http_network_transaction.cc
|
| diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
|
| index c12f95dfa6764397b7e7900121e191f017dda604..7644df733ab5f938b5abfb27a003b0e402733af4 100644
|
| --- a/net/http/http_network_transaction.cc
|
| +++ b/net/http/http_network_transaction.cc
|
| @@ -709,6 +709,12 @@ int HttpNetworkTransaction::DoLoop(int result) {
|
| net_log_.EndEventWithNetErrorCode(
|
| NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, rv);
|
| break;
|
| + case STATE_HANDLE_AUTH_CHALLENGE:
|
| + rv = DoHandleAuthChallenge();
|
| + break;
|
| + case STATE_HANDLE_AUTH_CHALLENGE_COMPLETE:
|
| + rv = DoHandleAuthChallengeComplete(rv);
|
| + break;
|
| case STATE_READ_BODY:
|
| DCHECK_EQ(OK, rv);
|
| net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_READ_BODY);
|
| @@ -1102,17 +1108,72 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
|
| ProcessAlternativeServices(session_, *response_.headers.get(),
|
| HostPortPair::FromURL(request_->url));
|
|
|
| - int rv = HandleAuthChallenge();
|
| - if (rv != OK)
|
| - return rv;
|
| -
|
| if (IsSecureRequest())
|
| stream_->GetSSLInfo(&response_.ssl_info);
|
|
|
| - headers_valid_ = true;
|
| + next_state_ = STATE_HANDLE_AUTH_CHALLENGE;
|
| return OK;
|
| }
|
|
|
| +int HttpNetworkTransaction::DoHandleAuthChallenge() {
|
| + const HttpResponseHeaders* headers = GetResponseHeaders();
|
| + DCHECK(headers);
|
| + // Note that the server or a proxy can send an authentication header with a
|
| + // response that doesn't have a 401 or 407 status code. This method is
|
| + // typically used to send the final authentication token for a multi-round
|
| + // authentication handshake where no further responses are necessary from the
|
| + // client.
|
| + // TODO(asanka): The logic below doesn't handle authentication headers if the
|
| + // status code isn't 401 or 407. Fix it.
|
| +
|
| + int status = headers->response_code();
|
| + if (status != HTTP_UNAUTHORIZED &&
|
| + status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
|
| + return OK;
|
| + HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED
|
| + ? HttpAuth::AUTH_PROXY
|
| + : HttpAuth::AUTH_SERVER;
|
| + if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
|
| + return ERR_UNEXPECTED_PROXY_AUTH;
|
| +
|
| + // This case can trigger when an HTTPS server responds with a "Proxy
|
| + // authentication required" status code through a non-authenticating
|
| + // proxy.
|
| + if (!auth_controllers_[target].get())
|
| + return ERR_UNEXPECTED_PROXY_AUTH;
|
| +
|
| + if (target == HttpAuth::AUTH_SERVER && !ShouldApplyServerAuth())
|
| + return OK;
|
| +
|
| + net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_HANDLE_AUTH_CHALLENGE);
|
| + pending_auth_target_ = target;
|
| + next_state_ = STATE_HANDLE_AUTH_CHALLENGE_COMPLETE;
|
| + return auth_controllers_[target]->HandleAuthChallenge(response_, io_callback_,
|
| + net_log_);
|
| +}
|
| +
|
| +int HttpNetworkTransaction::DoHandleAuthChallengeComplete(int result) {
|
| + DCHECK(pending_auth_target_ == HttpAuth::AUTH_PROXY ||
|
| + pending_auth_target_ == HttpAuth::AUTH_SERVER);
|
| + net_log_.EndEventWithNetErrorCode(
|
| + NetLog::TYPE_HTTP_TRANSACTION_HANDLE_AUTH_CHALLENGE, result);
|
| + if (result == OK)
|
| + headers_valid_ = true;
|
| + // If there's no AuthHandler, then we won't be able to generate an
|
| + // authentication token next time around regardless of whether the caller
|
| + // provides credentials via ResetAuth().
|
| + if (!auth_controllers_[pending_auth_target_]->HaveAuthHandler()) {
|
| + pending_auth_target_ = HttpAuth::AUTH_NONE;
|
| + return result;
|
| + }
|
| + scoped_refptr<AuthChallengeInfo> auth_info =
|
| + auth_controllers_[pending_auth_target_]->auth_info();
|
| + if (auth_info.get())
|
| + response_.auth_challenge = auth_info;
|
| +
|
| + return result;
|
| +}
|
| +
|
| int HttpNetworkTransaction::DoReadBody() {
|
| DCHECK(read_buf_.get());
|
| DCHECK_GT(read_buf_len_, 0);
|
| @@ -1562,39 +1623,6 @@ bool HttpNetworkTransaction::ShouldApplyServerAuth() const {
|
| return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA);
|
| }
|
|
|
| -int HttpNetworkTransaction::HandleAuthChallenge() {
|
| - scoped_refptr<HttpResponseHeaders> headers(GetResponseHeaders());
|
| - DCHECK(headers.get());
|
| -
|
| - int status = headers->response_code();
|
| - if (status != HTTP_UNAUTHORIZED &&
|
| - status != HTTP_PROXY_AUTHENTICATION_REQUIRED)
|
| - return OK;
|
| - HttpAuth::Target target = status == HTTP_PROXY_AUTHENTICATION_REQUIRED ?
|
| - HttpAuth::AUTH_PROXY : HttpAuth::AUTH_SERVER;
|
| - if (target == HttpAuth::AUTH_PROXY && proxy_info_.is_direct())
|
| - return ERR_UNEXPECTED_PROXY_AUTH;
|
| -
|
| - // This case can trigger when an HTTPS server responds with a "Proxy
|
| - // authentication required" status code through a non-authenticating
|
| - // proxy.
|
| - if (!auth_controllers_[target].get())
|
| - return ERR_UNEXPECTED_PROXY_AUTH;
|
| -
|
| - int rv = auth_controllers_[target]->HandleAuthChallenge(
|
| - headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false,
|
| - net_log_);
|
| - if (auth_controllers_[target]->HaveAuthHandler())
|
| - pending_auth_target_ = target;
|
| -
|
| - scoped_refptr<AuthChallengeInfo> auth_info =
|
| - auth_controllers_[target]->auth_info();
|
| - if (auth_info.get())
|
| - response_.auth_challenge = auth_info;
|
| -
|
| - return rv;
|
| -}
|
| -
|
| bool HttpNetworkTransaction::HaveAuth(HttpAuth::Target target) const {
|
| return auth_controllers_[target].get() &&
|
| auth_controllers_[target]->HaveAuth();
|
|
|