OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <string> | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/strings/string_util.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "net/base/net_errors.h" | |
11 #include "net/base/test_completion_callback.h" | |
12 #include "net/http/http_auth_challenge_tokenizer.h" | |
13 #include "net/http/http_auth_handler_digest.h" | |
14 #include "net/http/http_request_info.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace net { | |
18 | |
19 namespace { | |
20 | |
21 const char* const kSimpleChallenge = | |
22 "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; | |
23 | |
24 // RespondToChallenge creates an HttpAuthHandlerDigest for the specified | |
25 // |challenge|, and generates a response to the challenge which is returned in | |
26 // |token|. | |
27 // | |
28 // The return value indicates whether the |token| was successfully created. | |
29 // | |
30 // If |target| is HttpAuth::AUTH_PROXY, then |proxy_name| specifies the source | |
31 // of the |challenge|. Otherwise, the scheme and host and port of |request_url| | |
32 // indicates the origin of the challenge. | |
33 bool RespondToChallenge(HttpAuth::Target target, | |
34 const std::string& proxy_name, | |
35 const std::string& request_url, | |
36 const std::string& challenge, | |
37 std::string* token) { | |
38 // Input validation. | |
39 if (token == NULL) { | |
40 ADD_FAILURE() << "|token| must be non-NULL"; | |
41 return false; | |
42 } | |
43 EXPECT_TRUE(target != HttpAuth::AUTH_PROXY || !proxy_name.empty()); | |
44 EXPECT_FALSE(request_url.empty()); | |
45 EXPECT_FALSE(challenge.empty()); | |
46 | |
47 token->clear(); | |
48 scoped_ptr<HttpAuthHandlerDigest::Factory> factory( | |
49 new HttpAuthHandlerDigest::Factory()); | |
50 HttpAuthHandlerDigest::NonceGenerator* nonce_generator = | |
51 new HttpAuthHandlerDigest::FixedNonceGenerator("client_nonce"); | |
52 factory->set_nonce_generator(nonce_generator); | |
53 scoped_ptr<HttpAuthHandler> handler; | |
54 | |
55 // Create a handler for a particular challenge. | |
56 GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name); | |
57 int rv_create = factory->CreateAuthHandlerFromString( | |
58 challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler); | |
59 if (rv_create != OK || handler.get() == NULL) { | |
60 ADD_FAILURE() << "Unable to create auth handler."; | |
61 return false; | |
62 } | |
63 | |
64 // Create a token in response to the challenge. | |
65 // NOTE: HttpAuthHandlerDigest's implementation of GenerateAuthToken always | |
66 // completes synchronously. That's why this test can get away with a | |
67 // TestCompletionCallback without an IO thread. | |
68 TestCompletionCallback callback; | |
69 scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo()); | |
70 request->url = GURL(request_url); | |
71 AuthCredentials credentials(base::ASCIIToUTF16("foo"), | |
72 base::ASCIIToUTF16("bar")); | |
73 int rv_generate = handler->GenerateAuthToken( | |
74 &credentials, request.get(), callback.callback(), token); | |
75 if (rv_generate != OK) { | |
76 ADD_FAILURE() << "Problems generating auth token"; | |
77 return false; | |
78 } | |
79 | |
80 return true; | |
81 } | |
82 | |
83 } // namespace | |
84 | |
85 | |
86 TEST(HttpAuthHandlerDigestTest, ParseChallenge) { | |
87 static const struct { | |
88 // The challenge string. | |
89 const char* challenge; | |
90 // Expected return value of ParseChallenge. | |
91 bool parsed_success; | |
92 // The expected values that were parsed. | |
93 const char* parsed_realm; | |
94 const char* parsed_nonce; | |
95 const char* parsed_domain; | |
96 const char* parsed_opaque; | |
97 bool parsed_stale; | |
98 int parsed_algorithm; | |
99 int parsed_qop; | |
100 } tests[] = { | |
101 { // Check that a minimal challenge works correctly. | |
102 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\"", | |
103 true, | |
104 "Thunder Bluff", | |
105 "xyz", | |
106 "", | |
107 "", | |
108 false, | |
109 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
110 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
111 }, | |
112 | |
113 { // Realm does not need to be quoted, even though RFC2617 requires it. | |
114 "Digest nonce=\"xyz\", realm=ThunderBluff", | |
115 true, | |
116 "ThunderBluff", | |
117 "xyz", | |
118 "", | |
119 "", | |
120 false, | |
121 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
122 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
123 }, | |
124 | |
125 { // We allow the realm to be omitted, and will default it to empty string. | |
126 // See http://crbug.com/20984. | |
127 "Digest nonce=\"xyz\"", | |
128 true, | |
129 "", | |
130 "xyz", | |
131 "", | |
132 "", | |
133 false, | |
134 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
135 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
136 }, | |
137 | |
138 { // Try with realm set to empty string. | |
139 "Digest realm=\"\", nonce=\"xyz\"", | |
140 true, | |
141 "", | |
142 "xyz", | |
143 "", | |
144 "", | |
145 false, | |
146 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
147 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
148 }, | |
149 | |
150 // Handle ISO-8859-1 character as part of the realm. The realm is converted | |
151 // to UTF-8. However, the credentials will still use the original encoding. | |
152 { | |
153 "Digest nonce=\"xyz\", realm=\"foo-\xE5\"", | |
154 true, | |
155 "foo-\xC3\xA5", | |
156 "xyz", | |
157 "", | |
158 "", | |
159 false, | |
160 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
161 HttpAuthHandlerDigest::QOP_UNSPECIFIED, | |
162 }, | |
163 | |
164 { // At a minimum, a nonce must be provided. | |
165 "Digest realm=\"Thunder Bluff\"", | |
166 false, | |
167 "", | |
168 "", | |
169 "", | |
170 "", | |
171 false, | |
172 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
173 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
174 }, | |
175 | |
176 { // The nonce does not need to be quoted, even though RFC2617 | |
177 // requires it. | |
178 "Digest nonce=xyz, realm=\"Thunder Bluff\"", | |
179 true, | |
180 "Thunder Bluff", | |
181 "xyz", | |
182 "", | |
183 "", | |
184 false, | |
185 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
186 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
187 }, | |
188 | |
189 { // Unknown authentication parameters are ignored. | |
190 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", foo=\"bar\"", | |
191 true, | |
192 "Thunder Bluff", | |
193 "xyz", | |
194 "", | |
195 "", | |
196 false, | |
197 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
198 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
199 }, | |
200 | |
201 { // Check that when algorithm has an unsupported value, parsing fails. | |
202 "Digest nonce=\"xyz\", algorithm=\"awezum\", realm=\"Thunder\"", | |
203 false, | |
204 // The remaining values don't matter (but some have been set already). | |
205 "", | |
206 "xyz", | |
207 "", | |
208 "", | |
209 false, | |
210 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
211 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
212 }, | |
213 | |
214 { // Check that algorithm's value is case insensitive, and that MD5 is | |
215 // a supported algorithm. | |
216 "Digest nonce=\"xyz\", algorithm=\"mD5\", realm=\"Oblivion\"", | |
217 true, | |
218 "Oblivion", | |
219 "xyz", | |
220 "", | |
221 "", | |
222 false, | |
223 HttpAuthHandlerDigest::ALGORITHM_MD5, | |
224 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
225 }, | |
226 | |
227 { // Check that md5-sess is a supported algorithm. | |
228 "Digest nonce=\"xyz\", algorithm=\"md5-sess\", realm=\"Oblivion\"", | |
229 true, | |
230 "Oblivion", | |
231 "xyz", | |
232 "", | |
233 "", | |
234 false, | |
235 HttpAuthHandlerDigest::ALGORITHM_MD5_SESS, | |
236 HttpAuthHandlerDigest::QOP_UNSPECIFIED, | |
237 }, | |
238 | |
239 { // Check that qop's value is case insensitive, and that auth is known. | |
240 "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"aUth\"", | |
241 true, | |
242 "Oblivion", | |
243 "xyz", | |
244 "", | |
245 "", | |
246 false, | |
247 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
248 HttpAuthHandlerDigest::QOP_AUTH | |
249 }, | |
250 | |
251 { // auth-int is not handled, but will fall back to default qop. | |
252 "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth-int\"", | |
253 true, | |
254 "Oblivion", | |
255 "xyz", | |
256 "", | |
257 "", | |
258 false, | |
259 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
260 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
261 }, | |
262 | |
263 { // Unknown qop values are ignored. | |
264 "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth,foo\"", | |
265 true, | |
266 "Oblivion", | |
267 "xyz", | |
268 "", | |
269 "", | |
270 false, | |
271 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
272 HttpAuthHandlerDigest::QOP_AUTH | |
273 }, | |
274 | |
275 { // If auth-int is included with auth, then use auth. | |
276 "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth,auth-int\"", | |
277 true, | |
278 "Oblivion", | |
279 "xyz", | |
280 "", | |
281 "", | |
282 false, | |
283 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
284 HttpAuthHandlerDigest::QOP_AUTH | |
285 }, | |
286 | |
287 { // Opaque parameter parsing should work correctly. | |
288 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", opaque=\"foobar\"", | |
289 true, | |
290 "Thunder Bluff", | |
291 "xyz", | |
292 "", | |
293 "foobar", | |
294 false, | |
295 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
296 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
297 }, | |
298 | |
299 { // Opaque parameters do not need to be quoted, even though RFC2617 | |
300 // seems to require it. | |
301 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", opaque=foobar", | |
302 true, | |
303 "Thunder Bluff", | |
304 "xyz", | |
305 "", | |
306 "foobar", | |
307 false, | |
308 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
309 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
310 }, | |
311 | |
312 { // Domain can be parsed. | |
313 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", " | |
314 "domain=\"http://intranet.example.com/protection\"", | |
315 true, | |
316 "Thunder Bluff", | |
317 "xyz", | |
318 "http://intranet.example.com/protection", | |
319 "", | |
320 false, | |
321 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
322 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
323 }, | |
324 | |
325 { // Multiple domains can be parsed. | |
326 "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", " | |
327 "domain=\"http://intranet.example.com/protection http://www.google.com\"", | |
328 true, | |
329 "Thunder Bluff", | |
330 "xyz", | |
331 "http://intranet.example.com/protection http://www.google.com", | |
332 "", | |
333 false, | |
334 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
335 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
336 }, | |
337 | |
338 { // If a non-Digest scheme is somehow passed in, it should be rejected. | |
339 "Basic realm=\"foo\"", | |
340 false, | |
341 "", | |
342 "", | |
343 "", | |
344 "", | |
345 false, | |
346 HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, | |
347 HttpAuthHandlerDigest::QOP_UNSPECIFIED | |
348 }, | |
349 }; | |
350 | |
351 GURL origin("http://www.example.com"); | |
352 scoped_ptr<HttpAuthHandlerDigest::Factory> factory( | |
353 new HttpAuthHandlerDigest::Factory()); | |
354 for (size_t i = 0; i < arraysize(tests); ++i) { | |
355 scoped_ptr<HttpAuthHandler> handler; | |
356 int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, | |
357 HttpAuth::AUTH_SERVER, | |
358 origin, | |
359 BoundNetLog(), | |
360 &handler); | |
361 if (tests[i].parsed_success) { | |
362 EXPECT_EQ(OK, rv); | |
363 } else { | |
364 EXPECT_NE(OK, rv); | |
365 EXPECT_TRUE(handler.get() == NULL); | |
366 continue; | |
367 } | |
368 ASSERT_TRUE(handler.get() != NULL); | |
369 HttpAuthHandlerDigest* digest = | |
370 static_cast<HttpAuthHandlerDigest*>(handler.get()); | |
371 EXPECT_STREQ(tests[i].parsed_realm, digest->realm_.c_str()); | |
372 EXPECT_STREQ(tests[i].parsed_nonce, digest->nonce_.c_str()); | |
373 EXPECT_STREQ(tests[i].parsed_domain, digest->domain_.c_str()); | |
374 EXPECT_STREQ(tests[i].parsed_opaque, digest->opaque_.c_str()); | |
375 EXPECT_EQ(tests[i].parsed_stale, digest->stale_); | |
376 EXPECT_EQ(tests[i].parsed_algorithm, digest->algorithm_); | |
377 EXPECT_EQ(tests[i].parsed_qop, digest->qop_); | |
378 EXPECT_TRUE(handler->encrypts_identity()); | |
379 EXPECT_FALSE(handler->is_connection_based()); | |
380 EXPECT_TRUE(handler->NeedsIdentity()); | |
381 EXPECT_FALSE(handler->AllowsDefaultCredentials()); | |
382 } | |
383 } | |
384 | |
385 TEST(HttpAuthHandlerDigestTest, AssembleCredentials) { | |
386 static const struct { | |
387 const char* req_method; | |
388 const char* req_path; | |
389 const char* challenge; | |
390 const char* username; | |
391 const char* password; | |
392 const char* cnonce; | |
393 int nonce_count; | |
394 const char* expected_creds; | |
395 } tests[] = { | |
396 { // MD5 with username/password | |
397 "GET", | |
398 "/test/drealm1", | |
399 | |
400 // Challenge | |
401 "Digest realm=\"DRealm1\", " | |
402 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\", " | |
403 "algorithm=MD5, qop=\"auth\"", | |
404 | |
405 "foo", "bar", // username/password | |
406 "082c875dcb2ca740", // cnonce | |
407 1, // nc | |
408 | |
409 // Authorization | |
410 "Digest username=\"foo\", realm=\"DRealm1\", " | |
411 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\", " | |
412 "uri=\"/test/drealm1\", algorithm=MD5, " | |
413 "response=\"bcfaa62f1186a31ff1b474a19a17cf57\", " | |
414 "qop=auth, nc=00000001, cnonce=\"082c875dcb2ca740\"" | |
415 }, | |
416 | |
417 { // MD5 with username but empty password. username has space in it. | |
418 "GET", | |
419 "/test/drealm1/", | |
420 | |
421 // Challenge | |
422 "Digest realm=\"DRealm1\", " | |
423 "nonce=\"Ure30oRXBAA=7eca98bbf521ac6642820b11b86bd2d9ed7edc70\", " | |
424 "algorithm=MD5, qop=\"auth\"", | |
425 | |
426 "foo bar", "", // Username/password | |
427 "082c875dcb2ca740", // cnonce | |
428 1, // nc | |
429 | |
430 // Authorization | |
431 "Digest username=\"foo bar\", realm=\"DRealm1\", " | |
432 "nonce=\"Ure30oRXBAA=7eca98bbf521ac6642820b11b86bd2d9ed7edc70\", " | |
433 "uri=\"/test/drealm1/\", algorithm=MD5, " | |
434 "response=\"93c9c6d5930af3b0eb26c745e02b04a0\", " | |
435 "qop=auth, nc=00000001, cnonce=\"082c875dcb2ca740\"" | |
436 }, | |
437 | |
438 { // MD5 with no username. | |
439 "GET", | |
440 "/test/drealm1/", | |
441 | |
442 // Challenge | |
443 "Digest realm=\"DRealm1\", " | |
444 "nonce=\"7thGplhaBAA=41fb92453c49799cf353c8cd0aabee02d61a98a8\", " | |
445 "algorithm=MD5, qop=\"auth\"", | |
446 | |
447 "", "pass", // Username/password | |
448 "6509bc74daed8263", // cnonce | |
449 1, // nc | |
450 | |
451 // Authorization | |
452 "Digest username=\"\", realm=\"DRealm1\", " | |
453 "nonce=\"7thGplhaBAA=41fb92453c49799cf353c8cd0aabee02d61a98a8\", " | |
454 "uri=\"/test/drealm1/\", algorithm=MD5, " | |
455 "response=\"bc597110f41a62d07f8b70b6977fcb61\", " | |
456 "qop=auth, nc=00000001, cnonce=\"6509bc74daed8263\"" | |
457 }, | |
458 | |
459 { // MD5 with no username and no password. | |
460 "GET", | |
461 "/test/drealm1/", | |
462 | |
463 // Challenge | |
464 "Digest realm=\"DRealm1\", " | |
465 "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\", " | |
466 "algorithm=MD5, qop=\"auth\"", | |
467 | |
468 "", "", // Username/password | |
469 "1522e61005789929", // cnonce | |
470 1, // nc | |
471 | |
472 // Authorization | |
473 "Digest username=\"\", realm=\"DRealm1\", " | |
474 "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\", " | |
475 "uri=\"/test/drealm1/\", algorithm=MD5, " | |
476 "response=\"22cfa2b30cb500a9591c6d55ec5590a8\", " | |
477 "qop=auth, nc=00000001, cnonce=\"1522e61005789929\"" | |
478 }, | |
479 | |
480 { // No algorithm, and no qop. | |
481 "GET", | |
482 "/", | |
483 | |
484 // Challenge | |
485 "Digest realm=\"Oblivion\", nonce=\"nonce-value\"", | |
486 | |
487 "FooBar", "pass", // Username/password | |
488 "", // cnonce | |
489 1, // nc | |
490 | |
491 // Authorization | |
492 "Digest username=\"FooBar\", realm=\"Oblivion\", " | |
493 "nonce=\"nonce-value\", uri=\"/\", " | |
494 "response=\"f72ff54ebde2f928860f806ec04acd1b\"" | |
495 }, | |
496 | |
497 { // MD5-sess | |
498 "GET", | |
499 "/", | |
500 | |
501 // Challenge | |
502 "Digest realm=\"Baztastic\", nonce=\"AAAAAAAA\", " | |
503 "algorithm=\"md5-sess\", qop=auth", | |
504 | |
505 "USER", "123", // Username/password | |
506 "15c07961ed8575c4", // cnonce | |
507 1, // nc | |
508 | |
509 // Authorization | |
510 "Digest username=\"USER\", realm=\"Baztastic\", " | |
511 "nonce=\"AAAAAAAA\", uri=\"/\", algorithm=MD5-sess, " | |
512 "response=\"cbc1139821ee7192069580570c541a03\", " | |
513 "qop=auth, nc=00000001, cnonce=\"15c07961ed8575c4\"" | |
514 } | |
515 }; | |
516 GURL origin("http://www.example.com"); | |
517 scoped_ptr<HttpAuthHandlerDigest::Factory> factory( | |
518 new HttpAuthHandlerDigest::Factory()); | |
519 for (size_t i = 0; i < arraysize(tests); ++i) { | |
520 scoped_ptr<HttpAuthHandler> handler; | |
521 int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, | |
522 HttpAuth::AUTH_SERVER, | |
523 origin, | |
524 BoundNetLog(), | |
525 &handler); | |
526 EXPECT_EQ(OK, rv); | |
527 ASSERT_TRUE(handler != NULL); | |
528 | |
529 HttpAuthHandlerDigest* digest = | |
530 static_cast<HttpAuthHandlerDigest*>(handler.get()); | |
531 std::string creds = | |
532 digest->AssembleCredentials(tests[i].req_method, | |
533 tests[i].req_path, | |
534 AuthCredentials( | |
535 base::ASCIIToUTF16(tests[i].username), | |
536 base::ASCIIToUTF16(tests[i].password)), | |
537 tests[i].cnonce, | |
538 tests[i].nonce_count); | |
539 | |
540 EXPECT_STREQ(tests[i].expected_creds, creds.c_str()); | |
541 } | |
542 } | |
543 | |
544 TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) { | |
545 scoped_ptr<HttpAuthHandlerDigest::Factory> factory( | |
546 new HttpAuthHandlerDigest::Factory()); | |
547 scoped_ptr<HttpAuthHandler> handler; | |
548 std::string default_challenge = | |
549 "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; | |
550 GURL origin("intranet.google.com"); | |
551 int rv = factory->CreateAuthHandlerFromString( | |
552 default_challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), | |
553 &handler); | |
554 EXPECT_EQ(OK, rv); | |
555 ASSERT_TRUE(handler.get() != NULL); | |
556 HttpAuthChallengeTokenizer tok_default(default_challenge.begin(), | |
557 default_challenge.end()); | |
558 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
559 handler->HandleAnotherChallenge(&tok_default)); | |
560 | |
561 std::string stale_challenge = default_challenge + ", stale=true"; | |
562 HttpAuthChallengeTokenizer tok_stale(stale_challenge.begin(), | |
563 stale_challenge.end()); | |
564 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_STALE, | |
565 handler->HandleAnotherChallenge(&tok_stale)); | |
566 | |
567 std::string stale_false_challenge = default_challenge + ", stale=false"; | |
568 HttpAuthChallengeTokenizer tok_stale_false(stale_false_challenge.begin(), | |
569 stale_false_challenge.end()); | |
570 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
571 handler->HandleAnotherChallenge(&tok_stale_false)); | |
572 | |
573 std::string realm_change_challenge = | |
574 "Digest realm=\"SomethingElse\", nonce=\"nonce-value2\""; | |
575 HttpAuthChallengeTokenizer tok_realm_change(realm_change_challenge.begin(), | |
576 realm_change_challenge.end()); | |
577 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM, | |
578 handler->HandleAnotherChallenge(&tok_realm_change)); | |
579 } | |
580 | |
581 TEST(HttpAuthHandlerDigest, RespondToServerChallenge) { | |
582 std::string auth_token; | |
583 EXPECT_TRUE(RespondToChallenge( | |
584 HttpAuth::AUTH_SERVER, | |
585 std::string(), | |
586 "http://www.example.com/path/to/resource", | |
587 kSimpleChallenge, | |
588 &auth_token)); | |
589 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
590 "nonce=\"nonce-value\", uri=\"/path/to/resource\", " | |
591 "response=\"6779f90bd0d658f937c1af967614fe84\"", | |
592 auth_token); | |
593 } | |
594 | |
595 TEST(HttpAuthHandlerDigest, RespondToHttpsServerChallenge) { | |
596 std::string auth_token; | |
597 EXPECT_TRUE(RespondToChallenge( | |
598 HttpAuth::AUTH_SERVER, | |
599 std::string(), | |
600 "https://www.example.com/path/to/resource", | |
601 kSimpleChallenge, | |
602 &auth_token)); | |
603 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
604 "nonce=\"nonce-value\", uri=\"/path/to/resource\", " | |
605 "response=\"6779f90bd0d658f937c1af967614fe84\"", | |
606 auth_token); | |
607 } | |
608 | |
609 TEST(HttpAuthHandlerDigest, RespondToProxyChallenge) { | |
610 std::string auth_token; | |
611 EXPECT_TRUE(RespondToChallenge( | |
612 HttpAuth::AUTH_PROXY, | |
613 "http://proxy.intranet.corp.com:3128", | |
614 "http://www.example.com/path/to/resource", | |
615 kSimpleChallenge, | |
616 &auth_token)); | |
617 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
618 "nonce=\"nonce-value\", uri=\"/path/to/resource\", " | |
619 "response=\"6779f90bd0d658f937c1af967614fe84\"", | |
620 auth_token); | |
621 } | |
622 | |
623 TEST(HttpAuthHandlerDigest, RespondToProxyChallengeHttps) { | |
624 std::string auth_token; | |
625 EXPECT_TRUE(RespondToChallenge( | |
626 HttpAuth::AUTH_PROXY, | |
627 "http://proxy.intranet.corp.com:3128", | |
628 "https://www.example.com/path/to/resource", | |
629 kSimpleChallenge, | |
630 &auth_token)); | |
631 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
632 "nonce=\"nonce-value\", uri=\"www.example.com:443\", " | |
633 "response=\"3270da8467afbe9ddf2334a48d46e9b9\"", | |
634 auth_token); | |
635 } | |
636 | |
637 TEST(HttpAuthHandlerDigest, RespondToProxyChallengeWs) { | |
638 std::string auth_token; | |
639 EXPECT_TRUE(RespondToChallenge( | |
640 HttpAuth::AUTH_PROXY, | |
641 "http://proxy.intranet.corp.com:3128", | |
642 "ws://www.example.com/echo", | |
643 kSimpleChallenge, | |
644 &auth_token)); | |
645 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
646 "nonce=\"nonce-value\", uri=\"www.example.com:80\", " | |
647 "response=\"aa1df184f68d5b6ab9d9aa4f88e41b4c\"", | |
648 auth_token); | |
649 } | |
650 | |
651 TEST(HttpAuthHandlerDigest, RespondToProxyChallengeWss) { | |
652 std::string auth_token; | |
653 EXPECT_TRUE(RespondToChallenge( | |
654 HttpAuth::AUTH_PROXY, | |
655 "http://proxy.intranet.corp.com:3128", | |
656 "wss://www.example.com/echo", | |
657 kSimpleChallenge, | |
658 &auth_token)); | |
659 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
660 "nonce=\"nonce-value\", uri=\"www.example.com:443\", " | |
661 "response=\"3270da8467afbe9ddf2334a48d46e9b9\"", | |
662 auth_token); | |
663 } | |
664 | |
665 TEST(HttpAuthHandlerDigest, RespondToChallengeAuthQop) { | |
666 std::string auth_token; | |
667 EXPECT_TRUE(RespondToChallenge( | |
668 HttpAuth::AUTH_SERVER, | |
669 std::string(), | |
670 "http://www.example.com/path/to/resource", | |
671 "Digest realm=\"Oblivion\", nonce=\"nonce-value\", qop=\"auth\"", | |
672 &auth_token)); | |
673 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
674 "nonce=\"nonce-value\", uri=\"/path/to/resource\", " | |
675 "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " | |
676 "qop=auth, nc=00000001, cnonce=\"client_nonce\"", | |
677 auth_token); | |
678 } | |
679 | |
680 TEST(HttpAuthHandlerDigest, RespondToChallengeOpaque) { | |
681 std::string auth_token; | |
682 EXPECT_TRUE(RespondToChallenge( | |
683 HttpAuth::AUTH_SERVER, | |
684 std::string(), | |
685 "http://www.example.com/path/to/resource", | |
686 "Digest realm=\"Oblivion\", nonce=\"nonce-value\", " | |
687 "qop=\"auth\", opaque=\"opaque text\"", | |
688 &auth_token)); | |
689 EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " | |
690 "nonce=\"nonce-value\", uri=\"/path/to/resource\", " | |
691 "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " | |
692 "opaque=\"opaque text\", " | |
693 "qop=auth, nc=00000001, cnonce=\"client_nonce\"", | |
694 auth_token); | |
695 } | |
696 | |
697 | |
698 } // namespace net | |
OLD | NEW |