OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 // Note: The on-same-thread check is intentionally not using a lock | 89 // Note: The on-same-thread check is intentionally not using a lock |
90 // to protect access to first_thread. This method is meant to be only | 90 // to protect access to first_thread. This method is meant to be only |
91 // used on the same thread, in which case there are no race conditions. If | 91 // used on the same thread, in which case there are no race conditions. If |
92 // there are race conditions (say, a read completes during a partial write), | 92 // there are race conditions (say, a read completes during a partial write), |
93 // the DCHECK will correctly fail. | 93 // the DCHECK will correctly fail. |
94 static base::PlatformThreadId first_thread = | 94 static base::PlatformThreadId first_thread = |
95 base::PlatformThread::CurrentId(); | 95 base::PlatformThread::CurrentId(); |
96 DCHECK_EQ(first_thread, base::PlatformThread::CurrentId()); | 96 DCHECK_EQ(first_thread, base::PlatformThread::CurrentId()); |
97 #endif | 97 #endif |
98 | 98 |
99 HttpAuthHandler::AuthScheme auth_scheme = handler->auth_scheme(); | 99 HttpAuth::Scheme auth_scheme = handler->auth_scheme(); |
100 DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuthHandler::AUTH_SCHEME_MAX); | 100 DCHECK(auth_scheme >= 0 && auth_scheme < HttpAuth::AUTH_SCHEME_MAX); |
101 | 101 |
102 // Record start and rejection events for authentication. | 102 // Record start and rejection events for authentication. |
103 // | 103 // |
104 // The results map to: | 104 // The results map to: |
105 // Basic Start: 0 | 105 // Basic Start: 0 |
106 // Basic Reject: 1 | 106 // Basic Reject: 1 |
107 // Digest Start: 2 | 107 // Digest Start: 2 |
108 // Digest Reject: 3 | 108 // Digest Reject: 3 |
109 // NTLM Start: 4 | 109 // NTLM Start: 4 |
110 // NTLM Reject: 5 | 110 // NTLM Reject: 5 |
111 // Negotiate Start: 6 | 111 // Negotiate Start: 6 |
112 // Negotiate Reject: 7 | 112 // Negotiate Reject: 7 |
113 static const int kEventBucketsEnd = | 113 static const int kEventBucketsEnd = |
114 HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_EVENT_MAX; | 114 HttpAuth::AUTH_SCHEME_MAX * AUTH_EVENT_MAX; |
115 int event_bucket = auth_scheme * AUTH_EVENT_MAX + auth_event; | 115 int event_bucket = auth_scheme * AUTH_EVENT_MAX + auth_event; |
116 DCHECK(event_bucket >= 0 && event_bucket < kEventBucketsEnd); | 116 DCHECK(event_bucket >= 0 && event_bucket < kEventBucketsEnd); |
117 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", event_bucket, | 117 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthCount", event_bucket, |
118 kEventBucketsEnd); | 118 kEventBucketsEnd); |
119 | 119 |
120 // Record the target of the authentication. | 120 // Record the target of the authentication. |
121 // | 121 // |
122 // The results map to: | 122 // The results map to: |
123 // Basic Proxy: 0 | 123 // Basic Proxy: 0 |
124 // Basic Secure Proxy: 1 | 124 // Basic Secure Proxy: 1 |
125 // Basic Server: 2 | 125 // Basic Server: 2 |
126 // Basic Secure Server: 3 | 126 // Basic Secure Server: 3 |
127 // Digest Proxy: 4 | 127 // Digest Proxy: 4 |
128 // Digest Secure Proxy: 5 | 128 // Digest Secure Proxy: 5 |
129 // Digest Server: 6 | 129 // Digest Server: 6 |
130 // Digest Secure Server: 7 | 130 // Digest Secure Server: 7 |
131 // NTLM Proxy: 8 | 131 // NTLM Proxy: 8 |
132 // NTLM Secure Proxy: 9 | 132 // NTLM Secure Proxy: 9 |
133 // NTLM Server: 10 | 133 // NTLM Server: 10 |
134 // NTLM Secure Server: 11 | 134 // NTLM Secure Server: 11 |
135 // Negotiate Proxy: 12 | 135 // Negotiate Proxy: 12 |
136 // Negotiate Secure Proxy: 13 | 136 // Negotiate Secure Proxy: 13 |
137 // Negotiate Server: 14 | 137 // Negotiate Server: 14 |
138 // Negotiate Secure Server: 15 | 138 // Negotiate Secure Server: 15 |
139 if (auth_event != AUTH_EVENT_START) | 139 if (auth_event != AUTH_EVENT_START) |
140 return; | 140 return; |
141 static const int kTargetBucketsEnd = | 141 static const int kTargetBucketsEnd = |
142 HttpAuthHandler::AUTH_SCHEME_MAX * AUTH_TARGET_MAX; | 142 HttpAuth::AUTH_SCHEME_MAX * AUTH_TARGET_MAX; |
143 AuthTarget auth_target = DetermineAuthTarget(handler); | 143 AuthTarget auth_target = DetermineAuthTarget(handler); |
144 int target_bucket = auth_scheme * AUTH_TARGET_MAX + auth_target; | 144 int target_bucket = auth_scheme * AUTH_TARGET_MAX + auth_target; |
145 DCHECK(target_bucket >= 0 && target_bucket < kTargetBucketsEnd); | 145 DCHECK(target_bucket >= 0 && target_bucket < kTargetBucketsEnd); |
146 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthTarget", target_bucket, | 146 UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthTarget", target_bucket, |
147 kTargetBucketsEnd); | 147 kTargetBucketsEnd); |
148 } | 148 } |
149 | 149 |
150 } // namespace | 150 } // namespace |
151 | 151 |
152 HttpAuthController::HttpAuthController( | 152 HttpAuthController::HttpAuthController( |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 case HttpAuth::AUTHORIZATION_RESULT_INVALID: | 275 case HttpAuth::AUTHORIZATION_RESULT_INVALID: |
276 InvalidateCurrentHandler(); | 276 InvalidateCurrentHandler(); |
277 break; | 277 break; |
278 case HttpAuth::AUTHORIZATION_RESULT_REJECT: | 278 case HttpAuth::AUTHORIZATION_RESULT_REJECT: |
279 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); | 279 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); |
280 InvalidateCurrentHandler(); | 280 InvalidateCurrentHandler(); |
281 break; | 281 break; |
282 case HttpAuth::AUTHORIZATION_RESULT_STALE: | 282 case HttpAuth::AUTHORIZATION_RESULT_STALE: |
283 if (http_auth_cache_->UpdateStaleChallenge(auth_origin_, | 283 if (http_auth_cache_->UpdateStaleChallenge(auth_origin_, |
284 handler_->realm(), | 284 handler_->realm(), |
285 handler_->scheme(), | 285 handler_->auth_scheme(), |
286 challenge_used)) { | 286 challenge_used)) { |
287 handler_.reset(); | 287 handler_.reset(); |
288 identity_ = HttpAuth::Identity(); | 288 identity_ = HttpAuth::Identity(); |
289 } else { | 289 } else { |
290 // It's possible that a server could incorrectly issue a stale | 290 // It's possible that a server could incorrectly issue a stale |
291 // response when the entry is not in the cache. Just evict the | 291 // response when the entry is not in the cache. Just evict the |
292 // current value from the cache. | 292 // current value from the cache. |
293 InvalidateCurrentHandler(); | 293 InvalidateCurrentHandler(); |
294 } | 294 } |
295 break; | 295 break; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in | 381 // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in |
382 // round 1 and round 2, which is redundant but correct. It would be nice | 382 // round 1 and round 2, which is redundant but correct. It would be nice |
383 // to add an auth entry to the cache only once, preferrably in round 1. | 383 // to add an auth entry to the cache only once, preferrably in round 1. |
384 // See http://crbug.com/21015. | 384 // See http://crbug.com/21015. |
385 switch (identity_.source) { | 385 switch (identity_.source) { |
386 case HttpAuth::IDENT_SRC_NONE: | 386 case HttpAuth::IDENT_SRC_NONE: |
387 case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS: | 387 case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS: |
388 break; | 388 break; |
389 default: | 389 default: |
390 http_auth_cache_->Add(auth_origin_, handler_->realm(), | 390 http_auth_cache_->Add(auth_origin_, handler_->realm(), |
391 handler_->scheme(), handler_->challenge(), | 391 handler_->auth_scheme(), handler_->challenge(), |
392 identity_.username, identity_.password, | 392 identity_.username, identity_.password, |
393 auth_path_); | 393 auth_path_); |
394 break; | 394 break; |
395 } | 395 } |
396 } | 396 } |
397 | 397 |
398 bool HttpAuthController::HaveAuthHandler() const { | 398 bool HttpAuthController::HaveAuthHandler() const { |
399 return handler_.get() != NULL; | 399 return handler_.get() != NULL; |
400 } | 400 } |
401 | 401 |
(...skipping 17 matching lines...) Expand all Loading... |
419 // the preemptively used auth entry matches the realm of the subsequent | 419 // the preemptively used auth entry matches the realm of the subsequent |
420 // challenge, then we can invalidate the preemptively used entry. | 420 // challenge, then we can invalidate the preemptively used entry. |
421 // Otherwise as-is we may send the failed credentials one extra time. | 421 // Otherwise as-is we may send the failed credentials one extra time. |
422 if (identity_.source == HttpAuth::IDENT_SRC_PATH_LOOKUP) | 422 if (identity_.source == HttpAuth::IDENT_SRC_PATH_LOOKUP) |
423 return; | 423 return; |
424 | 424 |
425 // Clear the cache entry for the identity we just failed on. | 425 // Clear the cache entry for the identity we just failed on. |
426 // Note: we require the username/password to match before invalidating | 426 // Note: we require the username/password to match before invalidating |
427 // since the entry in the cache may be newer than what we used last time. | 427 // since the entry in the cache may be newer than what we used last time. |
428 http_auth_cache_->Remove(auth_origin_, handler_->realm(), | 428 http_auth_cache_->Remove(auth_origin_, handler_->realm(), |
429 handler_->scheme(), identity_.username, | 429 handler_->auth_scheme(), identity_.username, |
430 identity_.password); | 430 identity_.password); |
431 } | 431 } |
432 | 432 |
433 bool HttpAuthController::SelectNextAuthIdentityToTry() { | 433 bool HttpAuthController::SelectNextAuthIdentityToTry() { |
434 DCHECK(CalledOnValidThread()); | 434 DCHECK(CalledOnValidThread()); |
435 DCHECK(handler_.get()); | 435 DCHECK(handler_.get()); |
436 DCHECK(identity_.invalid); | 436 DCHECK(identity_.invalid); |
437 | 437 |
438 // Try to use the username/password encoded into the URL first. | 438 // Try to use the username/password encoded into the URL first. |
439 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && | 439 if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() && |
440 !embedded_identity_used_) { | 440 !embedded_identity_used_) { |
441 identity_.source = HttpAuth::IDENT_SRC_URL; | 441 identity_.source = HttpAuth::IDENT_SRC_URL; |
442 identity_.invalid = false; | 442 identity_.invalid = false; |
443 // Extract the username:password from the URL. | 443 // Extract the username:password from the URL. |
444 GetIdentityFromURL(auth_url_, | 444 GetIdentityFromURL(auth_url_, |
445 &identity_.username, | 445 &identity_.username, |
446 &identity_.password); | 446 &identity_.password); |
447 embedded_identity_used_ = true; | 447 embedded_identity_used_ = true; |
448 // TODO(eroman): If the password is blank, should we also try combining | 448 // TODO(eroman): If the password is blank, should we also try combining |
449 // with a password from the cache? | 449 // with a password from the cache? |
450 return true; | 450 return true; |
451 } | 451 } |
452 | 452 |
453 // Check the auth cache for a realm entry. | 453 // Check the auth cache for a realm entry. |
454 HttpAuthCache::Entry* entry = | 454 HttpAuthCache::Entry* entry = |
455 http_auth_cache_->Lookup(auth_origin_, handler_->realm(), | 455 http_auth_cache_->Lookup(auth_origin_, handler_->realm(), |
456 handler_->scheme()); | 456 handler_->auth_scheme()); |
457 | 457 |
458 if (entry) { | 458 if (entry) { |
459 identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; | 459 identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP; |
460 identity_.invalid = false; | 460 identity_.invalid = false; |
461 identity_.username = entry->username(); | 461 identity_.username = entry->username(); |
462 identity_.password = entry->password(); | 462 identity_.password = entry->password(); |
463 return true; | 463 return true; |
464 } | 464 } |
465 | 465 |
466 // Use default credentials (single sign on) if this is the first attempt | 466 // Use default credentials (single sign on) if this is the first attempt |
(...skipping 13 matching lines...) Expand all Loading... |
480 | 480 |
481 void HttpAuthController::PopulateAuthChallenge() { | 481 void HttpAuthController::PopulateAuthChallenge() { |
482 DCHECK(CalledOnValidThread()); | 482 DCHECK(CalledOnValidThread()); |
483 | 483 |
484 // Populates response_.auth_challenge with the authentication challenge info. | 484 // Populates response_.auth_challenge with the authentication challenge info. |
485 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). | 485 // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo(). |
486 | 486 |
487 auth_info_ = new AuthChallengeInfo; | 487 auth_info_ = new AuthChallengeInfo; |
488 auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY; | 488 auth_info_->is_proxy = target_ == HttpAuth::AUTH_PROXY; |
489 auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_)); | 489 auth_info_->host_and_port = ASCIIToWide(GetHostAndPort(auth_origin_)); |
490 auth_info_->scheme = ASCIIToWide(handler_->scheme()); | 490 auth_info_->scheme = ASCIIToWide( |
| 491 HttpAuth::SchemeToString(handler_->auth_scheme())); |
491 // TODO(eroman): decode realm according to RFC 2047. | 492 // TODO(eroman): decode realm according to RFC 2047. |
492 auth_info_->realm = ASCIIToWide(handler_->realm()); | 493 auth_info_->realm = ASCIIToWide(handler_->realm()); |
493 } | 494 } |
494 | 495 |
495 void HttpAuthController::OnIOComplete(int result) { | 496 void HttpAuthController::OnIOComplete(int result) { |
496 DCHECK(CalledOnValidThread()); | 497 DCHECK(CalledOnValidThread()); |
497 // This error occurs with GSSAPI, if the user has not already logged in. | 498 // This error occurs with GSSAPI, if the user has not already logged in. |
498 // In that case, disable the current scheme as it cannot succeed. | 499 // In that case, disable the current scheme as it cannot succeed. |
499 if (result == ERR_MISSING_AUTH_CREDENTIALS) { | 500 if (result == ERR_MISSING_AUTH_CREDENTIALS) { |
500 DisableAuthScheme(handler_->scheme()); | 501 DisableAuthScheme(handler_->auth_scheme()); |
501 auth_token_.clear(); | 502 auth_token_.clear(); |
502 result = OK; | 503 result = OK; |
503 } | 504 } |
504 if (user_callback_) { | 505 if (user_callback_) { |
505 CompletionCallback* c = user_callback_; | 506 CompletionCallback* c = user_callback_; |
506 user_callback_ = NULL; | 507 user_callback_ = NULL; |
507 c->Run(result); | 508 c->Run(result); |
508 } | 509 } |
509 } | 510 } |
510 | 511 |
511 scoped_refptr<AuthChallengeInfo> HttpAuthController::auth_info() { | 512 scoped_refptr<AuthChallengeInfo> HttpAuthController::auth_info() { |
512 DCHECK(CalledOnValidThread()); | 513 DCHECK(CalledOnValidThread()); |
513 return auth_info_; | 514 return auth_info_; |
514 } | 515 } |
515 | 516 |
516 bool HttpAuthController::IsAuthSchemeDisabled(const std::string& scheme) const { | 517 bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const { |
517 DCHECK(CalledOnValidThread()); | 518 DCHECK(CalledOnValidThread()); |
518 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); | 519 return disabled_schemes_.find(scheme) != disabled_schemes_.end(); |
519 } | 520 } |
520 | 521 |
521 void HttpAuthController::DisableAuthScheme(const std::string& scheme) { | 522 void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) { |
522 DCHECK(CalledOnValidThread()); | 523 DCHECK(CalledOnValidThread()); |
523 disabled_schemes_.insert(scheme); | 524 disabled_schemes_.insert(scheme); |
524 } | 525 } |
525 | 526 |
526 } // namespace net | 527 } // namespace net |
OLD | NEW |