| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include "base/basictypes.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/test_completion_callback.h" |
| #include "net/http/http_auth_handler_digest.h" |
| #include "net/http/http_request_info.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| const char* const kSimpleChallenge = |
| "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; |
| |
| // RespondToChallenge creates an HttpAuthHandlerDigest for the specified |
| // |challenge|, and generates a response to the challenge which is returned in |
| // |token|. |
| // |
| // The return value indicates whether the |token| was successfully created. |
| // |
| // If |target| is HttpAuth::AUTH_PROXY, then |proxy_name| specifies the source |
| // of the |challenge|. Otherwise, the scheme and host and port of |request_url| |
| // indicates the origin of the challenge. |
| bool RespondToChallenge(HttpAuth::Target target, |
| const std::string& proxy_name, |
| const std::string& request_url, |
| const std::string& challenge, |
| std::string* token) { |
| // Input validation. |
| if (token == NULL) { |
| ADD_FAILURE() << "|token| must be non-NULL"; |
| return false; |
| } |
| EXPECT_TRUE(target != HttpAuth::AUTH_PROXY || !proxy_name.empty()); |
| EXPECT_FALSE(request_url.empty()); |
| EXPECT_FALSE(challenge.empty()); |
| |
| token->clear(); |
| scoped_ptr<HttpAuthHandlerDigest::Factory> factory( |
| new HttpAuthHandlerDigest::Factory()); |
| HttpAuthHandlerDigest::NonceGenerator* nonce_generator = |
| new HttpAuthHandlerDigest::FixedNonceGenerator("client_nonce"); |
| factory->set_nonce_generator(nonce_generator); |
| scoped_ptr<HttpAuthHandler> handler; |
| |
| // Create a handler for a particular challenge. |
| GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name); |
| int rv_create = factory->CreateAuthHandlerFromString( |
| challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler); |
| if (rv_create != OK || handler.get() == NULL) { |
| ADD_FAILURE() << "Unable to create auth handler."; |
| return false; |
| } |
| |
| // Create a token in response to the challenge. |
| // NOTE: HttpAuthHandlerDigest's implementation of GenerateAuthToken always |
| // completes synchronously. That's why this test can get away with a |
| // TestCompletionCallback without an IO thread. |
| TestCompletionCallback callback; |
| scoped_ptr<HttpRequestInfo> request(new HttpRequestInfo()); |
| request->url = GURL(request_url); |
| AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar")); |
| int rv_generate = handler->GenerateAuthToken( |
| &credentials, request.get(), callback.callback(), token); |
| if (rv_generate != OK) { |
| ADD_FAILURE() << "Problems generating auth token"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| } // namespace |
| |
| |
| TEST(HttpAuthHandlerDigestTest, ParseChallenge) { |
| static const struct { |
| // The challenge string. |
| const char* challenge; |
| // Expected return value of ParseChallenge. |
| bool parsed_success; |
| // The expected values that were parsed. |
| const char* parsed_realm; |
| const char* parsed_nonce; |
| const char* parsed_domain; |
| const char* parsed_opaque; |
| bool parsed_stale; |
| int parsed_algorithm; |
| int parsed_qop; |
| } tests[] = { |
| { // Check that a minimal challenge works correctly. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Realm does not need to be quoted, even though RFC2617 requires it. |
| "Digest nonce=\"xyz\", realm=ThunderBluff", |
| true, |
| "ThunderBluff", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // We allow the realm to be omitted, and will default it to empty string. |
| // See http://crbug.com/20984. |
| "Digest nonce=\"xyz\"", |
| true, |
| "", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Try with realm set to empty string. |
| "Digest realm=\"\", nonce=\"xyz\"", |
| true, |
| "", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| // Handle ISO-8859-1 character as part of the realm. The realm is converted |
| // to UTF-8. However, the credentials will still use the original encoding. |
| { |
| "Digest nonce=\"xyz\", realm=\"foo-\xE5\"", |
| true, |
| "foo-\xC3\xA5", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED, |
| }, |
| |
| { // At a minimum, a nonce must be provided. |
| "Digest realm=\"Thunder Bluff\"", |
| false, |
| "", |
| "", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // The nonce does not need to be quoted, even though RFC2617 |
| // requires it. |
| "Digest nonce=xyz, realm=\"Thunder Bluff\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Unknown authentication parameters are ignored. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", foo=\"bar\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Check that when algorithm has an unsupported value, parsing fails. |
| "Digest nonce=\"xyz\", algorithm=\"awezum\", realm=\"Thunder\"", |
| false, |
| // The remaining values don't matter (but some have been set already). |
| "", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Check that algorithm's value is case insensitive, and that MD5 is |
| // a supported algorithm. |
| "Digest nonce=\"xyz\", algorithm=\"mD5\", realm=\"Oblivion\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_MD5, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Check that md5-sess is a supported algorithm. |
| "Digest nonce=\"xyz\", algorithm=\"md5-sess\", realm=\"Oblivion\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_MD5_SESS, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED, |
| }, |
| |
| { // Check that qop's value is case insensitive, and that auth is known. |
| "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"aUth\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_AUTH |
| }, |
| |
| { // auth-int is not handled, but will fall back to default qop. |
| "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth-int\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Unknown qop values are ignored. |
| "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth,foo\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_AUTH |
| }, |
| |
| { // If auth-int is included with auth, then use auth. |
| "Digest nonce=\"xyz\", realm=\"Oblivion\", qop=\"auth,auth-int\"", |
| true, |
| "Oblivion", |
| "xyz", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_AUTH |
| }, |
| |
| { // Opaque parameter parsing should work correctly. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", opaque=\"foobar\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "", |
| "foobar", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Opaque parameters do not need to be quoted, even though RFC2617 |
| // seems to require it. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", opaque=foobar", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "", |
| "foobar", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Domain can be parsed. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", " |
| "domain=\"http://intranet.example.com/protection\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "http://intranet.example.com/protection", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // Multiple domains can be parsed. |
| "Digest nonce=\"xyz\", realm=\"Thunder Bluff\", " |
| "domain=\"http://intranet.example.com/protection http://www.google.com\"", |
| true, |
| "Thunder Bluff", |
| "xyz", |
| "http://intranet.example.com/protection http://www.google.com", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| |
| { // If a non-Digest scheme is somehow passed in, it should be rejected. |
| "Basic realm=\"foo\"", |
| false, |
| "", |
| "", |
| "", |
| "", |
| false, |
| HttpAuthHandlerDigest::ALGORITHM_UNSPECIFIED, |
| HttpAuthHandlerDigest::QOP_UNSPECIFIED |
| }, |
| }; |
| |
| GURL origin("http://www.example.com"); |
| scoped_ptr<HttpAuthHandlerDigest::Factory> factory( |
| new HttpAuthHandlerDigest::Factory()); |
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| scoped_ptr<HttpAuthHandler> handler; |
| int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, |
| HttpAuth::AUTH_SERVER, |
| origin, |
| BoundNetLog(), |
| &handler); |
| if (tests[i].parsed_success) { |
| EXPECT_EQ(OK, rv); |
| } else { |
| EXPECT_NE(OK, rv); |
| EXPECT_TRUE(handler.get() == NULL); |
| continue; |
| } |
| ASSERT_TRUE(handler.get() != NULL); |
| HttpAuthHandlerDigest* digest = |
| static_cast<HttpAuthHandlerDigest*>(handler.get()); |
| EXPECT_STREQ(tests[i].parsed_realm, digest->realm_.c_str()); |
| EXPECT_STREQ(tests[i].parsed_nonce, digest->nonce_.c_str()); |
| EXPECT_STREQ(tests[i].parsed_domain, digest->domain_.c_str()); |
| EXPECT_STREQ(tests[i].parsed_opaque, digest->opaque_.c_str()); |
| EXPECT_EQ(tests[i].parsed_stale, digest->stale_); |
| EXPECT_EQ(tests[i].parsed_algorithm, digest->algorithm_); |
| EXPECT_EQ(tests[i].parsed_qop, digest->qop_); |
| EXPECT_TRUE(handler->encrypts_identity()); |
| EXPECT_FALSE(handler->is_connection_based()); |
| EXPECT_TRUE(handler->NeedsIdentity()); |
| EXPECT_FALSE(handler->AllowsDefaultCredentials()); |
| } |
| } |
| |
| TEST(HttpAuthHandlerDigestTest, AssembleCredentials) { |
| static const struct { |
| const char* req_method; |
| const char* req_path; |
| const char* challenge; |
| const char* username; |
| const char* password; |
| const char* cnonce; |
| int nonce_count; |
| const char* expected_creds; |
| } tests[] = { |
| { // MD5 with username/password |
| "GET", |
| "/test/drealm1", |
| |
| // Challenge |
| "Digest realm=\"DRealm1\", " |
| "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\", " |
| "algorithm=MD5, qop=\"auth\"", |
| |
| "foo", "bar", // username/password |
| "082c875dcb2ca740", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"foo\", realm=\"DRealm1\", " |
| "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\", " |
| "uri=\"/test/drealm1\", algorithm=MD5, " |
| "response=\"bcfaa62f1186a31ff1b474a19a17cf57\", " |
| "qop=auth, nc=00000001, cnonce=\"082c875dcb2ca740\"" |
| }, |
| |
| { // MD5 with username but empty password. username has space in it. |
| "GET", |
| "/test/drealm1/", |
| |
| // Challenge |
| "Digest realm=\"DRealm1\", " |
| "nonce=\"Ure30oRXBAA=7eca98bbf521ac6642820b11b86bd2d9ed7edc70\", " |
| "algorithm=MD5, qop=\"auth\"", |
| |
| "foo bar", "", // Username/password |
| "082c875dcb2ca740", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"foo bar\", realm=\"DRealm1\", " |
| "nonce=\"Ure30oRXBAA=7eca98bbf521ac6642820b11b86bd2d9ed7edc70\", " |
| "uri=\"/test/drealm1/\", algorithm=MD5, " |
| "response=\"93c9c6d5930af3b0eb26c745e02b04a0\", " |
| "qop=auth, nc=00000001, cnonce=\"082c875dcb2ca740\"" |
| }, |
| |
| { // MD5 with no username. |
| "GET", |
| "/test/drealm1/", |
| |
| // Challenge |
| "Digest realm=\"DRealm1\", " |
| "nonce=\"7thGplhaBAA=41fb92453c49799cf353c8cd0aabee02d61a98a8\", " |
| "algorithm=MD5, qop=\"auth\"", |
| |
| "", "pass", // Username/password |
| "6509bc74daed8263", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"\", realm=\"DRealm1\", " |
| "nonce=\"7thGplhaBAA=41fb92453c49799cf353c8cd0aabee02d61a98a8\", " |
| "uri=\"/test/drealm1/\", algorithm=MD5, " |
| "response=\"bc597110f41a62d07f8b70b6977fcb61\", " |
| "qop=auth, nc=00000001, cnonce=\"6509bc74daed8263\"" |
| }, |
| |
| { // MD5 with no username and no password. |
| "GET", |
| "/test/drealm1/", |
| |
| // Challenge |
| "Digest realm=\"DRealm1\", " |
| "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\", " |
| "algorithm=MD5, qop=\"auth\"", |
| |
| "", "", // Username/password |
| "1522e61005789929", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"\", realm=\"DRealm1\", " |
| "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\", " |
| "uri=\"/test/drealm1/\", algorithm=MD5, " |
| "response=\"22cfa2b30cb500a9591c6d55ec5590a8\", " |
| "qop=auth, nc=00000001, cnonce=\"1522e61005789929\"" |
| }, |
| |
| { // No algorithm, and no qop. |
| "GET", |
| "/", |
| |
| // Challenge |
| "Digest realm=\"Oblivion\", nonce=\"nonce-value\"", |
| |
| "FooBar", "pass", // Username/password |
| "", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"FooBar\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/\", " |
| "response=\"f72ff54ebde2f928860f806ec04acd1b\"" |
| }, |
| |
| { // MD5-sess |
| "GET", |
| "/", |
| |
| // Challenge |
| "Digest realm=\"Baztastic\", nonce=\"AAAAAAAA\", " |
| "algorithm=\"md5-sess\", qop=auth", |
| |
| "USER", "123", // Username/password |
| "15c07961ed8575c4", // cnonce |
| 1, // nc |
| |
| // Authorization |
| "Digest username=\"USER\", realm=\"Baztastic\", " |
| "nonce=\"AAAAAAAA\", uri=\"/\", algorithm=MD5-sess, " |
| "response=\"cbc1139821ee7192069580570c541a03\", " |
| "qop=auth, nc=00000001, cnonce=\"15c07961ed8575c4\"" |
| } |
| }; |
| GURL origin("http://www.example.com"); |
| scoped_ptr<HttpAuthHandlerDigest::Factory> factory( |
| new HttpAuthHandlerDigest::Factory()); |
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| scoped_ptr<HttpAuthHandler> handler; |
| int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, |
| HttpAuth::AUTH_SERVER, |
| origin, |
| BoundNetLog(), |
| &handler); |
| EXPECT_EQ(OK, rv); |
| ASSERT_TRUE(handler != NULL); |
| |
| HttpAuthHandlerDigest* digest = |
| static_cast<HttpAuthHandlerDigest*>(handler.get()); |
| std::string creds = |
| digest->AssembleCredentials(tests[i].req_method, |
| tests[i].req_path, |
| AuthCredentials( |
| ASCIIToUTF16(tests[i].username), |
| ASCIIToUTF16(tests[i].password)), |
| tests[i].cnonce, |
| tests[i].nonce_count); |
| |
| EXPECT_STREQ(tests[i].expected_creds, creds.c_str()); |
| } |
| } |
| |
| TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) { |
| scoped_ptr<HttpAuthHandlerDigest::Factory> factory( |
| new HttpAuthHandlerDigest::Factory()); |
| scoped_ptr<HttpAuthHandler> handler; |
| std::string default_challenge = |
| "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; |
| GURL origin("intranet.google.com"); |
| int rv = factory->CreateAuthHandlerFromString( |
| default_challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), |
| &handler); |
| EXPECT_EQ(OK, rv); |
| ASSERT_TRUE(handler.get() != NULL); |
| HttpAuth::ChallengeTokenizer tok_default(default_challenge.begin(), |
| default_challenge.end()); |
| EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| handler->HandleAnotherChallenge(&tok_default)); |
| |
| std::string stale_challenge = default_challenge + ", stale=true"; |
| HttpAuth::ChallengeTokenizer tok_stale(stale_challenge.begin(), |
| stale_challenge.end()); |
| EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_STALE, |
| handler->HandleAnotherChallenge(&tok_stale)); |
| |
| std::string stale_false_challenge = default_challenge + ", stale=false"; |
| HttpAuth::ChallengeTokenizer tok_stale_false(stale_false_challenge.begin(), |
| stale_false_challenge.end()); |
| EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| handler->HandleAnotherChallenge(&tok_stale_false)); |
| |
| std::string realm_change_challenge = |
| "Digest realm=\"SomethingElse\", nonce=\"nonce-value2\""; |
| HttpAuth::ChallengeTokenizer tok_realm_change(realm_change_challenge.begin(), |
| realm_change_challenge.end()); |
| EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM, |
| handler->HandleAnotherChallenge(&tok_realm_change)); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToServerChallenge) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_SERVER, |
| std::string(), |
| "http://www.example.com/path/to/resource", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/path/to/resource\", " |
| "response=\"6779f90bd0d658f937c1af967614fe84\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToHttpsServerChallenge) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_SERVER, |
| std::string(), |
| "https://www.example.com/path/to/resource", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/path/to/resource\", " |
| "response=\"6779f90bd0d658f937c1af967614fe84\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToProxyChallenge) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_PROXY, |
| "http://proxy.intranet.corp.com:3128", |
| "http://www.example.com/path/to/resource", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/path/to/resource\", " |
| "response=\"6779f90bd0d658f937c1af967614fe84\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToProxyChallengeHttps) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_PROXY, |
| "http://proxy.intranet.corp.com:3128", |
| "https://www.example.com/path/to/resource", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"www.example.com:443\", " |
| "response=\"3270da8467afbe9ddf2334a48d46e9b9\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToProxyChallengeWs) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_PROXY, |
| "http://proxy.intranet.corp.com:3128", |
| "ws://www.example.com/echo", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"www.example.com:80\", " |
| "response=\"aa1df184f68d5b6ab9d9aa4f88e41b4c\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToProxyChallengeWss) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_PROXY, |
| "http://proxy.intranet.corp.com:3128", |
| "wss://www.example.com/echo", |
| kSimpleChallenge, |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"www.example.com:443\", " |
| "response=\"3270da8467afbe9ddf2334a48d46e9b9\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToChallengeAuthQop) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_SERVER, |
| std::string(), |
| "http://www.example.com/path/to/resource", |
| "Digest realm=\"Oblivion\", nonce=\"nonce-value\", qop=\"auth\"", |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/path/to/resource\", " |
| "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " |
| "qop=auth, nc=00000001, cnonce=\"client_nonce\"", |
| auth_token); |
| } |
| |
| TEST(HttpAuthHandlerDigest, RespondToChallengeOpaque) { |
| std::string auth_token; |
| EXPECT_TRUE(RespondToChallenge( |
| HttpAuth::AUTH_SERVER, |
| std::string(), |
| "http://www.example.com/path/to/resource", |
| "Digest realm=\"Oblivion\", nonce=\"nonce-value\", " |
| "qop=\"auth\", opaque=\"opaque text\"", |
| &auth_token)); |
| EXPECT_EQ("Digest username=\"foo\", realm=\"Oblivion\", " |
| "nonce=\"nonce-value\", uri=\"/path/to/resource\", " |
| "response=\"5b1459beda5cee30d6ff9e970a69c0ea\", " |
| "opaque=\"opaque text\", " |
| "qop=auth, nc=00000001, cnonce=\"client_nonce\"", |
| auth_token); |
| } |
| |
| |
| } // namespace net |