=== modified file 'src/ExternalACL.h'
--- old/src/ExternalACL.h	2009-03-08 19:34:36 +0000
+++ new/src/ExternalACL.h	2010-05-13 10:44:46 +0000
@@ -79,6 +79,7 @@
     /* when requiresRequest is made dynamic, review this too */
     //    virtual bool requiresReply() const {return true;}
     virtual bool isProxyAuth() const;
+    virtual char const *proxyAuthName() const;
     virtual wordlist *dump() const;
     virtual bool valid () const;
     virtual bool empty () const;

=== modified file 'src/HttpRequest.h'
--- old/src/HttpRequest.h	2010-04-17 02:29:04 +0000
+++ new/src/HttpRequest.h	2010-05-10 13:01:07 +0000
@@ -210,6 +210,8 @@
 
     String extacl_message;	/* String to be used for error page purposes */
 
+    String auth_name;           /* String to be used for auth select */
+
 #if FOLLOW_X_FORWARDED_FOR
     String x_forwarded_for_iterator; /* XXX a list of IP addresses */
 #endif /* FOLLOW_X_FORWARDED_FOR */

=== modified file 'src/acl/Acl.cc'
--- old/src/acl/Acl.cc	2009-03-08 19:45:44 +0000
+++ new/src/acl/Acl.cc	2010-05-13 08:42:22 +0000
@@ -182,6 +182,11 @@
     return false;
 }
 
+char const*
+ACL::proxyAuthName() const
+{
+    return NULL;
+}
 
 ACLList::ACLList() : op (1), _acl (NULL), next (NULL)
 {}

=== modified file 'src/acl/Acl.h'
--- old/src/acl/Acl.h	2009-03-08 19:45:44 +0000
+++ new/src/acl/Acl.h	2010-05-13 08:41:26 +0000
@@ -61,6 +61,7 @@
     virtual void parse() = 0;
     virtual char const *typeString() const = 0;
     virtual bool isProxyAuth() const;
+    virtual char const* proxyAuthName() const;
     virtual bool requiresRequest() const;
     virtual bool requiresReply() const;
     virtual int match(ACLChecklist * checklist) = 0;

=== modified file 'src/acl/Data.h'
--- old/src/acl/Data.h	2009-03-08 19:34:36 +0000
+++ new/src/acl/Data.h	2010-05-27 12:49:54 +0000
@@ -54,4 +54,10 @@
     virtual bool empty() const =0;
 };
 
+class ACLNameData: public ACLData<char const *>
+{
+public:
+    String name;
+};
+
 #endif /* SQUID_ACLDATA_H */

=== modified file 'src/acl/RegexData.cc'
--- old/src/acl/RegexData.cc	2009-03-08 19:34:36 +0000
+++ new/src/acl/RegexData.cc	2010-05-27 13:05:02 +0000
@@ -113,9 +113,9 @@
     return W;
 }
 
-static void aclParseRegexList(relist **curlist);
+static void aclParseRegexList(String *name, relist **curlist);
 void
