| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "base/threading/platform_thread.h" | 12 #include "base/threading/platform_thread.h" |
| 13 #include "net/base/auth.h" | 13 #include "net/base/auth.h" |
| 14 #include "net/base/url_util.h" | 14 #include "net/base/url_util.h" |
| 15 #include "net/dns/host_resolver.h" | 15 #include "net/dns/host_resolver.h" |
| 16 #include "net/http/http_auth_handler.h" | 16 #include "net/http/http_auth_handler.h" |
| 17 #include "net/http/http_auth_handler_factory.h" | 17 #include "net/http/http_auth_handler_factory.h" |
| 18 #include "net/http/http_network_session.h" | 18 #include "net/http/http_network_session.h" |
| 19 #include "net/http/http_request_headers.h" | 19 #include "net/http/http_request_headers.h" |
| 20 #include "net/http/http_request_info.h" | 20 #include "net/http/http_request_info.h" |
| 21 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
| 22 | 22 |
| 23 namespace net { | 23 namespace net { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // Returns a log message for all the response headers related to the auth | |
| 28 // challenge. | |
| 29 std::string AuthChallengeLogMessage(HttpResponseHeaders* headers) { | |
| 30 std::string msg; | |
| 31 std::string header_val; | |
| 32 size_t iter = 0; | |
| 33 while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) { | |
| 34 msg.append("\n Has header Proxy-Authenticate: "); | |
| 35 msg.append(header_val); | |
| 36 } | |
| 37 | |
| 38 iter = 0; | |
| 39 while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) { | |
| 40 msg.append("\n Has header WWW-Authenticate: "); | |
| 41 msg.append(header_val); | |
| 42 } | |
| 43 | |
| 44 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate | |
| 45 // authentication with a "Proxy-Support: Session-Based-Authentication" | |
| 46 // response header. | |
| 47 iter = 0; | |
| 48 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) { | |
| 49 msg.append("\n Has header Proxy-Support: "); | |
| 50 msg.append(header_val); | |
| 51 } | |
| 52 | |
| 53 return msg; | |
| 54 } | |
| 55 | |
| 56 enum AuthEvent { | 27 enum AuthEvent { |
| 57 AUTH_EVENT_START = 0, | 28 AUTH_EVENT_START = 0, |
| 58 AUTH_EVENT_REJECT, | 29 AUTH_EVENT_REJECT, |
| 59 AUTH_EVENT_MAX, | 30 AUTH_EVENT_MAX, |
| 60 }; | 31 }; |
| 61 | 32 |
| 62 enum AuthTarget { | 33 enum AuthTarget { |
| 63 AUTH_TARGET_PROXY = 0, | 34 AUTH_TARGET_PROXY = 0, |
| 64 AUTH_TARGET_SECURE_PROXY, | 35 AUTH_TARGET_SECURE_PROXY, |
| 65 AUTH_TARGET_SERVER, | 36 AUTH_TARGET_SERVER, |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // the auth scheme and want to retry. | 211 // the auth scheme and want to retry. |
| 241 if (!auth_token_.empty()) { | 212 if (!auth_token_.empty()) { |
| 242 authorization_headers->SetHeader( | 213 authorization_headers->SetHeader( |
| 243 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); | 214 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); |
| 244 auth_token_.clear(); | 215 auth_token_.clear(); |
| 245 } | 216 } |
| 246 } | 217 } |
| 247 | 218 |
| 248 int HttpAuthController::HandleAuthChallenge( | 219 int HttpAuthController::HandleAuthChallenge( |
| 249 scoped_refptr<HttpResponseHeaders> headers, | 220 scoped_refptr<HttpResponseHeaders> headers, |
| 221 const SSLInfo& ssl_info, |
| 250 bool do_not_send_server_auth, | 222 bool do_not_send_server_auth, |
| 251 bool establishing_tunnel, | 223 bool establishing_tunnel, |
| 252 const BoundNetLog& net_log) { | 224 const BoundNetLog& net_log) { |
| 253 DCHECK(CalledOnValidThread()); | 225 DCHECK(CalledOnValidThread()); |
| 254 DCHECK(headers.get()); | 226 DCHECK(headers.get()); |
| 255 DCHECK(auth_origin_.is_valid()); | 227 DCHECK(auth_origin_.is_valid()); |
| 256 VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " " | |
| 257 << auth_origin_ << " requested auth " | |
| 258 << AuthChallengeLogMessage(headers.get()); | |
| 259 | 228 |
| 260 // Give the existing auth handler first try at the authentication headers. | 229 // Give the existing auth handler first try at the authentication headers. |
| 261 // This will also evict the entry in the HttpAuthCache if the previous | 230 // This will also evict the entry in the HttpAuthCache if the previous |
| 262 // challenge appeared to be rejected, or is using a stale nonce in the Digest | 231 // challenge appeared to be rejected, or is using a stale nonce in the Digest |
| 263 // case. | 232 // case. |
| 264 if (HaveAuth()) { | 233 if (HaveAuth()) { |
| 265 std::string challenge_used; | 234 std::string challenge_used; |
| 266 HttpAuth::AuthorizationResult result = | 235 HttpAuth::AuthorizationResult result = HttpAuth::HandleChallengeResponse( |
| 267 HttpAuth::HandleChallengeResponse(handler_.get(), | 236 handler_.get(), *headers, target_, disabled_schemes_, &challenge_used); |
| 268 headers.get(), | |
| 269 target_, | |
| 270 disabled_schemes_, | |
| 271 &challenge_used); | |
| 272 switch (result) { | 237 switch (result) { |
| 273 case HttpAuth::AUTHORIZATION_RESULT_ACCEPT: | 238 case HttpAuth::AUTHORIZATION_RESULT_ACCEPT: |
| 274 break; | 239 break; |
| 275 case HttpAuth::AUTHORIZATION_RESULT_INVALID: | 240 case HttpAuth::AUTHORIZATION_RESULT_INVALID: |
| 276 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); | 241 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
| 277 break; | 242 break; |
| 278 case HttpAuth::AUTHORIZATION_RESULT_REJECT: | 243 case HttpAuth::AUTHORIZATION_RESULT_REJECT: |
| 279 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); | 244 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); |
| 280 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); | 245 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
| 281 break; | 246 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 310 } | 275 } |
| 311 | 276 |
| 312 identity_.invalid = true; | 277 identity_.invalid = true; |
| 313 | 278 |
| 314 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || | 279 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || |
| 315 !do_not_send_server_auth); | 280 !do_not_send_server_auth); |
| 316 | 281 |
| 317 do { | 282 do { |
| 318 if (!handler_.get() && can_send_auth) { | 283 if (!handler_.get() && can_send_auth) { |
| 319 // Find the best authentication challenge that we support. | 284 // Find the best authentication challenge that we support. |
| 320 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, | 285 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, *headers, |
| 321 headers.get(), | 286 ssl_info, target_, auth_origin_, |
| 322 target_, | 287 disabled_schemes_, net_log, &handler_); |
| 323 auth_origin_, | |
| 324 disabled_schemes_, | |
| 325 net_log, | |
| 326 &handler_); | |
| 327 if (handler_.get()) | 288 if (handler_.get()) |
| 328 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); | 289 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); |
| 329 } | 290 } |
| 330 | 291 |
| 331 if (!handler_.get()) { | 292 if (!handler_.get()) { |
| 332 if (establishing_tunnel) { | 293 if (establishing_tunnel) { |
| 333 LOG(ERROR) << "Can't perform auth to the " | |
| 334 << HttpAuth::GetAuthTargetString(target_) << " " | |
| 335 << auth_origin_ << " when establishing a tunnel" | |
| 336 << AuthChallengeLogMessage(headers.get()); | |
| 337 | |
| 338 // We are establishing a tunnel, we can't show the error page because an | 294 // We are establishing a tunnel, we can't show the error page because an |
| 339 // active network attacker could control its contents. Instead, we just | 295 // active network attacker could control its contents. Instead, we just |
| 340 // fail to establish the tunnel. | 296 // fail to establish the tunnel. |
| 341 DCHECK(target_ == HttpAuth::AUTH_PROXY); | 297 DCHECK(target_ == HttpAuth::AUTH_PROXY); |
| 342 return ERR_PROXY_AUTH_UNSUPPORTED; | 298 return ERR_PROXY_AUTH_UNSUPPORTED; |
| 343 } | 299 } |
| 344 // We found no supported challenge -- let the transaction continue so we | 300 // We found no supported challenge -- let the transaction continue so we |
| 345 // end up displaying the error page. | 301 // end up displaying the error page. |
| 346 return OK; | 302 return OK; |
| 347 } | 303 } |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 DCHECK(CalledOnValidThread()); | 525 DCHECK(CalledOnValidThread()); |
| 570 disabled_schemes_.insert(scheme); | 526 disabled_schemes_.insert(scheme); |
| 571 } | 527 } |
| 572 | 528 |
| 573 void HttpAuthController::DisableEmbeddedIdentity() { | 529 void HttpAuthController::DisableEmbeddedIdentity() { |
| 574 DCHECK(CalledOnValidThread()); | 530 DCHECK(CalledOnValidThread()); |
| 575 embedded_identity_used_ = true; | 531 embedded_identity_used_ = true; |
| 576 } | 532 } |
| 577 | 533 |
| 578 } // namespace net | 534 } // namespace net |
| OLD | NEW |