Home | History | Annotate | Download | only in http
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/http/http_auth_handler_factory.h"
      6 
      7 #include "base/stl_util.h"
      8 #include "base/strings/string_util.h"
      9 #include "net/base/net_errors.h"
     10 #include "net/http/http_auth_challenge_tokenizer.h"
     11 #include "net/http/http_auth_filter.h"
     12 #include "net/http/http_auth_handler_basic.h"
     13 #include "net/http/http_auth_handler_digest.h"
     14 #include "net/http/http_auth_handler_ntlm.h"
     15 
     16 #if defined(USE_KERBEROS)
     17 #include "net/http/http_auth_handler_negotiate.h"
     18 #endif
     19 
     20 namespace net {
     21 
     22 int HttpAuthHandlerFactory::CreateAuthHandlerFromString(
     23     const std::string& challenge,
     24     HttpAuth::Target target,
     25     const GURL& origin,
     26     const BoundNetLog& net_log,
     27     scoped_ptr<HttpAuthHandler>* handler) {
     28   HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
     29   return CreateAuthHandler(&props, target, origin, CREATE_CHALLENGE, 1,
     30                            net_log, handler);
     31 }
     32 
     33 int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString(
     34     const std::string& challenge,
     35     HttpAuth::Target target,
     36     const GURL& origin,
     37     int digest_nonce_count,
     38     const BoundNetLog& net_log,
     39     scoped_ptr<HttpAuthHandler>* handler) {
     40   HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
     41   return CreateAuthHandler(&props, target, origin, CREATE_PREEMPTIVE,
     42                            digest_nonce_count, net_log, handler);
     43 }
     44 
     45 // static
     46 HttpAuthHandlerRegistryFactory* HttpAuthHandlerFactory::CreateDefault(
     47     HostResolver* host_resolver) {
     48   DCHECK(host_resolver);
     49   HttpAuthHandlerRegistryFactory* registry_factory =
     50       new HttpAuthHandlerRegistryFactory();
     51   registry_factory->RegisterSchemeFactory(
     52       "basic", new HttpAuthHandlerBasic::Factory());
     53   registry_factory->RegisterSchemeFactory(
     54       "digest", new HttpAuthHandlerDigest::Factory());
     55 
     56 #if defined(USE_KERBEROS)
     57   HttpAuthHandlerNegotiate::Factory* negotiate_factory =
     58       new HttpAuthHandlerNegotiate::Factory();
     59 #if defined(OS_POSIX)
     60   negotiate_factory->set_library(new GSSAPISharedLibrary(std::string()));
     61 #elif defined(OS_WIN)
     62   negotiate_factory->set_library(new SSPILibraryDefault());
     63 #endif
     64   negotiate_factory->set_host_resolver(host_resolver);
     65   registry_factory->RegisterSchemeFactory("negotiate", negotiate_factory);
     66 #endif  // defined(USE_KERBEROS)
     67 
     68   HttpAuthHandlerNTLM::Factory* ntlm_factory =
     69       new HttpAuthHandlerNTLM::Factory();
     70 #if defined(OS_WIN)
     71   ntlm_factory->set_sspi_library(new SSPILibraryDefault());
     72 #endif
     73   registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
     74   return registry_factory;
     75 }
     76 
     77 namespace {
     78 
     79 bool IsSupportedScheme(const std::vector<std::string>& supported_schemes,
     80                        const std::string& scheme) {
     81   std::vector<std::string>::const_iterator it = std::find(
     82       supported_schemes.begin(), supported_schemes.end(), scheme);
     83   return it != supported_schemes.end();
     84 }
     85 
     86 }  // namespace
     87 
     88 HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
     89 }
     90 
     91 HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
     92   STLDeleteContainerPairSecondPointers(factory_map_.begin(),
     93                                        factory_map_.end());
     94 }
     95 
     96 void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
     97     const std::string& scheme,
     98     URLSecurityManager* security_manager) {
     99   HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
    100   if (factory)
    101     factory->set_url_security_manager(security_manager);
    102 }
    103 
    104 void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
    105     const std::string& scheme,
    106     HttpAuthHandlerFactory* factory) {
    107   std::string lower_scheme = base::StringToLowerASCII(scheme);
    108   FactoryMap::iterator it = factory_map_.find(lower_scheme);
    109   if (it != factory_map_.end()) {
    110     delete it->second;
    111   }
    112   if (factory)
    113     factory_map_[lower_scheme] = factory;
    114   else
    115     factory_map_.erase(it);
    116 }
    117 
    118 HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
    119     const std::string& scheme) const {
    120   std::string lower_scheme = base::StringToLowerASCII(scheme);
    121   FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
    122   if (it == factory_map_.end()) {
    123     return NULL;                  // |scheme| is not registered.
    124   }
    125   return it->second;
    126 }
    127 
    128 // static
    129 HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
    130     const std::vector<std::string>& supported_schemes,
    131     URLSecurityManager* security_manager,
    132     HostResolver* host_resolver,
    133     const std::string& gssapi_library_name,
    134     bool negotiate_disable_cname_lookup,
    135     bool negotiate_enable_port) {
    136   HttpAuthHandlerRegistryFactory* registry_factory =
    137       new HttpAuthHandlerRegistryFactory();
    138   if (IsSupportedScheme(supported_schemes, "basic"))
    139     registry_factory->RegisterSchemeFactory(
    140         "basic", new HttpAuthHandlerBasic::Factory());
    141   if (IsSupportedScheme(supported_schemes, "digest"))
    142     registry_factory->RegisterSchemeFactory(
    143         "digest", new HttpAuthHandlerDigest::Factory());
    144   if (IsSupportedScheme(supported_schemes, "ntlm")) {
    145     HttpAuthHandlerNTLM::Factory* ntlm_factory =
    146         new HttpAuthHandlerNTLM::Factory();
    147     ntlm_factory->set_url_security_manager(security_manager);
    148 #if defined(OS_WIN)
    149     ntlm_factory->set_sspi_library(new SSPILibraryDefault());
    150 #endif
    151     registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
    152   }
    153 #if defined(USE_KERBEROS)
    154   if (IsSupportedScheme(supported_schemes, "negotiate")) {
    155     HttpAuthHandlerNegotiate::Factory* negotiate_factory =
    156         new HttpAuthHandlerNegotiate::Factory();
    157 #if defined(OS_POSIX)
    158     negotiate_factory->set_library(
    159         new GSSAPISharedLibrary(gssapi_library_name));
    160 #elif defined(OS_WIN)
    161     negotiate_factory->set_library(new SSPILibraryDefault());
    162 #endif
    163     negotiate_factory->set_url_security_manager(security_manager);
    164     DCHECK(host_resolver || negotiate_disable_cname_lookup);
    165     negotiate_factory->set_host_resolver(host_resolver);
    166     negotiate_factory->set_disable_cname_lookup(negotiate_disable_cname_lookup);
    167     negotiate_factory->set_use_port(negotiate_enable_port);
    168     registry_factory->RegisterSchemeFactory("negotiate", negotiate_factory);
    169   }
    170 #endif  // defined(USE_KERBEROS)
    171 
    172   return registry_factory;
    173 }
    174 
    175 int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
    176     HttpAuthChallengeTokenizer* challenge,
    177     HttpAuth::Target target,
    178     const GURL& origin,
    179     CreateReason reason,
    180     int digest_nonce_count,
    181     const BoundNetLog& net_log,
    182     scoped_ptr<HttpAuthHandler>* handler) {
    183   std::string scheme = challenge->scheme();
    184   if (scheme.empty()) {
    185     handler->reset();
    186     return ERR_INVALID_RESPONSE;
    187   }
    188   std::string lower_scheme = base::StringToLowerASCII(scheme);
    189   FactoryMap::iterator it = factory_map_.find(lower_scheme);
    190   if (it == factory_map_.end()) {
    191     handler->reset();
    192     return ERR_UNSUPPORTED_AUTH_SCHEME;
    193   }
    194   DCHECK(it->second);
    195   return it->second->CreateAuthHandler(challenge, target, origin, reason,
    196                                        digest_nonce_count, net_log, handler);
    197 }
    198 
    199 }  // namespace net
    200