-aclParseRegexList(relist **curlist)
+aclParseRegexList(String *name, relist **curlist)
 {
     relist **Tail;
     relist *q = NULL;
@@ -123,9 +123,21 @@
     regex_t comp;
     int errcode;
     int flags = REG_EXTENDED | REG_NOSUB;
+    bool first = true;
 
     for (Tail = (relist **)curlist; *Tail; Tail = &((*Tail)->next));
     while ((t = ConfigParser::strtokFile())) {
+        if (first) {
+            first = false;
+            if (strcmp(t, "-n") == 0) {
+                *name = ConfigParser::strtokFile();
+                continue;
+            }
+            else {
+                *name = "default";
+            }
+        }
+
         if (strcmp(t, "-i") == 0) {
             flags |= REG_ICASE;
             continue;
@@ -155,7 +167,7 @@
 void
 ACLRegexData::parse()
 {
-    aclParseRegexList(&data);
+    aclParseRegexList(&name, &data);
 }
 
 bool

=== modified file 'src/acl/RegexData.h'
--- old/src/acl/RegexData.h	2009-03-08 19:34:36 +0000
+++ new/src/acl/RegexData.h	2010-05-28 14:24:36 +0000
@@ -40,7 +40,7 @@
 /** \todo CLEANUP: break out relist, we don't need the rest. */
 #include "structs.h"
 
-class ACLRegexData : public ACLData<char const *>
+class ACLRegexData : public ACLNameData
 {
 
 public:

=== modified file 'src/acl/UserData.cc'
--- old/src/acl/UserData.cc	2009-03-08 19:34:36 +0000
+++ new/src/acl/UserData.cc	2010-05-11 13:03:15 +0000
@@ -131,6 +131,18 @@
     if ((t = ConfigParser::strtokFile())) {
         debugs(28, 5, "aclParseUserList: First token is " << t);
 
+        if (strcmp("-n", t) == 0) {
+            debugs(28, 5, "aclParseUserList: Found a name");
+            name = ConfigParser::strtokFile();
+            t = ConfigParser::strtokFile();
+        }
+        else
+        {
+            debugs(28, 5, "aclParseUserList: Using default name");
+            name = "default";
+        }
+
+        debugs(28, 6, "aclParseUserList: Got token: " << t);
         if (strcmp("-i", t) == 0) {
             debugs(28, 5, "aclParseUserList: Going case-insensitive");
             flags.case_insensitive = 1;

=== modified file 'src/acl/UserData.h'
--- old/src/acl/UserData.h	2009-03-31 12:39:30 +0000
+++ new/src/acl/UserData.h	2010-05-28 14:25:37 +0000
@@ -39,7 +39,7 @@
 #include "acl/Acl.h"
 #include "acl/Data.h"
 
-class ACLUserData : public ACLData<char const *>
+class ACLUserData : public ACLNameData
 {
 
 public:

=== modified file 'src/auth/AclProxyAuth.cc'
--- old/src/auth/AclProxyAuth.cc	2009-09-16 00:13:28 +0000
+++ new/src/auth/AclProxyAuth.cc	2010-05-28 15:49:20 +0000
@@ -51,15 +51,15 @@
     delete data;
 }
 
-ACLProxyAuth::ACLProxyAuth(ACLData<char const *> *newData, char const *theType) : data (newData), type_(theType) {}
+ACLProxyAuth::ACLProxyAuth(ACLNameData *newData, char const *theType) : data (newData), type_(theType) {}
 
-ACLProxyAuth::ACLProxyAuth (ACLProxyAuth const &old) : data (old.data->clone()), type_(old.type_)
+ACLProxyAuth::ACLProxyAuth (ACLProxyAuth const &old) : data (dynamic_cast<ACLNameData *>(old.data->clone())), type_(old.type_)
 {}
 
 ACLProxyAuth &
 ACLProxyAuth::operator= (ACLProxyAuth const &rhs)
 {
-    data = rhs.data->clone();
+    data = dynamic_cast<ACLNameData *>(rhs.data->clone());
     type_ = rhs.type_;
     return *this;
 }
@@ -76,11 +76,19 @@
     data->parse();
 }
 
+char const*
+ACLProxyAuth::proxyAuthName() const
+{
+    return data->name.termedBuf();
+}
+
 int
 ACLProxyAuth::match(ACLChecklist *checklist)
 {
     int ti;
 
+    Filled(checklist)->request->auth_name = data->name.termedBuf();
+    
     if ((ti = AuthenticateAcl(checklist)) != 1)
         return ti;
 

=== modified file 'src/auth/AclProxyAuth.h'
--- old/src/auth/AclProxyAuth.h	2009-03-31 12:39:30 +0000
+++ new/src/auth/AclProxyAuth.h	2010-05-27 12:57:28 +0000
@@ -68,13 +68,14 @@
     MEMPROXY_CLASS(ACLProxyAuth);
 
     ~ACLProxyAuth();
-    ACLProxyAuth(ACLData<char const *> *, char const *);
+    ACLProxyAuth(ACLNameData *, char const *);
     ACLProxyAuth (ACLProxyAuth const &);
     ACLProxyAuth &operator= (ACLProxyAuth const &);
 
     virtual char const *typeString() const;
     virtual void parse();
     virtual bool isProxyAuth() const {return true;}
+    char const *proxyAuthName() const;
 
     virtual int match(ACLChecklist *checklist);
     virtual wordlist *dump() const;
@@ -92,7 +93,7 @@
     static ACLProxyAuth RegexRegistryEntry_;
     int matchProxyAuth(ACLChecklist *);
     void checkAuthForCaching(ACLChecklist *) const;
-    ACLData<char const *> *data;
+    ACLNameData *data;
     char const *type_;
 };
 

=== modified file 'src/auth/Config.cc'
--- old/src/auth/Config.cc	2009-02-24 23:52:44 +0000
+++ new/src/auth/Config.cc	2010-05-12 10:42:06 +0000
@@ -43,12 +43,12 @@
  * It may also be NULL reflecting that no user could be created.
  */
 AuthUserRequest *
-AuthConfig::CreateAuthUser(const char *proxy_auth)
+AuthConfig::CreateAuthUser(const char *auth_name, const char *proxy_auth)
 {
     assert(proxy_auth != NULL);
     debugs(29, 9, "AuthConfig::CreateAuthUser: header = '" << proxy_auth << "'");
 
-    AuthConfig *config = Find(proxy_auth);
+    AuthConfig *config = Find(auth_name, proxy_auth);
 
     if (config == NULL || !config->active()) {
         debugs(29, 1, "AuthConfig::CreateAuthUser: Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth << "'");
@@ -66,10 +66,11 @@
 }
 
 AuthConfig *
-AuthConfig::Find(const char *proxy_auth)
+AuthConfig::Find(const char *auth_name, const char *proxy_auth)
 {
     for (authConfig::iterator  i = Config.authConfiguration.begin(); i != Config.authConfiguration.end(); ++i)
-        if (strncasecmp(proxy_auth, (*i)->type(), strlen((*i)->type())) == 0)
+        if (strncasecmp(proxy_auth, (*i)->type(), strlen((*i)->type())) == 0
+            && strncasecmp(auth_name, (*i)->name(), strlen((*i)->name())) == 0)
             return *i;
 
     return NULL;

=== modified file 'src/auth/Config.h'
--- old/src/auth/Config.h	2009-02-24 23:52:44 +0000
+++ new/src/auth/Config.h	2010-05-12 12:39:06 +0000
@@ -56,9 +56,9 @@
 {
 
 public:
-    static AuthUserRequest *CreateAuthUser (const char *proxy_auth);
+    static AuthUserRequest *CreateAuthUser (const char *auth_name, const char *proxy_auth);
 
-    static AuthConfig *Find(const char *proxy_auth);
+    static AuthConfig *Find(const char *auth_name, const char *proxy_auth);
     AuthConfig() {}
 
     virtual ~AuthConfig() {}
@@ -118,6 +118,8 @@
     virtual void parse(AuthConfig *, int, char *) = 0;
     /** the http string id */
     virtual const char * type() const = 0;
+    /** the name of this auth */
+    virtual const char * name() const = 0;
 };
 
 #endif /* SQUID_AUTHCONFIG_H */

=== modified file 'src/auth/Scheme.h'
--- old/src/auth/Scheme.h	2009-02-24 23:52:44 +0000
+++ new/src/auth/Scheme.h	2010-05-28 14:27:50 +0000
@@ -70,7 +70,9 @@
     /* per scheme methods */
     virtual char const *type () const = 0;
     virtual void done() = 0;
-    virtual AuthConfig *createConfig() = 0;
+    virtual AuthConfig *createConfig(char const *) = 0;
+    virtual AuthConfig *findConfig(char const*) = 0;
+    virtual void stats(StoreEntry *) = 0;
     // Not implemented
     AuthScheme(AuthScheme const &);
     AuthScheme &operator=(AuthScheme const&);

=== modified file 'src/auth/User.cc'
--- old/src/auth/User.cc	2010-04-17 02:29:04 +0000
+++ new/src/auth/User.cc	2010-05-12 10:06:46 +0000
@@ -52,7 +52,7 @@
 
 AuthUser::AuthUser (AuthConfig *aConfig) :
         auth_type (AUTH_UNKNOWN), config(aConfig),
-        usernamehash (NULL), ipcount (0), expiretime (0), references (0), username_(NULL)
+        usernamehash (NULL), ipcount (0), expiretime (0), references (0), username_(NULL), authname_(NULL)
 {
     proxy_auth_list.head = proxy_auth_list.tail = NULL;
     proxy_match_cache.head = proxy_match_cache.tail = NULL;
@@ -133,6 +133,9 @@
     if (username_)
         xfree((char*)username_);
 
+    if (authname_)
+        xfree((char*)authname_);
+
     /* prevent accidental reuse */
     auth_type = AUTH_UNKNOWN;
 }

=== modified file 'src/auth/User.cci'
--- old/src/auth/User.cci	2009-02-24 23:52:44 +0000
+++ new/src/auth/User.cci	2010-05-12 10:07:28 +0000
@@ -57,6 +57,23 @@
     }
 }
 
+char const *
+AuthUser::authname () const
+{
+    return authname_;
+}
+
+void
+AuthUser::authname(char const*aString)
+{
+    if (aString) {
+        assert(!authname_);
+        authname_ = xstrdup(aString);
+    } else {
+        safe_free(authname_);
+    }
+}
+
 void
 AuthUser::addRequest(AuthUserRequest *request)
 {

=== modified file 'src/auth/User.h'
--- old/src/auth/User.h	2010-05-02 19:32:42 +0000
+++ new/src/auth/User.h	2010-05-28 14:28:14 +0000
@@ -84,6 +84,8 @@
     virtual ~AuthUser();
     _SQUID_INLINE_ char const *username() const;
     _SQUID_INLINE_ void username(char const *);
+    _SQUID_INLINE_ char const *authname() const;
+    _SQUID_INLINE_ void authname(char const *);
     void clearIp();
     void removeIp(Ip::Address);
     void addIp(Ip::Address);
@@ -107,6 +109,12 @@
      */
     char const *username_;
 
+    /**
+     * The authname_ memory will be allocated via
+     * xstrdup(). It is our responsibility.
+     */
+    char const *authname_;
+
     /** what ip addresses has this user been seen at?, plus a list length cache */
     dlink_list ip_list;
 };

=== modified file 'src/auth/UserRequest.cc'
--- old/src/auth/UserRequest.cc	2010-04-17 02:29:04 +0000
+++ new/src/auth/UserRequest.cc	2010-05-28 14:17:36 +0000
@@ -47,6 +47,8 @@
 #include "acl/Acl.h"
 #include "client_side.h"
 */
+#include "acl/Acl.h"
+#include "auth/AclProxyAuth.h"
 #include "auth/Config.h"
 #include "auth/Scheme.h"
 #include "HttpReply.h"
@@ -69,6 +71,15 @@
         return NULL;
 }
 
+char const *
+AuthUserRequest::authname() const
+{
+    if (user())
+        return user()->authname();
+    else
+        return NULL;
+}
+
 size_t
 authenticateRequestRefCount (AuthUserRequest *aRequest)
 {
@@ -261,11 +272,11 @@
 }
 
 void
-AuthUserRequest::addHeader(HttpReply * rep, int accelerated)
+AuthUserRequest::addHeader(AuthConfig *scheme, HttpReply * rep, int accelerated)
 {}
 
 void
-AuthUserRequest::addTrailer(HttpReply * rep, int accelerated)
+AuthUserRequest::addTrailer(AuthConfig *scheme, HttpReply * rep, int accelerated)
 {}
 
 void
@@ -336,7 +347,7 @@
     proxy_auth = request->header.getStr(headertype);
 
     /*
-     * a note on proxy_auth logix here:
+     * a note on proxy_auth logic here:
      * proxy_auth==NULL -> unauthenticated request || already
      * authenticated connection so we test for an authenticated
      * connection when we recieve no authentication header.
@@ -392,7 +403,7 @@
         debugs(29, 9, "authenticateAuthenticate: This is a new checklist test on FD:" << (conn != NULL ? conn->fd : -1)  );
 
         if (proxy_auth && !request->auth_user_request && conn != NULL && conn->auth_user_request) {
-            AuthConfig * scheme = AuthConfig::Find(proxy_auth);
+            AuthConfig * scheme = AuthConfig::Find(conn->auth_user_request->authname(), proxy_auth);
 
             if (!conn->auth_user_request->user() || conn->auth_user_request->user()->config != scheme) {
                 debugs(29, 1, "authenticateAuthenticate: Unexpected change of authentication scheme from '" <<
@@ -410,7 +421,7 @@
             /* beginning of a new request check */
             debugs(29, 4, "authenticateAuthenticate: no connection authentication type");
 
-            *auth_user_request = AuthConfig::CreateAuthUser(proxy_auth);
+            *auth_user_request = AuthConfig::CreateAuthUser(request->auth_name.termedBuf(), proxy_auth);
             if (!authenticateValidateUser(*auth_user_request)) {
                 if (*auth_user_request == NULL)
                     return AUTH_ACL_CHALLENGE;
@@ -583,15 +594,22 @@
             /* scheme specific */
             auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request);
         else {
-            /* call each configured & running authscheme */
+            /* call each configured & running authscheme which matches this authname */
+            ACL *a = ACL::FindByName(AclMatchedName);
+            assert(a && a->isProxyAuth());
 
             for (authConfig::iterator  i = Config.authConfiguration.begin(); i != Config.authConfiguration.end(); ++i) {
                 AuthConfig *scheme = *i;
 
                 if (scheme->active())
-                    scheme->fixHeader(NULL, rep, type, request);
+                {
+                    if (strcmp(a->proxyAuthName(), scheme->name()) == 0)
+                        scheme->fixHeader(NULL, rep, type, request);
+                    else
+                        debugs(29, 4, "authenticateFixHeader: Configured scheme " << scheme->type() << " " << scheme->name() << " none matching name");
+                }
                 else
-                    debugs(29, 4, "authenticateFixHeader: Configured scheme " << scheme->type() << " not Active");
+                    debugs(29, 4, "authenticateFixHeader: Configured scheme " << scheme->type() << " " << scheme->name() << " not Active");
             }
         }
 
@@ -602,7 +620,15 @@
      */
 
     if (auth_user_request != NULL) {
-        auth_user_request->addHeader(rep, accelerated);
+        ACL *a = ACL::FindByName(AclMatchedName);
+        assert(a && a->isProxyAuth());
+
+        for (authConfig::iterator  i = Config.authConfiguration.begin(); i != Config.authConfiguration.end(); ++i) {
+            AuthConfig *scheme = *i;
+            
+            if (strcmp(a->proxyAuthName(), scheme->name()) == 0)
+                auth_user_request->addHeader(scheme, rep, accelerated);
+        }
         if (auth_user_request->lastReply != AUTH_AUTHENTICATED)
             auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE;
     }
@@ -619,8 +645,17 @@
 void
 authenticateAddTrailer(HttpReply * rep, AuthUserRequest * auth_user_request, HttpRequest * request, int accelerated)
 {
-    if (auth_user_request != NULL)
-        auth_user_request->addTrailer(rep, accelerated);
+    if (auth_user_request != NULL) {
+        ACL *a = ACL::FindByName(AclMatchedName);
+        assert(a && a->isProxyAuth());
+
+        for (authConfig::iterator  i = Config.authConfiguration.begin(); i != Config.authConfiguration.end(); ++i) {
+            AuthConfig *scheme = *i;
+            
+            if (strcmp(a->proxyAuthName(), scheme->name()) == 0)
+                auth_user_request->addTrailer(scheme, rep, accelerated);
+        }
+    }
 }
 
 void

=== modified file 'src/auth/UserRequest.h'
--- old/src/auth/UserRequest.h	2010-04-17 02:29:04 +0000
+++ new/src/auth/UserRequest.h	2010-05-28 10:54:26 +0000
@@ -89,8 +89,8 @@
     virtual void authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type) = 0;
     /* template method */
     virtual int module_direction() = 0;
-    virtual void addHeader(HttpReply * rep, int accel);
-    virtual void addTrailer(HttpReply * rep, int accel);
+    virtual void addHeader(AuthConfig *scheme, HttpReply * rep, int accel);
+    virtual void addTrailer(AuthConfig *scheme, HttpReply * rep, int accel);
     virtual void onConnectionClose(ConnStateData *);
 
     /**
@@ -140,6 +140,8 @@
      */
     char const *username() const;
 
+    char const *authname() const;
+
     AuthScheme *scheme() const;
 
     virtual const char * connLastHeader();

=== modified file 'src/auth/basic/auth_basic.cc'
--- old/src/auth/basic/auth_basic.cc	2010-02-13 09:16:30 +0000
+++ new/src/auth/basic/auth_basic.cc	2010-05-28 15:38:24 +0000
@@ -59,13 +59,6 @@
 static HLPCB authenticateBasicHandleReply;
 static AUTHSSTATS authenticateBasicStats;
 
-static helper *basicauthenticators = NULL;
-
-static AuthBasicConfig basicConfig;
-
-static int authbasic_initialised = 0;
-
-
 /*
  *
  * Public Functions
@@ -78,19 +71,6 @@
 void
 basicScheme::done()
 {
-    /* TODO: this should be a Config call. */
-
-    if (basicauthenticators)
-        helperShutdown(basicauthenticators);
-
-    authbasic_initialised = 0;
-
-    if (!shutting_down)
-        return;
-
-    delete basicauthenticators;
-    basicauthenticators = NULL;
-
     /* XXX Reinstate auth shutdown for dynamic schemes? */
     debugs(29, DBG_CRITICAL, HERE << "Basic authentication Shutdown.");
 }
@@ -130,7 +110,7 @@
 bool
 BasicUser::authenticated() const
 {
-    if ((flags.credentials_ok == 1) && (credentials_checkedtime + basicConfig.credentialsTTL > squid_curtime))
+    if ((flags.credentials_ok == 1) && (credentials_checkedtime + dynamic_cast<AuthBasicConfig *>(config)->credentialsTTL > squid_curtime))
         return true;
 
     debugs(29, 4, "User not authenticated or credentials need rechecking.");
@@ -155,7 +135,6 @@
 AuthBasicUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
 {
     assert(user() != NULL);
-
     basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
 
     /* if the password is not ok, do an identity */
@@ -164,7 +143,7 @@
         return;
 
     /* are we about to recheck the credentials externally? */
-    if ((basic_auth->credentials_checkedtime + basicConfig.credentialsTTL) <= squid_curtime) {
+    if ((basic_auth->credentials_checkedtime + dynamic_cast<AuthBasicConfig *>(basic_auth->config)->credentialsTTL) <= squid_curtime) {
         debugs(29, 4, "authBasicAuthenticate: credentials expired - rechecking");
         return;
     }
@@ -193,7 +172,7 @@
 
     case 1:			/* checked & ok */
 
-        if (basic_auth->credentials_checkedtime + basicConfig.credentialsTTL <= squid_curtime)
+        if (basic_auth->credentials_checkedtime + dynamic_cast<AuthBasicConfig *>(basic_auth->config)->credentialsTTL <= squid_curtime)
             return -1;
 
         return 0;
@@ -221,6 +200,14 @@
 void
 AuthBasicConfig::done()
 {
+    if (basicauthenticators)
+        helperShutdown(basicauthenticators);
+
+    authbasic_initialised = 0;
+
+    delete basicauthenticators;
+    basicauthenticators = NULL;
+
     if (authenticate)
         wordlistDestroy(&authenticate);
 
@@ -306,7 +293,7 @@
     storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
 }
 
-AuthBasicConfig::AuthBasicConfig() : authenticateChildren(20)
+AuthBasicConfig::AuthBasicConfig() : authenticateChildren(20), authName(NULL), authenticate(NULL), basicauthenticators(NULL), authbasic_initialised(0)
 {
     /* TODO: move into initialisation list */
     credentialsTTL = 2 * 60 * 60;	/* two hours */
@@ -346,7 +333,7 @@
 static void
 authenticateBasicStats(StoreEntry * sentry)
 {
-    helperStats(sentry, basicauthenticators, "Basic Authenticator Statistics");
+    basicScheme::GetInstance().stats(sentry);
 }
 
 CBDATA_TYPE(AuthenticateStateData);
@@ -429,8 +416,8 @@
         /* replace the colon so we can find the password */
         *seperator = ':';
     }
-
-    if (!basicConfig.casesensitive)
+    
+    if (!dynamic_cast<AuthBasicConfig *>(config)->casesensitive)
         Tolower((char *)username());
 }
 
@@ -464,6 +451,7 @@
         extractUsername();
         extractPassword();
     }
+    authname(config->name());
     currentRequest = NULL;
     httpAuthHeader = NULL;
 }
@@ -485,7 +473,8 @@
         /* log the username */
         debugs(29, 9, HERE << "Creating new user for logging '" << username() << "'");
         /* new scheme data */
-        BasicUser *basic_auth = new BasicUser(& basicConfig);
+        /* \todo Do I need to copy this? */
+        BasicUser *basic_auth = new BasicUser(config);
         auth_user_request->user(basic_auth);
         /* save the credentials */
         basic_auth->username(username());
@@ -502,7 +491,7 @@
 {
     /* the user doesn't exist in the username cache yet */
     debugs(29, 9, HERE << "Creating new user '" << username() << "'");
-    BasicUser *basic_user = new BasicUser(&basicConfig);
+    BasicUser *basic_user = new BasicUser(config);
     /* save the credentials */
     basic_user->username(username());
     username(NULL);
@@ -556,7 +545,7 @@
     while (xisgraph(*proxy_auth))
         proxy_auth++;
 
-    BasicUser *basic_auth, local_basic(&basicConfig);
+    BasicUser *basic_auth, local_basic(this);
 
     /* Trim leading whitespace before decoding */
     while (xisspace(*proxy_auth))
@@ -648,7 +637,7 @@
     assert(basic_auth != NULL);
     debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
 
-    if (basicConfig.authenticate == NULL) {
+    if (dynamic_cast<AuthBasicConfig *>(basic_auth->config)->authenticate == NULL) {
         handler(data, NULL);
         return;
     }
@@ -675,7 +664,7 @@
     r->handler = handler;
     r->data = cbdataReference(data);
     r->auth_user_request = auth_user_request;
-    if (basicConfig.utf8) {
+    if (dynamic_cast<AuthBasicConfig *>(config)->utf8) {
         latin1_to_utf8(user, sizeof(user), username());
         latin1_to_utf8(pass, sizeof(pass), passwd);
         xstrncpy(user, rfc1738_escape(user), sizeof(user));
@@ -685,11 +674,59 @@
         xstrncpy(pass, rfc1738_escape(passwd), sizeof(pass));
     }
     snprintf(buf, sizeof(buf), "%s %s\n", user, pass);
-    helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
-}
-
-AuthConfig *
-basicScheme::createConfig()
-{
-    return &basicConfig;
+    helperSubmit(dynamic_cast<AuthBasicConfig *>(config)->basicauthenticators, buf, authenticateBasicHandleReply, r);
+}
+
+AuthConfig *
+basicScheme::findConfig(char const *auth_name)
+{
+    AuthBasicConfig *auth_config;
+
+    dlink_node *link = config.head;
+    debugs(29, DBG_CRITICAL, "***** Looking for: "  << auth_name);
+
+    while (link) {
+        auth_config = static_cast<AuthBasicConfig *>(link->data);
+        if (strcmp(auth_name, auth_config->name()) == 0)
+            return auth_config;
+        link = link->next;
+    }
+
+    return NULL;
+}
+
+AuthConfig *
+basicScheme::createConfig(char const *auth_name)
+{
+    AuthBasicConfig *auth_config;
+
+    dlink_node *link = config.head;
+
+    auth_config = dynamic_cast<AuthBasicConfig *>(findConfig(auth_name));
+
+    if (!auth_config) {
+        auth_config = new AuthBasicConfig();
+        debugs(29, DBG_CRITICAL, "***** New auth called: "  << auth_name << " " << (void*)auth_name);
+        auth_config->authName = auth_name;
+
+        link = dlinkNodeNew();
+
+        dlinkAddTail(auth_config, link, &config);
+    }
+
+    return auth_config;
+}
+
+void
+basicScheme::stats(StoreEntry * sentry)
+{
+    AuthBasicConfig *auth_config;
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthBasicConfig *>(link->data);
+        if (auth_config->authbasic_initialised)
+            helperStats(sentry, auth_config->basicauthenticators, "Basic Authenticator Statistics");
+        link = link->next;
+    }
 }

=== modified file 'src/auth/basic/auth_basic.h'
--- old/src/auth/basic/auth_basic.h	2009-12-19 05:47:00 +0000
+++ new/src/auth/basic/auth_basic.h	2010-05-12 15:19:17 +0000
@@ -127,12 +127,16 @@
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
+    virtual const char * name() const {return authName.termedBuf();}
     HelperChildConfig authenticateChildren;
+    String authName;
     char *basicAuthRealm;
     wordlist *authenticate;
     time_t credentialsTTL;
     int casesensitive;
     int utf8;
+    helper *basicauthenticators;
+    int authbasic_initialised;
 };
 
 #endif

=== modified file 'src/auth/basic/basicScheme.cc'
--- old/src/auth/basic/basicScheme.cc	2009-05-20 06:59:04 +0000
+++ new/src/auth/basic/basicScheme.cc	2010-05-27 15:17:27 +0000
@@ -44,6 +44,7 @@
 basicScheme::basicScheme()
 {
     AddScheme(*this);
+    config.head = config.tail = NULL;
 }
 
 char const *

=== modified file 'src/auth/basic/basicScheme.h'
--- old/src/auth/basic/basicScheme.h	2009-05-20 06:59:04 +0000
+++ new/src/auth/basic/basicScheme.h	2010-05-12 12:40:05 +0000
@@ -49,13 +49,17 @@
     /* per scheme */
     virtual char const *type () const;
     virtual void done();
-    virtual AuthConfig *createConfig();
+    virtual void stats(StoreEntry * sentry);
+    virtual AuthConfig *createConfig(char const*);
+    virtual AuthConfig *findConfig(char const*);
     /* Not implemented */
     basicScheme (basicScheme const &);
     basicScheme &operator=(basicScheme const &);
 
 private:
     static basicScheme *_instance;
+    /* Configs for this scheme */
+    dlink_list config;
 };
 
 #endif /* SQUID_BASICSCHEME_H */

=== modified file 'src/auth/digest/auth_digest.cc'
--- old/src/auth/digest/auth_digest.cc	2010-04-17 02:29:04 +0000
+++ new/src/auth/digest/auth_digest.cc	2010-05-28 15:57:07 +0000
@@ -56,13 +56,8 @@
 static HLPCB authenticateDigestHandleReply;
 static AUTHSSTATS authenticateDigestStats;
 
-static helper *digestauthenticators = NULL;
-
 static hash_table *digest_nonce_cache;
 
-static AuthDigestConfig digestConfig;
-
-static int authdigest_initialised = 0;
 static MemAllocator *digest_nonce_pool = NULL;
 
 CBDATA_TYPE(DigestAuthenticateStateData);
@@ -104,14 +99,10 @@
 static digest_nonce_h *authenticateDigestNonceFindNonce(const char *nonceb64);
 static digest_nonce_h *authenticateDigestNonceNew(void);
 static void authenticateDigestNonceDelete(digest_nonce_h * nonce);
-static void authenticateDigestNonceSetup(void);
 static void authenticateDigestNonceShutdown(void);
 static void authenticateDigestNonceReconfigure(void);
 static const char *authenticateDigestNonceNonceb64(digest_nonce_h * nonce);
-static int authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]);
-static int authDigestNonceIsStale(digest_nonce_h * nonce);
 static void authDigestNonceEncode(digest_nonce_h * nonce);
