]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
RefCount AuthUser and children
authorAmos Jeffries <squid3@treenet.co.nz>
Sun, 11 Apr 2010 09:02:42 +0000 (21:02 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Sun, 11 Apr 2010 09:02:42 +0000 (21:02 +1200)
Also adds CacheMgr "username_cache" display page to view the
currently cached usernames and how long their TTLs are for.

34 files changed:
src/DelayUser.cc
src/DelayUser.h
src/Makefile.am
src/acl/FilledChecklist.cc
src/auth/Acl.cc
src/auth/AuthAclState.h [new file with mode: 0644]
src/auth/AuthType.h [new file with mode: 0644]
src/auth/Gadgets.cc
src/auth/Gadgets.h
src/auth/Makefile.am
src/auth/User.cc
src/auth/User.cci
src/auth/User.h
src/auth/UserRequest.cc
src/auth/UserRequest.h
src/auth/basic/auth_basic.cc
src/auth/basic/auth_basic.h
src/auth/basic/basicUserRequest.cc
src/auth/digest/auth_digest.cc
src/auth/digest/auth_digest.h
src/auth/digest/digestScheme.cc
src/auth/digest/digestScheme.h
src/auth/digest/digestUserRequest.cc
src/auth/enums.h [deleted file]
src/auth/negotiate/auth_negotiate.cc
src/auth/negotiate/auth_negotiate.h
src/auth/negotiate/negotiateUserRequest.cc
src/auth/negotiate/negotiateUserRequest.h
src/auth/ntlm/auth_ntlm.cc
src/auth/ntlm/auth_ntlm.h
src/auth/ntlm/ntlmUserRequest.cc
src/client_side.h
src/stat.cc
src/typedefs.h

index 543a297c5a4f5e6e60ce521e50c43c773bc939e9..7e6e42cc62b824f8af8a6e637f7c235e4191b670 100644 (file)
@@ -180,22 +180,20 @@ DelayUserBucket::operator new(size_t size)
 }
 
 void
-DelayUserBucket::operator delete (void *address)
+DelayUserBucket::operator delete(void *address)
 {
-    DelayPools::MemoryUsed -= sizeof (DelayUserBucket);
-    ::operator delete (address);
+    DelayPools::MemoryUsed -= sizeof(DelayUserBucket);
+    ::operator delete(address);
 }
 
-DelayUserBucket::DelayUserBucket(AuthUser *aUser) : authUser (aUser)
+DelayUserBucket::DelayUserBucket(AuthUser::Pointer aUser) : authUser(aUser)
 {
     debugs(77, 3, "DelayUserBucket::DelayUserBucket");
-
-    authUser->lock();
 }
 
 DelayUserBucket::~DelayUserBucket()
 {
-    authUser->unlock();
+    authUser = NULL;
     debugs(77, 3, "DelayUserBucket::~DelayUserBucket");
 }
 
@@ -203,10 +201,10 @@ void
 DelayUserBucket::stats (StoreEntry *entry) const
 {
     storeAppendPrintf(entry, " %s:", authUser->username());
-    theBucket.stats (entry);
+    theBucket.stats(entry);
 }
 
-DelayUser::Id::Id(DelayUser::Pointer aDelayUser,AuthUser *aUser) : theUser(aDelayUser)
+DelayUser::Id::Id(DelayUser::Pointer aDelayUser, AuthUser::Pointer aUser) : theUser(aDelayUser)
 {
     theBucket = new DelayUserBucket(aUser);
     DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp);
index 885389e4d5139e4c5e827c4f032d7240372a9692..7c41f55e9bfb72d2e08bdfff3ac11f28cd923921 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "squid.h"
 #include "auth/Gadgets.h"
+#include "auth/User.h"
 #include "CompositePoolNode.h"
 #include "DelayIdComposite.h"
 #include "DelayBucket.h"
@@ -59,10 +60,10 @@ public:
     void operator delete (void *);
 
     void stats(StoreEntry *)const;
-    DelayUserBucket(AuthUser *);
+    DelayUserBucket(AuthUser::Pointer);
     ~DelayUserBucket();
     DelayBucket theBucket;
-    AuthUser *authUser;
+    AuthUser::Pointer authUser;
 };
 
 /// \ingroup DelayPoolsAPI
@@ -91,7 +92,7 @@ private:
     public:
         void *operator new(size_t);
         void operator delete (void *);
-        Id (RefCount<DelayUser>, AuthUser *);
+        Id(RefCount<DelayUser>, AuthUser::Pointer);
         ~Id();
         virtual int bytesWanted (int min, int max) const;
         virtual void bytesIn(int qty);
index 0def6223135d246ac70c787d5c8bd3f1ed2356a2..88f93ab971f55a5f0fcfe4862de8b08ae7b3f4a3 100644 (file)
@@ -154,8 +154,6 @@ noinst_LTLIBRARIES = libsquid.la
 
 # libraries used by many targets
 COMMON_LIBS = \
-       base/libbase.la \
-       libsquid.la \
        auth/libacls.la \
        ident/libident.la \
        acl/libacls.la \
@@ -163,6 +161,8 @@ COMMON_LIBS = \
        acl/libstate.la \
        auth/libauth.la \
        acl/libapi.la \
+       base/libbase.la \
+       libsquid.la \
        ip/libip.la \
        fs/libfs.la
 
@@ -755,7 +755,7 @@ snmp_core.o snmp_agent.o: ../snmplib/libsnmp.a $(top_srcdir)/include/cache_snmp.
 globals.cc: globals.h mk-globals-c.awk
        $(AWK) -f $(srcdir)/mk-globals-c.awk < $(srcdir)/globals.h > $@
 
-## Generate files containing strng arrays for various enums....
+## Generate files containing string arrays for various enums....
 hier_code.cc: hier_code.h mk-string-arrays.awk
        $(AWK) -f $(srcdir)/mk-string-arrays.awk < $(srcdir)/hier_code.h > $@
 
@@ -981,6 +981,7 @@ tests_testAuth_SOURCES = \
        ConfigParser.cc \
        HelperChildConfig.h \
        HelperChildConfig.cc \
+       ip/stubQosConfig.cc \
        tests/stub_acl.cc tests/stub_cache_cf.cc \
        tests/stub_helper.cc cbdata.cc String.cc \
        tests/stub_store.cc HttpHeaderTools.cc HttpHeader.cc mem.cc ClientInfo.h \
index f59e5f1aea228098e6487d101f7cbf475ab19d32..92f3ba772d3fd6e678dac1a097a9869b6b9a806c 100644 (file)
@@ -30,7 +30,7 @@ ACLFilledChecklist::authenticated()
 
     /* get authed here */
     /* Note: this fills in auth_user_request when applicable */
-    auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr);
+    AuthAclState result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr);
     switch (result) {
 
     case AUTH_ACL_CANNOT_AUTHENTICATE:
index 6952fbc76d2cb1c5389183221b2998db63a097b2..6e43bca198af9181add2a3d9ccbd1ce2686f3919 100644 (file)
@@ -32,7 +32,7 @@ AuthenticateAcl(ACLChecklist *ch)
 
     /* get authed here */
     /* Note: this fills in auth_user_request when applicable */
-    const auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(
+    const AuthAclState result = AuthUserRequest::tryToAuthenticateAndSetAuthUser(
                                   &checklist->auth_user_request, headertype, request,
                                   checklist->conn(), checklist->src_addr);
     switch (result) {
diff --git a/src/auth/AuthAclState.h b/src/auth/AuthAclState.h
new file mode 100644 (file)
index 0000000..10d6390
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _SQUID__SRC_AUTH_AUTHACLSTATE_H
+#define _SQUID__SRC_AUTH_AUTHACLSTATE_H
+
+typedef enum {
+    AUTH_ACL_CHALLENGE = -2,
+    AUTH_ACL_HELPER = -1,
+    AUTH_ACL_CANNOT_AUTHENTICATE = 0,
+    AUTH_AUTHENTICATED = 1
+} AuthAclState;
+
+#endif
diff --git a/src/auth/AuthType.h b/src/auth/AuthType.h
new file mode 100644 (file)
index 0000000..eec96b7
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _SQUID__SRC_AUTH_AUTHTYPE_H
+#define _SQUID__SRC_AUTH_AUTHTYPE_H
+
+typedef enum {
+    AUTH_UNKNOWN,               /* default */
+    AUTH_BASIC,
+    AUTH_NTLM,
+    AUTH_DIGEST,
+    AUTH_NEGOTIATE,
+    AUTH_BROKEN                 /* known type, but broken data */
+} AuthType;
+
+extern const char *AuthType_str[];
+
+#endif
index 2748630ab3ef864e479eb3fe24acade23891dd26..424b2b3e633c0a15e1c9744c7989d7c50db971ed 100644 (file)
@@ -120,23 +120,6 @@ authenticateShutdown(void)
     }
 }
 
-/**
- \retval 0 not in use
- \retval ? in use
- */
-int
-authenticateAuthUserInuse(AuthUser * auth_user)
-{
-    assert(auth_user != NULL);
-    return auth_user->references;
-}
-
-void
-authenticateAuthUserMerge(AuthUser * from, AuthUser * to)
-{
-    to->absorb (from);
-}
-
 /**
  * Cleans all config-dependent data from the auth_user cache.
  \note It DOES NOT Flush the user cache.
@@ -145,7 +128,7 @@ void
 authenticateUserCacheRestart(void)
 {
     AuthUserHashPointer *usernamehash;
-    AuthUser *auth_user;
+    AuthUser::Pointer auth_user;
     debugs(29, 3, HERE << "Clearing config dependent cache data.");
     hash_first(proxy_auth_username_cache);
 
@@ -155,35 +138,24 @@ authenticateUserCacheRestart(void)
     }
 }
 
-
+// TODO: remove this wrapper. inline the actions.
 void
 AuthUserHashPointer::removeFromCache(void *usernamehash_p)
 {
     AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(usernamehash_p);
-    AuthUser *auth_user = usernamehash->auth_user;
-
-    if ((authenticateAuthUserInuse(auth_user) - 1))
-        debugs(29, 1, "AuthUserHashPointer::removeFromCache: entry in use - not freeing");
-
-    auth_user->unlock();
-
-    /** \todo change behaviour - we remove from the auth user list here, and then unlock, and the
-     * delete ourselves.
-     */
+    hash_remove_link(proxy_auth_username_cache, (hash_link *)usernamehash);
+    delete usernamehash;
 }
 
