[squid-dev] [PATCH] refactor Auth::Config

Amos Jeffries squid3 at treenet.co.nz
Tue Dec 20 18:05:56 UTC 2016


This is the patch refactoring the Auth::Config objects to get v5
building again.

The object storing auth_param settings is renamed to SchemeConfig.

A new Auth::Config object is added. The objects holding auth_param,
auth_schemes and other authenticate_* directives settings are stored
there instead of just auth_params.

Lots of outdated doxygen docs that have more up to date copies elsewhere
are removed. The "\ingroup AuthAPI" are left for now since some auth
things are not yet in the Auth:: namespace, but other auth related
groups are dropped completely.

Code parsing and dumping auth_param lines has been de-duplicated. Along
with the keep_alive and utf8 settings, which are shared by multiple
schemes. This allows dropping several virtual methods from NTLM and
Negotiate scheme objects.

An auth/forward.h file is added for predefines. Some initial Auth::
symbols are listed there. It is not complete, but others can be added as
needed later.

Some unnecessary includes have been removed. There are probably more. I
just did the obvious ones related to the new auth/forward.h and
auth/Config.h files at this time.

Amos
-------------- next part --------------
=== removed file 'doc/Programming-Guide/BasicAuthentication.dox'
--- doc/Programming-Guide/BasicAuthentication.dox	2016-01-01 00:12:18 +0000
+++ doc/Programming-Guide/BasicAuthentication.dox	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/**
-\defgroup AuthAPIBasic Basic Authentication
-\ingroup AuthAPI
-
-\par
-Basic authentication provides a username and password.  These
-are written to the authentication module processes on a single
-line, separated by a space:
-\code
-<USERNAME> <PASSWORD>
-\endcode
-
-\par
-	The authentication module process reads username, password pairs
-	on stdin and returns either "OK" or "ERR" on stdout for
-	each input line.
-
-\par
-	The following simple perl script demonstrates how the
-	authentication module works.  This script allows any
-	user named "Dirk" (without checking the password)
-	and allows any user that uses the password "Sekrit":
-
-\code
-#!/usr/bin/perl -w
-$|=1;		# no buffering, important!
-while (<>) {
-        chop;
-        ($u,$p) = split;
-        $ans = &check($u,$p);
-        print "$ans\n";
-}
-
-sub check {
-        local($u,$p) = @_;
-        return 'ERR' unless (defined $p && defined $u);
-        return 'OK' if ('Dirk' eq $u);
-        return 'OK' if ('Sekrit' eq $p);
-        return 'ERR';
-}
-\endcode
-
- */

=== modified file 'src/SquidConfig.h'
--- src/SquidConfig.h	2016-12-10 04:48:25 +0000
+++ src/SquidConfig.h	2016-12-19 14:14:57 +0000
@@ -1,35 +1,32 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SQUIDCONFIG_H_
 #define SQUID_SQUIDCONFIG_H_
 
 #include "acl/forward.h"
-#if USE_AUTH
-#include "auth/SchemesConfig.h"
-#endif
 #include "base/RefCount.h"
 #include "base/YesNoNone.h"
 #include "ClientDelayConfig.h"
 #include "DelayConfig.h"
 #include "helper/ChildConfig.h"
 #include "HttpHeaderTools.h"
 #include "ip/Address.h"
 #include "Notes.h"
 #include "security/forward.h"
 #include "SquidTime.h"
 #if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 #include "store/forward.h"
 
 #if USE_OPENSSL
 class sslproxy_cert_sign;
 class sslproxy_cert_adapt;
 #endif
 
@@ -184,43 +181,40 @@
     char *effectiveGroup;
 
     struct {
         wordlist *redirect;
         wordlist *store_id;
 #if USE_UNLINKD
 
         char *unlinkd;
 #endif
 
         char *diskd;
 #if USE_OPENSSL
 
         char *ssl_password;
 #endif
 
     } Program;
 
     Helper::ChildConfig redirectChildren;
     Helper::ChildConfig storeIdChildren;
-    time_t authenticateGCInterval;
-    time_t authenticateTTL;
-    time_t authenticateIpTTL;
 
     struct {
         char *surrogate_id;
     } Accel;
     char *appendDomain;
     size_t appendDomainLen;
     char *pidFilename;
     char *netdbFilename;
     char *mimeTablePathname;
     char *etcHostsPath;
     char *visibleHostname;
     char *uniqueHostname;
     wordlist *hostnameAliases;
     char *errHtmlText;
 
     struct {
         char *host;
         char *file;
         time_t period;
         unsigned short port;
@@ -383,43 +377,40 @@
 
 #if USE_OPENSSL
         acl_access *ssl_bump;
 #endif
 #if FOLLOW_X_FORWARDED_FOR
         acl_access *followXFF;
 #endif /* FOLLOW_X_FORWARDED_FOR */
 
         /// acceptible PROXY protocol clients
         acl_access *proxyProtocol;
 
         /// spoof_client_ip squid.conf acl.
         /// nil unless configured
         acl_access* spoof_client_ip;
         acl_access *on_unsupported_protocol;
 
         acl_access *ftp_epsv;
 
         acl_access *forceRequestBodyContinuation;
         acl_access *serverPconnForNonretriable;
-#if USE_AUTH
-        acl_access *authSchemes;
-#endif
     } accessList;
     AclDenyInfoList *denyInfoList;
 
     struct {
         size_t list_width;
         int list_wrap;
         char *anon_user;
         int passive;
         int epsv_all;
         int epsv;
         int eprt;
         int sanitycheck;
         int telnet;
     } Ftp;
     RefreshPattern *Refresh;
 
     Store::DiskConfig cacheSwap;
 
     struct {
         char *directory;
@@ -526,44 +517,40 @@
 
 #if USE_LOADABLE_MODULES
     wordlist *loadable_module_names;
 #endif
 
     int client_ip_max_connections;
 
     char *redirector_extras;
 
     struct UrlHelperTimeout {
         int action;
         char *response;
     } onUrlRewriteTimeout;
 
     char *storeId_extras;
 
     struct {
         int v4_first;       ///< Place IPv4 first in the order of DNS results.
         ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies.
     } dns;
-
-#if USE_AUTH
-    Auth::SchemesConfigs authSchemesConfigs;
-#endif
 };
 
 extern SquidConfig Config;
 
 class SquidConfig2
 {
 public:
     void clear() {
         *this = SquidConfig2();
     }
 
     struct {
         int enable_purge = 0;
     } onoff;
     uid_t effectiveUserID = 0;
     gid_t effectiveGroupID = 0;
 };
 
 extern SquidConfig2 Config2;
 

=== added file 'src/auth/Config.cc'
--- src/auth/Config.cc	1970-01-01 00:00:00 +0000
+++ src/auth/Config.cc	2016-12-19 13:25:50 +0000
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 29    Authenticator */
+
+#include "squid.h"
+#include "acl/Tree.h"
+#include "auth/Config.h"
+
+Auth::Config Auth::TheConfig;
+

=== added file 'src/auth/Config.h'
--- src/auth/Config.h	1970-01-01 00:00:00 +0000
+++ src/auth/Config.h	2016-12-19 14:21:57 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_AUTH_CONFIG_H
+#define SQUID_SRC_AUTH_CONFIG_H
+
+#if USE_AUTH
+
+#include "acl/forward.h"
+#include "auth/SchemeConfig.h"
+#include "auth/SchemesConfig.h"
+
+namespace Auth
+{
+
+class Config
+{
+public:
+    /// set of auth_params directives
+    Auth::ConfigVector schemes;
+
+    /// set of auth_schemes directives
+    std::vector<Auth::SchemesConfig> schemeLists;
+
+    /// the ACL list for auth_schemes directives
+    acl_access *schemeAccess = nullptr;
+
+    /// the authenticate_cache_garbage_interval
+    time_t authenticateGCInterval;
+
+    /// the authenticate_ttl
+    time_t authenticateTTL;
+
+    /// the authenticate_ip_ttl
+    time_t authenticateIpTTL;
+};
+
+extern Auth::Config TheConfig;
+
+} // namespace Auth
+
+#endif /* USE_AUTH */
+#endif /* SQUID_SRC_AUTH_CONFIG_H */
+

=== modified file 'src/auth/CredentialsCache.cc'
--- src/auth/CredentialsCache.cc	2016-11-15 09:34:16 +0000
+++ src/auth/CredentialsCache.cc	2016-12-19 15:30:31 +0000
@@ -1,38 +1,37 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 29    Authenticator */
 
 #include "squid.h"
 #include "acl/Gadgets.h"
