--------------------- PatchSet 1247 Date: 2001/01/10 09:58:27 Author: rbcollins Branch: auth_digest Tag: (none) Log: cleanup nonces when a user is freed rather than waiting for the GC. Members: src/auth/digest/auth_digest.c:1.1.2.17->1.1.2.18 src/auth/digest/auth_digest.h:1.1.2.6->1.1.2.7 Index: squid/src/auth/digest/auth_digest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/digest/auth_digest.c,v retrieving revision 1.1.2.17 retrieving revision 1.1.2.18 diff -u -r1.1.2.17 -r1.1.2.18 --- squid/src/auth/digest/auth_digest.c 10 Jan 2001 07:52:43 -0000 1.1.2.17 +++ squid/src/auth/digest/auth_digest.c 10 Jan 2001 09:58:27 -0000 1.1.2.18 @@ -106,6 +106,8 @@ void authDigestNonceLink(digest_nonce_h *nonce); void authDigestNonceUnlink(digest_nonce_h *nonce); int authDigestNonceLinks(digest_nonce_h *nonce); +void authDigestNonceUserUnlink(digest_nonce_h *nonce); +void authDigestNoncePurge(digest_nonce_h *nonce); void authDigestNonceEncode(digest_nonce_h *nonce) @@ -189,8 +191,11 @@ if (nonce) { assert(nonce->references == 0); +#if UNREACHABLECODE if (nonce->flags.incache) hash_remove_link(digest_nonce_cache, (hash_link *)nonce); +#endif + assert (nonce->flags.incache==0); safe_free(nonce->nonceb64); memPoolFree(digest_nonce_pool, nonce); } @@ -220,10 +225,13 @@ hash_first(digest_nonce_cache); while ((nonce=((digest_nonce_h *)hash_next(digest_nonce_cache)))) { assert (nonce->flags.incache); + authDigestNoncePurge(nonce); +#if 0 hash_remove_link(digest_nonce_cache, (hash_link *)nonce); nonce->flags.incache=0; /* the cache's link */ authDigestNonceUnlink(nonce); +#endif } } if (digest_nonce_pool) @@ -248,7 +256,6 @@ * entries at a time. Lets see how it flys first. */ digest_nonce_h *nonce; - char * nonceb64=NULL; debug(29,3) ("authenticateDigestNonceCacheCleanup: Cleaning the nonce cache now\n"); debug(29,3) ("authenticateDigestNonceCacheCleanup: Current time: %d\n", current_time.tv_sec); @@ -259,10 +266,17 @@ if (authDigestNonceIsStale(nonce)) { debug(29,4)("authenticateDigestNonceCacheCleanup: Removing nonce %s from cache due to timeout.\n",nonce->nonceb64); assert (nonce->flags.incache); + /* invalidate nonce so future requests fail */ + nonce->flags.valid=0; + /* if it is tied to a auth_user, remove the tie */ + authDigestNonceUserUnlink(nonce); + authDigestNoncePurge(nonce); +#if 0 hash_remove_link(digest_nonce_cache, (hash_link *)nonce); nonce->flags.incache=0; /* the cache's link */ authDigestNonceUnlink(nonce); +#endif } } debug(29,3) ("authenticateDigestNonceCacheCleanup: Finished cleaning the nonce cache.\n"); @@ -396,6 +410,19 @@ return 0; } +void +authDigestNoncePurge(digest_nonce_h *nonce) +{ + if (!nonce) + return; + if (!nonce->flags.incache) + return; + hash_remove_link(digest_nonce_cache, (hash_link *)nonce); + nonce->flags.incache=0; + /* the cache's link */ + authDigestNonceUnlink(nonce); +} + /* USER related functions */ @@ -544,8 +571,8 @@ helperFree(digestauthenticators); digestauthenticators = NULL; } - authDigestUserShutdown(); authDigestRequestShutdown(); + authDigestUserShutdown(); authenticateDigestNonceShutdown(); debug(29,2)("authenticateDigestDone: Digest authentication shut down.\n"); } @@ -790,13 +817,13 @@ return; safe_free(digest_user->username); - /* currently the nonces aren't linked in */ link=digest_user->nonces.head; while (link) { tmplink=link; link=link->next; dlinkDelete(tmplink, &digest_user->nonces); + authDigestNoncePurge(tmplink->data); authDigestNonceUnlink(tmplink->data); dlinkNodeDelete(tmplink); } @@ -940,6 +967,40 @@ helperStats(sentry, digestauthenticators); } +/* NonceUserUnlink: remove the reference to auth_user and unlink the node from the list*/ + +void +authDigestNonceUserUnlink(digest_nonce_h *nonce) +{ + digest_user_h * digest_user; + dlink_node *link,*tmplink; + if (!nonce) + return; + if (!nonce->auth_user) + return; + digest_user = nonce->auth_user->scheme_data; + /* unlink from the user list. Yes we're crossing structures but this is the only + * time this code is needed + */ + link=digest_user->nonces.head; + while (link) + { + tmplink=link; + link=link->next; + if (tmplink->data==nonce) + { + dlinkDelete(tmplink, &digest_user->nonces); + authDigestNonceUnlink(tmplink->data); + dlinkNodeDelete(tmplink); + link=NULL; + } + } + /* this reference to auth_user was not locked because freeeing the auth_user frees + * the nonce too. + */ + nonce->auth_user=NULL; +} + /* authDigestUserLinkNonce: add a nonce to a given user's struct */ void @@ -960,10 +1021,14 @@ node=dlinkNodeNew(); dlinkAddTail(nonce,node,&digest_user->nonces); authDigestNonceLink(nonce); + /* ping this nonce to this auth user */ + assert ((nonce->auth_user==NULL) || (nonce->auth_user=auth_user)); + /* we don't lock this reference because removing the auth_user removes the + * hash too. Of course if that changes we're stuffed so read the code huh? + */ + nonce->auth_user=auth_user; } - - /* authenticateDigestUsername: return a pointer to the username in the */ char * authenticateDigestUsername(auth_user_t *auth_user) { @@ -1172,7 +1237,7 @@ /* increment the nonce count */ nonce->nc++; authDigestNonceLink(nonce); - + /* check the qop is what we expected */ if (digest_request->qop && strcmp(digest_request->qop, QOP_AUTH)) { @@ -1213,6 +1278,19 @@ return; } + /* check that we're not being hacked / the username hasn't changed */ + if (nonce->auth_user && strcmp(username, authenticateUserUsername(nonce->auth_user))) + { + debug (29,4)("authenticateDigestDecode: Username for the nonce does not equal the username for the request\n"); + authDigestLogUsername(auth_user_request, username); + + /* we don't need the scheme specific data anymore*/ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data=NULL; + return; + } + + /* if we got a qop, did we get a cnonce or did we get a cnonce wihtout a qop?*/ if ((digest_request->qop && !digest_request->cnonce) || (!digest_request->qop && digest_request->cnonce)) Index: squid/src/auth/digest/auth_digest.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/digest/auth_digest.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid/src/auth/digest/auth_digest.h 8 Jan 2001 23:26:07 -0000 1.1.2.6 +++ squid/src/auth/digest/auth_digest.h 10 Jan 2001 09:58:27 -0000 1.1.2.7 @@ -64,6 +64,8 @@ long nc; /* reference count */ short references; + /* the auth_user this nonce has been tied to */ + auth_user_t * auth_user; /* has this nonce been invalidated ? */ struct { unsigned int valid:1;