| 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/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/threading/platform_thread.h" | 9 #include "base/threading/platform_thread.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 default: | 309 default: |
| 310 NOTREACHED(); | 310 NOTREACHED(); |
| 311 break; | 311 break; |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 | 314 |
| 315 identity_.invalid = true; | 315 identity_.invalid = true; |
| 316 | 316 |
| 317 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || | 317 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || |
| 318 !do_not_send_server_auth); | 318 !do_not_send_server_auth); |
| 319 if (!handler_.get() && can_send_auth) { | |
| 320 // Find the best authentication challenge that we support. | |
| 321 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, | |
| 322 headers, target_, auth_origin_, | |
| 323 disabled_schemes_, net_log, | |
| 324 &handler_); | |
| 325 if (handler_.get()) | |
| 326 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); | |
| 327 } | |
| 328 | 319 |
| 329 if (!handler_.get()) { | 320 do { |
| 330 if (establishing_tunnel) { | 321 if (!handler_.get() && can_send_auth) { |
| 331 LOG(ERROR) << "Can't perform auth to the " | 322 // Find the best authentication challenge that we support. |
| 332 << HttpAuth::GetAuthTargetString(target_) << " " | 323 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, |
| 333 << auth_origin_ << " when establishing a tunnel" | 324 headers, target_, auth_origin_, |
| 334 << AuthChallengeLogMessage(headers.get()); | 325 disabled_schemes_, net_log, |
| 326 &handler_); |
| 327 if (handler_.get()) |
| 328 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); |
| 329 } |
| 335 | 330 |
| 336 // We are establishing a tunnel, we can't show the error page because an | 331 if (!handler_.get()) { |
| 337 // active network attacker could control its contents. Instead, we just | 332 if (establishing_tunnel) { |
| 338 // fail to establish the tunnel. | 333 LOG(ERROR) << "Can't perform auth to the " |
| 339 DCHECK(target_ == HttpAuth::AUTH_PROXY); | 334 << HttpAuth::GetAuthTargetString(target_) << " " |
| 340 return ERR_PROXY_AUTH_UNSUPPORTED; | 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 |
| 339 // active network attacker could control its contents. Instead, we just |
| 340 // fail to establish the tunnel. |
| 341 DCHECK(target_ == HttpAuth::AUTH_PROXY); |
| 342 return ERR_PROXY_AUTH_UNSUPPORTED; |
| 343 } |
| 344 // We found no supported challenge -- let the transaction continue so we |
| 345 // end up displaying the error page. |
| 346 return OK; |
| 341 } | 347 } |
| 342 // We found no supported challenge -- let the transaction continue | |
| 343 // so we end up displaying the error page. | |
| 344 return OK; | |
| 345 } | |
| 346 | 348 |
| 347 if (handler_->NeedsIdentity()) { | 349 if (handler_->NeedsIdentity()) { |
| 348 // Pick a new auth identity to try, by looking to the URL and auth cache. | 350 // Pick a new auth identity to try, by looking to the URL and auth cache. |
| 349 // If an identity to try is found, it is saved to identity_. | 351 // If an identity to try is found, it is saved to identity_. |
| 350 SelectNextAuthIdentityToTry(); | 352 SelectNextAuthIdentityToTry(); |
| 351 } else { | 353 } else { |
| 352 // Proceed with the existing identity or a null identity. | 354 // Proceed with the existing identity or a null identity. |
| 353 identity_.invalid = false; | 355 identity_.invalid = false; |
| 354 } | 356 } |
| 355 | 357 |
| 356 // From this point on, we are restartable. | 358 // From this point on, we are restartable. |
| 357 | 359 |
| 358 if (identity_.invalid) { | 360 if (identity_.invalid) { |
| 359 // We have exhausted all identity possibilities, all we can do now is | 361 // We have exhausted all identity possibilities. |
| 360 // pass the challenge information back to the client. | 362 if (!handler_->AllowsExplicitCredentials()) { |
| 361 PopulateAuthChallenge(); | 363 // If the handler doesn't accept explicit credentials, then we need to |
| 362 } else { | 364 // choose a different auth scheme. |
| 363 auth_info_ = NULL; | 365 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); |
| 364 } | 366 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_DISABLE_SCHEME); |
| 367 } else { |
| 368 // Pass the challenge information back to the client. |
| 369 PopulateAuthChallenge(); |
| 370 } |
| 371 } else { |
| 372 auth_info_ = NULL; |
| 373 } |
| 365 | 374 |
| 375 // If we get here and we don't have a handler_, that's because we |
| 376 // invalidated it due to not having any viable identities to use with it. Go |
| 377 // back and try again. |
| 378 // TODO(asanka): Instead we should create a priority list of |
| 379 // <handler,identity> and iterate through that. |
| 380 } while(!handler_.get()); |
| 366 return OK; | 381 return OK; |
| 367 } | 382 } |
| 368 | 383 |
| 369 void HttpAuthController::ResetAuth(const string16& username, | 384 void HttpAuthController::ResetAuth(const string16& username, |
| 370 const string16& password) { | 385 const string16& password) { |
| 371 DCHECK(CalledOnValidThread()); | 386 DCHECK(CalledOnValidThread()); |
| 372 DCHECK(identity_.invalid || (username.empty() && password.empty())); | 387 DCHECK(identity_.invalid || (username.empty() && password.empty())); |
| 373 | 388 |
| 374 if (identity_.invalid) { | 389 if (identity_.invalid) { |
| 375 // Update the username/password. | 390 // Update the username/password. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 return handler_.get() != NULL; | 427 return handler_.get() != NULL; |
| 413 } | 428 } |
| 414 | 429 |
| 415 bool HttpAuthController::HaveAuth() const { | 430 bool HttpAuthController::HaveAuth() const { |
| 416 return handler_.get() && !identity_.invalid; | 431 return handler_.get() && !identity_.invalid; |
| 417 } | 432 } |
| 418 | 433 |
| 419 void HttpAuthController::InvalidateCurrentHandler( | 434 void HttpAuthController::InvalidateCurrentHandler( |
| 420 InvalidateHandlerAction action) { | 435 InvalidateHandlerAction action) { |
| 421 DCHECK(CalledOnValidThread()); | 436 DCHECK(CalledOnValidThread()); |
| 437 DCHECK(handler_.get()); |
| 422 | 438 |
| 423 if (action == INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS) | 439 if (action == INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS) |
| 424 InvalidateRejectedAuthFromCache(); | 440 InvalidateRejectedAuthFromCache(); |
| 441 if (action == INVALIDATE_HANDLER_AND_DISABLE_SCHEME) |
| 442 DisableAuthScheme(handler_->auth_scheme()); |
| 425 handler_.reset(); | 443 handler_.reset(); |
| 426 identity_ = HttpAuth::Identity(); | 444 identity_ = HttpAuth::Identity(); |
| 427 } | 445 } |
| 428 | 446 |
| 429 void HttpAuthController::InvalidateRejectedAuthFromCache() { | 447 void HttpAuthController::InvalidateRejectedAuthFromCache() { |
| 430 DCHECK(CalledOnValidThread()); | 448 DCHECK(CalledOnValidThread()); |
| 431 DCHECK(HaveAuth()); | 449 DCHECK(HaveAuth()); |
| 432 | 450 |
| 433 // Clear the cache entry for the identity we just failed on. | 451 // Clear the cache entry for the identity we just failed on. |
| 434 // Note: we require the username/password to match before invalidating | 452 // Note: we require the username/password to match before invalidating |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 DCHECK(CalledOnValidThread()); | 569 DCHECK(CalledOnValidThread()); |
| 552 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); | 570 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); |
| 553 } | 571 } |
| 554 | 572 |
| 555 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { | 573 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { |
| 556 DCHECK(CalledOnValidThread()); | 574 DCHECK(CalledOnValidThread()); |
| 557 disabled_schemes_.insert(scheme); | 575 disabled_schemes_.insert(scheme); |
| 558 } | 576 } |
| 559 | 577 |
| 560 } // namespace net | 578 } // namespace net |
| OLD | NEW |