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" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "base/threading/platform_thread.h" | 12 #include "base/threading/platform_thread.h" |
13 #include "net/base/auth.h" | 13 #include "net/base/auth.h" |
14 #include "net/base/url_util.h" | 14 #include "net/base/url_util.h" |
15 #include "net/dns/host_resolver.h" | 15 #include "net/dns/host_resolver.h" |
16 #include "net/http/http_auth_handler.h" | 16 #include "net/http/http_auth_handler.h" |
17 #include "net/http/http_auth_handler_factory.h" | 17 #include "net/http/http_auth_handler_factory.h" |
18 #include "net/http/http_network_session.h" | 18 #include "net/http/http_network_session.h" |
19 #include "net/http/http_request_headers.h" | 19 #include "net/http/http_request_headers.h" |
20 #include "net/http/http_request_info.h" | 20 #include "net/http/http_request_info.h" |
21 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
22 | 22 |
23 namespace net { | 23 namespace net { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 // Returns a log message for all the response headers related to the auth | |
28 // challenge. | |
29 std::string AuthChallengeLogMessage(HttpResponseHeaders* headers) { | |
30 std::string msg; | |
31 std::string header_val; | |
32 size_t iter = 0; | |
33 while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) { | |
34 msg.append("\n Has header Proxy-Authenticate: "); | |
35 msg.append(header_val); | |
36 } | |
37 | |
38 iter = 0; | |
39 while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) { | |
40 msg.append("\n Has header WWW-Authenticate: "); | |
41 msg.append(header_val); | |
42 } | |
43 | |
44 // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate | |
45 // authentication with a "Proxy-Support: Session-Based-Authentication" | |
46 // response header. | |
47 iter = 0; | |
48 while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) { | |
49 msg.append("\n Has header Proxy-Support: "); | |
50 msg.append(header_val); | |
51 } | |
52 | |
53 return msg; | |
54 } | |
55 | |
56 enum AuthEvent { | 27 enum AuthEvent { |
57 AUTH_EVENT_START = 0, | 28 AUTH_EVENT_START = 0, |
58 AUTH_EVENT_REJECT, | 29 AUTH_EVENT_REJECT, |
59 AUTH_EVENT_MAX, | 30 AUTH_EVENT_MAX, |
60 }; | 31 }; |
61 | 32 |
62 enum AuthTarget { | 33 enum AuthTarget { |
63 AUTH_TARGET_PROXY = 0, | 34 AUTH_TARGET_PROXY = 0, |
64 AUTH_TARGET_SECURE_PROXY, | 35 AUTH_TARGET_SECURE_PROXY, |
65 AUTH_TARGET_SERVER, | 36 AUTH_TARGET_SERVER, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 // auth_token_ can be empty if we encountered a permanent error with | 210 // auth_token_ can be empty if we encountered a permanent error with |
240 // the auth scheme and want to retry. | 211 // the auth scheme and want to retry. |
241 if (!auth_token_.empty()) { | 212 if (!auth_token_.empty()) { |
242 authorization_headers->SetHeader( | 213 authorization_headers->SetHeader( |
243 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); | 214 HttpAuth::GetAuthorizationHeaderName(target_), auth_token_); |
244 auth_token_.clear(); | 215 auth_token_.clear(); |
245 } | 216 } |
246 } | 217 } |
247 | 218 |
248 int HttpAuthController::HandleAuthChallenge( | 219 int HttpAuthController::HandleAuthChallenge( |
249 scoped_refptr<HttpResponseHeaders> headers, | 220 const HttpResponseInfo& response_info, |
250 bool do_not_send_server_auth, | 221 bool do_not_send_server_auth, |
251 bool establishing_tunnel, | 222 bool establishing_tunnel, |
252 const BoundNetLog& net_log) { | 223 const BoundNetLog& net_log) { |
253 DCHECK(CalledOnValidThread()); | 224 DCHECK(CalledOnValidThread()); |
254 DCHECK(headers.get()); | 225 DCHECK(response_info.headers.get()); |
255 DCHECK(auth_origin_.is_valid()); | 226 DCHECK(auth_origin_.is_valid()); |
256 VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " " | |
257 << auth_origin_ << " requested auth " | |
258 << AuthChallengeLogMessage(headers.get()); | |
259 | 227 |
260 // Give the existing auth handler first try at the authentication headers. | 228 // Give the existing auth handler first try at the authentication headers. |
261 // This will also evict the entry in the HttpAuthCache if the previous | 229 // This will also evict the entry in the HttpAuthCache if the previous |
262 // challenge appeared to be rejected, or is using a stale nonce in the Digest | 230 // challenge appeared to be rejected, or is using a stale nonce in the Digest |
263 // case. | 231 // case. |
264 if (HaveAuth()) { | 232 if (HaveAuth()) { |
265 std::string challenge_used; | 233 std::string challenge_used; |
266 HttpAuth::AuthorizationResult result = | 234 HttpAuth::AuthorizationResult result = HttpAuth::HandleChallengeResponse( |
267 HttpAuth::HandleChallengeResponse(handler_.get(), | 235 handler_.get(), response_info, target_, disabled_schemes_, |
268 headers.get(), | 236 &challenge_used); |
269 target_, | |
270 disabled_schemes_, | |
271 &challenge_used); | |
272 switch (result) { | 237 switch (result) { |
273 case HttpAuth::AUTHORIZATION_RESULT_ACCEPT: | 238 case HttpAuth::AUTHORIZATION_RESULT_ACCEPT: |
274 break; | 239 break; |
275 case HttpAuth::AUTHORIZATION_RESULT_INVALID: | 240 case HttpAuth::AUTHORIZATION_RESULT_INVALID: |
276 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); | 241 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
277 break; | 242 break; |
278 case HttpAuth::AUTHORIZATION_RESULT_REJECT: | 243 case HttpAuth::AUTHORIZATION_RESULT_REJECT: |
279 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); | 244 HistogramAuthEvent(handler_.get(), AUTH_EVENT_REJECT); |
280 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); | 245 InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS); |
281 break; | 246 break; |
(...skipping 28 matching lines...) Expand all Loading... |
310 } | 275 } |
311 | 276 |
312 identity_.invalid = true; | 277 identity_.invalid = true; |
313 | 278 |
314 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || | 279 bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER || |
315 !do_not_send_server_auth); | 280 !do_not_send_server_auth); |
316 | 281 |
317 do { | 282 do { |
318 if (!handler_.get() && can_send_auth) { | 283 if (!handler_.get() && can_send_auth) { |
319 // Find the best authentication challenge that we support. | 284 // Find the best authentication challenge that we support. |
320 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, | 285 HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, response_info, |
321 headers.get(), | 286 target_, auth_origin_, disabled_schemes_, |
322 target_, | 287 net_log, &handler_); |
323 auth_origin_, | |
324 disabled_schemes_, | |
325 net_log, | |
326 &handler_); | |
327 if (handler_.get()) | 288 if (handler_.get()) |
328 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); | 289 HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); |
329 } | 290 } |
330 | 291 |
331 if (!handler_.get()) { | 292 if (!handler_.get()) { |
332 if (establishing_tunnel) { | 293 if (establishing_tunnel) { |
333 LOG(ERROR) << "Can't perform auth to the " | |
334 << HttpAuth::GetAuthTargetString(target_) << " " | |
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 | 294 // 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 | 295 // active network attacker could control its contents. Instead, we just |
340 // fail to establish the tunnel. | 296 // fail to establish the tunnel. |
341 DCHECK(target_ == HttpAuth::AUTH_PROXY); | 297 DCHECK(target_ == HttpAuth::AUTH_PROXY); |
342 return ERR_PROXY_AUTH_UNSUPPORTED; | 298 return ERR_PROXY_AUTH_UNSUPPORTED; |
343 } | 299 } |
344 // We found no supported challenge -- let the transaction continue so we | 300 // We found no supported challenge -- let the transaction continue so we |
345 // end up displaying the error page. | 301 // end up displaying the error page. |
346 return OK; | 302 return OK; |
347 } | 303 } |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 DCHECK(CalledOnValidThread()); | 525 DCHECK(CalledOnValidThread()); |
570 disabled_schemes_.insert(scheme); | 526 disabled_schemes_.insert(scheme); |
571 } | 527 } |
572 | 528 |
573 void HttpAuthController::DisableEmbeddedIdentity() { | 529 void HttpAuthController::DisableEmbeddedIdentity() { |
574 DCHECK(CalledOnValidThread()); | 530 DCHECK(CalledOnValidThread()); |
575 embedded_identity_used_ = true; | 531 embedded_identity_used_ = true; |
576 } | 532 } |
577 | 533 |
578 } // namespace net | 534 } // namespace net |
OLD | NEW |