=== 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 +{ +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 +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 +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 *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(old.data->clone())), type_(old.type_) {} ACLProxyAuth & ACLProxyAuth::operator= (ACLProxyAuth const &rhs) { - data = rhs.data->clone(); + data = dynamic_cast(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 *); + 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 *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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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; +}