| // Copyright (c) 2010 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 "net/http/http_auth_handler_factory.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_util.h" |
| #include "build/build_config.h" |
| #include "net/base/net_errors.h" |
| #include "net/http/http_auth_challenge_tokenizer.h" |
| #include "net/http/http_auth_filter.h" |
| #include "net/http/http_auth_handler_basic.h" |
| #include "net/http/http_auth_handler_digest.h" |
| #include "net/http/http_auth_handler_ntlm.h" |
| #include "net/http/http_auth_preferences.h" |
| #include "net/http/http_auth_scheme.h" |
| #include "net/net_buildflags.h" |
| #include "net/ssl/ssl_info.h" |
| |
| #if BUILDFLAG(USE_KERBEROS) |
| #include "net/http/http_auth_handler_negotiate.h" |
| #endif |
| |
| namespace net { |
| |
| int HttpAuthHandlerFactory::CreateAuthHandlerFromString( |
| const std::string& challenge, |
| HttpAuth::Target target, |
| const SSLInfo& ssl_info, |
| const GURL& origin, |
| const NetLogWithSource& net_log, |
| std::unique_ptr<HttpAuthHandler>* handler) { |
| HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); |
| return CreateAuthHandler(&props, target, ssl_info, origin, CREATE_CHALLENGE, |
| 1, net_log, handler); |
| } |
| |
| int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString( |
| const std::string& challenge, |
| HttpAuth::Target target, |
| const GURL& origin, |
| int digest_nonce_count, |
| const NetLogWithSource& net_log, |
| std::unique_ptr<HttpAuthHandler>* handler) { |
| HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); |
| SSLInfo null_ssl_info; |
| return CreateAuthHandler(&props, target, null_ssl_info, origin, |
| CREATE_PREEMPTIVE, digest_nonce_count, net_log, |
| handler); |
| } |
| |
| namespace { |
| |
| const char* const kDefaultAuthSchemes[] = {kBasicAuthScheme, kDigestAuthScheme, |
| #if BUILDFLAG(USE_KERBEROS) && !defined(OS_ANDROID) |
| kNegotiateAuthScheme, |
| #endif |
| kNtlmAuthScheme}; |
| |
| } // namespace |
| |
| HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() = default; |
| |
| HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() = default; |
| |
| void HttpAuthHandlerRegistryFactory::SetHttpAuthPreferences( |
| const std::string& scheme, |
| const HttpAuthPreferences* prefs) { |
| HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme); |
| if (factory) |
| factory->set_http_auth_preferences(prefs); |
| } |
| |
| void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory( |
| const std::string& scheme, |
| HttpAuthHandlerFactory* factory) { |
| factory->set_http_auth_preferences(http_auth_preferences()); |
| std::string lower_scheme = base::ToLowerASCII(scheme); |
| if (factory) |
| factory_map_[lower_scheme] = base::WrapUnique(factory); |
| else |
| factory_map_.erase(lower_scheme); |
| } |
| |
| HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory( |
| const std::string& scheme) const { |
| std::string lower_scheme = base::ToLowerASCII(scheme); |
| auto it = factory_map_.find(lower_scheme); |
| if (it == factory_map_.end()) { |
| return NULL; // |scheme| is not registered. |
| } |
| return it->second.get(); |
| } |
| |
| // static |
| std::unique_ptr<HttpAuthHandlerRegistryFactory> |
| HttpAuthHandlerFactory::CreateDefault(HostResolver* host_resolver, |
| const HttpAuthPreferences* prefs |
| #if defined(OS_CHROMEOS) |
| , |
| bool allow_gssapi_library_load |
| #elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) |
| , |
| const std::string& gssapi_library_name |
| #endif |
| ) { |
| std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), |
| std::end(kDefaultAuthSchemes)); |
| return HttpAuthHandlerRegistryFactory::Create(host_resolver, prefs, auth_types |
| #if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) |
| , |
| gssapi_library_name |
| #endif |
| #if defined(OS_CHROMEOS) |
| , |
| allow_gssapi_library_load |
| #endif |
| ); |
| } |
| |
| // static |
| std::unique_ptr<HttpAuthHandlerRegistryFactory> |
| HttpAuthHandlerRegistryFactory::Create( |
| HostResolver* host_resolver, |
| const HttpAuthPreferences* prefs, |
| const std::vector<std::string>& auth_schemes |
| #if defined(OS_CHROMEOS) |
| , |
| bool allow_gssapi_library_load |
| #elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA) |
| , |
| const std::string& gssapi_library_name |
| #endif |
| ) { |
| std::set<std::string> auth_schemes_set(auth_schemes.begin(), |
| auth_schemes.end()); |
| |
| std::unique_ptr<HttpAuthHandlerRegistryFactory> registry_factory( |
| new HttpAuthHandlerRegistryFactory()); |
| if (base::ContainsKey(auth_schemes_set, kBasicAuthScheme)) { |
| registry_factory->RegisterSchemeFactory( |
| kBasicAuthScheme, new HttpAuthHandlerBasic::Factory()); |
| } |
| |
| if (base::ContainsKey(auth_schemes_set, kDigestAuthScheme)) { |
| registry_factory->RegisterSchemeFactory( |
| kDigestAuthScheme, new HttpAuthHandlerDigest::Factory()); |
| } |
| |
| if (base::ContainsKey(auth_schemes_set, kNtlmAuthScheme)) { |
| HttpAuthHandlerNTLM::Factory* ntlm_factory = |
| new HttpAuthHandlerNTLM::Factory(); |
| #if defined(OS_WIN) |
| ntlm_factory->set_sspi_library(new SSPILibraryDefault()); |
| #endif // defined(OS_WIN) |
| registry_factory->RegisterSchemeFactory(kNtlmAuthScheme, ntlm_factory); |
| } |
| |
| #if BUILDFLAG(USE_KERBEROS) |
| if (base::ContainsKey(auth_schemes_set, kNegotiateAuthScheme)) { |
| DCHECK(host_resolver); |
| HttpAuthHandlerNegotiate::Factory* negotiate_factory = |
| new HttpAuthHandlerNegotiate::Factory(); |
| #if defined(OS_WIN) |
| negotiate_factory->set_library(std::make_unique<SSPILibraryDefault>()); |
| #elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS) |
| negotiate_factory->set_library( |
| std::make_unique<GSSAPISharedLibrary>(gssapi_library_name)); |
| #elif defined(OS_CHROMEOS) |
| negotiate_factory->set_library(std::make_unique<GSSAPISharedLibrary>("")); |
| negotiate_factory->set_allow_gssapi_library_load(allow_gssapi_library_load); |
| #endif |
| negotiate_factory->set_host_resolver(host_resolver); |
| registry_factory->RegisterSchemeFactory(kNegotiateAuthScheme, |
| negotiate_factory); |
| } |
| #endif // BUILDFLAG(USE_KERBEROS) |
| |
| if (prefs) { |
| registry_factory->set_http_auth_preferences(prefs); |
| for (auto& factory_entry : registry_factory->factory_map_) { |
| factory_entry.second->set_http_auth_preferences(prefs); |
| } |
| } |
| return registry_factory; |
| } |
| |
| int HttpAuthHandlerRegistryFactory::CreateAuthHandler( |
| HttpAuthChallengeTokenizer* challenge, |
| HttpAuth::Target target, |
| const SSLInfo& ssl_info, |
| const GURL& origin, |
| CreateReason reason, |
| int digest_nonce_count, |
| const NetLogWithSource& net_log, |
| std::unique_ptr<HttpAuthHandler>* handler) { |
| std::string scheme = challenge->scheme(); |
| if (scheme.empty()) { |
| handler->reset(); |
| return ERR_INVALID_RESPONSE; |
| } |
| std::string lower_scheme = base::ToLowerASCII(scheme); |
| auto it = factory_map_.find(lower_scheme); |
| if (it == factory_map_.end()) { |
| handler->reset(); |
| return ERR_UNSUPPORTED_AUTH_SCHEME; |
| } |
| DCHECK(it->second); |
| return it->second->CreateAuthHandler(challenge, target, ssl_info, origin, |
| reason, digest_nonce_count, net_log, |
| handler); |
| } |
| |
| } // namespace net |