-AuthUserHashPointer::AuthUserHashPointer(AuthUser * anAuth_user):
+AuthUserHashPointer::AuthUserHashPointer(AuthUser::Pointer anAuth_user):
         auth_user(anAuth_user)
 {
     key = (void *)anAuth_user->username();
     next = NULL;
     hash_join(proxy_auth_username_cache, (hash_link *) this);
-
-    /** lock for presence in the cache */
-    auth_user->lock();
 }
 
-AuthUser *
+AuthUser::Pointer
 AuthUserHashPointer::user() const
 {
     return auth_user;
index 2e94fc2f0d0c9a16404948a305b5d6caddfda07d..96da2c09a837421f6020d0400a3e0f4b65b8a8c1 100644 (file)
@@ -36,6 +36,7 @@
 #include "hash.h"
 #include "MemPool.h"
 #include "auth/Config.h"
+#include "auth/User.h"
 
 class AuthUser;
 
@@ -52,15 +53,15 @@ struct AuthUserHashPointer : public hash_link {
     /* first two items must be same as hash_link */
 
 public:
-    static void removeFromCache (void *anAuthUserHashPointer);
+    static void removeFromCache(void *anAuthUserHashPointer);
     MEMPROXY_CLASS(AuthUserHashPointer);
 
-    AuthUserHashPointer(AuthUser *);
+    AuthUserHashPointer(AuthUser::Pointer );
 
-    AuthUser *user() const;
+    AuthUser::Pointer user() const;
 
 private:
-    AuthUser *auth_user;
+    AuthUser::Pointer auth_user;
 };
 
 MEMPROXY_CLASS_INLINE(AuthUserHashPointer);
@@ -75,19 +76,10 @@ class StoreEntry;
  */
 typedef void AUTHSSTATS(StoreEntry *);
 
-/**
- \ingroup AuthAPI
- * subsumed by the C++ interface
- \todo does 'subsumed' mean deprecated use a C++ API call?
- */
-extern void authenticateAuthUserMerge(AuthUser *, AuthUser *);
-
 /// \ingroup AuthAPI
 extern void authenticateInit(Auth::authConfig *);
 /// \ingroup AuthAPI
 extern void authenticateShutdown(void);
-/// \ingroup AuthAPI
-extern int authenticateAuthUserInuse(AuthUser * auth_user);
 
 /// \ingroup AuthAPI
 extern void authenticateFreeProxyAuthUserACLResults(void *data);
index becf34eba6689e41c36132f029b0ad42b2fba16a..470ece27795abbbe393a1c450db586b22b47bda9 100644 (file)
@@ -8,20 +8,21 @@ EXTRA_LTLIBRARIES = libbasic.la libdigest.la libntlm.la libnegotiate.la
 
 ## authentication framework; this library is always built
 libauth_la_SOURCES = \
+       AuthType.h \
+       AuthType.cc \
        Config.cc \
        Config.h \
-       enums.h \
+       Gadgets.cc \
+       Gadgets.h \
        Scheme.cc \
        Scheme.h \
+       State.h \
+       State.cc \
        User.h \
        User.cci \
        User.cc \
        UserRequest.h \
-       UserRequest.cc \
-       Gadgets.cc \
-       Gadgets.h \
-       State.h \
-       State.cc
+       UserRequest.cc
 
 libauth_la_LIBADD = $(AUTH_LIBS_TO_BUILD)
 libauth_la_DEPENDENCIES = $(AUTH_LIBS_TO_BUILD)
@@ -34,7 +35,8 @@ libacls_la_SOURCES = \
        AclMaxUserIp.cc \
        AclMaxUserIp.h \
        AclProxyAuth.cc \
-       AclProxyAuth.h
+       AclProxyAuth.h \
+       AuthAclState.h
 
 libbasic_la_SOURCES = \
        basic/basicScheme.cc \
@@ -68,6 +70,9 @@ libnegotiate_la_SOURCES = \
        negotiate/negotiateUserRequest.cc \
        negotiate/negotiateUserRequest.h
 
+AuthType.cc: AuthType.h $(top_srcdir)/src/mk-string-arrays.awk
+       $(AWK) -f $(top_srcdir)/src/mk-string-arrays.awk < $(srcdir)/AuthType.h > $@
+
 
 TESTS += testHeaders
 
index cceb296ad751a6b441a833a6dc80dac4a85e8679..0b1a8d8e2aa9fea93d0aba29a0ac8646603154f5 100644 (file)
 #include "acl/Gadgets.h"
 #include "event.h"
 #include "SquidTime.h"
+#include "Store.h"
 
 #ifndef _USE_INLINE_
 #include "auth/User.cci"
 #endif
 
 // This should be converted into a pooled type. Does not need to be cbdata
-CBDATA_TYPE(auth_user_ip_t);
-
-AuthUser::AuthUser (AuthConfig *aConfig) :
-        auth_type (AUTH_UNKNOWN), config(aConfig),
-        usernamehash (NULL), ipcount (0), expiretime (0), references (0), username_(NULL)
+CBDATA_TYPE(AuthUserIP);
+
+AuthUser::AuthUser(AuthConfig *aConfig) :
+        auth_type(AUTH_UNKNOWN),
+        config(aConfig),
+        usernamehash(NULL),
+        ipcount(0),
+        expiretime(0),
+        username_(NULL)
 {
     proxy_auth_list.head = proxy_auth_list.tail = NULL;
     proxy_match_cache.head = proxy_match_cache.tail = NULL;
@@ -60,7 +65,7 @@ AuthUser::AuthUser (AuthConfig *aConfig) :
 #if USER_REQUEST_LOOP_DEAD
     requests.head = requests.tail = NULL;
 #endif
-    debugs(29, 5, "AuthUser::AuthUser: Initialised auth_user '" << this << "' with refcount '" << references << "'.");
+    debugs(29, 5, "AuthUser::AuthUser: Initialised auth_user '" << this << "'.");
 }
 
 /**
@@ -71,13 +76,23 @@ AuthUser::AuthUser (AuthConfig *aConfig) :
  * related scheme data itself.
  */
 void
-AuthUser::absorb(AuthUser *from)
+AuthUser::absorb(AuthUser::Pointer from)
 {
+
+    /* RefCount children CANNOT be merged like this. The external AuthUser::Pointer's cannot be changed. */
+
+    /* check that we only have the two references:
+     * 1) our function scope
+     * 2) the parsing function scope)
+     */
+    assert(from->RefCountCount() == 2);
+
     /*
-     * XXX combine two authuser structs. Incomplete: it should merge
-     * in hash references too and ask the module to merge in scheme
-     * data
+     * XXX Incomplete: it should merge in hash references too and ask the module to merge in scheme data
+     *  dlink_list proxy_auth_list;
+     *  dlink_list proxy_match_cache;
      */
+
     debugs(29, 5, "authenticateAuthUserMerge auth_user '" << from << "' into auth_user '" << this << "'.");
 #if USER_REQUEST_LOOP_DEAD
     dlink_node *link = from->requests.head;
@@ -95,15 +110,60 @@ AuthUser::absorb(AuthUser *from)
     }
 #endif /* USER_REQUEST_LOOP_DEAD */
 
-    references += from->references;
-    from->references = 0;
-    delete from;
+    /* absorb the list of IP address sources (for max_user_ip controls) */
+    AuthUserIP *new_ipdata;
+    while (from->ip_list.head != NULL) {
+        new_ipdata = static_cast<AuthUserIP *>(from->ip_list.head->data);
+
+        /* If this IP has expired - ignore the expensive merge actions. */
+        if (new_ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
+            /* This IP has expired - remove from the source list */
+            dlinkDelete(&new_ipdata->node, &(from->ip_list));
+            cbdataFree(new_ipdata);
+            /* catch incipient underflow */
+            from->ipcount--;
+        } else {
+            /* add to our list. replace if already present. */
+            AuthUserIP *ipdata = static_cast<AuthUserIP *>(ip_list.head->data);
+            bool found = false;
+            while (ipdata) {
+                AuthUserIP *tempnode = static_cast<AuthUserIP *>(ipdata->node.next->data);
+
+                if (ipdata->ipaddr == new_ipdata->ipaddr) {
+                    /* This IP has already been seen. */
+                    found = true;
+                    /* update IP ttl and stop searching. */
+                    ipdata->ip_expiretime = max(ipdata->ip_expiretime, new_ipdata->ip_expiretime);
+                    break;
+                } else if (ipdata->ip_expiretime + Config.authenticateIpTTL < squid_curtime) {
+                    /* This IP has expired - cleanup the destination list */
+                    dlinkDelete(&ipdata->node, &ip_list);
+                    cbdataFree(ipdata);
+                    /* catch incipient underflow */
+                    assert(ipcount);
+                    ipcount--;
+                }
+
+                ipdata = tempnode;
+            }
+
+            if (!found) {
+                /* This ip is not in the seen list. Add it. */
+                dlinkAddTail(&new_ipdata->node, &ipdata->node, &ip_list);
+                ipcount++;
+                /* remove from the source list */
+                dlinkDelete(&new_ipdata->node, &(from->ip_list));
+                from->ipcount--;
+            }
+        }
+    }
 }
 
 AuthUser::~AuthUser()
 {
-    debugs(29, 5, "AuthUser::~AuthUser: Freeing auth_user '" << this << "' with refcount '" << references << "'.");
-    assert(references == 0);
+    debugs(29, 5, "AuthUser::~AuthUser: Freeing auth_user '" << this << "'.");
+    assert(RefCountCount() == 0);
+
     /* were they linked in by username ? */
 
     if (usernamehash) {
@@ -150,8 +210,7 @@ AuthUser::cacheInit(void)
 {
     if (!proxy_auth_username_cache) {
         /* First time around, 7921 should be big enough */
-        proxy_auth_username_cache =
-            hash_create((HASHCMP *) strcmp, 7921, hash_string);
+        proxy_auth_username_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
         assert(proxy_auth_username_cache);
         eventAdd("User Cache Maintenance", cacheCleanup, NULL, Config.authenticateGCInterval, 1);
     }
@@ -165,7 +224,7 @@ AuthUser::CachedACLsReset()
      * This must complete all at once, because we are ensuring correctness.
      */
     AuthUserHashPointer *usernamehash;
-    AuthUser *auth_user;
+    AuthUser::Pointer auth_user;
     char const *username = NULL;
     debugs(29, 3, "AuthUser::CachedACLsReset: Flushing the ACL caches for all users.");
     hash_first(proxy_auth_username_cache);
@@ -189,7 +248,7 @@ AuthUser::cacheCleanup(void *datanotused)
      * entries at a time. Lets see how it flys first.
      */
     AuthUserHashPointer *usernamehash;
-    AuthUser *auth_user;
+    AuthUser::Pointer auth_user;
     char const *username = NULL;
     debugs(29, 3, "AuthUser::cacheCleanup: Cleaning the user cache now");
     debugs(29, 3, "AuthUser::cacheCleanup: Current time: " << current_time.tv_sec);
@@ -205,18 +264,17 @@ AuthUser::cacheCleanup(void *datanotused)
                auth_user->auth_type << "\n\tUsername: " << username <<
                "\n\texpires: " <<
                (long int) (auth_user->expiretime + Config.authenticateTTL) <<
-               "\n\treferences: " << (long int) auth_user->references);
+               "\n\treferences: " << (long int) auth_user->RefCountCount());
 
         if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) {
             debugs(29, 5, "AuthUser::cacheCleanup: Removing user " << username << " from cache due to timeout.");
-            /* the minus 1 accounts for the cache lock */
-
-            if (!(authenticateAuthUserInuse(auth_user) - 1))
-                /* we don't warn if we leave the user in the cache,
-                 * because other modules (ie delay pools) may keep
-                 * locks on users, and thats legitimate
-                 */
-                auth_user->unlock();
+
+            /* Old credentials are always removed. Existing users must hold their own
+             * AuthUser::Pointer to the credentials. Cache exists only for finding
+             * and re-using current valid credentials.
+             */
+            hash_remove_link(proxy_auth_username_cache, usernamehash);
+            delete usernamehash;
         }
     }
 
