Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: net/http/http_auth_handler_digest.cc

Issue 3360017: Fix multi-round authentication.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: SocketStream fix Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_auth_handler_digest.h ('k') | net/http/http_auth_handler_digest_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 const std::string& method, 166 const std::string& method,
167 const std::string& path, 167 const std::string& path,
168 const string16& username, 168 const string16& username,
169 const string16& password, 169 const string16& password,
170 const std::string& cnonce, 170 const std::string& cnonce,
171 int nonce_count) const { 171 int nonce_count) const {
172 // the nonce-count is an 8 digit hex string. 172 // the nonce-count is an 8 digit hex string.
173 std::string nc = StringPrintf("%08x", nonce_count); 173 std::string nc = StringPrintf("%08x", nonce_count);
174 174
175 // TODO(eroman): is this the right encoding? 175 // TODO(eroman): is this the right encoding?
176 std::string authorization = std::string("Digest username=") + 176 std::string authorization = (std::string("Digest username=") +
177 HttpUtil::Quote(UTF16ToUTF8(username)); 177 HttpUtil::Quote(UTF16ToUTF8(username)));
178 authorization += ", realm=" + HttpUtil::Quote(realm_); 178 authorization += ", realm=" + HttpUtil::Quote(realm_);
179 authorization += ", nonce=" + HttpUtil::Quote(nonce_); 179 authorization += ", nonce=" + HttpUtil::Quote(nonce_);
180 authorization += ", uri=" + HttpUtil::Quote(path); 180 authorization += ", uri=" + HttpUtil::Quote(path);
181 181
182 if (algorithm_ != ALGORITHM_UNSPECIFIED) { 182 if (algorithm_ != ALGORITHM_UNSPECIFIED) {
183 authorization += ", algorithm=" + AlgorithmToString(algorithm_); 183 authorization += ", algorithm=" + AlgorithmToString(algorithm_);
184 } 184 }
185 std::string response = AssembleResponseDigest(method, path, username, 185 std::string response = AssembleResponseDigest(method, path, username,
186 password, cnonce, nc); 186 password, cnonce, nc);
187 // No need to call HttpUtil::Quote() as the response digest cannot contain 187 // No need to call HttpUtil::Quote() as the response digest cannot contain
188 // any characters needing to be escaped. 188 // any characters needing to be escaped.
189 authorization += ", response=\"" + response + "\""; 189 authorization += ", response=\"" + response + "\"";
190 190
191 if (!opaque_.empty()) { 191 if (!opaque_.empty()) {
192 authorization += ", opaque=" + HttpUtil::Quote(opaque_); 192 authorization += ", opaque=" + HttpUtil::Quote(opaque_);
193 } 193 }
194 if (qop_ != QOP_UNSPECIFIED) { 194 if (qop_ != QOP_UNSPECIFIED) {
195 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop. 195 // TODO(eroman): Supposedly IIS server requires quotes surrounding qop.
196 authorization += ", qop=" + QopToString(qop_); 196 authorization += ", qop=" + QopToString(qop_);
197 authorization += ", nc=" + nc; 197 authorization += ", nc=" + nc;
198 authorization += ", cnonce=" + HttpUtil::Quote(cnonce); 198 authorization += ", cnonce=" + HttpUtil::Quote(cnonce);
199 } 199 }
200 200
201 return authorization; 201 return authorization;
202 } 202 }
203 203
204 bool HttpAuthHandlerDigest::Init(HttpAuth::ChallengeTokenizer* challenge) {
205 return ParseChallenge(challenge);
206 }
207
208 HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge(
209 HttpAuth::ChallengeTokenizer* challenge) {
210 // Even though Digest is not connection based, a "second round" is parsed
211 // to differentiate between stale and rejected responses.
212 // Note that the state of the current handler is not mutated - this way if
213 // there is a rejection the realm hasn't changed.
214 if (!challenge->valid() ||
215 !LowerCaseEqualsASCII(challenge->scheme(), "digest"))
216 return HttpAuth::AUTHORIZATION_RESULT_INVALID;
217
218 // Try to find the "stale" value.
219 while (challenge->GetNext()) {
220 if (!LowerCaseEqualsASCII(challenge->name(), "stale"))
221 continue;
222 if (LowerCaseEqualsASCII(challenge->unquoted_value(), "true"))
223 return HttpAuth::AUTHORIZATION_RESULT_STALE;
224 }
225
226 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
227 }
228
204 // The digest challenge header looks like: 229 // The digest challenge header looks like:
205 // WWW-Authenticate: Digest 230 // WWW-Authenticate: Digest
206 // [realm="<realm-value>"] 231 // [realm="<realm-value>"]
207 // nonce="<nonce-value>" 232 // nonce="<nonce-value>"
208 // [domain="<list-of-URIs>"] 233 // [domain="<list-of-URIs>"]
209 // [opaque="<opaque-token-value>"] 234 // [opaque="<opaque-token-value>"]
210 // [stale="<true-or-false>"] 235 // [stale="<true-or-false>"]
211 // [algorithm="<digest-algorithm>"] 236 // [algorithm="<digest-algorithm>"]
212 // [qop="<list-of-qop-values>"] 237 // [qop="<list-of-qop-values>"]
213 // [<extension-directive>] 238 // [<extension-directive>]
(...skipping 10 matching lines...) Expand all
224 scheme_ = "digest"; 249 scheme_ = "digest";
225 score_ = 2; 250 score_ = 2;
226 properties_ = ENCRYPTS_IDENTITY; 251 properties_ = ENCRYPTS_IDENTITY;
227 252
228 // Initialize to defaults. 253 // Initialize to defaults.
229 stale_ = false; 254 stale_ = false;
230 algorithm_ = ALGORITHM_UNSPECIFIED; 255 algorithm_ = ALGORITHM_UNSPECIFIED;
231 qop_ = QOP_UNSPECIFIED; 256 qop_ = QOP_UNSPECIFIED;
232 realm_ = nonce_ = domain_ = opaque_ = std::string(); 257 realm_ = nonce_ = domain_ = opaque_ = std::string();
233 258
259 // FAIL -- Couldn't match auth-scheme.
234 if (!challenge->valid() || 260 if (!challenge->valid() ||
235 !LowerCaseEqualsASCII(challenge->scheme(), "digest")) 261 !LowerCaseEqualsASCII(challenge->scheme(), "digest"))
236 return false; // FAIL -- Couldn't match auth-scheme. 262 return false;
237 263
238 // Loop through all the properties. 264 // Loop through all the properties.
239 while (challenge->GetNext()) { 265 while (challenge->GetNext()) {
240 if (challenge->value().empty()) { 266 if (challenge->value().empty()) {
241 DLOG(INFO) << "Invalid digest property"; 267 DLOG(INFO) << "Invalid digest property";
242 return false; 268 return false;
243 } 269 }
244 270
271 // FAIL -- couldn't parse a property.
245 if (!ParseChallengeProperty(challenge->name(), challenge->unquoted_value())) 272 if (!ParseChallengeProperty(challenge->name(), challenge->unquoted_value()))
246 return false; // FAIL -- couldn't parse a property. 273 return false;
247 } 274 }
248 275
249 // Check if tokenizer failed. 276 // Check if tokenizer failed.
250 if (!challenge->valid()) 277 if (!challenge->valid())
251 return false; // FAIL 278 return false;
252 279
253 // Check that a minimum set of properties were provided. 280 // Check that a minimum set of properties were provided.
254 if (nonce_.empty()) 281 if (nonce_.empty())
255 return false; // FAIL 282 return false;
256 283
257 return true; 284 return true;
258 } 285 }
259 286
260 bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name, 287 bool HttpAuthHandlerDigest::ParseChallengeProperty(const std::string& name,
261 const std::string& value) { 288 const std::string& value) {
262 if (LowerCaseEqualsASCII(name, "realm")) { 289 if (LowerCaseEqualsASCII(name, "realm")) {
263 realm_ = value; 290 realm_ = value;
264 } else if (LowerCaseEqualsASCII(name, "nonce")) { 291 } else if (LowerCaseEqualsASCII(name, "nonce")) {
265 nonce_ = value; 292 nonce_ = value;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 // method and only constructing when valid. 342 // method and only constructing when valid.
316 scoped_ptr<HttpAuthHandler> tmp_handler( 343 scoped_ptr<HttpAuthHandler> tmp_handler(
317 new HttpAuthHandlerDigest(digest_nonce_count)); 344 new HttpAuthHandlerDigest(digest_nonce_count));
318 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) 345 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
319 return ERR_INVALID_RESPONSE; 346 return ERR_INVALID_RESPONSE;
320 handler->swap(tmp_handler); 347 handler->swap(tmp_handler);
321 return OK; 348 return OK;
322 } 349 }
323 350
324 } // namespace net 351 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_digest.h ('k') | net/http/http_auth_handler_digest_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698