+#include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "base/RunnersRegistry.h"
 #include "Debug.h"
 #include "event.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
 
 namespace Auth {
 
 class CredentialCacheRr : public RegisteredRunner
 {
 public:
     explicit CredentialCacheRr(const char *n, CredentialsCache * const c) :
         name(n),
         whichCache(c)
     {}
 
     virtual ~CredentialCacheRr() {
         debugs(29, 5, "Terminating Auth credentials cache: " << name);
         // invalidate the CBDATA reference.
         // causes Auth::*::User::Cache() to produce nil / invalid pointer
         delete whichCache.get();
     }
 
     virtual void endingShutdown() override {
         debugs(29, 5, "Clearing Auth credentials cache: " << name);
@@ -68,41 +67,41 @@
     debugs(29, 6, "lookup for " << userKey);
     auto p = store_.find(userKey);
     if (p == store_.end())
         return User::Pointer(nullptr);
     return p->second;
 }
 
 void
 CredentialsCache::Cleanup(void *data)
 {
     debugs(29, 5, "checkpoint");
     // data is this in disguise
     CredentialsCache *self = static_cast<CredentialsCache *>(data);
     self->cleanup();
 }
 
 void
 CredentialsCache::cleanup()
 {
     // cache entries with expiretime <= expirationTime are to be evicted
-    const time_t expirationTime =  current_time.tv_sec - ::Config.authenticateTTL;
+    const time_t expirationTime =  current_time.tv_sec - Auth::TheConfig.authenticateTTL;
 
     const auto end = store_.end();
     for (auto i = store_.begin(); i != end;) {
         debugs(29, 6, "considering " << i->first << "(expires in " <<
                (expirationTime - i->second->expiretime) << " sec)");
         if (i->second->expiretime <= expirationTime) {
             debugs(29, 6, "evicting " << i->first);
             i = store_.erase(i); //erase advances i
         } else {
             ++i;
         }
     }
     gcScheduled_ = false;
     scheduleCleanup();
 }
 
 void
 CredentialsCache::insert(const SBuf &userKey, Auth::User::Pointer anAuth_user)
 {
     debugs(29, 6, "adding " << userKey << " (" << anAuth_user->username() << ")");
@@ -116,37 +115,37 @@
 CredentialsCache::sortedUsersList() const
 {
     std::vector<Auth::User::Pointer> rv(size(), nullptr);
     std::transform(store_.begin(), store_.end(), rv.begin(),
     [](StoreType::value_type v) { return v.second; }
                   );
     std::sort(rv.begin(), rv.end(),
     [](const Auth::User::Pointer &lhs, const Auth::User::Pointer &rhs) {
         return strcmp(lhs->username(), rhs->username()) < 0;
     }
              );
     return rv;
 }
 
 void
 CredentialsCache::scheduleCleanup()
 {
     if (!gcScheduled_ && store_.size()) {
         gcScheduled_ = true;
         eventAdd(cacheCleanupEventName, &CredentialsCache::Cleanup,
-                 this, ::Config.authenticateGCInterval, 1);
+                 this, Auth::TheConfig.authenticateGCInterval, 1);
     }
 }
 
 void
 CredentialsCache::doConfigChangeCleanup()
 {
     // purge expired entries entirely
     cleanup();
     // purge the ACL match data stored in the credentials
     for (auto i : store_) {
         aclCacheMatchFlush(&i.second->proxy_match_cache);
     }
 }
 
 } /* namespace Auth */
 

=== modified file 'src/auth/Gadgets.cc'
--- src/auth/Gadgets.cc	2016-01-24 17:41:43 +0000
+++ src/auth/Gadgets.cc	2016-12-20 10:20:36 +0000
@@ -22,128 +22,126 @@
 #include "auth/digest/User.h"
 #include "auth/Gadgets.h"
 #include "auth/negotiate/User.h"
 #include "auth/ntlm/User.h"
 #include "auth/Scheme.h"
 #include "auth/User.h"
 #include "auth/UserRequest.h"
 #include "client_side.h"
 #include "globals.h"
 #include "http/Stream.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
 
 /**** PUBLIC FUNCTIONS (ALL GENERIC!)  ****/
 
 int
 authenticateActiveSchemeCount(void)
 {
     int rv = 0;
 
-    for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
-        if ((*i)->configured())
+    for (auto *scheme : Auth::TheConfig.schemes) {
+        if (scheme->configured())
             ++rv;
+    }
 
     debugs(29, 9, HERE << rv << " active.");
 
     return rv;
 }
 
 int
 authenticateSchemeCount(void)
 {
     int rv = Auth::Scheme::GetSchemes().size();
 
     debugs(29, 9, HERE << rv << " active.");
 
     return rv;
 }
 
 static void
 authenticateRegisterWithCacheManager(Auth::ConfigVector * config)
 {
-    for (Auth::ConfigVector::iterator i = config->begin(); i != config->end(); ++i) {
-        Auth::Config *scheme = *i;
+    for (auto *scheme : *config)
         scheme->registerWithCacheManager();
-    }
 }
 
 void
 authenticateInit(Auth::ConfigVector * config)
 {
     /* If we do not have any auth config state to create stop now. */
     if (!config)
         return;
 
-    for (Auth::ConfigVector::iterator i = config->begin(); i != config->end(); ++i) {
-        Auth::Config *schemeCfg = *i;
-
-        if (schemeCfg->configured())
-            schemeCfg->init(schemeCfg);
+    for (auto *scheme : *config) {
+        if (scheme->configured())
+            scheme->init(scheme);
     }
 
     authenticateRegisterWithCacheManager(config);
 }
 
 void
 authenticateRotate(void)
 {
-    for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
-        if ((*i)->configured())
-            (*i)->rotateHelpers();
+    for (auto *scheme : Auth::TheConfig.schemes) {
+        if (scheme->configured())
+            scheme->rotateHelpers();
+    }
 }
 
 void
 authenticateReset(void)
 {
     debugs(29, 2, "Reset authentication State.");
 
     // username cache is cleared via Runner registry
 
     /* schedule shutdown of the helpers */
     authenticateRotate();
 
     /* free current global config details too. */
-    Auth::TheConfig.clear();
+    Auth::TheConfig.schemes.clear();
 }
 
 std::vector<Auth::User::Pointer>
 authenticateCachedUsersList()
 {
     auto aucp_compare = [=](const Auth::User::Pointer lhs, const Auth::User::Pointer rhs) {
         return lhs->userKey() < rhs->userKey();
     };
     std::vector<Auth::User::Pointer> v1, v2, rv, u1, u2;
 #if HAVE_AUTH_MODULE_BASIC
-    if (Auth::Config::Find("basic") != nullptr)
+    if (Auth::SchemeConfig::Find("basic"))
         u1 = Auth::Basic::User::Cache()->sortedUsersList();
 #endif
 #if HAVE_AUTH_MODULE_DIGEST
-    if (Auth::Config::Find("digest") != nullptr)
+    if (Auth::SchemeConfig::Find("digest"))
         u2 = Auth::Digest::User::Cache()->sortedUsersList();
 #endif
     if (u1.size() > 0 || u2.size() > 0) {
         v1.reserve(u1.size()+u2.size());
         std::merge(u1.begin(), u1.end(),u2.begin(), u2.end(),
                    std::back_inserter(v1), aucp_compare);
         u1.clear();
         u2.clear();
     }
 #if HAVE_AUTH_MODULE_NEGOTIATE
-    if (Auth::Config::Find("negotiate") != nullptr)
+    if (Auth::SchemeConfig::Find("negotiate"))
         u1 = Auth::Negotiate::User::Cache()->sortedUsersList();
 #endif
 #if HAVE_AUTH_MODULE_NTLM
-    if (Auth::Config::Find("ntlm") != nullptr)
+    if (Auth::SchemeConfig::Find("ntlm"))
         u2 = Auth::Ntlm::User::Cache()->sortedUsersList();
 #endif
     if (u1.size() > 0 || u2.size() > 0) {
         v2.reserve(u1.size()+u2.size());
         std::merge(u1.begin(), u1.end(),u2.begin(), u2.end(),
                    std::back_inserter(v2), aucp_compare);
     }
     rv.reserve(v1.size()+v2.size());
     std::merge(v1.begin(), v1.end(),v2.begin(), v2.end(),
                std::back_inserter(rv), aucp_compare);
     return rv;
 }
 

=== modified file 'src/auth/Gadgets.h'
--- src/auth/Gadgets.h	2016-01-01 00:12:18 +0000
+++ src/auth/Gadgets.h	2016-12-19 13:25:57 +0000
@@ -1,48 +1,40 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_GADGETS_H
 #define SQUID_AUTH_GADGETS_H
 
 #if USE_AUTH
 
-#include "auth/Config.h"
 #include "auth/User.h"
 #include "hash.h"
 
-namespace Auth
-{
-class Scheme;
-}
 class ConnStateData;
 class StoreEntry;
 
-/**
- \ingroup AuthAPI
- \todo this should be a generic cachemgr API type ?
- */
+// TODO this should be a generic cachemgr API type ?
 typedef void AUTHSSTATS(StoreEntry *);
 
 /// \ingroup AuthAPI
 void authenticateInit(Auth::ConfigVector *);
 
 /** \ingroup AuthAPI
  * Remove all idle authentication state. Intended for use by reconfigure.
  *
  * Removes the username cache contents and global configuration state.
  * Stops just short of detaching the auth components completely.
  *
  * Currently active requests should finish. Howevee new requests will not use
  * authentication unless something causes the global config to be rebuilt.
  * Such as a configure load action adding config and re-running authenticateInit().
  */
 void authenticateReset(void);
 
 void authenticateRotate(void);
 
 /// \ingroup AuthAPI

=== modified file 'src/auth/Makefile.am'
--- src/auth/Makefile.am	2016-12-10 04:48:25 +0000
+++ src/auth/Makefile.am	2016-12-19 13:25:57 +0000
@@ -8,45 +8,48 @@
 include $(top_srcdir)/src/Common.am
 include $(top_srcdir)/src/TestHeaders.am
 
 SUBDIRS = $(AUTH_MODULES)
 DIST_SUBDIRS = basic digest negotiate ntlm
 
 noinst_LTLIBRARIES = libauth.la libacls.la
 ## not needed? $(AUTH_LIBS_TO_BUILD)
 ## EXTRA_LTLIBRARIES = libdigest.la libntlm.la libnegotiate.la
 
 ## authentication framework; this library is always built
 libauth_la_SOURCES = \
 	Type.h \
 	Type.cc \
 	Config.cc \
 	Config.h \
 	CredentialsCache.h \
 	CredentialsCache.cc \
 	CredentialState.cc \
 	CredentialState.h \
+	forward.h \
 	Gadgets.cc \
 	Gadgets.h \
 	QueueNode.h \
 	Scheme.cc \
 	Scheme.h \
+	SchemeConfig.cc \
+	SchemeConfig.h \
 	SchemesConfig.h \
 	SchemesConfig.cc \
 	State.h \
 	State.cc \
 	User.h \
 	User.cc \
 	UserRequest.h \
 	UserRequest.cc
 
 libauth_la_LIBADD = $(AUTH_LIBS_TO_BUILD)
 libauth_la_DEPENDENCIES = $(AUTH_LIBS_TO_BUILD)
 
 ## authentication-dependent ACLs and authentication code they share
 libacls_la_SOURCES = \
 	Acl.cc \
 	Acl.h \
 	\
 	AclMaxUserIp.cc \
 	AclMaxUserIp.h \
 	AclProxyAuth.cc \

=== modified file 'src/auth/QueueNode.h'
--- src/auth/QueueNode.h	2016-01-01 00:12:18 +0000
+++ src/auth/QueueNode.h	2016-12-19 13:25:58 +0000
@@ -1,31 +1,32 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SRC_AUTH_QUEUENODE_H
 #define SQUID_SRC_AUTH_QUEUENODE_H
 
+#include "auth/forward.h"
 #include "cbdata.h"
 
 namespace Auth
 {
 
 /**
  * A queue of auth requests waiting for verification to occur.
  *
  * Certain authentication schemes such a Basic and Bearer auth
  * permit credentials tokens to be repeated from multiple sources
  * simultaneously. This queue node allows multiple validation
  * queries to be collapsed into one backend helper lookup.
  * CBDATA and handlers stored in these queue nodes can be notified
  * all at once with a result when the lookup completes.
  */
 class QueueNode
 {
     MEMPROXY_CLASS(Auth::QueueNode);
 
 private:

=== modified file 'src/auth/Scheme.cc'
--- src/auth/Scheme.cc	2016-01-01 00:12:18 +0000
+++ src/auth/Scheme.cc	2016-12-19 13:25:59 +0000
@@ -1,34 +1,34 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 29    Authenticator */
 
 #include "squid.h"
-#include "auth/Config.h"
 #include "auth/Gadgets.h"
 #include "auth/Scheme.h"
+#include "auth/SchemeConfig.h"
 #include "globals.h"
 
 std::vector<Auth::Scheme::Pointer> *Auth::Scheme::_Schemes = NULL;
 
 void
 Auth::Scheme::AddScheme(Auth::Scheme::Pointer instance)
 {
     iterator i = GetSchemes().begin();
 
     while (i != GetSchemes().end()) {
         assert(strcmp((*i)->type(), instance->type()) != 0);
         ++i;
     }
 
     GetSchemes().push_back(instance);
 }
 
 Auth::Scheme::Pointer
 Auth::Scheme::Find(const char *typestr)
 {

=== modified file 'src/auth/Scheme.h'
--- src/auth/Scheme.h	2016-01-01 00:12:18 +0000
+++ src/auth/Scheme.h	2016-12-19 13:26:00 +0000
@@ -1,88 +1,77 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_SCHEME_H
 #define SQUID_AUTH_SCHEME_H
 
 #if USE_AUTH
 
+#include "auth/forward.h"
 #include "base/RefCount.h"
 
-#include <vector>
-
-/**
- \defgroup AuthSchemeAPI    Authentication Scheme API
- \ingroup AuthAPI
- */
-
 namespace Auth
 {
 
-class Config;
-
 /**
- * \ingroup AuthAPI
- * \ingroup AuthSchemeAPI
- * \par
  * I represent an authentication scheme. For now my children
  * store the scheme metadata.
- * \par
+ *
  * Should we need multiple configs of a single scheme,
  * a new class should be made, and the config specific calls on Auth::Scheme moved to it.
  */
 class Scheme : public RefCountable
 {
 public:
     typedef RefCount<Scheme> Pointer;
     typedef std::vector<Scheme::Pointer>::iterator iterator;
     typedef std::vector<Scheme::Pointer>::const_iterator const_iterator;
 
 public:
     Scheme() : initialised (false) {};
     virtual ~Scheme() {};
 
     static void AddScheme(Scheme::Pointer);
 
     /**
      * Final termination of all authentication components.
      * To be used only on shutdown. All global pointers are released.
      * After this all schemes will appear completely unsupported
      * until a call to InitAuthModules().
      * Release the Auth::TheConfig handles instead to disable authentication
      * without terminiating all support.
      */
     static void FreeAll();
 
     /**
      * Locate an authentication scheme component by Name.
      */
     static Scheme::Pointer Find(const char *);
 
     /* per scheme methods */
     virtual char const *type() const = 0;
     virtual void shutdownCleanup() = 0;
-    virtual Auth::Config *createConfig() = 0;
+    virtual Auth::SchemeConfig *createConfig() = 0;
 
     // Not implemented
     Scheme(Scheme const &);
     Scheme &operator=(Scheme const&);
 
     static std::vector<Scheme::Pointer> &GetSchemes();
 
 protected:
     bool initialised;
 
 private:
     static std::vector<Scheme::Pointer> *_Schemes;
 };
 
 } // namespace Auth
 
 #endif /* USE_AUTH */
 #endif /* SQUID_AUTH_SCHEME_H */
 

=== renamed file 'src/auth/Config.cc' => 'src/auth/SchemeConfig.cc'
--- src/auth/Config.cc	2016-12-10 04:48:25 +0000
+++ src/auth/SchemeConfig.cc	2016-12-20 13:49:00 +0000
@@ -1,103 +1,103 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 29    Authenticator */
 
 #include "squid.h"
 #include "auth/Config.h"
+#include "auth/forward.h"
 #include "auth/Gadgets.h"
 #include "auth/UserRequest.h"
 #include "cache_cf.h"
 #include "ConfigParser.h"
 #include "Debug.h"
 #include "format/Format.h"
 #include "globals.h"
 #include "Store.h"
 #include "wordlist.h"
 
-Auth::ConfigVector Auth::TheConfig;
-
 /**
  * Get an User credentials object filled out for the given Proxy- or WWW-Authenticate header.
  * Any decoding which needs to be done will be done.
  *
  * It may be a cached AuthUser or a new Unauthenticated object.
  * It may also be NULL reflecting that no user could be created.
  */
 Auth::UserRequest::Pointer
-Auth::Config::CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al)
+Auth::SchemeConfig::CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al)
 {
     assert(proxy_auth != NULL);
     debugs(29, 9, HERE << "header = '" << proxy_auth << "'");
 
-    Auth::Config *config = Find(proxy_auth);
+    Auth::SchemeConfig *config = Find(proxy_auth);
 
     if (config == NULL || !config->active()) {
         debugs(29, (shutting_down?3:DBG_IMPORTANT), (shutting_down?"":"WARNING: ") <<
                "Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth << "'");
         return NULL;
     }
     static MemBuf rmb;
     rmb.reset();
     if (config->keyExtras) {
         // %credentials and %username, which normally included in
         // request_format, are - at this time, but that is OK
         // because user name is added to key explicitly, and we do
         // not want to store authenticated credentials at all.
         config->keyExtras->assemble(rmb, al, 0);
     }
 
     return config->decode(proxy_auth, rmb.hasContent() ? rmb.content() : NULL);
 }
 
-Auth::Config *
-Auth::Config::Find(const char *proxy_auth)
+Auth::SchemeConfig *
+Auth::SchemeConfig::Find(const char *proxy_auth)
 {
-    for (Auth::ConfigVector::iterator  i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
-        if (strncasecmp(proxy_auth, (*i)->type(), strlen((*i)->type())) == 0)
-            return *i;
+    for (auto *scheme : Auth::TheConfig.schemes) {
+        if (strncasecmp(proxy_auth, scheme->type(), strlen(scheme->type())) == 0)
+            return scheme;
+    }
 
     return NULL;
 }
 
-Auth::Config *
-Auth::Config::GetParsed(const char *proxy_auth)
+Auth::SchemeConfig *
+Auth::SchemeConfig::GetParsed(const char *proxy_auth)
 {
     if (auto *cfg = Find(proxy_auth))
         return cfg;
     fatalf("auth_schemes: required authentication method '%s' is not configured", proxy_auth);
     return nullptr;
 }
 
 /** Default behaviour is to expose nothing */
 void
-Auth::Config::registerWithCacheManager(void)
+Auth::SchemeConfig::registerWithCacheManager(void)
 {}
 
 void
-Auth::Config::parse(Auth::Config * scheme, int, char *param_str)
+Auth::SchemeConfig::parse(Auth::SchemeConfig * scheme, int, char *param_str)
 {
     if (strcmp(param_str, "program") == 0) {
         if (authenticateProgram)
             wordlistDestroy(&authenticateProgram);
 
         parse_wordlist(&authenticateProgram);
 
         requirePathnameExists("Authentication helper program", authenticateProgram->key);
 
     } else if (strcmp(param_str, "realm") == 0) {
         realm.clear();
 
         char *token = ConfigParser::NextQuotedOrToEol();
 
         while (token && *token && xisspace(*token))
             ++token;
 
         if (!token || !*token) {
             debugs(29, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Missing auth_param " << scheme->type() << " realm");
             self_destruct();
@@ -109,60 +109,72 @@
     } else if (strcmp(param_str, "children") == 0) {
         authenticateChildren.parseConfig();
 
     } else if (strcmp(param_str, "key_extras") == 0) {
         keyExtrasLine = ConfigParser::NextQuotedToken();
         Format::Format *nlf =  new ::Format::Format(scheme->type());
         if (!nlf->parse(keyExtrasLine.termedBuf())) {
             debugs(29, DBG_CRITICAL, "FATAL: Failed parsing key_extras formatting value");
             self_destruct();
             return;
         }
         if (keyExtras)
             delete keyExtras;
 
         keyExtras = nlf;
 
         if (char *t = strtok(NULL, w_space)) {
             debugs(29, DBG_CRITICAL, "FATAL: Unexpected argument '" << t << "' after request_format specification");
             self_destruct();
         }
+    } else if (strcmp(param_str, "keep_alive") == 0) {
+        parse_onoff(&keep_alive);
+    } else if (strcmp(param_str, "utf8") == 0) {
+        parse_onoff(&utf8);
     } else {
         debugs(29, DBG_CRITICAL, "Unrecognised " << scheme->type() << " auth scheme parameter '" << param_str << "'");
     }
 }
 
 bool
-Auth::Config::dump(StoreEntry *entry, const char *name, Auth::Config *scheme) const
+Auth::SchemeConfig::dump(StoreEntry *entry, const char *name, Auth::SchemeConfig *scheme) const
 {
     if (!authenticateProgram)
         return false; // not configured
 
+    const char *schemeType = scheme->type();
+
     wordlist *list = authenticateProgram;
-    storeAppendPrintf(entry, "%s %s", name, scheme->type());
+    storeAppendPrintf(entry, "%s %s", name, schemeType);
     while (list != NULL) {
         storeAppendPrintf(entry, " %s", list->key);
         list = list->next;
     }
     storeAppendPrintf(entry, "\n");
 
-    storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, scheme->type(), SQUIDSBUFPRINT(realm));
+    storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, schemeType, SQUIDSBUFPRINT(realm));
 
     storeAppendPrintf(entry, "%s %s children %d startup=%d idle=%d concurrency=%d\n",
-                      name, scheme->type(),
+                      name, schemeType,
                       authenticateChildren.n_max, authenticateChildren.n_startup,
                       authenticateChildren.n_idle, authenticateChildren.concurrency);
 
-    if (keyExtrasLine.size() > 0)
-        storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, scheme->type(), keyExtrasLine.termedBuf());
+    if (keyExtrasLine.size() > 0) // default is none
+        storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, schemeType, keyExtrasLine.termedBuf());
+
+    if (!keep_alive) // default is on
+        storeAppendPrintf(entry, "%s %s keep_alive off\n", name, schemeType);
+
+    if (utf8) // default is off
+        storeAppendPrintf(entry, "%s %s utf8 on\n", name, schemeType);
 
     return true;
 }
 
 void
-Auth::Config::done()
+Auth::SchemeConfig::done()
 {
     delete keyExtras;
     keyExtras = NULL;
     keyExtrasLine.clean();
 }
 

=== renamed file 'src/auth/Config.h' => 'src/auth/SchemeConfig.h'
--- src/auth/Config.h	2016-12-10 04:48:25 +0000
+++ src/auth/SchemeConfig.h	2016-12-20 12:15:10 +0000
@@ -1,77 +1,78 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
-#ifndef SQUID_AUTH_CONFIG_H
-#define SQUID_AUTH_CONFIG_H
+#ifndef SQUID_SRC_AUTH_SCHEMECONFIG_H
+#define SQUID_SRC_AUTH_SCHEMECONFIG_H
 
 #if USE_AUTH
 
 #include "AccessLogEntry.h"
+#include "auth/forward.h"
 #include "auth/UserRequest.h"
 #include "helper/ChildConfig.h"
 
 class StoreEntry;
 class HttpReply;
 class HttpRequest;
 class wordlist;
 
 /* for Http::HdrType parameters-by-value */
 #include "HttpHeader.h"
 
 namespace Format
 {
 class Format;
 }
 
 namespace Auth
 {
 
 /**
  * \ingroup AuthAPI
  * \par
  * I am the configuration for an auth scheme.
  * Currently each scheme has only one instance of me,
  * but this may change.
  * \par
  * This class is treated like a ref counted class.
  * If the children ever stop being singletons, implement the
  * ref counting...
  */
-class Config
+class SchemeConfig
 {
 
 public:
     static UserRequest::Pointer CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al);
 
-    static Config *Find(const char *proxy_auth);
+    static SchemeConfig *Find(const char *proxy_auth);
     /// Call this method if you need a guarantee that all auth schemes has been
     /// already configured.
-    static Config *GetParsed(const char *proxy_auth);
-    Config() : authenticateChildren(20), authenticateProgram(NULL), keyExtras(NULL) {}
+    static SchemeConfig *GetParsed(const char *proxy_auth);
+    SchemeConfig() : authenticateChildren(20) {}
 
-    virtual ~Config() {}
+    virtual ~SchemeConfig() {}
 
     /**
      * Used by squid to determine whether the auth module has successfully initialised itself with the current configuration.
      *
      \retval true   Authentication Module loaded and running.
      \retval false  No Authentication Module loaded.
      */
     virtual bool active() const = 0;
 
     /**
      * new decode API: virtual factory pattern
      \par
      * Responsible for decoding the passed authentication header, creating or
      * linking to a AuthUser object and for storing any needed details to complete
      * authentication in Auth::UserRequest::authenticate().
      *
      \param proxy_auth  Login Pattern to parse.
      \retval *      Details needed to authenticate.
      */
     virtual UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm) = 0;
@@ -89,57 +90,55 @@
      * The configured function is used to see if the auth module has been given valid
      * parameters and is able to handle authentication requests.
      *
      \retval true   Authentication Module configured ready for use.
      \retval false  Not configured or Configuration Error.
      *          No other module functions except Shutdown/Dump/Parse/FreeConfig will be called by Squid.
      */
     virtual bool configured() const = 0;
 
     /**
      * Shutdown just the auth helpers.
      * For use by log rotate etc. where auth needs to stay running, with the helpers restarted.
      */
     virtual void rotateHelpers(void) = 0;
 
     /**
      * Responsible for writing to the StoreEntry the configuration parameters that a user
      * would put in a config file to recreate the running configuration.
      * Returns whether the scheme is configured.
      */
-    virtual bool dump(StoreEntry *, const char *, Config *) const;
+    virtual bool dump(StoreEntry *, const char *, SchemeConfig *) const;
 
     /** add headers as needed when challenging for auth */
     virtual void fixHeader(UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *) = 0;
 
     /** prepare to handle requests */
-    virtual void init(Config *) = 0;
+    virtual void init(SchemeConfig *) = 0;
 
     /** expose any/all statistics to a CacheManager */
     virtual void registerWithCacheManager(void);
 
     /** parse config options */
-    virtual void parse(Config *, int, char *);
+    virtual void parse(SchemeConfig *, int, char *);
 
     /** the http string id */
     virtual const char * type() const = 0;
 
 public:
     Helper::ChildConfig authenticateChildren;
-    wordlist *authenticateProgram; ///< Helper program to run, includes all parameters
+    wordlist *authenticateProgram = nullptr; ///< Helper program to run, includes all parameters
     String keyExtrasLine;  ///< The format of the request to the auth helper
-    Format::Format *keyExtras; ///< The compiled request format
+    Format::Format *keyExtras = nullptr; ///< The compiled request format
+    int keep_alive = 1; ///< whether to close the connection on auth challenges. default: on
+    int utf8 = 0; ///< wheter to accept UTF-8 characterset instead of ASCII. default: off
 
 protected:
     /// RFC 7235 section 2.2 - Protection Space (Realm)
     SBuf realm;
 };
 
-typedef std::vector<Config *> ConfigVector;
-
-extern ConfigVector TheConfig;
-
 } // namespace Auth
 
 #endif /* USE_AUTH */
-#endif /* SQUID_AUTHCONFIG_H */
+#endif /* SQUID_SRC_AUTH_SCHEMECONFIG_H */
 

=== modified file 'src/auth/SchemesConfig.cc'
--- src/auth/SchemesConfig.cc	2016-12-10 04:48:25 +0000
+++ src/auth/SchemesConfig.cc	2016-12-19 13:26:03 +0000
@@ -1,47 +1,46 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "auth/Config.h"
-#include "auth/SchemesConfig.h"
 #include "fatal.h"
 #include "parser/Tokenizer.h"
 
 static void
 addUnique(const SBuf &scheme, std::vector<SBuf> &vec)
 {
     static const SBuf all("ALL");
     if (scheme == all) {
-        for (const auto config: Auth::TheConfig)
+        for (const auto config: Auth::TheConfig.schemes)
             addUnique(SBuf(config->type()), vec);
     } else if (std::find(vec.begin(), vec.end(), scheme) == vec.end())
         vec.push_back(scheme);
 }
 
 void
 Auth::SchemesConfig::expand()
 {
     static const CharacterSet delimiters("delimiters", ",");
     static const CharacterSet quotedDelimiters("quotedDelimiters", ", ");
     const CharacterSet *resultDelimiters = quoted ? &quotedDelimiters : &delimiters;
     std::vector<SBuf> expanded;
     Parser::Tokenizer t(schemes);
     SBuf scheme;
     while (t.token(scheme, *resultDelimiters))
         addUnique(scheme, expanded);
     t.skipAllTrailing(CharacterSet::SP + CharacterSet::HTAB);
     if (!t.remaining().isEmpty())
         addUnique(t.remaining(), expanded);
 
     authConfigs.clear();
     transform(expanded.begin(), expanded.end(),
     back_inserter(authConfigs), [](SBuf &s) {
-        return Auth::Config::GetParsed(s.c_str());
+        return Auth::SchemeConfig::GetParsed(s.c_str());
     });
 }
 

=== modified file 'src/auth/SchemesConfig.h'
--- src/auth/SchemesConfig.h	2016-12-10 04:48:25 +0000
+++ src/auth/SchemesConfig.h	2016-12-19 13:26:04 +0000
@@ -1,52 +1,49 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SCHEMES_CONFIG_H
 #define SQUID_SCHEMES_CONFIG_H
 
 #if USE_AUTH
 
-#include "auth/Config.h"
+#include "auth/SchemeConfig.h"
 
 namespace Auth
 {
 
 /**
- * \ingroup AuthAPI
  * Stores authentication schemes list, configured by auth_schemes
  * directive.
  */
 class SchemesConfig
 {
 public:
     SchemesConfig(const char *s, const bool q) : schemes(s), quoted(q), rawSchemes(schemes.c_str()) {}
     /// Expands special "ALL" scheme name (if provided), removes
     /// duplicates and fills authConfigs vector.
     void expand();
 
 public:
     /// corresponding vector of Auth::Config objects
-    ConfigVector authConfigs;
+    Auth::ConfigVector authConfigs;
 
 private:
     /// raw auth schemes list (may have duplicates)
     SBuf schemes;
     const bool quoted;
 
 public:
     /// optimization for storing schemes.c_str()
     const char *rawSchemes;
 };
 
-typedef std::vector<SchemesConfig> SchemesConfigs;
-
 } // namespace Auth
 
 #endif /* USE_AUTH */
 #endif /* SQUID_SCHEMES_CONFIG_H */
 

=== modified file 'src/auth/User.cc'
--- src/auth/User.cc	2016-07-05 05:45:44 +0000
+++ src/auth/User.cc	2016-12-19 15:32:50 +0000
@@ -1,45 +1,44 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 29    Authenticator */
 
 #include "squid.h"
 #include "acl/Acl.h"
 #include "acl/Gadgets.h"
 #include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "auth/Gadgets.h"
 #include "auth/User.h"
 #include "auth/UserRequest.h"
 #include "event.h"
 #include "globals.h"
-#include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
 
-Auth::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
     auth_type(Auth::AUTH_UNKNOWN),
     config(aConfig),
     ipcount(0),
     expiretime(0),
     credentials_state(Auth::Unchecked),
     username_(nullptr),
     requestRealm_(aRequestRealm)
 {
     proxy_match_cache.head = proxy_match_cache.tail = NULL;
     ip_list.head = ip_list.tail = NULL;
     debugs(29, 5, HERE << "Initialised auth_user '" << this << "'.");
 }
 
 Auth::CredentialState
 Auth::User::credentials() const
 {
     return credentials_state;
 }
 
 void
@@ -184,98 +183,98 @@
 
 void
 Auth::User::addIp(Ip::Address ipaddr)
 {
     AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
     int found = 0;
 
     /*
      * we walk the entire list to prevent the first item in the list
      * preventing old entries being flushed and locking a user out after
      * a timeout+reconfigure
      */
     while (ipdata) {
         AuthUserIP *tempnode = (AuthUserIP *) ipdata->node.next;
         /* walk the ip list */
 
         if (ipdata->ipaddr == ipaddr) {
             /* This ip has already been seen. */
             found = 1;
             /* update IP ttl */
-            ipdata->ip_expiretime = squid_curtime + ::Config.authenticateIpTTL;
+            ipdata->ip_expiretime = squid_curtime + Auth::TheConfig.authenticateIpTTL;
         } else if (ipdata->ip_expiretime <= squid_curtime) {
             /* This IP has expired - remove from the seen list */
             dlinkDelete(&ipdata->node, &ip_list);
             delete ipdata;
             /* catch incipient underflow */
             assert(ipcount);
             -- ipcount;
         }
 
         ipdata = tempnode;
     }
 
     if (found)
         return;
 
     /* This ip is not in the seen list */
-    ipdata = new AuthUserIP(ipaddr, squid_curtime + ::Config.authenticateIpTTL);
+    ipdata = new AuthUserIP(ipaddr, squid_curtime + Auth::TheConfig.authenticateIpTTL);
 
     dlinkAddTail(ipdata, &ipdata->node, &ip_list);
 
     ++ipcount;
 
     debugs(29, 2, HERE << "user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")");
 }
 
 SBuf
 Auth::User::BuildUserKey(const char *username, const char *realm)
 {
     SBuf key;
     if (realm)
         key.Printf("%s:%s", username, realm);
     else
         key.append(username, strlen(username));
     return key;
 }
 
 /**
  * Dump the username cache statictics for viewing...
  */
 void
 Auth::User::CredentialsCacheStats(StoreEntry *output)
 {
     auto userlist = authenticateCachedUsersList();
     storeAppendPrintf(output, "Cached Usernames: %d", static_cast<int32_t>(userlist.size()));
     storeAppendPrintf(output, "\n%-15s %-9s %-9s %-9s %s\t%s\n",
                       "Type",
                       "State",
                       "Check TTL",
                       "Cache TTL",
                       "Username", "Key");
     storeAppendPrintf(output, "--------------- --------- --------- --------- ------------------------------\n");
     for ( auto auth_user : userlist ) {
         storeAppendPrintf(output, "%-15s %-9s %-9d %-9d %s\t" SQUIDSBUFPH "\n",
                           Auth::Type_str[auth_user->auth_type],
                           CredentialState_str[auth_user->credentials()],
                           auth_user->ttl(),
-                          static_cast<int32_t>(auth_user->expiretime - squid_curtime + ::Config.authenticateTTL),
+                          static_cast<int32_t>(auth_user->expiretime - squid_curtime + Auth::TheConfig.authenticateTTL),
                           auth_user->username(),
                           SQUIDSBUFPRINT(auth_user->userKey())
                          );
     }
 }
 
 void
 Auth::User::username(char const *aString)
 {
     if (aString) {
         assert(!username_);
         username_ = xstrdup(aString);
         // NP: param #2 is working around a c_str() data-copy performance regression
         userKey_ = BuildUserKey(username_, (!requestRealm_.isEmpty() ? requestRealm_.c_str() : NULL));
     } else {
         safe_free(username_);
         userKey_.clear();
     }
 }
 

=== modified file 'src/auth/User.h'
--- src/auth/User.h	2016-02-23 08:51:22 +0000
+++ src/auth/User.h	2016-12-19 13:26:10 +0000
@@ -1,72 +1,70 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_USER_H
 #define SQUID_AUTH_USER_H
 
 #if USE_AUTH
 
 #include "auth/CredentialState.h"
+#include "auth/forward.h"
 #include "auth/Type.h"
 #include "base/CbcPointer.h"
 #include "base/RefCount.h"
 #include "dlink.h"
 #include "ip/Address.h"
 #include "Notes.h"
 #include "sbuf/SBuf.h"
 
 class StoreEntry;
 
 namespace Auth
 {
 
-class Config;
-class CredentialsCache;
-
 /**
  * This is the main user related structure. It stores user-related data,
  * and is persistent across requests. It can even persist across
  * multiple external authentications. One major benefit of preserving this
  * structure is the cached ACL match results. This structure, is private to
  * the authentication framework.
  */
 class User : public RefCountable
 {
 public:
     typedef RefCount<User> Pointer;
 
 protected:
-    User(Auth::Config *, const char *requestRealm);
+    User(Auth::SchemeConfig *, const char *requestRealm);
 public:
     virtual ~User();
 
     /* extra fields for proxy_auth */
     /** \deprecated this determines what scheme owns the user data. */
     Auth::Type auth_type;
     /** the config for this user */
-    Auth::Config *config;
+    Auth::SchemeConfig *config;
     dlink_list proxy_match_cache;
     size_t ipcount;
     long expiretime;
 
     /// list of key=value pairs the helper produced
     NotePairs notes;
 
 public:
     static SBuf BuildUserKey(const char *username, const char *realm);
 
     void absorb(Auth::User::Pointer from);
     char const *username() const { return username_; }
     void username(char const *); ///< set stored username and userKey
 
     // NP: key is set at the same time as username_. Until then both are empty/NULL.
     const SBuf userKey() const {return userKey_;}
 
     /**
      * How long these credentials are still valid for.
      * Negative numbers means already expired.

=== modified file 'src/auth/UserRequest.cc'
--- src/auth/UserRequest.cc	2016-12-10 04:48:25 +0000
+++ src/auth/UserRequest.cc	2016-12-19 14:28:42 +0000
@@ -1,50 +1,45 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 29    Authenticator */
 
 /* The functions in this file handle authentication.
  * They DO NOT perform access control or auditing.
  * See acl.c for access control and client_side.c for auditing */
 
 #include "squid.h"
 #include "acl/FilledChecklist.h"
 #include "auth/Config.h"
-#include "auth/Scheme.h"
-#include "auth/SchemesConfig.h"
-#include "auth/User.h"
-#include "auth/UserRequest.h"
 #include "client_side.h"
 #include "comm/Connection.h"
 #include "fatal.h"
 #include "format/Format.h"
 #include "http/Stream.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
 #include "MemBuf.h"
-#include "SquidConfig.h"
 
 /* Generic Functions */
 
 char const *
 Auth::UserRequest::username() const
 {
     if (user() != NULL)
         return user()->username();
     else
         return NULL;
 }
 
 /**** PUBLIC FUNCTIONS (ALL GENERIC!)  ****/
 
 /* send the initial data to an authenticator module */
 void
 Auth::UserRequest::start(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
 {
     assert(handler);
     assert(data);
@@ -321,57 +316,57 @@
 
         /* remove this request struct - the link is already authed and it can't be to reauth. */
 
         /* This should _only_ ever occur on the first pass through
          * authenticateAuthenticate
          */
         assert(*auth_user_request == NULL);
         conn->setAuth(NULL, "changed credentials token");
     }
 
     /* we have a proxy auth header and as far as we know this connection has
      * not had bungled connection oriented authentication happen on it. */
     debugs(29, 9, HERE << "header " << (proxy_auth ? proxy_auth : "-") << ".");
 
     if (*auth_user_request == NULL) {
         if (conn != NULL) {
             debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection);
         }
 
         if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->getAuth() != NULL) {
-            Auth::Config * scheme = Auth::Config::Find(proxy_auth);
+            Auth::SchemeConfig * scheme = Auth::SchemeConfig::Find(proxy_auth);
 
             if (conn->getAuth()->user() == NULL || conn->getAuth()->user()->config != scheme) {
                 debugs(29, DBG_IMPORTANT, "WARNING: Unexpected change of authentication scheme from '" <<
                        (conn->getAuth()->user()!=NULL?conn->getAuth()->user()->config->type():"[no user]") <<
                        "' to '" << proxy_auth << "' (client " <<
                        src_addr << ")");
 
                 conn->setAuth(NULL, "changed auth scheme");
             }
         }
 
         if (request->auth_user_request == NULL && (conn == NULL || conn->getAuth() == NULL)) {
             /* beginning of a new request check */
             debugs(29, 4, HERE << "No connection authentication type");
 
-            *auth_user_request = Auth::Config::CreateAuthUser(proxy_auth, al);
+            *auth_user_request = Auth::SchemeConfig::CreateAuthUser(proxy_auth, al);
             if (*auth_user_request == NULL)
                 return AUTH_ACL_CHALLENGE;
             else if (!(*auth_user_request)->valid()) {
                 /* the decode might have left a username for logging, or a message to
                  * the user */
 
                 if ((*auth_user_request)->username()) {
                     request->auth_user_request = *auth_user_request;
                 }
 
                 *auth_user_request = NULL;
                 return AUTH_ACL_CHALLENGE;
             }
 
         } else if (request->auth_user_request != NULL) {
             *auth_user_request = request->auth_user_request;
         } else {
             assert (conn != NULL);
             if (conn->getAuth() != NULL) {
                 *auth_user_request = conn->getAuth();
@@ -450,92 +445,90 @@
             request->auth_user_request = t;
         }
         return t->lastReply;
     }
 
     // ok, call the actual authenticator routine.
     AuthAclState result = authenticate(aUR, headertype, request, conn, src_addr, al);
 
     // auth process may have changed the UserRequest we are dealing with
     t = authTryGetUser(*aUR, conn, request);
 
     if (t != NULL && result != AUTH_ACL_CANNOT_AUTHENTICATE && result != AUTH_ACL_HELPER)
         t->lastReply = result;
 
     return result;
 }
 
 static Auth::ConfigVector &
 schemesConfig(HttpRequest *request, HttpReply *rep)
 {
-    if (::Config.accessList.authSchemes) {
+    if (!Auth::TheConfig.schemeLists.empty() && Auth::TheConfig.schemeAccess) {
         ACLFilledChecklist ch(NULL, request, NULL);
         ch.reply = rep;
         HTTPMSGLOCK(ch.reply);
-        const allow_t answer = ch.fastCheck(::Config.accessList.authSchemes);
+        const allow_t answer = ch.fastCheck(Auth::TheConfig.schemeAccess);
         if (answer == ACCESS_ALLOWED)
-            return ::Config.authSchemesConfigs.at(answer.kind).authConfigs;
+            return Auth::TheConfig.schemeLists.at(answer.kind).authConfigs;
     }
-    return Auth::TheConfig;
+    return Auth::TheConfig.schemes;
 }
 
 void
 Auth::UserRequest::addReplyAuthHeader(HttpReply * rep, Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal)
 /* send the auth types we are configured to support (and have compiled in!) */
 {
     Http::HdrType type;
 
     switch (rep->sline.status()) {
 
     case Http::scProxyAuthenticationRequired:
         /* Proxy authorisation needed */
         type = Http::HdrType::PROXY_AUTHENTICATE;
         break;
 
     case Http::scUnauthorized:
         /* WWW Authorisation needed */
         type = Http::HdrType::WWW_AUTHENTICATE;
         break;
 
     default:
         /* Keep GCC happy */
         /* some other HTTP status */
         type = Http::HdrType::BAD_HDR;
         break;
     }
 
     debugs(29, 9, "headertype:" << type << " authuser:" << auth_user_request);
 
     if (((rep->sline.status() == Http::scProxyAuthenticationRequired)
             || (rep->sline.status() == Http::scUnauthorized)) && internal)
         /* this is a authenticate-needed response */
     {
 
         if (auth_user_request != NULL && auth_user_request->direction() == Auth::CRED_CHALLENGE)
             /* add the scheme specific challenge header to the response */
             auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request);
         else {
-            /* call each configured & running authscheme */
+            /* call each configured & running auth scheme */
             Auth::ConfigVector &configs = schemesConfig(request, rep);
-            for (Auth::ConfigVector::iterator i = configs.begin(); i != configs.end(); ++i) {
-                Auth::Config *scheme = *i;
-
+            for (auto *scheme : configs) {
                 if (scheme->active()) {
                     if (auth_user_request != NULL && auth_user_request->scheme()->type() == scheme->type())
                         scheme->fixHeader(auth_user_request, rep, type, request);
                     else
                         scheme->fixHeader(NULL, rep, type, request);
                 } else
                     debugs(29, 4, HERE << "Configured scheme " << scheme->type() << " not Active");
             }
         }
 
     }
 
     /*
      * allow protocol specific headers to be _added_ to the existing
      * response - currently Digest or Negotiate auth
      */
     if (auth_user_request != NULL) {
         auth_user_request->addAuthenticationInfoHeader(rep, accelerated);
         if (auth_user_request->lastReply != AUTH_AUTHENTICATED)
             auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE;

=== modified file 'src/auth/basic/Config.cc'
--- src/auth/basic/Config.cc	2016-01-01 00:12:18 +0000
+++ src/auth/basic/Config.cc	2016-12-20 12:18:51 +0000
@@ -79,87 +79,83 @@
         debugs(29, 9, "Sending type:" << hdrType << " header: 'Basic realm=\"" << realm << "\"'");
         httpHeaderPutStrf(&rep->header, hdrType, "Basic realm=\"" SQUIDSBUFPH "\"", SQUIDSBUFPRINT(realm));
     }
 }
 
 void
 Auth::Basic::Config::rotateHelpers()
 {
     /* schedule closure of existing helpers */
     if (basicauthenticators) {
         helperShutdown(basicauthenticators);
     }
 
     /* NP: dynamic helper restart will ensure they start up again as needed. */
 }
 
 /** shutdown the auth helpers and free any allocated configuration details */
 void
 Auth::Basic::Config::done()
 {
-    Auth::Config::done();
+    Auth::SchemeConfig::done();
 
     authbasic_initialised = 0;
 
     if (basicauthenticators) {
         helperShutdown(basicauthenticators);
     }
 
     delete basicauthenticators;
     basicauthenticators = NULL;
 
     if (authenticateProgram)
         wordlistDestroy(&authenticateProgram);
 }
 
 bool
-Auth::Basic::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
+Auth::Basic::Config::dump(StoreEntry * entry, const char *name, Auth::SchemeConfig * scheme) const
 {
-    if (!Auth::Config::dump(entry, name, scheme))
+    if (!Auth::SchemeConfig::dump(entry, name, scheme))
         return false; // not configured
 
     storeAppendPrintf(entry, "%s basic credentialsttl %d seconds\n", name, (int) credentialsTTL);
     storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
-    storeAppendPrintf(entry, "%s basic utf8 %s\n", name, utf8 ? "on" : "off");
     return true;
 }
 
 Auth::Basic::Config::Config() :
     credentialsTTL( 2*60*60 ),
-    casesensitive(0),
-    utf8(0)
+    casesensitive(0)
 {
     static const SBuf defaultRealm("Squid proxy-caching web server");
     realm = defaultRealm;
 }
 
 void
-Auth::Basic::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
+Auth::Basic::Config::parse(Auth::SchemeConfig * scheme, int n_configured, char *param_str)
 {
     if (strcmp(param_str, "credentialsttl") == 0) {
         parse_time_t(&credentialsTTL);
     } else if (strcmp(param_str, "casesensitive") == 0) {
         parse_onoff(&casesensitive);
-    } else if (strcmp(param_str, "utf8") == 0) {
-        parse_onoff(&utf8);
     } else
-        Auth::Config::parse(scheme, n_configured, param_str);
+        Auth::SchemeConfig::parse(scheme, n_configured, param_str);
 }
 
 static void
 authenticateBasicStats(StoreEntry * sentry)
 {
     if (basicauthenticators)
         basicauthenticators->packStatsInto(sentry, "Basic Authenticator Statistics");
 }
 
 char *
 Auth::Basic::Config::decodeCleartext(const char *httpAuthHeader)
 {
     const char *proxy_auth = httpAuthHeader;
 
     /* trim BASIC from string */
     while (xisgraph(*proxy_auth))
         ++proxy_auth;
 
     /* Trim leading whitespace before decoding */
     while (xisspace(*proxy_auth))
@@ -262,41 +258,41 @@
         lb->addToNameCache();
 
         auth_user = lb;
         assert(auth_user != NULL);
     } else {
         /* replace the current cached password with the new one */
         Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(auth_user.getRaw());
         assert(basic_auth);
         basic_auth->updateCached(local_basic);
         auth_user = basic_auth;
     }
 
     /* link the request to the in-cache user */
     auth_user_request->user(auth_user);
     return auth_user_request;
 }
 
 /** Initialize helpers and the like for this auth scheme. Called AFTER parsing the
  * config file */
 void
-Auth::Basic::Config::init(Auth::Config *)
+Auth::Basic::Config::init(Auth::SchemeConfig *)
 {
     if (authenticateProgram) {
         authbasic_initialised = 1;
 
         if (basicauthenticators == NULL)
             basicauthenticators = new helper("basicauthenticator");
 
         basicauthenticators->cmdline = authenticateProgram;
 
         basicauthenticators->childs.updateLimits(authenticateChildren);
 
         basicauthenticators->ipc_type = IPC_STREAM;
 
         helperOpenServers(basicauthenticators);
     }
 }
 
 void
 Auth::Basic::Config::registerWithCacheManager(void)
 {

=== modified file 'src/auth/basic/Config.h'
--- src/auth/basic/Config.h	2016-01-01 00:12:18 +0000
+++ src/auth/basic/Config.h	2016-12-20 12:14:04 +0000
@@ -1,58 +1,57 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef __AUTH_BASIC_H__
 #define __AUTH_BASIC_H__
 
 #if HAVE_AUTH_MODULE_BASIC
 
-#include "auth/Config.h"
 #include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
 #include "auth/UserRequest.h"
 #include "helper/forward.h"
 
 namespace Auth
 {
 namespace Basic
 {
 
 /** Basic authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
 {
 public:
     Config();
     virtual bool active() const;
     virtual bool configured() const;
     virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
     virtual void done();
     virtual void rotateHelpers();
-    virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
+    virtual bool dump(StoreEntry *, const char *, Auth::SchemeConfig *) const;
     virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
-    virtual void init(Auth::Config *);
-    virtual void parse(Auth::Config *, int, char *);
+    virtual void init(Auth::SchemeConfig *);
+    virtual void parse(Auth::SchemeConfig *, int, char *);
     void decode(char const *httpAuthHeader, Auth::UserRequest::Pointer);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
 
 public:
     time_t credentialsTTL;
     int casesensitive;
-    int utf8;
 
 private:
     char * decodeCleartext(const char *httpAuthHeader);
 };
 
 } // namespace Basic
 } // namespace Auth
 
 extern helper *basicauthenticators;
 
 #endif /* HAVE_AUTH_MODULE_BASIC */
 #endif /* __AUTH_BASIC_H__ */
 

=== modified file 'src/auth/basic/Scheme.cc'
--- src/auth/basic/Scheme.cc	2016-01-01 00:12:18 +0000
+++ src/auth/basic/Scheme.cc	2016-12-19 13:27:07 +0000
@@ -23,27 +23,27 @@
     }
     return _instance;
 }
 
 char const *
 Auth::Basic::Scheme::type() const
 {
     return "basic";
 }
 
 void
 Auth::Basic::Scheme::shutdownCleanup()
 {
     if (_instance == NULL)
         return;
 
     _instance = NULL;
     debugs(29, DBG_CRITICAL, "Shutdown: Basic authentication.");
 }
 
-Auth::Config *
+Auth::SchemeConfig *
 Auth::Basic::Scheme::createConfig()
 {
     Auth::Basic::Config *newCfg = new Auth::Basic::Config;
-    return dynamic_cast<Auth::Config*>(newCfg);
+    return dynamic_cast<Auth::SchemeConfig*>(newCfg);
 }
 

=== modified file 'src/auth/basic/Scheme.h'
--- src/auth/basic/Scheme.h	2016-01-01 00:12:18 +0000
+++ src/auth/basic/Scheme.h	2016-12-19 13:27:08 +0000
@@ -2,47 +2,46 @@
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_BASIC_SCHEME_H
 #define SQUID_AUTH_BASIC_SCHEME_H
 
 #if HAVE_AUTH_MODULE_BASIC
 
 #include "auth/Scheme.h"
 
 namespace Auth
 {
 namespace Basic
 {
 
 /// \ingroup AuthAPI
-/// \ingroup AuthSchemeAPI
 class Scheme : public Auth::Scheme
 {
 
 public:
     static Auth::Scheme::Pointer GetInstance();
     Scheme() {};
     virtual ~Scheme() {}
 
     /* per scheme */
     virtual char const *type() const;
     virtual void shutdownCleanup();
-    virtual Auth::Config *createConfig();
+    virtual Auth::SchemeConfig *createConfig();
     /* Not implemented */
     Scheme(Scheme const &);
     Scheme &operator=(Scheme const &);
 
 private:
     static Auth::Scheme::Pointer _instance;
 };
 
 } // namespace Basic
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_BASIC */
 #endif /* SQUID_AUTH_BASIC_SCHEME_H */
 

=== modified file 'src/auth/basic/User.cc'
--- src/auth/basic/User.cc	2016-01-01 00:12:18 +0000
+++ src/auth/basic/User.cc	2016-12-19 14:43:15 +0000
@@ -1,56 +1,55 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "auth/basic/Config.h"
 #include "auth/basic/User.h"
+#include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "Debug.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
 
-Auth::Basic::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Basic::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
     Auth::User(aConfig, aRequestRealm),
     passwd(NULL),
     queue(NULL),
     currentRequest(NULL)
 {}
 
 Auth::Basic::User::~User()
 {
     safe_free(passwd);
 }
 
 int32_t
 Auth::Basic::User::ttl() const
 {
     if (credentials() != Auth::Ok && credentials() != Auth::Pending)
         return -1; // TTL is obsolete NOW.
 
     int32_t basic_ttl = expiretime - squid_curtime + static_cast<Auth::Basic::Config*>(config)->credentialsTTL;
-    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + ::Config.authenticateTTL);
+    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Auth::TheConfig.authenticateTTL);
 
     return min(basic_ttl, global_ttl);
 }
 
 bool
 Auth::Basic::User::authenticated() const
 {
     if ((credentials() == Auth::Ok) && (expiretime + static_cast<Auth::Basic::Config*>(config)->credentialsTTL > squid_curtime))
         return true;
 
     debugs(29, 4, "User not authenticated or credentials need rechecking.");
 
     return false;
 }
 
 bool
 Auth::Basic::User::valid() const
 {
     if (username() == NULL)
         return false;

=== modified file 'src/auth/basic/User.h'
--- src/auth/basic/User.h	2016-01-01 00:12:18 +0000
+++ src/auth/basic/User.h	2016-12-19 13:27:10 +0000
@@ -1,52 +1,52 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef _SQUID_AUTH_BASIC_USER_H
 #define _SQUID_AUTH_BASIC_USER_H
 
 #if HAVE_AUTH_MODULE_BASIC
 
 #include "auth/User.h"
 #include "auth/UserRequest.h"
 
 namespace Auth
 {
 
-class Config;
+class SchemeConfig;
 class QueueNode;
 
 namespace Basic
 {
 
 /** User credentials for the Basic authentication protocol */
 class User : public Auth::User
 {
     MEMPROXY_CLASS(Auth::Basic::User);
 
 public:
-    User(Auth::Config *, const char *requestRealm);
+    User(Auth::SchemeConfig *, const char *requestRealm);
     virtual ~User();
     bool authenticated() const;
     bool valid() const;
 
     /** Update the cached password for a username. */
     void updateCached(User *from);
     virtual int32_t ttl() const override;
 
     /* Auth::User API */
     static CbcPointer<Auth::CredentialsCache> Cache();
     virtual void addToNameCache() override;
 
     char *passwd;
 
     QueueNode *queue;
 
 private:
     Auth::UserRequest::Pointer currentRequest;
 };
 

=== modified file 'src/auth/basic/UserRequest.cc'
--- src/auth/basic/UserRequest.cc	2016-01-01 00:12:18 +0000
+++ src/auth/basic/UserRequest.cc	2016-12-19 13:27:11 +0000
@@ -42,89 +42,89 @@
 Auth::Basic::UserRequest::credentialsStr()
 {
     Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
     if (basic_auth)
         return basic_auth->passwd;
     return NULL;
 }
 
 /* log a basic user in
  */
 void
 Auth::Basic::UserRequest::authenticate(HttpRequest *, ConnStateData *, Http::HdrType)
 {
     assert(user() != NULL);
 
     /* if the password is not ok, do an identity */
     if (!user() || user()->credentials() != Auth::Ok)
         return;
 
     /* are we about to recheck the credentials externally? */
-    if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL) <= squid_curtime) {
+    if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL) <= squid_curtime) {
         debugs(29, 4, HERE << "credentials expired - rechecking");
         return;
     }
 
     /* we have been through the external helper, and the credentials haven't expired */
     debugs(29, 9, HERE << "user '" << user()->username() << "' authenticated");
 
     /* Decode now takes care of finding the AuthUser struct in the cache */
     /* after external auth occurs anyway */
     user()->expiretime = current_time.tv_sec;
 }
 
 Auth::Direction
 Auth::Basic::UserRequest::module_direction()
 {
     /* null auth_user is checked for by Auth::UserRequest::direction() */
     if (user()->auth_type != Auth::AUTH_BASIC)
         return Auth::CRED_ERROR;
 
     switch (user()->credentials()) {
 
     case Auth::Unchecked:
     case Auth::Pending:
         return Auth::CRED_LOOKUP;
 
     case Auth::Ok:
-        if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL <= squid_curtime)
+        if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL <= squid_curtime)
             return Auth::CRED_LOOKUP;
         return Auth::CRED_VALID;
 
     case Auth::Failed:
         return Auth::CRED_VALID;
 
     default:
         return Auth::CRED_ERROR;
     }
 }
 
 /* send the initial data to a basic authenticator module */
 void
 Auth::Basic::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
 {
     assert(user()->auth_type == Auth::AUTH_BASIC);
     Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(user().getRaw());
     assert(basic_auth != NULL);
     debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
 
-    if (static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->authenticateProgram == NULL) {
+    if (static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->authenticateProgram == NULL) {
         debugs(29, DBG_CRITICAL, "ERROR: No Basic authentication program configured.");
         handler(data);
         return;
     }
 
     /* check to see if the auth_user already has a request outstanding */
     if (user()->credentials() == Auth::Pending) {
         /* there is a request with the same credentials already being verified */
 
         Auth::QueueNode *node = new Auth::QueueNode(this, handler, data);
 
         /* queue this validation request to be infored of the pending lookup results */
         node->next = basic_auth->queue;
         basic_auth->queue = node;
         return;
     }
     // otherwise submit this request to the auth helper(s) for validation
 
     /* mark this user as having verification in progress */
     user()->credentials(Auth::Pending);

=== modified file 'src/auth/digest/Config.cc'
--- src/auth/digest/Config.cc	2016-11-27 13:57:50 +0000
+++ src/auth/digest/Config.cc	2016-12-20 12:18:55 +0000
@@ -198,41 +198,41 @@
 
 #endif
 
         assert(!nonce->flags.incache);
 
         safe_free(nonce->key);
 
         digest_nonce_pool->freeOne(nonce);
     }
 }
 
 static void
 authenticateDigestNonceSetup(void)
 {
     if (!digest_nonce_pool)
         digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h));
 
     if (!digest_nonce_cache) {
         digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
         assert(digest_nonce_cache);
-        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->nonceGCInterval, 1);
     }
 }
 
 void
 authenticateDigestNonceShutdown(void)
 {
     /*
      * We empty the cache of any nonces left in there.
      */
     digest_nonce_h *nonce;
 
     if (digest_nonce_cache) {
         debugs(29, 2, "Shutting down nonce cache");
         hash_first(digest_nonce_cache);
 
         while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {
             assert(nonce->flags.incache);
             authDigestNoncePurge(nonce);
         }
     }
@@ -261,42 +261,42 @@
     debugs(29, 3, "Current time: " << current_time.tv_sec);
     hash_first(digest_nonce_cache);
 
     while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {
         debugs(29, 3, "nonce entry  : " << nonce << " '" << (char *) nonce->key << "'");
         debugs(29, 4, "Creation time: " << nonce->noncedata.creationtime);
 
         if (authDigestNonceIsStale(nonce)) {
             debugs(29, 4, "Removing nonce " << (char *) nonce->key << " from cache due to timeout.");
             assert(nonce->flags.incache);
             /* invalidate nonce so future requests fail */
             nonce->flags.valid = false;
             /* if it is tied to a auth_user, remove the tie */
             authDigestNonceUserUnlink(nonce);
             authDigestNoncePurge(nonce);
         }
     }
 
     debugs(29, 3, "Finished cleaning the nonce cache.");
 
-    if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->active())
-        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+    if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->active())
+        eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->nonceGCInterval, 1);
 }
 
 static void
 authDigestNonceLink(digest_nonce_h * nonce)
 {
     assert(nonce != NULL);
     ++nonce->references;
     debugs(29, 9, "nonce '" << nonce << "' now at '" << nonce->references << "'.");
 }
 
 #if NOT_USED
 static int
 authDigestNonceLinks(digest_nonce_h * nonce)
 {
     if (!nonce)
         return -1;
 
     return nonce->references;
 }
 
