Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / http / http_auth.cc
blob3cc9db1a1229f76d78a8f231cef27935ceebfe94
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
3 // found in the LICENSE file.
5 #include "net/http/http_auth.h"
7 #include <algorithm>
9 #include "base/basictypes.h"
10 #include "base/strings/string_tokenizer.h"
11 #include "base/strings/string_util.h"
12 #include "net/base/net_errors.h"
13 #include "net/http/http_auth_handler.h"
14 #include "net/http/http_auth_handler_factory.h"
15 #include "net/http/http_request_headers.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h"
19 namespace net {
21 HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {}
23 // static
24 void HttpAuth::ChooseBestChallenge(
25 HttpAuthHandlerFactory* http_auth_handler_factory,
26 const HttpResponseHeaders* headers,
27 Target target,
28 const GURL& origin,
29 const std::set<Scheme>& disabled_schemes,
30 const BoundNetLog& net_log,
31 scoped_ptr<HttpAuthHandler>* handler) {
32 DCHECK(http_auth_handler_factory);
33 DCHECK(handler->get() == NULL);
35 // Choose the challenge whose authentication handler gives the maximum score.
36 scoped_ptr<HttpAuthHandler> best;
37 const std::string header_name = GetChallengeHeaderName(target);
38 std::string cur_challenge;
39 void* iter = NULL;
40 while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) {
41 scoped_ptr<HttpAuthHandler> cur;
42 int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
43 cur_challenge, target, origin, net_log, &cur);
44 if (rv != OK) {
45 VLOG(1) << "Unable to create AuthHandler. Status: "
46 << ErrorToString(rv) << " Challenge: " << cur_challenge;
47 continue;
49 if (cur.get() && (!best.get() || best->score() < cur->score()) &&
50 (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
51 best.swap(cur);
53 handler->swap(best);
56 // static
57 HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
58 HttpAuthHandler* handler,
59 const HttpResponseHeaders* headers,
60 Target target,
61 const std::set<Scheme>& disabled_schemes,
62 std::string* challenge_used) {
63 DCHECK(handler);
64 DCHECK(headers);
65 DCHECK(challenge_used);
66 challenge_used->clear();
67 HttpAuth::Scheme current_scheme = handler->auth_scheme();
68 if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
69 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
70 std::string current_scheme_name = SchemeToString(current_scheme);
71 const std::string header_name = GetChallengeHeaderName(target);
72 void* iter = NULL;
73 std::string challenge;
74 HttpAuth::AuthorizationResult authorization_result =
75 HttpAuth::AUTHORIZATION_RESULT_INVALID;
76 while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
77 HttpAuth::ChallengeTokenizer props(challenge.begin(), challenge.end());
78 if (!LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str()))
79 continue;
80 authorization_result = handler->HandleAnotherChallenge(&props);
81 if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
82 *challenge_used = challenge;
83 return authorization_result;
86 // Finding no matches is equivalent to rejection.
87 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
90 HttpAuth::ChallengeTokenizer::ChallengeTokenizer(
91 std::string::const_iterator begin,
92 std::string::const_iterator end)
93 : begin_(begin),
94 end_(end),
95 scheme_begin_(begin),
96 scheme_end_(begin),
97 params_begin_(end),
98 params_end_(end) {
99 Init(begin, end);
102 HttpUtil::NameValuePairsIterator HttpAuth::ChallengeTokenizer::param_pairs()
103 const {
104 return HttpUtil::NameValuePairsIterator(params_begin_, params_end_, ',');
107 std::string HttpAuth::ChallengeTokenizer::base64_param() const {
108 // Strip off any padding.
109 // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.)
111 // Our base64 decoder requires that the length be a multiple of 4.
112 int encoded_length = params_end_ - params_begin_;
113 while (encoded_length > 0 && encoded_length % 4 != 0 &&
114 params_begin_[encoded_length - 1] == '=') {
115 --encoded_length;
117 return std::string(params_begin_, params_begin_ + encoded_length);
120 void HttpAuth::ChallengeTokenizer::Init(std::string::const_iterator begin,
121 std::string::const_iterator end) {
122 // The first space-separated token is the auth-scheme.
123 // NOTE: we are more permissive than RFC 2617 which says auth-scheme
124 // is separated by 1*SP.
125 base::StringTokenizer tok(begin, end, HTTP_LWS);
126 if (!tok.GetNext()) {
127 // Default param and scheme iterators provide empty strings
128 return;
131 // Save the scheme's position.
132 scheme_begin_ = tok.token_begin();
133 scheme_end_ = tok.token_end();
135 params_begin_ = scheme_end_;
136 params_end_ = end;
137 HttpUtil::TrimLWS(&params_begin_, &params_end_);
140 // static
141 std::string HttpAuth::GetChallengeHeaderName(Target target) {
142 switch (target) {
143 case AUTH_PROXY:
144 return "Proxy-Authenticate";
145 case AUTH_SERVER:
146 return "WWW-Authenticate";
147 default:
148 NOTREACHED();
149 return std::string();
153 // static
154 std::string HttpAuth::GetAuthorizationHeaderName(Target target) {
155 switch (target) {
156 case AUTH_PROXY:
157 return HttpRequestHeaders::kProxyAuthorization;
158 case AUTH_SERVER:
159 return HttpRequestHeaders::kAuthorization;
160 default:
161 NOTREACHED();
162 return std::string();
166 // static
167 std::string HttpAuth::GetAuthTargetString(Target target) {
168 switch (target) {
169 case AUTH_PROXY:
170 return "proxy";
171 case AUTH_SERVER:
172 return "server";
173 default:
174 NOTREACHED();
175 return std::string();
179 // static
180 const char* HttpAuth::SchemeToString(Scheme scheme) {
181 static const char* const kSchemeNames[] = {
182 "basic",
183 "digest",
184 "ntlm",
185 "negotiate",
186 "spdyproxy",
187 "mock",
189 COMPILE_ASSERT(arraysize(kSchemeNames) == AUTH_SCHEME_MAX,
190 http_auth_scheme_names_incorrect_size);
191 if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) {
192 NOTREACHED();
193 return "invalid_scheme";
195 return kSchemeNames[scheme];
198 } // namespace net