--------------------- PatchSet 887 Date: 2000/12/04 12:22:10 Author: rbcollins Branch: auth_rewrite Tag: (none) Log: NTLM Helper protocol V3 Challenge caching and renewal code. Only uses limit support as yet. Time based to come soon. Members: ntlm_auth_modules/fakeauth/fakeauth_auth.c:1.1.2.6.2.4->1.1.2.6.2.5 src/cf.data.pre:1.1.1.3.4.1.2.18->1.1.1.3.4.1.2.18.2.1 src/helper.c:1.1.1.3.12.13.2.1->1.1.1.3.12.13.2.2 src/structs.h:1.1.1.3.4.1.2.26.2.7->1.1.1.3.4.1.2.26.2.8 src/typedefs.h:1.1.1.3.12.13.2.7->1.1.1.3.12.13.2.8 src/auth/ntlm/auth_ntlm.c:1.1.2.7->1.1.2.8 src/auth/ntlm/auth_ntlm.h:1.1.2.1->1.1.2.2 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.6.2.4 retrieving revision 1.1.2.6.2.5 diff -u -r1.1.2.6.2.4 -r1.1.2.6.2.5 --- squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c 4 Dec 2000 11:02:14 -0000 1.1.2.6.2.4 +++ squid/ntlm_auth_modules/fakeauth/fakeauth_auth.c 4 Dec 2000 12:22:10 -0000 1.1.2.6.2.5 @@ -41,7 +41,9 @@ #define ERR "ERR\n" #define OK "OK\n" +#if 0 #define NTLM_STATIC_CHALLENGE "deadbeef" +#endif static char *authenticate_ntlm_domain = "LIFELESSWKS"; /* NTLM authentication by ad@netbsd.org - 07/1999 */ Index: squid/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v retrieving revision 1.1.1.3.4.1.2.18 retrieving revision 1.1.1.3.4.1.2.18.2.1 diff -u -r1.1.1.3.4.1.2.18 -r1.1.1.3.4.1.2.18.2.1 --- squid/src/cf.data.pre 12 Nov 2000 21:22:21 -0000 1.1.1.3.4.1.2.18 +++ squid/src/cf.data.pre 4 Dec 2000 12:22:11 -0000 1.1.1.3.4.1.2.18.2.1 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.1.1.3.4.1.2.18 2000/11/12 21:22:21 rbcollins Exp $ +# $Id: cf.data.pre,v 1.1.1.3.4.1.2.18.2.1 2000/12/04 12:22:11 rbcollins Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1109,6 +1109,25 @@ lots of ntlm authenticator processes. DOC_END +NAME: max_ntlm_challenge_reuses +TYPE: int +DEFAULT: 0 +LOC: Config.ntlmchallengeuses +DOC_START + The maximum number of times a challenge given by a ntlm authentication helper + can be reused. Increasing this number increases your exposure to replay attacks + on your network. See max_ntlm_challenge_lifetime for more information. +DOC_END + +NAME: max_ntlm_challenge_lifetime +TYPE: time_t +DEFAULT: 2 minutes +LOC: Config.ntlmchallengelifetime +DOC_START + The maximum time period that a ntlm challenge is reused over. The actual period + will be the minimum of this time AND the number of reused challenges. +DOC_END + NAME: authenticate_program TYPE: wordlist LOC: Config.Program.authenticate Index: squid/src/helper.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/helper.c,v retrieving revision 1.1.1.3.12.13.2.1 retrieving revision 1.1.1.3.12.13.2.2 diff -u -r1.1.1.3.12.13.2.1 -r1.1.1.3.12.13.2.2 --- squid/src/helper.c 4 Dec 2000 11:02:15 -0000 1.1.1.3.12.13.2.1 +++ squid/src/helper.c 4 Dec 2000 12:22:11 -0000 1.1.1.3.12.13.2.2 @@ -1,6 +1,6 @@ /* - * $Id: helper.c,v 1.1.1.3.12.13.2.1 2000/12/04 11:02:15 rbcollins Exp $ + * $Id: helper.c,v 1.1.1.3.12.13.2.2 2000/12/04 12:22:11 rbcollins Exp $ * * DEBUG: section 29 Helper process maintenance * AUTHOR: Harvest Derived? @@ -300,8 +300,8 @@ continue; if (!srv->flags.alive) continue; - if ((hlp->available != NULL) && (srv->data != NULL) && - !(hlp->available(srv->data))) + if ((hlp->IsAvailable != NULL) && (srv->data != NULL) && + !(hlp->IsAvailable(srv->data))) continue; if ((rv != NULL) && (rv->deferred_requestsdeferred_requests)) continue; @@ -343,6 +343,8 @@ helperStatefulServerKickQueue(srv); }else{ srv->flags.reserved=S_HELPER_FREE; + if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) + srv->parent->OnEmptyQueue(srv->data); helperStatefulKickQueue(hlp); } } @@ -354,7 +356,11 @@ if (srv->deferred_requests>0) srv->deferred_requests--; if (!(srv->deferred_requests) && (srv->flags.reserved==S_HELPER_DEFERRED) && !(srv->queue.head)) + { srv->flags.reserved=S_HELPER_FREE; + if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) + srv->parent->OnEmptyQueue(srv->data); + } } void * @@ -739,6 +745,8 @@ case S_HELPER_RELEASE: /* helper finished with */ if (!srv->queue.head){ srv->flags.reserved = S_HELPER_FREE; + if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) + srv->parent->OnEmptyQueue(srv->data); debug(29, 5)("StatefulHandleRead: releasing %s #%d\n",hlp->id_name, srv->index+1); }else{ srv->flags.reserved = S_HELPER_DEFERRED; @@ -928,7 +936,7 @@ continue; if (!srv->flags.alive) continue; - if ((hlp->available != NULL) && (srv->data != NULL) && !(hlp->available(srv->data))) + if ((hlp->IsAvailable != NULL) && (srv->data != NULL) && !(hlp->IsAvailable(srv->data))) continue; return srv; } Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.1.1.3.4.1.2.26.2.7 retrieving revision 1.1.1.3.4.1.2.26.2.8 diff -u -r1.1.1.3.4.1.2.26.2.7 -r1.1.1.3.4.1.2.26.2.8 --- squid/src/structs.h 4 Dec 2000 11:02:15 -0000 1.1.1.3.4.1.2.26.2.7 +++ squid/src/structs.h 4 Dec 2000 12:22:11 -0000 1.1.1.3.4.1.2.26.2.8 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.7 2000/12/04 11:02:15 rbcollins Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.8 2000/12/04 12:22:11 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -409,7 +409,11 @@ time_t authenticateTTL; time_t authenticateIpTTL; int ntlmauthenticateChildren; + int ntlmchallengeuses; + time_t ntlmchallengelifetime; +#if 0 char *authenticate_ntlm_default_domain; +#endif struct { int single_host; char *host; @@ -1925,7 +1929,8 @@ int n_running; int ipc_type; MemPool *datapool; - HLPSAVAIL *available; + HLPSAVAIL *IsAvailable; + HLPSONEQ *OnEmptyQueue; time_t last_queue_warn; struct { int requests; Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.1.1.3.12.13.2.7 retrieving revision 1.1.1.3.12.13.2.8 diff -u -r1.1.1.3.12.13.2.7 -r1.1.1.3.12.13.2.8 --- squid/src/typedefs.h 4 Dec 2000 11:02:15 -0000 1.1.1.3.12.13.2.7 +++ squid/src/typedefs.h 4 Dec 2000 12:22:11 -0000 1.1.1.3.12.13.2.8 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.1.1.3.12.13.2.7 2000/12/04 11:02:15 rbcollins Exp $ + * $Id: typedefs.h,v 1.1.1.3.12.13.2.8 2000/12/04 12:22:11 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -247,6 +247,7 @@ typedef void HLPCB(void *, char *buf); typedef stateful_helper_callback_t HLPSCB(void *, void * lastserver, char *buf); typedef int HLPSAVAIL(void *); +typedef void HLPSONEQ(void *); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int); Index: squid/src/auth/ntlm/auth_ntlm.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/ntlm/auth_ntlm.c,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -r1.1.2.7 -r1.1.2.8 --- squid/src/auth/ntlm/auth_ntlm.c 4 Dec 2000 11:02:17 -0000 1.1.2.7 +++ squid/src/auth/ntlm/auth_ntlm.c 4 Dec 2000 12:22:12 -0000 1.1.2.8 @@ -80,7 +80,9 @@ static AUTHSSTART authenticateNTLMStart; static AUTHSSTATS authenticateNTLMStats; +/* helper callbacks to handle per server state data */ static HLPSAVAIL authenticateNTLMHelperServerAvailable; +static HLPSONEQ authenticateNTLMHelperServerOnEmpty; static statefulhelper *ntlmauthenticators = NULL; @@ -135,7 +137,8 @@ ntlmauthenticators->n_to_start = Config.ntlmauthenticateChildren; ntlmauthenticators->ipc_type = IPC_TCP_SOCKET; ntlmauthenticators->datapool=ntlm_helper_state_pool; - ntlmauthenticators->available=authenticateNTLMHelperServerAvailable; + ntlmauthenticators->IsAvailable=authenticateNTLMHelperServerAvailable; + ntlmauthenticators->OnEmptyQueue=authenticateNTLMHelperServerOnEmpty; helperStatefulOpenServers(ntlmauthenticators); /* TODO: In here send the initial YR */ if (!ntlminit) { @@ -269,6 +272,7 @@ helperstate->challenge=xstrndup(reply, NTLM_CHALLENGE_SZ+5); /* and we satisfy the request that happended on the refresh boundary */ #endif + /* note this code is now in two places FIXME */ assert(r->auth_user != NULL); assert(r->auth_user->auth_type == AUTH_NTLM); auth_user=r->auth_user; @@ -336,7 +340,8 @@ } #ifndef NTLMHELPPROTOCOLV2 else if (strncasecmp(reply, "BH ", 3) == 0) { - /* TODO kick off a refresh process */ + /* TODO kick off a refresh process */ + fatal("BH handler code not written yet. BYAHAHAHAHAHHA. Please tell Robert on squid-users.\n"); } #endif else { @@ -386,6 +391,26 @@ helperStatefulStats(sentry, ntlmauthenticators); } +/* is a particular challenge still valid ? */ +int +authenticateNTLMValidChallenge(ntlm_helper_state_t *helperstate) +{ + if (helperstate->challenge == NULL) return 0; + return 1; +} + +/* does our policy call for changing the challenge now? */ +int +authenticateNTLMChangeChallenge(ntlm_helper_state_t *helperstate) +{ + /* don't check for invalid challenges just for expiry choices */ + /* this is needed because we have to starve the helper until all old + * requests have been satisfied */ + if (helperstate->challengeuses>Config.ntlmchallengeuses) return 1; + /* TODO: check the lifetime */ + return 0; +} + /* send the initial data to a stateful ntlm authenticator module */ static void authenticateNTLMStart(acl_proxy_auth_user * auth_user, RH * handler, void *data) @@ -455,12 +480,25 @@ * 3: tell it to get a challenge, or give ntlmauthdone the challenge */ server=helperStatefulDefer(ntlmauthenticators); - if (server==NULL) fatal("unable to get a deferred ntlm helper... this shouldn't happen.\n"); helperstate=helperStatefulServerGetData(server); + while ((server !=NULL) && + authenticateNTLMChangeChallenge(helperstate)) + { + /* flag this helper for challenge changing */ + helperstate->starve=1; + /* and release the deferred request */ + helperStatefulReleaseServer(server); + server=helperStatefulDefer(ntlmauthenticators); + helperstate=helperStatefulServerGetData(server); + } + if (server==NULL) fatal("unable to get a deferred ntlm helper... this shouldn't happen.\n"); + + auth_user->auth_data.ntlm_auth.authhelper=server; + /* tell the log what helper we have been given */ + debug(29,5)("authenticateNTLMStart: helper '%d' assigned\n",server); /* valid challenge? */ - if((helperstate->challenge == NULL) || 1) + if(!authenticateNTLMValidChallenge(helperstate)) { - auth_user->auth_data.ntlm_auth.authhelper=server; r = xcalloc(1, sizeof(authenticateStateData)); cbdataAdd(r, cbdataXfree, 0); r->handler = handler; @@ -471,7 +509,13 @@ helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, auth_user->auth_data.ntlm_auth.authhelper); } else { /* we have a valid challenge */ - /* TODO: reuse the challenge */ + /* TODO: turn the below into a function and call from here and handlereply */ + /* increment the challenge uses */ + helperstate->challengeuses++; + /* assign the challenge */ + auth_user->auth_data.ntlm_auth.authchallenge = + xstrndup(helperstate->challenge, NTLM_CHALLENGE_SZ+5); + handler(data, NULL); } break; @@ -514,6 +558,22 @@ return 0; } +void +authenticateNTLMHelperServerOnEmpty(void *data) +{ + ntlm_helper_state_t *statedata=data; + if (statedata == NULL) return; + if (statedata->starve) + { + /* we have been starving the helper */ + debug(29,6)("authenticateNTLMHelperServerOnEmpty: resetting challenge details\n"); + statedata->starve=0; + statedata->challengeuses=0; + xfree(statedata->challenge); + statedata->challenge=NULL; + } +} + /* clear the NTLM helper of being reserved for future requests */ void Index: squid/src/auth/ntlm/auth_ntlm.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/ntlm/auth_ntlm.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/src/auth/ntlm/auth_ntlm.h 4 Dec 2000 11:02:17 -0000 1.1.2.1 +++ squid/src/auth/ntlm/auth_ntlm.h 4 Dec 2000 12:22:12 -0000 1.1.2.2 @@ -9,6 +9,7 @@ struct _ntlm_helper_state_t { char *challenge; /* the challenge to use with this helper */ int starve; /* 0= normal operation. 1=don't hand out any more challenges */ + int challengeuses; /* the number of times this challenge has been issued */ }; typedef struct _ntlm_helper_state_t ntlm_helper_state_t;