| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "net/http/http_auth_handler_negotiate.h" | 5 #include "net/http/http_auth_handler_negotiate.h" |
| 6 | 6 |
| 7 #include "net/base/mock_host_resolver.h" | 7 #include "net/base/mock_host_resolver.h" |
| 8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 9 #include "net/base/test_completion_callback.h" | 9 #include "net/base/test_completion_callback.h" |
| 10 #include "net/http/http_request_info.h" | 10 #include "net/http/http_request_info.h" |
| 11 #if defined(OS_WIN) | 11 #if defined(OS_WIN) |
| 12 #include "net/http/mock_sspi_library_win.h" | 12 #include "net/http/mock_sspi_library_win.h" |
| 13 #elif defined(OS_POSIX) | 13 #elif defined(OS_POSIX) |
| 14 #include "net/http/mock_gssapi_library_posix.h" | 14 #include "net/http/mock_gssapi_library_posix.h" |
| 15 #include "net/third_party/gssapi/gssapi.h" |
| 15 #endif | 16 #endif |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "testing/platform_test.h" | 18 #include "testing/platform_test.h" |
| 18 | 19 |
| 19 #if defined(OS_WIN) | 20 #if defined(OS_WIN) |
| 20 typedef net::MockSSPILibrary MockAuthLibrary; | 21 typedef net::MockSSPILibrary MockAuthLibrary; |
| 21 #elif defined(OS_POSIX) | 22 #elif defined(OS_POSIX) |
| 22 typedef net::test::MockGSSAPILibrary MockAuthLibrary; | 23 typedef net::test::MockGSSAPILibrary MockAuthLibrary; |
| 23 #endif | 24 #endif |
| 24 | 25 |
| 25 | 26 |
| 26 namespace net { | 27 namespace net { |
| 27 | 28 |
| 28 class HttpAuthHandlerNegotiateTest : public PlatformTest { | 29 class HttpAuthHandlerNegotiateTest : public PlatformTest { |
| 29 public: | 30 public: |
| 30 virtual void SetUp() { | 31 virtual void SetUp() { |
| 31 auth_library_.reset(new MockAuthLibrary()); | 32 auth_library_.reset(new MockAuthLibrary()); |
| 32 SetupMocks(auth_library_.get()); | |
| 33 resolver_ = new MockHostResolver(); | 33 resolver_ = new MockHostResolver(); |
| 34 resolver_->rules()->AddIPLiteralRule("alias", "10.0.0.2", | 34 resolver_->rules()->AddIPLiteralRule("alias", "10.0.0.2", |
| 35 "canonical.example.com"); | 35 "canonical.example.com"); |
| 36 | 36 |
| 37 url_security_manager_.reset(new URLSecurityManagerAllow()); | 37 url_security_manager_.reset(new URLSecurityManagerAllow()); |
| 38 factory_.reset(new HttpAuthHandlerNegotiate::Factory()); | 38 factory_.reset(new HttpAuthHandlerNegotiate::Factory()); |
| 39 factory_->set_url_security_manager(url_security_manager_.get()); | 39 factory_->set_url_security_manager(url_security_manager_.get()); |
| 40 factory_->set_library(auth_library_.get()); | 40 factory_->set_library(auth_library_.get()); |
| 41 factory_->set_host_resolver(resolver_); | 41 factory_->set_host_resolver(resolver_); |
| 42 } | 42 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 GSS_S_COMPLETE, // Major response code | 125 GSS_S_COMPLETE, // Major response code |
| 126 0, // Minor response code | 126 0, // Minor response code |
| 127 context2, // Context | 127 context2, // Context |
| 128 { arraysize(kAuthResponse), | 128 { arraysize(kAuthResponse), |
| 129 const_cast<char*>(kAuthResponse) }, // Expected input token | 129 const_cast<char*>(kAuthResponse) }, // Expected input token |
| 130 { arraysize(kAuthResponse), | 130 { arraysize(kAuthResponse), |
| 131 const_cast<char*>(kAuthResponse) } // Output token | 131 const_cast<char*>(kAuthResponse) } // Output token |
| 132 }, | 132 }, |
| 133 }; | 133 }; |
| 134 | 134 |
| 135 size_t i; | 135 for (size_t i = 0; i < arraysize(queries); ++i) { |
| 136 for (i = 0; i < arraysize(queries); ++i) { | |
| 137 mock_library->ExpectSecurityContext(queries[i].expected_package, | 136 mock_library->ExpectSecurityContext(queries[i].expected_package, |
| 138 queries[i].response_code, | 137 queries[i].response_code, |
| 139 queries[i].minor_response_code, | 138 queries[i].minor_response_code, |
| 140 queries[i].context_info, | 139 queries[i].context_info, |
| 141 queries[i].expected_input_token, | 140 queries[i].expected_input_token, |
| 142 queries[i].output_token); | 141 queries[i].output_token); |
| 143 } | 142 } |
| 144 #endif // defined(OS_POSIX) | 143 #endif // defined(OS_POSIX) |
| 145 } | 144 } |
| 146 | 145 |
| 146 #if defined(OS_POSIX) |
| 147 void SetupErrorMocks(MockAuthLibrary* mock_library, |
| 148 int major_status, |
| 149 int minor_status) { |
| 150 const gss_OID_desc kDefaultMech = { 0, NULL }; |
| 151 test::GssContextMockImpl context( |
| 152 "localhost", // Source name |
| 153 "example.com", // Target name |
| 154 0, // Lifetime |
| 155 kDefaultMech, // Mechanism |
| 156 0, // Context flags |
| 157 1, // Locally initiated |
| 158 0); // Open |
| 159 test::MockGSSAPILibrary::SecurityContextQuery query = { |
| 160 "Negotiate", // Package name |
| 161 major_status, // Major response code |
| 162 minor_status, // Minor response code |
| 163 context, // Context |
| 164 { 0, NULL }, // Expected input token |
| 165 { 0, NULL } // Output token |
| 166 }; |
| 167 |
| 168 mock_library->ExpectSecurityContext(query.expected_package, |
| 169 query.response_code, |
| 170 query.minor_response_code, |
| 171 query.context_info, |
| 172 query.expected_input_token, |
| 173 query.output_token); |
| 174 } |
| 175 |
| 176 #endif // defined(OS_POSIX) |
| 177 |
| 147 int CreateHandler(bool disable_cname_lookup, bool use_port, | 178 int CreateHandler(bool disable_cname_lookup, bool use_port, |
| 148 bool synchronous_resolve_mode, | 179 bool synchronous_resolve_mode, |
| 149 const std::string& url_string, | 180 const std::string& url_string, |
| 150 scoped_ptr<HttpAuthHandlerNegotiate>* handler) { | 181 scoped_ptr<HttpAuthHandlerNegotiate>* handler) { |
| 151 factory_->set_disable_cname_lookup(disable_cname_lookup); | 182 factory_->set_disable_cname_lookup(disable_cname_lookup); |
| 152 factory_->set_use_port(use_port); | 183 factory_->set_use_port(use_port); |
| 153 resolver_->set_synchronous_mode(synchronous_resolve_mode); | 184 resolver_->set_synchronous_mode(synchronous_resolve_mode); |
| 154 GURL gurl(url_string); | 185 GURL gurl(url_string); |
| 155 | 186 |
| 156 // Note: This is a little tricky because CreateAuthHandlerFromString | 187 // Note: This is a little tricky because CreateAuthHandlerFromString |
| 157 // expects a scoped_ptr<HttpAuthHandler>* rather than a | 188 // expects a scoped_ptr<HttpAuthHandler>* rather than a |
| 158 // scoped_ptr<HttpAuthHandlerNegotiate>*. This needs to do the cast | 189 // scoped_ptr<HttpAuthHandlerNegotiate>*. This needs to do the cast |
| 159 // after creating the handler, and make sure that generic_handler | 190 // after creating the handler, and make sure that generic_handler |
| 160 // no longer holds on to the HttpAuthHandlerNegotiate object. | 191 // no longer holds on to the HttpAuthHandlerNegotiate object. |
| 161 scoped_ptr<HttpAuthHandler> generic_handler; | 192 scoped_ptr<HttpAuthHandler> generic_handler; |
| 162 int rv = factory_->CreateAuthHandlerFromString("Negotiate", | 193 int rv = factory_->CreateAuthHandlerFromString("Negotiate", |
| 163 HttpAuth::AUTH_SERVER, | 194 HttpAuth::AUTH_SERVER, |
| 164 gurl, | 195 gurl, |
| 165 BoundNetLog(), | 196 BoundNetLog(), |
| 166 &generic_handler); | 197 &generic_handler); |
| 167 if (rv != OK) | 198 if (rv != OK) |
| 168 return rv; | 199 return rv; |
| 169 HttpAuthHandlerNegotiate* negotiate_handler = | 200 HttpAuthHandlerNegotiate* negotiate_handler = |
| 170 static_cast<HttpAuthHandlerNegotiate*>(generic_handler.release()); | 201 static_cast<HttpAuthHandlerNegotiate*>(generic_handler.release()); |
| 171 handler->reset(negotiate_handler); | 202 handler->reset(negotiate_handler); |
| 172 return rv; | 203 return rv; |
| 173 } | 204 } |
| 174 | 205 |
| 206 MockAuthLibrary* AuthLibrary() { return auth_library_.get(); } |
| 207 |
| 175 private: | 208 private: |
| 176 #if defined(OS_WIN) | 209 #if defined(OS_WIN) |
| 177 scoped_ptr<SecPkgInfoW> security_package_; | 210 scoped_ptr<SecPkgInfoW> security_package_; |
| 178 #endif | 211 #endif |
| 179 scoped_ptr<MockAuthLibrary> auth_library_; | 212 scoped_ptr<MockAuthLibrary> auth_library_; |
| 180 scoped_refptr<MockHostResolver> resolver_; | 213 scoped_refptr<MockHostResolver> resolver_; |
| 181 scoped_ptr<URLSecurityManager> url_security_manager_; | 214 scoped_ptr<URLSecurityManager> url_security_manager_; |
| 182 scoped_ptr<HttpAuthHandlerNegotiate::Factory> factory_; | 215 scoped_ptr<HttpAuthHandlerNegotiate::Factory> factory_; |
| 183 }; | 216 }; |
| 184 | 217 |
| 185 TEST_F(HttpAuthHandlerNegotiateTest, DisableCname) { | 218 TEST_F(HttpAuthHandlerNegotiateTest, DisableCname) { |
| 219 SetupMocks(AuthLibrary()); |
| 186 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; | 220 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 187 EXPECT_EQ(OK, CreateHandler( | 221 EXPECT_EQ(OK, CreateHandler( |
| 188 true, false, true, "http://alias:500", &auth_handler)); | 222 true, false, true, "http://alias:500", &auth_handler)); |
| 189 | 223 |
| 190 ASSERT_TRUE(auth_handler.get() != NULL); | 224 ASSERT_TRUE(auth_handler.get() != NULL); |
| 191 TestCompletionCallback callback; | 225 TestCompletionCallback callback; |
| 192 HttpRequestInfo request_info; | 226 HttpRequestInfo request_info; |
| 193 std::string token; | 227 std::string token; |
| 194 std::wstring username = L"foo"; | 228 std::wstring username = L"foo"; |
| 195 std::wstring password = L"bar"; | 229 std::wstring password = L"bar"; |
| 196 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, | 230 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, |
| 197 &request_info, | 231 &request_info, |
| 198 &callback, &token)); | 232 &callback, &token)); |
| 199 #if defined(OS_WIN) | 233 #if defined(OS_WIN) |
| 200 EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); | 234 EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); |
| 201 #elif defined(OS_POSIX) | 235 #elif defined(OS_POSIX) |
| 202 EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); | 236 EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); |
| 203 #endif | 237 #endif |
| 204 } | 238 } |
| 205 | 239 |
| 206 TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) { | 240 TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) { |
| 241 SetupMocks(AuthLibrary()); |
| 207 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; | 242 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 208 EXPECT_EQ(OK, CreateHandler( | 243 EXPECT_EQ(OK, CreateHandler( |
| 209 true, true, true, "http://alias:80", &auth_handler)); | 244 true, true, true, "http://alias:80", &auth_handler)); |
| 210 ASSERT_TRUE(auth_handler.get() != NULL); | 245 ASSERT_TRUE(auth_handler.get() != NULL); |
| 211 TestCompletionCallback callback; | 246 TestCompletionCallback callback; |
| 212 HttpRequestInfo request_info; | 247 HttpRequestInfo request_info; |
| 213 std::string token; | 248 std::string token; |
| 214 std::wstring username = L"foo"; | 249 std::wstring username = L"foo"; |
| 215 std::wstring password = L"bar"; | 250 std::wstring password = L"bar"; |
| 216 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, | 251 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, |
| 217 &request_info, | 252 &request_info, |
| 218 &callback, &token)); | 253 &callback, &token)); |
| 219 #if defined(OS_WIN) | 254 #if defined(OS_WIN) |
| 220 EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); | 255 EXPECT_EQ(L"HTTP/alias", auth_handler->spn()); |
| 221 #elif defined(OS_POSIX) | 256 #elif defined(OS_POSIX) |
| 222 EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); | 257 EXPECT_EQ(L"HTTP@alias", auth_handler->spn()); |
| 223 #endif | 258 #endif |
| 224 } | 259 } |
| 225 | 260 |
| 226 TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) { | 261 TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) { |
| 262 SetupMocks(AuthLibrary()); |
| 227 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; | 263 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 228 EXPECT_EQ(OK, CreateHandler( | 264 EXPECT_EQ(OK, CreateHandler( |
| 229 true, true, true, "http://alias:500", &auth_handler)); | 265 true, true, true, "http://alias:500", &auth_handler)); |
| 230 ASSERT_TRUE(auth_handler.get() != NULL); | 266 ASSERT_TRUE(auth_handler.get() != NULL); |
| 231 TestCompletionCallback callback; | 267 TestCompletionCallback callback; |
| 232 HttpRequestInfo request_info; | 268 HttpRequestInfo request_info; |
| 233 std::string token; | 269 std::string token; |
| 234 std::wstring username = L"foo"; | 270 std::wstring username = L"foo"; |
| 235 std::wstring password = L"bar"; | 271 std::wstring password = L"bar"; |
| 236 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, | 272 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, |
| 237 &request_info, | 273 &request_info, |
| 238 &callback, &token)); | 274 &callback, &token)); |
| 239 #if defined(OS_WIN) | 275 #if defined(OS_WIN) |
| 240 EXPECT_EQ(L"HTTP/alias:500", auth_handler->spn()); | 276 EXPECT_EQ(L"HTTP/alias:500", auth_handler->spn()); |
| 241 #elif defined(OS_POSIX) | 277 #elif defined(OS_POSIX) |
| 242 EXPECT_EQ(L"HTTP@alias:500", auth_handler->spn()); | 278 EXPECT_EQ(L"HTTP@alias:500", auth_handler->spn()); |
| 243 #endif | 279 #endif |
| 244 } | 280 } |
| 245 | 281 |
| 246 TEST_F(HttpAuthHandlerNegotiateTest, CnameSync) { | 282 TEST_F(HttpAuthHandlerNegotiateTest, CnameSync) { |
| 283 SetupMocks(AuthLibrary()); |
| 247 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; | 284 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 248 EXPECT_EQ(OK, CreateHandler( | 285 EXPECT_EQ(OK, CreateHandler( |
| 249 false, false, true, "http://alias:500", &auth_handler)); | 286 false, false, true, "http://alias:500", &auth_handler)); |
| 250 ASSERT_TRUE(auth_handler.get() != NULL); | 287 ASSERT_TRUE(auth_handler.get() != NULL); |
| 251 TestCompletionCallback callback; | 288 TestCompletionCallback callback; |
| 252 HttpRequestInfo request_info; | 289 HttpRequestInfo request_info; |
| 253 std::string token; | 290 std::string token; |
| 254 std::wstring username = L"foo"; | 291 std::wstring username = L"foo"; |
| 255 std::wstring password = L"bar"; | 292 std::wstring password = L"bar"; |
| 256 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, | 293 EXPECT_EQ(OK, auth_handler->GenerateAuthToken(&username, &password, |
| 257 &request_info, | 294 &request_info, |
| 258 &callback, &token)); | 295 &callback, &token)); |
| 259 #if defined(OS_WIN) | 296 #if defined(OS_WIN) |
| 260 EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); | 297 EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); |
| 261 #elif defined(OS_POSIX) | 298 #elif defined(OS_POSIX) |
| 262 EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); | 299 EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); |
| 263 #endif | 300 #endif |
| 264 } | 301 } |
| 265 | 302 |
| 266 TEST_F(HttpAuthHandlerNegotiateTest, CnameAsync) { | 303 TEST_F(HttpAuthHandlerNegotiateTest, CnameAsync) { |
| 304 SetupMocks(AuthLibrary()); |
| 267 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; | 305 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 268 EXPECT_EQ(OK, CreateHandler( | 306 EXPECT_EQ(OK, CreateHandler( |
| 269 false, false, false, "http://alias:500", &auth_handler)); | 307 false, false, false, "http://alias:500", &auth_handler)); |
| 270 ASSERT_TRUE(auth_handler.get() != NULL); | 308 ASSERT_TRUE(auth_handler.get() != NULL); |
| 271 TestCompletionCallback callback; | 309 TestCompletionCallback callback; |
| 272 HttpRequestInfo request_info; | 310 HttpRequestInfo request_info; |
| 273 std::string token; | 311 std::string token; |
| 274 std::wstring username = L"foo"; | 312 std::wstring username = L"foo"; |
| 275 std::wstring password = L"bar"; | 313 std::wstring password = L"bar"; |
| 276 EXPECT_EQ(ERR_IO_PENDING, auth_handler->GenerateAuthToken( | 314 EXPECT_EQ(ERR_IO_PENDING, auth_handler->GenerateAuthToken( |
| 277 &username, &password, &request_info, &callback, &token)); | 315 &username, &password, &request_info, &callback, &token)); |
| 278 EXPECT_EQ(OK, callback.WaitForResult()); | 316 EXPECT_EQ(OK, callback.WaitForResult()); |
| 279 #if defined(OS_WIN) | 317 #if defined(OS_WIN) |
| 280 EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); | 318 EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn()); |
| 281 #elif defined(OS_POSIX) | 319 #elif defined(OS_POSIX) |
| 282 EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); | 320 EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn()); |
| 283 #endif | 321 #endif |
| 284 } | 322 } |
| 285 | 323 |
| 324 #if defined(OS_POSIX) |
| 325 |
| 326 // These tests are only for GSSAPI, as we can't use explicit credentials with |
| 327 // that library. |
| 328 |
| 329 TEST_F(HttpAuthHandlerNegotiateTest, ServerNotInKerberosDatabase) { |
| 330 SetupErrorMocks(AuthLibrary(), GSS_S_FAILURE, 0x96C73A07); // No server |
| 331 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 332 EXPECT_EQ(OK, CreateHandler( |
| 333 false, false, false, "http://alias:500", &auth_handler)); |
| 334 ASSERT_TRUE(auth_handler.get() != NULL); |
| 335 TestCompletionCallback callback; |
| 336 HttpRequestInfo request_info; |
| 337 std::string token; |
| 338 EXPECT_EQ(ERR_IO_PENDING, auth_handler->GenerateAuthToken( |
| 339 NULL, NULL, &request_info, &callback, &token)); |
| 340 EXPECT_EQ(ERR_MISSING_AUTH_CREDENTIALS, callback.WaitForResult()); |
| 341 } |
| 342 |
| 343 TEST_F(HttpAuthHandlerNegotiateTest, NoKerberosCredentials) { |
| 344 SetupErrorMocks(AuthLibrary(), GSS_S_FAILURE, 0x96C73AC3); // No credentials |
| 345 scoped_ptr<HttpAuthHandlerNegotiate> auth_handler; |
| 346 EXPECT_EQ(OK, CreateHandler( |
| 347 false, false, false, "http://alias:500", &auth_handler)); |
| 348 ASSERT_TRUE(auth_handler.get() != NULL); |
| 349 TestCompletionCallback callback; |
| 350 HttpRequestInfo request_info; |
| 351 std::string token; |
| 352 EXPECT_EQ(ERR_IO_PENDING, auth_handler->GenerateAuthToken( |
| 353 NULL, NULL, &request_info, &callback, &token)); |
| 354 EXPECT_EQ(ERR_MISSING_AUTH_CREDENTIALS, callback.WaitForResult()); |
| 355 } |
| 356 |
| 357 #endif // defined(OS_POSIX) |
| 358 |
| 286 } // namespace net | 359 } // namespace net |
| OLD | NEW |