@@ -349,162 +349,161 @@
 }
 
 int
 authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9])
 {
     unsigned long intnc;
     /* do we have a nonce ? */
 
     if (!nonce)
         return 0;
 
     intnc = strtol(nc, NULL, 16);
 
     /* has it already been invalidated ? */
     if (!nonce->flags.valid) {
         debugs(29, 4, "Nonce already invalidated");
         return 0;
     }
 
     /* is the nonce-count ok ? */
-    if (!static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->CheckNonceCount) {
+    if (!static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->CheckNonceCount) {
         /* Ignore client supplied NC */
         intnc = nonce->nc + 1;
     }
 
-    if ((static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->NonceStrictness && intnc != nonce->nc + 1) ||
+    if ((static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->NonceStrictness && intnc != nonce->nc + 1) ||
             intnc < nonce->nc + 1) {
         debugs(29, 4, "Nonce count doesn't match");
         nonce->flags.valid = false;
         return 0;
     }
 
     /* increment the nonce count - we've already checked that intnc is a
      *  valid representation for us, so we don't need the test here.
      */
     nonce->nc = intnc;
 
     return !authDigestNonceIsStale(nonce);
 }
 
 int
 authDigestNonceIsStale(digest_nonce_h * nonce)
 {
     /* do we have a nonce ? */
 
     if (!nonce)
         return -1;
 
     /* Is it already invalidated? */
     if (!nonce->flags.valid)
         return -1;
 
     /* has it's max duration expired? */
-    if (nonce->noncedata.creationtime + static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxduration < current_time.tv_sec) {
+    if (nonce->noncedata.creationtime + static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration < current_time.tv_sec) {
         debugs(29, 4, "Nonce is too old. " <<
                nonce->noncedata.creationtime << " " <<
-               static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxduration << " " <<
+               static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration << " " <<
                current_time.tv_sec);
 
         nonce->flags.valid = false;
         return -1;
     }
 
     if (nonce->nc > 99999998) {
         debugs(29, 4, "Nonce count overflow");
         nonce->flags.valid = false;
         return -1;
     }
 
-    if (nonce->nc > static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxuses) {
+    if (nonce->nc > static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxuses) {
         debugs(29, 4, "Nonce count over user limit");
         nonce->flags.valid = false;
         return -1;
     }
 
     /* seems ok */
     return 0;
 }
 
 /**
  * \retval  0    the digest is not stale yet
  * \retval -1    the digest will be stale on the next request
  */
 int
 authDigestNonceLastRequest(digest_nonce_h * nonce)
 {
     if (!nonce)
         return -1;
 
     if (nonce->nc == 99999997) {
         debugs(29, 4, "Nonce count about to overflow");
         return -1;
     }
 
-    if (nonce->nc >= static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxuses - 1) {
+    if (nonce->nc >= static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxuses - 1) {
         debugs(29, 4, "Nonce count about to hit user limit");
         return -1;
     }
 
     /* and other tests are possible. */
     return 0;
 }
 
 void
 authDigestNoncePurge(digest_nonce_h * nonce)
 {
     if (!nonce)
         return;
 
     if (!nonce->flags.incache)
         return;
 
     hash_remove_link(digest_nonce_cache, nonce);
 
     nonce->flags.incache = false;
 
     /* the cache's link */
     authDigestNonceUnlink(nonce);
 }
 
 void
 Auth::Digest::Config::rotateHelpers()
 {
     /* schedule closure of existing helpers */
     if (digestauthenticators) {
         helperShutdown(digestauthenticators);
     }
 
     /* NP: dynamic helper restart will ensure they start up again as needed. */
 }
 
 bool
-Auth::Digest::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
+Auth::Digest::Config::dump(StoreEntry * entry, const char *name, Auth::SchemeConfig * scheme) const
 {
-    if (!Auth::Config::dump(entry, name, scheme))
+    if (!Auth::SchemeConfig::dump(entry, name, scheme))
         return false;
 
     storeAppendPrintf(entry, "%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n",
                       name, "digest", noncemaxuses,
                       name, "digest", (int) noncemaxduration,
                       name, "digest", (int) nonceGCInterval);
-    storeAppendPrintf(entry, "%s digest utf8 %s\n", name, utf8 ? "on" : "off");
     return true;
 }
 
 bool
 Auth::Digest::Config::active() const
 {
     return authdigest_initialised == 1;
 }
 
 bool
 Auth::Digest::Config::configured() const
 {
     if ((authenticateProgram != NULL) &&
             (authenticateChildren.n_max != 0) &&
             !realm.isEmpty() && (noncemaxduration > -1))
         return true;
 
     return false;
 }
 
@@ -529,124 +528,114 @@
             }
         }
     }
     if (!nonce) {
         nonce = authenticateDigestNonceNew();
     }
 
     debugs(29, 9, "Sending type:" << hdrType <<
            " header: 'Digest realm=\"" << realm << "\", nonce=\"" <<
            authenticateDigestNonceNonceb64(nonce) << "\", qop=\"" << QOP_AUTH <<
            "\", stale=" << (stale ? "true" : "false"));
 
     /* in the future, for WWW auth we may want to support the domain entry */
     httpHeaderPutStrf(&rep->header, hdrType, "Digest realm=\"" SQUIDSBUFPH "\", nonce=\"%s\", qop=\"%s\", stale=%s",
                       SQUIDSBUFPRINT(realm), authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false");
 }
 
 /* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
  * config file */
 void
-Auth::Digest::Config::init(Auth::Config *)
+Auth::Digest::Config::init(Auth::SchemeConfig *)
 {
     if (authenticateProgram) {
         authenticateDigestNonceSetup();
         authdigest_initialised = 1;
 
         if (digestauthenticators == NULL)
             digestauthenticators = new helper("digestauthenticator");
 
         digestauthenticators->cmdline = authenticateProgram;
 
         digestauthenticators->childs.updateLimits(authenticateChildren);
 
         digestauthenticators->ipc_type = IPC_STREAM;
 
         helperOpenServers(digestauthenticators);
     }
 }
 
 void
 Auth::Digest::Config::registerWithCacheManager(void)
 {
     Mgr::RegisterAction("digestauthenticator",
                         "Digest User Authenticator Stats",
                         authenticateDigestStats, 0, 1);
 }
 
 /* free any allocated configuration details */
 void
 Auth::Digest::Config::done()
 {
-    Auth::Config::done();
+    Auth::SchemeConfig::done();
 
     authdigest_initialised = 0;
 
     if (digestauthenticators)
         helperShutdown(digestauthenticators);
 
     if (!shutting_down)
         return;
 
     delete digestauthenticators;
     digestauthenticators = NULL;
 
     if (authenticateProgram)
         wordlistDestroy(&authenticateProgram);
 }
 
 Auth::Digest::Config::Config() :
     nonceGCInterval(5*60),
     noncemaxduration(30*60),
     noncemaxuses(50),
     NonceStrictness(0),
     CheckNonceCount(1),
-    PostWorkaround(0),
-    utf8(0)
+    PostWorkaround(0)
 {}
 
 void
-Auth::Digest::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
+Auth::Digest::Config::parse(Auth::SchemeConfig * scheme, int n_configured, char *param_str)
 {
-    if (strcmp(param_str, "program") == 0) {
-        if (authenticateProgram)
-            wordlistDestroy(&authenticateProgram);
-
-        parse_wordlist(&authenticateProgram);
-
-        requirePathnameExists("auth_param digest program", authenticateProgram->key);
-    } else if (strcmp(param_str, "nonce_garbage_interval") == 0) {
+    if (strcmp(param_str, "nonce_garbage_interval") == 0) {
         parse_time_t(&nonceGCInterval);
     } else if (strcmp(param_str, "nonce_max_duration") == 0) {
         parse_time_t(&noncemaxduration);
     } else if (strcmp(param_str, "nonce_max_count") == 0) {
         parse_int((int *) &noncemaxuses);
     } else if (strcmp(param_str, "nonce_strictness") == 0) {
         parse_onoff(&NonceStrictness);
     } else if (strcmp(param_str, "check_nonce_count") == 0) {
         parse_onoff(&CheckNonceCount);
     } else if (strcmp(param_str, "post_workaround") == 0) {
         parse_onoff(&PostWorkaround);
-    } else if (strcmp(param_str, "utf8") == 0) {
-        parse_onoff(&utf8);
     } else
-        Auth::Config::parse(scheme, n_configured, param_str);
+        Auth::SchemeConfig::parse(scheme, n_configured, param_str);
 }
 
 const char *
 Auth::Digest::Config::type() const
 {
     return Auth::Digest::Scheme::GetInstance()->type();
 }
 
 static void
 authenticateDigestStats(StoreEntry * sentry)
 {
     if (digestauthenticators)
         digestauthenticators->packStatsInto(sentry, "Digest Authenticator Statistics");
 }
 
 /* NonceUserUnlink: remove the reference to auth_user and unlink the node from the list */
 
 static void
 authDigestNonceUserUnlink(digest_nonce_h * nonce)
 {
@@ -709,41 +698,41 @@
 
     authDigestNonceLink(nonce);
 
     /* ping this nonce to this auth user */
     assert((nonce->user == NULL) || (nonce->user == user));
 
     /* we don't lock this reference because removing the user removes the
      * hash too. Of course if that changes we're stuffed so read the code huh?
      */
     nonce->user = user;
 }
 
 /* setup the necessary info to log the username */
 static Auth::UserRequest::Pointer
 authDigestLogUsername(char *username, Auth::UserRequest::Pointer auth_user_request, const char *requestRealm)
 {
     assert(auth_user_request != NULL);
 
     /* log the username */
     debugs(29, 9, "Creating new user for logging '" << (username?username:"[no username]") << "'");
-    Auth::User::Pointer digest_user = new Auth::Digest::User(static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest")), requestRealm);
+    Auth::User::Pointer digest_user = new Auth::Digest::User(static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest")), requestRealm);
     /* save the credentials */
     digest_user->username(username);
     /* set the auth_user type */
     digest_user->auth_type = Auth::AUTH_BROKEN;
     /* link the request to the user */
     auth_user_request->user(digest_user);
     return auth_user_request;
 }
 
 /*
  * Decode a Digest [Proxy-]Auth string, placing the results in the passed
  * Auth_user structure.
  */
 Auth::UserRequest::Pointer
 Auth::Digest::Config::decode(char const *proxy_auth, const char *aRequestRealm)
 {
     const char *item;
     const char *p;
     const char *pos = NULL;
     char *username = NULL;

=== modified file 'src/auth/digest/Config.h'
--- src/auth/digest/Config.h	2016-01-01 00:12:18 +0000
+++ src/auth/digest/Config.h	2016-12-20 12:14:14 +0000
@@ -1,35 +1,35 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef __AUTH_DIGEST_H__
 #define __AUTH_DIGEST_H__
 
 #if HAVE_AUTH_MODULE_DIGEST
 
-#include "auth/Config.h"
 #include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
 #include "auth/UserRequest.h"
 #include "helper/forward.h"
 #include "rfc2617.h"
 
 namespace Auth
 {
 namespace Digest
 {
 class User;
 }
 }
 
 /* Generic */
 typedef struct _digest_nonce_data digest_nonce_data;
 typedef struct _digest_nonce_h digest_nonce_h;
 
 /* data to be encoded into the nonce's b64 representation */
 struct _digest_nonce_data {
     time_t creationtime;
     /* in memory address of the nonce struct (similar purpose to an ETag) */
@@ -54,57 +54,56 @@
         bool incache;
     } flags;
 };
 
 void authDigestNonceUnlink(digest_nonce_h * nonce);
 int authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]);
 int authDigestNonceIsStale(digest_nonce_h * nonce);
 const char *authenticateDigestNonceNonceb64(const digest_nonce_h * nonce);
 int authDigestNonceLastRequest(digest_nonce_h * nonce);
 void authenticateDigestNonceShutdown(void);
 void authDigestNoncePurge(digest_nonce_h * nonce);
 void authDigestUserLinkNonce(Auth::Digest::User * user, digest_nonce_h * nonce);
 digest_nonce_h *authenticateDigestNonceNew(void);
 
 namespace Auth
 {
 namespace Digest
 {
 
 /** Digest Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
 {
 public:
     Config();
     virtual bool active() const;
     virtual bool configured() const;
     virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
     virtual void done();
     virtual void rotateHelpers();
-    virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
+    virtual bool dump(StoreEntry *, const char *, Auth::SchemeConfig *) const;
     virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
-    virtual void init(Auth::Config *);
-    virtual void parse(Auth::Config *, int, char *);
+    virtual void init(Auth::SchemeConfig *);
+    virtual void parse(Auth::SchemeConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
 
 public:
     time_t nonceGCInterval;
     time_t noncemaxduration;
     unsigned int noncemaxuses;
     int NonceStrictness;
     int CheckNonceCount;
     int PostWorkaround;
-    int utf8;
 };
 
 } // namespace Digest
 } // namespace Auth
 
 /* strings */
 #define QOP_AUTH "auth"
 
 extern helper *digestauthenticators;
 
 #endif /* HAVE_AUTH_MODULE_DIGEST */
 #endif
 

=== modified file 'src/auth/digest/Scheme.cc'
--- src/auth/digest/Scheme.cc	2016-01-01 00:12:18 +0000
+++ src/auth/digest/Scheme.cc	2016-12-19 13:27:31 +0000
@@ -26,27 +26,27 @@
 }
 
 char const *
 Auth::Digest::Scheme::type() const
 {
     return "digest";
 }
 
 void
 Auth::Digest::Scheme::shutdownCleanup()
 {
     if (_instance == NULL)
         return;
 
     authenticateDigestNonceShutdown();
 
     _instance = NULL;
     debugs(29, DBG_CRITICAL, "Shutdown: Digest authentication.");
 }
 
-Auth::Config *
+Auth::SchemeConfig *
 Auth::Digest::Scheme::createConfig()
 {
     Auth::Digest::Config *digestCfg = new Auth::Digest::Config;
-    return dynamic_cast<Auth::Config*>(digestCfg);
+    return dynamic_cast<Auth::SchemeConfig*>(digestCfg);
 }
 

=== modified file 'src/auth/digest/Scheme.h'
--- src/auth/digest/Scheme.h	2016-01-01 00:12:18 +0000
+++ src/auth/digest/Scheme.h	2016-12-19 13:27:32 +0000
@@ -1,50 +1,49 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_DIGEST_SCHEME_H
 #define SQUID_AUTH_DIGEST_SCHEME_H
 
 #if HAVE_AUTH_MODULE_DIGEST
 
 #include "auth/Scheme.h"
 
 namespace Auth
 {
 namespace Digest
 {
 
-/// \ingroup AuthSchemeAPI
 /// \ingroup AuthAPI
 class Scheme : public Auth::Scheme
 {
 
 public:
     static Auth::Scheme::Pointer GetInstance();
     Scheme() {};
     virtual ~Scheme() {}
 
     /* per scheme */
     virtual char const *type () const;
     virtual void shutdownCleanup();
-    virtual Auth::Config *createConfig();
+    virtual Auth::SchemeConfig *createConfig();
 
     /* Not implemented */
     Scheme(Scheme const &);
     Scheme &operator=(Scheme const &);
 
 private:
     static Auth::Scheme::Pointer _instance;
 
 };
 
 } // namespace Digest
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_DIGEST */
 #endif /* SQUID_AUTH_DIGEST_SCHEME_H */
 

=== modified file 'src/auth/digest/User.cc'
--- src/auth/digest/User.cc	2016-01-01 00:12:18 +0000
+++ src/auth/digest/User.cc	2016-12-19 14:50:30 +0000
@@ -1,78 +1,77 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
+#include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "auth/digest/Config.h"
 #include "auth/digest/User.h"
 #include "Debug.h"
 #include "dlink.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
 
-Auth::Digest::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Digest::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
     Auth::User(aConfig, aRequestRealm),
     HA1created(0)
 {
     memset(HA1, 0, sizeof(HA1));
 }
 
 Auth::Digest::User::~User()
 {
     dlink_node *link, *tmplink;
     link = nonces.head;
 
     while (link) {
         tmplink = link;
         link = link->next;
         dlinkDelete(tmplink, &nonces);
         authDigestNoncePurge(static_cast < digest_nonce_h * >(tmplink->data));
         authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data));
         delete tmplink;
     }
 }
 
 int32_t
 Auth::Digest::User::ttl() const
 {
-    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + ::Config.authenticateTTL);
+    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Auth::TheConfig.authenticateTTL);
 
     /* find the longest lasting nonce. */
     int32_t latest_nonce = -1;
     dlink_node *link = nonces.head;
     while (link) {
         digest_nonce_h *nonce = static_cast<digest_nonce_h *>(link->data);
         if (nonce->flags.valid && nonce->noncedata.creationtime > latest_nonce)
             latest_nonce = nonce->noncedata.creationtime;
 
         link = link->next;
     }
     if (latest_nonce == -1)
         return min(-1, global_ttl);
 
-    int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<Config*>(Auth::Config::Find("digest"))->noncemaxduration;
+    int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration;
 
     return min(nonce_ttl, global_ttl);
 }
 
 digest_nonce_h *
 Auth::Digest::User::currentNonce()
 {
     digest_nonce_h *nonce = NULL;
     dlink_node *link = nonces.tail;
     if (link) {
         nonce = static_cast<digest_nonce_h *>(link->data);
         if (authDigestNonceIsStale(nonce))
             nonce = NULL;
     }
     return nonce;
 }
 
 CbcPointer<Auth::CredentialsCache>
 Auth::Digest::User::Cache()
 {

=== modified file 'src/auth/digest/User.h'
--- src/auth/digest/User.h	2016-01-01 00:12:18 +0000
+++ src/auth/digest/User.h	2016-12-19 13:27:34 +0000
@@ -9,41 +9,41 @@
 #ifndef _SQUID_AUTH_DIGEST_USER_H
 #define _SQUID_AUTH_DIGEST_USER_H
 
 #if HAVE_AUTH_MODULE_DIGEST
 
 #include "auth/digest/Config.h"
 #include "auth/User.h"
 #include "rfc2617.h"
 
 namespace Auth
 {
 namespace Digest
 {
 
 /** User credentials for the Digest authentication protocol */
 class User : public Auth::User
 {
     MEMPROXY_CLASS(Auth::Digest::User);
 
 public:
-    User(Auth::Config *, const char *requestRealm);
+    User(Auth::SchemeConfig *, const char *requestRealm);
     virtual ~User();
     int authenticated() const;
     virtual int32_t ttl() const override;
 
     /* Auth::User API */
     static CbcPointer<Auth::CredentialsCache> Cache();
     virtual void addToNameCache() override;
 
     HASH HA1;
     int HA1created;
 
     /* what nonces have been allocated to this user */
     dlink_list nonces;
 
     digest_nonce_h * currentNonce();
 };
 
 } // namespace Digest
 } // namespace Auth
 

=== modified file 'src/auth/digest/UserRequest.cc'
--- src/auth/digest/UserRequest.cc	2016-11-27 13:57:50 +0000
+++ src/auth/digest/UserRequest.cc	2016-12-19 13:27:35 +0000
@@ -110,41 +110,41 @@
 
     DigestCalcHA1(digest_request->algorithm, NULL, NULL, NULL,
                   authenticateDigestNonceNonceb64(digest_request->nonce),
                   digest_request->cnonce,
                   digest_user->HA1, SESSIONKEY);
     SBuf sTmp = request->method.image();
     DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
                        digest_request->nc, digest_request->cnonce, digest_request->qop,
                        sTmp.c_str(), digest_request->uri, HA2, Response);
 
     debugs(29, 9, "\nResponse = '" << digest_request->response << "'\nsquid is = '" << Response << "'");
 
     if (strcasecmp(digest_request->response, Response) != 0) {
         if (!digest_request->flags.helper_queried) {
             /* Query the helper in case the password has changed */
             digest_request->flags.helper_queried = true;
             auth_user->credentials(Auth::Pending);
             return;
         }
 
-        if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->PostWorkaround && request->method != Http::METHOD_GET) {
+        if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->PostWorkaround && request->method != Http::METHOD_GET) {
             /* Ugly workaround for certain very broken browsers using the
              * wrong method to calculate the request-digest on POST request.
              * This should be deleted once Digest authentication becomes more
              * widespread and such broken browsers no longer are commonly
              * used.
              */
             sTmp = HttpRequestMethod(Http::METHOD_GET).image();
             DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
                                digest_request->nc, digest_request->cnonce, digest_request->qop,
                                sTmp.c_str(), digest_request->uri, HA2, Response);
 
             if (strcasecmp(digest_request->response, Response)) {
                 auth_user->credentials(Auth::Failed);
                 digest_request->flags.invalid_password = true;
                 digest_request->setDenyMessage("Incorrect password");
                 return;
             } else {
                 const char *useragent = request->header.getStr(Http::HdrType::USER_AGENT);
 
                 static Ip::Address last_broken_addr;
@@ -216,41 +216,41 @@
 }
 
 void
 Auth::Digest::UserRequest::addAuthenticationInfoHeader(HttpReply * rep, int accel)
 {
     Http::HdrType type;
 
     /* don't add to authentication error pages */
     if ((!accel && rep->sline.status() == Http::scProxyAuthenticationRequired)
             || (accel && rep->sline.status() == Http::scUnauthorized))
         return;
 
     type = accel ? Http::HdrType::AUTHENTICATION_INFO : Http::HdrType::PROXY_AUTHENTICATION_INFO;
 
 #if WAITING_FOR_TE
     /* test for http/1.1 transfer chunked encoding */
     if (chunkedtest)
         return;
 #endif
 
-    if ((static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->authenticateProgram) && authDigestNonceLastRequest(nonce)) {
+    if ((static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->authenticateProgram) && authDigestNonceLastRequest(nonce)) {
         flags.authinfo_sent = true;
         Auth::Digest::User *digest_user = dynamic_cast<Auth::Digest::User *>(user().getRaw());
         if (!digest_user)
             return;
 
         digest_nonce_h *nextnonce = digest_user->currentNonce();
         if (!nextnonce || authDigestNonceLastRequest(nonce)) {
             nextnonce = authenticateDigestNonceNew();
             authDigestUserLinkNonce(digest_user, nextnonce);
         }
         debugs(29, 9, "Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nextnonce) << "\"");
         httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nextnonce));
     }
 }
 
 #if WAITING_FOR_TE
 void
 Auth::Digest::UserRequest::addAuthenticationInfoTrailer(HttpReply * rep, int accel)
 {
     int type;
@@ -274,48 +274,48 @@
         nonce = digest_user->currentNonce();
         if (!nonce) {
             nonce = authenticateDigestNonceNew();
             authDigestUserLinkNonce(digest_user, nonce);
         }
         debugs(29, 9, "Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
         httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
     }
 }
 #endif
 
 /* send the initial data to a digest authenticator module */
 void
 Auth::Digest::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
 {
     char buf[8192];
 
     assert(user() != NULL && user()->auth_type == Auth::AUTH_DIGEST);
     debugs(29, 9, HERE << "'\"" << user()->username() << "\":\"" << realm << "\"'");
 
-    if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->authenticateProgram == NULL) {
+    if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->authenticateProgram == NULL) {
         debugs(29, DBG_CRITICAL, "ERROR: No Digest authentication program configured.");
         handler(data);
         return;
     }
 
     const char *keyExtras = helperRequestKeyExtras(request, al);
