| OLD | NEW |
| 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_auth_controller.h" | 5 #include "net/http/http_auth_controller.h" |
| 6 | 6 |
| 7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
| 8 #include "net/base/host_resolver.h" | 8 #include "net/base/host_resolver.h" |
| 9 #include "net/base/net_util.h" | 9 #include "net/base/net_util.h" |
| 10 #include "net/http/http_auth_handler_factory.h" | 10 #include "net/http/http_auth_handler_factory.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 } | 43 } |
| 44 | 44 |
| 45 return msg; | 45 return msg; |
| 46 } | 46 } |
| 47 | 47 |
| 48 } // namespace | 48 } // namespace |
| 49 | 49 |
| 50 HttpAuthController::HttpAuthController( | 50 HttpAuthController::HttpAuthController( |
| 51 HttpAuth::Target target, | 51 HttpAuth::Target target, |
| 52 const GURL& auth_url, | 52 const GURL& auth_url, |
| 53 scoped_refptr<HttpNetworkSession> session, | 53 scoped_refptr<HttpNetworkSession> session) |
| 54 const BoundNetLog& net_log) | |
| 55 : target_(target), | 54 : target_(target), |
| 56 auth_url_(auth_url), | 55 auth_url_(auth_url), |
| 57 auth_origin_(auth_url.GetOrigin()), | 56 auth_origin_(auth_url.GetOrigin()), |
| 58 auth_path_(HttpAuth::AUTH_PROXY ? std::string() : auth_url.path()), | 57 auth_path_(HttpAuth::AUTH_PROXY ? std::string() : auth_url.path()), |
| 59 embedded_identity_used_(false), | 58 embedded_identity_used_(false), |
| 60 default_credentials_used_(false), | 59 default_credentials_used_(false), |
| 61 session_(session), | 60 session_(session) { |
| 62 net_log_(net_log) { | |
| 63 } | 61 } |
| 64 | 62 |
| 65 HttpAuthController::~HttpAuthController() {} | 63 HttpAuthController::~HttpAuthController() {} |
| 66 | 64 |
| 67 int HttpAuthController::MaybeGenerateAuthToken(const HttpRequestInfo* request, | 65 int HttpAuthController::MaybeGenerateAuthToken(const HttpRequestInfo* request, |
| 68 CompletionCallback* callback) { | 66 CompletionCallback* callback, |
| 69 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(); | 67 const BoundNetLog& net_log) { |
| 68 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(net_log); |
| 70 if (!needs_auth) | 69 if (!needs_auth) |
| 71 return OK; | 70 return OK; |
| 72 const std::wstring* username = NULL; | 71 const std::wstring* username = NULL; |
| 73 const std::wstring* password = NULL; | 72 const std::wstring* password = NULL; |
| 74 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) { | 73 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) { |
| 75 username = &identity_.username; | 74 username = &identity_.username; |
| 76 password = &identity_.password; | 75 password = &identity_.password; |
| 77 } | 76 } |
| 78 DCHECK(auth_token_.empty()); | 77 DCHECK(auth_token_.empty()); |
| 79 return handler_->GenerateAuthToken(username, password, request, callback, | 78 return handler_->GenerateAuthToken(username, password, request, callback, |
| 80 &auth_token_); | 79 &auth_token_); |
| 81 } | 80 } |
| 82 | 81 |
| 83 bool HttpAuthController::SelectPreemptiveAuth() { | 82 bool HttpAuthController::SelectPreemptiveAuth(const BoundNetLog& net_log) { |
| 84 DCHECK(!HaveAuth()); | 83 DCHECK(!HaveAuth()); |
| 85 DCHECK(identity_.invalid); | 84 DCHECK(identity_.invalid); |
| 86 | 85 |
| 87 // Don't do preemptive authorization if the URL contains a username/password, | 86 // Don't do preemptive authorization if the URL contains a username/password, |
| 88 // since we must first be challenged in order to use the URL's identity. | 87 // since we must first be challenged in order to use the URL's identity. |
| 89 if (auth_url_.has_username()) | 88 if (auth_url_.has_username()) |
| 90 return false; | 89 return false; |
| 91 | 90 |
| 92 // SelectPreemptiveAuth() is on the critical path for each request, so it | 91 // SelectPreemptiveAuth() is on the critical path for each request, so it |
| 93 // is expected to be fast. LookupByPath() is fast in the common case, since | 92 // is expected to be fast. LookupByPath() is fast in the common case, since |
| 94 // the number of http auth cache entries is expected to be very small. | 93 // the number of http auth cache entries is expected to be very small. |
| 95 // (For most users in fact, it will be 0.) | 94 // (For most users in fact, it will be 0.) |
| 96 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath( | 95 HttpAuthCache::Entry* entry = session_->auth_cache()->LookupByPath( |
| 97 auth_origin_, auth_path_); | 96 auth_origin_, auth_path_); |
| 98 if (!entry) | 97 if (!entry) |
| 99 return false; | 98 return false; |
| 100 | 99 |
| 101 // Try to create a handler using the previous auth challenge. | 100 // Try to create a handler using the previous auth challenge. |
| 102 scoped_ptr<HttpAuthHandler> handler_preemptive; | 101 scoped_ptr<HttpAuthHandler> handler_preemptive; |
| 103 int rv_create = session_->http_auth_handler_factory()-> | 102 int rv_create = session_->http_auth_handler_factory()-> |
| 104 CreatePreemptiveAuthHandlerFromString(entry->auth_challenge(), target_, | 103 CreatePreemptiveAuthHandlerFromString(entry->auth_challenge(), target_, |
| 105 auth_origin_, | 104 auth_origin_, |
| 106 entry->IncrementNonceCount(), | 105 entry->IncrementNonceCount(), |
| 107 net_log_, &handler_preemptive); | 106 net_log, &handler_preemptive); |
| 108 if (rv_create != OK) | 107 if (rv_create != OK) |
| 109 return false; | 108 return false; |
| 110 | 109 |
| 111 // Set the state | 110 // Set the state |
| 112 identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; | 111 identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; |
| 113 identity_.invalid = false; | 112 identity_.invalid = false; |
| 114 identity_.username = entry->username(); | 113 identity_.username = entry->username(); |
| 115 identity_.password = entry->password(); | 114 identity_.password = entry->password(); |
| 116 handler_.swap(handler_preemptive); | 115 handler_.swap(handler_preemptive); |
| 117 return true; | 116 return true; |
| 118 } | 117 } |
| 119 | 118 |
| 120 void HttpAuthController::AddAuthorizationHeader( | 119 void HttpAuthController::AddAuthorizationHeader( |
| 121 HttpRequestHeaders* authorization_headers) { | 120 HttpRequestHeaders* authorization_headers) { |
| 122 DCHECK(HaveAuth()); | 121 DCHECK(HaveAuth()); |
| 123 DCHECK(!auth_token_.empty()); | 122 DCHECK(!auth_token_.empty()); |
| 124 authorization_headers->SetHeader( | 123 authorization_headers->SetHeader( |
| 125 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); | 124 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); |
| 126 auth_token_.clear(); | 125 auth_token_.clear(); |
| 127 } | 126 } |
| 128 | 127 |
| 129 int HttpAuthController::HandleAuthChallenge( | 128 int HttpAuthController::HandleAuthChallenge( |
| 130 scoped_refptr<HttpResponseHeaders> headers, | 129 scoped_refptr<HttpResponseHeaders> headers, |
| 131 bool do_not_send_server_auth, | 130 bool do_not_send_server_auth, |
| 132 bool establishing_tunnel) { | 131 bool establishing_tunnel, |
| 132 const BoundNetLog& net_log) { |
| 133 DCHECK(headers); | 133 DCHECK(headers); |
| 134 DCHECK(auth_origin_.is_valid()); | 134 DCHECK(auth_origin_.is_valid()); |
| 135 | 135 |
| 136 LOG(INFO) << "The " << HttpAuth::GetAuthTargetString(target_) << " " | 136 LOG(INFO) << "The " << HttpAuth::GetAuthTargetString(target_) << " " |
| 137 << auth_origin_ << " requested auth" | 137 << auth_origin_ << " requested auth" |
| 138 << AuthChallengeLogMessage(headers.get()); | 138 << AuthChallengeLogMessage(headers.get()); |
| 139 | 139 |
| 140 // The auth we tried just failed, hence it can't be valid. Remove it from | 140 // The auth we tried just failed, hence it can't be valid. Remove it from |
| 141 // the cache so it won't be used again. | 141 // the cache so it won't be used again. |
| 142 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round | 142 // TODO(wtc): IsFinalRound is not the right condition. In a multi-round |
| 143 // auth sequence, the server may fail the auth in round 1 if our first | 143 // auth sequence, the server may fail the auth in round 1 if our first |
| 144 // authorization header is broken. We should inspect response_.headers to | 144 // authorization header is broken. We should inspect response_.headers to |
| 145 // determine if the server already failed the auth or wants us to continue. | 145 // determine if the server already failed the auth or wants us to continue. |
| 146 // See http://crbug.com/21015. | 146 // See http://crbug.com/21015. |
| 147 if (HaveAuth() && handler_->IsFinalRound()) { | 147 if (HaveAuth() && handler_->IsFinalRound()) { |
| 148 InvalidateRejectedAuthFromCache(); | 148 InvalidateRejectedAuthFromCache(); |
| 149 handler_.reset(); | 149 handler_.reset(); |
| 150 identity_ = HttpAuth::Identity(); | 150 identity_ = HttpAuth::Identity(); |
| 151 } | 151 } |
| 152 | 152 |
| 153 identity_.invalid = true; | 153 identity_.invalid = true; |
| 154 | 154 |
| 155 if (target_ != HttpAuth::AUTH_SERVER || !do_not_send_server_auth) { | 155 if (target_ != HttpAuth::AUTH_SERVER || !do_not_send_server_auth) { |
| 156 // Find the best authentication challenge that we support. | 156 // Find the best authentication challenge that we support. |
| 157 HttpAuth::ChooseBestChallenge(session_->http_auth_handler_factory(), | 157 HttpAuth::ChooseBestChallenge(session_->http_auth_handler_factory(), |
| 158 headers, target_, auth_origin_, net_log_, | 158 headers, target_, auth_origin_, net_log, |
| 159 &handler_); | 159 &handler_); |
| 160 } | 160 } |
| 161 | 161 |
| 162 if (!handler_.get()) { | 162 if (!handler_.get()) { |
| 163 if (establishing_tunnel) { | 163 if (establishing_tunnel) { |
| 164 LOG(ERROR) << "Can't perform auth to the " | 164 LOG(ERROR) << "Can't perform auth to the " |
| 165 << HttpAuth::GetAuthTargetString(target_) << " " | 165 << HttpAuth::GetAuthTargetString(target_) << " " |
| 166 << auth_origin_ << " when establishing a tunnel" | 166 << auth_origin_ << " when establishing a tunnel" |
| 167 << AuthChallengeLogMessage(headers.get()); | 167 << AuthChallengeLogMessage(headers.get()); |
| 168 | 168 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 | 312 |
| 313 auth_info_ = new AuthChallengeInfo; | 313 auth_info_ = new AuthChallengeInfo; |
| 314 auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY; | 314 auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY; |
| 315 auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_)); | 315 auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_)); |
| 316 auth_info_->scheme = ASCIIToWide(handler_->scheme()); | 316 auth_info_->scheme = ASCIIToWide(handler_->scheme()); |
| 317 // TODO(eroman): decode realm according to RFC 2047. | 317 // TODO(eroman): decode realm according to RFC 2047. |
| 318 auth_info_->realm = ASCIIToWide(handler_->realm()); | 318 auth_info_->realm = ASCIIToWide(handler_->realm()); |
| 319 } | 319 } |
| 320 | 320 |
| 321 } // namespace net | 321 } // namespace net |
| OLD | NEW |