@@ -227,12 +285,12 @@ AuthUser::cacheCleanup(void *datanotused)
 void
 AuthUser::clearIp()
 {
-    auth_user_ip_t *ipdata, *tempnode;
+    AuthUserIP *ipdata, *tempnode;
 
-    ipdata = (auth_user_ip_t *) ip_list.head;
+    ipdata = (AuthUserIP *) ip_list.head;
 
     while (ipdata) {
-        tempnode = (auth_user_ip_t *) ipdata->node.next;
+        tempnode = (AuthUserIP *) ipdata->node.next;
         /* walk the ip list */
         dlinkDelete(&ipdata->node, &ip_list);
         cbdataFree(ipdata);
@@ -249,7 +307,7 @@ AuthUser::clearIp()
 void
 AuthUser::removeIp(IpAddress ipaddr)
 {
-    auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
+    AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
 
     while (ipdata) {
         /* walk the ip list */
@@ -264,7 +322,7 @@ AuthUser::removeIp(IpAddress ipaddr)
             return;
         }
 
-        ipdata = (auth_user_ip_t *) ipdata->node.next;
+        ipdata = (AuthUserIP *) ipdata->node.next;
     }
 
 }
@@ -272,10 +330,10 @@ AuthUser::removeIp(IpAddress ipaddr)
 void
 AuthUser::addIp(IpAddress ipaddr)
 {
-    auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
+    AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
     int found = 0;
 
-    CBDATA_INIT_TYPE(auth_user_ip_t);
+    CBDATA_INIT_TYPE(AuthUserIP);
 
     /*
      * we walk the entire list to prevent the first item in the list
@@ -283,7 +341,7 @@ AuthUser::addIp(IpAddress ipaddr)
      * a timeout+reconfigure
      */
     while (ipdata) {
-        auth_user_ip_t *tempnode = (auth_user_ip_t *) ipdata->node.next;
+        AuthUserIP *tempnode = (AuthUserIP *) ipdata->node.next;
         /* walk the ip list */
 
         if (ipdata->ipaddr == ipaddr) {
@@ -307,7 +365,7 @@ AuthUser::addIp(IpAddress ipaddr)
         return;
 
     /* This ip is not in the seen list */
-    ipdata = cbdataAlloc(auth_user_ip_t);
+    ipdata = cbdataAlloc(AuthUserIP);
 
     ipdata->ip_expiretime = squid_curtime;
 
@@ -320,37 +378,40 @@ AuthUser::addIp(IpAddress ipaddr)
     debugs(29, 2, "authenticateAuthUserAddIp: user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")");
 }
 
-
+/* addToNameCache: add a auth_user structure to the username cache */
 void
-AuthUser::lock()
+AuthUser::addToNameCache()
 {
-    debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "'.");
-    assert(this != NULL);
-    references++;
-    debugs(29, 9, "authenticateAuthUserLock auth_user '" << this << "' now at '" << references << "'.");
+    usernamehash = new AuthUserHashPointer(this);
 }
 
+/**
+ * Dump the username cache statictics for viewing...
+ */
 void
-AuthUser::unlock()
+AuthUser::UsernameCacheStats(StoreEntry *output)
 {
-    debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "'.");
-    assert(this != NULL);
+    AuthUserHashPointer *usernamehash;
 
-    if (references > 0) {
-        references--;
-    } else {
-        debugs(29, 1, "Attempt to lower Auth User " << this << " refcount below 0!");
-    }
+    /* overview of username cache */
+    storeAppendPrintf(output, "Cached Usernames: %d of %d\n", proxy_auth_username_cache->count, proxy_auth_username_cache->size);
 
-    debugs(29, 9, "authenticateAuthUserUnlock auth_user '" << this << "' now at '" << references << "'.");
+    /* cache dump column titles */
+    storeAppendPrintf(output, "Authentication cached Usernames:\n");
+    storeAppendPrintf(output, "%-15s %-9s %s\n",
+                      "Type",
+                      "TTL",
+                      "Username");
+    storeAppendPrintf(output, "--------------- --------- ------------------------------\n");
 
-    if (references == 0)
-        delete this;
-}
+    hash_first(proxy_auth_username_cache);
+    while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
+        AuthUser::Pointer auth_user = usernamehash->user();
 
-/* addToNameCache: add a auth_user structure to the username cache */
-void
-AuthUser::addToNameCache()
-{
-    usernamehash = new AuthUserHashPointer (this);
+        storeAppendPrintf(output, "%-15s %-9d %s\n",
+                          AuthType_str[auth_user->auth_type],
+                          auth_user->ttl(),
+                          auth_user->username()
+                          );
+    }
 }
index 91c7988b51efc71af829c0abe2625ed0bd576441..35e4074a8bd339e5b6d403a6e885f38542097122 100644 (file)
@@ -47,7 +47,7 @@ AuthUser::username () const
 }
 
 void
