--------------------- PatchSet 538 Date: 2000/08/17 15:21:07 Author: kinkie Branch: ntlm Tag: (none) Log: Removed leftover code Added a few comments Added hash-based caching of credentials, with fast-track authentication Members: ntlm_auth_modules/NTLMSSP/ntlm_auth.c:1.1.2.5->1.1.2.6 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.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid/ntlm_auth_modules/NTLMSSP/ntlm_auth.c 10 Aug 2000 11:53:55 -0000 1.1.2.5 +++ squid/ntlm_auth_modules/NTLMSSP/ntlm_auth.c 17 Aug 2000 15:21:07 -0000 1.1.2.6 @@ -13,14 +13,28 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * Warning! We MIGHT be open to buffer overflows caused by malformed headers + * + * DONE list: + * use hashtable to cache authentications. Yummy performance-boost, security + * loss should be negligible for two reasons: + * - if they-re using NT, there's no security to speak of anyways + * - it can't get worse than basic authentication. + * + * TODO list: + * implement cache expiration + * PDC disconnect, after X minutes of inactivity + * challenge hash expiry and renewal. + * 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 + * */ #include "config.h" - #include "ntlm.h" - #include "util.h" +#include "hash.h" #if HAVE_CTYPE_H #include @@ -40,8 +54,42 @@ #if HAVE_UNISTD_H #include #endif +#if HAVE_STRING_H +#include +#endif + +#if HAVE_TIME_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif + char *domain = NULL, *domain_controller = NULL; +hash_table *cache; + +typedef struct _hash_entry { + char *k; /* the entry's value */ + time_t ctime; /* creation time. */ + char *creds; /* fast-track credentials. */ +} hash_entry; + +static int hashcmp(const void *a, const void *b) { + hash_entry *foo, *bar; + foo=(hash_entry *)a; + bar=(hash_entry *)b; + 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); + return hash4(key,size); +} + /* * options: @@ -70,11 +118,15 @@ } } +int status=0; /* 0=waiting, 1=got neg, waiting for auth */ + int main(int argc, char *argv[]) { char buf[10240]; char *ch, *decoded, *cred; ntlmhdr *fast_header; int plen; + hash_link *lnk; + hash_entry he; /* dummy, used for hash lookups */ process_options(argc,argv); if (domain==NULL) { @@ -86,22 +138,44 @@ "(with the -s argument)\n"); exit(1); } - + + /* initialize FDescs */ setbuf(stdout,NULL); setbuf(stderr,NULL); + + /* initialize cache hashtable */ + cache=hash_create(hashcmp,467,hashhash); - mainloop: while (1) { + while (1) { if(fgets(buf, 10240, stdin) == NULL) exit(0); ch=strchr(buf,'\n'); if (ch) *ch='\0'; /* terminate the string at newline. */ debug("ntlm authenticator. Got '%s' from cache\n",buf); + if (strncmp(buf,"RESET",5)==0) { debug("ntlm authenticator resetting, sending OK\n"); + debug("status %d\n",status); + status=0; printf("RESET OK\n"); continue; } + /* ultra-fast-track credentials checking. We don't even try to understand + what's going on. If it matches anything we got in cache, it's OK for + us.*/ + debug("Trying the fast-track way\n"); + he.k=buf; + lnk=hash_lookup(cache,&he); /* look up the cache */ + debug("lookup done\n"); + if (lnk) { + debug("cache hit. Fast-track-granting.\n"); + OK(((hash_entry *)lnk->key)->creds); + continue; + } else { + debug("cache miss. taking the long route, stopping by Redmond.\n"); + } + /* figure out what we got */ decoded=base64_decode(buf); /* Note: we don't need to manage memory at this point, since @@ -110,6 +184,7 @@ if (!decoded) { /* decoding failure, return error */ ERR("WHAT? Packet format error, couldn't base64-decode"); + status=0; continue; } @@ -119,15 +194,22 @@ /* sanity-check: it IS a NTLMSSP packet, isn't it? */ if (memcmp(fast_header->signature,"NTLMSSP",8) != 0) { ERR("not an NTLMSSP packet. What'cha talking 'bout, Willis?"); + status=0; continue; } /* fast-determine the packet type */ switch (fast_header->type) { case NTLM_NEGOTIATE: + debug("status %d\n",status); + if (status==1) { + fprintf(stderr,"Huh? Got two negotiations in a row\n"); + } + status=1; ch=make_challenge(); if (ch == NULL) { ERR("couldn't obtain a challenge from the Domain Controller\n"); + status=0; continue; } printf("CH %s\n",ch); @@ -137,16 +219,32 @@ continue; break; case NTLM_AUTHENTICATE: + if (status==0) { + fprintf(stderr,"Huh? Got two authentications in a row\n"); + } plen=strlen(buf)*3/4; /* we only need it here. Optimization */ + status=0; cred=ntlm_check_auth((struct ntlm_authenticate *)decoded, plen); if (cred!=NULL) { + hash_entry *h; OK(cred); + /* set the value in the cache */ + 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); + lnk=malloc(sizeof(hash_link)); + lnk->key=(char *)h; + hash_join(cache,lnk); } else { ERR("authentication failure"); } break; default: ERR("unknown authentication packet type"); + status=0; continue; } }