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 |