-static int authDigestNonceLastRequest(digest_nonce_h * nonce);
 static void authDigestNonceLink(digest_nonce_h * nonce);
 static void authDigestNonceUnlink(digest_nonce_h * nonce);
 #if NOT_USED
@@ -224,8 +215,8 @@
     }
 }
 
-static void
-authenticateDigestNonceSetup(void)
+void
+AuthDigestConfig::authenticateDigestNonceSetup(void)
 {
     if (!digest_nonce_pool)
         digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h));
@@ -233,7 +224,7 @@
     if (!digest_nonce_cache) {
         digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
         assert(digest_nonce_cache);
-        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig.nonceGCInterval, 1);
+        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, this, nonceGCInterval, 1);
     }
 }
 
@@ -278,6 +269,8 @@
      * the cache, 100/200 entries at a time. Lets see how it flies
      * first.
      */
+    AuthDigestConfig *config = static_cast<AuthDigestConfig *>(data);
+
     digest_nonce_h *nonce;
     debugs(29, 3, "authenticateDigestNonceCacheCleanup: Cleaning the nonce cache now");
     debugs(29, 3, "authenticateDigestNonceCacheCleanup: Current time: " << current_time.tv_sec);
@@ -287,7 +280,7 @@
         debugs(29, 3, "authenticateDigestNonceCacheCleanup: nonce entry  : " << nonce << " '" << (char *) nonce->key << "'");
         debugs(29, 4, "authenticateDigestNonceCacheCleanup: Creation time: " << nonce->noncedata.creationtime);
 
