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_handler_digest.h" | 5 #include "net/http/http_auth_handler_digest.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/md5.h" | 10 #include "base/md5.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 | 85 |
86 HttpAuthHandlerDigest::Factory::~Factory() { | 86 HttpAuthHandlerDigest::Factory::~Factory() { |
87 } | 87 } |
88 | 88 |
89 void HttpAuthHandlerDigest::Factory::set_nonce_generator( | 89 void HttpAuthHandlerDigest::Factory::set_nonce_generator( |
90 const NonceGenerator* nonce_generator) { | 90 const NonceGenerator* nonce_generator) { |
91 nonce_generator_.reset(nonce_generator); | 91 nonce_generator_.reset(nonce_generator); |
92 } | 92 } |
93 | 93 |
94 int HttpAuthHandlerDigest::Factory::CreateAuthHandler( | 94 int HttpAuthHandlerDigest::Factory::CreateAuthHandler( |
95 HttpAuthChallengeTokenizer* challenge, | 95 const HttpAuthChallengeTokenizer& challenge, |
96 HttpAuth::Target target, | 96 HttpAuth::Target target, |
97 const GURL& origin, | 97 const GURL& origin, |
98 CreateReason reason, | 98 CreateReason reason, |
99 int digest_nonce_count, | 99 int digest_nonce_count, |
100 const BoundNetLog& net_log, | 100 const BoundNetLog& net_log, |
101 scoped_ptr<HttpAuthHandler>* handler) { | 101 scoped_ptr<HttpAuthHandler>* handler) { |
102 // TODO(cbentzel): Move towards model of parsing in the factory | 102 // TODO(cbentzel): Move towards model of parsing in the factory |
103 // method and only constructing when valid. | 103 // method and only constructing when valid. |
104 scoped_ptr<HttpAuthHandler> tmp_handler( | 104 scoped_ptr<HttpAuthHandler> tmp_handler( |
105 new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get())); | 105 new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get())); |
106 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | 106 int result = |
107 return ERR_INVALID_RESPONSE; | 107 tmp_handler->HandleInitialChallenge(challenge, target, origin, net_log); |
108 handler->swap(tmp_handler); | 108 if (result == OK) |
109 return OK; | 109 handler->swap(tmp_handler); |
| 110 return result; |
110 } | 111 } |
111 | 112 |
112 HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge( | 113 HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge( |
113 HttpAuthChallengeTokenizer* challenge) { | 114 const HttpAuthChallengeTokenizer& challenge) { |
114 // Even though Digest is not connection based, a "second round" is parsed | 115 // Even though Digest is not connection based, a "second round" is parsed |
115 // to differentiate between stale and rejected responses. | 116 // to differentiate between stale and rejected responses. |
116 // Note that the state of the current handler is not mutated - this way if | 117 // Note that the state of the current handler is not mutated - this way if |
117 // there is a rejection the realm hasn't changed. | 118 // there is a rejection the realm hasn't changed. |
118 if (!challenge->SchemeIs(kDigestSchemeName)) | 119 if (!challenge.SchemeIs(kDigestSchemeName)) |
119 return HttpAuth::AUTHORIZATION_RESULT_INVALID; | 120 return HttpAuth::AUTHORIZATION_RESULT_INVALID; |
120 | 121 |
121 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); | 122 HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs(); |
122 | 123 |
123 // Try to find the "stale" value, and also keep track of the realm | 124 // Try to find the "stale" value, and also keep track of the realm |
124 // for the new challenge. | 125 // for the new challenge. |
125 std::string original_realm; | 126 std::string original_realm; |
126 while (parameters.GetNext()) { | 127 while (parameters.GetNext()) { |
127 if (base::LowerCaseEqualsASCII(parameters.name(), "stale")) { | 128 if (base::LowerCaseEqualsASCII(parameters.name(), "stale")) { |
128 if (base::LowerCaseEqualsASCII(parameters.value(), "true")) | 129 if (base::LowerCaseEqualsASCII(parameters.value(), "true")) |
129 return HttpAuth::AUTHORIZATION_RESULT_STALE; | 130 return HttpAuth::AUTHORIZATION_RESULT_STALE; |
130 } else if (base::LowerCaseEqualsASCII(parameters.name(), "realm")) { | 131 } else if (base::LowerCaseEqualsASCII(parameters.name(), "realm")) { |
131 original_realm = parameters.value(); | 132 original_realm = parameters.value(); |
132 } | 133 } |
133 } | 134 } |
134 return (original_realm_ != original_realm) ? | 135 return (original_realm_ != original_realm) ? |
135 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM : | 136 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM : |
136 HttpAuth::AUTHORIZATION_RESULT_REJECT; | 137 HttpAuth::AUTHORIZATION_RESULT_REJECT; |
137 } | 138 } |
138 | 139 |
139 bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge) { | 140 int HttpAuthHandlerDigest::Init(const HttpAuthChallengeTokenizer& challenge) { |
140 return ParseChallenge(challenge); | 141 return ParseChallenge(challenge) ? OK : ERR_INVALID_RESPONSE; |
141 } | 142 } |
142 | 143 |
143 int HttpAuthHandlerDigest::GenerateAuthTokenImpl( | 144 int HttpAuthHandlerDigest::GenerateAuthTokenImpl( |
144 const AuthCredentials* credentials, const HttpRequestInfo* request, | 145 const AuthCredentials* credentials, |
145 const CompletionCallback& callback, std::string* auth_token) { | 146 const HttpRequestInfo& request, |
| 147 const CompletionCallback& callback, |
| 148 std::string* auth_token) { |
146 // Generate a random client nonce. | 149 // Generate a random client nonce. |
147 std::string cnonce = nonce_generator_->GenerateNonce(); | 150 std::string cnonce = nonce_generator_->GenerateNonce(); |
148 | 151 |
149 // Extract the request method and path -- the meaning of 'path' is overloaded | 152 // Extract the request method and path -- the meaning of 'path' is overloaded |
150 // in certain cases, to be a hostname. | 153 // in certain cases, to be a hostname. |
151 std::string method; | 154 std::string method; |
152 std::string path; | 155 std::string path; |
153 GetRequestMethodAndPath(request, &method, &path); | 156 GetRequestMethodAndPath(request, &method, &path); |
154 | 157 |
155 *auth_token = AssembleCredentials(method, path, *credentials, | 158 *auth_token = AssembleCredentials(method, path, *credentials, |
(...skipping 26 matching lines...) Expand all Loading... |
182 // [<extension-directive>] | 185 // [<extension-directive>] |
183 // | 186 // |
184 // Note that according to RFC 2617 (section 1.2) the realm is required. | 187 // Note that according to RFC 2617 (section 1.2) the realm is required. |
185 // However we allow it to be omitted, in which case it will default to the | 188 // However we allow it to be omitted, in which case it will default to the |
186 // empty string. | 189 // empty string. |
187 // | 190 // |
188 // This allowance is for better compatibility with webservers that fail to | 191 // This allowance is for better compatibility with webservers that fail to |
189 // send the realm (See http://crbug.com/20984 for an instance where a | 192 // send the realm (See http://crbug.com/20984 for an instance where a |
190 // webserver was not sending the realm with a BASIC challenge). | 193 // webserver was not sending the realm with a BASIC challenge). |
191 bool HttpAuthHandlerDigest::ParseChallenge( | 194 bool HttpAuthHandlerDigest::ParseChallenge( |
192 HttpAuthChallengeTokenizer* challenge) { | 195 const HttpAuthChallengeTokenizer& challenge) { |
193 auth_scheme_ = kDigestSchemeName; | 196 auth_scheme_ = kDigestSchemeName; |
194 | 197 |
195 // Initialize to defaults. | 198 // Initialize to defaults. |
196 stale_ = false; | 199 stale_ = false; |
197 algorithm_ = ALGORITHM_UNSPECIFIED; | 200 algorithm_ = ALGORITHM_UNSPECIFIED; |
198 qop_ = QOP_UNSPECIFIED; | 201 qop_ = QOP_UNSPECIFIED; |
199 realm_ = original_realm_ = nonce_ = domain_ = opaque_ = std::string(); | 202 realm_ = original_realm_ = nonce_ = domain_ = opaque_ = std::string(); |
200 | 203 |
201 // FAIL -- Couldn't match auth-scheme. | 204 // FAIL -- Couldn't match auth-scheme. |
202 if (!challenge->SchemeIs(kDigestSchemeName)) | 205 if (!challenge.SchemeIs(kDigestSchemeName)) |
203 return false; | 206 return false; |
204 | 207 |
205 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); | 208 HttpUtil::NameValuePairsIterator parameters = challenge.param_pairs(); |
206 | 209 |
207 // Loop through all the properties. | 210 // Loop through all the properties. |
208 while (parameters.GetNext()) { | 211 while (parameters.GetNext()) { |
209 // FAIL -- couldn't parse a property. | 212 // FAIL -- couldn't parse a property. |
210 if (!ParseChallengeProperty(parameters.name(), | 213 if (!ParseChallengeProperty(parameters.name(), |
211 parameters.value())) | 214 parameters.value())) |
212 return false; | 215 return false; |
213 } | 216 } |
214 | 217 |
215 // Check if tokenizer failed. | 218 // Check if tokenizer failed. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 return "MD5"; | 294 return "MD5"; |
292 case ALGORITHM_MD5_SESS: | 295 case ALGORITHM_MD5_SESS: |
293 return "MD5-sess"; | 296 return "MD5-sess"; |
294 default: | 297 default: |
295 NOTREACHED(); | 298 NOTREACHED(); |
296 return std::string(); | 299 return std::string(); |
297 } | 300 } |
298 } | 301 } |
299 | 302 |
300 void HttpAuthHandlerDigest::GetRequestMethodAndPath( | 303 void HttpAuthHandlerDigest::GetRequestMethodAndPath( |
301 const HttpRequestInfo* request, | 304 const HttpRequestInfo& request, |
302 std::string* method, | 305 std::string* method, |
303 std::string* path) const { | 306 std::string* path) const { |
304 DCHECK(request); | 307 const GURL& url = request.url; |
305 | |
306 const GURL& url = request->url; | |
307 | 308 |
308 if (target_ == HttpAuth::AUTH_PROXY && | 309 if (target_ == HttpAuth::AUTH_PROXY && |
309 (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) { | 310 (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) { |
310 *method = "CONNECT"; | 311 *method = "CONNECT"; |
311 *path = GetHostAndPort(url); | 312 *path = GetHostAndPort(url); |
312 } else { | 313 } else { |
313 *method = request->method; | 314 *method = request.method; |
314 *path = url.PathForRequest(); | 315 *path = url.PathForRequest(); |
315 } | 316 } |
316 } | 317 } |
317 | 318 |
318 std::string HttpAuthHandlerDigest::AssembleResponseDigest( | 319 std::string HttpAuthHandlerDigest::AssembleResponseDigest( |
319 const std::string& method, | 320 const std::string& method, |
320 const std::string& path, | 321 const std::string& path, |
321 const AuthCredentials& credentials, | 322 const AuthCredentials& credentials, |
322 const std::string& cnonce, | 323 const std::string& cnonce, |
323 const std::string& nc) const { | 324 const std::string& nc) const { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop. | 375 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop. |
375 authorization += ", qop=" + QopToString(qop_); | 376 authorization += ", qop=" + QopToString(qop_); |
376 authorization += ", nc=" + nc; | 377 authorization += ", nc=" + nc; |
377 authorization += ", cnonce=" + HttpUtil::Quote(cnonce); | 378 authorization += ", cnonce=" + HttpUtil::Quote(cnonce); |
378 } | 379 } |
379 | 380 |
380 return authorization; | 381 return authorization; |
381 } | 382 } |
382 | 383 |
383 } // namespace net | 384 } // namespace net |
OLD | NEW |