--------------------- PatchSet 1039 Date: 2001/01/03 00:20:27 Author: rbcollins Branch: auth_digest Tag: (none) Log: updated for the new split struct code & the per scheme config parameters Members: src/cf.data.pre:1.1.1.3.4.1.2.18.2.4.2.7->1.1.1.3.4.1.2.18.2.4.2.8 src/structs.h:1.1.1.3.4.1.2.26.2.12.2.5->1.1.1.3.4.1.2.26.2.12.2.6 src/auth/digest/auth_digest.c:1.1.2.7->1.1.2.8 src/auth/digest/auth_digest.h:1.1.2.3->1.1.2.4 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.2.4.2.7 retrieving revision 1.1.1.3.4.1.2.18.2.4.2.8 diff -u -r1.1.1.3.4.1.2.18.2.4.2.7 -r1.1.1.3.4.1.2.18.2.4.2.8 --- squid/src/cf.data.pre 2 Jan 2001 11:59:36 -0000 1.1.1.3.4.1.2.18.2.4.2.7 +++ squid/src/cf.data.pre 3 Jan 2001 00:20:27 -0000 1.1.1.3.4.1.2.18.2.4.2.8 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.1.1.3.4.1.2.18.2.4.2.7 2001/01/02 11:59:36 rbcollins Exp $ +# $Id: cf.data.pre,v 1.1.1.3.4.1.2.18.2.4.2.8 2001/01/03 00:20:27 rbcollins Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -1089,33 +1089,6 @@ are sent. DOC_END -NAME: authenticate_program_digest -TYPE: wordlist -LOC: Config.Program.digestauthenticate -DEFAULT: none -DOC_START - Specify the command for the external digest authenticator. Such a - program reads a line containing the uuencoded NEGOTIATE and replies - with the ntlm CHALLENGE, then waits for the response and answers with - "OK" or "ERR" in an endless loop. If you use an ntlm authenticator, - make sure you have 1 acl of type proxy_auth. By default, the - ntlm authenticator_program is not used. - - authenticate_program_digest @DEFAULT_PREFIX@/bin/ntlm_auth -DOC_END - -NAME: authenticate_children_digest -TYPE: int -DEFAULT: 5 -LOC: Config.digestauthenticateChildren -DOC_START - The number of ntlm authenticator processes to spawn (default 5). If you - start too few Squid will have to wait for them to process a backlog - of usercode/password verifications, slowing it down. When password - verifications are done via a (slow) network you are likely to need - lots of ntlm authenticator processes. -DOC_END - NAME: auth_param TYPE: authparam LOC: Config.authConfig @@ -1128,7 +1101,16 @@ auth_param basic program @DEFAULT_PREFIX@/bin/ncsa_auth @DEFAULT_PREFIX@/etc/passwd would tell the basic authentication scheme it's program parameter. - Parameters for the basic scheme follow. + The order that authentication prompts are presented to the client_agent + is dependant on the order the scheme first appears in config file. + IE has a bug (it's not rfc 2617 compliant) in that it will use the basic + scheme if basic is the first entry presented, even if more secure schemes + are presented. For now use the order in the file below. If other browsers + have difficulties (don't recognise the schemes offered even if you are using + basic) then either put basic first, or disable the other schemes (by commenting + out their program entry). + + === Parameters for the basic scheme follow. === "program" cmdline Specify the command for the external authenticator. Such a @@ -1170,8 +1152,51 @@ If you are using such a system, you will be vulnerable to replay attacks unless you also enable the IP ttl is strict option. + === Parameters for the digest scheme follow === + + "program" cmdline + Specify the command for the external authenticator. Such a + program reads a line containing "username":"realm" and replies + with the appropriate H(A1) value base64 encoded. See rfc 2616 for + the definition of H(A1). If you use an authenticator, + make sure you have 1 acl of type proxy_auth. By default, + authentication is not used. + + If you want to use build a authenticator, + jump over to the ../digest_auth_modules directory and choose the + authenticator to use. It it's directory type + % make + % make install + + Then, set this line to something like + + auth_param digest program @DEFAULT_PREFIX@/bin/digest_auth_pw @DEFAULT_PREFIX@/etc/digpass + + + "children" numberofchildren + The number of authenticator processes to spawn (no default). If you + start too few Squid will have to wait for them to process a backlog + of H(A1) calculations, slowing it down. When the H(A1) calculations + are done via a (slow) network you are likely to need lots of + authenticator processes. + auth_param digest children 5 + + "realm" realmstring + Specifies the realm name which is to be reported to the client for + the digest proxy authentication scheme (part of the text the user will + see when prompted their username and password). There is no default. + auth_param digest realm Squid proxy-caching web server + + "nonce_garbage_interval" timeinterval + Specifies the interval that nonces that have been issued to client_agent's + are checked for validity. + NOCOMMENT_START #Recommended minimum configuration: +#authparam digest program +authparam digest children 5 +authparan digest realm Squid proxy-caching web server +authparam digest nonce_garbage_interval 5 minutes #authparam basic program authparam basic children 5 authparam basic realm Squid proxy-caching web server @@ -1922,16 +1947,6 @@ the Squid FAQ (http://squid.nlanr.net/Squid/FAQ/FAQ-10.html). DOC_END -NAME: digest_auth_realm -TYPE: eol -DEFAULT: Squid proxy-caching web server -LOC: Config.digestAuthRealm -DOC_START - Specifies the realm name which is to be reported to the client for - proxy authentication (part of the text the user will see when - prompted their username and password). -DOC_END - NAME: ident_lookup_access TYPE: acl_access IFDEF: USE_IDENT 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.12.2.5 retrieving revision 1.1.1.3.4.1.2.26.2.12.2.6 diff -u -r1.1.1.3.4.1.2.26.2.12.2.5 -r1.1.1.3.4.1.2.26.2.12.2.6 --- squid/src/structs.h 2 Jan 2001 11:59:37 -0000 1.1.1.3.4.1.2.26.2.12.2.5 +++ squid/src/structs.h 3 Jan 2001 00:20:28 -0000 1.1.1.3.4.1.2.26.2.12.2.6 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.12.2.5 2001/01/02 11:59:37 rbcollins Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.12.2.6 2001/01/03 00:20:28 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -400,7 +400,6 @@ char *dnsserver; #endif wordlist *redirect; - wordlist *digestauthenticate; wordlist *ntlmauthenticate; #if USE_ICMP char *pinger; @@ -416,7 +415,6 @@ time_t authenticateGCInterval; time_t authenticateTTL; time_t authenticateIpTTL; - int digestauthenticateChildren; int ntlmauthenticateChildren; int ntlmchallengeuses; time_t ntlmchallengelifetime; @@ -542,7 +540,6 @@ acl_access *redirector; } accessList; acl_deny_info_list *denyInfoList; - char *digestAuthRealm; struct _authConfig { authScheme *schemes; int n_allocated; Index: squid/src/auth/digest/auth_digest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/digest/auth_digest.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/digest/auth_digest.c 1 Jan 2001 03:09:28 -0000 1.1.2.7 +++ squid/src/auth/digest/auth_digest.c 3 Jan 2001 00:20:28 -0000 1.1.2.8 @@ -57,7 +57,11 @@ static AUTHSDIRECTION authenticateDigestDirection; static AUTHSDECODE authenticateDigestDecodeAuth; static AUTHSFIXERR authenticateDigestFixHeader; -static AUTHSFREE authenticateDigestFreeUser; +static AUTHSFREE authenticateDigestUserFree; +static AUTHSFREECONFIG authDigestFreeConfig; +static AUTHSINIT authDigestInit; +static AUTHSPARSE authDigestParse; +static AUTHSREQFREE authDigestAURequestFree; static AUTHSSTART authenticateDigestStart; static AUTHSSTATS authenticateDigestStats; static AUTHSUSERNAME authenticateDigestUsername; @@ -67,6 +71,8 @@ static hash_table *digest_nonce_cache; +static auth_digest_config *digestConfig = NULL; + static int authdigest_initialised = 0; MemPool *digest_user_pool = NULL; MemPool *digest_request_pool = NULL; @@ -125,7 +131,7 @@ digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); assert(digest_nonce_cache); /* TODO: make the GCinvterval digest specific */ - eventAdd("Digest none cache maintenance",authenticateDigestNonceCacheCleanup, NULL, Config.authenticateGCInterval,1); + eventAdd("Digest none cache maintenance",authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval,1); } } @@ -156,6 +162,7 @@ while ((nonce=((digest_nonce_h *)hash_next(digest_nonce_cache)))) { debug(29,6) ("authenticateDigestNonceCacheCleanup: nonce entry : '%s'\n", nonce->nonceb64); debug(29,6) ("authenticateDigestNonceCacheCleanup: Creation time: %d\n", nonce->noncedata.creationtime); + /* TODO put nonce timeout code into place */ #if 0 if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) { debug(29,3)("authenticateProxyUserCacheCleanup: Removing user %s from cache due to timeout.\n",username); @@ -167,7 +174,7 @@ #endif } debug(29,6) ("authenticateDigestNonceCacheCleanup: Finished cleaning the nonce cache.\n"); - eventAdd("Digest none cache maintenance",authenticateDigestNonceCacheCleanup, NULL, Config.authenticateGCInterval,1); + eventAdd("Digest none cache maintenance",authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval,1); } @@ -204,25 +211,23 @@ return strcmp(u1->username,u2->username); } -digest_user_h * +auth_user_t * authDigestUserFindUsername(const char * username) { auth_user_hash_pointer *usernamehash; - digest_request_h *digest_request; - digest_user_h * digest_user; + auth_user_t *auth_user; debug(29,9)("authDigestUserFindUsername: Looking for user '%s'\n",username); if (username && (usernamehash = hash_lookup(proxy_auth_username_cache, username))) { while ((usernamehash->auth_user->auth_type != AUTH_DIGEST) && (usernamehash->next)) usernamehash=usernamehash->next; - digest_user=NULL; + auth_user=NULL; if (usernamehash->auth_user->auth_type==AUTH_DIGEST) { - digest_request=usernamehash->auth_user->scheme_data; - digest_user=digest_request->user; + auth_user=usernamehash->auth_user; } - return digest_user; + return auth_user; } return NULL; } @@ -253,13 +258,43 @@ void authDigestRequestDelete(digest_request_h *digest_request) { + if (digest_request->nonceb64) + xfree(digest_request->nonceb64); + if (digest_request->cnonce) + xfree(digest_request->cnonce); + if (digest_request->realm) + xfree(digest_request->realm); + if (digest_request->pszPass) + xfree(digest_request->pszPass); + if (digest_request->algorithm) + xfree(digest_request->algorithm); + if (digest_request->pszMethod) + xfree(digest_request->pszMethod); + if (digest_request->qop) + xfree(digest_request->qop); + if (digest_request->uri) + xfree(digest_request->uri); + if (digest_request->response) + xfree(digest_request->response); + if (digest_request->nonce) + authenticateDigestNonceDelete(digest_request->nonce); + memPoolFree(digest_request_pool, digest_request); +} +void +authDigestAURequestFree(auth_user_request_t *auth_user_request) +{ + if (auth_user_request->scheme_data != NULL) + authDigestRequestDelete((digest_request_h *)auth_user_request->scheme_data); } digest_request_h * authDigestRequestNew() { - return memPoolAlloc(digest_request_pool); + digest_request_h *tmp; + tmp=memPoolAlloc(digest_request_pool); + assert (tmp !=NULL); + return tmp; } void @@ -296,41 +331,44 @@ void authSchemeSetup_digest(authscheme_entry_t *authscheme) { +#if 0 static int init = 0; +#endif assert(!authdigest_initialised); -// authscheme->parsefunc = storeUfsDirParse; -// authscheme->reconfigurefunc = storeUfsDirReconfigure; authscheme->Active =authenticateDigestActive; - if (Config.Program.digestauthenticate) - { - authscheme->authAuthenticate = authenticateDigestAuthenticateUser; - authscheme->authenticated= authDigestAuthenticated; - authscheme->authFixHeader=authenticateDigestFixHeader; - authscheme->FreeUser =authenticateDigestFreeUser; - authscheme->authStart =authenticateDigestStart; - authscheme->authStats =authenticateDigestStats; - authscheme->authUserUsername = authenticateDigestUsername; - authscheme->getdirection=authenticateDigestDirection; - authscheme->oncloseconnection=NULL; - authscheme->decodeauth =authenticateDigestDecodeAuth; - authscheme->donefunc = authDigestDone; - authDigestUserSetup(); - authDigestRequestSetup(); - authenticateDigestNonceSetup(); - authdigest_initialised = 1; - if (digestauthenticators == NULL) - digestauthenticators = helperCreate("digestauthenticator"); - digestauthenticators->cmdline = Config.Program.digestauthenticate; - digestauthenticators->n_to_start = Config.digestauthenticateChildren; - digestauthenticators->ipc_type = IPC_TCP_SOCKET; - helperOpenServers(digestauthenticators); - if (!init) - { - cachemgrRegister("digestauthenticator", "User Authenticator Stats", - authenticateDigestStats, 0, 1); - init++; - } + authscheme->parse =authDigestParse; + authscheme->freeconfig =authDigestFreeConfig; + authscheme->init =authDigestInit; + authscheme->authAuthenticate = authenticateDigestAuthenticateUser; + authscheme->authenticated= authDigestAuthenticated; + authscheme->authFixHeader=authenticateDigestFixHeader; + authscheme->FreeUser =authenticateDigestUserFree; + authscheme->authStart =authenticateDigestStart; + authscheme->authStats =authenticateDigestStats; + authscheme->authUserUsername = authenticateDigestUsername; + authscheme->getdirection=authenticateDigestDirection; + authscheme->oncloseconnection=NULL; + authscheme->decodeauth =authenticateDigestDecodeAuth; + authscheme->donefunc = authDigestDone; + authscheme->requestFree = authDigestAURequestFree; +#if 0 + authDigestUserSetup(); + authDigestRequestSetup(); + authenticateDigestNonceSetup(); + authdigest_initialised = 1; + if (digestauthenticators == NULL) + digestauthenticators = helperCreate("digestauthenticator"); + digestauthenticators->cmdline = Config.Program.digestauthenticate; + digestauthenticators->n_to_start = Config.digestauthenticateChildren; + digestauthenticators->ipc_type = IPC_TCP_SOCKET; + helperOpenServers(digestauthenticators); + if (!init) + { + cachemgrRegister("digestauthenticator", "User Authenticator Stats", + authenticateDigestStats, 0, 1); + init++; } +#endif } int @@ -342,9 +380,9 @@ } int -authDigestAuthenticated(auth_user_t * auth_user) +authDigestAuthenticated(auth_user_request_t * auth_user_request) { - if (auth_user->flags.credentials_ok==1) + if (auth_user_request->auth_user->flags.credentials_ok==1) return 1; else return 0; @@ -352,8 +390,9 @@ /* log a digest user in */ -static auth_user_t * -authenticateDigestAuthenticateUser(auth_user_t *auth_user, request_t *request, ConnStateData *conn, http_hdr_type type) { +static void +authenticateDigestAuthenticateUser(auth_user_request_t *auth_user_request, request_t *request, ConnStateData *conn, http_hdr_type type) { + auth_user_t *auth_user; digest_request_h * digest_request; digest_user_h * digest_user; @@ -361,35 +400,36 @@ HASHHEX HA2 = ""; HASHHEX Response; - /* if the check has failed, just return */ - if (auth_user->flags.credentials_ok==3) + assert (auth_user_request->auth_user != NULL); + auth_user=auth_user_request->auth_user; + + /* if the check has corrupted the user, just return */ + if (auth_user_request->auth_user->flags.credentials_ok==3) { - return auth_user; + return; } assert(auth_user->scheme_data != NULL); - digest_request = auth_user->scheme_data; + digest_user = auth_user->scheme_data; - assert(digest_request->user != NULL); - digest_user=digest_request->user; + assert(auth_user_request->scheme_data != NULL); + digest_request=auth_user_request->scheme_data; /* do we have the HA1 */ if (!digest_user->HA1created) { - auth_user->flags.credentials_ok=2; - return auth_user; + auth_user_request->auth_user->flags.credentials_ok=2; + return; } - +#if 0 debug(29,4)("authenticateDigestAuthenticateuser: user '%s' is in the user cache as auth_user '%d', for us '%d' \n", digest_user->username,auth_user,digest_user->auth_user); - - /* - * we don't add another link from the new proxy_auth to the - * auth_user structure because digest headers are unique */ +#endif if (digest_request->nonce==NULL) { /* this isn't a nonce we issued */ + /* TODO: record breaks in authentication at the request level */ auth_user->flags.credentials_ok=3; - return auth_user; + return; } DigestCalcHA1(digest_request->algorithm, NULL,NULL,NULL, authenticateDigestNonceNonceb64(digest_request->nonce), @@ -405,8 +445,11 @@ if (strcasecmp(digest_request->response,Response)) { auth_user->flags.credentials_ok=3; - return auth_user; + return; } + +#if 0 + /* this is unneeded now the auth_rewrite code manages the request * user difference */ /* we have authenticated this request */ if (auth_user != digest_user->auth_user) { @@ -417,6 +460,7 @@ /* lock the old structure for this request */ authenticateAuthUserLock(auth_user); } +#endif auth_user->flags.credentials_ok=1; /* TODO: cleanup the digest_request info that is no longer needed */ @@ -438,12 +482,12 @@ * after external auth occurs anyway */ auth_user->expiretime = current_time.tv_sec; auth_user->ip_expiretime = squid_curtime; - return auth_user; + return; } -int authenticateDigestDirection(auth_user_t *auth_user) { +int authenticateDigestDirection(auth_user_request_t *auth_user_request) { /* null auth_user is checked for by authenticateDirection */ - switch (auth_user->flags.credentials_ok) { + switch (auth_user_request->auth_user->flags.credentials_ok) { case 0: /* not checked */ return -1; case 1: /* checked & ok */ @@ -457,31 +501,45 @@ } void -authenticateDigestFixHeader(auth_user_t *auth_user, HttpReply *rep, http_hdr_type type, request_t * request){ +authenticateDigestFixHeader(auth_user_request_t *auth_user_request, HttpReply *rep, http_hdr_type type, request_t * request){ digest_nonce_h *nonce = authenticateDigestNonceNew(); - if (Config.Program.digestauthenticate){ - debug(29, 5) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\"\n",type,Config.digestAuthRealm,authenticateDigestNonceNonceb64(nonce)); + if (digestConfig->authenticate){ + debug(29, 5) ("authenticateFixHeader: Sending type:%d header: 'Digest realm=\"%s\", nonce=\"%s\"\n",type,digestConfig->digestAuthRealm,authenticateDigestNonceNonceb64(nonce)); /* in the future, for WWW auth we may want to support the domain entry */ - httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\", nonce=\"%s\", qop=\"auth\"",Config.digestAuthRealm,authenticateDigestNonceNonceb64(nonce)); + httpHeaderPutStrf(&rep->header, type, "Digest realm=\"%s\", nonce=\"%s\", qop=\"auth\"",digestConfig->digestAuthRealm,authenticateDigestNonceNonceb64(nonce)); } } void -authenticateDigestFreeUser(auth_user_t *auth_user) { - digest_request_h * digest_request = auth_user->scheme_data; +authenticateDigestUserFree(auth_user_t *auth_user) { + digest_user_h * digest_user = auth_user->scheme_data; +#if 0 + dlink_node *link,*tmplink; +#endif debug(29,6) ("authenticateDigestFreeUser: Clearing Digest scheme data\n"); + if (!digest_user) + return; /* TODO the whole shebang -logic: free all the request details. -if a nonce is reference don't free the nonce -if a user is referenbced that != auth_user, don't free it otherwise do so +logic: free all the user specific details. auth_rewrite takes care of freeing each request +if a nonce is referenced don't free the nonce */ -// if (digest_auth->username) -// xfree(digest_auth->username); -// if (digest_auth->passwd) -// xfree(digest_auth->passwd); - memPoolFree(digest_request_pool, auth_user->scheme_data); + if (digest_user->username) + xfree(digest_user->username); + + /* currently the nonces aren't linked in */ +#if 0 + link=digest_user->nonces.head; + while (link) + { + tmplink=link; + link=link->next; + + } +#endif + + memPoolFree(digest_user_pool, auth_user->scheme_data); auth_user->scheme_data = NULL; } @@ -489,8 +547,9 @@ authenticateDigestHandleReply(void *data, char *reply) { authenticateStateData *r = data; - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; digest_request_h *digest_request; + digest_user_h *digest_user; int valid; char *t = NULL; debug(29, 5) ("authenticateDigestHandleReply: {%s}\n", reply ? reply : ""); @@ -500,17 +559,17 @@ if (*reply == '\0') reply = NULL; } - assert(r->auth_user != NULL); - assert(r->auth_user->auth_type == AUTH_DIGEST); - auth_user=r->auth_user; - assert(auth_user->scheme_data != NULL); - digest_request = auth_user->scheme_data; + assert(r->auth_user_request != NULL); + auth_user_request=r->auth_user_request; + assert(auth_user_request->scheme_data != NULL); + digest_request = auth_user_request->scheme_data; + digest_user = auth_user_request->auth_user->scheme_data; if (reply && (strncasecmp(reply, "ERR", 3) == 0)) - auth_user->flags.credentials_ok = 3; + auth_user_request->auth_user->flags.credentials_ok = 3; else { - CvtBin(reply,digest_request->user->HA1); - digest_request->user->HA1created=1; + CvtBin(reply,digest_user->HA1); + digest_user->HA1created=1; } valid = cbdataValid(r->data); cbdataUnlock(r->data); @@ -523,6 +582,85 @@ authenticateStateFree(r); } +/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the + * config file */ +static void +authDigestInit(authScheme *scheme) +{ + static int init = 0; + if (digestConfig->authenticate){ + authDigestUserSetup(); + authDigestRequestSetup(); + authenticateDigestNonceSetup(); + authdigest_initialised = 1; + if (digestauthenticators == NULL) + digestauthenticators = helperCreate("digestauthenticator"); + digestauthenticators->cmdline = digestConfig->authenticate; + digestauthenticators->n_to_start = digestConfig->authenticateChildren; + digestauthenticators->ipc_type = IPC_TCP_SOCKET; + helperOpenServers(digestauthenticators); + if (!init) + { + cachemgrRegister("digestauthenticator", "User Authenticator Stats", + authenticateDigestStats, 0, 1); + init++; + } + } +} + + +/* free any allocated configuration details */ +void +authDigestFreeConfig(authScheme *scheme) +{ + if (digestConfig==NULL) + return; + assert(digestConfig==scheme->scheme_data); + if (digestConfig->authenticate) + wordlistDestroy(&digestConfig->authenticate); + if (digestConfig->digestAuthRealm) + safe_free(digestConfig->digestAuthRealm); + xfree(digestConfig); + digestConfig=NULL; +} + +static void +authDigestParse(authScheme *scheme, int n_configured, char *param_str) +{ + if (scheme->scheme_data==NULL) + { + assert (digestConfig==NULL); + /* this is the first param to be found */ + scheme->scheme_data=xmalloc(sizeof(auth_digest_config)); + memset(scheme->scheme_data, 0, sizeof(auth_digest_config)); + digestConfig=scheme->scheme_data; + digestConfig->authenticateChildren=5; + } + digestConfig=scheme->scheme_data; + if (strcasecmp(param_str,"program")==0) + { + parse_wordlist(&digestConfig->authenticate); + requirePathnameExists("authparam digest program",digestConfig->authenticate->key); + } + else if (strcasecmp(param_str,"children")==0) + { + parse_int(&digestConfig->authenticateChildren); + } + else if (strcasecmp(param_str,"realm")==0) + { + parse_eol(&digestConfig->digestAuthRealm); + } + else if (strcasecmp(param_str,"nonce_garbage_interval")==0) + { + parse_time_t(&digestConfig->nonceGCInterval); + } + else + { + debug(28,0)("unrecognised digest auth scheme parameter '%s'\n",param_str); + } +} + + static void authenticateDigestStats(StoreEntry * sentry) { @@ -534,9 +672,9 @@ /* authenticateDigestUsername: return a pointer to the username in the */ char * authenticateDigestUsername(auth_user_t *auth_user) { - digest_request_h * digest_request = auth_user->scheme_data; - if (auth_user->auth_type==AUTH_DIGEST) - return digest_request->user->username; + digest_user_h * digest_user = auth_user->scheme_data; + if (digest_user) + return digest_user->username; return NULL; } @@ -546,28 +684,29 @@ */ static void -authenticateDigestDecodeAuth(auth_user_t *auth_user, const char * proxy_auth) { +authenticateDigestDecodeAuth(auth_user_request_t *auth_user_request, const char * proxy_auth) { String temp; const char *item; const char *p; const char *pos = NULL; - char * username; + char * username=NULL; digest_nonce_h *nonce; int ilen; digest_request_h * digest_request; digest_user_h * digest_user; + auth_user_t * auth_user; dlink_node *node; debug(29,5)("authenticateDigestDecodeAuth: beginning\n"); - assert(auth_user != NULL); - assert(auth_user->auth_type == AUTH_UNKNOWN); + assert(auth_user_request != NULL); + +#if 0 /* 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 = authDigestRequestNew(); - assert (auth_user->scheme_data != NULL); - digest_request=auth_user->scheme_data; +#endif + digest_request = authDigestRequestNew(); /* trim DIGEST from string */ while (!xisspace(*proxy_auth)) @@ -673,53 +812,70 @@ } stringClean(&temp); - if (!digest_request->nonceb64) - { - fatal("No nonce!\n"); - } - nonce=authenticateDigestNonceFindNonce(digest_request->nonceb64); if (nonce==NULL) { /* we couldn't find a matching nonce! */ debug (29,6)("authenticateDigestDecode: Unexpected nonce recieved\n"); - authDigestRequestDelete(digest_request); - auth_user->scheme_data=NULL; + /* log the username */ + debug(29,6)("authBasicDecodeAuth: Creating new user for logging '%s'\n",username); + /* new auth_user */ + auth_user=authenticateAuthUserNew("digest"); + /* new scheme data */ + digest_user=authDigestUserNew(); + /* save the credentials */ + digest_user->username=username; + /* link the scheme data in */ + auth_user->scheme_data=digest_user; + /* set the auth_user type */ auth_user->auth_type=AUTH_BROKEN; + /* link the request to the user */ + auth_user_request->auth_user=auth_user; + /* lock for the auth_user_request link */ + authenticateAuthUserLock(auth_user); + node=dlinkNodeNew(); + dlinkAdd(auth_user_request, node, &auth_user->requests); + /* we don't need the scheme specific data */ + authDigestRequestDelete(digest_request); + auth_user_request->scheme_data=NULL; return; } digest_request->nonce=nonce; /* find the user */ - if ((digest_user=authDigestUserFindUsername(username))== NULL) + if ((auth_user=authDigestUserFindUsername(username))== NULL) { /* the user doesn't exist in the username cache yet */ debug(29,6)("authDigestDecodeAuth: Creating new digest user '%s'\n",username); + /* new auth_user */ + auth_user=authenticateAuthUserNew("digest"); + /* new scheme user data */ digest_user=authDigestUserNew(); - assert (digest_user != NULL); + /* save the username */ digest_user->username=username; /* link the primary struct in */ - digest_user->auth_user=auth_user; - digest_request->user=digest_user; - /* this auth_user struct is the 'luck one' to get added to the username cache */ - /* the requests after this link to the digest_user but can't get cached acls */ - if (!auth_user->usernamehash) - { - /* store user in hash's */ - debug(29,4)("authenticateDigestAuthenticateuser: user '%s' is not in the user cache\n", digest_request->user->username); - authenticateUserNameCacheAdd(auth_user); - } + auth_user->scheme_data=digest_user; + /* set the user type */ + auth_user->auth_type=AUTH_DIGEST; + /* this auth_user struct is the one to get added to the username cache */ + /* store user in hash's */ + debug(29,4)("authenticateDigestAuthenticateuser: user '%s' is not in the user cache\n", digest_user->username); + authenticateUserNameCacheAdd(auth_user); } else { - debug(29,6)("authDigestDecodeAuth: Found digest user '%s' in the user cache as '%d'\n",username,digest_user); + debug(29,6)("authDigestDecodeAuth: Found user '%s' in the user cache as '%d'\n",username,auth_user); + digest_user=auth_user->scheme_data; xfree(username); } /*link the request and the user */ - digest_request->user=digest_user; + auth_user_request->auth_user=auth_user; + auth_user_request->scheme_data=digest_request; + /* lock for the request link */ + authenticateAuthUserLock(auth_user); node=dlinkNodeNew(); - dlinkAdd(digest_request, node, &digest_user->requests); + dlinkAdd(auth_user_request, node, &auth_user->requests); debug(29,2)("username = '%s'\nrealm = '%s'\nqop = '%s'\nalgorithm = '%s'\nuri = '%s'\nnonce = '%s'\nnc = '%s'\ncnonce = '%s'\nresponse = '%s'\ndigestnonce = '%d'\n", digest_user->username, digest_request->realm, @@ -757,19 +913,22 @@ /* send the initial data to a digest authenticator module */ static void -authenticateDigestStart(auth_user_t * auth_user, RH * handler, void *data) +authenticateDigestStart(auth_user_request_t * auth_user_request, RH * handler, void *data) { authenticateStateData *r = NULL; char buf[8192]; digest_request_h * digest_request; - assert(auth_user); + digest_user_h * digest_user; + assert(auth_user_request); assert(handler); - assert(auth_user->auth_type==AUTH_DIGEST); - assert(auth_user->scheme_data != NULL); - digest_request = auth_user->scheme_data; - debug(29, 5) ("authenticateStart: '\"%s\":\"%s\"'\n", digest_request->user->username, + assert(auth_user_request->auth_user->auth_type==AUTH_DIGEST); + assert(auth_user_request->auth_user->scheme_data != NULL); + assert(auth_user_request->scheme_data != NULL); + digest_request = auth_user_request->scheme_data; + digest_user = auth_user_request->auth_user->scheme_data; + debug(29, 5) ("authenticateStart: '\"%s\":\"%s\"'\n", digest_user->username, digest_request->realm); - if (Config.Program.digestauthenticate == NULL) { + if (digestConfig->authenticate == NULL) { handler(data, NULL); return; } @@ -778,7 +937,7 @@ r->handler = handler; cbdataLock(data); r->data = data; - r->auth_user = auth_user; - snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_request->user->username, digest_request->realm); + r->auth_user_request = auth_user_request; + snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username, digest_request->realm); helperSubmit(digestauthenticators, buf, authenticateDigestHandleReply, r); } Index: squid/src/auth/digest/auth_digest.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/digest/auth_digest.h,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -r1.1.2.3 -r1.1.2.4 --- squid/src/auth/digest/auth_digest.h 21 Dec 2000 04:17:37 -0000 1.1.2.3 +++ squid/src/auth/digest/auth_digest.h 3 Jan 2001 00:20:28 -0000 1.1.2.4 @@ -10,7 +10,7 @@ /* Generic */ typedef struct { void *data; - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; RH *handler; } authenticateStateData; @@ -24,13 +24,17 @@ char *username; HASH HA1; int HA1created; +#if 0 /* workaround for incorrect division in the auth_user types * it points to the auth_user struct that has all the acl caching going on */ auth_user_t *auth_user; +#endif /* what nonces have been allocated to this user*/ dlink_list nonces; +#if 0 /* what digest requests are in progress for this user */ dlink_list requests; +#endif }; /* the digest_request structure is what follows the http_request around */ @@ -45,7 +49,9 @@ char * qop;// = "auth"; char *uri;// = "/dir/index.html"; char *response; +#if 0 digest_user_h *user; +#endif digest_nonce_h *nonce; }; @@ -61,18 +67,14 @@ digest_nonce_data noncedata; }; - -#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; +/* configuration runtime data */ +struct _auth_digest_config { + int authenticateChildren; + char *digestAuthRealm; + wordlist *authenticate; + time_t nonceGCInterval; }; -typedef struct _ntlm_helper_state_t ntlm_helper_state_t; - -extern MemPool *ntlm_helper_state_pool; -#endif +typedef struct _auth_digest_config auth_digest_config; #endif