| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // the auth scheme and want to retry. | 240 // the auth scheme and want to retry. |
| 241 if (!auth_token_.empty()) { | 241 if (!auth_token_.empty()) { |
| 242 authorization_headers->SetHeader( | 242 authorization_headers->SetHeader( |
| 243 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); | 243 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); |
| 244 auth_token_.clear(); | 244 auth_token_.clear(); |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 | 247 |
| 248 int HttpAuthController::HandleAuthChallenge( | 248 int HttpAuthController::HandleAuthChallenge( |
| 249 scoped_refptr<HttpResponseHeaders> headers, | 249 scoped_refptr<HttpResponseHeaders> headers, |
| 250 bool do_not_send_server_auth, | 250 int challenge_option_mask, |
| 251 bool establishing_tunnel, | |
| 252 const BoundNetLog& net_log) { | 251 const BoundNetLog& net_log) { |
| 253 DCHECK(CalledOnValidThread()); | 252 DCHECK(CalledOnValidThread()); |
| 254 DCHECK(headers); | 253 DCHECK(headers); |
| 255 DCHECK(auth_origin_.is_valid()); | 254 DCHECK(auth_origin_.is_valid()); |
| 256 VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " " | 255 VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " " |
| 257 << auth_origin_ << " requested auth " | 256 << auth_origin_ << " requested auth " |
| 258 << AuthChallengeLogMessage(headers.get()); | 257 << AuthChallengeLogMessage(headers.get()); |
| 259 | 258 |
| 260 // Give the existing auth handler first try at the authentication headers. | 259 // Give the existing auth handler first try at the authentication headers. |
| 261 // This will also evict the entry in the HttpAuthCache if the previous | 260 // This will also evict the entry in the HttpAuthCache if the previous |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); | 299 INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
| 301 break; | 300 break; |
| 302 default: | 301 default: |
| 303 NOTREACHED(); | 302 NOTREACHED(); |
| 304 break; | 303 break; |
| 305 } | 304 } |
| 306 } | 305 } |
| 307 | 306 |
| 308 identity_.invalid = true; | 307 identity_.invalid = true; |
| 309 | 308 |
| 310 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || | 309 bool can_send_auth = |
| 311 !do_not_send_server_auth); | 310 (target_ != HttpAuth::AUTH_SERVER || |
| 311 (challenge_option_mask & CHALLENGE_OPTION_SEND_SERVER_AUTH)); |
| 312 | 312 |
| 313 do { | 313 do { |
| 314 if (!handler_.get() && can_send_auth) { | 314 if (!handler_.get() && can_send_auth) { |
| 315 // Find the best authentication challenge that we support. | 315 // Find the best authentication challenge that we support. |
| 316 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, | 316 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, |
| 317 headers, target_, auth_origin_, | 317 headers, target_, auth_origin_, |
| 318 disabled_schemes_, net_log, | 318 disabled_schemes_, net_log, |
| 319 &handler_); | 319 &handler_); |
| 320 if (handler_.get()) | 320 if (handler_.get()) |
| 321 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); | 321 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); |
| 322 } | 322 } |
| 323 | 323 |
| 324 if (!handler_.get()) { | 324 if (!handler_.get()) { |
| 325 if (establishing_tunnel) { | 325 if (challenge_option_mask & CHALLENGE_OPTION_ESTABLISHING_TUNNEL) { |
| 326 LOG(ERROR) << "Can't perform auth to the " | 326 LOG(ERROR) << "Can't perform auth to the " |
| 327 << HttpAuth::GetAuthTargetString(target_) << " " | 327 << HttpAuth::GetAuthTargetString(target_) << " " |
| 328 << auth_origin_ << " when establishing a tunnel" | 328 << auth_origin_ << " when establishing a tunnel" |
| 329 << AuthChallengeLogMessage(headers.get()); | 329 << AuthChallengeLogMessage(headers.get()); |
| 330 | 330 |
| 331 // We are establishing a tunnel, we can't show the error page because an | 331 // We are establishing a tunnel, we can't show the error page because an |
| 332 // active network attacker could control its contents. Instead, we just | 332 // active network attacker could control its contents. Instead, we just |
| 333 // fail to establish the tunnel. | 333 // fail to establish the tunnel. |
| 334 DCHECK(target_ == HttpAuth::AUTH_PROXY); | 334 DCHECK(target_ == HttpAuth::AUTH_PROXY); |
| 335 return ERR_PROXY_AUTH_UNSUPPORTED; | 335 return ERR_PROXY_AUTH_UNSUPPORTED; |
| 336 } | 336 } |
| 337 // We found no supported challenge -- let the transaction continue so we | 337 // We found no supported challenge -- let the transaction continue so we |
| 338 // end up displaying the error page. | 338 // end up displaying the error page. |
| 339 return OK; | 339 return OK; |
| 340 } | 340 } |
| 341 | 341 |
| 342 if (handler_->NeedsIdentity()) { | 342 if (handler_->NeedsIdentity()) { |
| 343 // Pick a new auth identity to try, by looking to the URL and auth cache. | 343 // Pick a new auth identity to try, by looking to the URL and auth cache. |
| 344 // If an identity to try is found, it is saved to identity_. | 344 // If an identity to try is found, it is saved to identity_. |
| 345 SelectNextAuthIdentityToTry(); | 345 SelectNextAuthIdentityToTry(challenge_option_mask); |
| 346 } else { | 346 } else { |
| 347 // Proceed with the existing identity or a null identity. | 347 // Proceed with the existing identity or a null identity. |
| 348 identity_.invalid = false; | 348 identity_.invalid = false; |
| 349 } | 349 } |
| 350 | 350 |
| 351 // From this point on, we are restartable. | 351 // From this point on, we are restartable. |
| 352 | 352 |
| 353 if (identity_.invalid) { | 353 if (identity_.invalid) { |
| 354 // We have exhausted all identity possibilities. | 354 // We have exhausted all identity possibilities. |
| 355 if (!handler_->AllowsExplicitCredentials()) { | 355 if (!handler_->AllowsExplicitCredentials()) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 DCHECK(CalledOnValidThread()); | 438 DCHECK(CalledOnValidThread()); |
| 439 DCHECK(HaveAuth()); | 439 DCHECK(HaveAuth()); |
| 440 | 440 |
| 441 // Clear the cache entry for the identity we just failed on. | 441 // Clear the cache entry for the identity we just failed on. |
| 442 // Note: we require the credentials to match before invalidating | 442 // Note: we require the credentials to match before invalidating |
| 443 // since the entry in the cache may be newer than what we used last time. | 443 // since the entry in the cache may be newer than what we used last time. |
| 444 http_auth_cache_->Remove(auth_origin_, handler_->realm(), | 444 http_auth_cache_->Remove(auth_origin_, handler_->realm(), |
| 445 handler_->auth_scheme(), identity_.credentials); | 445 handler_->auth_scheme(), identity_.credentials); |
| 446 } | 446 } |
| 447 | 447 |
| 448 bool HttpAuthController::SelectNextAuthIdentityToTry() { | 448 bool HttpAuthController::SelectNextAuthIdentityToTry( |
| 449 int challenge_option_mask) { |
| 449 DCHECK(CalledOnValidThread()); | 450 DCHECK(CalledOnValidThread()); |
| 450 DCHECK(handler_.get()); | 451 DCHECK(handler_.get()); |
| 451 DCHECK(identity_.invalid); | 452 DCHECK(identity_.invalid); |
| 452 | 453 |
| 453 // Try to use the username:password encoded into the URL first. | 454 // Try to use the username:password encoded into the URL first. |
| 454 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && | 455 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && |
| 456 (challenge_option_mask & CHALLENGE_OPTION_USE_EMBEDDED_AUTH) && |
| 455 !embedded_identity_used_) { | 457 !embedded_identity_used_) { |
| 456 identity_.source = HttpAuth::IDENT_SRC_URL; | 458 identity_.source = HttpAuth::IDENT_SRC_URL; |
| 457 identity_.invalid = false; | 459 identity_.invalid = false; |
| 458 // Extract the username:password from the URL. | 460 // Extract the username:password from the URL. |
| 459 string16 username; | 461 string16 username; |
| 460 string16 password; | 462 string16 password; |
| 461 GetIdentityFromURL(auth_url_, &username, &password); | 463 GetIdentityFromURL(auth_url_, &username, &password); |
| 462 identity_.credentials.Set(username, password); | 464 identity_.credentials.Set(username, password); |
| 463 embedded_identity_used_ = true; | 465 embedded_identity_used_ = true; |
| 464 // TODO(eroman): If the password is blank, should we also try combining | 466 // TODO(eroman): If the password is blank, should we also try combining |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 DCHECK(CalledOnValidThread()); | 559 DCHECK(CalledOnValidThread()); |
| 558 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); | 560 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); |
| 559 } | 561 } |
| 560 | 562 |
| 561 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { | 563 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { |
| 562 DCHECK(CalledOnValidThread()); | 564 DCHECK(CalledOnValidThread()); |
| 563 disabled_schemes_.insert(scheme); | 565 disabled_schemes_.insert(scheme); |
| 564 } | 566 } |
| 565 | 567 |
| 566 } // namespace net | 568 } // namespace net |
| OLD | NEW |