--------------------- PatchSet 634 Date: 2000/10/15 06:06:37 Author: rbcollins Branch: ntlm Tag: (none) Log: Fixed some nasty bugs. helpers are no longer referenced after authentication completes. No more stuck helpers! experimental CHALLENGE-AUTHENTICATION caching (use --enable-ntlm-auth-caching to try it out. Members: ntlm_auth_modules/fakeauth/fakeauth_auth.c:1.1.2.2->1.1.2.3 src/acl.c:1.1.1.3.12.19->1.1.1.3.12.20 src/authenticate.c:1.1.1.3.12.13->1.1.1.3.12.14 src/client_side.c:1.1.1.3.4.1.2.22->1.1.1.3.4.1.2.23 src/enums.h:1.1.1.3.12.10->1.1.1.3.12.11 src/helper.c:1.1.1.3.12.9->1.1.1.3.12.10 src/structs.h:1.1.1.3.4.1.2.18->1.1.1.3.4.1.2.19 src/typedefs.h:1.1.1.3.12.9->1.1.1.3.12.10 Index: squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c =================================================================== RCS file: /cvsroot/squid-sf//squid/ntlm_auth_modules/fakeauth/Attic/fakeauth_auth.c,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c 3 Aug 2000 22:24:34 -0000 1.1.2.2 +++ squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c 15 Oct 2000 06:06:37 -0000 1.1.2.3 @@ -227,6 +227,11 @@ if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; /* strip \n */ + if(strncasecmp(buf,"RESET",5)==0){ + printf("RESET OK\n"); + } + else + { ntlmMakeChallenge(&chal); fmt = "NTLM %s"; @@ -252,20 +257,22 @@ printf(ERR); } else */ if(fgets(buf, 256, stdin) == NULL) exit(0); + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; /* strip \n */ if(strncasecmp(buf,"RESET",5)==0){ printf("RESET OK\n"); -}else -{ - cleartext=(char *)uudecode(buf); - if(ntlmDecodeAuth((struct ntlm_authenticate *)cleartext, user, 256)){ - printf("ERR %s\n",user); - } - else - { - printf("OK %s\n",user); - } -} - - } + } + else { + cleartext=(char *)uudecode(buf); + if(ntlmDecodeAuth((struct ntlm_authenticate *)cleartext, user, 256)){ + printf("ERR %s\n",user); + } + else + { + printf("OK %s\n",user); + } + } + } + } exit(0); } Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3.12.19 retrieving revision 1.1.1.3.12.20 diff -u -r1.1.1.3.12.19 -r1.1.1.3.12.20 --- squid/src/acl.c 13 Oct 2000 12:45:36 -0000 1.1.1.3.12.19 +++ squid/src/acl.c 15 Oct 2000 06:06:38 -0000 1.1.1.3.12.20 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3.12.19 2000/10/13 12:45:36 rbcollins Exp $ + * $Id: acl.c,v 1.1.1.3.12.20 2000/10/15 06:06:38 rbcollins Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1515,13 +1515,15 @@ debug(28,0)("Username to be used is %s\n",authentry->authuser); checklist->conn->auth_state=AUTHENTICATE_STATE_DONE; xstrncpy(checklist->conn->authuser,authentry->authuser,USER_IDENT_SZ); - authenticateNTLMStart("RESET", aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper); +assert(checklist); + authenticateNTLMStart("RESET", aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper); return; /* the rest of this function applies to cache misses */ } } #endif debug(28,6)("aclLookupProxyStatefulAuthStart: Asking NTLM authenticator '%d' on FD '%d'\n",checklist->conn->authhelper,checklist->conn->fd); } +assert(checklist); authenticateNTLMStart(sent_string, aclLookupProxyNTLMAuthDone, checklist, checklist->conn->authhelper); } #endif /*NTLM*/ @@ -2142,6 +2144,7 @@ debug(28,0)("aclLookupProxyNTLMAuthDone: returned RESET OK from helper in state done - assuming this was a cache hit.\n"); } + checklist->conn->authhelper= NULL; break; case AUTHENTICATE_STATE_NEGOTIATE: xstrncpy(checklist->conn->authchallenge,result,NTLM_CHALLENGE_SZ); @@ -2192,7 +2195,7 @@ debug(28,6)("aclLookupProxyNTLMAuthDone: failed NTLM authentication on FD:%d error '%s'\n",checklist->conn->fd,result); } assert(checklist->conn->authhelper); - checklist->conn->authhelper=0; /*clear the handler*/ + checklist->conn->authhelper=0; /*clear the handler*/ break; } aclCheck(checklist); Index: squid/src/authenticate.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v retrieving revision 1.1.1.3.12.13 retrieving revision 1.1.1.3.12.14 diff -u -r1.1.1.3.12.13 -r1.1.1.3.12.14 --- squid/src/authenticate.c 13 Oct 2000 12:45:37 -0000 1.1.1.3.12.13 +++ squid/src/authenticate.c 15 Oct 2000 06:06:38 -0000 1.1.1.3.12.14 @@ -1,6 +1,6 @@ /* - * $Id: authenticate.c,v 1.1.1.3.12.13 2000/10/13 12:45:37 rbcollins Exp $ + * $Id: authenticate.c,v 1.1.1.3.12.14 2000/10/15 06:06:38 rbcollins Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -60,6 +60,7 @@ static helper *authenticators = NULL; #endif #ifdef USE_NTLM +static HLPSCB authenticateNTLMHandleReply; static void authenticateStatefulStateFree(authenticateStatefulStateData * r); static statefulhelper *ntlmauthenticators = NULL; #endif @@ -87,52 +88,66 @@ #endif #ifdef USE_NTLM -static int +static stateful_helper_callback_t authenticateNTLMHandleReply(void *data, void * lastserver, char *reply) /*note: this is not as clean as it should be. the callback NTLMAuthDone should * be returning the value for Morerequests. */ { authenticateStatefulStateData *r = data; - int valid,morerequests=0; + int valid; + stateful_helper_callback_t result = S_HELPER_UNKNOWN; + void *nextserver=NULL; char *t = NULL; debug(29, 5) ("authenticateNTLMHandleReply: Helper: '%d' {%s}\n", lastserver, reply ? reply : ""); if (reply) { if (strncasecmp(reply, "CH ", 3) == 0) { reply += 3; - morerequests=1; + result=S_HELPER_RESERVE; + nextserver=lastserver; debug(29,4)("authenticateNTLMHandleReply: helper '%d'\n",lastserver); } else if (strncasecmp(reply, "OK ", 3) == 0) { - /*give aclNTLM the full header - they must know when it's ok, and 'ERR' _could_ collide with valid domain */ - /* we're finished, leave release the helper*/ - morerequests=0; + /*give aclNTLM the full header - they must know when it's ok, and 'ERR' _could_ collide with valid domain */ + /* we're finished, leave release the helper*/ + result=S_HELPER_RELEASE; } else if (strncasecmp(reply, "RESET OK", 8) == 0) { - /* Helper successfully reset */ - /* note a reset request returning here MUST NOT set morerequests=1*/ - morerequests=0; + /* Helper successfully reset */ + /* note a reset request returning here MUST NOT reserve the helper */ + result=S_HELPER_RELEASE; } else if (strncasecmp(reply, "ERR", 3) == 0) { { - morerequests=0; /*some error has occured. no more requests */ + result=S_HELPER_RELEASE; /*some error has occured. no more requests */ if ((t = strchr(reply, ' ')))/* strip after a space */ *t = '\0'; } } else { - debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply); - // fatal("unknown helper response"); - } + debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply); + // fatal("unknown stateful helper response"); // + } if (*reply == '\0') reply = NULL; } + else + { + fatal("authenticateNTLMHandleReply: called with no result string\n"); + } valid = cbdataValid(r->data); cbdataUnlock(r->data); if (valid) - r->handler(r->data, lastserver, reply); + r->handler(r->data, nextserver, reply); + else + { + debug(29,1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%d'.\n",lastserver); + result=S_HELPER_RELEASE; + } +// cbdataUnlock(r->data); authenticateStatefulStateFree(r); - return morerequests; + debug(29,5)("NTLM HandleReply, telling stateful helper : %d\n",result); + return result; } #endif @@ -205,8 +220,9 @@ { authenticateStatefulStateData *r = NULL; char buf[8192]; -/* assert(auth_user);*/ + assert(proxy_auth); assert(handler); + assert(data); debug(29, 5) ("authenticateNTLMStart: '%s'\n", proxy_auth); if (Config.Program.ntlmauthenticate == NULL) { debug(29, 5) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", proxy_auth); Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.1.1.3.4.1.2.22 retrieving revision 1.1.1.3.4.1.2.23 diff -u -r1.1.1.3.4.1.2.22 -r1.1.1.3.4.1.2.23 --- squid/src/client_side.c 13 Oct 2000 12:45:37 -0000 1.1.1.3.4.1.2.22 +++ squid/src/client_side.c 15 Oct 2000 06:06:38 -0000 1.1.1.3.4.1.2.23 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.1.1.3.4.1.2.22 2000/10/13 12:45:37 rbcollins Exp $ + * $Id: client_side.c,v 1.1.1.3.4.1.2.23 2000/10/15 06:06:38 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -793,20 +793,17 @@ cbdataFree(http); } -#if defined (USE_NTLM) /* || defined (USE_BASIC) etc */ +#if defined (USE_NTLM) /* || defined (USE_DIGEST) etc */ /* This just releases the stateful helper used by a connection */ static void connStateFreeHelperDone(void * data, void * lastserver, char * result) { - ConnStateData *connState = data; - assert(!data); - if (result && (strncasecmp(result, "OK", 2) != 0)){ + ConnCloseHelperData *r = data; + assert(r); /* if we don't have data, then we are making a memory leak */ + if (result && (strncasecmp(result, "RESET OK", 2) != 0)){ debug(33,1)("connStateFreeHelperDone: error resetting stateful helper, result '%s'.\n",result); } -#ifdef USE_NTLM - connState->authhelper=0; -#endif - connStateFree(connState->fd,data); + cbdataFree(r); } #endif @@ -820,8 +817,13 @@ assert(connState != NULL); #ifdef USE_NTLM if (connState->authhelper){ - debug(33,4)("connStateFree: FD %d releasing helper %d.\n",fd,connState->authhelper); - authenticateNTLMStart("RESET",connStateFreeHelperDone,connState,connState->authhelper); + ConnCloseHelperData *r; + debug(33,1)("connStateFree: FD %d releasing helper %d.\n",fd,connState->authhelper); + r=xcalloc(1, sizeof(ConnCloseHelperData)); + cbdataAdd(r, cbdataXfree, 0); + + authenticateNTLMStart("RESET",connStateFreeHelperDone,r,connState->authhelper); + connState->authhelper=NULL; } #endif clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.1.1.3.12.10 retrieving revision 1.1.1.3.12.11 diff -u -r1.1.1.3.12.10 -r1.1.1.3.12.11 --- squid/src/enums.h 13 Oct 2000 12:45:37 -0000 1.1.1.3.12.10 +++ squid/src/enums.h 15 Oct 2000 06:06:38 -0000 1.1.1.3.12.11 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.1.1.3.12.10 2000/10/13 12:45:37 rbcollins Exp $ + * $Id: enums.h,v 1.1.1.3.12.11 2000/10/15 06:06:38 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -517,6 +517,13 @@ #endif } auth_state_t; +/* stateful helper callback response codes */ +typedef enum { + S_HELPER_UNKNOWN, + S_HELPER_RESERVE, + S_HELPER_RELEASE +} stateful_helper_callback_t; + #if SQUID_SNMP enum { SNMP_C_VIEW, Index: squid/src/helper.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/helper.c,v retrieving revision 1.1.1.3.12.9 retrieving revision 1.1.1.3.12.10 diff -u -r1.1.1.3.12.9 -r1.1.1.3.12.10 --- squid/src/helper.c 9 Oct 2000 22:15:58 -0000 1.1.1.3.12.9 +++ squid/src/helper.c 15 Oct 2000 06:06:38 -0000 1.1.1.3.12.10 @@ -1,6 +1,6 @@ /* - * $Id: helper.c,v 1.1.1.3.12.9 2000/10/09 22:15:58 rbcollins Exp $ + * $Id: helper.c,v 1.1.1.3.12.10 2000/10/15 06:06:38 rbcollins Exp $ * * DEBUG: section 29 Helper process maintenance * AUTHOR: Harvest Derived? @@ -181,6 +181,7 @@ srv = memAllocate(MEM_HELPER_STATEFUL_SERVER); cbdataAdd(srv, memFree, MEM_HELPER_STATEFUL_SERVER); srv->flags.alive = 1; + srv->flags.reserved = 0; srv->index = k; srv->rfd = rfd; srv->wfd = wfd; @@ -246,6 +247,7 @@ r->buf = xstrdup(buf); cbdataLock(r->data); if (lastserver){ + debug(29,5)("StatefulSubmit with lastserver %d\n",lastserver); helperStatefulDispatch(lastserver, r); } else @@ -265,7 +267,7 @@ * manage the state in the helper */ { - helper * hlp = srv->parent; + statefulhelper * hlp = srv->parent; helper_stateful_request * r; r = srv->request; if (r != NULL) { @@ -278,7 +280,9 @@ srv->request = NULL; } helperKickQueue(hlp); + debug(29,1)("helperStatefulReset reset helper %s #%d\n",hlp->id_name,srv->index+1); srv->flags.busy = 0; + srv->flags.reserved=0; } void @@ -356,13 +360,14 @@ for (link = hlp->servers.head; link; link = link->next) { srv = link->data; tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time); - storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\t%s\n", + storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c%c\t%7.3f\t%7d\t%s\n", srv->index + 1, srv->rfd, srv->stats.uses, srv->flags.alive ? 'A' : ' ', srv->flags.busy ? 'B' : ' ', srv->flags.closing ? 'C' : ' ', + srv->flags.reserved ? 'R': ' ', srv->flags.shutdown ? 'S' : ' ', tt < 0.0 ? 0.0 : tt, (int) srv->offset, @@ -429,6 +434,11 @@ hlp->id_name, srv->index + 1); continue; } + if (srv->flags.reserved) { + debug(34, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n", + hlp->id_name, srv->index + 1); + continue; + } srv->flags.closing = 1; comm_close(srv->wfd); srv->wfd = -1; @@ -448,7 +458,7 @@ helper * helperStatefulCreate(const char *name) { - helper *hlp = memAllocate(MEM_HELPER_STATEFUL); + statefulhelper *hlp = memAllocate(MEM_HELPER_STATEFUL); cbdataAdd(hlp, memFree, MEM_HELPER_STATEFUL); hlp->id_name = name; return hlp; @@ -632,9 +642,27 @@ /* end of reply found */ debug(29, 3) ("helperStatefulHandleRead: end of reply found\n"); *t = '\0'; - if (cbdataValid(r->data)) - if(!(r->callback(r->data,srv, srv->buf))) /*if non-zero reserve helper */ - srv->flags.busy = 0; + if (cbdataValid(r->data)){ + switch((r->callback(r->data,srv, srv->buf))){ /*if non-zero reserve helper */ + case S_HELPER_UNKNOWN: + fatal("helperStatefulHandleRead: either a non-state aware callback was give to the stateful helper routines, or an uninitialised callback response was recieved.\n"); + break; + case S_HELPER_RELEASE: + srv->flags.reserved = 0; + debug(29, 5)("StatefulHandleRead: releasing %s #%d\n",hlp->id_name, srv->index+1); + break; + case S_HELPER_RESERVE: + srv->flags.reserved = 1; + debug(29, 5)("StatefulHandleRead: reserving %s #%d\n",hlp->id_name, srv->index+1); + break; + default: + fatal("helperStatefulHandleRead: unknown stateful helper callback result.\n"); + } + + } + else + {debug(29,1)("StatefulHandleRead: no callback data registered\n");} + srv->flags.busy = 0; srv->offset = 0; helperStatefulRequestFree(r); srv->request = NULL; @@ -674,7 +702,7 @@ } static void -StatefulEnqueue(helper * hlp, helper_stateful_request * r) +StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r) { dlink_node *link = memAllocate(MEM_DLINK_NODE); dlinkAddTail(r, link, &hlp->queue); @@ -752,6 +780,8 @@ srv = n->data; if (srv->flags.busy) continue; + if (srv->flags.reserved) + continue; if (!srv->flags.alive) continue; return srv; @@ -792,13 +822,14 @@ static void helperStatefulDispatch(helper_stateful_server * srv, helper_stateful_request * r) { - helper *hlp = srv->parent; + statefulhelper *hlp = srv->parent; if (!cbdataValid(r->data)) { debug(29, 1) ("helperStatefulDispatch: invalid callback data\n"); helperStatefulRequestFree(r); return; } /* we keep ourselves busy when we're in a state request. */ + debug(29,9)("helperStatefulDispatch busying helper %s #%d\n",hlp->id_name,srv->index+1); srv->flags.busy = 1; srv->request = r; srv->dispatch_time = current_time; Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.1.1.3.4.1.2.18 retrieving revision 1.1.1.3.4.1.2.19 diff -u -r1.1.1.3.4.1.2.18 -r1.1.1.3.4.1.2.19 --- squid/src/structs.h 13 Oct 2000 12:45:37 -0000 1.1.1.3.4.1.2.18 +++ squid/src/structs.h 15 Oct 2000 06:06:38 -0000 1.1.1.3.4.1.2.19 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1.2.18 2000/10/13 12:45:37 rbcollins Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.19 2000/10/15 06:06:38 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -950,6 +950,11 @@ } defer; }; +/* this is an ugly hack. We need to pass callback data to NTLMStart, when we reset a stateful helper being used when a comms interruption occurs during the negotiate-challenge-authenticate transactions */ +struct _ConnCloseHelperData { + int dummy; +}; + struct _ipcache_addrs { struct in_addr *in_addrs; unsigned char *bad_mask; @@ -1885,7 +1890,13 @@ dlink_node link; helper *parent; helper_stateful_request *request; - struct _helper_flags flags; + struct _helper_stateful_flags { + unsigned int alive:1; + unsigned int busy:1; + unsigned int closing:1; + unsigned int shutdown:1; + unsigned int reserved:1; + } flags; struct { int uses; } stats; Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.1.1.3.12.9 retrieving revision 1.1.1.3.12.10 diff -u -r1.1.1.3.12.9 -r1.1.1.3.12.10 --- squid/src/typedefs.h 13 Oct 2000 12:45:38 -0000 1.1.1.3.12.9 +++ squid/src/typedefs.h 15 Oct 2000 06:06:38 -0000 1.1.1.3.12.10 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.1.1.3.12.9 2000/10/13 12:45:38 rbcollins Exp $ + * $Id: typedefs.h,v 1.1.1.3.12.10 2000/10/15 06:06:38 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -106,6 +106,7 @@ typedef struct _icpUdpData icpUdpData; typedef struct _clientHttpRequest clientHttpRequest; typedef struct _ConnStateData ConnStateData; +typedef struct _ConnCloseHelperData ConnCloseHelperData; typedef struct _ipcache_addrs ipcache_addrs; typedef struct _domain_ping domain_ping; typedef struct _domain_type domain_type; @@ -135,6 +136,7 @@ typedef struct _SwapDir SwapDir; typedef struct _request_flags request_flags; typedef struct _helper_flags helper_flags; +typedef struct _helper_stateful_flags helper_stateful_flags; typedef struct _http_state_flags http_state_flags; typedef struct _request_t request_t; typedef struct _AccessLogEntry AccessLogEntry; @@ -235,7 +237,7 @@ typedef void SIGHDLR(int sig); typedef void STVLDCB(void *, int, int); typedef void HLPCB(void *, char *buf); -typedef int HLPSCB(void *, void * lastserver, char *buf); +typedef stateful_helper_callback_t HLPSCB(void *, void * lastserver, char *buf); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int);