| 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" |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(net_log); | 149 bool needs_auth = HaveAuth() || SelectPreemptiveAuth(net_log); |
| 150 if (!needs_auth) | 150 if (!needs_auth) |
| 151 return OK; | 151 return OK; |
| 152 const AuthCredentials* credentials = NULL; | 152 const AuthCredentials* credentials = NULL; |
| 153 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) | 153 if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) |
| 154 credentials = &identity_.credentials; | 154 credentials = &identity_.credentials; |
| 155 DCHECK(auth_token_.empty()); | 155 DCHECK(auth_token_.empty()); |
| 156 DCHECK(callback_.is_null()); | 156 DCHECK(callback_.is_null()); |
| 157 int rv = handler_->GenerateAuthToken( | 157 int rv = handler_->GenerateAuthToken( |
| 158 credentials, request, | 158 credentials, request, |
| 159 base::Bind(&HttpAuthController::OnIOComplete, base::Unretained(this)), | 159 base::Bind(&HttpAuthController::OnGenerateAuthTokenDone, |
| 160 base::Unretained(this)), |
| 160 &auth_token_); | 161 &auth_token_); |
| 161 if (DisableOnAuthHandlerResult(rv)) | 162 |
| 162 rv = OK; | 163 if (rv == ERR_IO_PENDING) { |
| 163 if (rv == ERR_IO_PENDING) | |
| 164 callback_ = callback; | 164 callback_ = callback; |
| 165 else | 165 return rv; |
| 166 OnIOComplete(rv); | 166 } |
| 167 return rv; | 167 |
| 168 return HandleGenerateTokenResult(rv); |
| 168 } | 169 } |
| 169 | 170 |
| 170 bool HttpAuthController::SelectPreemptiveAuth(const NetLogWithSource& net_log) { | 171 bool HttpAuthController::SelectPreemptiveAuth(const NetLogWithSource& net_log) { |
| 171 DCHECK(CalledOnValidThread()); | 172 DCHECK(CalledOnValidThread()); |
| 172 DCHECK(!HaveAuth()); | 173 DCHECK(!HaveAuth()); |
| 173 DCHECK(identity_.invalid); | 174 DCHECK(identity_.invalid); |
| 174 | 175 |
| 175 // Don't do preemptive authorization if the URL contains a username:password, | 176 // Don't do preemptive authorization if the URL contains a username:password, |
| 176 // since we must first be challenged in order to use the URL's identity. | 177 // since we must first be challenged in order to use the URL's identity. |
| 177 if (auth_url_.has_username()) | 178 if (auth_url_.has_username()) |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 // Populates response_.auth_challenge with the authentication challenge info. | 465 // Populates response_.auth_challenge with the authentication challenge info. |
| 465 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). | 466 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). |
| 466 | 467 |
| 467 auth_info_ = new AuthChallengeInfo; | 468 auth_info_ = new AuthChallengeInfo; |
| 468 auth_info_->is_proxy = (target_ == HttpAuth::AUTH_PROXY); | 469 auth_info_->is_proxy = (target_ == HttpAuth::AUTH_PROXY); |
| 469 auth_info_->challenger = url::Origin(auth_origin_); | 470 auth_info_->challenger = url::Origin(auth_origin_); |
| 470 auth_info_->scheme = HttpAuth::SchemeToString(handler_->auth_scheme()); | 471 auth_info_->scheme = HttpAuth::SchemeToString(handler_->auth_scheme()); |
| 471 auth_info_->realm = handler_->realm(); | 472 auth_info_->realm = handler_->realm(); |
| 472 } | 473 } |
| 473 | 474 |
| 474 bool HttpAuthController::DisableOnAuthHandlerResult(int result) { | 475 int HttpAuthController::HandleGenerateTokenResult(int result) { |
| 475 DCHECK(CalledOnValidThread()); | 476 DCHECK(CalledOnValidThread()); |
| 477 switch (result) { |
| 478 // Occurs if the credential handle is found to be invalid at the point it is |
| 479 // exercised (i.e. GenerateAuthToken stage). We are going to consider this |
| 480 // to be an error that invalidates the identity but not necessarily the |
| 481 // scheme. Doing so allows a different identity to be used with the same |
| 482 // scheme. See https://crbug.com/648366. |
| 483 case ERR_INVALID_HANDLE: |
| 476 | 484 |
| 477 switch (result) { | 485 // If the GenerateAuthToken call fails with this error, this means that the |
| 486 // handler can no longer be used. However, the authentication scheme is |
| 487 // considered still usable. This allows a scheme that attempted and failed |
| 488 // to use default credentials to recover and use explicit credentials. |
| 489 // |
| 490 // The current handler may be tied to external state that is no longer |
| 491 // valid, hence should be discarded. Since the scheme is still valid, a new |
| 492 // handler can be created for the current scheme. |
| 493 case ERR_INVALID_AUTH_CREDENTIALS: |
| 494 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
| 495 auth_token_.clear(); |
| 496 return OK; |
| 497 |
| 478 // Occurs with GSSAPI, if the user has not already logged in. | 498 // Occurs with GSSAPI, if the user has not already logged in. |
| 479 case ERR_MISSING_AUTH_CREDENTIALS: | 499 case ERR_MISSING_AUTH_CREDENTIALS: |
| 480 | 500 |
| 481 // Can occur with GSSAPI or SSPI if the underlying library reports | 501 // Can occur with GSSAPI or SSPI if the underlying library reports |
| 482 // a permanent error. | 502 // a permanent error. |
| 483 case ERR_UNSUPPORTED_AUTH_SCHEME: | 503 case ERR_UNSUPPORTED_AUTH_SCHEME: |
| 484 | 504 |
| 485 // These two error codes represent failures we aren't handling. | 505 // These two error codes represent failures we aren't handling. |
| 486 case ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS: | 506 case ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS: |
| 487 case ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS: | 507 case ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS: |
| 488 | 508 |
| 489 // Can be returned by SSPI if the authenticating authority or | 509 // Can be returned by SSPI if the authenticating authority or |
| 490 // target is not known. | 510 // target is not known. |
| 491 case ERR_MISCONFIGURED_AUTH_ENVIRONMENT: | 511 case ERR_MISCONFIGURED_AUTH_ENVIRONMENT: |
| 492 | 512 |
| 493 // In these cases, disable the current scheme as it cannot | 513 // In these cases, disable the current scheme as it cannot |
| 494 // succeed. | 514 // succeed. |
| 495 DisableAuthScheme(handler_->auth_scheme()); | 515 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_DISABLE_SCHEME); |
| 496 auth_token_.clear(); | 516 auth_token_.clear(); |
| 497 return true; | 517 return OK; |
| 498 | 518 |
| 499 default: | 519 default: |
| 500 return false; | 520 return result; |
| 501 } | 521 } |
| 502 } | 522 } |
| 503 | 523 |
| 504 void HttpAuthController::OnIOComplete(int result) { | 524 void HttpAuthController::OnGenerateAuthTokenDone(int result) { |
| 505 DCHECK(CalledOnValidThread()); | 525 DCHECK(CalledOnValidThread()); |
| 506 if (DisableOnAuthHandlerResult(result)) | 526 result = HandleGenerateTokenResult(result); |
| 507 result = OK; | |
| 508 if (!callback_.is_null()) { | 527 if (!callback_.is_null()) { |
| 509 CompletionCallback c = callback_; | 528 CompletionCallback c = callback_; |
| 510 callback_.Reset(); | 529 callback_.Reset(); |
| 511 c.Run(result); | 530 c.Run(result); |
| 512 } | 531 } |
| 513 } | 532 } |
| 514 | 533 |
| 515 scoped_refptr<AuthChallengeInfo> HttpAuthController::auth_info() { | 534 scoped_refptr<AuthChallengeInfo> HttpAuthController::auth_info() { |
| 516 DCHECK(CalledOnValidThread()); | 535 DCHECK(CalledOnValidThread()); |
| 517 return auth_info_; | 536 return auth_info_; |
| 518 } | 537 } |
| 519 | 538 |
| 520 bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const { | 539 bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const { |
| 521 DCHECK(CalledOnValidThread()); | 540 DCHECK(CalledOnValidThread()); |
| 522 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); | 541 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); |
| 523 } | 542 } |
| 524 | 543 |
| 525 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { | 544 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { |
| 526 DCHECK(CalledOnValidThread()); | 545 DCHECK(CalledOnValidThread()); |
| 527 disabled_schemes_.insert(scheme); | 546 disabled_schemes_.insert(scheme); |
| 528 } | 547 } |
| 529 | 548 |
| 530 void HttpAuthController::DisableEmbeddedIdentity() { | 549 void HttpAuthController::DisableEmbeddedIdentity() { |
| 531 DCHECK(CalledOnValidThread()); | 550 DCHECK(CalledOnValidThread()); |
| 532 embedded_identity_used_ = true; | 551 embedded_identity_used_ = true; |
| 533 } | 552 } |
| 534 | 553 |
| 535 } // namespace net | 554 } // namespace net |
| OLD | NEW |