-    if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->utf8) {
+    if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->utf8) {
         char userstr[1024];
         latin1_to_utf8(userstr, sizeof(userstr), user()->username());
         if (keyExtras)
             snprintf(buf, 8192, "\"%s\":\"%s\" %s\n", userstr, realm, keyExtras);
         else
             snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
     } else {
         if (keyExtras)
             snprintf(buf, 8192, "\"%s\":\"%s\" %s\n", user()->username(), realm, keyExtras);
         else
             snprintf(buf, 8192, "\"%s\":\"%s\"\n", user()->username(), realm);
     }
 
     helperSubmit(digestauthenticators, buf, Auth::Digest::UserRequest::HandleReply,
                  new Auth::StateData(this, handler, data));
 }
 
 void
 Auth::Digest::UserRequest::HandleReply(void *data, const Helper::Reply &reply)
 {

=== added file 'src/auth/forward.h'
--- src/auth/forward.h	1970-01-01 00:00:00 +0000
+++ src/auth/forward.h	2016-12-19 13:27:53 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_AUTH_FORWARD_H
+#define SQUID_SRC_AUTH_FORWARD_H
+
+#if USE_AUTH
+
+#include <vector>
+
+/// HTTP Authentication
+namespace Auth
+{
+
+class CredentialsCache;
+
+class Scheme;
+class SchemeConfig;
+typedef std::vector<Auth::SchemeConfig *> ConfigVector;
+
+} // namespace Auth
+
+#endif /* USE_AUTH */
+#endif /* SQUID_SRC_AUTH_FORWARD_H */
+

=== modified file 'src/auth/negotiate/Config.cc'
--- src/auth/negotiate/Config.cc	2016-01-24 17:41:43 +0000
+++ src/auth/negotiate/Config.cc	2016-12-20 11:17:35 +0000
@@ -14,132 +14,94 @@
 
 #include "squid.h"
 #include "auth/Gadgets.h"
 #include "auth/negotiate/Config.h"
 #include "auth/negotiate/Scheme.h"
 #include "auth/negotiate/User.h"
 #include "auth/negotiate/UserRequest.h"
 #include "auth/State.h"
 #include "cache_cf.h"
 #include "client_side.h"
 #include "helper.h"
 #include "http/Stream.h"
 #include "HttpHeaderTools.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
 #include "mgr/Registration.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "wordlist.h"
 
-/**
- \defgroup AuthNegotiateInternal Negotiate Authenticator Internals
- \ingroup AuthNegotiateAPI
- */
-
-/* Negotiate Scheme */
 static AUTHSSTATS authenticateNegotiateStats;
 
-/// \ingroup AuthNegotiateInternal
 statefulhelper *negotiateauthenticators = NULL;
 
-/// \ingroup AuthNegotiateInternal
 static int authnegotiate_initialised = 0;
 
-/// \ingroup AuthNegotiateInternal
 static hash_table *proxy_auth_cache = NULL;
 
 void
 Auth::Negotiate::Config::rotateHelpers()
 {
     /* schedule closure of existing helpers */
     if (negotiateauthenticators) {
         helperStatefulShutdown(negotiateauthenticators);
     }
 
     /* NP: dynamic helper restart will ensure they start up again as needed. */
 }
 
 void
 Auth::Negotiate::Config::done()
 {
-    Auth::Config::done();
+    Auth::SchemeConfig::done();
 
     authnegotiate_initialised = 0;
 
     if (negotiateauthenticators) {
         helperStatefulShutdown(negotiateauthenticators);
     }
 
     if (!shutting_down)
         return;
 
     delete negotiateauthenticators;
     negotiateauthenticators = NULL;
 
     if (authenticateProgram)
         wordlistDestroy(&authenticateProgram);
 
     debugs(29, DBG_IMPORTANT, "Reconfigure: Negotiate authentication configuration cleared.");
 }
 
-bool
-Auth::Negotiate::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
-{
-    if (!Auth::Config::dump(entry, name, scheme))
-        return false;
-
-    storeAppendPrintf(entry, "%s negotiate keep_alive %s\n", name, keep_alive ? "on" : "off");
-    return true;
-}
-
-Auth::Negotiate::Config::Config() : keep_alive(1)
-{ }
-
-void
-Auth::Negotiate::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
-{
-    if (strcmp(param_str, "program") == 0) {
-        if (authenticateProgram)
-            wordlistDestroy(&authenticateProgram);
-
-        parse_wordlist(&authenticateProgram);
-
-        requirePathnameExists("auth_param negotiate program", authenticateProgram->key);
-    } else if (strcmp(param_str, "keep_alive") == 0) {
-        parse_onoff(&keep_alive);
-    } else
-        Auth::Config::parse(scheme, n_configured, param_str);
-}
-
 const char *
 Auth::Negotiate::Config::type() const
 {
     return Auth::Negotiate::Scheme::GetInstance()->type();
 }
 
 /**
  * Initialize helpers and the like for this auth scheme.
  * Called AFTER parsing the config file
  */
 void
-Auth::Negotiate::Config::init(Auth::Config *)
+Auth::Negotiate::Config::init(Auth::SchemeConfig *)
 {
     if (authenticateProgram) {
 
         authnegotiate_initialised = 1;
 
         if (negotiateauthenticators == NULL)
             negotiateauthenticators = new statefulhelper("negotiateauthenticator");
 
         if (!proxy_auth_cache)
             proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
 
         assert(proxy_auth_cache);
 
         negotiateauthenticators->cmdline = authenticateProgram;
 
         negotiateauthenticators->childs.updateLimits(authenticateChildren);
 
         negotiateauthenticators->ipc_type = IPC_STREAM;
 
         helperStatefulOpenServers(negotiateauthenticators);
@@ -155,42 +117,40 @@
 }
 
 bool
 Auth::Negotiate::Config::active() const
 {
     return authnegotiate_initialised == 1;
 }
 
 bool
 Auth::Negotiate::Config::configured() const
 {
     if (authenticateProgram && (authenticateChildren.n_max != 0)) {
         debugs(29, 9, HERE << "returning configured");
         return true;
     }
 
     debugs(29, 9, HERE << "returning unconfigured");
     return false;
 }
 
-/* Negotiate Scheme */
-
 void
 Auth::Negotiate::Config::fixHeader(Auth::UserRequest::Pointer auth_user_request, HttpReply *rep, Http::HdrType reqType, HttpRequest * request)
 {
     if (!authenticateProgram)
         return;
 
     /* Need keep-alive */
     if (!request->flags.proxyKeepalive && request->flags.mustKeepalive)
         return;
 
     /* New request, no user details */
     if (auth_user_request == NULL) {
         debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate'");
         httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
 
         if (!keep_alive) {
             /* drop the connection */
             rep->header.delByName("keep-alive");
             request->flags.proxyKeepalive = false;
         }
@@ -239,34 +199,34 @@
             debugs(29, DBG_CRITICAL, "ERROR: Negotiate auth fixHeader: state " << negotiate_request->user()->credentials() << ".");
             fatal("unexpected state in AuthenticateNegotiateFixErrorHeader.\n");
         }
     }
 }
 
 static void
 authenticateNegotiateStats(StoreEntry * sentry)
 {
     if (negotiateauthenticators)
         negotiateauthenticators->packStatsInto(sentry, "Negotiate Authenticator Statistics");
 }
 
 /*
  * Decode a Negotiate [Proxy-]Auth string, placing the results in the passed
  * Auth_user structure.
  */
 Auth::UserRequest::Pointer
 Auth::Negotiate::Config::decode(char const *proxy_auth, const char *aRequestRealm)
 {
-    Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::Config::Find("negotiate"), aRequestRealm);
+    Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::SchemeConfig::Find("negotiate"), aRequestRealm);
     Auth::UserRequest *auth_user_request = new Auth::Negotiate::UserRequest();
     assert(auth_user_request->user() == NULL);
 
     auth_user_request->user(newUser);
     auth_user_request->user()->auth_type = Auth::AUTH_NEGOTIATE;
 
     auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
 
     /* all we have to do is identify that it's Negotiate - the helper does the rest */
     debugs(29, 9, HERE << "decode Negotiate authentication");
     return auth_user_request;
 }
 

