| 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 |