-        if (authDigestNonceIsStale(nonce)) {
+        if (config->authDigestNonceIsStale(nonce)) {
             debugs(29, 4, "authenticateDigestNonceCacheCleanup: Removing nonce " << (char *) nonce->key << " from cache due to timeout.");
             assert(nonce->flags.incache);
             /* invalidate nonce so future requests fail */
@@ -300,8 +293,8 @@
 
     debugs(29, 3, "authenticateDigestNonceCacheCleanup: Finished cleaning the nonce cache.");
 
-    if (digestConfig.active())
-        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig.nonceGCInterval, 1);
+    if (config->active())
+        eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, config, config->nonceGCInterval, 1);
 }
 
 static void
@@ -370,8 +363,8 @@
     return nonce;
 }
 
-static int
-authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9])
+int
+AuthDigestConfig::authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9])
 {
     unsigned long intnc;
     /* do we have a nonce ? */
@@ -388,12 +381,12 @@
     }
 
     /* is the nonce-count ok ? */
-    if (!digestConfig.CheckNonceCount) {
+    if (!CheckNonceCount) {
         nonce->nc++;
         return -1;              /* forced OK by configuration */
     }
 
-    if ((digestConfig.NonceStrictness && intnc != nonce->nc + 1) ||
+    if ((NonceStrictness && intnc != nonce->nc + 1) ||
             intnc < nonce->nc + 1) {
         debugs(29, 4, "authDigestNonceIsValid: Nonce count doesn't match");
         nonce->flags.valid = 0;
@@ -409,8 +402,8 @@
     return -1;
 }
 
-static int
-authDigestNonceIsStale(digest_nonce_h * nonce)
+int
+AuthDigestConfig::authDigestNonceIsStale(digest_nonce_h * nonce)
 {
     /* do we have a nonce ? */
 
@@ -418,10 +411,10 @@
         return -1;
 
     /* has it's max duration expired? */
-    if (nonce->noncedata.creationtime + digestConfig.noncemaxduration < current_time.tv_sec) {
+    if (nonce->noncedata.creationtime + noncemaxduration < current_time.tv_sec) {
         debugs(29, 4, "authDigestNonceIsStale: Nonce is too old. " <<
                nonce->noncedata.creationtime << " " <<
-               digestConfig.noncemaxduration << " " <<
+               noncemaxduration << " " <<
                current_time.tv_sec);
 
         nonce->flags.valid = 0;
@@ -434,7 +427,7 @@
         return -1;
     }
 
-    if (nonce->nc > digestConfig.noncemaxuses) {
+    if (nonce->nc > noncemaxuses) {
         debugs(29, 4, "authDigestNoncelastRequest: Nonce count over user limit");
         nonce->flags.valid = 0;
         return -1;
@@ -445,8 +438,8 @@
 }
 
 /* return -1 if the digest will be stale on the next request */
-static int
-authDigestNonceLastRequest(digest_nonce_h * nonce)
+int
+AuthDigestConfig::authDigestNonceLastRequest(digest_nonce_h * nonce)
 {
     if (!nonce)
         return -1;
@@ -456,7 +449,7 @@
         return -1;
     }
 
-    if (nonce->nc >= digestConfig.noncemaxuses - 1) {
+    if (nonce->nc >= noncemaxuses - 1) {
         debugs(29, 4, "authDigestNoncelastRequest: Nonce count about to hit user limit");
         return -1;
     }
@@ -529,24 +522,18 @@
 {
     /** \todo this should be a Config call. */
 
-    if (digestauthenticators)
-        helperShutdown(digestauthenticators);
+    /** \todo do I need call Config done for each Config?? */
 
     if (DigestFieldsInfo) {
         httpHeaderDestroyFieldsInfo(DigestFieldsInfo, DIGEST_ENUM_END);
         DigestFieldsInfo = NULL;
     }
 
-    authdigest_initialised = 0;
-
     if (!shutting_down) {
         authenticateDigestNonceReconfigure();
         return;
     }
 
-    delete digestauthenticators;
-    digestauthenticators = NULL;
-
     authDigestUserShutdown();
     authenticateDigestNonceShutdown();
     debugs(29, 2, "authenticateDigestDone: Digest authentication shut down.");
@@ -657,7 +644,7 @@
             return;
         }
 
-        if (digestConfig.PostWorkaround && request->method != METHOD_GET) {
+        if (dynamic_cast<AuthDigestConfig *>(digest_user->config)->PostWorkaround && request->method != 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
@@ -701,7 +688,7 @@
         }
 
         /* check for stale nonce */
-        if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
+        if (!dynamic_cast<AuthDigestConfig *>(digest_user->config)->authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
             debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK but nonce stale");
             credentials(Failed);
             digest_request->setDenyMessage("Stale nonce");
@@ -746,9 +733,10 @@
 
 /* add the [proxy]authorisation header */
 void
-AuthDigestUserRequest::addHeader(HttpReply * rep, int accel)
+AuthDigestUserRequest::addHeader(AuthConfig *scheme, HttpReply * rep, int accel)
 {
     http_hdr_type type;
+    AuthDigestConfig *config;
 
     /* don't add to authentication error pages */
 
@@ -757,6 +745,7 @@
         return;
 
     type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO;
+    config = dynamic_cast<AuthDigestConfig *>(scheme);
 
 #if WAITING_FOR_TE
     /* test for http/1.1 transfer chunked encoding */
@@ -765,7 +754,7 @@
 
 #endif
 
-    if ((digestConfig.authenticate) && authDigestNonceLastRequest(nonce)) {
+    if ((config->authenticate) && config->authDigestNonceLastRequest(nonce)) {
         flags.authinfo_sent = 1;
         debugs(29, 9, "authDigestAddHead: Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
         httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
@@ -775,9 +764,10 @@
 #if WAITING_FOR_TE
 /* add the [proxy]authorisation header */
 void
-AuthDigestUserRequest::addTrailer(HttpReply * rep, int accel)
+AuthDigestUserRequest::addTrailer(AuthConfig *scheme, HttpReply * rep, int accel)
 {
     int type;
+    AuthDigestConfig *config;
 
     if (!auth_user_request)
         return;
@@ -793,8 +783,9 @@
         return;
 
     type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO;
+    config = dynamic_cast<AuthDigestConfig *>(scheme);
 
-    if ((digestConfig.authenticate) && authDigestNonceLastRequest(nonce)) {
+    if ((config->authenticate) && authDigestNonceLastRequest(nonce)) {
         debugs(29, 9, "authDigestAddTrailer: Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
         httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
     }
@@ -936,9 +927,21 @@
         wordlistDestroy(&authenticate);
 
     safe_free(digestAuthRealm);
+
+    if (digestauthenticators)
+        helperShutdown(digestauthenticators);
+
+    authdigest_initialised = 0;
+
+    if (!shutting_down) {
+        return;
+    }
+
+    delete digestauthenticators;
+    digestauthenticators = NULL;
 }
 
-AuthDigestConfig::AuthDigestConfig() : authenticateChildren(20)
+AuthDigestConfig::AuthDigestConfig() : authenticateChildren(20), digestauthenticators(NULL), authdigest_initialised(0)
 {
     /* TODO: move into initialisation list */
     /* 5 minutes */
@@ -996,7 +999,7 @@
 static void
 authenticateDigestStats(StoreEntry * sentry)
 {
-    helperStats(sentry, digestauthenticators, "Digest Authenticator Statistics");
+    digestScheme::GetInstance().stats(sentry);
 }
 
 /* NonceUserUnlink: remove the reference to auth_user and unlink the node from the list */
@@ -1075,18 +1078,20 @@
 }
 
 /* setup the necessary info to log the username */
-static AuthUserRequest *
-authDigestLogUsername(char *username, AuthDigestUserRequest *auth_user_request)
+AuthUserRequest *
+AuthDigestConfig::authDigestLogUsername(char *username, AuthDigestUserRequest *auth_user_request)
 {
     assert(auth_user_request != NULL);
 
     /* log the username */
     debugs(29, 9, "authDigestLogUsername: Creating new user for logging '" << username << "'");
-    digest_user_h *digest_user = new DigestUser(&digestConfig);
+    digest_user_h *digest_user = new DigestUser(this);
     /* save the credentials */
     digest_user->username(username);
     /* set the auth_user type */
     digest_user->auth_type = AUTH_BROKEN;
+    /* set the auth_user auth name */
+    digest_user->authname(name());
     /* link the request to the user */
     auth_user_request->authUser(digest_user);
     auth_user_request->user(digest_user);
@@ -1344,7 +1349,7 @@
     if ((auth_user = authDigestUserFindUsername(username)) == NULL) {
         /* the user doesn't exist in the username cache yet */
         debugs(29, 9, "authDigestDecodeAuth: Creating new digest user '" << username << "'");
-        digest_user = new DigestUser (&digestConfig);
+        digest_user = new DigestUser (this);
         /* auth_user is a parent */
         auth_user = digest_user;
         /* save the username */
@@ -1400,7 +1405,7 @@
     assert(digest_user != NULL);
     debugs(29, 9, "authenticateStart: '\"" << digest_user->username() << "\":\"" << realm << "\"'");
 
-    if (digestConfig.authenticate == NULL) {
+    if (dynamic_cast<AuthDigestConfig*>(digest_user->config)->authenticate == NULL) {
         handler(data, NULL);
         return;
     }
@@ -1410,7 +1415,7 @@
     r->data = cbdataReference(data);
     r->auth_user_request = this;
     AUTHUSERREQUESTLOCK(r->auth_user_request, "r");
-    if (digestConfig.utf8) {
+    if (dynamic_cast<AuthDigestConfig*>(digest_user->config)->utf8) {
         char userstr[1024];
         latin1_to_utf8(userstr, sizeof(userstr), digest_user->username());
         snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
@@ -1418,7 +1423,7 @@
         snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username(), realm);
     }
 
-    helperSubmit(digestauthenticators, buf, authenticateDigestHandleReply, r);
+    helperSubmit(dynamic_cast<AuthDigestConfig*>(digest_user->config)->digestauthenticators, buf, authenticateDigestHandleReply, r);
 }
 
 DigestUser::DigestUser (AuthConfig *aConfig) : AuthUser (aConfig), HA1created (0)
@@ -1475,8 +1480,52 @@
 }
 
 AuthConfig *
-digestScheme::createConfig()
-{
-    return &digestConfig;
-}
-
+digestScheme::findConfig(char const *auth_name)
+{
+    AuthDigestConfig *auth_config;
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthDigestConfig *>(link->data);
+        if (strcmp(auth_name, auth_config->name()) == 0)
+            return auth_config;
+        link = link->next;
+    }
+
+    return NULL;
+}
+
+AuthConfig *
+digestScheme::createConfig(char const *auth_name)
+{
+    AuthDigestConfig *auth_config;
+    dlink_node *link = config.head;
+
+    auth_config = dynamic_cast<AuthDigestConfig *>(findConfig(auth_name));
+
+    if (!auth_config) {
+        auth_config = new AuthDigestConfig();
+        auth_config->authName = auth_name;
+
+        link = dlinkNodeNew();
+
+        dlinkAddTail(auth_config, link, &config);
+    }
+
+    return auth_config;
+}
+
+void
+digestScheme::stats(StoreEntry * sentry)
+{
+    AuthDigestConfig *auth_config;
+
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthDigestConfig *>(link->data);
+        if (auth_config->authdigest_initialised)
+            helperStats(sentry, auth_config->digestauthenticators, "Digest Authenticator Statistics");
+        link = link->next;
+    }
+}

=== modified file 'src/auth/digest/auth_digest.h'
--- old/src/auth/digest/auth_digest.h	2009-12-16 03:46:59 +0000
+++ new/src/auth/digest/auth_digest.h	2010-05-28 15:44:12 +0000
@@ -63,10 +63,10 @@
     virtual int authenticated() const;
     virtual void authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type);
     virtual int module_direction();
-    virtual void addHeader(HttpReply * rep, int accel);
+    virtual void addHeader(AuthConfig *scheme, HttpReply * rep, int accel);
 #if WAITING_FOR_TE
 
-    virtual void addTrailer(HttpReply * rep, int accel);
+    virtual void addTrailer(AuthConfig *scheme, HttpReply * rep, int accel);
 #endif
 
     virtual void module_start(RH *, void *);
@@ -153,6 +153,12 @@
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
+    virtual const char * name() const {return authName.termedBuf();}
+    int authDigestNonceIsStale(digest_nonce_h * nonce);
+    int authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]);
+    void authenticateDigestNonceSetup(void);
+    int authDigestNonceLastRequest(digest_nonce_h * nonce);
+    AuthUserRequest *authDigestLogUsername(char *username, AuthDigestUserRequest *auth_user_request);
     HelperChildConfig authenticateChildren;
     char *digestAuthRealm;
     wordlist *authenticate;
@@ -163,6 +169,9 @@
     int CheckNonceCount;
     int PostWorkaround;
     int utf8;
+    String authName;
+    helper *digestauthenticators;
+    int authdigest_initialised;
 };
 
 typedef class AuthDigestConfig auth_digest_config;

=== modified file 'src/auth/digest/digestScheme.cc'
--- old/src/auth/digest/digestScheme.cc	2009-05-20 06:59:04 +0000
+++ new/src/auth/digest/digestScheme.cc	2010-05-28 08:26:03 +0000
@@ -44,6 +44,7 @@
 digestScheme::digestScheme()
 {
     AddScheme(*this);
+    config.head = config.tail = NULL;
 }
 
 char const *

=== modified file 'src/auth/digest/digestScheme.h'
--- old/src/auth/digest/digestScheme.h	2009-05-20 06:59:04 +0000
+++ new/src/auth/digest/digestScheme.h	2010-05-28 15:42:54 +0000
@@ -49,13 +49,17 @@
     /* per scheme */
     virtual char const *type () const;
     virtual void done();
-    virtual AuthConfig *createConfig();
+    virtual AuthConfig *createConfig(const char *);
+    virtual AuthConfig *findConfig(const char *);
+    virtual void stats(StoreEntry*);
     /* Not implemented */
     digestScheme (digestScheme const &);
     digestScheme &operator=(digestScheme const &);
 
 private:
     static digestScheme *_instance;
+    /* Configs for this scheme */
+    dlink_list config;
 };
 
 #endif /* SQUID_DIGESTSCHEME_H */

=== modified file 'src/auth/negotiate/auth_negotiate.cc'
--- old/src/auth/negotiate/auth_negotiate.cc	2010-02-13 09:16:30 +0000
+++ new/src/auth/negotiate/auth_negotiate.cc	2010-05-28 15:57:31 +0000
@@ -74,18 +74,9 @@
 static HLPSCB authenticateNegotiateHandleReply;
 static AUTHSSTATS authenticateNegotiateStats;
 
-/// \ingroup AuthNegotiateInternal
-static statefulhelper *negotiateauthenticators = NULL;
-
 CBDATA_TYPE(authenticateStateData);
 
 /// \ingroup AuthNegotiateInternal
-static int authnegotiate_initialised = 0;
-
-/// \ingroup AuthNegotiateInternal
-static auth_negotiate_config negotiateConfig;
-
-/// \ingroup AuthNegotiateInternal
 static hash_table *proxy_auth_cache = NULL;
 
 /*
@@ -104,6 +95,17 @@
     /* TODO: this should be a Config call. */
     debugs(29, 2, "negotiateScheme::done: shutting down Negotiate authentication.");
 
+    /* TODO: call AuthNegotiateConfig::done() for all Config?? */
+
+    debugs(29, 2, "negotiateScheme::done: Negotiate authentication Shutdown.");
+}
+
+void
+AuthNegotiateConfig::done()
+{
+    if (authenticate)
+        wordlistDestroy(&authenticate);
+
     if (negotiateauthenticators)
         helperStatefulShutdown(negotiateauthenticators);
 
@@ -114,15 +116,6 @@
 
     delete negotiateauthenticators;
     negotiateauthenticators = NULL;
-
-    debugs(29, 2, "negotiateScheme::done: Negotiate authentication Shutdown.");
-}
-
-void
-AuthNegotiateConfig::done()
-{
-    if (authenticate)
-        wordlistDestroy(&authenticate);
 }
 
 void
@@ -142,7 +135,7 @@
 
 }
 
-AuthNegotiateConfig::AuthNegotiateConfig() : authenticateChildren(20), keep_alive(1)
+AuthNegotiateConfig::AuthNegotiateConfig() : authenticateChildren(20), keep_alive(1), authnegotiate_initialised(0), negotiateauthenticators(NULL)
 { }
 
 void
@@ -543,7 +536,7 @@
 static void
 authenticateNegotiateStats(StoreEntry * sentry)
 {
-    helperStatefulStats(sentry, negotiateauthenticators, "Negotiate Authenticator Statistics");
+    negotiateScheme::GetInstance().stats(sentry);
 }
 
 
@@ -565,7 +558,7 @@
 
     debugs(29, 8, "AuthNegotiateUserRequest::module_start: auth state is '" << auth_state << "'");
 
-    if (negotiateConfig.authenticate == NULL) {
+    if (dynamic_cast<AuthNegotiateConfig *>(negotiate_user->config)->authenticate == NULL) {
         debugs(29, 0, "AuthNegotiateUserRequest::module_start: no Negotiate program specified.");
         handler(data, NULL);
         return;
@@ -586,7 +579,7 @@
     waiting = 1;
 
     safe_free(client_blob);
-    helperStatefulSubmit(negotiateauthenticators, buf, authenticateNegotiateHandleReply, r, authserver);
+    helperStatefulSubmit(dynamic_cast<AuthNegotiateConfig *>(negotiate_user->config)->negotiateauthenticators, buf, authenticateNegotiateHandleReply, r, authserver);
 }
 
 /**
@@ -632,11 +625,12 @@
 AuthUserRequest *
 AuthNegotiateConfig::decode(char const *proxy_auth)
 {
-    NegotiateUser *newUser = new NegotiateUser(&negotiateConfig);
+    NegotiateUser *newUser = new NegotiateUser(this);
     AuthNegotiateUserRequest *auth_user_request = new AuthNegotiateUserRequest ();
     assert(auth_user_request->user() == NULL);
     auth_user_request->user(newUser);
     auth_user_request->user()->auth_type = AUTH_NEGOTIATE;
+    auth_user_request->user()->authname(name());
     auth_user_request->user()->addRequest(auth_user_request);
 
     /* all we have to do is identify that it's Negotiate - the helper does the rest */
@@ -804,10 +798,41 @@
     proxy_auth_list.head = proxy_auth_list.tail = NULL;
 }
 
-AuthConfig *
-negotiateScheme::createConfig()
-{
-    return &negotiateConfig;
+
+AuthConfig *
+negotiateScheme::findConfig(char const *auth_name)
+{
+    AuthNegotiateConfig *auth_config;
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthNegotiateConfig *>(link->data);
+        if (strcmp(auth_name, auth_config->name()) == 0)
+            return auth_config;
+        link = link->next;
+    }
+
+    return NULL;
+}
+
+AuthConfig *
+negotiateScheme::createConfig(char const *auth_name)
+{
+    AuthNegotiateConfig *auth_config;
+    dlink_node *link = config.head;
+
+    auth_config = dynamic_cast<AuthNegotiateConfig *>(findConfig(auth_name));
+
+    if (!auth_config) {
+        auth_config = new AuthNegotiateConfig();
+        auth_config->authName = auth_name;
+
+        link = dlinkNodeNew();
+
+        dlinkAddTail(auth_config, link, &config);
+    }
+
+    return auth_config;
 }
 
 const char *
@@ -816,3 +841,17 @@
     return NULL;
 }
 
+void
+negotiateScheme::stats(StoreEntry * sentry)
+{
+    AuthNegotiateConfig *auth_config;
+
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthNegotiateConfig *>(link->data);
+        if (auth_config->authnegotiate_initialised)
+            helperStats(sentry, auth_config->negotiateauthenticators, "Basic Authenticator Statistics");
+        link = link->next;
+    }
+}

=== modified file 'src/auth/negotiate/auth_negotiate.h'
--- old/src/auth/negotiate/auth_negotiate.h	2009-12-16 03:46:59 +0000
+++ new/src/auth/negotiate/auth_negotiate.h	2010-05-28 15:37:03 +0000
@@ -130,9 +130,13 @@
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
+    virtual const char * name() const {return authName;}
     HelperChildConfig authenticateChildren;
     int keep_alive;
     wordlist *authenticate;
+    char const *authName;
+    int authnegotiate_initialised;
+    statefulhelper *negotiateauthenticators;
 };
 
 /// \ingroup AuthNegotiateAPI

=== modified file 'src/auth/negotiate/negotiateScheme.cc'
--- old/src/auth/negotiate/negotiateScheme.cc	2009-05-20 06:59:04 +0000
+++ new/src/auth/negotiate/negotiateScheme.cc	2010-05-28 08:30:31 +0000
@@ -44,6 +44,7 @@
 negotiateScheme::negotiateScheme()
 {
     AddScheme(*this);
+    config.head = config.tail = NULL;
 }
 
 char const *

=== modified file 'src/auth/negotiate/negotiateScheme.h'
--- old/src/auth/negotiate/negotiateScheme.h	2009-05-20 06:59:04 +0000
+++ new/src/auth/negotiate/negotiateScheme.h	2010-05-28 15:37:00 +0000
@@ -49,13 +49,17 @@
     /* per scheme */
     virtual char const *type () const;
     virtual void done();
-    virtual AuthConfig *createConfig();
+    virtual AuthConfig *findConfig(char const*);
+    virtual AuthConfig *createConfig(char const*);
+    virtual void stats(StoreEntry*);
     /* Not implemented */
     negotiateScheme (negotiateScheme const &);
     negotiateScheme &operator=(negotiateScheme const &);
 
 private:
     static negotiateScheme *_instance;
+    /* Configs for this scheme */
+    dlink_list config;
 };
 
 #endif /* SQUID_negotiateSCHEME_H */

=== modified file 'src/auth/ntlm/auth_ntlm.cc'
--- old/src/auth/ntlm/auth_ntlm.cc	2010-02-13 09:16:30 +0000
+++ new/src/auth/ntlm/auth_ntlm.cc	2010-05-28 14:57:06 +0000
@@ -62,14 +62,8 @@
 static HLPSCB authenticateNTLMHandleReply;
 static AUTHSSTATS authenticateNTLMStats;
 
-static statefulhelper *ntlmauthenticators = NULL;
-
 CBDATA_TYPE(authenticateStateData);
 
-static int authntlm_initialised = 0;
-
-static auth_ntlm_config ntlmConfig;
-
 static hash_table *proxy_auth_cache = NULL;
 
 /*
@@ -85,6 +79,18 @@
     /* TODO: this should be a Config call. */
     debugs(29, 2, "ntlmScheme::done: shutting down NTLM authentication.");
 
+    /* TODO: Should this call all the AuthNTLMConfig::done() */
+
+    debugs(29, 2, "ntlmScheme::done: NTLM authentication Shutdown.");
+}
+
+/* free any allocated configuration details */
+void
+AuthNTLMConfig::done()
+{
+    if (authenticate)
+        wordlistDestroy(&authenticate);
+
     if (ntlmauthenticators)
         helperStatefulShutdown(ntlmauthenticators);
 
@@ -95,16 +101,6 @@
 
     delete ntlmauthenticators;
     ntlmauthenticators = NULL;
-
-    debugs(29, 2, "ntlmScheme::done: NTLM authentication Shutdown.");
-}
-
-/* free any allocated configuration details */
-void
-AuthNTLMConfig::done()
-{
-    if (authenticate)
-        wordlistDestroy(&authenticate);
 }
 
 void
@@ -124,7 +120,7 @@
 
 }
 