-AuthUser::username(char const*aString)
+AuthUser::username(char const *aString)
 {
     if (aString) {
         assert(!username_);
index ccad09a4a64063d047b626a180cbc58a07969ae1..72ebdffe612d33489d9779235815670d76424c88 100644 (file)
 #ifndef SQUID_AUTHUSER_H
 #define SQUID_AUTHUSER_H
 
+#if USER_REQUEST_LOOP_DEAD
 #include "auth/UserRequest.h"
+#endif
+
+#include "auth/AuthType.h"
+#include "dlink.h"
+#include "ip/IpAddress.h"
+#include "RefCount.h"
 
 class AuthConfig;
 class AuthUserHashPointer;
-
-/* for auth_type_t */
-#include "enums.h"
-
-#include "ip/IpAddress.h"
-#include "dlink.h"
+class StoreEntry;
 
 /**
  *  \ingroup AuthAPI
@@ -53,16 +55,17 @@ class AuthUserHashPointer;
  * structure is the cached ACL match results. This structure, is private to
  * the authentication framework.
  */
-class AuthUser
+class AuthUser : public RefCountable
 {
-
 public:
+    typedef RefCount<AuthUser> Pointer;
+
     /* extra fields for proxy_auth */
     /* auth_type and auth_module are deprecated. Do Not add new users of these fields.
      * Aim to remove shortly
      */
     /** \deprecated this determines what scheme owns the user data. */
-    auth_type_t auth_type;
+    AuthType auth_type;
     /** the config for this user */
     AuthConfig *config;
     /** we only have one username associated with a given auth_user struct */
@@ -72,17 +75,21 @@ public:
     dlink_list proxy_match_cache;
     size_t ipcount;
     long expiretime;
-    /** how many references are outstanding to this instance */
-    size_t references;
 
     static void cacheInit();
     static void CachedACLsReset();
 
-    void absorb(AuthUser *from);
+    void absorb(AuthUser::Pointer from);
     virtual ~AuthUser();
     _SQUID_INLINE_ char const *username() const;
     _SQUID_INLINE_ void username(char const *);
 
+    /**
+     * How long these credentials are still valid for.
+     * Negative numbers means already expired.
+     */
+    virtual int32_t ttl() const = 0;
+
     /* Manage list of IPs using this username */
     void clearIp();
     void removeIp(IpAddress);
@@ -102,10 +109,8 @@ public:
     _SQUID_INLINE_ void doneRequest(AuthUserRequest::Pointer);
 #endif /* USER_REQUEST_LOOP_DEAD */
 
-    void lock();
-    void unlock();
-
     void addToNameCache();
+    static void UsernameCacheStats(StoreEntry * output);
 
 protected:
     AuthUser(AuthConfig *);
index 493ae4a0486d343790381bf3236eb9595de67fcf..63525d4185991199bb74aa35a8feb6e4b62c0171 100644 (file)
@@ -56,7 +56,7 @@
 char const *
 AuthUserRequest::username() const
 {
-    if (user())
+    if (user() != NULL)
         return user()->username();
     else
         return NULL;
@@ -138,7 +138,7 @@ AuthUserRequest::~AuthUserRequest()
     assert(RefCountCount()==0);
     debugs(29, 5, "AuthUserRequest::~AuthUserRequest: freeing request " << this);
 
-    if (user()) {
+    if (user() != NULL) {
 #if USER_REQUEST_LOOP_DEAD
         /* AYJ: something strange: in order to be deleted this object must not be
          * referenced anywhere. Including the AuthUser list of requests.
@@ -147,23 +147,22 @@ AuthUserRequest::~AuthUserRequest()
         user()->doneRequest(this);
 #endif /* USER_REQUEST_LOOP_DEAD */
 
-        /* unlock the request structure's lock and release it */
-        user()->unlock();
+        /* release our references to the user credentials */
         user(NULL);
     }
 
-    safe_free (message);
+    safe_free(message);
 }
 
 void
-AuthUserRequest::setDenyMessage (char const *aString)
+AuthUserRequest::setDenyMessage(char const *aString)
 {
-    safe_free (message);
-    message = xstrdup (aString);
+    safe_free(message);
+    message = xstrdup(aString);
 }
 
 char const *
-AuthUserRequest::getDenyMessage ()
+AuthUserRequest::getDenyMessage()
 {
     return message;
 }
@@ -181,7 +180,7 @@ AuthUserRequest::denyMessage(char const * const default_message)
 static void
 authenticateAuthUserRequestSetIp(AuthUserRequest::Pointer auth_user_request, IpAddress &ipaddr)
 {
-    AuthUser *auth_user = auth_user_request->user();
+    AuthUser::Pointer auth_user = auth_user_request->user();
 
     if (!auth_user)
         return;
@@ -192,7 +191,7 @@ authenticateAuthUserRequestSetIp(AuthUserRequest::Pointer auth_user_request, IpA
 void
 authenticateAuthUserRequestRemoveIp(AuthUserRequest::Pointer auth_user_request, IpAddress const &ipaddr)
 {
-    AuthUser *auth_user = auth_user_request->user();
+    AuthUser::Pointer auth_user = auth_user_request->user();
 
     if (!auth_user)
         return;
@@ -211,7 +210,7 @@ int
 authenticateAuthUserRequestIPCount(AuthUserRequest::Pointer auth_user_request)
 {
     assert(auth_user_request != NULL);
-    assert(auth_user_request->user());
+    assert(auth_user_request->user() != NULL);
     return auth_user_request->user()->ipcount;
 }
 
@@ -306,7 +305,7 @@ authTryGetUser(AuthUserRequest::Pointer auth_user_request, ConnStateData * conn,
  *
  * Caller is responsible for locking and unlocking their *auth_user_request!
  */
-auth_acl_t
+AuthAclState
 AuthUserRequest::authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr)
 {
     const char *proxy_auth;
@@ -475,7 +474,7 @@ AuthUserRequest::authenticate(AuthUserRequest::Pointer * auth_user_request, http
     return AUTH_AUTHENTICATED;
 }
 
-auth_acl_t
+AuthAclState
 AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr)
 {
     /* If we have already been called, return the cached value */
@@ -492,7 +491,7 @@ AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer * auth
     }
 
     /* ok, call the actual authenticator routine. */
-    auth_acl_t result = authenticate(auth_user_request, headertype, request, conn, src_addr);
+    AuthAclState result = authenticate(auth_user_request, headertype, request, conn, src_addr);
 
     t = authTryGetUser(*auth_user_request, conn, request);
 
index d95c2b5a312f51009d23d478c2cb24a49577cee7..cfc6a945ac720b40be6d27c129c4c90fb1bc1f38 100644 (file)
 #ifndef SQUID_AUTHUSERREQUEST_H
 #define SQUID_AUTHUSERREQUEST_H
 
-#include "auth/enums.h"
+#include "auth/AuthAclState.h"
 #include "auth/Scheme.h"
+#include "auth/User.h"
 #include "dlink.h"
 #include "ip/IpAddress.h"
 #include "typedefs.h"
 #include "HttpHeader.h"
 
-class AuthUser;
 class ConnStateData;
 class HttpReply;
 class HttpRequest;
 
-struct AuthUserIP {
+/// \ingroup AuthAPI
+class AuthUserIP
+{
+public:
     dlink_node node;
     /* IP addr this user authenticated from */
 
@@ -73,7 +76,7 @@ public:
      * it has request specific data, and links to user specific data
      * the user
      */
-    AuthUser *_auth_user;
+    AuthUser::Pointer _auth_user;
 
     /**
      *  Used by squid to determine what the next step in performing authentication for a given scheme is.
@@ -110,13 +113,13 @@ public:
      */
     virtual void module_start(RH *handler, void *data) = 0;
 
-    virtual AuthUser *user() {return _auth_user;}
+    virtual AuthUser::Pointer user() {return _auth_user;}
 
-    virtual const AuthUser *user() const {return _auth_user;}
+    virtual const AuthUser::Pointer user() const {return _auth_user;}
 
-    virtual void user(AuthUser *aUser) {_auth_user=aUser;}
+    virtual void user(AuthUser::Pointer aUser) {_auth_user=aUser;}
 
-    static auth_acl_t tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer *, http_hdr_type, HttpRequest *, ConnStateData *, IpAddress &);
+    static AuthAclState tryToAuthenticateAndSetAuthUser(AuthUserRequest::Pointer *, http_hdr_type, HttpRequest *, ConnStateData *, IpAddress &);
     static void addReplyAuthHeader(HttpReply * rep, AuthUserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal);
 
     AuthUserRequest();
@@ -150,7 +153,7 @@ public:
 
 private:
 
-    static auth_acl_t authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr);
+    static AuthAclState authenticate(AuthUserRequest::Pointer * auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData * conn, IpAddress &src_addr);
 
     /** return a message on the 407 error pages */
     char *message;
@@ -160,7 +163,7 @@ private:
      * is to allow multiple auth acl references from different _access areas
      * when using connection based authentication
      */
-    auth_acl_t lastReply;
+    AuthAclState lastReply;
 };
 
 /* AuthUserRequest */
index d73c952c1371bd8db34eadadcb02830a2e3296b2..a16f3fa7ea0157a7af16a4fa1be5f9eada6e90ef 100644 (file)
@@ -92,6 +92,18 @@ AuthBasicConfig::type() const
     return basicScheme::GetInstance()->type();
 }
 
+int32_t
+BasicUser::ttl() const
+{
+    if (flags.credentials_ok != 1)
+        return -1; // TTL is obsolete NOW.
+
+    int32_t basic_ttl = credentials_checkedtime - squid_curtime + static_cast<AuthBasicConfig*>(config)->credentialsTTL;
+    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Config.authenticateTTL);
+
+    return min(basic_ttl, global_ttl);
+}
+
 
 bool
 BasicUser::authenticated() const
@@ -158,7 +170,10 @@ authenticateBasicHandleReply(void *data, char *reply)
 
     assert(r->auth_user_request != NULL);
     assert(r->auth_user_request->user()->auth_type == AUTH_BASIC);
-    basic_data *basic_auth = dynamic_cast<basic_data *>(r->auth_user_request->user());
+
+    /* this is okay since we only play with the BasicUser child fields below
+     * and dont pass the pointer itself anywhere */
+    BasicUser *basic_auth = dynamic_cast<BasicUser *>(r->auth_user_request->user().getRaw());
 
     assert(basic_auth != NULL);
 
@@ -255,7 +270,7 @@ authenticateBasicStats(StoreEntry * sentry)
     helperStats(sentry, basicauthenticators, "Basic Authenticator Statistics");
 }
 
-static AuthUser *
+static AuthUser::Pointer
 authBasicAuthUserFindUsername(const char *username)
 {
     AuthUserHashPointer *usernamehash;
@@ -280,7 +295,7 @@ BasicUser::deleteSelf() const
     delete this;
 }
 
-BasicUser::BasicUser(AuthConfig *aConfig) : AuthUser (aConfig) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext (NULL), currentRequest (NULL), httpAuthHeader (NULL)
+BasicUser::BasicUser(AuthConfig *aConfig) : AuthUser(aConfig) , passwd (NULL), credentials_checkedtime(0), auth_queue(NULL), cleartext(NULL), currentRequest(NULL), httpAuthHeader(NULL)
 {
     flags.credentials_ok = 0;
 }
@@ -387,7 +402,6 @@ BasicUser::valid() const
 
 /**
  * Generate a duplicate of the bad credentials before clearing the working copy.
- * apparently for logging, but WTF?!
  */
 void
 BasicUser::makeLoggingInstance(AuthUserRequest::Pointer auth_user_request)
@@ -396,7 +410,7 @@ BasicUser::makeLoggingInstance(AuthUserRequest::Pointer auth_user_request)
         /* log the username */
         debugs(29, 9, HERE << "Creating new user for logging '" << username() << "'");
         /* new scheme data */
-        BasicUser *basic_auth = new BasicUser(config);
+        AuthUser::Pointer basic_auth = dynamic_cast<AuthUser*>(new BasicUser(config));
         auth_user_request->user(basic_auth);
         /* save the credentials */
         basic_auth->username(username());
@@ -410,7 +424,9 @@ BasicUser::makeLoggingInstance(AuthUserRequest::Pointer auth_user_request)
     }
 }
 
-AuthUser *
+#if 0
+/* TODO: instead of duplicating into the cache why not just add a ::Pointer to ourselves there? */
+AuthUser::Pointer
 BasicUser::makeCachedFrom()
 {
     /* the user doesn't exist in the username cache yet */
@@ -430,13 +446,18 @@ BasicUser::makeCachedFrom()
     /* the requests after this link to the basic_user */
     /* store user in hash */
     basic_user->addToNameCache();
-    return basic_user;
+
+    AuthUser::Pointer auth_user = dynamic_cast<AuthUser*>(basic_user);
+    return auth_user;
 }
+#endif
 
 void
 BasicUser::updateCached(BasicUser *from)
 {
-    debugs(29, 9, HERE << "Found user '" << from->username() << "' in the user cache as '" << this << "'");
+    debugs(29, 9, HERE << "Found user '" << from->username() << "' already in the user cache as '" << this << "'");
+
+    assert(strcmp(from->username(), username()) == 0);
 
     if (strcmp(from->passwd, passwd)) {
         debugs(29, 4, HERE << "new password found. Updating in user master record and resetting auth state to unchecked");
@@ -469,35 +490,49 @@ AuthBasicConfig::decode(char const *proxy_auth)
     while (xisgraph(*proxy_auth))
         proxy_auth++;
 
-    BasicUser *basic_auth, local_basic(this);
+    /* decoder copy. maybe temporary. maybe added to hash if none already existing. */
+    BasicUser *local_basic = new BasicUser(this);
 
     /* Trim leading whitespace before decoding */
     while (xisspace(*proxy_auth))
         proxy_auth++;
 
-    local_basic.decode(proxy_auth, auth_user_request);
+    local_basic->decode(proxy_auth, auth_user_request);
 
-    if (!local_basic.valid()) {
-        local_basic.makeLoggingInstance(auth_user_request);
+    if (!local_basic->valid()) {
+        local_basic->makeLoggingInstance(auth_user_request);
         return auth_user_request;
     }
 
     /* now lookup and see if we have a matching auth_user structure in memory. */
-    AuthUser *auth_user = NULL;
+    AuthUser::Pointer auth_user;
+
+    if ((auth_user = authBasicAuthUserFindUsername(local_basic->username())) == NULL) {
+        /* the user doesn't exist in the username cache yet */
+        /* save the credentials */
+        debugs(29, 9, HERE << "Creating new user '" << local_basic->username() << "'");
+        /* set the auth_user type */
+        local_basic->auth_type = AUTH_BASIC;
+        /* current time for timeouts */
+        local_basic->expiretime = current_time.tv_sec;
+
+        /* this basic_user struct is the 'lucky one' to get added to the username cache */
+        /* the requests after this link to the basic_user */
+        /* store user in hash */
+        local_basic->addToNameCache();
 
-    if ((auth_user = authBasicAuthUserFindUsername(local_basic.username())) == NULL) {
-        /* TODO: optimize. make "local_basic" the object we will store. dont allocate, duplicate, discard. */
-        auth_user = local_basic.makeCachedFrom();
-        basic_auth = dynamic_cast<BasicUser *>(auth_user);
-        assert (basic_auth);
+        auth_user = dynamic_cast<AuthUser*>(local_basic);
+        assert(auth_user != NULL);
     } else {
-        basic_auth = dynamic_cast<BasicUser *>(auth_user);
+        /* replace the current cached password with the new one */
+        BasicUser *basic_auth = dynamic_cast<BasicUser *>(auth_user.getRaw());
         assert(basic_auth);
-        basic_auth->updateCached(&local_basic);
+        basic_auth->updateCached(local_basic);
+        auth_user = basic_auth;
     }
 
     /* link the request to the in-cache user */
-    auth_user_request->user(basic_auth);
+    auth_user_request->user(auth_user);
 #if USER_REQUEST_LOOP_DEAD
     basic_auth->addRequest(auth_user_request);
 #endif /* USER_REQUEST_LOOP_DEAD */
index e9f12d008902643201cbbcb3d7e6609923435d63..6b506c1281a25aee6b08a44121852ef606848f8a 100644 (file)
@@ -42,15 +42,18 @@ public:
 
     bool valid() const;
     void makeLoggingInstance(AuthUserRequest::Pointer auth_user_request);
-    AuthUser * makeCachedFrom();
+#if 0
+    AuthUser::Pointer makeCachedFrom();
+#endif
+    /** Update the cached password for a username. */
     void updateCached(BasicUser *from);
+    virtual int32_t ttl() const;
+
     char *passwd;
     time_t credentials_checkedtime;
 
     struct {
-
-unsigned int credentials_ok:
-        2;     /*0=unchecked,1=ok,2=failed */
+        unsigned int credentials_ok:2; /* 0=unchecked, 1=ok, 2=failed */
     } flags;
     BasicAuthQueueNode *auth_queue;
 
@@ -65,8 +68,6 @@ private:
 
 MEMPROXY_CLASS_INLINE(BasicUser);
 
-typedef class BasicUser basic_data;
-
 /* configuration runtime data */
 
 class AuthBasicConfig : public AuthConfig
@@ -91,4 +92,4 @@ public:
     int utf8;
 };
 
-#endif
+#endif /* __AUTH_BASIC_H__ */
index dc45db4cd632b9b1dd6f5877db6d83b9932c8e55..f8829dcf54aa93f0b991e886cc475304cb58930d 100644 (file)
@@ -7,7 +7,7 @@
 int
 AuthBasicUserRequest::authenticated() const
 {
-    BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user());
+    BasicUser const *basic_auth = dynamic_cast<BasicUser const *>(user().getRaw());
 
     if (basic_auth && basic_auth->authenticated())
         return 1;
@@ -22,7 +22,7 @@ AuthBasicUserRequest::authenticate(HttpRequest * request, ConnStateData * conn,
 {
     assert(user() != NULL);
 
-    basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
+    BasicUser *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
 
     /* if the password is not ok, do an identity */
 
@@ -49,7 +49,7 @@ int
 AuthBasicUserRequest::module_direction()
 {
     /* null auth_user is checked for by authenticateDirection */
-    basic_data *basic_auth = dynamic_cast<BasicUser *>(user());
+    BasicUser const *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
     assert (basic_auth);
 
     switch (basic_auth->flags.credentials_ok) {
@@ -78,9 +78,8 @@ AuthBasicUserRequest::module_direction()
 void
 AuthBasicUserRequest::module_start(RH * handler, void *data)
 {
-    basic_data *basic_auth;
     assert(user()->auth_type == AUTH_BASIC);
-    basic_auth = dynamic_cast<basic_data *>(user());
+    BasicUser *basic_auth = dynamic_cast<BasicUser *>(user().getRaw());
     assert(basic_auth != NULL);
     debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
 
@@ -96,6 +95,6 @@ AuthBasicUserRequest::module_start(RH * handler, void *data)
         return;
     }
 
-    basic_auth->submitRequest (this, handler, data);
+    basic_auth->submitRequest(this, handler, data);
 }
 
index bf5a6d963cb51d0fb6881bb244692c54bc3efcc1..4c0c8d8fe6813e5dc8ef8d5e654b654cfb0aacfc 100644 (file)
@@ -480,46 +480,24 @@ authDigestNoncePurge(digest_nonce_h * nonce)
 }
 
 /* USER related functions */
-static AuthUser *
+static AuthUser::Pointer
 authDigestUserFindUsername(const char *username)
 {
     AuthUserHashPointer *usernamehash;
-    AuthUser *auth_user;
     debugs(29, 9, HERE << "Looking for user '" << username << "'");
 
     if (username && (usernamehash = static_cast < auth_user_hash_pointer * >(hash_lookup(proxy_auth_username_cache, username)))) {
-        while ((usernamehash->user()->auth_type != AUTH_DIGEST) &&
-                (usernamehash->next))
-            usernamehash = static_cast < auth_user_hash_pointer * >(usernamehash->next);
-
-        auth_user = NULL;
+        while ((usernamehash->user()->auth_type != AUTH_DIGEST) && (usernamehash->next))
+            usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
 
         if (usernamehash->user()->auth_type == AUTH_DIGEST) {
-            auth_user = usernamehash->user();
+            return usernamehash->user();
         }
-
-        return auth_user;
     }
 
     return NULL;
 }
 
-static void
-authDigestUserShutdown(void)
-{
-    /** \todo Future work: the auth framework could flush it's cache */
-    AuthUserHashPointer *usernamehash;
-    AuthUser *auth_user;
-    hash_first(proxy_auth_username_cache);
-
-    while ((usernamehash = ((auth_user_hash_pointer *) hash_next(proxy_auth_username_cache)))) {
-        auth_user = usernamehash->user();
-
-        if (strcmp(auth_user->config->type(), "digest") == 0)
-            auth_user->unlock();
-    }
-}
-
 /** delete the digest request structure. Does NOT delete related structures */
 void
 digestScheme::done()
@@ -544,7 +522,7 @@ digestScheme::done()
     delete digestauthenticators;
     digestauthenticators = NULL;
 
-    authDigestUserShutdown();
+    PurgeCredentialsCache();
     authenticateDigestNonceShutdown();
     debugs(29, 2, "authenticateDigestDone: Digest authentication shut down.");
 
@@ -620,7 +598,6 @@ AuthDigestConfig::fixHeader(AuthUserRequest::Pointer auth_user_request, HttpRepl
 
 DigestUser::~DigestUser()
 {
-
     dlink_node *link, *tmplink;
     link = nonces.head;
 
@@ -634,6 +611,30 @@ DigestUser::~DigestUser()
     }
 }
 
+int32_t
+DigestUser::ttl() const
+{
+    int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Config.authenticateTTL);
+
+    /* find the longest lasting nonce. */
+    int32_t latest_nonce = -1;
+    dlink_node *link = nonces.head;
+    while (link) {
+        digest_nonce_h *nonce = static_cast<digest_nonce_h *>(link->data);
+        if (nonce->flags.valid && nonce->noncedata.creationtime > latest_nonce)
+            latest_nonce = nonce->noncedata.creationtime;
+
+        link = link->next;
+    }
+    if (latest_nonce == -1)
+        return min(-1, global_ttl);
+
+    int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->noncemaxduration;
+
+    return min(nonce_ttl, global_ttl);
+}
+
+
 /* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
  * config file */
 void
@@ -744,7 +745,7 @@ authenticateDigestStats(StoreEntry * sentry)
 static void
 authDigestNonceUserUnlink(digest_nonce_h * nonce)
 {
-    digest_user_h *digest_user;
+    DigestUser *digest_user;
     dlink_node *link, *tmplink;
 
     if (!nonce)
@@ -784,7 +785,7 @@ static void
 authDigestUserLinkNonce(DigestUser * user, digest_nonce_h * nonce)
 {
     dlink_node *node;
-    digest_user_h *digest_user;
+    DigestUser *digest_user;
 
     if (!user || !nonce)
         return;
@@ -822,14 +823,13 @@ authDigestLogUsername(char *username, AuthUserRequest::Pointer auth_user_request
 
     /* log the username */
     debugs(29, 9, "authDigestLogUsername: Creating new user for logging '" << username << "'");
-    digest_user_h *digest_user = new DigestUser(static_cast<AuthDigestConfig*>(AuthConfig::Find("digest")));
+    AuthUser::Pointer digest_user = new DigestUser(static_cast<AuthDigestConfig*>(AuthConfig::Find("digest")));
     /* save the credentials */
     digest_user->username(username);
     /* set the auth_user type */
     digest_user->auth_type = AUTH_BROKEN;
     /* link the request to the user */
     auth_user_request->user(digest_user);
-    digest_user->lock();
 #if USER_REQUEST_LOOP_DEAD
     digest_user->addRequest(auth_user_request);
 #endif
@@ -1079,9 +1079,9 @@ AuthDigestConfig::decode(char const *proxy_auth)
     /* we don't send or parse opaques. Ok so we're flexable ... */
 
     /* find the user */
-    digest_user_h *digest_user;
+    DigestUser *digest_user;
 
-    AuthUser *auth_user;
+    AuthUser::Pointer auth_user;
 
     if ((auth_user = authDigestUserFindUsername(username)) == NULL) {
         /* the user doesn't exist in the username cache yet */
@@ -1106,14 +1106,13 @@ AuthDigestConfig::decode(char const *proxy_auth)
         authDigestUserLinkNonce(digest_user, nonce);
     } else {
         debugs(29, 9, "authDigestDecodeAuth: Found user '" << username << "' in the user cache as '" << auth_user << "'");
-        digest_user = static_cast < digest_user_h * >(auth_user);
+        digest_user = static_cast<DigestUser *>(auth_user.getRaw());
         xfree(username);
     }
 
     /*link the request and the user */
     assert(digest_request != NULL);
 
-    digest_user->lock();
     digest_request->user(digest_user);
 #if USER_REQUEST_LOOP_DEAD
     digest_user->addRequest(digest_request);
@@ -1130,5 +1129,5 @@ AuthDigestConfig::decode(char const *proxy_auth)
     return digest_request;
 }
 
-DigestUser::DigestUser (AuthConfig *aConfig) : AuthUser (aConfig), HA1created (0)
+DigestUser::DigestUser(AuthConfig *aConfig) : AuthUser(aConfig), HA1created (0)
 {}
index dfbe62ae6a4f8650f3765e594bd65ea952c860c4..a37e4bfd55f599b05592827ed4a6679072ede915 100644 (file)
@@ -29,6 +29,9 @@ public:
     DigestUser(AuthConfig *);
     ~DigestUser();
     int authenticated() const;
+
+    virtual int32_t ttl() const;
+
     HASH HA1;
     int HA1created;
 
@@ -39,8 +42,6 @@ public:
 
 MEMPROXY_CLASS_INLINE(DigestUser);
 
-typedef class DigestUser digest_user_h;
-
 
 /* data to be encoded into the nonce's b64 representation */
 
index 2d4053cf196bfc0466b35cdcdc4aab13f90a8cfa..f823107baf51e9ac2468d116834f0066135c9b3a 100644 (file)
@@ -58,3 +58,20 @@ digestScheme::createConfig()
     AuthDigestConfig *digestCfg = new AuthDigestConfig;
     return dynamic_cast<AuthConfig*>(digestCfg);
 }
+
+void
+digestScheme::PurgeCredentialsCache(void)
+{
+    AuthUserHashPointer *usernamehash;
+    AuthUser::Pointer auth_user;
+    hash_first(proxy_auth_username_cache);
+
+    while ((usernamehash = static_cast<AuthUserHashPointer *>(hash_next(proxy_auth_username_cache)) )) {
+        auth_user = usernamehash->user();
+
+        if (strcmp(auth_user->config->type(), "digest") == 0) {
+            hash_remove_link(proxy_auth_username_cache, static_cast<hash_link*>(usernamehash));
+            delete usernamehash;
+        }
+    }
+}
index 2d12f547e0e503ec7f6287ee5f9086617f7b5a1e..1d7652574b26ef55ee231ae97045b5acfb00db50 100644 (file)
@@ -57,6 +57,13 @@ public:
 
 private:
     static AuthScheme::Pointer _instance;
+
+    /**
+     * Remove all cached user credentials from circulation.
+     * Intended for use during shutdown procedure.
+     * After calling this all newly received credentials must be re-authenticated.
+     */
+    static void PurgeCredentialsCache(void);
 };
 
 #endif /* SQUID_DIGESTSCHEME_H */
index 3fd996c4755601156ae4c1c52c640039f017e177..3c953b427b87addccb504b54788a52ba61c911fe 100644 (file)
@@ -68,29 +68,24 @@ AuthDigestUserRequest::authenticated() const
 void
 AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
 {
-    AuthDigestUserRequest *digest_request;
-    digest_user_h *digest_user;
-
     HASHHEX SESSIONKEY;
     HASHHEX HA2 = "";
     HASHHEX Response;
 
-    assert(authUser() != NULL);
-    AuthUser *auth_user = user();
-
-    digest_user = dynamic_cast<digest_user_h*>(auth_user);
-    assert(digest_user != NULL);
-
     /* if the check has corrupted the user, just return */
-
     if (credentials() == Failed) {
         return;
     }
 
-    digest_request = this;
+    assert(user() != NULL);
+    AuthUser::Pointer auth_user = user();
 
-    /* do we have the HA1 */
+    DigestUser *digest_user = dynamic_cast<DigestUser*>(auth_user.getRaw());
+    assert(digest_user != NULL);
 
+    AuthDigestUserRequest *digest_request = this;
+
+    /* do we have the HA1 */
     if (!digest_user->HA1created) {
         credentials(Pending);
         return;
@@ -165,7 +160,7 @@ AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData * conn,
 
         /* check for stale nonce */
         if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
-            debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK but nonce stale");
+            debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << auth_user->username() << "' validated OK but nonce stale");
             credentials(Failed);
             digest_request->setDenyMessage("Stale nonce");
             return;
@@ -175,7 +170,7 @@ AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData * conn,
     credentials(Ok);
 
     /* password was checked and did match */
-    debugs(29, 4, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK");
+    debugs(29, 4, "authenticateDigestAuthenticateuser: user '" << auth_user->username() << "' validated OK");
 
     /* auth_user is now linked, we reset these values
      * after external auth occurs anyway */
@@ -265,11 +260,14 @@ AuthDigestUserRequest::module_start(RH * handler, void *data)
 {
     authenticateStateData *r = NULL;
     char buf[8192];
-    digest_user_h *digest_user;
-    assert(user()->auth_type == AUTH_DIGEST);
-    digest_user = dynamic_cast<digest_user_h*>(user());
+
+    assert(user() != NULL && user()->auth_type == AUTH_DIGEST);
+#if 0
+    DigestUser *digest_user = dynamic_cast<DigestUser*>(user().getRaw());
     assert(digest_user != NULL);
-    debugs(29, 9, "authenticateStart: '\"" << digest_user->username() << "\":\"" << realm << "\"'");
+#endif
+
+    debugs(29, 9, "authenticateStart: '\"" << user()->username() << "\":\"" << realm << "\"'");
 
     if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->authenticate == NULL) {
         handler(data, NULL);
@@ -282,10 +280,10 @@ AuthDigestUserRequest::module_start(RH * handler, void *data)
     r->auth_user_request = static_cast<AuthUserRequest*>(this);
     if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->utf8) {
         char userstr[1024];
-        latin1_to_utf8(userstr, sizeof(userstr), digest_user->username());
+        latin1_to_utf8(userstr, sizeof(userstr), user()->username());
         snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
     } else {
-        snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username(), realm);
+        snprintf(buf, 8192, "\"%s\":\"%s\"\n", user()->username(), realm);
     }
 
     helperSubmit(digestauthenticators, buf, AuthDigestUserRequest::HandleReply, r);
@@ -310,20 +308,21 @@ AuthDigestUserRequest::HandleReply(void *data, char *reply)
     assert(replyData->auth_user_request != NULL);
     AuthUserRequest::Pointer auth_user_request = replyData->auth_user_request;
 
-    /* AYJ: 2009-12-12: allow this because the digest_request pointer is purely local */
-    AuthDigestUserRequest *digest_request = dynamic_cast < AuthDigestUserRequest * >(auth_user_request.getRaw());
-    assert(digest_request);
-
-    digest_user_h *digest_user = dynamic_cast < digest_user_h * >(auth_user_request->user());
-    assert(digest_user != NULL);
-
     if (reply && (strncasecmp(reply, "ERR", 3) == 0)) {
+        /* allow this because the digest_request pointer is purely local */
+        AuthDigestUserRequest *digest_request = dynamic_cast<AuthDigestUserRequest *>(auth_user_request.getRaw());
+        assert(digest_request);
+
         digest_request->credentials(AuthDigestUserRequest::Failed);
         digest_request->flags.invalid_password = 1;
 
         if (t && *t)
             digest_request->setDenyMessage(t);
     } else if (reply) {
+        /* allow this because the digest_request pointer is purely local */
+        DigestUser *digest_user = dynamic_cast<DigestUser *>(auth_user_request->user().getRaw());
+        assert(digest_user != NULL);
+
         CvtBin(reply, digest_user->HA1);
         digest_user->HA1created = 1;
     }
diff --git a/src/auth/enums.h b/src/auth/enums.h
deleted file mode 100644 (file)
index 058fd68..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _SQUID__SRC_AUTH_ENUMS_H
-#define _SQUID__SRC_AUTH_ENUMS_H
-
-typedef enum {
-    AUTH_ACL_CHALLENGE = -2,
-    AUTH_ACL_HELPER = -1,
-    AUTH_ACL_CANNOT_AUTHENTICATE = 0,
-    AUTH_AUTHENTICATED = 1
-} auth_acl_t;
-
-typedef enum {
-    AUTH_UNKNOWN,               /* default */
-    AUTH_BASIC,
-    AUTH_NTLM,
-    AUTH_DIGEST,
-    AUTH_NEGOTIATE,
-    AUTH_BROKEN                 /* known type, but broken data */
-} auth_type_t;
-
-#endif
index 6e9a6ff630231ecd5fdddeb14df31dd2fd489929..a1bbaf47aaa939639d6b406d7e86f3365db0845c 100644 (file)
@@ -293,6 +293,13 @@ NegotiateUser::~NegotiateUser()
     debugs(29, 5, "NegotiateUser::~NegotiateUser: doing nothing to clearNegotiate scheme data for '" << this << "'");
 }
 
+int32_t
+NegotiateUser::ttl() const
+{
+    return -1; // Negotiate canot be cached.
+}
+
+
 static void
 authenticateNegotiateStats(StoreEntry * sentry)
 {
index d0cdd3103854784946c10e71c3fe91bb74b01bc6..baa1bf12114064f71da03a78ad1413c3693cedbd 100644 (file)
@@ -27,9 +27,11 @@ class NegotiateUser : public AuthUser
 
 public:
     MEMPROXY_CLASS(NegotiateUser);
-    virtual void deleteSelf() const;
     NegotiateUser(AuthConfig *);
     ~NegotiateUser();
+    virtual void deleteSelf() const;
+    virtual int32_t ttl() const;
+
     dlink_list proxy_auth_list;
 };
 
index dbf4511131ceb96f79a70fab43331c4500d0700f..68a1a8d4ddc591c6cc35732575b8b360e7787084 100644 (file)
@@ -119,15 +119,12 @@ AuthNegotiateUserRequest::module_start(RH * handler, void *data)
 {
     authenticateStateData *r = NULL;
     static char buf[MAX_AUTHTOKEN_LEN];
-    NegotiateUser *negotiate_user;
-    AuthUser *auth_user = user();
 
     assert(data);
     assert(handler);
-    assert(auth_user);
-    assert(auth_user->auth_type == AUTH_NEGOTIATE);
 
-    negotiate_user = dynamic_cast<NegotiateUser*>(user());
+    assert(user() != NULL);
+    assert(user()->auth_type == AUTH_NEGOTIATE);
 
     debugs(29, 8, HERE << "auth state is '" << auth_state << "'");
 
@@ -193,16 +190,6 @@ AuthNegotiateUserRequest::onConnectionClose(ConnStateData *conn)
 void
 AuthNegotiateUserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type)
 {
-    const char *proxy_auth, *blob;
-
-    /** \todo rename this!! */
-    AuthUser *local_auth_user;
-    NegotiateUser *negotiate_user;
-
-    local_auth_user = user();
-    assert(local_auth_user);
-    assert(local_auth_user->auth_type == AUTH_NEGOTIATE);
-    negotiate_user = dynamic_cast<NegotiateUser *>(local_auth_user);
     assert (this);
 
     /** Check that we are in the client side, where we can generate auth challenges */
@@ -223,10 +210,10 @@ AuthNegotiateUserRequest::authenticate(HttpRequest * aRequest, ConnStateData * c
     }
 
     /* get header */
-    proxy_auth = aRequest->header.getStr(type);
+    const char *proxy_auth = aRequest->header.getStr(type);
 
     /* locate second word */
-    blob = proxy_auth;
+    const char *blob = proxy_auth;
 
     if (blob) {
         while (xisspace(*blob) && *blob)
@@ -291,10 +278,6 @@ AuthNegotiateUserRequest::HandleReply(void *data, void *lastserver, char *reply)
     int valid;
     char *blob, *arg = NULL;
 
-    AuthUser *auth_user;
-    NegotiateUser *negotiate_user;
-    AuthNegotiateUserRequest *negotiate_request;
-
     debugs(29, 8, HERE << "helper: '" << lastserver << "' sent us '" << (reply ? reply : "<NULL>") << "'");
     valid = cbdataReferenceValid(r->data);
 
@@ -313,19 +296,15 @@ AuthNegotiateUserRequest::HandleReply(void *data, void *lastserver, char *reply)
     AuthUserRequest::Pointer auth_user_request = r->auth_user_request;
     assert(auth_user_request != NULL);
 
-    negotiate_request = dynamic_cast<AuthNegotiateUserRequest *>(auth_user_request.getRaw());
+    AuthNegotiateUserRequest *negotiate_request = dynamic_cast<AuthNegotiateUserRequest *>(auth_user_request.getRaw());
     assert(negotiate_request != NULL);
 
     assert(negotiate_request->waiting);
     negotiate_request->waiting = 0;
     safe_free(negotiate_request->client_blob);
 
-    auth_user = auth_user_request->user();
-    assert(auth_user != NULL);
-    assert(auth_user->auth_type == AUTH_NEGOTIATE);
-
-    negotiate_user = dynamic_cast<NegotiateUser *>(auth_user_request->user());
-    assert(negotiate_user != NULL);
+    assert(auth_user_request->user() != NULL);
+    assert(auth_user_request->user()->auth_type == AUTH_NEGOTIATE);
 
     if (negotiate_request->authserver == NULL)
         negotiate_request->authserver = static_cast<helper_stateful_server*>(lastserver);
@@ -363,7 +342,7 @@ AuthNegotiateUserRequest::HandleReply(void *data, void *lastserver, char *reply)
         if (arg)
             *arg++ = '\0';
 
-        negotiate_user->username(arg);
+        auth_user_request->user()->username(arg);
         auth_user_request->denyMessage("Login successful");
         safe_free(negotiate_request->server_blob);
         negotiate_request->server_blob = xstrdup(blob);
@@ -372,25 +351,25 @@ AuthNegotiateUserRequest::HandleReply(void *data, void *lastserver, char *reply)
         debugs(29, 4, HERE << "Successfully validated user via Negotiate. Username '" << blob << "'");
 
         /* connection is authenticated */
-        debugs(29, 4, HERE << "authenticated user " << negotiate_user->username());
+        debugs(29, 4, HERE << "authenticated user " << auth_user_request->user()->username());
         /* see if this is an existing user with a different proxy_auth
          * string */
-        AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, negotiate_user->username()));
-        AuthUser *local_auth_user = negotiate_request->user();
-        while (usernamehash && (usernamehash->user()->auth_type != AUTH_NEGOTIATE || strcmp(usernamehash->user()->username(), negotiate_user->username()) != 0))
+        AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->username()));
+        AuthUser::Pointer local_auth_user = negotiate_request->user();
+        while (usernamehash && (usernamehash->user()->auth_type != AUTH_NEGOTIATE || strcmp(usernamehash->user()->username(), auth_user_request->user()->username()) != 0))
             usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
         if (usernamehash) {
             /* we can't seamlessly recheck the username due to the
              * challenge-response nature of the protocol.
-             * Just free the temporary auth_user */
+             * Just free the temporary auth_user after merging as
+             * much of it new state into the existing one as possible */
             usernamehash->user()->absorb(local_auth_user);
-            //authenticateAuthUserMerge(local_auth_user, usernamehash->user());
             local_auth_user = usernamehash->user();
+            /* from here on we are working with the original cached credentials. */
             negotiate_request->_auth_user = local_auth_user;
         } else {
             /* store user in hash's */
             local_auth_user->addToNameCache();
-            // authenticateUserNameCacheAdd(local_auth_user);
         }
         /* set these to now because this is either a new login from an
          * existing user or a new user */
index 5f980359658adfabf4f43bdf22d192def5575a9a..e068ccf5664abc4aab92c1be6e8d8b8d3955de0a 100644 (file)
@@ -6,8 +6,6 @@
 #include "helper.h"
 #include "MemPool.h"
 
-// #include "typedefs.h"
-
 class ConnStateData;
 class HttpReply;
 class HttpRequest;
index dbc1515e29aa437f64701e097d40f87217088198..333942403d521ad8b7829eae6b0650c1e819d660 100644 (file)
@@ -264,6 +264,13 @@ NTLMUser::~NTLMUser()
     debugs(29, 5, "NTLMUser::~NTLMUser: doing nothing to clearNTLM scheme data for '" << this << "'");
 }
 
+int32_t
+NTLMUser::ttl() const
+{
+    return -1; // NTLM credentials cannot be cached.
+}
+
+
 static void
 authenticateNTLMStats(StoreEntry * sentry)
 {
index d61eece5e1320e65bc63fe0a76df974ad3e1f967..0a4e01639077b3c74dbc2ab3da0e8fc3497a7ab7 100644 (file)
@@ -18,9 +18,12 @@ class NTLMUser : public AuthUser
 
 public:
     MEMPROXY_CLASS(NTLMUser);
-    virtual void deleteSelf() const;
     NTLMUser(AuthConfig *);
     ~NTLMUser();
+
+    virtual void deleteSelf() const;
+    virtual int32_t ttl() const;
+
     dlink_list proxy_auth_list;
 };
 
index 0e41ccf7a8bcbf0c4d476dd8278dd9220ccf6d68..6f0e107fc181ac443920fc3d47f60f892838f7d7 100644 (file)
@@ -79,15 +79,9 @@ AuthNTLMUserRequest::module_start(RH * handler, void *data)
 {
     authenticateStateData *r = NULL;
     static char buf[8192];
-    ntlm_user_t *ntlm_user;
-    AuthUser *auth_user = user();
 
     assert(data);
     assert(handler);
-    assert(auth_user);
-    assert(auth_user->auth_type == AUTH_NTLM);
-
-    ntlm_user = dynamic_cast<ntlm_user_t *>(user());
 
     debugs(29, 8, "AuthNTLMUserRequest::module_start: auth state is '" << auth_state << "'");
 
@@ -168,15 +162,7 @@ AuthNTLMUserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn,
 {
     const char *proxy_auth, *blob;
 
-    /* TODO: rename this!! */
-    AuthUser *local_auth_user;
-    ntlm_user_t *ntlm_user;
-
-    local_auth_user = user();
-    assert(local_auth_user);
-    assert(local_auth_user->auth_type == AUTH_NTLM);
-    ntlm_user = dynamic_cast<ntlm_user_t *>(local_auth_user);
-    assert (this);
+    assert(this);
 
     /* Check that we are in the client side, where we can generate
      * auth challenges */
@@ -265,11 +251,6 @@ AuthNTLMUserRequest::HandleReply(void *data, void *lastserver, char *reply)
     int valid;
     char *blob;
 
-    AuthUser *auth_user;
-    NTLMUser *ntlm_user;
-    AuthUserRequest::Pointer auth_user_request;
-    AuthNTLMUserRequest *ntlm_request;
-
     debugs(29, 8, "authenticateNTLMHandleReply: helper: '" << lastserver << "' sent us '" << (reply ? reply : "<NULL>") << "'");
     valid = cbdataReferenceValid(r->data);
 
@@ -285,22 +266,18 @@ AuthNTLMUserRequest::HandleReply(void *data, void *lastserver, char *reply)
         reply = (char *)"BH Internal error";
     }
 
-    auth_user_request = r->auth_user_request;
+    AuthUserRequest::Pointer auth_user_request = r->auth_user_request;
     assert(auth_user_request != NULL);
 
-    ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request.getRaw());
+    AuthNTLMUserRequest *ntlm_request = dynamic_cast<AuthNTLMUserRequest *>(auth_user_request.getRaw());
     assert(ntlm_request != NULL);
     assert(ntlm_request->waiting);
+    assert(ntlm_request->user() != NULL);
+    assert(ntlm_request->user()->auth_type == AUTH_NTLM);
+
     ntlm_request->waiting = 0;
     safe_free(ntlm_request->client_blob);
 
-    auth_user = ntlm_request->user();
-    assert(auth_user != NULL);
-    assert(auth_user->auth_type == AUTH_NTLM);
-    ntlm_user = dynamic_cast<ntlm_user_t *>(auth_user_request->user());
-
-    assert(ntlm_user != NULL);
-
     if (ntlm_request->authserver == NULL)
         ntlm_request->authserver = static_cast<helper_stateful_server*>(lastserver);
     else
@@ -308,7 +285,6 @@ AuthNTLMUserRequest::HandleReply(void *data, void *lastserver, char *reply)
 
     /* seperate out the useful data */
     blob = strchr(reply, ' ');
-
     if (blob)
         blob++;
 
@@ -327,31 +303,29 @@ AuthNTLMUserRequest::HandleReply(void *data, void *lastserver, char *reply)
         }
     } else if (strncasecmp(reply, "AF ", 3) == 0) {
         /* we're finished, release the helper */
-        ntlm_user->username(blob);
+        auth_user_request->user()->username(blob);
         auth_user_request->denyMessage("Login successful");
         safe_free(ntlm_request->server_blob);
 
         debugs(29, 4, "authenticateNTLMHandleReply: Successfully validated user via NTLM. Username '" << blob << "'");
         /* connection is authenticated */
-        debugs(29, 4, "AuthNTLMUserRequest::authenticate: authenticated user " << ntlm_user->username());
+        debugs(29, 4, "AuthNTLMUserRequest::authenticate: authenticated user " << auth_user_request->user()->username());
         /* see if this is an existing user with a different proxy_auth
          * string */
-        auth_user_hash_pointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, ntlm_user->username()));
-        AuthUser *local_auth_user = ntlm_request->user();
-        while (usernamehash && (usernamehash->user()->auth_type != AUTH_NTLM || strcmp(usernamehash->user()->username(), ntlm_user->username()) != 0))
+        auth_user_hash_pointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->username()));
+        AuthUser::Pointer local_auth_user = ntlm_request->user();
+        while (usernamehash && (usernamehash->user()->auth_type != AUTH_NTLM || strcmp(usernamehash->user()->username(), auth_user_request->user()->username()) != 0))
             usernamehash = static_cast<AuthUserHashPointer *>(usernamehash->next);
         if (usernamehash) {
             /* we can't seamlessly recheck the username due to the
              * challenge-response nature of the protocol.
              * Just free the temporary auth_user */
             usernamehash->user()->absorb(local_auth_user);
-            //authenticateAuthUserMerge(local_auth_user, usernamehash->user());
             local_auth_user = usernamehash->user();
             ntlm_request->_auth_user = local_auth_user;
         } else {
             /* store user in hash's */
             local_auth_user->addToNameCache();
-            // authenticateUserNameCacheAdd(local_auth_user);
         }
         /* set these to now because this is either a new login from an
          * existing user or a new user */