=== modified file 'src/auth/negotiate/Config.h'
--- src/auth/negotiate/Config.h	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Config.h	2016-12-20 11:16:46 +0000
@@ -1,52 +1,46 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef __AUTH_NEGOTIATE_H__
 #define __AUTH_NEGOTIATE_H__
 
 #if HAVE_AUTH_MODULE_NEGOTIATE
 
-#include "auth/Config.h"
 #include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
 #include "auth/UserRequest.h"
 #include "helper/forward.h"
 
 namespace Auth
 {
 namespace Negotiate
 {
 
 /** Negotiate Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
 {
 public:
-    Config();
     virtual bool active() const;
     virtual bool configured() const;
     virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
     virtual void done();
     virtual void rotateHelpers();
-    virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
     virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
-    virtual void init(Auth::Config *);
-    virtual void parse(Auth::Config *, int, char *);
+    virtual void init(Auth::SchemeConfig *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-
-public:
-    int keep_alive;
 };
 
 } // namespace Negotiate
 } // namespace Auth
 
 extern statefulhelper *negotiateauthenticators;
 
 #endif /* HAVE_AUTH_MODULE_NEGOTIATE */
 #endif
 

=== modified file 'src/auth/negotiate/Scheme.cc'
--- src/auth/negotiate/Scheme.cc	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Scheme.cc	2016-12-19 13:28:02 +0000
@@ -23,27 +23,27 @@
     }
     return _instance;
 }
 
 char const *
 Auth::Negotiate::Scheme::type() const
 {
     return "negotiate";
 }
 
 void
 Auth::Negotiate::Scheme::shutdownCleanup()
 {
     if (_instance == NULL)
         return;
 
     _instance = NULL;
     debugs(29, DBG_CRITICAL, "Shutdown: Negotiate authentication.");
 }
 