-AuthNTLMConfig::AuthNTLMConfig() : authenticateChildren(20), keep_alive(1)
+AuthNTLMConfig::AuthNTLMConfig() : authenticateChildren(20), keep_alive(1), ntlmauthenticators(NULL), authntlm_initialised(0)
 { }
 
 void
@@ -459,7 +455,7 @@
 static void
 authenticateNTLMStats(StoreEntry * sentry)
 {
-    helperStatefulStats(sentry, ntlmauthenticators, "NTLM Authenticator Statistics");
+    ntlmScheme::GetInstance().stats(sentry);
 }
 
 
@@ -481,7 +477,7 @@
 
     debugs(29, 8, "AuthNTLMUserRequest::module_start: auth state is '" << auth_state << "'");
 
-    if (ntlmConfig.authenticate == NULL) {
+    if (dynamic_cast<AuthNTLMConfig *>(ntlm_user->config)->authenticate == NULL) {
         debugs(29, 0, "AuthNTLMUserRequest::module_start: no NTLM program specified.");
         handler(data, NULL);
         return;
@@ -502,7 +498,7 @@
     waiting = 1;
 
     safe_free(client_blob);
-    helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, authserver);
+    helperStatefulSubmit(dynamic_cast<AuthNTLMConfig *>(ntlm_user->config)->ntlmauthenticators, buf, authenticateNTLMHandleReply, r, authserver);
 }
 
 /**
@@ -549,10 +545,11 @@
 AuthUserRequest *
 AuthNTLMConfig::decode(char const *proxy_auth)
 {
-    NTLMUser *newUser = new NTLMUser(&ntlmConfig);
+    NTLMUser *newUser = new NTLMUser(this);
     AuthNTLMUserRequest *auth_user_request = new AuthNTLMUserRequest ();
     assert(auth_user_request->user() == NULL);
     auth_user_request->user(newUser);
+    auth_user_request->user()->authname(name());
     auth_user_request->user()->auth_type = AUTH_NTLM;
     auth_user_request->user()->addRequest(auth_user_request);
 
@@ -720,9 +717,39 @@
 }
 
 AuthConfig *
-ntlmScheme::createConfig()
-{
-    return &ntlmConfig;
+ntlmScheme::findConfig(char const *auth_name)
+{
+    AuthNTLMConfig *auth_config;
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthNTLMConfig *>(link->data);
+        if (strcmp(auth_name, auth_config->name()) == 0)
+            return auth_config;
+        link = link->next;
+    }
+
+    return NULL;
+}
+
+AuthConfig *
+ntlmScheme::createConfig(char const *auth_name)
+{
+    AuthNTLMConfig *auth_config;
+    dlink_node *link = config.head;
+
+    auth_config = dynamic_cast<AuthNTLMConfig *>(findConfig(auth_name));
+
+    if (!auth_config) {
+        auth_config = new AuthNTLMConfig();
+        auth_config->authName = auth_name;
+
+        link = dlinkNodeNew();
+
+        dlinkAddTail(auth_config, link, &config);
+    }
+
+    return auth_config;
 }
 
 const char *
@@ -730,3 +757,17 @@
 {
     return NULL;
 }
+
+void
+ntlmScheme::stats(StoreEntry * sentry)
+{
+    AuthNTLMConfig *auth_config;
+    dlink_node *link = config.head;
+
+    while (link) {
+        auth_config = static_cast<AuthNTLMConfig *>(link->data);
+        if (auth_config->authntlm_initialised)
+            helperStatefulStats(sentry, auth_config->ntlmauthenticators, "NTLM Authenticator Statistics");
+        link = link->next;
+    }
+}

=== modified file 'src/auth/ntlm/auth_ntlm.h'
--- old/src/auth/ntlm/auth_ntlm.h	2009-12-16 03:46:59 +0000
+++ new/src/auth/ntlm/auth_ntlm.h	2010-05-28 14:55:52 +0000
@@ -115,9 +115,13 @@
     virtual void parse(AuthConfig *, int, char *);
     virtual void registerWithCacheManager(void);
     virtual const char * type() const;
+    virtual const char * name() const {return authName.termedBuf();}
     HelperChildConfig authenticateChildren;
     int keep_alive;
     wordlist *authenticate;
+    String authName;
+    statefulhelper *ntlmauthenticators;
+    int authntlm_initialised;
 };
 
 typedef class AuthNTLMConfig auth_ntlm_config;

=== modified file 'src/auth/ntlm/ntlmScheme.cc'
--- old/src/auth/ntlm/ntlmScheme.cc	2009-05-20 06:59:04 +0000
+++ new/src/auth/ntlm/ntlmScheme.cc	2010-05-27 15:17:35 +0000
@@ -44,6 +44,7 @@
 ntlmScheme::ntlmScheme()
 {
     AddScheme(*this);
+    config.head = config.tail = NULL;
 }
 
 char const *

=== modified file 'src/auth/ntlm/ntlmScheme.h'
--- old/src/auth/ntlm/ntlmScheme.h	2009-05-20 06:59:04 +0000
+++ new/src/auth/ntlm/ntlmScheme.h	2010-05-28 15:36:36 +0000
@@ -49,13 +49,17 @@
     /* per scheme */
     virtual char const *type () const;
     virtual void done();