index 6dda0f3cb1d352c7581aca338b59bbe635d290bf..2e68d9cb427c31bf05475b8a0fdd43791ace2acc 100644 (file)
@@ -33,6 +33,7 @@
 #ifndef SQUID_CLIENTSIDE_H
 #define SQUID_CLIENTSIDE_H
 
+#include "auth/AuthType.h"
 #include "auth/UserRequest.h"
 #include "base/AsyncJob.h"
 #include "BodyPipe.h"
@@ -174,7 +175,7 @@ public:
      * Is this connection based authentication? if so what type it
      * is.
      */
-    auth_type_t auth_type;
+    AuthType auth_type;
 
     /**
      * note this is ONLY connection based because NTLM is against HTTP spec.
index dd909d9caf1512e2c3c5c947b28ab0498d87f42a..1a9562e233180961c77cd8f72d97a31e6a197c84 100644 (file)
@@ -1040,6 +1040,9 @@ statRegisterWithCacheManager(void)
     manager->registerAction("active_requests",
                             "Client-side Active Requests",
                             statClientRequests, 0, 1);
+    manager->registerAction("username_cache",
+                            "Active Cached Usernames",
+                            AuthUser::UsernameCacheStats, 0, 1);
 #if DEBUG_OPENFD
     manager->registerAction("openfd_objects", "Objects with Swapout files open",
                             statOpenfdObj, 0, 0);
index b316c47a42d960849bb184c1a59c76980255c18c..73034c75e7ed7cb6de8955f5eccd7a0a1deebdb1 100644 (file)
@@ -54,10 +54,6 @@ typedef struct {
 /// \deprecated Use AuthUserHashPointer instead.
 typedef struct AuthUserHashPointer auth_user_hash_pointer;
 
-/// \ingroup AuthAPI
-/// \deprecated Use AuthUserIP instead.
-typedef struct AuthUserIP auth_user_ip_t;
-
 /* temporary: once Config is fully hidden, this shouldn't be needed */
 #include "Array.h"