--------------------- PatchSet 857 Date: 2000/11/20 13:18:03 Author: rbcollins Branch: auth_rewrite Tag: (none) Log: auth working & half split into modules. Members: src/Makefile.in:1.1.1.3.12.8.2.1->1.1.1.3.12.8.2.2 src/authenticate.c:1.1.1.3.12.17.2.2->1.1.1.3.12.17.2.3 src/client_side.c:1.1.1.3.4.1.2.30->1.1.1.3.4.1.2.30.2.1 src/protos.h:1.1.1.3.12.17.2.2->1.1.1.3.12.17.2.3 src/structs.h:1.1.1.3.4.1.2.26.2.1->1.1.1.3.4.1.2.26.2.2 src/typedefs.h:1.1.1.3.12.13.2.1->1.1.1.3.12.13.2.2 src/auth/Makefile.in:1.1.2.1->1.1.2.2 src/auth/basic/auth_basic.c:1.1->1.1.2.1 src/auth/ntlm/Makefile.in:1.1.2.1->1.1.2.2 src/auth/ntlm/auth_ntlm.c:1.1->1.1.2.1 Index: squid/src/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/Makefile.in,v retrieving revision 1.1.1.3.12.8.2.1 retrieving revision 1.1.1.3.12.8.2.2 diff -u -r1.1.1.3.12.8.2.1 -r1.1.1.3.12.8.2.2 --- squid/src/Makefile.in 20 Nov 2000 06:55:36 -0000 1.1.1.3.12.8.2.1 +++ squid/src/Makefile.in 20 Nov 2000 13:18:03 -0000 1.1.1.3.12.8.2.2 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.1.1.3.12.8.2.1 2000/11/20 06:55:36 rbcollins Exp $ +# $Id: Makefile.in,v 1.1.1.3.12.8.2.2 2000/11/20 13:18:03 rbcollins Exp $ # # Uncomment and customize the following to suit your needs: # @@ -92,6 +92,7 @@ access_log.o \ acl.o \ asn.o \ + auth_modules.o \ authenticate.o \ cache_cf.o \ CacheDigest.o \ @@ -299,6 +300,12 @@ repl_modules repl/stamp: @sh -c "cd repl && $(MAKE) all" +auth_modules.c: auth_modules.sh Makefile + sh $(srcdir)/auth_modules.sh $(AUTH_MODULES) >auth_modules.c + +auth_modules.o: auth_modules.c + $(CC) -c auth_modules.c $(CFLAGS) -I$(srcdir) + $(AUTH_OBJS): @sh -c "cd `dirname $@` && $(MAKE) $(MFLAGS) `basename $@`" @@ -410,7 +417,7 @@ clean: -rm -rf *.o *pure_* core $(PROGS) $(UTILS) $(CGIPROGS) $(SUID_UTILS) -rm -f cf_gen cf_gen_defines.h cf_parser.c cf.data globals.c string_arrays.c - -rm -f store_modules.c repl_modules.c squid.conf + -rm -f store_modules.c repl_modules.c auth_modules.c squid.conf @for dir in $(SUBDIRS); do \ echo "Making $@ in $$dir..."; \ (cd $$dir ; $(MAKE) $(MFLAGS) prefix="$(prefix)" $@) || exit 1; \ Index: squid/src/authenticate.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v retrieving revision 1.1.1.3.12.17.2.2 retrieving revision 1.1.1.3.12.17.2.3 diff -u -r1.1.1.3.12.17.2.2 -r1.1.1.3.12.17.2.3 --- squid/src/authenticate.c 18 Nov 2000 01:39:05 -0000 1.1.1.3.12.17.2.2 +++ squid/src/authenticate.c 20 Nov 2000 13:18:03 -0000 1.1.1.3.12.17.2.3 @@ -1,6 +1,6 @@ /* - * $Id: authenticate.c,v 1.1.1.3.12.17.2.2 2000/11/18 01:39:05 rbcollins Exp $ + * $Id: authenticate.c,v 1.1.1.3.12.17.2.3 2000/11/20 13:18:03 rbcollins Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -64,20 +64,23 @@ authenticateDecodeAuth(const char *proxy_auth, acl_proxy_auth_user * auth_user); /* Basic Scheme */ - +#if 0 static void authenticateBasicStart(acl_proxy_auth_user *, RH *, void *); static HLPCB authenticateBasicHandleReply; static void authenticateDecodeBasicAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth); + static helper *basicauthenticators = NULL; /* NTLM Scheme */ + static void authenticateNTLMStart(acl_proxy_auth_user *, RH * handler, void *); static HLPSCB authenticateNTLMHandleReply; static void authenticateDecodeNTLMAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth); -static statefulhelper *ntlmauthenticators = NULL; +static statefulhelper *ntlmauthenticators = NULL; +#endif /* * @@ -90,6 +93,7 @@ void authenticateDecodeAuth(const char *proxy_auth, acl_proxy_auth_user * auth_user) { + int i = 0; /* if (proxy_auth == NULL) return 0; */ @@ -97,6 +101,19 @@ assert(proxy_auth != NULL); assert(auth_user != NULL); /* we need this created for us. */ debug(29, 6) ("authenticateDecodeAuth: header = '%s'\n", proxy_auth); + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { + if (strncasecmp(proxy_auth, authscheme_list[i].typestr, strlen(authscheme_list[i].typestr)) == 0) { + auth_user->auth_module = i+1; + authscheme_list[i].decodeauth(auth_user, proxy_auth); + return; + } + } + auth_user->auth_type = AUTH_UNKNOWN; + debug(29, 1) + ("authenticateDecodeAuth: Unsupported proxy-auth scheme, '%s'\n", + proxy_auth); + return; +#if 0 if (strncasecmp(proxy_auth, "Basic ", 6) == 0) { if (Config.Program.authenticate != NULL) { proxy_auth += 6; @@ -123,6 +140,7 @@ proxy_auth); auth_user->auth_type = AUTH_UNKNOWN; return; } +#endif } static void @@ -182,7 +200,7 @@ auth_user->ip_expiretime = squid_curtime; return auth_user; } - +#if 0 int authenticateBasicDirection(acl_proxy_auth_user *auth_user) { /* null auth_user is checked for by authenticateDirection */ switch (auth_user->flags.credentials_ok) { @@ -455,14 +473,14 @@ return result; } -#if 0 + static void authenticateNTLMStateFree(authenticateNTLMStateData * r) { cbdataFree(r); } #endif - +#if 0 static void authenticateNTLMStats(StoreEntry * sentry) { @@ -533,6 +551,14 @@ helperStatefulReleaseServer(auth_user->auth_data.ntlm_auth.authhelper); auth_user->auth_data.ntlm_auth.authhelper=NULL; } +#endif +/* clear any connection related authentication details */ +void +authenticateOnCloseConnection(acl_proxy_auth_user *auth_user){ + if (authscheme_list[auth_user->auth_module-1].oncloseconnection){ + authscheme_list[auth_user->auth_module-1].oncloseconnection(auth_user); + } +} #if OBSOLETE /* send the initial data to a stateful ntlm authenticator module */ @@ -563,7 +589,7 @@ debug(29,9)("authenticateNTLMstart: finished\n"); } #endif - +#if 0 /* * Decode an NTLM [Proxy-]Auth string, placing the results in the passed * Auth_user structure. @@ -576,7 +602,7 @@ debug(29, 6) ("authenticateDecodeNTLMAuth: NTLM authentication\n"); return; } - +#endif /**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/ @@ -586,6 +612,12 @@ { assert(auth_user); assert(handler); + if (auth_user->auth_module>0) + authscheme_list[auth_user->auth_module-1].authStart(auth_user, handler, data); + else + handler(data,NULL); +} +#if 0 assert((auth_user->auth_type==AUTH_BASIC) || (auth_user->auth_type==AUTH_NTLM)); switch(auth_user->auth_type) { @@ -602,6 +634,7 @@ default: } } +#endif /* * Check a auth_user pointer for validity. Does not check passwords, just data @@ -901,6 +934,9 @@ authenticateDirection(acl_proxy_auth_user *auth_user) { if (!auth_user) return -2; if (authenticateUserAuthenticated(auth_user)) return 0; + if (auth_user->auth_module>0) + return authscheme_list[auth_user->auth_module-1].getdirection(auth_user); +#if 0 switch (auth_user->auth_type) { case AUTH_UNKNOWN: case AUTH_BROKEN: @@ -910,6 +946,7 @@ case AUTH_NTLM: return authenticateNTLMDirection(auth_user); } +#endif return -2; } @@ -918,6 +955,8 @@ void authenticateInit(void) { + authSchemeSetup(); +#if 0 static int init = 0; static int ntlminit = 0; if (Config.Program.authenticate){ @@ -948,11 +987,14 @@ ntlminit++; } } +#endif } void authenticateShutdown(void) { + int i; +#if 0 if (basicauthenticators) helperShutdown(basicauthenticators); if (ntlmauthenticators) @@ -963,6 +1005,12 @@ basicauthenticators = NULL; helperStatefulFree(ntlmauthenticators); ntlmauthenticators = NULL; +#endif + /* find the currently known authscheme types */ + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { + authscheme_list[i].donefunc(); + authscheme_list[i].typestr=NULL; + } } @@ -1235,6 +1283,26 @@ hash_join(proxy_auth_cache, (hash_link *) proxy_auth_hash); } +/* + * called to add another auth scheme module + */ +void +authSchemeAdd(char *type, AUTHSSETUP * setup) +{ + int i; + /* find the number of currently known authscheme types */ + for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { + assert(strcmp(authscheme_list[i].typestr, type) != 0); + } + /* add the new type */ + authscheme_list = xrealloc(authscheme_list, (i + 2) * sizeof(authscheme_entry_t)); + memset(&authscheme_list[i + 1], 0, sizeof(authscheme_entry_t)); + authscheme_list[i].typestr = type; + /* Call the scheme module to set up capabilities and initialize any global data */ + setup(&authscheme_list[i]); +} + + /* UserNameCacheAdd: add a auth_user structure to the username cache */ void 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.30 retrieving revision 1.1.1.3.4.1.2.30.2.1 diff -u -r1.1.1.3.4.1.2.30 -r1.1.1.3.4.1.2.30.2.1 --- squid/src/client_side.c 16 Nov 2000 11:47:00 -0000 1.1.1.3.4.1.2.30 +++ squid/src/client_side.c 20 Nov 2000 13:18:04 -0000 1.1.1.3.4.1.2.30.2.1 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.1.1.3.4.1.2.30 2000/11/16 11:47:00 rbcollins Exp $ + * $Id: client_side.c,v 1.1.1.3.4.1.2.30.2.1 2000/11/20 13:18:04 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -808,11 +808,9 @@ debug(33, 3) ("connStateFree: FD %d\n", fd); assert(connState != NULL); if (connState->auth_user) { - if ((connState->auth_user->auth_type==AUTH_NTLM) && (connState->auth_user->auth_data.ntlm_auth.authhelper)) { - debug(33,1)("connStateFree: FD %d releasing helper %d.\n",fd,connState->auth_user->auth_data.ntlm_auth.authhelper); - authenticateNTLMReleasehelper(connState->auth_user); - } + authenticateOnCloseConnection(connState->auth_user); authenticateAuthUserUnlock(connState->auth_user); + connState->auth_user=NULL; /* for consistency sake */ } clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ while ((http = connState->chr) != NULL) { Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.1.1.3.12.17.2.2 retrieving revision 1.1.1.3.12.17.2.3 diff -u -r1.1.1.3.12.17.2.2 -r1.1.1.3.12.17.2.3 --- squid/src/protos.h 18 Nov 2000 01:39:05 -0000 1.1.1.3.12.17.2.2 +++ squid/src/protos.h 20 Nov 2000 13:18:04 -0000 1.1.1.3.12.17.2.3 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.1.1.3.12.17.2.2 2000/11/18 01:39:05 rbcollins Exp $ + * $Id: protos.h,v 1.1.1.3.12.17.2.3 2000/11/20 13:18:04 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -702,6 +702,8 @@ extern void redirectInit(void); extern void redirectShutdown(void); +/* auth_modules.c */ +extern void authSchemeSetup(void); /* authenticate.c */ extern void authenticateStart(acl_proxy_auth_user *, RH *, void *); @@ -729,7 +731,8 @@ extern void authenticateUserCacheRestart(); extern char *authenticateUserUsername(acl_proxy_auth_user *auth_user); extern int authenticateValidateUser(acl_proxy_auth_user * auth_user); -extern void authenticateNTLMReleasehelper(acl_proxy_auth_user *auth_user); +extern void authenticateOnCloseConnection(acl_proxy_auth_user *auth_user); +extern void authSchemeAdd(char *type, AUTHSSETUP * setup); extern void refreshAddToList(const char *, int, time_t, int, time_t); extern int refreshIsCachable(const StoreEntry *); 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.1 retrieving revision 1.1.1.3.4.1.2.26.2.2 diff -u -r1.1.1.3.4.1.2.26.2.1 -r1.1.1.3.4.1.2.26.2.2 --- squid/src/structs.h 17 Nov 2000 12:14:33 -0000 1.1.1.3.4.1.2.26.2.1 +++ squid/src/structs.h 20 Nov 2000 13:18:04 -0000 1.1.1.3.4.1.2.26.2.2 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.1 2000/11/17 12:14:33 rbcollins Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.2 2000/11/20 13:18:04 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -103,6 +103,7 @@ struct _acl_proxy_auth_user { /* extra fields for proxy_auth */ auth_type_t auth_type; /* this determines what struct we find in the union. */ + int auth_module; /* the index +1 in the authscheme_list to the authscheme entry */ /* the we only have one username associated with a given auth_user struct */ acl_proxy_auth_hash_pointer *usernamehash; /* we may have many proxy-authenticate strings that decode to the same user*/ @@ -125,6 +126,22 @@ } auth_data; }; +/* + * This defines an auth scheme + */ + +struct _authscheme_entry { + char *typestr; +// STFSPARSE *parsefunc; +// STFSRECONFIGURE *reconfigurefunc; + AUTHSONCLOSEC *oncloseconnection; + AUTHSDECODE *decodeauth; + AUTHSDIRECTION *getdirection; + AUTHSSHUTDOWN *donefunc; + AUTHSSTART *authStart; + AUTHSSTATS *authStats; +}; + struct _acl_deny_info_list { int err_page_id; char *err_page_name; Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,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/typedefs.h 20 Nov 2000 06:55:36 -0000 1.1.1.3.12.13.2.1 +++ squid/src/typedefs.h 20 Nov 2000 13:18:04 -0000 1.1.1.3.12.13.2.2 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.1.1.3.12.13.2.1 2000/11/20 06:55:36 rbcollins Exp $ + * $Id: typedefs.h,v 1.1.1.3.12.13.2.2 2000/11/20 13:18:04 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -210,8 +210,6 @@ typedef void EVH(void *); typedef void PF(int, void *); -/* authenticate.c authenticate scheme routines typedefs */ - /* disk.c / diskd.c callback typedefs */ typedef void DRCB(int, const char *buf, int size, int errflag, void *data); /* Disk read CB */ @@ -291,6 +289,15 @@ typedef double hbase_f(double); typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count); +/* authenticate.c authenticate scheme routines typedefs */ +typedef void AUTHSDECODE(acl_proxy_auth_user *, const char *); +typedef int AUTHSDIRECTION(acl_proxy_auth_user *); +typedef void AUTHSONCLOSEC(acl_proxy_auth_user *); +typedef void AUTHSSETUP(authscheme_entry_t *); +typedef void AUTHSSHUTDOWN(void); +typedef void AUTHSSTART(acl_proxy_auth_user * , RH * , void *); +typedef void AUTHSSTATS(StoreEntry *); + /* append/vprintf's for Packer */ typedef void (*append_f) (void *, const char *buf, int size); #if STDC_HEADERS Index: squid/src/auth/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/Attic/Makefile.in,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/Makefile.in 20 Nov 2000 07:40:35 -0000 1.1.2.1 +++ squid/src/auth/Makefile.in 20 Nov 2000 13:18:04 -0000 1.1.2.2 @@ -8,29 +8,29 @@ all: @test -z "$(SUBDIRS)" || for dir in $(SUBDIRS); do \ - sh -c "cd $$dir && $(MAKE) $(MFLAGS) all" || exit 1; \ - done + sh -c "cd $$dir && $(MAKE) $(MFLAGS) all" || exit 1; \ + done; $(OUTLIBS): @sh -c "cd `basename $@ .a` && $(MAKE) $(MFLAGS) ../$@" clean: -rm -f *.a stamp - @for dir in *; do \ - if [ -f $$dir/Makefile ]; then \ - sh -c "cd $$dir && $(MAKE) $(MFLAGS) $@" || exit 1;\ - fi; \ - done + -for dir in *; do \ + if [ -f $$dir/Makefile ]; then \ + sh -c "cd $$dir && $(MAKE) $(MFLAGS) $@" || exit 1;\ + fi; \ + done distclean: -rm -f *.a Makefile - @for dir in *; do \ - if [ -f $$dir/Makefile ]; then \ - sh -c "cd $$dir && $(MAKE) $(MFLAGS) distclean"; \ - fi; \ - done + -for dir in *; do \ + if [ -f $$dir/Makefile ]; then \ + sh -c "cd $$dir && $(MAKE) $(MFLAGS) distclean"; \ + fi; \ + done .DEFAULT: @test -z "$(SUBDIRS)" || for dir in $(SUBDIRS); do \ - sh -c "cd $$dir && $(MAKE) $(MFLAGS) $@" || exit 1; \ - done + sh -c "cd $$dir && $(MAKE) $(MFLAGS) $@" || exit 1; \ + done --- /dev/null Wed Feb 14 00:45:56 2007 +++ squid/src/auth/basic/auth_basic.c Wed Feb 14 00:46:58 2007 @@ -0,0 +1,320 @@ + +/* + * $Id$ + * + * DEBUG: section 29 Authenticator + * AUTHOR: Duane Wessels + * + * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from the + * Internet community. Development is led by Duane Wessels of the + * National Laboratory for Applied Network Research and funded by the + * National Science Foundation. Squid is Copyrighted (C) 1998 by + * the Regents of the University of California. Please see the + * COPYRIGHT file for full details. Squid incorporates software + * developed and/or copyrighted by other sources. Please see the + * CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* The functions in this file handle authentication. + They DO NOT perform access control or auditing. + See acl.c for access control and client_side.c for auditing */ + + +#include "squid.h" + +#if 0 +typedef struct { + void *data; + acl_proxy_auth_user *auth_user; +// SRH *handler; + RH *handler; +} authenticateStatefulStateData; +#endif +#if 0 +static void authenticateStatefulStateFree(authenticateStatefulStateData * r); +#endif + +/* Generic */ +typedef struct { + void *data; + acl_proxy_auth_user *auth_user; + RH *handler; +} authenticateStateData; + +static void +authenticateStateFree(authenticateStateData * r) +{ + cbdataFree(r); +} + +/* Basic Scheme */ + +static void authenticateBasicStart(acl_proxy_auth_user *, RH *, void *); +static HLPCB authenticateBasicHandleReply; +static AUTHSDIRECTION authenticateBasicDirection; +static AUTHSDECODE authenticateBasicDecodeAuth; +static AUTHSSTART authenticateBasicStart; +static AUTHSSTATS authenticateBasicStats; + +static helper *basicauthenticators = NULL; + +static int authbasic_initialised = 0; + +/* + * + * Private Functions + * + */ + +void +authBasicDone(void) +{ +// memPoolDestroy(ufs_state_pool); + if (basicauthenticators) + helperShutdown(basicauthenticators); + authbasic_initialised = 0; + helperFree(basicauthenticators); + basicauthenticators = NULL; +} + +void +authSchemeSetup_basic(authscheme_entry_t *authscheme) { +static int init = 0; + assert(!authbasic_initialised); +// authscheme->parsefunc = storeUfsDirParse; +// authscheme->reconfigurefunc = storeUfsDirReconfigure; + authscheme->authStart =authenticateBasicStart; + authscheme->authStats =authenticateBasicStats; + authscheme->getdirection=authenticateBasicDirection; + authscheme->oncloseconnection=NULL; + authscheme->decodeauth =authenticateBasicDecodeAuth; + authscheme->donefunc = authBasicDone; +// ufs_state_pool = memPoolCreate("UFS IO State data", sizeof(ufsstate_t)); + if (Config.Program.authenticate){ + if (basicauthenticators == NULL) + basicauthenticators = helperCreate("basicauthenticator"); + basicauthenticators->cmdline = Config.Program.authenticate; + basicauthenticators->n_to_start = Config.authenticateChildren; + basicauthenticators->ipc_type = IPC_TCP_SOCKET; + helperOpenServers(basicauthenticators); + if (!init) { + cachemgrRegister("basicauthenticator", + "User Authenticator Stats", + authenticateBasicStats, 0, 1); + init++; + } + } + authbasic_initialised = 1; +} + +/* log a basic user in + */ +static acl_proxy_auth_user * +authenticateBasicAuthenticateUser(acl_proxy_auth_user *data, const char * proxy_auth) { + acl_proxy_auth_hash_pointer *usernamehash, *proxy_auth_hash=NULL; + acl_proxy_auth_user *auth_user=data; + /* if the password is not ok, do an identity */ + if (auth_user->flags.credentials_ok!=1) + return auth_user; + + /* password was checked and did match */ + debug(29, 4) ("authenticateBasicAuthenticateuser: user '%s' validated OK\n", + auth_user->auth_data.basic_auth.username); + /* see if this is an existing user with a different proxy_auth string */ + if ((usernamehash = hash_lookup(proxy_auth_username_cache, + auth_user->auth_data.basic_auth.username))) { + while ((usernamehash->auth_user->auth_type != auth_user->auth_type) && + (usernamehash->next) && + !strcmp(usernamehash->auth_user->auth_data.basic_auth.username,auth_user->auth_data.basic_auth.username) ) + usernamehash=usernamehash->next; + if (usernamehash->auth_user->auth_type==auth_user->auth_type) { + /* + * add another link from the new proxy_auth to the + * auth_user structure and update the information */ + assert(proxy_auth_hash == NULL); + authenticateProxyAuthCacheAddLink(proxy_auth, usernamehash->auth_user); + /* maybe the p/w changed. update in the old structure */ + xfree(usernamehash->auth_user->auth_data.basic_auth.passwd); + usernamehash->auth_user->auth_data.basic_auth.passwd = + auth_user->auth_data.basic_auth.passwd; + auth_user->auth_data.basic_auth.passwd = NULL; + /* and remove the temporary structure */ + authenticateAuthUserUnlock(auth_user); + authenticateFreeProxyAuthUser(auth_user); + auth_user = usernamehash->auth_user; + /* lock the structure for this request */ + authenticateAuthUserLock(auth_user); + } + } else { + /* store user in hash's */ + authenticateUserNameCacheAdd(auth_user); + authenticateProxyAuthCacheAddLink(proxy_auth, auth_user); + } + /* auth_user is now linked, we reset these values + * after external auth occurs anyway */ + auth_user->expiretime = current_time.tv_sec; + auth_user->ip_expiretime = squid_curtime; + return auth_user; +} + +int authenticateBasicDirection(acl_proxy_auth_user *auth_user) { +/* null auth_user is checked for by authenticateDirection */ + switch (auth_user->flags.credentials_ok) { + case 0: /* not checked */ + return -1; + case 1: /* checked & ok */ + return 0; + case 2: /* partway through checking. Invalid for basic */ + return -2; + case 3: /* authentication process failed. */ + return -2; + } + return -2; +} + +static void +authenticateBasicHandleReply(void *data, char *reply) +{ + authenticateStateData *r = data; + acl_proxy_auth_user *auth_user; + int valid; + char *t = NULL; + debug(29, 5) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : ""); + if (reply) { + if ((t = strchr(reply, ' '))) + *t = '\0'; + if (*reply == '\0') + reply = NULL; + } + assert(r->auth_user != NULL); + assert(r->auth_user->auth_type == AUTH_BASIC); + auth_user=r->auth_user; + if (reply && (strncasecmp(reply, "OK", 2) == 0)) + auth_user->flags.credentials_ok = 1; + else + auth_user->flags.credentials_ok = 2; + valid = cbdataValid(r->data); + cbdataUnlock(r->data); + if (valid) + r->handler(r->data, NULL); +#if 0 + if (valid) + r->handler(r->data, reply); +#endif + authenticateStateFree(r); +} + +static void +authenticateBasicStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "Basic Authenticator Statistics:\n"); + helperStats(sentry, basicauthenticators); +} + +/* + * Decode a Basic [Proxy-]Auth string, placing the results in the passed + * Auth_user structure. + */ + +static void +authenticateBasicDecodeAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth) { + char *sent_auth; + char *cleartext; + assert(auth_user->auth_type == AUTH_UNKNOWN); + + /* trim BASIC from string */ + while (!xisspace(*proxy_auth)) + proxy_auth++; + + /* Trim leading whitespace before decoding */ + while (xisspace(*proxy_auth)) + proxy_auth++; + /* username and password */ + sent_auth = xstrdup(proxy_auth); + /* Trim trailing \n before decoding */ + strtok(sent_auth, "\n"); + cleartext = uudecode(sent_auth); + xfree(sent_auth); + /* + * Don't allow NL or CR in the credentials. + * Oezguer Kesim + */ + strtok(cleartext, "\r\n"); + debug(29, 6) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext); + /* have we been called twice? */ + assert(auth_user->auth_data.basic_auth.username == NULL); + auth_user->auth_data.basic_auth.username = + xstrndup(cleartext, USER_IDENT_SZ); + xfree(cleartext); + /* again, have we been called twice? */ + assert(auth_user->auth_data.basic_auth.passwd == NULL); + if ((cleartext = + strchr(auth_user->auth_data.basic_auth.username, ':')) != NULL) + *(cleartext)++ = '\0'; + if (cleartext == NULL) { + debug(29, 2) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n", + proxy_auth); auth_user->auth_type = AUTH_BROKEN; + } + if (*cleartext == '\0') { + debug(29, 2) ("authenticateBasicDecodeAuth: Disallowing empty password," + "user is '%s'\n", auth_user->auth_data.basic_auth.username); + auth_user->auth_type = AUTH_BROKEN; + } + /* special case: we have to free the strings for user and password + * if we are not returning AUTH_BASIC else the UserFree function will + * be confused. + */ + if (auth_user->auth_type != AUTH_BASIC) { + if (auth_user->auth_data.basic_auth.username) + xfree(auth_user->auth_data.basic_auth.username); + } else { + auth_user->auth_data.basic_auth.passwd = xstrndup(cleartext, USER_IDENT_SZ); + } + /* we are finished with the proxy_auth */ +// xfree(auth_user->proxy_auth); +// auth_user->proxy_auth = NULL; + return; +} + +/* send the initial data to a basic authenticator module */ +static void +authenticateBasicStart(acl_proxy_auth_user * auth_user, RH * handler, void *data) +{ + authenticateStateData *r = NULL; + char buf[8192]; + assert(auth_user); + assert(handler); + assert(auth_user->auth_type==AUTH_BASIC); + debug(29, 5) ("authenticateStart: '%s:%s'\n", auth_user->auth_data.basic_auth.username, + auth_user->auth_data.basic_auth.passwd); + if (Config.Program.authenticate == NULL) { + handler(data, NULL); + return; + } + r = xcalloc(1, sizeof(authenticateStateData)); + cbdataAdd(r, cbdataXfree, 0); + r->handler = handler; + cbdataLock(data); + r->data = data; + r->auth_user = auth_user; + snprintf(buf, 8192, "%s %s\n", auth_user->auth_data.basic_auth.username, auth_user->auth_data.basic_auth.passwd); + helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r); +} Index: squid/src/auth/ntlm/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/ntlm/Attic/Makefile.in,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/Makefile.in 20 Nov 2000 07:40:35 -0000 1.1.2.1 +++ squid/src/auth/ntlm/Makefile.in 20 Nov 2000 13:18:04 -0000 1.1.2.2 @@ -4,7 +4,7 @@ # $Id$ # -AUTH = ntlm +AUTH = ntlm top_srcdir = @top_srcdir@ VPATH = @srcdir@ --- /dev/null Wed Feb 14 00:45:56 2007 +++ squid/src/auth/ntlm/auth_ntlm.c Wed Feb 14 00:46:58 2007 @@ -0,0 +1,566 @@ + +/* + * $Id$ + * + * DEBUG: section 29 Authenticator + * AUTHOR: Duane Wessels + * + * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from the + * Internet community. Development is led by Duane Wessels of the + * National Laboratory for Applied Network Research and funded by the + * National Science Foundation. Squid is Copyrighted (C) 1998 by + * the Regents of the University of California. Please see the + * COPYRIGHT file for full details. Squid incorporates software + * developed and/or copyrighted by other sources. Please see the + * CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* The functions in this file handle authentication. + They DO NOT perform access control or auditing. + See acl.c for access control and client_side.c for auditing */ + + +#include "squid.h" + +#if 0 +typedef struct { + void *data; + acl_proxy_auth_user *auth_user; +// SRH *handler; + RH *handler; +} authenticateStatefulStateData; +#endif +#if 0 +static void authenticateStatefulStateFree(authenticateStatefulStateData * r); +#endif + +/* Generic */ +typedef struct { + void *data; + acl_proxy_auth_user *auth_user; + RH *handler; +} authenticateStateData; + +static void +authenticateStateFree(authenticateStateData * r) +{ + cbdataFree(r); +} + +/* NTLM Scheme */ +static void authenticateNTLMStart(acl_proxy_auth_user *, RH * handler, void *); +static HLPSCB authenticateNTLMHandleReply; +static AUTHSDIRECTION authenticateNTLMDirection; +static AUTHSDECODE authenticateDecodeNTLMAuth; +static AUTHSONCLOSEC authenticateNTLMOnCloseConnection; +static AUTHSSTART authenticateNTLMStart; +static AUTHSSTATS authenticateNTLMStats; + +static statefulhelper *ntlmauthenticators = NULL; + +static int authntlm_initialised = 0; + +/* + * + * Private Functions + * + */ + +void +authNTLMDone(void) +{ +// memPoolDestroy(ufs_state_pool); + + if (ntlmauthenticators) + helperStatefulShutdown(ntlmauthenticators); + authntlm_initialised = 0; + if (!shutting_down) + return; + helperStatefulFree(ntlmauthenticators); + ntlmauthenticators = NULL; +} + +void +authSchemeSetup_ntlm(authscheme_entry_t *authscheme) { +static int ntlminit = 0; + assert(!authntlm_initialised); +// authscheme->parsefunc = storeUfsDirParse; +// authscheme->reconfigurefunc = storeUfsDirReconfigure; + authscheme->authStart =authenticateNTLMStart; + authscheme->authStats =authenticateNTLMStats; + authscheme->getdirection=authenticateNTLMDirection; + authscheme->decodeauth =authenticateDecodeNTLMAuth; + authscheme->donefunc = authNTLMDone; + authscheme->oncloseconnection = authenticateNTLMOnCloseConnection; +// ufs_state_pool = memPoolCreate("UFS IO State data", sizeof(ufsstate_t)); + authntlm_initialised = 1; + if (Config.Program.ntlmauthenticate){ + if (ntlmauthenticators == NULL) + ntlmauthenticators = helperStatefulCreate("ntlmauthenticator"); + ntlmauthenticators->cmdline = Config.Program.ntlmauthenticate; + ntlmauthenticators->n_to_start = Config.ntlmauthenticateChildren; + ntlmauthenticators->ipc_type = IPC_TCP_SOCKET; + helperStatefulOpenServers(ntlmauthenticators); + if (!ntlminit) { + cachemgrRegister("ntlmauthenticator", + "User NTLM Authenticator Stats", + authenticateNTLMStats, 0, 1); + ntlminit++; + } + } +} + +/* NTLM Scheme */ + +int authenticateNTLMDirection(acl_proxy_auth_user *auth_user) { +/* null auth_user is checked for by authenticateDirection */ + switch (auth_user->auth_data.ntlm_auth.auth_state) { + case AUTHENTICATE_STATE_NONE: /* no progress at all.*/ + debug(28,1) ("authenticateNTLMDirection: called before NTLM Authenticate!. Report a bug to squid-dev.\n"); + return -2; + case AUTHENTICATE_STATE_NEGOTIATE: /* send to helper */ + case AUTHENTICATE_STATE_RESPONSE: /*send to helper */ + return -1; + case AUTHENTICATE_STATE_CHALLENGE: /* send to client */ + return 1; + case AUTHENTICATE_STATE_DONE: /* do nothing.. */ + return 0; + } + return -2; +} + +static stateful_helper_callback_t +authenticateNTLMHandleReply(void *data, void * lastserver, char *reply) +{ +#if 0 + authenticateStatefulStateData *r = data; +#endif + authenticateStateData *r = data; + int valid; + stateful_helper_callback_t result = S_HELPER_UNKNOWN; +#if 0 + void *nextserver=NULL; +#endif + char *t = NULL; + acl_proxy_auth_user *auth_user; + debug(29, 5) ("authenticateNTLMHandleReply: Helper: '%d' {%s}\n", lastserver, reply ? reply : ""); + valid = cbdataValid(r->data); + cbdataUnlock(r->data); + if (valid) { + if (reply) { + /* seperate out the useful data */ + if (strncasecmp(reply, "CH ", 3) == 0) { + reply += 3; + /* we have been given a Challenge */ + /* we should check we weren't given an empty challenge */ +#if 0 + result=S_HELPER_RESERVE; +#endif + assert(r->auth_user != NULL); + assert(r->auth_user->auth_type == AUTH_NTLM); + auth_user=r->auth_user; + result=S_HELPER_DEFER; +#if 0 + nextserver=lastserver; +#endif + debug(29,5)("authenticateNTLMHandleReply: helper '%d'\n",lastserver); + assert(auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_NEGOTIATE); +// auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_CHALLENGE; + auth_user->auth_data.ntlm_auth.authhelper = lastserver; + auth_user->auth_data.ntlm_auth.authchallenge = + xstrndup(reply, NTLM_CHALLENGE_SZ+5); + } + else if (strncasecmp(reply, "OK ", 3) == 0) { + /* we're finished, release the helper*/ + reply+=3; + assert(r->auth_user != NULL); + assert(r->auth_user->auth_type == AUTH_NTLM); + auth_user=r->auth_user; + result=S_HELPER_RELEASE; + /* we only expect OK when finishing the handshake */ + assert(auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_RESPONSE); + auth_user->auth_data.ntlm_auth.username = xstrndup(reply, MAX_LOGIN_SZ); + auth_user->auth_data.ntlm_auth.authhelper = NULL; + auth_user->flags.credentials_ok = 1; /* login ok */ + } + else if (strncasecmp(reply, "RESET OK", 8) == 0) { + /* Helper successfully reset */ + /* note a reset request returning here MUST NOT reserve the helper */ + /* also auth_user does not need to be valid on a reset call */ + result=S_HELPER_RELEASE; + if (r->auth_user) r->auth_user->auth_data.ntlm_auth.authhelper=NULL; + } + else if (strncasecmp(reply, "ERR", 3) == 0) { + /* TODO: only work with auth_user here if it exists */ + assert(r->auth_user != NULL); + assert(r->auth_user->auth_type == AUTH_NTLM); + auth_user=r->auth_user; + /* todo: action of Negotiate state on error */ + result=S_HELPER_RELEASE; /*some error has occured. no more requests */ + auth_user->auth_data.ntlm_auth.authhelper = NULL; + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NONE; + if (auth_user->auth_data.ntlm_auth.auth_state == AUTHENTICATE_STATE_NEGOTIATE) { + /* The helper rejected the negotiate. It automatically + * resets */ + auth_user->flags.credentials_ok = 3; /* cannot process */ + debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %d.\n", lastserver); + } else { + auth_user->flags.credentials_ok = 2; /* Login/Usercode failed */ + debug(29, 1) ("authenticateNTLMHandleReply: Error validating user via NTLM.\n"); + } + if ((t = strchr(reply, ' ')))/* strip after a space */ + *t = '\0'; + } else { + /* TODO: only work with auth_user here if it exists */ + assert(r->auth_user != NULL); + assert(r->auth_user->auth_type == AUTH_NTLM); + auth_user=r->auth_user; + debug(29, 1) ("authenticateNTLMHandleReply: Unsupported helper response, '%s'\n", reply); + /* restart the authentication process */ + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NONE; + auth_user->flags.credentials_ok = 3; /* cannot process */ + auth_user->auth_data.ntlm_auth.authhelper = NULL; + } +#if 0 + if (*reply == '\0') + reply = NULL; +#endif + } else { + fatal("authenticateNTLMHandleReply: called with no result string\n"); + } +// r->handler(r->data, nextserver, reply); + r->handler(r->data, NULL); + } else { + debug(29,1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%d'.\n",lastserver); + result=S_HELPER_RELEASE; + } +#if 0 + authenticateStatefulStateFree(r); +#endif + authenticateStateFree(r); + debug(29,5)("NTLM HandleReply, telling stateful helper : %d\n",result); + return result; +} + +#if 0 +static void +authenticateNTLMStateFree(authenticateNTLMStateData * r) +{ + cbdataFree(r); +} +#endif + +static void +authenticateNTLMStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "NTLM Authenticator Statistics:\n"); + helperStatefulStats(sentry, ntlmauthenticators); +} + +/* send the initial data to a stateful ntlm authenticator module */ +static void +authenticateNTLMStart(acl_proxy_auth_user * auth_user, RH * handler, void *data) +{ +#if 0 + authenticateStatefulStateData *r = NULL; +#endif + authenticateStateData *r = NULL; + char buf[8192]; + char *sent_string=NULL; + + assert(auth_user); + assert(handler); + assert(data); + assert(auth_user->auth_type=AUTH_NTLM); + switch(auth_user->auth_data.ntlm_auth.auth_state) { + case AUTHENTICATE_STATE_NEGOTIATE: + sent_string = xstrdup(auth_user->auth_data.ntlm_auth.ntlmnegotiate); + break; + case AUTHENTICATE_STATE_RESPONSE: + sent_string = xstrdup(auth_user->auth_data.ntlm_auth.ntlmauthenticate); + assert(auth_user->auth_data.ntlm_auth.authhelper); + debug(28, 6) ("authenticateNTLMStart: Asking NTLMauthenticator '%d'.\n", auth_user->auth_data.ntlm_auth.authhelper); + break; + default: + fatal("Invalid authenticate state for NTLMStart"); + } + + while (!xisspace(*sent_string)) /*trim NTLM */ + sent_string++; + + while (xisspace(*sent_string)) /*trim leading spaces */ + sent_string++; + debug(29, 5) ("authenticateNTLMStart: state '%d'\n", auth_user->auth_data.ntlm_auth.auth_state); + debug(29, 5) ("authenticateNTLMStart: '%s'\n", sent_string); + if (Config.Program.ntlmauthenticate == NULL) { + debug(29, 1) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", sent_string); +// handler(data,0, NULL); + handler(data, NULL); + return; + } + r = xcalloc(1, sizeof(authenticateStateData)); +#if 0 + r = xcalloc(1, sizeof(authenticateStatefulStateData)); +#endif + cbdataAdd(r, cbdataXfree, 0); + r->handler = handler; + cbdataLock(data); + r->data = data; + r->auth_user = auth_user; + snprintf(buf, 8192, "%s\n", sent_string); + helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, auth_user->auth_data.ntlm_auth.authhelper); + debug(29,9)("authenticateNTLMstart: finished\n"); +} + +/* clear the NTLM helper of being reserved for future requests */ +void +authenticateNTLMReleasehelper(acl_proxy_auth_user *auth_user){ + assert(auth_user->auth_type==AUTH_NTLM); + debug(29,5) ("authenticateNTLMReleasehelper: releasing helper '%d'\n",auth_user->auth_data.ntlm_auth.authhelper); + helperStatefulReleaseServer(auth_user->auth_data.ntlm_auth.authhelper); + auth_user->auth_data.ntlm_auth.authhelper=NULL; +} + +/* clear any connection related authentication details */ +void +authenticateNTLMOnCloseConnection(acl_proxy_auth_user *auth_user) { + if (auth_user->auth_data.ntlm_auth.authhelper != NULL) + authenticateNTLMReleasehelper(auth_user); +} + +#if OBSOLETE +/* send the initial data to a stateful ntlm authenticator module */ +void +authenticateNTLMStart(const char *proxy_auth, SRH * handler, void *data, helper_ +stateful_server * lastserver) +{ + authenticateStatefulStateData *r = NULL; + char buf[8192]; + assert(proxy_auth); + assert(handler); + assert(data); + debug(29, 5) ("authenticateNTLMStart: '%s'\n", proxy_auth); + if (Config.Program.ntlmauthenticate == NULL) { + debug(29, 1) ("authenticateNTLMStart: no NTLM program specified:'%s'\n", + proxy_auth); + handler(data,0, NULL); + return; + } + r = xcalloc(1, sizeof(authenticateStatefulStateData)); + cbdataAdd(r, cbdataXfree, 0); + r->handler = handler; + cbdataLock(data); + r->data = data; + snprintf(buf, 8192, "%s\n", proxy_auth); + helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r +, lastserver); + debug(29,9)("authenticateNTLMstart: finished\n"); +} +#endif + +/* + * Decode an NTLM [Proxy-]Auth string, placing the results in the passed + * Auth_user structure. + */ + +void +authenticateDecodeNTLMAuth(acl_proxy_auth_user *auth_user, const char * proxy_auth) { + assert(auth_user->auth_type == AUTH_UNKNOWN); + auth_user->auth_type = AUTH_NTLM; + /* all we have to do is identify that it's NTLM - the helper does the rest */ + debug(29, 6) ("authenticateDecodeNTLMAuth: NTLM authentication\n"); + return; +} + +static acl_proxy_auth_user * +authenticateNTLMAuthenticateUser(void *data, const char * proxy_auth, ConnStateData *conn) { + acl_proxy_auth_user *auth_user=data; + acl_proxy_auth_hash_pointer *usernamehash, *proxy_auth_hash=NULL; + LOCAL_ARRAY(char, ntlmhash, NTLM_CHALLENGE_SZ * 2); +// char * proxy_auth=auth_user->proxy_auth; + assert(auth_user->auth_type==AUTH_NTLM); + switch (auth_user->auth_data.ntlm_auth.auth_state) { + case AUTHENTICATE_STATE_NONE: + /* we've recieved a negotiate request. pass to a helper */ + debug(29, 3) ("authenticateNTLMAuthenticateUser: auth state ntlm none. %s\n", + proxy_auth); + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_NEGOTIATE; +// auth_user->auth_data.ntlm_auth.ntlmnegotiate = auth_user->proxy_auth; +// /* use it up. */ +// auth_user->proxy_auth=NULL; + + auth_user->auth_data.ntlm_auth.ntlmnegotiate=xstrndup(proxy_auth, NTLM_CHALLENGE_SZ+5); + conn->auth_type=AUTH_NTLM; + conn->auth_user=auth_user; + + return auth_user; + break; + case AUTHENTICATE_STATE_NEGOTIATE: + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_CHALLENGE; +// xfree(auth_user->proxy_auth); +// auth_user->proxy_auth=NULL; + return auth_user; + break; + case AUTHENTICATE_STATE_CHALLENGE: + /* we should have recieved a NTLM challenge. pass it to the same + * helper process */ + debug(29,3) ("authenticateNTLMAuthenticateUser: auth state challenge with header %s.\n", proxy_auth); + /* do a cache lookup here. If it matches it's a successful ntlm + * challenge - release the helper and use the existing auth_user + * details. */ + if (strncmp("NTLM ", proxy_auth, 5) == 0) { +#if 0 + proxy_auth += 5; +#endif + auth_user->auth_data.ntlm_auth.ntlmauthenticate = xstrdup(proxy_auth); +// xfree(auth_user->proxy_auth); +// auth_user->proxy_auth = NULL; + } else { + fatal("Incorrect scheme in auth header\n"); + /* TODO: more fault tolerance.. reset the auth scheme here */ + } + /* cache entries have authenticateauthheaderchallengestring */ + snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", + auth_user->auth_data.ntlm_auth.ntlmauthenticate, + auth_user->auth_data.ntlm_auth.authchallenge); + /* see if we already know this user's authenticate */ + debug(29,3)("aclMatchProxyAuth: cache lookup with key '%s'\n",ntlmhash); + assert(proxy_auth_cache!=NULL); + proxy_auth_hash = hash_lookup(proxy_auth_cache, ntlmhash); + if (!proxy_auth_hash) { /* not in the hash table */ + debug(29,3)("authenticateNTLMAuthenticateUser: proxy-auth cache miss.\n"); + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_RESPONSE; +#if 0 + xstrndup(proxy_auth, NTLM_CHALLENGE_SZ+5); +#endif + /* verify with the ntlm helper */ + } else { + debug(29,3)("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n"); + /* throw away the temporary entry */ + authenticateNTLMReleasehelper(auth_user); + authenticateAuthUserUnlock(auth_user); + authenticateFreeProxyAuthUser(auth_user); + + auth_user = proxy_auth_hash->auth_user; + authenticateAuthUserLock(auth_user); + conn->auth_user=auth_user; + /* we found one */ + debug(29, 3) ("found matching cache entry\n"); + assert(auth_user->auth_type == AUTH_NTLM); + debug(29, 3) ("Username to be used is %s\n", + auth_user->auth_data.ntlm_auth.username); + auth_user->flags.credentials_ok = 1; /* authenticated ok */ + /* on ntlm auth we do not unlock the auth_user until the + * connection is dropped. Thank MS for this quirk */ + auth_user->expiretime = current_time.tv_sec ; + auth_user->ip_expiretime = squid_curtime; + } + return auth_user; + break; + case AUTHENTICATE_STATE_RESPONSE: + /* auth-challenge pair cache miss. We've just got the response */ + /*add to cache and let them through */ + auth_user->auth_data.ntlm_auth.auth_state = AUTHENTICATE_STATE_DONE; + /* this connection is authenticated */ + debug(29, 3) ("validated\nch %s\nauth %s\nauthuser %s\n", + auth_user->auth_data.ntlm_auth.authchallenge, + auth_user->auth_data.ntlm_auth.ntlmauthenticate, + auth_user->auth_data.ntlm_auth.username); + /* cache entries have authenticateauthheaderchallengestring */ + snprintf(ntlmhash, sizeof(ntlmhash) - 1, "%s%s", auth_user->auth_data.ntlm_auth.ntlmauthenticate, + auth_user->auth_data.ntlm_auth.authchallenge); + /* see if this is an existing user with a different proxy_auth + * string */ + if ((usernamehash = hash_lookup(proxy_auth_username_cache, + auth_user->auth_data.ntlm_auth.username))) { + while ((usernamehash->auth_user->auth_type != + auth_user->auth_type) && (usernamehash->next) && + !strcmp(usernamehash->auth_user->auth_data.ntlm_auth.username, auth_user->auth_data.ntlm_auth.username) ) + usernamehash=usernamehash->next; + if (usernamehash->auth_user->auth_type==auth_user->auth_type) { + /* + * add another link from the new proxy_auth to the + * auth_user structure and update the information */ + assert(proxy_auth_hash == NULL); + authenticateProxyAuthCacheAddLink(ntlmhash, usernamehash->auth_user); + /* we can't seamlessly recheck the username due to the + * challenge nature of the protocol. Just free the + * temporary auth_user */ + authenticateAuthUserUnlock(auth_user); + authenticateFreeProxyAuthUser(auth_user); + auth_user = usernamehash->auth_user; + authenticateAuthUserLock(auth_user); + conn->auth_user=auth_user; + } + } else { + /* store user in hash's */ + authenticateUserNameCacheAdd(auth_user); + authenticateProxyAuthCacheAddLink(ntlmhash, auth_user); + } + /* set these to now because this is either a new login from an + * existing user or a new user */ + auth_user->expiretime = current_time.tv_sec ; + auth_user->ip_expiretime = squid_curtime; + auth_user->flags.credentials_ok=1; /*authenticated ok */ + return auth_user; + break; +#if 0 +done in acl.c + case AUTHENTICATE_STATE_DONE: + debug(28, 5) ("aclMatchProxyAuth: connection in state Done. using connec +tion credentials for the request.\n"); + /* is it working right? */ + assert(checklist->auth_user == NULL); + assert(checklist->conn->auth_user != NULL); + /* we have a valid username. */ + auth_user = checklist->conn->auth_user; + /* store the username in the request for logging */ + xstrncpy(checklist->request->authuser, + auth_user->auth_data.ntlm_auth.username, + USER_IDENT_SZ); + if (auth_user->expiretime + Config.authenticateTTL > current_time.tv_sec +) + { + auth_user->expiretime = current_time.tv_sec; + } + else{ + //user passed externa; authentication in every case to get here. f. +Let it through + } + + /* we don't unlock the auth_user until the connection is dropped. Thank + * MS for this quirk. */ + if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user)){ + /* Once the match is completed we have finished with the + * auth_user structure */ + /* check to see if we have matched the user-acl before */ + return aclCacheMatchAcl(&auth_user->proxy_match_cache, acltype, + data, auth_user->auth_data.ntlm_auth.username); + } else { + return 0; + } + break; +#endif + } + + return auth_user; +} +