-Auth::Config *
+Auth::SchemeConfig *
 Auth::Negotiate::Scheme::createConfig()
 {
     Auth::Negotiate::Config *negotiateCfg = new Auth::Negotiate::Config;
-    return dynamic_cast<Auth::Config*>(negotiateCfg);
+    return dynamic_cast<Auth::SchemeConfig*>(negotiateCfg);
 }
 

=== modified file 'src/auth/negotiate/Scheme.h'
--- src/auth/negotiate/Scheme.h	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Scheme.h	2016-12-19 13:28:04 +0000
@@ -1,49 +1,48 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_NEGOTIATE_SCHEME_H
 #define SQUID_AUTH_NEGOTIATE_SCHEME_H
 
 #if HAVE_AUTH_MODULE_NEGOTIATE
 
 #include "auth/Scheme.h"
 
 namespace Auth
 {
 namespace Negotiate
 {
 
-/// \ingroup AuthSchemeAPI
 /// \ingroup AuthAPI
 class Scheme : public Auth::Scheme
 {
 
 public:
     static Auth::Scheme::Pointer GetInstance();
     Scheme() {};
     virtual ~Scheme() {};
 
     /* per scheme */
     virtual char const *type() const;
     virtual void shutdownCleanup();
-    virtual Auth::Config *createConfig();
+    virtual Auth::SchemeConfig *createConfig();
 
     /* Not implemented */
     Scheme (Scheme const &);
     Scheme &operator=(Scheme const &);
 
 private:
     static Auth::Scheme::Pointer _instance;
 };
 
 } // namespace Negotiate
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_NEGOTIATE */
 #endif /* SQUID_AUTH_NEGOTIATE_SCHEME_H */
 

=== modified file 'src/auth/negotiate/User.cc'
--- src/auth/negotiate/User.cc	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/User.cc	2016-12-19 13:28:05 +0000
@@ -1,35 +1,35 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
-#include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "auth/negotiate/User.h"
+#include "auth/SchemeConfig.h"
 #include "Debug.h"
 
-Auth::Negotiate::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Negotiate::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
     Auth::User(aConfig, aRequestRealm)
 {
 }
 
 Auth::Negotiate::User::~User()
 {
     debugs(29, 5, HERE << "doing nothing to clear Negotiate scheme data for '" << this << "'");
 }
 
 int32_t
 Auth::Negotiate::User::ttl() const
 {
     return -1; // Negotiate cannot be cached.
 }
 
 CbcPointer<Auth::CredentialsCache>
 Auth::Negotiate::User::Cache()
 {
     static CbcPointer<Auth::CredentialsCache> p(new Auth::CredentialsCache("negotiate", "GC Negotiate user credentials"));
     return p;

=== modified file 'src/auth/negotiate/User.h'
--- src/auth/negotiate/User.h	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/User.h	2016-12-19 13:28:06 +0000
@@ -1,46 +1,46 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef _SQUID_AUTH_NEGOTIATE_USER_H
 #define _SQUID_AUTH_NEGOTIATE_USER_H
 
 #if HAVE_AUTH_MODULE_NEGOTIATE
 
 #include "auth/User.h"
 
 namespace Auth
 {
 
-class Config;
+class SchemeConfig;
 
 namespace Negotiate
 {
 
 /** User credentials for the Negotiate authentication protocol */
 class User : public Auth::User
 {
     MEMPROXY_CLASS(Auth::Negotiate::User);
 
 public:
-    User(Auth::Config *, const char *requestRealm);
+    User(Auth::SchemeConfig *, const char *requestRealm);
     virtual ~User();
     virtual int32_t ttl() const override;
 
     /* Auth::User API */
     static CbcPointer<Auth::CredentialsCache> Cache();
     virtual void addToNameCache() override;
 
     dlink_list proxy_auth_list;
 };
 
 } // namespace Negotiate
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_NEGOTIATE */
 #endif /* _SQUID_AUTH_NEGOTIATE_USER_H */
 

=== modified file 'src/auth/negotiate/UserRequest.cc'
--- src/auth/negotiate/UserRequest.cc	2016-01-24 17:41:43 +0000
+++ src/auth/negotiate/UserRequest.cc	2016-12-19 13:28:07 +0000
@@ -111,41 +111,41 @@
     case Auth::Failed:
         return Auth::CRED_ERROR; // XXX: really? not VALID or CHALLENGE?
 
     default:
         debugs(29, DBG_IMPORTANT, "WARNING: Negotiate Authentication in unexpected state: " << user()->credentials());
         return Auth::CRED_ERROR;
     }
 }
 
 void
 Auth::Negotiate::UserRequest::startHelperLookup(HttpRequest *, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
 {
     static char buf[MAX_AUTHTOKEN_LEN];
 
     assert(data);
     assert(handler);
 
     assert(user() != NULL);
     assert(user()->auth_type == Auth::AUTH_NEGOTIATE);
 
-    if (static_cast<Auth::Negotiate::Config*>(Auth::Config::Find("negotiate"))->authenticateProgram == NULL) {
+    if (static_cast<Auth::Negotiate::Config*>(Auth::SchemeConfig::Find("negotiate"))->authenticateProgram == NULL) {
         debugs(29, DBG_CRITICAL, "ERROR: No Negotiate authentication program configured.");
         handler(data);
         return;
     }
 
     debugs(29, 8, HERE << "credentials state is '" << user()->credentials() << "'");
 
     const char *keyExtras = helperRequestKeyExtras(request, al);
     int printResult = 0;
     if (user()->credentials() == Auth::Pending) {
         if (keyExtras)
             printResult = snprintf(buf, sizeof(buf), "YR %s %s\n", client_blob, keyExtras);
         else
             printResult = snprintf(buf, sizeof(buf), "YR %s\n", client_blob); //CHECKME: can ever client_blob be 0 here?
     } else {
         if (keyExtras)
             printResult = snprintf(buf, sizeof(buf), "KK %s %s\n", client_blob, keyExtras);
         else
             printResult = snprintf(buf, sizeof(buf), "KK %s\n", client_blob);
     }

=== modified file 'src/auth/negotiate/UserRequest.h'
--- src/auth/negotiate/UserRequest.h	2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/UserRequest.h	2016-12-19 13:28:08 +0000
@@ -6,41 +6,40 @@
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef _SQUID_SRC_AUTH_NEGOTIATE_USERREQUEST_H
 #define _SQUID_SRC_AUTH_NEGOTIATE_USERREQUEST_H
 
 #if HAVE_AUTH_MODULE_NEGOTIATE
 
 #include "auth/UserRequest.h"
 #include "helper/forward.h"
 
 class ConnStateData;
 class HttpReply;
 class HttpRequest;
 
 namespace Auth
 {
 namespace Negotiate
 {
 
-/// \ingroup AuthNegotiateAPI
 class UserRequest : public Auth::UserRequest
 {
     MEMPROXY_CLASS(Auth::Negotiate::UserRequest);
 
 public:
     UserRequest();
     virtual ~UserRequest();
     virtual int authenticated() const;
     virtual void authenticate(HttpRequest * request, ConnStateData * conn, Http::HdrType type);
     virtual Direction module_direction();
     virtual void startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB *, void *);
     virtual const char *credentialsStr();
 
     virtual const char * connLastHeader();
 
     /* we need to store the helper server between requests */
     helper_stateful_server *authserver;
     void releaseAuthServer(void); ///< Release the authserver helper server properly.
 
     /* what connection is this associated with */

=== modified file 'src/auth/ntlm/Config.cc'
--- src/auth/ntlm/Config.cc	2016-01-24 17:41:43 +0000
+++ src/auth/ntlm/Config.cc	2016-12-20 11:18:30 +0000
@@ -37,99 +37,70 @@
 statefulhelper *ntlmauthenticators = NULL;
 static int authntlm_initialised = 0;
 
 static hash_table *proxy_auth_cache = NULL;
 
 void
 Auth::Ntlm::Config::rotateHelpers()
 {
     /* schedule closure of existing helpers */
     if (ntlmauthenticators) {
         helperStatefulShutdown(ntlmauthenticators);
     }
 
     /* NP: dynamic helper restart will ensure they start up again as needed. */
 }
 
 /* free any allocated configuration details */
 void
 Auth::Ntlm::Config::done()
 {
-    Auth::Config::done();
+    Auth::SchemeConfig::done();
 
     authntlm_initialised = 0;
 
     if (ntlmauthenticators) {
         helperStatefulShutdown(ntlmauthenticators);
     }
 
     if (!shutting_down)
         return;
 
     delete ntlmauthenticators;
     ntlmauthenticators = NULL;
 
     if (authenticateProgram)
         wordlistDestroy(&authenticateProgram);
 
     debugs(29, DBG_IMPORTANT, "Reconfigure: NTLM authentication configuration cleared.");
 }
 
-bool
-Auth::Ntlm::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
-{
-    if (!Auth::Config::dump(entry, name, scheme))
-        return false;
-
-    storeAppendPrintf(entry, "%s ntlm keep_alive %s\n", name, keep_alive ? "on" : "off");
-    return true;
-}
-
-Auth::Ntlm::Config::Config() : keep_alive(1)
-{ }
-
-void
-Auth::Ntlm::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
-{
-    if (strcmp(param_str, "program") == 0) {
-        if (authenticateProgram)
-            wordlistDestroy(&authenticateProgram);
-
-        parse_wordlist(&authenticateProgram);
-
-        requirePathnameExists("auth_param ntlm program", authenticateProgram->key);
-    } else if (strcmp(param_str, "keep_alive") == 0) {
-        parse_onoff(&keep_alive);
-    } else
-        Auth::Config::parse(scheme, n_configured, param_str);
-}
-
 const char *
 Auth::Ntlm::Config::type() const
 {
     return Auth::Ntlm::Scheme::GetInstance()->type();
 }
 
 /* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
  * config file */
 void
-Auth::Ntlm::Config::init(Auth::Config *)
+Auth::Ntlm::Config::init(Auth::SchemeConfig *)
 {
     if (authenticateProgram) {
 
         authntlm_initialised = 1;
 
         if (ntlmauthenticators == NULL)
             ntlmauthenticators = new statefulhelper("ntlmauthenticator");
 
         if (!proxy_auth_cache)
             proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
 
         assert(proxy_auth_cache);
 
         ntlmauthenticators->cmdline = authenticateProgram;
 
         ntlmauthenticators->childs.updateLimits(authenticateChildren);
 
         ntlmauthenticators->ipc_type = IPC_STREAM;
 
         helperStatefulOpenServers(ntlmauthenticators);
@@ -219,34 +190,34 @@
             debugs(29, DBG_CRITICAL, "NTLM Auth fixHeader: state " << ntlm_request->user()->credentials() << ".");
             fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n");
         }
     }
 }
 
 static void
 authenticateNTLMStats(StoreEntry * sentry)
 {
     if (ntlmauthenticators)
         ntlmauthenticators->packStatsInto(sentry, "NTLM Authenticator Statistics");
 }
 
 /*
  * Decode a NTLM [Proxy-]Auth string, placing the results in the passed
  * Auth_user structure.
  */
 Auth::UserRequest::Pointer
 Auth::Ntlm::Config::decode(char const *proxy_auth, const char *aRequestRealm)
 {
-    Auth::Ntlm::User *newUser = new Auth::Ntlm::User(Auth::Config::Find("ntlm"), aRequestRealm);
+    Auth::Ntlm::User *newUser = new Auth::Ntlm::User(Auth::SchemeConfig::Find("ntlm"), aRequestRealm);
     Auth::UserRequest::Pointer auth_user_request = new Auth::Ntlm::UserRequest();
     assert(auth_user_request->user() == NULL);
 
     auth_user_request->user(newUser);
     auth_user_request->user()->auth_type = Auth::AUTH_NTLM;
 
     auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
 
     /* all we have to do is identify that it's NTLM - the helper does the rest */
     debugs(29, 9, HERE << "decode: NTLM authentication");
     return auth_user_request;
 }
 

=== modified file 'src/auth/ntlm/Config.h'
--- src/auth/ntlm/Config.h	2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Config.h	2016-12-20 11:17:01 +0000
@@ -1,55 +1,49 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef __AUTH_NTLM_H__
 #define __AUTH_NTLM_H__
 
 #if HAVE_AUTH_MODULE_NTLM
 
-#include "auth/Config.h"
 #include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
 #include "auth/UserRequest.h"
 #include "helper/forward.h"
 
 class HttpRequest;
 class StoreEntry;
 
 namespace Auth
 {
 namespace Ntlm
 {
 
 /** NTLM Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
 {
 public:
-    Config();
     virtual bool active() const;
     virtual bool configured() const;
     virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
     virtual void done();
     virtual void rotateHelpers();
-    virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
     virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
-    virtual void init(Auth::Config *);
-    virtual void parse(Auth::Config *, int, char *);
+    virtual void init(Auth::SchemeConfig *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
-
-public:
-    int keep_alive;
 };
 
 } // namespace Ntlm
 } // namespace Auth
 
 extern statefulhelper *ntlmauthenticators;
 
 #endif /* HAVE_AUTH_MODULE_NTLM */
 #endif
 

=== modified file 'src/auth/ntlm/Scheme.cc'
--- src/auth/ntlm/Scheme.cc	2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Scheme.cc	2016-12-19 13:28:29 +0000
@@ -23,27 +23,27 @@
     }
     return _instance;
 }
 
 char const *
 Auth::Ntlm::Scheme::type() const
 {
     return "ntlm";
 }
 
 void
 Auth::Ntlm::Scheme::shutdownCleanup()
 {
     if (_instance == NULL)
         return;
 
     _instance = NULL;
     debugs(29, DBG_CRITICAL, "Shutdown: NTLM authentication.");
 }
 
-Auth::Config *
+Auth::SchemeConfig *
 Auth::Ntlm::Scheme::createConfig()
 {
     Auth::Ntlm::Config *ntlmCfg = new Auth::Ntlm::Config;
-    return dynamic_cast<Auth::Config*>(ntlmCfg);
+    return dynamic_cast<Auth::SchemeConfig*>(ntlmCfg);
 }
 

=== modified file 'src/auth/ntlm/Scheme.h'
--- src/auth/ntlm/Scheme.h	2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Scheme.h	2016-12-19 13:28:30 +0000
@@ -1,53 +1,52 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_AUTH_NTLM_SCHEME_H
 #define SQUID_AUTH_NTLM_SCHEME_H
 
 #if HAVE_AUTH_MODULE_NTLM
 
 #include "auth/Scheme.h"
 
 namespace Auth
 {
 namespace Ntlm
 {
 
-/// \ingroup AuthSchemeAPI
 /// \ingroup AuthAPI
 class Scheme : public Auth::Scheme
 {
 
 public:
     static Auth::Scheme::Pointer GetInstance();
     Scheme() {};
     virtual ~Scheme() {};
 
     /* per scheme */
     virtual char const *type() const;
     virtual void shutdownCleanup();
-    virtual Auth::Config *createConfig();
+    virtual Auth::SchemeConfig *createConfig();
 
     /* Not implemented */
     Scheme (Scheme const &);
     Scheme &operator=(Scheme const &);
 
 private:
     /**
      * Main instance of this authentication Scheme.
      * NULL when the scheme is not being used.
      */
     static Auth::Scheme::Pointer _instance;
 };
 
 } // namespace Ntlm
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_NTLM */
 #endif /* SQUID_AUTH_NTLM_SCHEME_H */
 

=== modified file 'src/auth/ntlm/User.cc'
--- src/auth/ntlm/User.cc	2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/User.cc	2016-12-19 13:28:31 +0000
@@ -1,35 +1,35 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
-#include "auth/Config.h"
 #include "auth/CredentialsCache.h"
 #include "auth/ntlm/User.h"
+#include "auth/SchemeConfig.h"
 #include "Debug.h"
 
-Auth::Ntlm::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Ntlm::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
     Auth::User(aConfig, aRequestRealm)
 {
 }
 
 Auth::Ntlm::User::~User()
 {
     debugs(29, 5, HERE << "doing nothing to clear NTLM scheme data for '" << this << "'");
 }
 
 int32_t
 Auth::Ntlm::User::ttl() const
 {
     return -1; // NTLM credentials cannot be cached.
 }
 
 CbcPointer<Auth::CredentialsCache>
 Auth::Ntlm::User::Cache()
 {
     static CbcPointer<Auth::CredentialsCache> p(new Auth::CredentialsCache("ntlm", "GC NTLM user credentials"));
     return p;

=== modified file 'src/auth/ntlm/User.h'
--- src/auth/ntlm/User.h	2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/User.h	2016-12-19 13:28:32 +0000
@@ -1,46 +1,44 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef _SQUID_AUTH_NTLM_USER_H
 #define _SQUID_AUTH_NTLM_USER_H
 
 #if HAVE_AUTH_MODULE_NTLM
 
 #include "auth/User.h"
 
 namespace Auth
 {
 
-class Config;
-
 namespace Ntlm
 {
 
 /** User credentials for the NTLM authentication protocol */
 class User : public Auth::User
 {
     MEMPROXY_CLASS(Auth::Ntlm::User);
 
 public:
-    User(Auth::Config *, const char *requestRealm);
+    User(Auth::SchemeConfig *, const char *requestRealm);
     virtual ~User();
     virtual int32_t ttl() const override;
 
     /* Auth::User API */
     static CbcPointer<Auth::CredentialsCache> Cache();
     virtual void addToNameCache() override;
 
     dlink_list proxy_auth_list;
 };
 
 } // namespace Ntlm
 } // namespace Auth
 
 #endif /* HAVE_AUTH_MODULE_NTLM */
 #endif /* _SQUID_AUTH_NTLM_USER_H */
 

=== modified file 'src/auth/ntlm/UserRequest.cc'
--- src/auth/ntlm/UserRequest.cc	2016-01-24 17:41:43 +0000
+++ src/auth/ntlm/UserRequest.cc	2016-12-19 13:28:33 +0000
@@ -107,41 +107,41 @@
     case Auth::Ok:
         return Auth::CRED_VALID;
 
     case Auth::Failed:
         return Auth::CRED_ERROR; // XXX: really? not VALID or CHALLENGE?
 
     default:
         debugs(29, DBG_IMPORTANT, "WARNING: NTLM Authentication in unexpected state: " << user()->credentials());
         return Auth::CRED_ERROR;
     }
 }
 
 void
 Auth::Ntlm::UserRequest::startHelperLookup(HttpRequest *, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
 {
     static char buf[MAX_AUTHTOKEN_LEN];
 
     assert(data);
     assert(handler);
 
-    if (static_cast<Auth::Ntlm::Config*>(Auth::Config::Find("ntlm"))->authenticateProgram == NULL) {
+    if (static_cast<Auth::Ntlm::Config*>(Auth::SchemeConfig::Find("ntlm"))->authenticateProgram == NULL) {
         debugs(29, DBG_CRITICAL, "ERROR: NTLM Start: no NTLM program configured.");
         handler(data);
         return;
     }
 
     debugs(29, 8, HERE << "credentials state is '" << user()->credentials() << "'");
 
     const char *keyExtras = helperRequestKeyExtras(request, al);
     int printResult = 0;
     if (user()->credentials() == Auth::Pending) {
         if (keyExtras)
             printResult = snprintf(buf, sizeof(buf), "YR %s %s\n", client_blob, keyExtras);
         else
             printResult = snprintf(buf, sizeof(buf), "YR %s\n", client_blob); //CHECKME: can ever client_blob be 0 here?
     } else {
         if (keyExtras)
             printResult = snprintf(buf, sizeof(buf), "KK %s %s\n", client_blob, keyExtras);
         else
             printResult = snprintf(buf, sizeof(buf), "KK %s\n", client_blob);
     }

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2016-12-10 16:27:09 +0000
+++ src/cache_cf.cc	2016-12-19 13:29:15 +0000
@@ -1,40 +1,42 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 03    Configuration File Parsing */
 
 #include "squid.h"
 #include "acl/Acl.h"
 #include "acl/AclDenyInfoList.h"
 #include "acl/AclSizeLimit.h"
 #include "acl/Address.h"
 #include "acl/Gadgets.h"
 #include "acl/MethodData.h"
 #include "acl/Tree.h"
 #include "anyp/PortCfg.h"
 #include "anyp/UriScheme.h"
+#include "auth/Config.h"
+#include "auth/Scheme.h"
 #include "AuthReg.h"
 #include "base/RunnersRegistry.h"
 #include "cache_cf.h"
 #include "CachePeer.h"
 #include "ConfigParser.h"
 #include "CpuAffinityMap.h"
 #include "DiskIO/DiskIOModule.h"
 #include "eui/Config.h"
 #include "ExternalACL.h"
 #include "format/Format.h"
 #include "ftp/Elements.h"
 #include "globals.h"
 #include "HttpHeaderTools.h"
 #include "icmp/IcmpConfig.h"
 #include "ident/Config.h"
 #include "ip/Intercept.h"
 #include "ip/QosConfig.h"
 #include "ip/tools.h"
 #include "ipc/Kids.h"
 #include "log/Config.h"
@@ -60,45 +62,40 @@
 #include "store/Disks.h"
 #include "StoreFileSystem.h"
 #include "tools.h"
 #include "util.h"
 #include "wordlist.h"
 /* wccp2 has its own conditional definitions */
 #include "wccp2.h"
 #if USE_ADAPTATION
 #include "adaptation/Config.h"
 #endif
 #if ICAP_CLIENT
 #include "adaptation/icap/Config.h"
 #endif
 #if USE_ECAP
 #include "adaptation/ecap/Config.h"
 #endif
 #if USE_OPENSSL
 #include "ssl/Config.h"
 #include "ssl/support.h"
 #endif
-#if USE_AUTH
-#include "auth/Config.h"
-#include "auth/Scheme.h"
-#include "auth/SchemesConfig.h"
-#endif
 #if USE_SQUID_ESI
 #include "esi/Parser.h"
 #endif
 #if SQUID_SNMP
 #include "snmp.h"
 #endif
 
 #if HAVE_GLOB_H
 #include <glob.h>
 #endif
 #include <limits>
 #include <list>
 #if HAVE_PWD_H
 #include <pwd.h>
 #endif
 #if HAVE_GRP_H
 #include <grp.h>
 #endif
 #if HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -921,49 +918,49 @@
 
     /*
      * Disable client side request pipelining if client_persistent_connections OFF.
      * Waste of resources queueing any pipelined requests when the first will close the connection.
      */
     if (Config.pipeline_max_prefetch > 0 && !Config.onoff.client_pconns) {
         debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " << Config.pipeline_max_prefetch <<
                " requires client_persistent_connections ON. Forced pipeline_prefetch 0.");
         Config.pipeline_max_prefetch = 0;
     }
 
 #if USE_AUTH
     /*
      * disable client side request pipelining. There is a race with
      * Negotiate and NTLM when the client sends a second request on an
      * connection before the authenticate challenge is sent. With
      * pipelining OFF, the client may fail to authenticate, but squid's
      * state will be preserved.
      */
     if (Config.pipeline_max_prefetch > 0) {
-        Auth::Config *nego = Auth::Config::Find("Negotiate");
-        Auth::Config *ntlm = Auth::Config::Find("NTLM");
+        Auth::SchemeConfig *nego = Auth::SchemeConfig::Find("Negotiate");
+        Auth::SchemeConfig *ntlm = Auth::SchemeConfig::Find("NTLM");
         if ((nego && nego->active()) || (ntlm && ntlm->active())) {
             debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced pipeline_prefetch 0.");
             Config.pipeline_max_prefetch = 0;
         }
     }
 
-    for (auto &authSchemes: Config.authSchemesConfigs) {
+    for (auto &authSchemes : Auth::TheConfig.schemeLists) {
         authSchemes.expand();
         if (authSchemes.authConfigs.empty()) {
             debugs(3, DBG_CRITICAL, "auth_schemes: at least one scheme name is required; got: " << authSchemes.rawSchemes);
             self_destruct();
         }
     }
 #endif
 }
 
 /** Parse a line containing an obsolete directive.
  * To upgrade it where possible instead of just "Bungled config" for
  * directives which cannot be marked as simply aliases of the some name.
  * For example if the parameter order and content has changed.
  * Or if the directive has been completely removed.
  */
 void
 parse_obsolete(const char *name)
 {
     // Directives which have been radically changed rather than removed
     if (!strcmp(name, "url_rewrite_concurrency")) {
@@ -1775,110 +1772,110 @@
     return s == NULL;
 }
 
 #if USE_AUTH
 static void
 parse_authparam(Auth::ConfigVector * config)
 {
     char *type_str = ConfigParser::NextToken();
     if (!type_str) {
         self_destruct();
         return;
     }
 
     char *param_str = ConfigParser::NextToken();
     if (!param_str) {
         self_destruct();
         return;
     }
 
     /* find a configuration for the scheme in the currently parsed configs... */
-    Auth::Config *schemeCfg = Auth::Config::Find(type_str);
+    Auth::SchemeConfig *schemeCfg = Auth::SchemeConfig::Find(type_str);
 
     if (schemeCfg == NULL) {
         /* Create a configuration based on the scheme info */
         Auth::Scheme::Pointer theScheme = Auth::Scheme::Find(type_str);
 
         if (theScheme == NULL) {
             debugs(3, DBG_CRITICAL, "Parsing Config File: Unknown authentication scheme '" << type_str << "'.");
             self_destruct();
             return;
         }
 
         config->push_back(theScheme->createConfig());
-        schemeCfg = Auth::Config::Find(type_str);
+        schemeCfg = Auth::SchemeConfig::Find(type_str);
         if (schemeCfg == NULL) {
             debugs(3, DBG_CRITICAL, "Parsing Config File: Corruption configuring authentication scheme '" << type_str << "'.");
             self_destruct();
             return;
         }
     }
 
     schemeCfg->parse(schemeCfg, config->size(), param_str);
 }
 
 static void
 free_authparam(Auth::ConfigVector * cfg)
 {
     /* Wipe the Auth globals and Detach/Destruct component config + state. */
     cfg->clear();
 
     /* on reconfigure initialize new auth schemes for the new config. */
     if (reconfiguring) {
         Auth::Init();
     }
 }
 
 static void
 dump_authparam(StoreEntry * entry, const char *name, Auth::ConfigVector cfg)
 {
-    for (Auth::ConfigVector::iterator  i = cfg.begin(); i != cfg.end(); ++i)
-        (*i)->dump(entry, name, (*i));
+    for (auto *scheme : cfg)
+        scheme->dump(entry, name, scheme);
 }
 
 static void
 parse_AuthSchemes(acl_access **authSchemes)
 {
     const char *tok = ConfigParser::NextQuotedToken();
     if (!tok) {
         debugs(29, DBG_CRITICAL, "FATAL: auth_schemes missing the parameter");
         self_destruct();
         return;
     }
-    Config.authSchemesConfigs.push_back(Auth::SchemesConfig(tok, ConfigParser::LastTokenWasQuoted()));
-    const allow_t action = allow_t(ACCESS_ALLOWED, Config.authSchemesConfigs.size() - 1);
+    Auth::TheConfig.schemeLists.emplace_back(tok, ConfigParser::LastTokenWasQuoted());
+    const allow_t action = allow_t(ACCESS_ALLOWED, Auth::TheConfig.schemeLists.size() - 1);
     ParseAclWithAction(authSchemes, action, "auth_schemes");
 }
 
 static void
 free_AuthSchemes(acl_access **authSchemes)
 {
-    Config.authSchemesConfigs.clear();
+    Auth::TheConfig.schemeLists.clear();
     free_acl_access(authSchemes);
 }
 
 static void
 dump_AuthSchemes(StoreEntry *entry, const char *name, acl_access *authSchemes)
 {
     if (authSchemes)
         dump_SBufList(entry, authSchemes->treeDump(name, [](const allow_t &action) {
-        return Config.authSchemesConfigs.at(action.kind).rawSchemes;
+        return Auth::TheConfig.schemeLists.at(action.kind).rawSchemes;
     }));
 }
 
 #endif /* USE_AUTH */
 
 static void
 ParseAclWithAction(acl_access **access, const allow_t &action, const char *desc, ACL *acl)
 {
     assert(access);
     SBuf name;
     if (!*access) {
         *access = new Acl::Tree;
         name.Printf("(%s rules)", desc);
         (*access)->context(name.c_str(), config_input_line);
     }
     Acl::AndNode *rule = new Acl::AndNode;
     name.Printf("(%s rule)", desc);
     rule->context(name.c_str(), config_input_line);
     acl ? rule->add(acl) : rule->lineParse();
     (*access)->add(rule, action);

=== modified file 'src/cf.data.depend'
--- src/cf.data.depend	2016-12-10 04:48:25 +0000
+++ src/cf.data.depend	2016-12-15 06:41:12 +0000
@@ -1,39 +1,39 @@
 ## Copyright (C) 1996-2016 The Squid Software Foundation and contributors
 ##
 ## Squid software is distributed under GPLv2+ license and includes
 ## contributions from numerous individuals and organizations.
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 #
 # type			dependencies
 #
 access_log		acl	logformat
 acl			external_acl_type auth_param
 acl_access		acl
 acl_address		acl
 acl_b_size_t		acl
 acl_tos			acl
 acl_nfmark		acl
 address
 authparam
-AuthSchemes
+AuthSchemes		acl auth_param
 b_int64_t
 b_size_t
 b_ssize_t
 cachedir		cache_replacement_policy
 cachemgrpasswd
 ConfigAclTos
 configuration_includes_quoted_values
 CpuAffinityMap
 debug
 delay_pool_access	acl	delay_class
 delay_pool_class	delay_pools
 delay_pool_count
 delay_pool_rates	delay_class
 client_delay_pool_access	acl
 client_delay_pool_count
 client_delay_pool_rates
 denyinfo		acl
 eol
 externalAclHelper	auth_param
 HelperChildConfig

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2016-12-10 04:48:25 +0000
+++ src/cf.data.pre	2016-12-20 12:37:28 +0000
@@ -464,41 +464,41 @@
 	"optimistic" kernel simply kills Squid kid with a SIGBUS signal.
 	Some of the memory limits enforced by the kernel are currently
 	poorly understood: We do not know how to detect and check them. This
 	option ensures that the mapped memory will be available. 
 
 	This option may have a positive performance side-effect: Locking
 	memory at start avoids runtime paging I/O. Paging slows Squid down.
 
 	Locking memory may require a large enough RLIMIT_MEMLOCK OS limit,
 	CAP_IPC_LOCK capability, or equivalent.
 DOC_END
 
 COMMENT_START
  OPTIONS FOR AUTHENTICATION
  -----------------------------------------------------------------------------
 COMMENT_END
 
 NAME: auth_param
 TYPE: authparam
 IFDEF: USE_AUTH
-LOC: Auth::TheConfig
+LOC: Auth::TheConfig.schemes
 DEFAULT: none
 DOC_START
 	This is used to define parameters for the various authentication
 	schemes supported by Squid.
 
 		format: auth_param scheme parameter [setting]
 
 	The order in which authentication schemes are presented to the client is
 	dependent on the order the scheme first appears in config file. IE
 	has a bug (it's not RFC 2617 compliant) in that it will use the basic
 	scheme if basic is the first entry presented, even if more secure
 	schemes are presented. For now use the order in the recommended
 	settings section below. If other browsers have difficulties (don't
 	recognize the schemes offered even if you are using basic) either
 	put basic first, or disable the other schemes (by commenting out their
 	program entry).
 
 	Once an authentication scheme is fully configured, it can only be
 	shutdown by shutting squid down and restarting. Changes can be made on
 	the fly and activated with a reconfigure. I.E. You can change to a
@@ -600,239 +600,177 @@
 		on-persistent-overload option applies.
 
 		The on-persistent-overload=action option specifies Squid
 		reaction to a new helper request arriving when the helper
 		has been overloaded for more that 3 minutes already. The number
 		of queued requests determines whether the helper is overloaded
 		(see the queue-size option).
 
 		Two actions are supported:
 
 		  die	Squid worker quits. This is the default behavior.
 
 		  ERR	Squid treats the helper request as if it was
 			immediately submitted, and the helper immediately
 			replied with an ERR response. This action has no effect
 			on the already queued and in-progress helper requests.
 
 		NOTE: NTLM and Negotiate schemes do not support concurrency
 			in the Squid code module even though some helpers can.
 
+	"keep_alive" on|off
+		If you experience problems with PUT/POST requests when using
+		the NTLM or Negotiate schemes then you can try setting this
+		to off. This will cause Squid to forcibly close the connection
+		on the initial request where the browser asks which schemes
+		are supported by the proxy.
 
-IF HAVE_AUTH_MODULE_BASIC
-	=== Basic authentication parameters ===
+		For Basic and Digest this parameter is ignored.
 
 	"utf8" on|off
 		HTTP uses iso-latin-1 as character set, while some
 		authentication backends such as LDAP expects UTF-8. If this is
 		set to on Squid will translate the HTTP iso-latin-1 charset to
 		UTF-8 before sending the username and password to the helper.
 
+		For NTLM and Negotiate this parameter is ignored.
+
+IF HAVE_AUTH_MODULE_BASIC
+	=== Basic authentication parameters ===
+
 	"credentialsttl" timetolive
 		Specifies how long squid assumes an externally validated
 		username:password pair is valid for - in other words how
 		often the helper program is called for that user. Set this
 		low to force revalidation with short lived passwords.
 
 		NOTE: setting this high does not impact your susceptibility
 		to replay attacks unless you are using an one-time password
 		system (such as SecureID). If you are using such a system,
 		you will be vulnerable to replay attacks unless you also
 		use the max_user_ip ACL in an http_access rule.
 
 	"casesensitive" on|off
 		Specifies if usernames are case sensitive. Most user databases
 		are case insensitive allowing the same username to be spelled
 		using both lower and upper case letters, but some are case
 		sensitive. This makes a big difference for user_max_ip ACL
 		processing and similar.
 
 ENDIF
 IF HAVE_AUTH_MODULE_DIGEST
 	=== Digest authentication parameters ===
 
-	"utf8" on|off
-		HTTP uses iso-latin-1 as character set, while some
-		authentication backends such as LDAP expects UTF-8. If this is
-		set to on Squid will translate the HTTP iso-latin-1 charset to
-		UTF-8 before sending the username and password to the helper.
-
 	"nonce_garbage_interval" timeinterval
 		Specifies the interval that nonces that have been issued
 		to client_agent's are checked for validity.
 
 	"nonce_max_duration" timeinterval
 		Specifies the maximum length of time a given nonce will be
 		valid for.
 
 	"nonce_max_count" number
 		Specifies the maximum number of times a given nonce can be
 		used.
 
 	"nonce_strictness" on|off
 		Determines if squid requires strict increment-by-1 behavior
 		for nonce counts, or just incrementing (off - for use when
 		user agents generate nonce counts that occasionally miss 1
 		(ie, 1,2,4,6)). Default off.
 
 	"check_nonce_count" on|off
 		This directive if set to off can disable the nonce count check
 		completely to work around buggy digest qop implementations in
 		certain mainstream browser versions. Default on to check the
 		nonce count to protect from authentication replay attacks.
 
 	"post_workaround" on|off
 		This is a workaround to certain buggy browsers who send an
 		incorrect request digest in POST requests when reusing the
 		same nonce as acquired earlier on a GET request.
 
 ENDIF
-IF HAVE_AUTH_MODULE_NEGOTIATE
-	=== Negotiate authentication parameters ===
-
-	"keep_alive" on|off
-		If you experience problems with PUT/POST requests when using
-		the this authentication scheme then you can try setting this
-		to off. This will cause Squid to forcibly close the connection
-		on the initial request where the browser asks which schemes
-		are supported by the proxy.
-
-ENDIF
-IF HAVE_AUTH_MODULE_NTLM
-	=== NTLM authentication parameters ===
-
-	"keep_alive" on|off
-		If you experience problems with PUT/POST requests when using
-		the this authentication scheme then you can try setting this
-		to off. This will cause Squid to forcibly close the connection
-		on the initial request where the browser asks which schemes
-		are supported by the proxy.
-ENDIF
 
 	=== Example Configuration ===
 
 	This configuration displays the recommended authentication scheme
 	order from most to least secure with recommended minimum configuration
 	settings for each scheme:
 
 #auth_param negotiate program <uncomment and complete this line to activate>
 #auth_param negotiate children 20 startup=0 idle=1
-#auth_param negotiate keep_alive on
 #
 #auth_param digest program <uncomment and complete this line to activate>
 #auth_param digest children 20 startup=0 idle=1
 #auth_param digest realm Squid proxy-caching web server
 #auth_param digest nonce_garbage_interval 5 minutes
 #auth_param digest nonce_max_duration 30 minutes
 #auth_param digest nonce_max_count 50
 #
 #auth_param ntlm program <uncomment and complete this line to activate>
 #auth_param ntlm children 20 startup=0 idle=1
-#auth_param ntlm keep_alive on
 #
 #auth_param basic program <uncomment and complete this line>
 #auth_param basic children 5 startup=5 idle=1
-#auth_param basic realm Squid proxy-caching web server
 #auth_param basic credentialsttl 2 hours
 DOC_END
 
 NAME: authenticate_cache_garbage_interval
+IFDEF: USE_AUTH
 TYPE: time_t
 DEFAULT: 1 hour
-LOC: Config.authenticateGCInterval
+LOC: Auth::TheConfig.authenticateGCInterval
 DOC_START
 	The time period between garbage collection across the username cache.
 	This is a trade-off between memory utilization (long intervals - say
 	2 days) and CPU (short intervals - say 1 minute). Only change if you
 	have good reason to.
 DOC_END
 
 NAME: authenticate_ttl
+IFDEF: USE_AUTH
 TYPE: time_t
 DEFAULT: 1 hour
-LOC: Config.authenticateTTL
+LOC: Auth::TheConfig.authenticateTTL
 DOC_START
 	The time a user & their credentials stay in the logged in
 	user cache since their last request. When the garbage
 	interval passes, all user credentials that have passed their
 	TTL are removed from memory.
 DOC_END
 
 NAME: authenticate_ip_ttl
+IFDEF: USE_AUTH
 TYPE: time_t
-LOC: Config.authenticateIpTTL
+LOC: Auth::TheConfig.authenticateIpTTL
 DEFAULT: 1 second
 DOC_START
 	If you use proxy authentication and the 'max_user_ip' ACL,
 	this directive controls how long Squid remembers the IP
 	addresses associated with each user.  Use a small value
 	(e.g., 60 seconds) if your users might change addresses
 	quickly, as is the case with dialup.   You might be safe
 	using a larger value (e.g., 2 hours) in a corporate LAN
 	environment with relatively static address assignments.
 DOC_END
 
-NAME: auth_schemes
-TYPE: AuthSchemes
-IFDEF: USE_AUTH
-LOC: Config.accessList.authSchemes
-DEFAULT: none
-DEFAULT_DOC: use all auth_param schemes in their configuration order
-DOC_START
-	Use this directive to customize authentication schemes presence and
-	order in Squid's Unauthorized and Authentication Required responses.
-
-		auth_schemes scheme1,scheme2,... [!]aclname ...
-
-	where schemeN is the name of one of the authentication schemes
-	configured using auth_param directives. At least one scheme name is
-	required. Multiple scheme names are separated by commas. Either
-	avoid whitespace or quote the entire schemes list.
-
-	A special "ALL" scheme name expands to all auth_param-configured
-	schemes in their configuration order. This directive cannot be used
-	to configure Squid to offer no authentication schemes at all.
-
-	The first matching auth_schemes rule determines the schemes order
-	for the current Authentication Required transaction. Note that the
-	future response is not yet available during auth_schemes evaluation.
-
-	If this directive is not used or none of its rules match, then Squid
-	responds with all configured authentication schemes in the order of
-	auth_param directives in the configuration file.
-
-	This directive does not determine when authentication is used or
-	how each authentication scheme authenticates clients.
-
-	The following example sends basic and negotiate authentication
-	schemes, in that order, when requesting authentication of HTTP
-	requests matching the isIE ACL (not shown) while sending all
-	auth_param schemes in their configuration order to other clients:
-
-		auth_schemes basic,negotiate isIE
-		auth_schemes ALL all # explicit default
-
-	This directive supports fast ACLs only.
-
-	See also: auth_param.
-DOC_END
-
 COMMENT_START
  ACCESS CONTROLS
  -----------------------------------------------------------------------------
 COMMENT_END
 
 NAME: external_acl_type
 TYPE: externalAclHelper
 LOC: Config.externalAclHelperList
 DEFAULT: none
 DOC_START
 	This option defines external acl classes using a helper program
 	to look up the status
 
 	  external_acl_type name [options] FORMAT /path/to/helper [helper arguments]
 
 	Options:
 
 	  ttl=n		TTL in seconds for cached results (defaults to 3600
 			for 1 hour)
 
@@ -1914,40 +1852,85 @@
 
 	Currently, this directive has effect on intercepted connections and
 	bumped tunnels only. Other cases are not supported because Squid
 	cannot know the intended destination of other traffic.
 
 	For example:
 	  # define what Squid errors indicate receiving non-HTTP traffic:
 	  acl foreignProtocol squid_error ERR_PROTOCOL_UNKNOWN ERR_TOO_BIG
 	  # define what Squid errors indicate receiving nothing:
 	  acl serverTalksFirstProtocol squid_error ERR_REQUEST_START_TIMEOUT
 	  # tunnel everything that does not look like HTTP:
           on_unsupported_protocol tunnel foreignProtocol
 	  # tunnel if we think the client waits for the server to talk first:
 	  on_unsupported_protocol tunnel serverTalksFirstProtocol
 	  # in all other error cases, just send an HTTP "error page" response:
 	  on_unsupported_protocol respond all
 
 	See also: squid_error ACL
 DOC_END
 
+NAME: auth_schemes
+TYPE: AuthSchemes
+IFDEF: USE_AUTH
+LOC: Auth::TheConfig.schemeAccess
+DEFAULT: none
+DEFAULT_DOC: use all auth_param schemes in their configuration order
+DOC_START
+	Use this directive to customize authentication schemes presence and
+	order in Squid's Unauthorized and Authentication Required responses.
+
+		auth_schemes scheme1,scheme2,... [!]aclname ...
+
+	where schemeN is the name of one of the authentication schemes
+	configured using auth_param directives. At least one scheme name is
+	required. Multiple scheme names are separated by commas. Either
+	avoid whitespace or quote the entire schemes list.
+
+	A special "ALL" scheme name expands to all auth_param-configured
+	schemes in their configuration order. This directive cannot be used
+	to configure Squid to offer no authentication schemes at all.
+
+	The first matching auth_schemes rule determines the schemes order
+	for the current Authentication Required transaction. Note that the
+	future response is not yet available during auth_schemes evaluation.
+
+	If this directive is not used or none of its rules match, then Squid
+	responds with all configured authentication schemes in the order of
+	auth_param directives in the configuration file.
+
+	This directive does not determine when authentication is used or
+	how each authentication scheme authenticates clients.
+
+	The following example sends basic and negotiate authentication
+	schemes, in that order, when requesting authentication of HTTP
+	requests matching the isIE ACL (not shown) while sending all
+	auth_param schemes in their configuration order to other clients:
+
+		auth_schemes basic,negotiate isIE
+		auth_schemes ALL all # explicit default
+
+	This directive supports fast ACLs only.
+
+	See also: auth_param.
+DOC_END
+
 COMMENT_START
  NETWORK OPTIONS
  -----------------------------------------------------------------------------
 COMMENT_END
 
 NAME: http_port ascii_port
 TYPE: PortCfg
 DEFAULT: none
 LOC: HttpPortList
 DOC_START
 	Usage:	port [mode] [options]
 		hostname:port [mode] [options]
 		1.2.3.4:port [mode] [options]
 
 	The socket addresses where Squid will listen for HTTP client
 	requests.  You may specify multiple socket addresses.
 	There are three forms: port alone, hostname with port, and
 	IP address with port.  If you specify a hostname or IP
 	address, Squid binds the socket to that specific
 	address. Most likely, you do not need to bind to a specific

=== modified file 'src/main.cc'
--- src/main.cc	2016-10-03 04:33:08 +0000
+++ src/main.cc	2016-12-19 13:36:49 +0000
@@ -1,34 +1,36 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 /* DEBUG: section 01    Startup and Main Loop */
 
 #include "squid.h"
 #include "AccessLogEntry.h"
 #include "acl/Acl.h"
 #include "acl/Asn.h"
+#include "auth/Config.h"
+#include "auth/Gadgets.h"
 #include "AuthReg.h"
 #include "base/RunnersRegistry.h"
 #include "base/Subscription.h"
 #include "base/TextException.h"
 #include "cache_cf.h"
 #include "CachePeer.h"
 #include "carp.h"
 #include "client_db.h"
 #include "client_side.h"
 #include "comm.h"
 #include "ConfigParser.h"
 #include "CpuAffinity.h"
 #include "DiskIO/DiskIOModule.h"
 #include "dns/forward.h"
 #include "errorpage.h"
 #include "event.h"
 #include "EventLoop.h"
 #include "ExternalACL.h"
 #include "fd.h"
 #include "format/Token.h"
@@ -70,43 +72,40 @@
 #include "store/Disks.h"
 #include "store_log.h"
 #include "StoreFileSystem.h"
 #include "tools.h"
 #include "unlinkd.h"
 #include "URL.h"
 #include "wccp.h"
 #include "wccp2.h"
 #include "WinSvc.h"
 
 #if USE_ADAPTATION
 #include "adaptation/Config.h"
 #endif
 #if USE_ECAP
 #include "adaptation/ecap/Config.h"
 #endif
 #if ICAP_CLIENT
 #include "adaptation/icap/Config.h"
 #include "adaptation/icap/icap_log.h"
 #endif
-#if USE_AUTH
-#include "auth/Gadgets.h"
-#endif
 #if USE_DELAY_POOLS
 #include "ClientDelayConfig.h"
 #endif
 #if USE_DELAY_POOLS
 #include "DelayPools.h"
 #endif
 #if USE_LOADABLE_MODULES
 #include "LoadableModules.h"
 #endif
 #if USE_OPENSSL
 #include "ssl/context_storage.h"
 #include "ssl/helper.h"
 #endif
 #if ICAP_CLIENT
 #include "adaptation/icap/Config.h"
 #endif
 #if USE_ECAP
 #include "adaptation/ecap/Config.h"
 #endif
 #if USE_ADAPTATION
@@ -947,41 +946,41 @@
     enableAdaptation = Adaptation::Ecap::TheConfig.onoff || enableAdaptation;
 #endif
     Adaptation::Config::Finalize(enableAdaptation);
 #endif
 
 #if ICAP_CLIENT
     icapLogOpen();
 #endif
     storeLogOpen();
     Dns::Init();
 #if USE_SSL_CRTD
     Ssl::Helper::GetInstance()->Init();
 #endif
 #if USE_OPENSSL
     if (Ssl::CertValidationHelper::GetInstance())
         Ssl::CertValidationHelper::GetInstance()->Init();
 #endif
 
     redirectInit();
 #if USE_AUTH
-    authenticateInit(&Auth::TheConfig);
+    authenticateInit(&Auth::TheConfig.schemes);
 #endif
     externalAclInit();
 
     if (IamPrimaryProcess()) {
 #if USE_WCCP
 
         wccpInit();
 #endif
 #if USE_WCCPv2
 
         wccp2Init();
 #endif
     }
 
     serverConnectionsOpen();
 
     neighbors_init();
 
     storeDirOpenSwapLogs();
 
@@ -1014,41 +1013,41 @@
     if (AvoidSignalAction("log rotation", do_rotate))
         return;
 
     icmpEngine.Close();
     redirectShutdown();
 #if USE_AUTH
     authenticateRotate();
 #endif
     externalAclShutdown();
 
     _db_rotate_log();       /* cache.log */
     storeDirWriteCleanLogs(1);
     storeLogRotate();       /* store.log */
     accessLogRotate();      /* access.log */
 #if ICAP_CLIENT
     icapLogRotate();               /*icap.log*/
 #endif
     icmpEngine.Open();
     redirectInit();
 #if USE_AUTH
-    authenticateInit(&Auth::TheConfig);
+    authenticateInit(&Auth::TheConfig.schemes);
 #endif
     externalAclInit();
 }
 
 static void
 setEffectiveUser(void)
 {
     keepCapabilities();
     leave_suid();       /* Run as non privilegied user */
 #if _SQUID_OS2_
 
     return;
 #endif
 
     if (geteuid() == 0) {
         debugs(0, DBG_CRITICAL, "Squid is not safe to run as root!  If you must");
         debugs(0, DBG_CRITICAL, "start Squid as root, then you must configure");
         debugs(0, DBG_CRITICAL, "it to run as a non-priveledged user with the");
         debugs(0, DBG_CRITICAL, "'cache_effective_user' option in the config file.");
         fatal("Don't run Squid as root, set 'cache_effective_user'!");
@@ -1158,41 +1157,41 @@
 
     ipcache_init();
 
     fqdncache_init();
 
     parseEtcHosts();
 
     Dns::Init();
 
 #if USE_SSL_CRTD
     Ssl::Helper::GetInstance()->Init();
 #endif
 
 #if USE_OPENSSL
     if (Ssl::CertValidationHelper::GetInstance())
         Ssl::CertValidationHelper::GetInstance()->Init();
 #endif
 
     redirectInit();
 #if USE_AUTH
-    authenticateInit(&Auth::TheConfig);
+    authenticateInit(&Auth::TheConfig.schemes);
 #endif
     externalAclInit();
 
     httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
 
     errorInitialize();
 
     accessLogInit();
 
 #if ICAP_CLIENT
     icapLogOpen();
 #endif
 
 #if USE_IDENT
     Ident::Init();
 #endif
 
 #if SQUID_SNMP
 
     snmpInit();

=== modified file 'src/tests/stub_libauth.cc'
--- src/tests/stub_libauth.cc	2016-12-10 04:48:25 +0000
+++ src/tests/stub_libauth.cc	2016-12-19 13:43:02 +0000
@@ -1,81 +1,84 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 
 #define STUB_API "auth/libauth.la"
 #include "STUB.h"
 
 #if USE_AUTH
-#include "auth/Config.h"
-Auth::UserRequest::Pointer Auth::Config::CreateAuthUser(const char *, AccessLogEntry::Pointer &al) STUB_RETVAL(NULL)
-Auth::Config * Auth::Config::Find(const char *) STUB_RETVAL(NULL)
-void Auth::Config::registerWithCacheManager(void) STUB_NOP
-Auth::ConfigVector Auth::TheConfig;
+#include "auth/SchemeConfig.h"
+namespace Auth
+{
+Auth::UserRequest::Pointer SchemeConfig::CreateAuthUser(const char *, AccessLogEntry::Pointer &al) STUB_RETVAL(NULL)
+Auth::SchemeConfig * SchemeConfig::Find(const char *) STUB_RETVAL(NULL)
+void SchemeConfig::registerWithCacheManager(void) STUB_NOP
+Auth::ConfigVector TheConfig;
+}
 
 #include "auth/Gadgets.h"
 int authenticateActiveSchemeCount(void) STUB_RETVAL(0)
 int authenticateSchemeCount(void) STUB_RETVAL(0)
 void authenticateInit(Auth::ConfigVector *) STUB
 void authenticateRotate(void) STUB
 void authenticateReset(void) STUB
 
 #include "auth/Scheme.h"
 #include <vector>
 std::vector<Auth::Scheme::Pointer> *Auth::Scheme::_Schemes = NULL;
 void Auth::Scheme::AddScheme(Auth::Scheme::Pointer) STUB
 Auth::Scheme::Pointer Auth::Scheme::Find(const char *) STUB_RETVAL(NULL)
 std::vector<Auth::Scheme::Pointer> & Auth::Scheme::GetSchemes() STUB_RETVAL(*_Schemes);
 void Auth::Scheme::FreeAll() STUB
 
+#include "auth/SchemesConfig.h"
+void Auth::SchemesConfig::expand() STUB
+
 #include "auth/User.h"
-Auth::User::User(Auth::Config *, const char *) STUB
+Auth::User::User(Auth::SchemeConfig *, const char *) STUB
 Auth::CredentialState Auth::User::credentials() const STUB_RETVAL(credentials_state)
 void Auth::User::credentials(CredentialState) STUB
 void Auth::User::absorb(Auth::User::Pointer) STUB
 Auth::User::~User() STUB_NOP
 void Auth::User::clearIp() STUB
 void Auth::User::removeIp(Ip::Address) STUB
 void Auth::User::addIp(Ip::Address) STUB
 void Auth::User::CredentialsCacheStats(StoreEntry *) STUB
 
 #include "auth/UserRequest.h"
 char const * Auth::UserRequest::username() const STUB_RETVAL("stub_username")
 void Auth::UserRequest::start(HttpRequest *, AccessLogEntry::Pointer &, AUTHCB *, void *) STUB
 bool Auth::UserRequest::valid() const STUB_RETVAL(false)
 void * Auth::UserRequest::operator new (size_t) STUB_RETVAL((void *)1)
 void Auth::UserRequest::operator delete (void *) STUB
 Auth::UserRequest::UserRequest() STUB
 Auth::UserRequest::~UserRequest() STUB
 void Auth::UserRequest::setDenyMessage(char const *) STUB
 char const * Auth::UserRequest::getDenyMessage() STUB_RETVAL("stub")
 char const * Auth::UserRequest::denyMessage(char const * const) STUB_RETVAL("stub")
 void authenticateAuthUserRequestRemoveIp(Auth::UserRequest::Pointer, Ip::Address const &) STUB
 void authenticateAuthUserRequestClearIp(Auth::UserRequest::Pointer) STUB
 int authenticateAuthUserRequestIPCount(Auth::UserRequest::Pointer) STUB_RETVAL(0)
 int authenticateUserAuthenticated(Auth::UserRequest::Pointer) STUB_RETVAL(0)
 Auth::Direction Auth::UserRequest::direction() STUB_RETVAL(Auth::CRED_ERROR)
 void Auth::UserRequest::addAuthenticationInfoHeader(HttpReply *, int) STUB
 void Auth::UserRequest::addAuthenticationInfoTrailer(HttpReply *, int) STUB
 void Auth::UserRequest::releaseAuthServer() STUB
 const char * Auth::UserRequest::connLastHeader() STUB_RETVAL("stub")
 AuthAclState Auth::UserRequest::authenticate(Auth::UserRequest::Pointer *, Http::HdrType, HttpRequest *, ConnStateData *, Ip::Address &, AccessLogEntry::Pointer &) STUB_RETVAL(AUTH_AUTHENTICATED)
 AuthAclState Auth::UserRequest::tryToAuthenticateAndSetAuthUser(Auth::UserRequest::Pointer *, Http::HdrType, HttpRequest *, ConnStateData *, Ip::Address &, AccessLogEntry::Pointer &) STUB_RETVAL(AUTH_AUTHENTICATED)
 void Auth::UserRequest::addReplyAuthHeader(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int, int) STUB
 void authenticateFixHeader(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int, int) STUB
 void authenticateAddTrailer(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int) STUB
 Auth::Scheme::Pointer Auth::UserRequest::scheme() const STUB_RETVAL(NULL)
 
 #include "AuthReg.h"
 void Auth::Init() STUB_NOP
 
-#include "auth/SchemesConfig.h"
-void Auth::SchemesConfig::expand() STUB
-
 #endif /* USE_AUTH */
 

=== modified file 'src/tests/testAuth.cc'
--- src/tests/testAuth.cc	2016-01-01 00:12:18 +0000
+++ src/tests/testAuth.cc	2016-12-19 13:43:38 +0000
@@ -1,35 +1,34 @@
 /*
  * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 
 #if USE_AUTH
 
 #include "auth/Config.h"
 #include "auth/Gadgets.h"
-#include "auth/Scheme.h"
 #include "auth/UserRequest.h"
 #include "ConfigParser.h"
 #include "testAuth.h"
 #include "unitTestMain.h"
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuth );
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthConfig );
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthUserRequest );
 #if HAVE_AUTH_MODULE_BASIC
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthBasicUserRequest );
 #endif
 #if HAVE_AUTH_MODULE_DIGEST
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthDigestUserRequest );
 #endif
 #if HAVE_AUTH_MODULE_NTLM
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthNTLMUserRequest );
 #endif
 #if HAVE_AUTH_MODULE_NEGOTIATE
 CPPUNIT_TEST_SUITE_REGISTRATION( testAuthNegotiateUserRequest );
 #endif



More information about the squid-dev mailing list