http_auth_handler_negotiate_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. // Copyright (c) 2012 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. #include "net/http/http_auth_handler_negotiate.h"
  5. #include <memory>
  6. #include <string>
  7. #include "base/bind.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "base/test/scoped_feature_list.h"
  13. #include "build/build_config.h"
  14. #include "build/chromeos_buildflags.h"
  15. #include "net/base/features.h"
  16. #include "net/base/net_errors.h"
  17. #include "net/base/test_completion_callback.h"
  18. #include "net/dns/mock_host_resolver.h"
  19. #include "net/http/http_auth_mechanism.h"
  20. #include "net/http/http_request_info.h"
  21. #include "net/http/mock_allow_http_auth_preferences.h"
  22. #include "net/log/net_log_with_source.h"
  23. #include "net/net_buildflags.h"
  24. #include "net/ssl/ssl_info.h"
  25. #include "net/test/gtest_util.h"
  26. #include "net/test/test_with_task_environment.h"
  27. #include "testing/gmock/include/gmock/gmock.h"
  28. #include "testing/gtest/include/gtest/gtest.h"
  29. #include "testing/platform_test.h"
  30. #include "url/gurl.h"
  31. #include "url/scheme_host_port.h"
  32. #if !BUILDFLAG(USE_KERBEROS)
  33. #error "use_kerberos should be true to use Negotiate authentication scheme."
  34. #endif
  35. #if BUILDFLAG(IS_ANDROID)
  36. #include "net/android/dummy_spnego_authenticator.h"
  37. #elif BUILDFLAG(IS_WIN)
  38. #include "net/http/mock_sspi_library_win.h"
  39. #elif BUILDFLAG(USE_EXTERNAL_GSSAPI)
  40. #include "net/http/mock_gssapi_library_posix.h"
  41. #else
  42. #error "use_kerberos is true, but no Kerberos implementation available."
  43. #endif
  44. using net::test::IsError;
  45. using net::test::IsOk;
  46. namespace net {
  47. constexpr char kFakeToken[] = "FakeToken";
  48. class HttpAuthHandlerNegotiateTest : public PlatformTest,
  49. public WithTaskEnvironment {
  50. public:
  51. void SetUp() override {
  52. scoped_feature_list_.InitAndEnableFeature(
  53. features::kSplitHostCacheByNetworkIsolationKey);
  54. network_isolation_key_ = NetworkIsolationKey::CreateTransient();
  55. #if BUILDFLAG(IS_WIN)
  56. auto auth_library =
  57. std::make_unique<MockAuthLibrary>(const_cast<wchar_t*>(NEGOSSP_NAME));
  58. #else
  59. auto auth_library = std::make_unique<MockAuthLibrary>();
  60. #endif
  61. auth_library_ = auth_library.get();
  62. resolver_ = std::make_unique<MockCachingHostResolver>(
  63. /*cache_invalidation_num=*/0,
  64. /*default_result=*/MockHostResolverBase::RuleResolver::
  65. GetLocalhostResult());
  66. resolver_->rules()->AddIPLiteralRule("alias", "10.0.0.2",
  67. "canonical.example.com");
  68. http_auth_preferences_ = std::make_unique<MockAllowHttpAuthPreferences>();
  69. factory_ = std::make_unique<HttpAuthHandlerNegotiate::Factory>(
  70. HttpAuthMechanismFactory());
  71. factory_->set_http_auth_preferences(http_auth_preferences_.get());
  72. #if BUILDFLAG(IS_ANDROID)
  73. auth_library_for_android_ = std::move(auth_library);
  74. http_auth_preferences_->set_auth_android_negotiate_account_type(
  75. "org.chromium.test.DummySpnegoAuthenticator");
  76. MockAuthLibrary::EnsureTestAccountExists();
  77. #else
  78. factory_->set_library(std::move(auth_library));
  79. #endif // BUILDFLAG(IS_ANDROID)
  80. }
  81. #if BUILDFLAG(IS_ANDROID)
  82. void TearDown() override { MockAuthLibrary::RemoveTestAccounts(); }
  83. #endif
  84. void SetupMocks(MockAuthLibrary* mock_library) {
  85. #if BUILDFLAG(IS_WIN)
  86. security_package_ = std::make_unique<SecPkgInfoW>();
  87. memset(security_package_.get(), 0x0, sizeof(SecPkgInfoW));
  88. security_package_->cbMaxToken = 1337;
  89. mock_library->ExpectQuerySecurityPackageInfo(SEC_E_OK,
  90. security_package_.get());
  91. #else
  92. // Copied from an actual transaction!
  93. static const char kAuthResponse[] =
  94. "\x60\x82\x02\xCA\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x01"
  95. "\x00\x6E\x82\x02\xB9\x30\x82\x02\xB5\xA0\x03\x02\x01\x05\xA1\x03"
  96. "\x02\x01\x0E\xA2\x07\x03\x05\x00\x00\x00\x00\x00\xA3\x82\x01\xC1"
  97. "\x61\x82\x01\xBD\x30\x82\x01\xB9\xA0\x03\x02\x01\x05\xA1\x16\x1B"
  98. "\x14\x55\x4E\x49\x58\x2E\x43\x4F\x52\x50\x2E\x47\x4F\x4F\x47\x4C"
  99. "\x45\x2E\x43\x4F\x4D\xA2\x2C\x30\x2A\xA0\x03\x02\x01\x01\xA1\x23"
  100. "\x30\x21\x1B\x04\x68\x6F\x73\x74\x1B\x19\x6E\x69\x6E\x6A\x61\x2E"
  101. "\x63\x61\x6D\x2E\x63\x6F\x72\x70\x2E\x67\x6F\x6F\x67\x6C\x65\x2E"
  102. "\x63\x6F\x6D\xA3\x82\x01\x6A\x30\x82\x01\x66\xA0\x03\x02\x01\x10"
  103. "\xA1\x03\x02\x01\x01\xA2\x82\x01\x58\x04\x82\x01\x54\x2C\xB1\x2B"
  104. "\x0A\xA5\xFF\x6F\xEC\xDE\xB0\x19\x6E\x15\x20\x18\x0C\x42\xB3\x2C"
  105. "\x4B\xB0\x37\x02\xDE\xD3\x2F\xB4\xBF\xCA\xEC\x0E\xF9\xF3\x45\x6A"
  106. "\x43\xF3\x8D\x79\xBD\xCB\xCD\xB2\x2B\xB8\xFC\xD6\xB4\x7F\x09\x48"
  107. "\x14\xA7\x4F\xD2\xEE\xBC\x1B\x2F\x18\x3B\x81\x97\x7B\x28\xA4\xAF"
  108. "\xA8\xA3\x7A\x31\x1B\xFC\x97\xB6\xBA\x8A\x50\x50\xD7\x44\xB8\x30"
  109. "\xA4\x51\x4C\x3A\x95\x6C\xA1\xED\xE2\xEF\x17\xFE\xAB\xD2\xE4\x70"
  110. "\xDE\xEB\x7E\x86\x48\xC5\x3E\x19\x5B\x83\x17\xBB\x52\x26\xC0\xF3"
  111. "\x38\x0F\xB0\x8C\x72\xC9\xB0\x8B\x99\x96\x18\xE1\x9E\x67\x9D\xDC"
  112. "\xF5\x39\x80\x70\x35\x3F\x98\x72\x16\x44\xA2\xC0\x10\xAA\x70\xBD"
  113. "\x06\x6F\x83\xB1\xF4\x67\xA4\xBD\xDA\xF7\x79\x1D\x96\xB5\x7E\xF8"
  114. "\xC6\xCF\xB4\xD9\x51\xC9\xBB\xB4\x20\x3C\xDD\xB9\x2C\x38\xEA\x40"
  115. "\xFB\x02\x6C\xCB\x48\x71\xE8\xF4\x34\x5B\x63\x5D\x13\x57\xBD\xD1"
  116. "\x3D\xDE\xE8\x4A\x51\x6E\xBE\x4C\xF5\xA3\x84\xF7\x4C\x4E\x58\x04"
  117. "\xBE\xD1\xCC\x22\xA0\x43\xB0\x65\x99\x6A\xE0\x78\x0D\xFC\xE1\x42"
  118. "\xA9\x18\xCF\x55\x4D\x23\xBD\x5C\x0D\xB5\x48\x25\x47\xCC\x01\x54"
  119. "\x36\x4D\x0C\x6F\xAC\xCD\x33\x21\xC5\x63\x18\x91\x68\x96\xE9\xD1"
  120. "\xD8\x23\x1F\x21\xAE\x96\xA3\xBD\x27\xF7\x4B\xEF\x4C\x43\xFF\xF8"
  121. "\x22\x57\xCF\x68\x6C\x35\xD5\x21\x48\x5B\x5F\x8F\xA5\xB9\x6F\x99"
  122. "\xA6\xE0\x6E\xF0\xC5\x7C\x91\xC8\x0B\x8A\x4B\x4E\x80\x59\x02\xE9"
  123. "\xE8\x3F\x87\x04\xA6\xD1\xCA\x26\x3C\xF0\xDA\x57\xFA\xE6\xAF\x25"
  124. "\x43\x34\xE1\xA4\x06\x1A\x1C\xF4\xF5\x21\x9C\x00\x98\xDD\xF0\xB4"
  125. "\x8E\xA4\x81\xDA\x30\x81\xD7\xA0\x03\x02\x01\x10\xA2\x81\xCF\x04"
  126. "\x81\xCC\x20\x39\x34\x60\x19\xF9\x4C\x26\x36\x46\x99\x7A\xFD\x2B"
  127. "\x50\x8B\x2D\x47\x72\x38\x20\x43\x0E\x6E\x28\xB3\xA7\x4F\x26\xF1"
  128. "\xF1\x7B\x02\x63\x58\x5A\x7F\xC8\xD0\x6E\xF5\xD1\xDA\x28\x43\x1B"
  129. "\x6D\x9F\x59\x64\xDE\x90\xEA\x6C\x8C\xA9\x1B\x1E\x92\x29\x24\x23"
  130. "\x2C\xE3\xEA\x64\xEF\x91\xA5\x4E\x94\xE1\xDC\x56\x3A\xAF\xD5\xBC"
  131. "\xC9\xD3\x9B\x6B\x1F\xBE\x40\xE5\x40\xFF\x5E\x21\xEA\xCE\xFC\xD5"
  132. "\xB0\xE5\xBA\x10\x94\xAE\x16\x54\xFC\xEB\xAB\xF1\xD4\x20\x31\xCC"
  133. "\x26\xFE\xBE\xFE\x22\xB6\x9B\x1A\xE5\x55\x2C\x93\xB7\x3B\xD6\x4C"
  134. "\x35\x35\xC1\x59\x61\xD4\x1F\x2E\x4C\xE1\x72\x8F\x71\x4B\x0C\x39"
  135. "\x80\x79\xFA\xCD\xEA\x71\x1B\xAE\x35\x41\xED\xF9\x65\x0C\x59\xF8"
  136. "\xE1\x27\xDA\xD6\xD1\x20\x32\xCD\xBF\xD1\xEF\xE2\xED\xAD\x5D\xA7"
  137. "\x69\xE3\x55\xF9\x30\xD3\xD4\x08\xC8\xCA\x62\xF8\x64\xEC\x9B\x92"
  138. "\x1A\xF1\x03\x2E\xCC\xDC\xEB\x17\xDE\x09\xAC\xA9\x58\x86";
  139. test::GssContextMockImpl context1(
  140. "localhost", // Source name
  141. "example.com", // Target name
  142. 23, // Lifetime
  143. *CHROME_GSS_SPNEGO_MECH_OID_DESC, // Mechanism
  144. 0, // Context flags
  145. 1, // Locally initiated
  146. 0); // Open
  147. test::GssContextMockImpl context2(
  148. "localhost", // Source name
  149. "example.com", // Target name
  150. 23, // Lifetime
  151. *CHROME_GSS_SPNEGO_MECH_OID_DESC, // Mechanism
  152. 0, // Context flags
  153. 1, // Locally initiated
  154. 1); // Open
  155. MockAuthLibrary::SecurityContextQuery queries[] = {
  156. MockAuthLibrary::SecurityContextQuery(
  157. "Negotiate", // Package name
  158. GSS_S_CONTINUE_NEEDED, // Major response code
  159. 0, // Minor response code
  160. context1, // Context
  161. nullptr, // Expected input token
  162. kAuthResponse), // Output token
  163. MockAuthLibrary::SecurityContextQuery(
  164. "Negotiate", // Package name
  165. GSS_S_COMPLETE, // Major response code
  166. 0, // Minor response code
  167. context2, // Context
  168. kAuthResponse, // Expected input token
  169. kAuthResponse) // Output token
  170. };
  171. for (const auto& query : queries) {
  172. mock_library->ExpectSecurityContext(
  173. query.expected_package, query.response_code,
  174. query.minor_response_code, query.context_info,
  175. query.expected_input_token, query.output_token);
  176. }
  177. #endif // BUILDFLAG(IS_WIN)
  178. }
  179. #if BUILDFLAG(IS_POSIX)
  180. void SetupErrorMocks(MockAuthLibrary* mock_library,
  181. int major_status,
  182. int minor_status) {
  183. const gss_OID_desc kDefaultMech = {0, nullptr};
  184. test::GssContextMockImpl context(
  185. "localhost", // Source name
  186. "example.com", // Target name
  187. 0, // Lifetime
  188. kDefaultMech, // Mechanism
  189. 0, // Context flags
  190. 1, // Locally initiated
  191. 0); // Open
  192. MockAuthLibrary::SecurityContextQuery query(
  193. "Negotiate", // Package name
  194. major_status, // Major response code
  195. minor_status, // Minor response code
  196. context, // Context
  197. nullptr, // Expected input token
  198. nullptr); // Output token
  199. mock_library->ExpectSecurityContext(query.expected_package,
  200. query.response_code,
  201. query.minor_response_code,
  202. query.context_info,
  203. query.expected_input_token,
  204. query.output_token);
  205. }
  206. #endif // BUILDFLAG(IS_POSIX)
  207. int CreateHandler(bool disable_cname_lookup,
  208. bool use_port,
  209. bool synchronous_resolve_mode,
  210. const std::string& url_string,
  211. std::unique_ptr<HttpAuthHandlerNegotiate>* handler) {
  212. http_auth_preferences_->set_negotiate_disable_cname_lookup(
  213. disable_cname_lookup);
  214. http_auth_preferences_->set_negotiate_enable_port(use_port);
  215. resolver_->set_synchronous_mode(synchronous_resolve_mode);
  216. url::SchemeHostPort scheme_host_port{GURL(url_string)};
  217. // Note: This is a little tricky because CreateAuthHandlerFromString
  218. // expects a std::unique_ptr<HttpAuthHandler>* rather than a
  219. // std::unique_ptr<HttpAuthHandlerNegotiate>*. This needs to do the cast
  220. // after creating the handler, and make sure that generic_handler
  221. // no longer holds on to the HttpAuthHandlerNegotiate object.
  222. std::unique_ptr<HttpAuthHandler> generic_handler;
  223. SSLInfo null_ssl_info;
  224. int rv = factory_->CreateAuthHandlerFromString(
  225. "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info,
  226. network_isolation_key(), scheme_host_port, NetLogWithSource(),
  227. resolver_.get(), &generic_handler);
  228. if (rv != OK)
  229. return rv;
  230. HttpAuthHandlerNegotiate* negotiate_handler =
  231. static_cast<HttpAuthHandlerNegotiate*>(generic_handler.release());
  232. handler->reset(negotiate_handler);
  233. return rv;
  234. }
  235. MockAuthLibrary* AuthLibrary() { return auth_library_; }
  236. MockCachingHostResolver* resolver() { return resolver_.get(); }
  237. MockAllowHttpAuthPreferences* http_auth_preferences() {
  238. return http_auth_preferences_.get();
  239. }
  240. const NetworkIsolationKey& network_isolation_key() const {
  241. return network_isolation_key_;
  242. }
  243. private:
  244. base::test::ScopedFeatureList scoped_feature_list_;
  245. NetworkIsolationKey network_isolation_key_;
  246. #if BUILDFLAG(IS_WIN)
  247. std::unique_ptr<SecPkgInfoW> security_package_;
  248. #elif BUILDFLAG(IS_ANDROID)
  249. std::unique_ptr<MockAuthLibrary> auth_library_for_android_;
  250. #endif
  251. // |auth_library_| is passed to |factory_|, which assumes ownership of it, but
  252. // can't be a scoped pointer to it since the tests need access when they set
  253. // up the mocks after passing ownership.
  254. raw_ptr<MockAuthLibrary> auth_library_;
  255. std::unique_ptr<MockCachingHostResolver> resolver_;
  256. std::unique_ptr<MockAllowHttpAuthPreferences> http_auth_preferences_;
  257. std::unique_ptr<HttpAuthHandlerNegotiate::Factory> factory_;
  258. };
  259. TEST_F(HttpAuthHandlerNegotiateTest, DisableCname) {
  260. SetupMocks(AuthLibrary());
  261. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  262. EXPECT_EQ(OK, CreateHandler(
  263. true, false, true, "http://alias:500", &auth_handler));
  264. ASSERT_TRUE(auth_handler.get() != nullptr);
  265. TestCompletionCallback callback;
  266. HttpRequestInfo request_info;
  267. std::string token;
  268. EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken(
  269. nullptr, &request_info, callback.callback(), &token)));
  270. #if BUILDFLAG(IS_WIN)
  271. EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing());
  272. #else
  273. EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing());
  274. #endif
  275. }
  276. TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) {
  277. SetupMocks(AuthLibrary());
  278. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  279. EXPECT_EQ(OK, CreateHandler(
  280. true, true, true, "http://alias:80", &auth_handler));
  281. ASSERT_TRUE(auth_handler.get() != nullptr);
  282. TestCompletionCallback callback;
  283. HttpRequestInfo request_info;
  284. std::string token;
  285. EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken(
  286. nullptr, &request_info, callback.callback(), &token)));
  287. #if BUILDFLAG(IS_WIN)
  288. EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing());
  289. #else
  290. EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing());
  291. #endif
  292. }
  293. TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) {
  294. SetupMocks(AuthLibrary());
  295. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  296. EXPECT_EQ(OK, CreateHandler(
  297. true, true, true, "http://alias:500", &auth_handler));
  298. ASSERT_TRUE(auth_handler.get() != nullptr);
  299. TestCompletionCallback callback;
  300. HttpRequestInfo request_info;
  301. std::string token;
  302. EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken(
  303. nullptr, &request_info, callback.callback(), &token)));
  304. #if BUILDFLAG(IS_WIN)
  305. EXPECT_EQ("HTTP/alias:500", auth_handler->spn_for_testing());
  306. #else
  307. EXPECT_EQ("HTTP@alias:500", auth_handler->spn_for_testing());
  308. #endif
  309. }
  310. TEST_F(HttpAuthHandlerNegotiateTest, CnameSync) {
  311. SetupMocks(AuthLibrary());
  312. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  313. const std::string url_string = "http://alias:500";
  314. EXPECT_EQ(OK, CreateHandler(false, false, true, url_string, &auth_handler));
  315. ASSERT_TRUE(auth_handler.get() != nullptr);
  316. TestCompletionCallback callback;
  317. HttpRequestInfo request_info;
  318. std::string token;
  319. EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken(
  320. nullptr, &request_info, callback.callback(), &token)));
  321. #if BUILDFLAG(IS_WIN)
  322. EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing());
  323. #else
  324. EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing());
  325. #endif
  326. // Make sure a cache-only lookup with the wrong NetworkIsolationKey (an empty
  327. // one) fails, to make sure the right NetworkIsolationKey was used.
  328. url::SchemeHostPort scheme_host_port{GURL(url_string)};
  329. HostResolver::ResolveHostParameters resolve_params;
  330. resolve_params.include_canonical_name = true;
  331. resolve_params.source = HostResolverSource::LOCAL_ONLY;
  332. std::unique_ptr<HostResolver::ResolveHostRequest> host_request1 =
  333. resolver()->CreateRequest(scheme_host_port, NetworkIsolationKey(),
  334. NetLogWithSource(), resolve_params);
  335. TestCompletionCallback callback2;
  336. int result = host_request1->Start(callback2.callback());
  337. EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback2.GetResult(result));
  338. // Make sure a cache-only lookup with the same NetworkIsolationKey succeeds,
  339. // to make sure the right NetworkIsolationKey was used.
  340. std::unique_ptr<HostResolver::ResolveHostRequest> host_request2 =
  341. resolver()->CreateRequest(scheme_host_port, network_isolation_key(),
  342. NetLogWithSource(), resolve_params);
  343. TestCompletionCallback callback3;
  344. result = host_request2->Start(callback3.callback());
  345. EXPECT_EQ(OK, callback3.GetResult(result));
  346. }
  347. TEST_F(HttpAuthHandlerNegotiateTest, CnameAsync) {
  348. SetupMocks(AuthLibrary());
  349. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  350. const std::string url_string = "http://alias:500";
  351. EXPECT_EQ(OK, CreateHandler(false, false, false, url_string, &auth_handler));
  352. ASSERT_TRUE(auth_handler.get() != nullptr);
  353. TestCompletionCallback callback;
  354. HttpRequestInfo request_info;
  355. std::string token;
  356. EXPECT_EQ(ERR_IO_PENDING,
  357. auth_handler->GenerateAuthToken(nullptr, &request_info,
  358. callback.callback(), &token));
  359. EXPECT_THAT(callback.WaitForResult(), IsOk());
  360. #if BUILDFLAG(IS_WIN)
  361. EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing());
  362. #else
  363. EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing());
  364. #endif
  365. // Make sure a cache-only lookup with the wrong NetworkIsolationKey (an empty
  366. // one) fails, to make sure the right NetworkIsolationKey was used.
  367. url::SchemeHostPort scheme_host_port{GURL(url_string)};
  368. HostResolver::ResolveHostParameters resolve_params;
  369. resolve_params.include_canonical_name = true;
  370. resolve_params.source = HostResolverSource::LOCAL_ONLY;
  371. std::unique_ptr<HostResolver::ResolveHostRequest> host_request1 =
  372. resolver()->CreateRequest(scheme_host_port, NetworkIsolationKey(),
  373. NetLogWithSource(), resolve_params);
  374. TestCompletionCallback callback2;
  375. int result = host_request1->Start(callback2.callback());
  376. EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback2.GetResult(result));
  377. // Make sure a cache-only lookup with the same NetworkIsolationKey succeeds,
  378. // to make sure the right NetworkIsolationKey was used.
  379. std::unique_ptr<HostResolver::ResolveHostRequest> host_request2 =
  380. resolver()->CreateRequest(scheme_host_port, network_isolation_key(),
  381. NetLogWithSource(), resolve_params);
  382. TestCompletionCallback callback3;
  383. result = host_request2->Start(callback3.callback());
  384. EXPECT_EQ(OK, callback3.GetResult(result));
  385. }
  386. #if BUILDFLAG(IS_POSIX)
  387. // This test is only for GSSAPI, as we can't use explicit credentials with
  388. // that library.
  389. TEST_F(HttpAuthHandlerNegotiateTest, ServerNotInKerberosDatabase) {
  390. SetupErrorMocks(AuthLibrary(), GSS_S_FAILURE, 0x96C73A07); // No server
  391. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  392. EXPECT_EQ(OK, CreateHandler(
  393. false, false, false, "http://alias:500", &auth_handler));
  394. ASSERT_TRUE(auth_handler.get() != nullptr);
  395. TestCompletionCallback callback;
  396. HttpRequestInfo request_info;
  397. std::string token;
  398. EXPECT_EQ(ERR_IO_PENDING,
  399. auth_handler->GenerateAuthToken(nullptr, &request_info,
  400. callback.callback(), &token));
  401. EXPECT_THAT(callback.WaitForResult(), IsError(ERR_MISSING_AUTH_CREDENTIALS));
  402. }
  403. // This test is only for GSSAPI, as we can't use explicit credentials with
  404. // that library.
  405. TEST_F(HttpAuthHandlerNegotiateTest, NoKerberosCredentials) {
  406. SetupErrorMocks(AuthLibrary(), GSS_S_FAILURE, 0x96C73AC3); // No credentials
  407. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  408. EXPECT_EQ(OK, CreateHandler(
  409. false, false, false, "http://alias:500", &auth_handler));
  410. ASSERT_TRUE(auth_handler.get() != nullptr);
  411. TestCompletionCallback callback;
  412. HttpRequestInfo request_info;
  413. std::string token;
  414. EXPECT_EQ(ERR_IO_PENDING,
  415. auth_handler->GenerateAuthToken(nullptr, &request_info,
  416. callback.callback(), &token));
  417. EXPECT_THAT(callback.WaitForResult(), IsError(ERR_MISSING_AUTH_CREDENTIALS));
  418. }
  419. #if BUILDFLAG(USE_EXTERNAL_GSSAPI)
  420. TEST_F(HttpAuthHandlerNegotiateTest, MissingGSSAPI) {
  421. MockAllowHttpAuthPreferences http_auth_preferences;
  422. auto negotiate_factory = std::make_unique<HttpAuthHandlerNegotiate::Factory>(
  423. HttpAuthMechanismFactory());
  424. negotiate_factory->set_http_auth_preferences(&http_auth_preferences);
  425. negotiate_factory->set_library(
  426. std::make_unique<GSSAPISharedLibrary>("/this/library/does/not/exist"));
  427. url::SchemeHostPort scheme_host_port(GURL("http://www.example.com"));
  428. std::unique_ptr<HttpAuthHandler> generic_handler;
  429. int rv = negotiate_factory->CreateAuthHandlerFromString(
  430. "Negotiate", HttpAuth::AUTH_SERVER, SSLInfo(), NetworkIsolationKey(),
  431. scheme_host_port, NetLogWithSource(), resolver(), &generic_handler);
  432. EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME));
  433. EXPECT_TRUE(generic_handler.get() == nullptr);
  434. }
  435. #endif // BUILDFLAG(USE_EXTERNAL_GSSAPI)
  436. // AllowGssapiLibraryLoad() is only supported on ChromeOS.
  437. #if BUILDFLAG(IS_CHROMEOS)
  438. TEST_F(HttpAuthHandlerNegotiateTest, AllowGssapiLibraryLoad) {
  439. // Disabling allow_gssapi_library_load should prevent handler creation.
  440. SetupMocks(AuthLibrary());
  441. http_auth_preferences()->set_allow_gssapi_library_load(false);
  442. std::unique_ptr<HttpAuthHandlerNegotiate> auth_handler;
  443. int rv = CreateHandler(true, false, true, "http://alias:500", &auth_handler);
  444. EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME));
  445. EXPECT_FALSE(auth_handler);
  446. // Handler creation can be dynamically re-enabled.
  447. http_auth_preferences()->set_allow_gssapi_library_load(true);
  448. rv = CreateHandler(true, false, true, "http://alias:500", &auth_handler);
  449. EXPECT_EQ(OK, rv);
  450. EXPECT_TRUE(auth_handler);
  451. }
  452. #endif // BUILDFLAG(IS_CHROMEOS)
  453. #endif // BUILDFLAG(IS_POSIX)
  454. class TestAuthSystem : public HttpAuthMechanism {
  455. public:
  456. TestAuthSystem() = default;
  457. ~TestAuthSystem() override = default;
  458. // HttpAuthMechanism implementation:
  459. bool Init(const NetLogWithSource&) override { return true; }
  460. bool NeedsIdentity() const override { return true; }
  461. bool AllowsExplicitCredentials() const override { return true; }
  462. net::HttpAuth::AuthorizationResult ParseChallenge(
  463. net::HttpAuthChallengeTokenizer* tok) override {
  464. return net::HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
  465. }
  466. int GenerateAuthToken(const net::AuthCredentials* credentials,
  467. const std::string& spn,
  468. const std::string& channel_bindings,
  469. std::string* auth_token,
  470. const NetLogWithSource& net_log,
  471. net::CompletionOnceCallback callback) override {
  472. *auth_token = kFakeToken;
  473. return net::OK;
  474. }
  475. void SetDelegation(HttpAuth::DelegationType delegation_type) override {}
  476. };
  477. TEST_F(HttpAuthHandlerNegotiateTest, OverrideAuthSystem) {
  478. auto negotiate_factory =
  479. std::make_unique<HttpAuthHandlerNegotiate::Factory>(base::BindRepeating(
  480. [](const HttpAuthPreferences*) -> std::unique_ptr<HttpAuthMechanism> {
  481. return std::make_unique<TestAuthSystem>();
  482. }));
  483. negotiate_factory->set_http_auth_preferences(http_auth_preferences());
  484. #if BUILDFLAG(IS_WIN)
  485. negotiate_factory->set_library(
  486. std::make_unique<MockAuthLibrary>(NEGOSSP_NAME));
  487. #elif !BUILDFLAG(IS_ANDROID)
  488. negotiate_factory->set_library(std::make_unique<MockAuthLibrary>());
  489. #endif
  490. url::SchemeHostPort scheme_host_port{GURL("http://www.example.com")};
  491. std::unique_ptr<HttpAuthHandler> handler;
  492. EXPECT_EQ(OK, negotiate_factory->CreateAuthHandlerFromString(
  493. "Negotiate", HttpAuth::AUTH_SERVER, SSLInfo(),
  494. NetworkIsolationKey(), scheme_host_port, NetLogWithSource(),
  495. resolver(), &handler));
  496. EXPECT_TRUE(handler);
  497. TestCompletionCallback callback;
  498. std::string auth_token;
  499. HttpRequestInfo request_info;
  500. EXPECT_EQ(OK, callback.GetResult(handler->GenerateAuthToken(
  501. nullptr, &request_info, callback.callback(), &auth_token)));
  502. EXPECT_EQ(kFakeToken, auth_token);
  503. }
  504. } // namespace net