15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_factory.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_auth_challenge_tokenizer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_filter.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_basic.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_digest.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_ntlm.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_KERBEROS)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_handler_negotiate.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthHandlerFactory::CreateAuthHandlerFromString(
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& challenge,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuth::Target target,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpAuthHandler>* handler) {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateAuthHandler(&props, target, origin, CREATE_CHALLENGE, 1,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           net_log, handler);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString(
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& challenge,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuth::Target target,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int digest_nonce_count,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpAuthHandler>* handler) {
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateAuthHandler(&props, target, origin, CREATE_PREEMPTIVE,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           digest_nonce_count, net_log, handler);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthHandlerRegistryFactory* HttpAuthHandlerFactory::CreateDefault(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResolver* host_resolver) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(host_resolver);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerRegistryFactory* registry_factory =
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new HttpAuthHandlerRegistryFactory();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registry_factory->RegisterSchemeFactory(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "basic", new HttpAuthHandlerBasic::Factory());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registry_factory->RegisterSchemeFactory(
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "digest", new HttpAuthHandlerDigest::Factory());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_KERBEROS)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerNegotiate::Factory* negotiate_factory =
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new HttpAuthHandlerNegotiate::Factory();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negotiate_factory->set_library(new GSSAPISharedLibrary(std::string()));
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negotiate_factory->set_library(new SSPILibraryDefault());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negotiate_factory->set_host_resolver(host_resolver);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registry_factory->RegisterSchemeFactory("negotiate", negotiate_factory);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(USE_KERBEROS)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerNTLM::Factory* ntlm_factory =
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new HttpAuthHandlerNTLM::Factory();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ntlm_factory->set_sspi_library(new SSPILibraryDefault());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return registry_factory;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsSupportedScheme(const std::vector<std::string>& supported_schemes,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& scheme) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>::const_iterator it = std::find(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supported_schemes.begin(), supported_schemes.end(), scheme);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it != supported_schemes.end();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthHandlerRegistryFactory::HttpAuthHandlerRegistryFactory() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthHandlerRegistryFactory::~HttpAuthHandlerRegistryFactory() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(factory_map_.begin(),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       factory_map_.end());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpAuthHandlerRegistryFactory::SetURLSecurityManager(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLSecurityManager* security_manager) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerFactory* factory = GetSchemeFactory(scheme);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (factory)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    factory->set_url_security_manager(security_manager);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerFactory* factory) {
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string lower_scheme = base::StringToLowerASCII(scheme);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FactoryMap::iterator it = factory_map_.find(lower_scheme);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != factory_map_.end()) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (factory)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    factory_map_[lower_scheme] = factory;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    factory_map_.erase(it);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme) const {
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string lower_scheme = base::StringToLowerASCII(scheme);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FactoryMap::const_iterator it = factory_map_.find(lower_scheme);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == factory_map_.end()) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;                  // |scheme| is not registered.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it->second;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& supported_schemes,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLSecurityManager* security_manager,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResolver* host_resolver,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& gssapi_library_name,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool negotiate_disable_cname_lookup,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool negotiate_enable_port) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerRegistryFactory* registry_factory =
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new HttpAuthHandlerRegistryFactory();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSupportedScheme(supported_schemes, "basic"))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registry_factory->RegisterSchemeFactory(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "basic", new HttpAuthHandlerBasic::Factory());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSupportedScheme(supported_schemes, "digest"))
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registry_factory->RegisterSchemeFactory(
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "digest", new HttpAuthHandlerDigest::Factory());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSupportedScheme(supported_schemes, "ntlm")) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerNTLM::Factory* ntlm_factory =
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpAuthHandlerNTLM::Factory();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntlm_factory->set_url_security_manager(security_manager);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntlm_factory->set_sspi_library(new SSPILibraryDefault());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_KERBEROS)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSupportedScheme(supported_schemes, "negotiate")) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerNegotiate::Factory* negotiate_factory =
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new HttpAuthHandlerNegotiate::Factory();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_library(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new GSSAPISharedLibrary(gssapi_library_name));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_library(new SSPILibraryDefault());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_url_security_manager(security_manager);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(host_resolver || negotiate_disable_cname_lookup);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_host_resolver(host_resolver);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_disable_cname_lookup(negotiate_disable_cname_lookup);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negotiate_factory->set_use_port(negotiate_enable_port);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registry_factory->RegisterSchemeFactory("negotiate", negotiate_factory);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(USE_KERBEROS)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return registry_factory;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    HttpAuthChallengeTokenizer* challenge,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuth::Target target,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateReason reason,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int digest_nonce_count,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpAuthHandler>* handler) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme = challenge->scheme();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scheme.empty()) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handler->reset();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_INVALID_RESPONSE;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string lower_scheme = base::StringToLowerASCII(scheme);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FactoryMap::iterator it = factory_map_.find(lower_scheme);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == factory_map_.end()) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handler->reset();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNSUPPORTED_AUTH_SCHEME;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it->second);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it->second->CreateAuthHandler(challenge, target, origin, reason,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       digest_nonce_count, net_log, handler);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
200