--------------------- PatchSet 541 Date: 2000/08/18 15:03:16 Author: kinkie Branch: ntlm Tag: (none) Log: Moved from ctime to atime in cache management. Added housekeeping code for cache cleanup and challenge renewal. Members: ntlm_auth_modules/NTLMSSP/ntlm_auth.c:1.1.2.6->1.1.2.7 Index: squid/ntlm_auth_modules/NTLMSSP/ntlm_auth.c =================================================================== RCS file: /cvsroot/squid-sf//squid/ntlm_auth_modules/NTLMSSP/Attic/ntlm_auth.c,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid/ntlm_auth_modules/NTLMSSP/ntlm_auth.c 17 Aug 2000 15:21:07 -0000 1.1.2.6 +++ squid/ntlm_auth_modules/NTLMSSP/ntlm_auth.c 18 Aug 2000 15:03:16 -0000 1.1.2.7 @@ -27,6 +27,9 @@ * This is somewhat parallel to the PDC disconnect issue * change syntax from options-driven to args-driven, with args domain * or domain[/\]server, and an arbitrary number of backup Domain Controllers + * we don't really need the "status" management, it's more for debugging + * purposes. Remove it. + * Maybe we can cache the created challenge, saving more time? * */ @@ -65,13 +68,19 @@ #include #endif +#if HAVE_SIGNAL_H +#include +#endif + char *domain = NULL, *domain_controller = NULL; -hash_table *cache; +/* cache-related hash and management functions */ + +hash_table *cache; typedef struct _hash_entry { char *k; /* the entry's value */ - time_t ctime; /* creation time. */ + time_t atime; /* creation time. */ char *creds; /* fast-track credentials. */ } hash_entry; @@ -79,17 +88,65 @@ hash_entry *foo, *bar; foo=(hash_entry *)a; bar=(hash_entry *)b; - debug("hashcmp (a='%s',b='%s')\n",foo->k,bar->k); +/* debug("hashcmp (a='%s',b='%s')\n",foo->k,bar->k); */ return strcmp(foo->k,bar->k); } static unsigned int hashhash(const void *data, unsigned int size) { hash_entry *h=(hash_entry *)data; char *key=h->k; - debug("hashhash (data='%s', size=%d)\n",((hash_entry *)data)->k,size); +/* debug("hashhash (data='%s', size=%d)\n",((hash_entry *)data)->k,size); */ return hash4(key,size); } +/* housekeeping cycle and periodic operations */ +static void cleanup_cache() { + time_t now=time(NULL); + hash_link *h; + hash_first(cache); + while (h=((hash_link *)hash_next(cache))) { + hash_entry *e=(hash_entry *)h->key; +#ifdef SHOW_CACHE_CONTENTS_UPON_HOUSEKEEP + debug("cache entry:\n\tchallenge: %s\n\tcreds: %s\n\tage: %d\n", + e->k, e->creds, now-e->atime); +#endif /* SHOW_CACHE_CONTENTS_UPON_HOUSEKEEP */ + if (now - e->atime < ENTRY_EXPIRY) /* recently accessed */ + continue; + debug("freeing entry for creds %s\n",e->creds); + hash_remove_link(cache,h); + free(e->creds); + free(e->k); + free(h); + } +} + +/* I know, it's a dumb function, and ugly to boot. + Let's get stuff working first, and worry about beauty later, OK? */ +static time_t last_refresh=0; +static int need_challenge_refresh=0; +static void refresh_challenge() { + time_t now=time(NULL); + if (last_refresh==0) { + last_refresh=now; + return; + } + /* we really want to do this synchronously, otherwise it might catch + us between challenge and authenticate of an uncached request: + BAMF! instant credentials request!*/ + if ((now-last_refresh)>CHALLENGE_REFLESH) { + debug("Asking for challenge refresh\n"); + need_challenge_refresh=1; + } +} + +/* Huh? It seems to be invoked more often than planned... */ +static void housekeep(int ignored) { + debug("housekeeping..\n"); + signal(SIGALRM,housekeep); + alarm(CYCLE); + cleanup_cache(); + refresh_challenge(); +} /* * options: @@ -145,6 +202,10 @@ /* initialize cache hashtable */ cache=hash_create(hashcmp,467,hashhash); + + /* initialize housekeeping cycle */ + signal(SIGALRM,housekeep); + alarm(CYCLE); while (1) { if(fgets(buf, 10240, stdin) == NULL) exit(0); @@ -167,10 +228,13 @@ debug("Trying the fast-track way\n"); he.k=buf; lnk=hash_lookup(cache,&he); /* look up the cache */ - debug("lookup done\n"); +/* debug("lookup done\n"); */ if (lnk) { + hash_entry *v=(hash_entry *)lnk->key; debug("cache hit. Fast-track-granting.\n"); - OK(((hash_entry *)lnk->key)->creds); + OK(v->creds); + v->atime=time(NULL); + status=0; continue; } else { debug("cache miss. taking the long route, stopping by Redmond.\n"); @@ -206,6 +270,14 @@ fprintf(stderr,"Huh? Got two negotiations in a row\n"); } status=1; + /* Challenge refresh. It's done here so to be done synchronously */ + /* It would be nice to be able to do it while idle though... */ + /* let's leave it like this - for now */ + if (need_challenge_refresh) { + debug("Closing connection to the DC for challenge renewal\n"); + dc_disconnect(); + need_challenge_refresh=0; + } ch=make_challenge(); if (ch == NULL) { ERR("couldn't obtain a challenge from the Domain Controller\n"); @@ -229,12 +301,13 @@ hash_entry *h; OK(cred); /* set the value in the cache */ + debug("storing in cache entry for creds %s\n",cred); h=malloc(sizeof(hash_entry)); h->k=malloc(strlen(buf)+1); strcpy(h->k,buf); h->creds=malloc(sizeof(cred)+1); strcpy(h->creds,cred); - h->ctime=time(NULL); + h->atime=time(NULL); lnk=malloc(sizeof(hash_link)); lnk->key=(char *)h; hash_join(cache,lnk);