| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <set> | 5 #include <set> |
| 6 #include <string> | 6 #include <string> |
| 7 | 7 |
| 8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 namespace net { | 24 namespace net { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { | 28 HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { |
| 29 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); | 29 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); |
| 30 auth_handler->set_connection_based(connection_based); | 30 auth_handler->set_connection_based(connection_based); |
| 31 std::string challenge_text = "Basic"; | 31 std::string challenge_text = "Basic"; |
| 32 HttpAuthChallengeTokenizer challenge(challenge_text.begin(), | 32 HttpAuthChallengeTokenizer challenge(challenge_text.begin(), |
| 33 challenge_text.end()); | 33 challenge_text.end()); |
| 34 GURL origin("www.example.com"); | 34 GURL origin("www.example.com"); |
| 35 EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge, | 35 EXPECT_TRUE(auth_handler->InitFromChallenge( |
| 36 HttpAuth::AUTH_SERVER, | 36 &challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog())); |
| 37 origin, | |
| 38 BoundNetLog())); | |
| 39 return auth_handler; | 37 return auth_handler; |
| 40 } | 38 } |
| 41 | 39 |
| 42 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) { | 40 HttpResponseHeaders* HeadersFromResponseText(const std::string& response) { |
| 43 return new HttpResponseHeaders( | 41 return new HttpResponseHeaders( |
| 44 HttpUtil::AssembleRawHeaders(response.c_str(), response.length())); | 42 HttpUtil::AssembleRawHeaders(response.c_str(), response.length())); |
| 45 } | 43 } |
| 46 | 44 |
| 47 HttpAuth::AuthorizationResult HandleChallengeResponse( | 45 HttpAuth::AuthorizationResult HandleChallengeResponse( |
| 48 bool connection_based, | 46 bool connection_based, |
| 49 const std::string& headers_text, | 47 const std::string& headers_text, |
| 50 std::string* challenge_used) { | 48 std::string* challenge_used) { |
| 51 scoped_ptr<HttpAuthHandlerMock> mock_handler( | 49 scoped_ptr<HttpAuthHandlerMock> mock_handler( |
| 52 CreateMockHandler(connection_based)); | 50 CreateMockHandler(connection_based)); |
| 53 std::set<HttpAuth::Scheme> disabled_schemes; | 51 std::set<HttpAuth::Scheme> disabled_schemes; |
| 54 scoped_refptr<HttpResponseHeaders> headers( | 52 scoped_refptr<HttpResponseHeaders> headers( |
| 55 HeadersFromResponseText(headers_text)); | 53 HeadersFromResponseText(headers_text)); |
| 56 return HttpAuth::HandleChallengeResponse( | 54 return HttpAuth::HandleChallengeResponse(mock_handler.get(), |
| 57 mock_handler.get(), | 55 headers.get(), |
| 58 headers.get(), | 56 HttpAuth::AUTH_SERVER, |
| 59 HttpAuth::AUTH_SERVER, | 57 disabled_schemes, |
| 60 disabled_schemes, | 58 challenge_used); |
| 61 challenge_used); | |
| 62 } | 59 } |
| 63 | 60 |
| 64 } // namespace | 61 } // namespace |
| 65 | 62 |
| 66 TEST(HttpAuthTest, ChooseBestChallenge) { | 63 TEST(HttpAuthTest, ChooseBestChallenge) { |
| 67 static const struct { | 64 static const struct { |
| 68 const char* headers; | 65 const char* headers; |
| 69 HttpAuth::Scheme challenge_scheme; | 66 HttpAuth::Scheme challenge_scheme; |
| 70 const char* challenge_realm; | 67 const char* challenge_realm; |
| 71 } tests[] = { | 68 } tests[] = {{// Basic is the only challenge type, pick it. |
| 72 { | 69 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" |
| 73 // Basic is the only challenge type, pick it. | 70 "www-authenticate: Basic realm=\"BasicRealm\"\n", |
| 74 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" | 71 HttpAuth::AUTH_SCHEME_BASIC, "BasicRealm", |
| 75 "www-authenticate: Basic realm=\"BasicRealm\"\n", | 72 }, |
| 76 | 73 {// Fake is the only challenge type, but it is unsupported. |
| 77 HttpAuth::AUTH_SCHEME_BASIC, | 74 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n" |
| 78 "BasicRealm", | 75 "www-authenticate: Fake realm=\"FooBar\"\n", |
| 79 }, | 76 HttpAuth::AUTH_SCHEME_MAX, "", |
| 80 { | 77 }, |
| 81 // Fake is the only challenge type, but it is unsupported. | 78 {// Pick Digest over Basic. |
| 82 "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n" | 79 "www-authenticate: Basic realm=\"FooBar\"\n" |
| 83 "www-authenticate: Fake realm=\"FooBar\"\n", | 80 "www-authenticate: Fake realm=\"FooBar\"\n" |
| 84 | 81 "www-authenticate: nonce=\"aaaaaaaaaa\"\n" |
| 85 HttpAuth::AUTH_SCHEME_MAX, | 82 "www-authenticate: Digest realm=\"DigestRealm\", " |
| 86 "", | 83 "nonce=\"aaaaaaaaaa\"\n", |
| 87 }, | 84 HttpAuth::AUTH_SCHEME_DIGEST, "DigestRealm", |
| 88 { | 85 }, |
| 89 // Pick Digest over Basic. | 86 {// Handle an empty header correctly. |
| 90 "www-authenticate: Basic realm=\"FooBar\"\n" | 87 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" |
| 91 "www-authenticate: Fake realm=\"FooBar\"\n" | 88 "www-authenticate:\n", |
| 92 "www-authenticate: nonce=\"aaaaaaaaaa\"\n" | 89 HttpAuth::AUTH_SCHEME_MAX, "", |
| 93 "www-authenticate: Digest realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"\n", | 90 }, |
| 94 | 91 { |
| 95 HttpAuth::AUTH_SCHEME_DIGEST, | 92 "WWW-Authenticate: Negotiate\n" |
| 96 "DigestRealm", | 93 "WWW-Authenticate: NTLM\n", |
| 97 }, | |
| 98 { | |
| 99 // Handle an empty header correctly. | |
| 100 "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n" | |
| 101 "www-authenticate:\n", | |
| 102 | |
| 103 HttpAuth::AUTH_SCHEME_MAX, | |
| 104 "", | |
| 105 }, | |
| 106 { | |
| 107 "WWW-Authenticate: Negotiate\n" | |
| 108 "WWW-Authenticate: NTLM\n", | |
| 109 | 94 |
| 110 #if defined(USE_KERBEROS) | 95 #if defined(USE_KERBEROS) |
| 111 // Choose Negotiate over NTLM on all platforms. | 96 // Choose Negotiate over NTLM on all platforms. |
| 112 // TODO(ahendrickson): This may be flaky on Linux and OSX as it | 97 // TODO(ahendrickson): This may be flaky on Linux and OSX as it |
| 113 // relies on being able to load one of the known .so files | 98 // relies on being able to load one of the known .so files |
| 114 // for gssapi. | 99 // for gssapi. |
| 115 HttpAuth::AUTH_SCHEME_NEGOTIATE, | 100 HttpAuth::AUTH_SCHEME_NEGOTIATE, |
| 116 #else | 101 #else |
| 117 // On systems that don't use Kerberos fall back to NTLM. | 102 // On systems that don't use Kerberos fall back to NTLM. |
| 118 HttpAuth::AUTH_SCHEME_NTLM, | 103 HttpAuth::AUTH_SCHEME_NTLM, |
| 119 #endif // defined(USE_KERBEROS) | 104 #endif // defined(USE_KERBEROS) |
| 120 "", | 105 "", |
| 121 } | 106 }}; |
| 122 }; | |
| 123 GURL origin("http://www.example.com"); | 107 GURL origin("http://www.example.com"); |
| 124 std::set<HttpAuth::Scheme> disabled_schemes; | 108 std::set<HttpAuth::Scheme> disabled_schemes; |
| 125 MockAllowURLSecurityManager url_security_manager; | 109 MockAllowURLSecurityManager url_security_manager; |
| 126 scoped_ptr<HostResolver> host_resolver(new MockHostResolver()); | 110 scoped_ptr<HostResolver> host_resolver(new MockHostResolver()); |
| 127 scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory( | 111 scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory( |
| 128 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); | 112 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); |
| 129 http_auth_handler_factory->SetURLSecurityManager( | 113 http_auth_handler_factory->SetURLSecurityManager("negotiate", |
| 130 "negotiate", &url_security_manager); | 114 &url_security_manager); |
| 131 | 115 |
| 132 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 116 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 133 // Make a HttpResponseHeaders object. | 117 // Make a HttpResponseHeaders object. |
| 134 std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n"); | 118 std::string headers_with_status_line("HTTP/1.1 401 Unauthorized\n"); |
| 135 headers_with_status_line += tests[i].headers; | 119 headers_with_status_line += tests[i].headers; |
| 136 scoped_refptr<HttpResponseHeaders> headers( | 120 scoped_refptr<HttpResponseHeaders> headers( |
| 137 HeadersFromResponseText(headers_with_status_line)); | 121 HeadersFromResponseText(headers_with_status_line)); |
| 138 | 122 |
| 139 scoped_ptr<HttpAuthHandler> handler; | 123 scoped_ptr<HttpAuthHandler> handler; |
| 140 HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), | 124 HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 156 } | 140 } |
| 157 | 141 |
| 158 TEST(HttpAuthTest, HandleChallengeResponse) { | 142 TEST(HttpAuthTest, HandleChallengeResponse) { |
| 159 std::string challenge_used; | 143 std::string challenge_used; |
| 160 const char* const kMockChallenge = | 144 const char* const kMockChallenge = |
| 161 "HTTP/1.1 401 Unauthorized\n" | 145 "HTTP/1.1 401 Unauthorized\n" |
| 162 "WWW-Authenticate: Mock token_here\n"; | 146 "WWW-Authenticate: Mock token_here\n"; |
| 163 const char* const kBasicChallenge = | 147 const char* const kBasicChallenge = |
| 164 "HTTP/1.1 401 Unauthorized\n" | 148 "HTTP/1.1 401 Unauthorized\n" |
| 165 "WWW-Authenticate: Basic realm=\"happy\"\n"; | 149 "WWW-Authenticate: Basic realm=\"happy\"\n"; |
| 166 const char* const kMissingChallenge = | 150 const char* const kMissingChallenge = "HTTP/1.1 401 Unauthorized\n"; |
| 167 "HTTP/1.1 401 Unauthorized\n"; | |
| 168 const char* const kEmptyChallenge = | 151 const char* const kEmptyChallenge = |
| 169 "HTTP/1.1 401 Unauthorized\n" | 152 "HTTP/1.1 401 Unauthorized\n" |
| 170 "WWW-Authenticate: \n"; | 153 "WWW-Authenticate: \n"; |
| 171 const char* const kBasicAndMockChallenges = | 154 const char* const kBasicAndMockChallenges = |
| 172 "HTTP/1.1 401 Unauthorized\n" | 155 "HTTP/1.1 401 Unauthorized\n" |
| 173 "WWW-Authenticate: Basic realm=\"happy\"\n" | 156 "WWW-Authenticate: Basic realm=\"happy\"\n" |
| 174 "WWW-Authenticate: Mock token_here\n"; | 157 "WWW-Authenticate: Mock token_here\n"; |
| 175 const char* const kTwoMockChallenges = | 158 const char* const kTwoMockChallenges = |
| 176 "HTTP/1.1 401 Unauthorized\n" | 159 "HTTP/1.1 401 Unauthorized\n" |
| 177 "WWW-Authenticate: Mock token_a\n" | 160 "WWW-Authenticate: Mock token_a\n" |
| 178 "WWW-Authenticate: Mock token_b\n"; | 161 "WWW-Authenticate: Mock token_b\n"; |
| 179 | 162 |
| 180 // Request based schemes should treat any new challenges as rejections of the | 163 // Request based schemes should treat any new challenges as rejections of the |
| 181 // previous authentication attempt. (There is a slight exception for digest | 164 // previous authentication attempt. (There is a slight exception for digest |
| 182 // authentication and the stale parameter, but that is covered in the | 165 // authentication and the stale parameter, but that is covered in the |
| 183 // http_auth_handler_digest_unittests). | 166 // http_auth_handler_digest_unittests). |
| 184 EXPECT_EQ( | 167 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 185 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 168 HandleChallengeResponse(false, kMockChallenge, &challenge_used)); |
| 186 HandleChallengeResponse(false, kMockChallenge, &challenge_used)); | |
| 187 EXPECT_EQ("Mock token_here", challenge_used); | 169 EXPECT_EQ("Mock token_here", challenge_used); |
| 188 | 170 |
| 189 EXPECT_EQ( | 171 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 190 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 172 HandleChallengeResponse(false, kBasicChallenge, &challenge_used)); |
| 191 HandleChallengeResponse(false, kBasicChallenge, &challenge_used)); | 173 EXPECT_EQ("", challenge_used); |
| 174 |
| 175 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 176 HandleChallengeResponse(false, kMissingChallenge, &challenge_used)); |
| 177 EXPECT_EQ("", challenge_used); |
| 178 |
| 179 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 180 HandleChallengeResponse(false, kEmptyChallenge, &challenge_used)); |
| 192 EXPECT_EQ("", challenge_used); | 181 EXPECT_EQ("", challenge_used); |
| 193 | 182 |
| 194 EXPECT_EQ( | 183 EXPECT_EQ( |
| 195 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
| 196 HandleChallengeResponse(false, kMissingChallenge, &challenge_used)); | |
| 197 EXPECT_EQ("", challenge_used); | |
| 198 | |
| 199 EXPECT_EQ( | |
| 200 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
| 201 HandleChallengeResponse(false, kEmptyChallenge, &challenge_used)); | |
| 202 EXPECT_EQ("", challenge_used); | |
| 203 | |
| 204 EXPECT_EQ( | |
| 205 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 184 HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 206 HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used)); | 185 HandleChallengeResponse(false, kBasicAndMockChallenges, &challenge_used)); |
| 207 EXPECT_EQ("Mock token_here", challenge_used); | 186 EXPECT_EQ("Mock token_here", challenge_used); |
| 208 | 187 |
| 209 EXPECT_EQ( | 188 EXPECT_EQ( |
| 210 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 189 HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 211 HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used)); | 190 HandleChallengeResponse(false, kTwoMockChallenges, &challenge_used)); |
| 212 EXPECT_EQ("Mock token_a", challenge_used); | 191 EXPECT_EQ("Mock token_a", challenge_used); |
| 213 | 192 |
| 214 // Connection based schemes will treat new auth challenges for the same scheme | 193 // Connection based schemes will treat new auth challenges for the same scheme |
| 215 // as acceptance (and continuance) of the current approach. If there are | 194 // as acceptance (and continuance) of the current approach. If there are |
| 216 // no auth challenges for the same scheme, the response will be treated as | 195 // no auth challenges for the same scheme, the response will be treated as |
| 217 // a rejection. | 196 // a rejection. |
| 218 EXPECT_EQ( | 197 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 219 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 198 HandleChallengeResponse(true, kMockChallenge, &challenge_used)); |
| 220 HandleChallengeResponse(true, kMockChallenge, &challenge_used)); | |
| 221 EXPECT_EQ("Mock token_here", challenge_used); | 199 EXPECT_EQ("Mock token_here", challenge_used); |
| 222 | 200 |
| 223 EXPECT_EQ( | 201 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 224 HttpAuth::AUTHORIZATION_RESULT_REJECT, | 202 HandleChallengeResponse(true, kBasicChallenge, &challenge_used)); |
| 225 HandleChallengeResponse(true, kBasicChallenge, &challenge_used)); | 203 EXPECT_EQ("", challenge_used); |
| 204 |
| 205 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 206 HandleChallengeResponse(true, kMissingChallenge, &challenge_used)); |
| 207 EXPECT_EQ("", challenge_used); |
| 208 |
| 209 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT, |
| 210 HandleChallengeResponse(true, kEmptyChallenge, &challenge_used)); |
| 226 EXPECT_EQ("", challenge_used); | 211 EXPECT_EQ("", challenge_used); |
| 227 | 212 |
| 228 EXPECT_EQ( | 213 EXPECT_EQ( |
| 229 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
| 230 HandleChallengeResponse(true, kMissingChallenge, &challenge_used)); | |
| 231 EXPECT_EQ("", challenge_used); | |
| 232 | |
| 233 EXPECT_EQ( | |
| 234 HttpAuth::AUTHORIZATION_RESULT_REJECT, | |
| 235 HandleChallengeResponse(true, kEmptyChallenge, &challenge_used)); | |
| 236 EXPECT_EQ("", challenge_used); | |
| 237 | |
| 238 EXPECT_EQ( | |
| 239 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 214 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 240 HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used)); | 215 HandleChallengeResponse(true, kBasicAndMockChallenges, &challenge_used)); |
| 241 EXPECT_EQ("Mock token_here", challenge_used); | 216 EXPECT_EQ("Mock token_here", challenge_used); |
| 242 | 217 |
| 243 EXPECT_EQ( | 218 EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT, |
| 244 HttpAuth::AUTHORIZATION_RESULT_ACCEPT, | 219 HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used)); |
| 245 HandleChallengeResponse(true, kTwoMockChallenges, &challenge_used)); | |
| 246 EXPECT_EQ("Mock token_a", challenge_used); | 220 EXPECT_EQ("Mock token_a", challenge_used); |
| 247 } | 221 } |
| 248 | 222 |
| 249 TEST(HttpAuthTest, GetChallengeHeaderName) { | 223 TEST(HttpAuthTest, GetChallengeHeaderName) { |
| 250 std::string name; | 224 std::string name; |
| 251 | 225 |
| 252 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER); | 226 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_SERVER); |
| 253 EXPECT_STREQ("WWW-Authenticate", name.c_str()); | 227 EXPECT_STREQ("WWW-Authenticate", name.c_str()); |
| 254 | 228 |
| 255 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY); | 229 name = HttpAuth::GetChallengeHeaderName(HttpAuth::AUTH_PROXY); |
| 256 EXPECT_STREQ("Proxy-Authenticate", name.c_str()); | 230 EXPECT_STREQ("Proxy-Authenticate", name.c_str()); |
| 257 } | 231 } |
| 258 | 232 |
| 259 TEST(HttpAuthTest, GetAuthorizationHeaderName) { | 233 TEST(HttpAuthTest, GetAuthorizationHeaderName) { |
| 260 std::string name; | 234 std::string name; |
| 261 | 235 |
| 262 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER); | 236 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER); |
| 263 EXPECT_STREQ("Authorization", name.c_str()); | 237 EXPECT_STREQ("Authorization", name.c_str()); |
| 264 | 238 |
| 265 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY); | 239 name = HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY); |
| 266 EXPECT_STREQ("Proxy-Authorization", name.c_str()); | 240 EXPECT_STREQ("Proxy-Authorization", name.c_str()); |
| 267 } | 241 } |
| 268 | 242 |
| 269 } // namespace net | 243 } // namespace net |
| OLD | NEW |