Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / http_auth_handler_digest_unittest.cc
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