| 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 user_callback_ = NULL; | 172 user_callback_ = NULL; |
| 173 } | 173 } |
| 174 | 174 |
| 175 int HttpAuthController::MaybeGenerateAuthToken(const HttpRequestInfo* request, | 175 int HttpAuthController::MaybeGenerateAuthToken(const HttpRequestInfo* request, |
| 176 OldCompletionCallback* callback, | 176 OldCompletionCallback* callback, |
| 177 const BoundNetLog& net_log) { | 177 const BoundNetLog& net_log) { |
| 178 DCHECK(CalledOnValidThread()); | 178 DCHECK(CalledOnValidThread()); |
| 179 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(net_log); | 179 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(net_log); |
| 180 if (!needs_auth) | 180 if (!needs_auth) |
| 181 return OK; | 181 return OK; |
| 182 const string16* username = NULL; | 182 const AuthCredentials* credentials = NULL; |
| 183 const string16* password = NULL; | 183 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) |
| 184 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) { | 184 credentials = &identity_.credentials; |
| 185 username = &identity_.username; | |
| 186 password = &identity_.password; | |
| 187 } | |
| 188 DCHECK(auth_token_.empty()); | 185 DCHECK(auth_token_.empty()); |
| 189 DCHECK(NULL == user_callback_); | 186 DCHECK(NULL == user_callback_); |
| 190 int rv = handler_->GenerateAuthToken(username, | 187 int rv = handler_->GenerateAuthToken(credentials, |
| 191 password, | |
| 192 request, | 188 request, |
| 193 &io_callback_, | 189 &io_callback_, |
| 194 &auth_token_); | 190 &auth_token_); |
| 195 if (DisableOnAuthHandlerResult(rv)) | 191 if (DisableOnAuthHandlerResult(rv)) |
| 196 rv = OK; | 192 rv = OK; |
| 197 if (rv == ERR_IO_PENDING) | 193 if (rv == ERR_IO_PENDING) |
| 198 user_callback_ = callback; | 194 user_callback_ = callback; |
| 199 else | 195 else |
| 200 OnIOComplete(rv); | 196 OnIOComplete(rv); |
| 201 return rv; | 197 return rv; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 226 CreatePreemptiveAuthHandlerFromString(entry->auth_challenge(), target_, | 222 CreatePreemptiveAuthHandlerFromString(entry->auth_challenge(), target_, |
| 227 auth_origin_, | 223 auth_origin_, |
| 228 entry->IncrementNonceCount(), | 224 entry->IncrementNonceCount(), |
| 229 net_log, &handler_preemptive); | 225 net_log, &handler_preemptive); |
| 230 if (rv_create != OK) | 226 if (rv_create != OK) |
| 231 return false; | 227 return false; |
| 232 | 228 |
| 233 // Set the state | 229 // Set the state |
| 234 identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; | 230 identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP; |
| 235 identity_.invalid = false; | 231 identity_.invalid = false; |
| 236 identity_.username = entry->username(); | 232 identity_.credentials = entry->credentials(); |
| 237 identity_.password = entry->password(); | |
| 238 handler_.swap(handler_preemptive); | 233 handler_.swap(handler_preemptive); |
| 239 return true; | 234 return true; |
| 240 } | 235 } |
| 241 | 236 |
| 242 void HttpAuthController::AddAuthorizationHeader( | 237 void HttpAuthController::AddAuthorizationHeader( |
| 243 HttpRequestHeaders* authorization_headers) { | 238 HttpRequestHeaders* authorization_headers) { |
| 244 DCHECK(CalledOnValidThread()); | 239 DCHECK(CalledOnValidThread()); |
| 245 DCHECK(HaveAuth()); | 240 DCHECK(HaveAuth()); |
| 246 // auth_token_ can be empty if we encountered a permanent error with | 241 // auth_token_ can be empty if we encountered a permanent error with |
| 247 // the auth scheme and want to retry. | 242 // the auth scheme and want to retry. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 | 369 |
| 375 // If we get here and we don't have a handler_, that's because we | 370 // 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 | 371 // invalidated it due to not having any viable identities to use with it. Go |
| 377 // back and try again. | 372 // back and try again. |
| 378 // TODO(asanka): Instead we should create a priority list of | 373 // TODO(asanka): Instead we should create a priority list of |
| 379 // <handler,identity> and iterate through that. | 374 // <handler,identity> and iterate through that. |
| 380 } while(!handler_.get()); | 375 } while(!handler_.get()); |
| 381 return OK; | 376 return OK; |
| 382 } | 377 } |
| 383 | 378 |
| 384 void HttpAuthController::ResetAuth(const string16& username, | 379 void HttpAuthController::ResetAuth(const AuthCredentials& credentials) { |
| 385 const string16& password) { | |
| 386 DCHECK(CalledOnValidThread()); | 380 DCHECK(CalledOnValidThread()); |
| 387 DCHECK(identity_.invalid || (username.empty() && password.empty())); | 381 DCHECK(identity_.invalid || credentials.Empty()); |
| 388 | 382 |
| 389 if (identity_.invalid) { | 383 if (identity_.invalid) { |
| 390 // Update the username/password. | 384 // Update the username/password. |
| 391 identity_.source = HttpAuth::IDENT_SRC_EXTERNAL; | 385 identity_.source = HttpAuth::IDENT_SRC_EXTERNAL; |
| 392 identity_.invalid = false; | 386 identity_.invalid = false; |
| 393 identity_.username = username; | 387 identity_.credentials = credentials; |
| 394 identity_.password = password; | |
| 395 } | 388 } |
| 396 | 389 |
| 397 DCHECK(identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP); | 390 DCHECK(identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP); |
| 398 | 391 |
| 399 // Add the auth entry to the cache before restarting. We don't know whether | 392 // Add the auth entry to the cache before restarting. We don't know whether |
| 400 // the identity is valid yet, but if it is valid we want other transactions | 393 // the identity is valid yet, but if it is valid we want other transactions |
| 401 // to know about it. If an entry for (origin, handler->realm()) already | 394 // to know about it. If an entry for (origin, handler->realm()) already |
| 402 // exists, we update it. | 395 // exists, we update it. |
| 403 // | 396 // |
| 404 // If identity_.source is HttpAuth::IDENT_SRC_NONE or | 397 // If identity_.source is HttpAuth::IDENT_SRC_NONE or |
| 405 // HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS, identity_ contains no | 398 // HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS, identity_ contains no |
| 406 // identity because identity is not required yet or we're using default | 399 // identity because identity is not required yet or we're using default |
| 407 // credentials. | 400 // credentials. |
| 408 // | 401 // |
| 409 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in | 402 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in |
| 410 // round 1 and round 2, which is redundant but correct. It would be nice | 403 // round 1 and round 2, which is redundant but correct. It would be nice |
| 411 // to add an auth entry to the cache only once, preferrably in round 1. | 404 // to add an auth entry to the cache only once, preferrably in round 1. |
| 412 // See http://crbug.com/21015. | 405 // See http://crbug.com/21015. |
| 413 switch (identity_.source) { | 406 switch (identity_.source) { |
| 414 case HttpAuth::IDENT_SRC_NONE: | 407 case HttpAuth::IDENT_SRC_NONE: |
| 415 case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS: | 408 case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS: |
| 416 break; | 409 break; |
| 417 default: | 410 default: |
| 418 http_auth_cache_->Add(auth_origin_, handler_->realm(), | 411 http_auth_cache_->Add(auth_origin_, handler_->realm(), |
| 419 handler_->auth_scheme(), handler_->challenge(), | 412 handler_->auth_scheme(), handler_->challenge(), |
| 420 identity_.username, identity_.password, | 413 identity_.credentials, auth_path_); |
| 421 auth_path_); | |
| 422 break; | 414 break; |
| 423 } | 415 } |
| 424 } | 416 } |
| 425 | 417 |
| 426 bool HttpAuthController::HaveAuthHandler() const { | 418 bool HttpAuthController::HaveAuthHandler() const { |
| 427 return handler_.get() != NULL; | 419 return handler_.get() != NULL; |
| 428 } | 420 } |
| 429 | 421 |
| 430 bool HttpAuthController::HaveAuth() const { | 422 bool HttpAuthController::HaveAuth() const { |
| 431 return handler_.get() && !identity_.invalid; | 423 return handler_.get() && !identity_.invalid; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 445 } | 437 } |
| 446 | 438 |
| 447 void HttpAuthController::InvalidateRejectedAuthFromCache() { | 439 void HttpAuthController::InvalidateRejectedAuthFromCache() { |
| 448 DCHECK(CalledOnValidThread()); | 440 DCHECK(CalledOnValidThread()); |
| 449 DCHECK(HaveAuth()); | 441 DCHECK(HaveAuth()); |
| 450 | 442 |
| 451 // Clear the cache entry for the identity we just failed on. | 443 // Clear the cache entry for the identity we just failed on. |
| 452 // Note: we require the username/password to match before invalidating | 444 // Note: we require the username/password to match before invalidating |
| 453 // since the entry in the cache may be newer than what we used last time. | 445 // since the entry in the cache may be newer than what we used last time. |
| 454 http_auth_cache_->Remove(auth_origin_, handler_->realm(), | 446 http_auth_cache_->Remove(auth_origin_, handler_->realm(), |
| 455 handler_->auth_scheme(), identity_.username, | 447 handler_->auth_scheme(), identity_.credentials); |
| 456 identity_.password); | |
| 457 } | 448 } |
| 458 | 449 |
| 459 bool HttpAuthController::SelectNextAuthIdentityToTry() { | 450 bool HttpAuthController::SelectNextAuthIdentityToTry() { |
| 460 DCHECK(CalledOnValidThread()); | 451 DCHECK(CalledOnValidThread()); |
| 461 DCHECK(handler_.get()); | 452 DCHECK(handler_.get()); |
| 462 DCHECK(identity_.invalid); | 453 DCHECK(identity_.invalid); |
| 463 | 454 |
| 464 // Try to use the username/password encoded into the URL first. | 455 // Try to use the username/password encoded into the URL first. |
| 465 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && | 456 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && |
| 466 !embedded_identity_used_) { | 457 !embedded_identity_used_) { |
| 467 identity_.source = HttpAuth::IDENT_SRC_URL; | 458 identity_.source = HttpAuth::IDENT_SRC_URL; |
| 468 identity_.invalid = false; | 459 identity_.invalid = false; |
| 469 // Extract the username:password from the URL. | 460 // Extract the username:password from the URL. |
| 470 GetIdentityFromURL(auth_url_, | 461 string16 username; |
| 471 &identity_.username, | 462 string16 password; |
| 472 &identity_.password); | 463 GetIdentityFromURL(auth_url_, &username, &password); |
| 464 identity_.credentials.Set(username, password); |
| 473 embedded_identity_used_ = true; | 465 embedded_identity_used_ = true; |
| 474 // 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 |
| 475 // with a password from the cache? | 467 // with a password from the cache? |
| 476 return true; | 468 return true; |
| 477 } | 469 } |
| 478 | 470 |
| 479 // Check the auth cache for a realm entry. | 471 // Check the auth cache for a realm entry. |
| 480 HttpAuthCache::Entry* entry = | 472 HttpAuthCache::Entry* entry = |
| 481 http_auth_cache_->Lookup(auth_origin_, handler_->realm(), | 473 http_auth_cache_->Lookup(auth_origin_, handler_->realm(), |
| 482 handler_->auth_scheme()); | 474 handler_->auth_scheme()); |
| 483 | 475 |
| 484 if (entry) { | 476 if (entry) { |
| 485 identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; | 477 identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; |
| 486 identity_.invalid = false; | 478 identity_.invalid = false; |
| 487 identity_.username = entry->username(); | 479 identity_.credentials = entry->credentials(); |
| 488 identity_.password = entry->password(); | |
| 489 return true; | 480 return true; |
| 490 } | 481 } |
| 491 | 482 |
| 492 // Use default credentials (single sign on) if this is the first attempt | 483 // Use default credentials (single sign on) if this is the first attempt |
| 493 // at identity. Do not allow multiple times as it will infinite loop. | 484 // at identity. Do not allow multiple times as it will infinite loop. |
| 494 // We use default credentials after checking the auth cache so that if | 485 // We use default credentials after checking the auth cache so that if |
| 495 // single sign-on doesn't work, we won't try default credentials for future | 486 // single sign-on doesn't work, we won't try default credentials for future |
| 496 // transactions. | 487 // transactions. |
| 497 if (!default_credentials_used_ && handler_->AllowsDefaultCredentials()) { | 488 if (!default_credentials_used_ && handler_->AllowsDefaultCredentials()) { |
| 498 identity_.source = HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS; | 489 identity_.source = HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 DCHECK(CalledOnValidThread()); | 558 DCHECK(CalledOnValidThread()); |
| 568 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); | 559 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); |
| 569 } | 560 } |
| 570 | 561 |
| 571 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { | 562 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { |
| 572 DCHECK(CalledOnValidThread()); | 563 DCHECK(CalledOnValidThread()); |
| 573 disabled_schemes_.insert(scheme); | 564 disabled_schemes_.insert(scheme); |
| 574 } | 565 } |
| 575 | 566 |
| 576 } // namespace net | 567 } // namespace net |
| OLD | NEW |