--------------------- PatchSet 923 Date: 2000/12/14 23:06:40 Author: rbcollins Branch: auth_digest Tag: (none) Log: decode going Members: configure.in:1.1.1.3.10.17.2.5->1.1.1.3.10.17.2.5.2.1 makefile.in:1.1.1.3.10.3.2.1->1.1.1.3.10.3.2.1.2.1 src/acl.c:1.1.1.3.12.26.2.9->1.1.1.3.12.26.2.9.2.1 src/enums.h:1.1.1.3.12.15.2.2->1.1.1.3.12.15.2.2.2.1 src/auth/digest/Makefile.in:1.1->1.1.2.1 src/auth/digest/auth_digest.c:1.1->1.1.2.1 src/auth/digest/auth_digest.h:1.1->1.1.2.1 Index: squid/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid/configure.in,v retrieving revision 1.1.1.3.10.17.2.5 retrieving revision 1.1.1.3.10.17.2.5.2.1 diff -u -r1.1.1.3.10.17.2.5 -r1.1.1.3.10.17.2.5.2.1 --- squid/configure.in 14 Dec 2000 11:16:48 -0000 1.1.1.3.10.17.2.5 +++ squid/configure.in 14 Dec 2000 23:06:40 -0000 1.1.1.3.10.17.2.5.2.1 @@ -3,13 +3,13 @@ dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.1.1.3.10.17.2.5 2000/12/14 11:16:48 rbcollins Exp $ +dnl $Id: configure.in,v 1.1.1.3.10.17.2.5.2.1 2000/12/14 23:06:40 rbcollins Exp $ dnl dnl dnl AC_INIT(src/main.c) AC_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.1.1.3.10.17.2.5 $)dnl +AC_REVISION($Revision: 1.1.1.3.10.17.2.5.2.1 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AC_CONFIG_AUX_DIR(cfgaux) @@ -726,6 +726,33 @@ fi AC_SUBST(AUTH_BASIC_MODULES) +dnl Select basic auth scheme modules to build +AUTH_DIGEST_MODULES= +AC_ARG_ENABLE(digest-auth-modules, +[ --enable-digest-auth-modules=\"list of modules\" + This option selects which digest scheme authentication + helper modules to build and install as part of the + normal build process. For a list of available modules + see the digest_auth_modules directory.], +[ case "$enableval" in + yes) + for module in $srcdir/digest_auth_modules/*; do + if test -f $module/Makefile.in; then + AUTH_DIGEST_MODULES="$AUTH_DIGEST_MODULES `basename $module`" + fi + done + ;; + no) + ;; + *) + AUTH_DIGEST_MODULES="`echo $enableval| sed -e 's/,/ /g;s/ */ /g'`" + esac +]) +if test -n "$AUTH_DIGEST_MODULES"; then + echo "Digest auth modules built: $AUTH_DIGEST_MODULES" +fi +AC_SUBST(AUTH_DIGEST_MODULES) + dnl Disable "unlinkd" code AC_ARG_ENABLE(unlinkd, [ --disable-unlinkd Do not use unlinkd], @@ -1726,6 +1753,13 @@ fi done +DIGEST_AUTH_MAKEFILES="" +for module in $srcdir/digest_auth_modules/*; do + if test -f $module/Makefile.in; then + DIGEST_AUTH_MAKEFILES="$DIGEST_AUTH_MAKEFILES ./digest_auth_modules/`basename $module`/Makefile" + fi +done + AC_OUTPUT(\ ./makefile \ ./lib/Makefile \ @@ -1746,4 +1780,6 @@ $AUTH_SCHEME_MAKEFILES \ ./auth_modules/Makefile \ $AUTH_MAKEFILES \ + ./digest_auth_modules/Makefile \ + $DIGEST_AUTH_MAKEFILES \ ) Index: squid/makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/Attic/makefile.in,v retrieving revision 1.1.1.3.10.3.2.1 retrieving revision 1.1.1.3.10.3.2.1.2.1 diff -u -r1.1.1.3.10.3.2.1 -r1.1.1.3.10.3.2.1.2.1 --- squid/makefile.in 14 Dec 2000 11:24:03 -0000 1.1.1.3.10.3.2.1 +++ squid/makefile.in 14 Dec 2000 23:06:40 -0000 1.1.1.3.10.3.2.1.2.1 @@ -1,4 +1,4 @@ -# $Id: makefile.in,v 1.1.1.3.10.3.2.1 2000/12/14 11:24:03 rbcollins Exp $ +# $Id: makefile.in,v 1.1.1.3.10.3.2.1.2.1 2000/12/14 23:06:40 rbcollins Exp $ # srcdir = @srcdir@ @@ -14,7 +14,7 @@ prefix = @prefix@ exec_prefix = @exec_prefix@ -SUBDIRS = lib @makesnmplib@ scripts src icons errors auth_modules +SUBDIRS = lib @makesnmplib@ scripts src icons errors auth_modules digest_auth_modules noargs: all @@ -38,6 +38,7 @@ rm -f config.log makefile rm -f include/paths.h include/autoconf.h include/config.h rm -f auth_modules/dummy + rm -f digest_auth_modules/dummy @for dir in $(SUBDIRS) contrib; do \ echo Making distclean in $$dir; \ (cd $$dir; $(MAKE) $(MFLAGS) prefix="$(prefix)" distclean); \ Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3.12.26.2.9 retrieving revision 1.1.1.3.12.26.2.9.2.1 diff -u -r1.1.1.3.12.26.2.9 -r1.1.1.3.12.26.2.9.2.1 --- squid/src/acl.c 11 Dec 2000 23:32:14 -0000 1.1.1.3.12.26.2.9 +++ squid/src/acl.c 14 Dec 2000 23:06:40 -0000 1.1.1.3.12.26.2.9.2.1 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3.12.26.2.9 2000/12/11 23:32:14 rbcollins Exp $ + * $Id: acl.c,v 1.1.1.3.12.26.2.9.2.1 2000/12/14 23:06:40 rbcollins Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1350,7 +1350,8 @@ auth_user = checklist->auth_user; assert((auth_user->auth_type==AUTH_NTLM) || - (auth_user->auth_type==AUTH_BASIC)); + (auth_user->auth_type==AUTH_BASIC) || + (auth_user->auth_type==AUTH_DIGEST)); authenticateStart(auth_user, aclLookupProxyAuthDone, checklist); } Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.1.1.3.12.15.2.2 retrieving revision 1.1.1.3.12.15.2.2.2.1 diff -u -r1.1.1.3.12.15.2.2 -r1.1.1.3.12.15.2.2.2.1 --- squid/src/enums.h 13 Dec 2000 01:23:31 -0000 1.1.1.3.12.15.2.2 +++ squid/src/enums.h 14 Dec 2000 23:06:41 -0000 1.1.1.3.12.15.2.2.2.1 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.1.1.3.12.15.2.2 2000/12/13 01:23:31 rbcollins Exp $ + * $Id: enums.h,v 1.1.1.3.12.15.2.2.2.1 2000/12/14 23:06:41 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -501,6 +501,7 @@ AUTH_UNKNOWN, /* default */ AUTH_BASIC, AUTH_NTLM, + AUTH_DIGEST, AUTH_BROKEN /* known type, but broken data */ } auth_type_t; --- /dev/null Wed Feb 14 00:45:56 2007 +++ squid/src/auth/digest/Makefile.in Wed Feb 14 00:47:16 2007 @@ -0,0 +1,55 @@ +# +# Makefile for the UFS storage driver for the Squid Object Cache server +# +# $Id$ +# + +AUTH = digest + +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +MAKEDEPEND = @MAKEDEPEND@ +AR_R = @AR_R@ +RANLIB = @RANLIB@ +AC_CFLAGS = @CFLAGS@ +SHELL = /bin/sh + +INCLUDE = -I../../../include -I$(top_srcdir)/include -I$(top_srcdir)/src/ +CFLAGS = $(AC_CFLAGS) $(INCLUDE) $(DEFINES) + +OUT = ../$(AUTH).a + +OBJS = \ + auth_digest.o + + +all: $(OUT) + +$(OUT): $(OBJS) + @rm -f ../stamp + $(AR_R) $(OUT) $(OBJS) + $(RANLIB) $(OUT) + +$(OBJS): $(top_srcdir)/include/version.h ../../../include/autoconf.h + +.c.o: + @rm -f ../stamp + $(CC) $(CFLAGS) -c $< + +clean: + -rm -rf *.o *pure_* core ../$(AUTH).a + +distclean: clean + -rm -f Makefile + -rm -f Makefile.bak + -rm -f tags + +install: + +tags: + ctags *.[ch] $(top_srcdir)/src/*.[ch] $(top_srcdir)/include/*.h $(top_srcdir)/lib/*.[ch] + +depend: + $(MAKEDEPEND) $(INCLUDE) -fMakefile *.c --- /dev/null Wed Feb 14 00:45:56 2007 +++ squid/src/auth/digest/auth_digest.c Wed Feb 14 00:47:16 2007 @@ -0,0 +1,652 @@ + +/* + * $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" +#include "auth_digest.h" +#include "md5.h" + +static void +authenticateStateFree(authenticateStateData * r) +{ + cbdataFree(r); +} + +/* Digest Scheme */ + +static HLPCB authenticateDigestHandleReply; +static AUTHSACTIVE authenticateDigestActive; +static AUTHSAUTHUSER authenticateDigestAuthenticateUser; +static AUTHSDIRECTION authenticateDigestDirection; +static AUTHSDECODE authenticateDigestDecodeAuth; +static AUTHSFIXERR authenticateDigestFixErrorHeader; +static AUTHSFREE authenticateDigestFreeUser; +static AUTHSSTART authenticateDigestStart; +static AUTHSSTATS authenticateDigestStats; +static AUTHSUSERNAME authenticateDigestUsername; +static AUTHSSHUTDOWN authDigestDone; + +static helper *digestauthenticators = NULL; + +static hash_table *digest_nonce_cache; + +static int authdigest_initialised = 0; +MemPool *digest_data_pool = NULL; +MemPool *digest_nonce_pool = NULL; + +/* + * + * Private Functions + * + */ + +#define HASHLEN 16 +typedef char HASH[HASHLEN]; +#define HASHHEXLEN 32 +typedef char HASHHEX[HASHHEXLEN+1]; +#define IN +#define OUT + +/* calculate H(A1) as per HTTP Digest spec */ +void DigestCalcHA1( + IN char * pszAlg, + IN char * pszUserName, + IN char * pszRealm, + IN char * pszPassword, + IN char * pszNonce, + IN char * pszCNonce, + OUT HASHHEX SessionKey + ); + +/* calculate request-digest/response-digest as per HTTP Digest spec */ +void DigestCalcResponse( + IN HASHHEX HA1, /* H(A1) */ + IN char * pszNonce, /* nonce from server */ + IN char * pszNonceCount, /* 8 hex digits */ + IN char * pszCNonce, /* client nonce */ + IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ + IN char * pszMethod, /* method from the request */ + IN char * pszDigestUri, /* requested URL */ + IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ + OUT HASHHEX Response /* request-digest or response-digest */ + ); + + +void CvtHex( + IN HASH Bin, + OUT HASHHEX Hex + ) +{ + unsigned short i; + unsigned char j; + + for (i = 0; i < HASHLEN; i++) { + j = (Bin[i] >> 4) & 0xf; + if (j <= 9) + Hex[i*2] = (j + '0'); + else + Hex[i*2] = (j + 'a' - 10); + j = Bin[i] & 0xf; + if (j <= 9) + Hex[i*2+1] = (j + '0'); + else + Hex[i*2+1] = (j + 'a' - 10); + }; + Hex[HASHHEXLEN] = '\0'; +}; + +/* calculate H(A1) as per spec */ +void DigestCalcHA1( + IN char * pszAlg, + IN char * pszUserName, + IN char * pszRealm, + IN char * pszPassword, + IN char * pszNonce, + IN char * pszCNonce, + OUT HASHHEX SessionKey + ) +{ + MD5_CTX Md5Ctx; + HASH HA1; + + MD5Init(&Md5Ctx); + MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); + MD5Final(HA1, &Md5Ctx); + if (stricmp(pszAlg, "md5-sess") == 0) { + MD5Init(&Md5Ctx); + MD5Update(&Md5Ctx, HA1, HASHLEN); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); + MD5Final(HA1, &Md5Ctx); + }; + CvtHex(HA1, SessionKey); +}; + +/* calculate request-digest/response-digest as per HTTP Digest spec */ +void DigestCalcResponse( + IN HASHHEX HA1, /* H(A1) */ + IN char * pszNonce, /* nonce from server */ + IN char * pszNonceCount, /* 8 hex digits */ + IN char * pszCNonce, /* client nonce */ + IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ + IN char * pszMethod, /* method from the request */ + IN char * pszDigestUri, /* requested URL */ + IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ + OUT HASHHEX Response /* request-digest or response-digest */ + ) +{ + MD5_CTX Md5Ctx; + HASH HA2; + HASH RespHash; + HASHHEX HA2Hex; + + // calculate H(A2) + MD5Init(&Md5Ctx); + MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); + if (stricmp(pszQop, "auth-int") == 0) { + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, HEntity, HASHHEXLEN); + }; + MD5Final(HA2, &Md5Ctx); + CvtHex(HA2, HA2Hex); + + // calculate response + MD5Init(&Md5Ctx); + MD5Update(&Md5Ctx, HA1, HASHHEXLEN); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); + MD5Update(&Md5Ctx, ":", 1); + if (*pszQop) { + MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); + MD5Update(&Md5Ctx, ":", 1); + MD5Update(&Md5Ctx, pszQop, strlen(pszQop)); + MD5Update(&Md5Ctx, ":", 1); + }; + MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); + MD5Final(RespHash, &Md5Ctx); + CvtHex(RespHash, Response); +}; + +digest_nonce_ptr * +authenticateDigestNonceCreate() +{ + digest_nonce_ptr *newnonce = memPoolAlloc(digest_nonce_pool); + newnonce->nonce=xstrdup("aaaaa"); + hash_join(digest_nonce_cache, (hash_link *) newnonce); + return newnonce; +} + +void +authenticateDigestNonceDestroy(digest_nonce_ptr *nonce) +{ + if (nonce) + { + hash_remove_link(digest_nonce_cache, (hash_link *)nonce); + xfree(nonce->nonce); + memPoolFree(digest_nonce_pool, nonce); + } +} + +void +authDigestDone(void) +{ +// memPoolDestroy(ufs_state_pool); + if (digestauthenticators) + helperShutdown(digestauthenticators); + authdigest_initialised = 0; + if (!shutting_down) + return; + helperFree(digestauthenticators); + digestauthenticators = NULL; + memPoolDestroy(digest_data_pool); + memPoolDestroy(digest_nonce_pool); +} + +void +authSchemeSetup_digest(authscheme_entry_t *authscheme) { +static int init = 0; + char * pszNonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093"; + char * pszCNonce = "0a4f113b"; + char * pszUser = "Mufasa"; + char * pszRealm = "testrealm@host.com"; + char * pszPass = "Circle Of Life"; + char * pszAlg = "md5"; + char szNonceCount[9] = "00000001"; + char * pszMethod = "GET"; + char * pszQop = "auth"; + char * pszURI = "/dir/index.html"; + HASHHEX HA1; + HASHHEX HA2 = ""; + HASHHEX Response; + + DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce, +pszCNonce, HA1); + DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop, + pszMethod, pszURI, HA2, Response); + debug(29,1)("Response = %s\n", Response); +// fatal("done that thang!\n"); + + assert(!authdigest_initialised); +// authscheme->parsefunc = storeUfsDirParse; +// authscheme->reconfigurefunc = storeUfsDirReconfigure; + authscheme->Active =authenticateDigestActive; + if (Config.Program.authenticate){ + authscheme->authAuthenticate = authenticateDigestAuthenticateUser; + authscheme->authFixErrorHeader=authenticateDigestFixErrorHeader; + authscheme->FreeUser =authenticateDigestFreeUser; + authscheme->authStart =authenticateDigestStart; + authscheme->authStats =authenticateDigestStats; + authscheme->authUserUsername = authenticateDigestUsername; + authscheme->getdirection=authenticateDigestDirection; + authscheme->oncloseconnection=NULL; + authscheme->decodeauth =authenticateDigestDecodeAuth; + authscheme->donefunc = authDigestDone; + if (!digest_data_pool) + digest_data_pool = memPoolCreate("Digest Scheme User Data", sizeof(digest_data)); + if (!digest_nonce_pool) + digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_ptr)); +// ufs_state_pool = memPoolCreate("UFS IO State data", sizeof(ufsstate_t)); + authdigest_initialised = 1; + if (digestauthenticators == NULL) + digestauthenticators = helperCreate("digestauthenticator"); + digestauthenticators->cmdline = Config.Program.authenticate; + digestauthenticators->n_to_start = Config.authenticateChildren; + digestauthenticators->ipc_type = IPC_TCP_SOCKET; + helperOpenServers(digestauthenticators); + if (!init) { + cachemgrRegister("digestauthenticator", + "User Authenticator Stats", + authenticateDigestStats, 0, 1); + init++; + } + if (!digest_nonce_cache) + { + digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); + assert(digest_nonce_cache); + //eventAdd("Digest none cache maintenance",authenticateDigestCleanup, NULL, interval,1); + } + } +} + +int +authenticateDigestActive(){ + if (authdigest_initialised) + return 1; + else + return 0; +} + +int authenticateDigestcmpUsername(digest_data * u1, digest_data *u2) +{ + return strcmp(u1->username,u2->username); +} + +/* log a digest user in + */ +static auth_user_t * +authenticateDigestAuthenticateUser(auth_user_t *auth_user, request_t *request, ConnStateData *conn, http_hdr_type type) { + auth_user_hash_pointer *usernamehash, *proxy_auth_hash=NULL; + digest_data * digest_auth, *temp_auth; + const char * proxy_auth; + /* if the password is not ok, do an identity */ + if (auth_user->flags.credentials_ok!=1) + return auth_user; + + /* get the header. */ + proxy_auth = httpHeaderGetStr(&request->header, type); + + assert(auth_user->scheme_data != NULL); + digest_auth = auth_user->scheme_data; + + /* password was checked and did match */ + debug(29, 4) ("authenticateDigestAuthenticateuser: user '%s' validated OK\n", + digest_auth->username); + /* see if this is an existing user with a different proxy_auth string */ + if ((usernamehash = hash_lookup(proxy_auth_username_cache, + digest_auth->username))) { + while ((usernamehash->auth_user->auth_type != auth_user->auth_type) && + (usernamehash->next) && + !authenticateDigestcmpUsername(usernamehash->auth_user->scheme_data,digest_auth)) + 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 */ + temp_auth=usernamehash->auth_user->scheme_data; +// xfree(temp_auth->passwd); +// temp_auth->passwd = digest_auth->passwd; +// digest_auth->passwd = NULL; + /* and remove the temporary structure */ + authenticateAuthUserUnlock(auth_user); + authenticateFreeProxyAuthUser(auth_user); + auth_user = usernamehash->auth_user; + /* and reference the existing digest data structure */ + digest_auth = auth_user->scheme_data; + /* 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 authenticateDigestDirection(auth_user_t *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 digest */ + return -2; + case 3: /* authentication process failed. */ + return -2; + } + return -2; +} + +void +authenticateDigestFixErrorHeader(auth_user_t *auth_user, HttpReply *rep, http_hdr_type type, request_t * request){ + digest_nonce_ptr *nonce = authenticateDigestNonceCreate(); + if (Config.Program.authenticate){ +#if 0 + debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'Digest realm=\"%s\"'\n",type,Config.proxyAuthRealm); + httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\"", Config.proxyAuthRealm); +#endif + debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'Digest realm=\"Robs server\", nonce=\"%s\"\n",type,nonce->nonce); + httpHeaderPutStrf(&rep->header, type, "Digest realm=\"Robs server\", nonce=\"%s\", qop=\"auth\"",nonce->nonce); + } +} + +void +authenticateDigestFreeUser(auth_user_t *auth_user) { + digest_data * digest_auth = auth_user->scheme_data; + debug(29,6) ("authenticateDigestFreeUser: Clearing Digest scheme data\n"); + if (digest_auth->username) + xfree(digest_auth->username); +// if (digest_auth->passwd) +// xfree(digest_auth->passwd); + memPoolFree(digest_data_pool, auth_user->scheme_data); + auth_user->scheme_data = NULL; +} + +static void +authenticateDigestHandleReply(void *data, char *reply) +{ + authenticateStateData *r = data; + auth_user_t *auth_user; + int valid; + char *t = NULL; + debug(29, 5) ("authenticateDigestHandleReply: {%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_DIGEST); + 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 +authenticateDigestStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "Digest Authenticator Statistics:\n"); + helperStats(sentry, digestauthenticators); +} + + +/* authenticateDigestUsername: return a pointer to the username in the */ +char * +authenticateDigestUsername(auth_user_t *auth_user) { + digest_data * digest_auth = auth_user->scheme_data; + if (auth_user->auth_type==AUTH_DIGEST) + return digest_auth->username; + return NULL; +} + +/* + * Decode a Digest [Proxy-]Auth string, placing the results in the passed + * Auth_user structure. + */ + +static void +authenticateDigestDecodeAuth(auth_user_t *auth_user, const char * proxy_auth) { + char *sent_auth; + char *cleartext; + String temp; + const char *item; + const char *p; + const char *pos = NULL; + + int ilen; + digest_data * digest_auth; + assert(auth_user->auth_type == AUTH_UNKNOWN); + /* digest until proved otherwise */ + auth_user->auth_type = AUTH_DIGEST; + /* have we been called before? */ + assert(auth_user->scheme_data == NULL); + auth_user->scheme_data = memPoolAlloc(digest_data_pool); + digest_auth=auth_user->scheme_data; + + /* trim DIGEST from string */ + while (!xisspace(*proxy_auth)) + proxy_auth++; + + /* Trim leading whitespace before decoding */ + while (xisspace(*proxy_auth)) + proxy_auth++; + + stringInit(&temp, proxy_auth); + while (strListGetItem(&temp, ',', &item,&ilen,&pos)) + { + if ((p = strchr(item,'=')) && (p-itemusername=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "realm", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->realm=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "qop", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->qop=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "algorithm", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->algorithm=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "uri", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->uri=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "nonce", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->nonce=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "nc", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + xstrncpy(digest_auth->nc,p,8); + } + else if (!strncmp(item, "cnonce", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->cnonce=xstrndup(p,strchr(p,'"')+1-p); + } + else if (!strncmp(item, "response", ilen)) + { + /* white space */ + while (xisspace(*p)) + p++; + /* quote mark */ + p++; + digest_auth->response=xstrndup(p,strchr(p,'"')+1-p); + } + } + stringClean(&temp); + debug(29,2)("username = '%s'\nrealm = '%s'\nqop = '%s'\nalgorithm = '%s'\nuri = '%s'\nnonce = '%s'\nnc = '%s'\ncnonce = '%s'\nresponse = '%s'\n", + digest_auth->username, digest_auth->realm, + digest_auth->qop, digest_auth->algorithm, + digest_auth->uri, digest_auth->nonce, + digest_auth->nc, digest_auth->cnonce, digest_auth->response); + + if (*cleartext == '\0') { + debug(29, 2) ("authenticateDigestDecodeAuth: Disallowing empty password," + "user is '%s'\n", digest_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_DIGEST else the UserFree function will + * be confused. + */ + if (auth_user->auth_type != AUTH_DIGEST) + { + if (digest_auth->username) + xfree(digest_auth->username); + memPoolFree(digest_data_pool, digest_auth); + auth_user->scheme_data = NULL; + } else { +// digest_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 digest authenticator module */ +static void +authenticateDigestStart(auth_user_t * auth_user, RH * handler, void *data) +{ + authenticateStateData *r = NULL; + char buf[8192]; + digest_data * digest_auth; + assert(auth_user); + assert(handler); + assert(auth_user->auth_type==AUTH_DIGEST); + assert(auth_user->scheme_data != NULL); + digest_auth = auth_user->scheme_data; +// debug(29, 5) ("authenticateStart: '%s:%s'\n", digest_auth->username, +// digest_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", digest_auth->username, digest_auth->passwd); + helperSubmit(digestauthenticators, buf, authenticateDigestHandleReply, r); +} --- /dev/null Wed Feb 14 00:45:56 2007 +++ squid/src/auth/digest/auth_digest.h Wed Feb 14 00:47:16 2007 @@ -0,0 +1,55 @@ +/* + * auth_digest.h + * Internal declarations for the digest auth module + */ + +#ifndef __AUTH_DIGEST_H__ +#define __AUTH_DIGEST_H__ + + +/* Generic */ +typedef struct { + void *data; + auth_user_t *auth_user; + RH *handler; +} authenticateStateData; + + +struct _digest_data { + char *username; + char * nonce;// = "dcd98b7102dd2f0e8b11d0f600bfb0c093"; + char * cnonce;// = "0a4f113b"; + char * realm;// = "testrealm@host.com"; + char * pszPass;// = "Circle Of Life"; + char * algorithm;// = "md5"; + char nc[9];// = "00000001"; + char * pszMethod;// = "GET"; + char * qop;// = "auth"; + char *uri;// = "/dir/index.html"; + char *response; +}; + +typedef struct _digest_data digest_data; + +typedef struct _digest_nonce_ptr digest_nonce_ptr; + +struct _digest_nonce_ptr { + char *nonce; + digest_nonce_ptr *next; +}; + + +#if 0 +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 */ + time_t renewed; +}; + +typedef struct _ntlm_helper_state_t ntlm_helper_state_t; + +extern MemPool *ntlm_helper_state_pool; +#endif + +#endif