blob: 7752d743a22a356ea659577e858ad8aa3f2c017b [file] [log] [blame]
[email protected]87c99b6a2011-05-13 20:06:481// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]c3b35c22008-09-27 03:19:422// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/http/http_auth.h"
6
7#include <algorithm>
8
9#include "base/basictypes.h"
[email protected]f4ebe772013-02-02 00:21:3910#include "base/strings/string_tokenizer.h"
[email protected]125ef482013-06-11 18:32:4711#include "base/strings/string_util.h"
[email protected]fa55e192010-02-15 14:25:5012#include "net/base/net_errors.h"
[email protected]df41d0d82014-03-13 00:43:2413#include "net/http/http_auth_challenge_tokenizer.h"
[email protected]40ecae222011-08-24 20:59:5614#include "net/http/http_auth_handler.h"
15#include "net/http/http_auth_handler_factory.h"
[email protected]87c99b6a2011-05-13 20:06:4816#include "net/http/http_request_headers.h"
[email protected]c3b35c22008-09-27 03:19:4217#include "net/http/http_response_headers.h"
18#include "net/http/http_util.h"
19
20namespace net {
21
[email protected]2858bbf2010-10-05 23:46:0222HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {}
23
[email protected]c3b35c22008-09-27 03:19:4224// static
[email protected]fa55e192010-02-15 14:25:5025void HttpAuth::ChooseBestChallenge(
26 HttpAuthHandlerFactory* http_auth_handler_factory,
27 const HttpResponseHeaders* headers,
28 Target target,
29 const GURL& origin,
[email protected]547fc792011-01-13 13:31:1730 const std::set<Scheme>& disabled_schemes,
[email protected]ac5c06e2010-05-27 15:07:3831 const BoundNetLog& net_log,
[email protected]36c8e5f72010-06-07 14:17:1432 scoped_ptr<HttpAuthHandler>* handler) {
[email protected]fa55e192010-02-15 14:25:5033 DCHECK(http_auth_handler_factory);
[email protected]eca50e122010-09-11 14:03:3034 DCHECK(handler->get() == NULL);
[email protected]3f918782009-02-28 01:29:2435
[email protected]c3b35c22008-09-27 03:19:4236 // Choose the challenge whose authentication handler gives the maximum score.
[email protected]36c8e5f72010-06-07 14:17:1437 scoped_ptr<HttpAuthHandler> best;
[email protected]c3b35c22008-09-27 03:19:4238 const std::string header_name = GetChallengeHeaderName(target);
39 std::string cur_challenge;
40 void* iter = NULL;
41 while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) {
[email protected]36c8e5f72010-06-07 14:17:1442 scoped_ptr<HttpAuthHandler> cur;
[email protected]fa55e192010-02-15 14:25:5043 int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
[email protected]ac5c06e2010-05-27 15:07:3844 cur_challenge, target, origin, net_log, &cur);
[email protected]fa55e192010-02-15 14:25:5045 if (rv != OK) {
[email protected]b30a3f52010-10-16 01:05:4646 VLOG(1) << "Unable to create AuthHandler. Status: "
47 << ErrorToString(rv) << " Challenge: " << cur_challenge;
[email protected]fa55e192010-02-15 14:25:5048 continue;
49 }
[email protected]17be1a62010-07-27 19:20:2350 if (cur.get() && (!best.get() || best->score() < cur->score()) &&
[email protected]547fc792011-01-13 13:31:1751 (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
[email protected]17be1a62010-07-27 19:20:2352 best.swap(cur);
[email protected]c3b35c22008-09-27 03:19:4253 }
[email protected]f9ee6b52008-11-08 06:46:2354 handler->swap(best);
[email protected]c3b35c22008-09-27 03:19:4255}
56
[email protected]eca50e122010-09-11 14:03:3057// static
58HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
59 HttpAuthHandler* handler,
60 const HttpResponseHeaders* headers,
61 Target target,
[email protected]547fc792011-01-13 13:31:1762 const std::set<Scheme>& disabled_schemes,
[email protected]c4857e02010-09-16 13:41:3663 std::string* challenge_used) {
[email protected]d66f8812010-10-20 16:52:1564 DCHECK(handler);
65 DCHECK(headers);
[email protected]c4857e02010-09-16 13:41:3666 DCHECK(challenge_used);
[email protected]d66f8812010-10-20 16:52:1567 challenge_used->clear();
[email protected]547fc792011-01-13 13:31:1768 HttpAuth::Scheme current_scheme = handler->auth_scheme();
[email protected]eca50e122010-09-11 14:03:3069 if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
70 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
[email protected]547fc792011-01-13 13:31:1771 std::string current_scheme_name = SchemeToString(current_scheme);
[email protected]eca50e122010-09-11 14:03:3072 const std::string header_name = GetChallengeHeaderName(target);
73 void* iter = NULL;
74 std::string challenge;
75 HttpAuth::AuthorizationResult authorization_result =
76 HttpAuth::AUTHORIZATION_RESULT_INVALID;
77 while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
[email protected]df41d0d82014-03-13 00:43:2478 HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
brettwbc17d2c82015-06-09 22:39:0879 if (!base::LowerCaseEqualsASCII(props.scheme(),
80 current_scheme_name.c_str()))
[email protected]eca50e122010-09-11 14:03:3081 continue;
82 authorization_result = handler->HandleAnotherChallenge(&props);
[email protected]c4857e02010-09-16 13:41:3683 if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
84 *challenge_used = challenge;
[email protected]eca50e122010-09-11 14:03:3085 return authorization_result;
[email protected]c4857e02010-09-16 13:41:3686 }
[email protected]eca50e122010-09-11 14:03:3087 }
[email protected]c4857e02010-09-16 13:41:3688 // Finding no matches is equivalent to rejection.
[email protected]eca50e122010-09-11 14:03:3089 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
90}
91
[email protected]c3b35c22008-09-27 03:19:4292// static
93std::string HttpAuth::GetChallengeHeaderName(Target target) {
[email protected]3f918782009-02-28 01:29:2494 switch (target) {
[email protected]c3b35c22008-09-27 03:19:4295 case AUTH_PROXY:
96 return "Proxy-Authenticate";
97 case AUTH_SERVER:
98 return "WWW-Authenticate";
99 default:
100 NOTREACHED();
[email protected]007b3f82013-04-09 08:46:45101 return std::string();
[email protected]c3b35c22008-09-27 03:19:42102 }
103}
104
105// static
106std::string HttpAuth::GetAuthorizationHeaderName(Target target) {
[email protected]3f918782009-02-28 01:29:24107 switch (target) {
[email protected]c3b35c22008-09-27 03:19:42108 case AUTH_PROXY:
[email protected]87c99b6a2011-05-13 20:06:48109 return HttpRequestHeaders::kProxyAuthorization;
[email protected]c3b35c22008-09-27 03:19:42110 case AUTH_SERVER:
[email protected]87c99b6a2011-05-13 20:06:48111 return HttpRequestHeaders::kAuthorization;
[email protected]c3b35c22008-09-27 03:19:42112 default:
113 NOTREACHED();
[email protected]007b3f82013-04-09 08:46:45114 return std::string();
[email protected]c3b35c22008-09-27 03:19:42115 }
116}
117
[email protected]228404f2010-06-24 04:31:41118// static
[email protected]547fc792011-01-13 13:31:17119std::string HttpAuth::GetAuthTargetString(Target target) {
120 switch (target) {
121 case AUTH_PROXY:
122 return "proxy";
123 case AUTH_SERVER:
124 return "server";
125 default:
126 NOTREACHED();
[email protected]007b3f82013-04-09 08:46:45127 return std::string();
[email protected]547fc792011-01-13 13:31:17128 }
129}
130
131// static
132const char* HttpAuth::SchemeToString(Scheme scheme) {
133 static const char* const kSchemeNames[] = {
134 "basic",
135 "digest",
136 "ntlm",
137 "negotiate",
[email protected]ec44ee02012-09-28 21:31:51138 "spdyproxy",
[email protected]547fc792011-01-13 13:31:17139 "mock",
140 };
mostynb91e0da982015-01-20 19:17:27141 static_assert(arraysize(kSchemeNames) == AUTH_SCHEME_MAX,
142 "http auth scheme names incorrect size");
[email protected]547fc792011-01-13 13:31:17143 if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) {
144 NOTREACHED();
145 return "invalid_scheme";
146 }
147 return kSchemeNames[scheme];
[email protected]228404f2010-06-24 04:31:41148}
149
[email protected]c3b35c22008-09-27 03:19:42150} // namespace net