-    virtual AuthConfig *createConfig();
+    virtual AuthConfig *findConfig(const char*);
+    virtual AuthConfig *createConfig(const char*);
+    virtual void stats(StoreEntry*);
     /* Not implemented */
     ntlmScheme (ntlmScheme const &);
     ntlmScheme &operator=(ntlmScheme const &);
 
 private:
     static ntlmScheme *_instance;
+    /* Configs for this scheme */
+    dlink_list config;
 };
 
 #endif /* SQUID_ntlmSCHEME_H */

=== modified file 'src/cache_cf.cc'
--- old/src/cache_cf.cc	2010-05-26 03:06:02 +0000
+++ new/src/cache_cf.cc	2010-05-27 10:21:13 +0000
@@ -1438,17 +1438,30 @@
 static void
 parse_authparam(authConfig * config)
 {
-    char *type_str;
+    char const *auth_name;
+    char const *type_str;
     char *param_str;
 
-    if ((type_str = strtok(NULL, w_space)) == NULL)
+    if ((auth_name = strtok(NULL, w_space)) == NULL)
         self_destruct();
 
+    if (strcasecmp(auth_name, "-n") == 0) {
+        if ((auth_name = strtok(NULL, w_space)) == NULL)
+            self_destruct();
+
+        if ((type_str = strtok(NULL, w_space)) == NULL)
+            self_destruct();
+    }
+    else {
+        type_str = auth_name;
+        auth_name = "default";
+    }
+
     if ((param_str = strtok(NULL, w_space)) == NULL)
         self_destruct();
 
     /* find a configuration for the scheme */
-    AuthConfig *scheme = AuthConfig::Find (type_str);
+    AuthConfig *scheme = AuthConfig::Find (auth_name, type_str);
 
     if (scheme == NULL) {
         /* Create a configuration */
@@ -1459,7 +1472,7 @@
             return;
         }
 
-        config->push_back(theScheme->createConfig());
+        config->push_back(theScheme->createConfig(auth_name));
         scheme = config->back();
         assert (scheme);
     }

=== modified file 'src/external_acl.cc'
--- old/src/external_acl.cc	2010-04-17 02:29:04 +0000
+++ new/src/external_acl.cc	2010-05-13 10:43:20 +0000
@@ -123,6 +123,8 @@
 
     bool require_auth;
 
+    char *auth_name;
+
     enum {
         QUOTE_METHOD_SHELL = 1,
         QUOTE_METHOD_URL
@@ -197,6 +199,7 @@
 {
     external_acl *p = static_cast<external_acl *>(data);
     safe_free(p->name);
+    safe_free(p->auth_name);
 
     while (p->format) {
         external_acl_format *f = p->format;
@@ -392,9 +395,22 @@
             parse_header_token(format, (token+3), _external_acl_format::EXT_ACL_HEADER_REQUEST);
         } else if (strncmp(token, "%<{", 3) == 0) {
             parse_header_token(format, (token+3), _external_acl_format::EXT_ACL_HEADER_REPLY);
-        } else if (strcmp(token, "%LOGIN") == 0) {
+        } else if (strncmp(token, "%LOGIN", 6) == 0) {
             format->type = _external_acl_format::EXT_ACL_LOGIN;
             a->require_auth = true;
+
+            if (token[6] == '{') {
+                char *end = strchr(token+6, '}');
+                if (end)
+                    *end = '\0';
+                else
+                    self_destruct();
+
+                a->auth_name = xstrdup(token+7);
+            }
+            else {
+                a->auth_name = xstrdup("default");
+            }
         }
 
 #if USE_IDENT
@@ -1529,3 +1545,9 @@
 {
     return data->def->require_auth;
 }
+
+char const*
+ACLExternal::proxyAuthName() const
+{
+    return data->def->auth_name;
+}

