--------------------- PatchSet 1032 Date: 2001/01/02 10:57:01 Author: rbcollins Branch: auth_rewrite Tag: (none) Log: many things: proxy auth message in err struct optimised out. auth_user split into auth_user and auth_user_request. removed proxy_auth_header cache because _only_ basic can take advantage - and the added complexity in code isn't worth it. Members: src/HttpRequest.c:1.1.1.3.10.2.2.1->1.1.1.3.10.2.2.2 src/acl.c:1.1.1.3.12.26.2.12->1.1.1.3.12.26.2.13 src/authenticate.c:1.1.1.3.12.17.2.15->1.1.1.3.12.17.2.16 src/client_side.c:1.1.1.3.4.1.2.30.2.7->1.1.1.3.4.1.2.30.2.8 src/errorpage.c:1.1.1.3.10.9.2.3->1.1.1.3.10.9.2.4 src/globals.h:1.1.1.3.12.8.2.2->1.1.1.3.12.8.2.3 src/protos.h:1.1.1.3.12.17.2.13->1.1.1.3.12.17.2.14 src/redirect.c:1.1.1.3.4.1.2.2.2.1->1.1.1.3.4.1.2.2.2.2 src/structs.h:1.1.1.3.4.1.2.26.2.15->1.1.1.3.4.1.2.26.2.16 src/tools.c:1.1.1.3.10.7.2.2->1.1.1.3.10.7.2.3 src/typedefs.h:1.1.1.3.12.13.2.11->1.1.1.3.12.13.2.12 src/auth/basic/auth_basic.c:1.1.2.12->1.1.2.13 src/auth/basic/auth_basic.h:1.1.2.3->1.1.2.4 Index: squid/src/HttpRequest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpRequest.c,v retrieving revision 1.1.1.3.10.2.2.1 retrieving revision 1.1.1.3.10.2.2.2 diff -u -r1.1.1.3.10.2.2.1 -r1.1.1.3.10.2.2.2 --- squid/src/HttpRequest.c 23 Nov 2000 10:37:26 -0000 1.1.1.3.10.2.2.1 +++ squid/src/HttpRequest.c 2 Jan 2001 10:57:01 -0000 1.1.1.3.10.2.2.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.c,v 1.1.1.3.10.2.2.1 2000/11/23 10:37:26 rbcollins Exp $ + * $Id: HttpRequest.c,v 1.1.1.3.10.2.2.2 2001/01/02 10:57:01 rbcollins Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -57,8 +57,8 @@ assert(req); if (req->body_connection) clientAbortBody(req); - if (req->auth_user) - authenticateAuthUserUnlock(req->auth_user); + if (req->auth_user_request) + authenticateAuthUserRequestUnlock(req->auth_user_request); safe_free(req->canonical); stringClean(&req->urlpath); httpHeaderClean(&req->header); Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3.12.26.2.12 retrieving revision 1.1.1.3.12.26.2.13 diff -u -r1.1.1.3.12.26.2.12 -r1.1.1.3.12.26.2.13 --- squid/src/acl.c 1 Jan 2001 10:48:28 -0000 1.1.1.3.12.26.2.12 +++ squid/src/acl.c 2 Jan 2001 10:57:01 -0000 1.1.1.3.12.26.2.13 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3.12.26.2.12 2001/01/01 10:48:28 rbcollins Exp $ + * $Id: acl.c,v 1.1.1.3.12.26.2.13 2001/01/02 10:57:01 rbcollins Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1154,11 +1154,11 @@ */ static int aclMatchProxyAuth(void *data, http_hdr_type headertype, - auth_user_t * auth_user, aclCheck_t * checklist, squid_acl acltype) + auth_user_request_t * auth_user_request, aclCheck_t * checklist, squid_acl acltype) { /* checklist is used to register user name when identified, nothing else */ const char * proxy_auth; - assert(auth_user == checklist->auth_user); /* consistent parameters ? */ + assert(auth_user_request == checklist->auth_user_request); /* consistent parameters ? */ /* General program flow in proxy_auth acls * 1. Consistency checks: are we getting sensible data @@ -1188,147 +1188,147 @@ debug(28,5) ("aclMatchProxyAuth: auth state none:broken auth or no proxy_auth header.\n"); /* something wrong with the AUTH credentials. Force a new attempt */ - checklist->auth_user = NULL; - checklist->conn->auth_user = NULL; - if (auth_user) { + checklist->auth_user_request = NULL; + checklist->conn->auth_user_request = NULL; + if (auth_user_request) { /* unlock the ACL lock */ - authenticateAuthUserUnlock(auth_user); - authenticateFreeProxyAuthUser(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); } return -2; } /* we have a proxy auth header and as far as we know this connection has * not had bungled connection oriented authentication happen on it. */ debug(28,6) ("aclMatchProxyAuth: header %s.\n", proxy_auth); - if (auth_user == NULL) { + if (auth_user_request == NULL) { debug(28,5) ("aclMatchProxyAuth: This is a new request on FD:%d\n", checklist->conn->fd); - if ((!checklist->request->auth_user) && (checklist->conn->auth_type==AUTH_UNKNOWN )) { + if ((!checklist->request->auth_user_request) && (checklist->conn->auth_type==AUTH_UNKNOWN )) { /* beginning of a new request check */ debug(28,5)("aclMatchProxyAuth: no connection authentication type\n"); - if (!authenticateValidateUser(auth_user=authenticateGetAuthUser(proxy_auth))) { + if (!authenticateValidateUser(auth_user_request=authenticateGetAuthUser(proxy_auth))) { /* Couldn't get a valid auth_user from the given header */ - if (auth_user) - authenticateFreeProxyAuthUser(auth_user); + if (auth_user_request) + authenticateAuthUserRequestUnlock(auth_user_request); return -2; } +#if 0 /* lock the new user request for this ACL processing */ - authenticateAuthUserLock(auth_user); - } else if (checklist->request->auth_user) { - auth_user=checklist->request->auth_user; + authenticateAuthUserRequestLock(auth_user_request); +#endif + } else if (checklist->request->auth_user_request) { + auth_user_request=checklist->request->auth_user_request; /* lock the user request for this ACL processing */ - authenticateAuthUserLock(auth_user); + authenticateAuthUserRequestLock(auth_user_request); } else { - if (checklist->conn->auth_user != NULL) { - auth_user=checklist->conn->auth_user; + if (checklist->conn->auth_user_request != NULL) { + auth_user_request=checklist->conn->auth_user_request; /* lock the user request for this ACL processing */ - authenticateAuthUserLock(auth_user); + authenticateAuthUserRequestLock(auth_user_request); } else { /* failed connection based authentication */ - debug(28,1)("auth user %d connauth user %d conn type %d\n",auth_user,checklist->conn->auth_user,checklist->conn->auth_type); + debug(28,1)("auth user %d connauth user %d conn type %d\n",auth_user_request, checklist->conn->auth_user_request,checklist->conn->auth_type); return -2; } } } /* Clear the reference in the checklist */ - checklist->auth_user = NULL; - if (!authenticateUserAuthenticated(auth_user)){ + checklist->auth_user_request = NULL; + if (!authenticateUserAuthenticated(auth_user_request)){ /* User not logged in. Log them in */ +#if 0 /* if they have not got an IP already give them one */ if (!auth_user->ipaddr.s_addr) auth_user->ipaddr = checklist->src_addr; - auth_user=authenticateAuthenticateUser(auth_user, checklist->request, checklist->conn,headertype); - assert(auth_user != NULL); - switch (authenticateDirection(auth_user)) { +#endif + authenticateAuthUserRequestSetIp(auth_user_request, checklist->src_addr); + authenticateAuthenticateUser(auth_user_request, checklist->request, checklist->conn,headertype); + switch (authenticateDirection(auth_user_request)) { case 1: /* this ACL check is finished. Unlock. */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); return -2; case -1: /* we are partway through authentication within squid * store the auth_user for the callback to here */ - checklist->auth_user=auth_user; + checklist->auth_user_request=auth_user_request; /* we will be called back here. Do not Unlock */ return -1; case -2: /* this ACL check is finished. Unlock. */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); return -2; - } /* on 0 fallthrough */ + } /* on 0 the authentication is finished - fallthrough */ /* See of user authentication failed for some reason */ - if (auth_user->flags.credentials_ok>1) { + if (!authenticateUserAuthenticated(auth_user_request)) { if ((!checklist->rfc931[0]) && - (authenticateUserUsername(auth_user))) { - if (!checklist->request->auth_user) { + (authenticateUserRequestUsername(auth_user_request))) { + if (!checklist->request->auth_user_request) { /* lock the user for the request structure link */ - authenticateAuthUserLock(auth_user); - checklist->request->auth_user=auth_user; + authenticateAuthUserRequestLock(auth_user_request); + checklist->request->auth_user_request=auth_user_request; } -#if 0 - xstrncpy(checklist->request->authuser, - authenticateUserUsername(auth_user), - USER_IDENT_SZ); -#endif } /* this ACL check is finished. Unlock. */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); #if 0 - authenticateFreeProxyAuthUser(auth_user); + authenticateFreeProxyAuthUser(auth_user_request); #endif return -2; } } /* User authenticated ok */ - assert(auth_user->flags.credentials_ok==1); + assert(authenticateUserAuthenticated(auth_user_request)); /* conn based auth can't time out during a connection */ - if ((checklist->conn->auth_user) || (auth_user->expiretime + Config.authenticateTTL > current_time.tv_sec)) + if ((checklist->conn->auth_user_request) || (auth_user_request->auth_user->expiretime + Config.authenticateTTL > current_time.tv_sec)) { - auth_user->expiretime = current_time.tv_sec; + auth_user_request->auth_user->expiretime = current_time.tv_sec; /* copy username to request for logging on client-side */ /* the username/password was correct at this point */ - if (!checklist->request->auth_user) { + if (!checklist->request->auth_user_request) { /* lock the user for the request structure link */ - authenticateAuthUserLock(auth_user); - checklist->request->auth_user=auth_user; + authenticateAuthUserRequestLock(auth_user_request); + checklist->request->auth_user_request=auth_user_request; } -#if 0 - xstrncpy(checklist->request->authuser, - authenticateUserUsername(auth_user), USER_IDENT_SZ); -#endif - if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user)) { + if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user_request)) { /* Once the match is completed we have finished with the * auth_user structure */ - /* But IFF it is a connection based authenticate we only unlock - * when closing the connection */ /* this ACL check completed */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); /* check to see if we have matched the user-acl before */ return - aclCacheMatchAcl(&auth_user->proxy_match_cache, - acltype, data, authenticateUserUsername(auth_user)); + aclCacheMatchAcl(&auth_user_request->auth_user->proxy_match_cache, + acltype, data, authenticateUserRequestUsername(auth_user_request)); } /* this acl check completed */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); return 0; } else { /* timeout */ + fatalf("user credentials not used for too long in acl.c - currently broken\n" + "the timeout values: expire:%d TTL %d expire+TTL %d now %d\n", + auth_user_request->auth_user->expiretime,Config.authenticateTTL, + auth_user_request->auth_user->expiretime+ Config.authenticateTTL, + current_time.tv_sec); + /* this is broken because it assumes we can retry authentication - for + digest/NTLM/kerberos we may not be able to. the Decode process should + catch timed out but not garbage collected users anyway - this code + _should_ be unreachable */ debug(28, 4) ("aclMatchProxyAuth: user '%s' timeout\n", - authenticateUserUsername(auth_user)); + authenticateUserRequestUsername(auth_user_request)); /* reset the password check info */ - auth_user->flags.credentials_ok = 0; - /* now give the checklist this auth_user */ - checklist->auth_user = auth_user; + auth_user_request->auth_user->flags.credentials_ok = 0; + /* now give the checklist this auth_user_request */ + checklist->auth_user_request = auth_user_request; /* update the TTL so we don't have an infinite loop */ - auth_user->expiretime = current_time.tv_sec; + auth_user_request->auth_user->expiretime = current_time.tv_sec; /* this ACL check completed */ - authenticateAuthUserUnlock(auth_user); + authenticateAuthUserRequestUnlock(auth_user_request); /* and trigger the external helper in case the password is still ok */ return -1; } /* unreachable code. Spit a debug info and fatal squid out of here */ -debug(29,1)("auth user %d connauth user %d conn type %d creds %d timeout %d\n",auth_user,checklist->conn->auth_user,checklist->conn->auth_type,auth_user->flags.credentials_ok, auth_user->expiretime + Config.authenticateTTL > current_time.tv_sec ? 1: 0); fatal("acl unreachable code!"); return -2; } @@ -1336,14 +1336,13 @@ static void aclLookupProxyAuthStart(aclCheck_t * checklist) { - auth_user_t *auth_user; - assert(checklist->auth_user!=NULL); /* this is created for us */ - auth_user = checklist->auth_user; + auth_user_request_t *auth_user_request; + assert(checklist->auth_user_request!=NULL); /* this is created for us */ + auth_user_request = checklist->auth_user_request; - assert((auth_user->auth_type==AUTH_NTLM) || - (auth_user->auth_type==AUTH_BASIC)); + assert(authenticateValidateUser(auth_user_request)); - authenticateStart(auth_user, aclLookupProxyAuthDone, checklist); + authenticateStart(auth_user_request, aclLookupProxyAuthDone, checklist); } static int @@ -1635,7 +1634,7 @@ #endif /* Check the password */ switch (aclMatchProxyAuth(ae->data, headertype, - checklist->auth_user, checklist, ae->type)) { + checklist->auth_user_request, checklist, ae->type)) { case 0: debug(28, 5) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n"); /* Authenticated but not Authorised for this ACL */ @@ -1884,7 +1883,7 @@ cbdataUnlock(checklist->callback_data); checklist->callback = NULL; checklist->callback_data = NULL; - assert(checklist->auth_user == NULL); + assert(checklist->auth_user_request == NULL); aclChecklistFree(checklist); } @@ -1947,7 +1946,7 @@ aclLookupProxyAuthDone(void *data, char *result) { aclCheck_t *checklist = data; - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_DONE; if (result != NULL) fatal("AclLookupProxyAuthDone: Old code floating around somewhere.\nMake clean and if that doesn't work, report a bug\n"); @@ -1959,15 +1958,15 @@ if (checklist->auth_user->auth_type == AUTH_NTLM) assert (checklist->conn->auth_user == checklist->auth_user); #endif - auth_user = checklist->auth_user; - if ((auth_user->auth_module==0) || (auth_user->flags.credentials_ok == 3)) { - /* we have lost the plot (auth_module==0) or - * credentials could not be checked either way + auth_user_request = checklist->auth_user_request; + if (!authenticateValidateUser(auth_user_request)) + { + /* credentials could not be checked either way * restart the whole process */ - checklist->conn->auth_user = NULL; + checklist->conn->auth_user_request = NULL; checklist->conn->auth_type = AUTH_BROKEN; - checklist->auth_user = NULL; - authenticateAuthUserUnlock(auth_user); + checklist->auth_user_request = NULL; + authenticateAuthUserRequestUnlock(auth_user_request); #if 0 /* This is handled automagically */ authenticateFreeProxyAuthUser(auth_user); @@ -1975,6 +1974,7 @@ aclCheck(checklist); return; } +#if 0 if (auth_user->flags.credentials_ok == 2) { /* credentials check failed - user/password/challenge ... bad. */ /* terminate the login process @@ -1992,6 +1992,7 @@ aclCheck(checklist); return; } +#endif aclCheck(checklist); } Index: squid/src/authenticate.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v retrieving revision 1.1.1.3.12.17.2.15 retrieving revision 1.1.1.3.12.17.2.16 diff -u -r1.1.1.3.12.17.2.15 -r1.1.1.3.12.17.2.16 --- squid/src/authenticate.c 1 Jan 2001 09:51:21 -0000 1.1.1.3.12.17.2.15 +++ squid/src/authenticate.c 2 Jan 2001 10:57:01 -0000 1.1.1.3.12.17.2.16 @@ -1,6 +1,6 @@ /* - * $Id: authenticate.c,v 1.1.1.3.12.17.2.15 2001/01/01 09:51:21 rbcollins Exp $ + * $Id: authenticate.c,v 1.1.1.3.12.17.2.16 2001/01/02 10:57:01 rbcollins Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -42,14 +42,16 @@ static void -authenticateDecodeAuth(const char *proxy_auth, auth_user_t * auth_user); +authenticateDecodeAuth(const char *proxy_auth, auth_user_request_t * auth_user_request); /* * - * Private Functions + * Private Data * */ +MemPool *auth_user_request_pool = NULL; + /* Generic Functions */ @@ -82,7 +84,7 @@ } void -authenticateDecodeAuth(const char *proxy_auth, auth_user_t * auth_user) +authenticateDecodeAuth(const char *proxy_auth, auth_user_request_t * auth_user_request) { int i = 0; /* if (proxy_auth == NULL) @@ -90,15 +92,15 @@ */ //checked by aclMatchProxy. assert(proxy_auth != NULL); - assert(auth_user != NULL); /* we need this created for us. */ + assert(auth_user_request != NULL); /* we need this created for us. */ debug(29, 6) ("authenticateDecodeAuth: header = '%s'\n", proxy_auth); if (authenticateAuthSchemeConfigured(proxy_auth)) { /* we're configured to use this scheme - but is it active ? */ if ((i=authenticateAuthSchemeId(proxy_auth))!=-1) { - auth_user->auth_module = i+1; - authscheme_list[i].decodeauth(auth_user, proxy_auth); + authscheme_list[i].decodeauth(auth_user_request, proxy_auth); + auth_user_request->auth_user->auth_module = i+1; return; } #if 0 @@ -111,7 +113,9 @@ } #endif } - auth_user->auth_type = AUTH_UNKNOWN; +#if 0 + auth_user_request->auth_type = AUTH_UNKNOWN; +#endif debug(29, 1) ("authenticateDecodeAuth: Unsupported or unconfigured proxy-auth scheme, '%s'\n", proxy_auth); @@ -121,12 +125,12 @@ /* clear any connection related authentication details */ void authenticateOnCloseConnection(ConnStateData *conn){ - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; assert(conn != NULL); - if (conn->auth_user !=NULL) { - auth_user = conn->auth_user; - if (authscheme_list[auth_user->auth_module-1].oncloseconnection){ - authscheme_list[auth_user->auth_module-1].oncloseconnection(conn); + if (conn->auth_user_request !=NULL) { + auth_user_request = conn->auth_user_request; + if (authscheme_list[auth_user_request->auth_user->auth_module-1].oncloseconnection){ + authscheme_list[auth_user_request->auth_user->auth_module-1].oncloseconnection(conn); } } } @@ -135,13 +139,13 @@ /* send the initial data to an authenticator module */ void -authenticateStart(auth_user_t * auth_user, RH * handler, void *data) +authenticateStart(auth_user_request_t * auth_user_request, RH * handler, void *data) { - assert(auth_user); + assert(auth_user_request); assert(handler); - debug(29,5)("authenticateStart: auth_user '%d'\n", auth_user); - if (auth_user->auth_module>0) - authscheme_list[auth_user->auth_module-1].authStart(auth_user, handler, data); + debug(29,5)("authenticateStart: auth_user_request '%d'\n", auth_user_request); + if (auth_user_request->auth_user->auth_module>0) + authscheme_list[auth_user_request->auth_user->auth_module-1].authStart(auth_user_request, handler, data); else handler(data,NULL); } @@ -152,18 +156,22 @@ */ int -authenticateValidateUser(auth_user_t * auth_user) { - debug(29,6) ("authenticateValidateUser: Validating Auth_user '%d'.\n",auth_user); - if (auth_user == NULL) { - debug(29,6) ("authenticateValidateUser: Auth_user was NULL!\n",auth_user); +authenticateValidateUser(auth_user_request_t * auth_user_request) { + debug(29,6) ("authenticateValidateUser: Validating Auth_user request '%d'.\n",auth_user_request); + if (auth_user_request == NULL) { + debug(29,6) ("authenticateValidateUser: Auth_user_request was NULL!\n"); return 0; } - if (auth_user->auth_type == AUTH_UNKNOWN) { - debug(29,6) ("authenticateValidateUser: Auth_user '%d' uses unknown scheme.\n",auth_user); + if (auth_user_request->auth_user == NULL) { + debug(29,6) ("authenticateValidateUser: No associated auth_user structure\n"); return 0; } - if (auth_user->auth_type == AUTH_BROKEN) { - debug(29,6) ("authenticateValidateUser: Auth_user '%d' is broken for it's scheme.\n",auth_user); + if (auth_user_request->auth_user->auth_type == AUTH_UNKNOWN) { + debug(29,6) ("authenticateValidateUser: Auth_user '%d' uses unknown scheme.\n",auth_user_request->auth_user); + return 0; + } + if (auth_user_request->auth_user->auth_type == AUTH_BROKEN) { + debug(29,6) ("authenticateValidateUser: Auth_user '%d' is broken for it's scheme.\n",auth_user_request->auth_user); return 0; } /* any other sanity checks that we need in the future */ @@ -171,18 +179,108 @@ /* Thus should a module call to something like authValidate */ /* finally return ok */ - debug(29,6) ("authenticateValidateUser: Validated Auth_user '%d'.\n",auth_user); + debug(29,6) ("authenticateValidateUser: Validated Auth_user request '%d'.\n",auth_user_request); return 1; } + +auth_user_t * +authenticateAuthUserNew(const char *scheme) +{ + auth_user_t* temp_auth; + temp_auth = memAllocate(MEM_AUTH_USER_T); + assert (temp_auth != NULL); + temp_auth->auth_type=AUTH_UNKNOWN; + temp_auth->references=0; + temp_auth->auth_module=authenticateAuthSchemeId(scheme)+1; + return temp_auth; +} + +auth_user_request_t * +authenticateAuthUserRequestNew() +{ + auth_user_request_t *temp_request; + if (!auth_user_request_pool) + auth_user_request_pool = memPoolCreate("Authenticate Request Data", sizeof(auth_user_request_t)); + temp_request=memPoolAlloc(auth_user_request_pool); + assert (temp_request != NULL); + temp_request->auth_user=NULL; + temp_request->message=NULL; + temp_request->scheme_data=NULL; + temp_request->references=0; + return temp_request; +} + +void +authenticateAuthUserRequestFree(auth_user_request_t * auth_user_request) +{ + dlink_node *link,tmplink; + debug(29,6)("authenticateAuthUserRequestFree: freeing request %d\n",auth_user_request); + if (!auth_user_request) + return; + assert (auth_user_request->references==0); + if (auth_user_request->auth_user) + { + if (auth_user_request->scheme_data != NULL) + { + /* we MUST know the module */ + assert((auth_user_request->auth_user->auth_module>0)); + /* and the module MUST support requestFree if it has created scheme data */ + assert(authscheme_list[auth_user_request->auth_user->auth_module-1].requestFree != NULL); + authscheme_list[auth_user_request->auth_user->auth_module-1].requestFree(auth_user_request); + } + /* unlink from the auth_user struct */ + link = auth_user_request->auth_user->requests.head; + while (link && (link->data != auth_user_request)) + link=link->next; + assert (link!=NULL); + dlinkDelete(link, &auth_user_request->auth_user->requests); + dlinkNodeDelete(link); + + /* unlock the request structure's lock */ + authenticateAuthUserUnlock(auth_user_request->auth_user); + auth_user_request->auth_user= NULL; + } + else + assert (auth_user_request->scheme_data == NULL); + if (auth_user_request->message) + xfree(auth_user_request->message); +} + +char * +authenticateAuthUserRequestMessage(auth_user_request_t * auth_user_request) +{ + if (auth_user_request) + return auth_user_request->message; + return NULL; +} + +void +authenticateAuthUserRequestSetIp(auth_user_request_t *auth_user_request, struct in_addr ipaddr) +{ + if (auth_user_request->auth_user) + if (!auth_user_request->auth_user->ipaddr.s_addr) + auth_user_request->auth_user->ipaddr=ipaddr; +} + /* Get Auth User: Return a filled out auth_user structure for the given * Proxy Auth (or Auth) header. It may be a cached Auth User or a new - * Unauthenticated structure. The structure is NOT locked here. + * Unauthenticated structure. The structure is given an inital lock here. */ -auth_user_t * +auth_user_request_t * authenticateGetAuthUser(const char *proxy_auth) { +#if 0 auth_user_hash_pointer *proxy_auth_hash = NULL; - auth_user_t *auth_user; +#endif + auth_user_request_t *auth_user_request = authenticateAuthUserRequestNew(); + /* and lock for the request instance */ + authenticateAuthUserRequestLock(auth_user_request); + authenticateDecodeAuth(proxy_auth, auth_user_request); +#if 0 +/* We don't look in the cache anymore because + a) only the basic scheme can benefit from that + b) digest/NTLM (and I suspect kerberos) will have unique headers each and every time + c) the benefits vs the decode time are marginal vsd the extra code overhead. */ /* see if we already know this user. Note that NTLM users will never be * found here: ntlm keys are not put in the hash table because the * negotiate phase is not unqiue. */ @@ -190,24 +288,32 @@ if (!proxy_auth_hash) { /* not in the hash table */ debug(29, 4) ("authenticateGetAuthUser: proxy-auth cache miss. Decoding header details.\n"); +#if 0 auth_user = memAllocate(MEM_AUTH_USER_T); - authenticateDecodeAuth(proxy_auth, auth_user); +#endif + auth_user_request = authenticateAuthUserRequestNew(); + authenticateDecodeAuth(proxy_auth, auth_user_request); } else { debug(29, 4) ("authenticateGetAuthUser: proxy-auth cache hit.\n"); - auth_user = proxy_auth_hash->auth_user; + /* create a new request structure */ + auth_user_request = authenticateAuthUserRequestNew(); + /* tie in the known user */ + auth_user_request->auth_user = proxy_auth_hash->auth_user; + /* decode to get request specific details */ } - return auth_user; +#endif + return auth_user_request; } /* * authenticateUserAuthenticated: is this auth_user structure logged in ? */ int -authenticateUserAuthenticated(auth_user_t *auth_user) { - assert(authenticateValidateUser(auth_user)); - if (auth_user->auth_module>0) - return authscheme_list[auth_user->auth_module-1].authenticated(auth_user); +authenticateUserAuthenticated(auth_user_request_t *auth_user_request) { + assert(authenticateValidateUser(auth_user_request)); + if (auth_user_request->auth_user->auth_module>0) + return authscheme_list[auth_user_request->auth_user->auth_module-1].authenticated(auth_user_request); else return 0; #if 0 @@ -220,19 +326,18 @@ } /* - * authenticateAuthenticateUser: log this user in returns a new auth_user. - * This is because cache hits destroy prior auth_user structs. - * We could use a auth_user_handle approach I suppose... RC + * authenticateAuthenticateUser: log this user request in. + * Cache hits may change the auth_user pointer in the structure if needed. + * This is basically a handle approach. */ -auth_user_t * -authenticateAuthenticateUser(auth_user_t *auth_user, request_t *request, ConnStateData *conn, http_hdr_type type) { +void +authenticateAuthenticateUser(auth_user_request_t *auth_user_request, request_t *request, ConnStateData *conn, http_hdr_type type) { #if 0 const char * proxy_auth; #endif - assert(auth_user !=NULL); - if (auth_user->auth_module>0) - return authscheme_list[auth_user->auth_module-1].authAuthenticate(auth_user, request, conn, type); - return auth_user; + assert(auth_user_request !=NULL); + if (auth_user_request->auth_user->auth_module>0) + authscheme_list[auth_user_request->auth_user->auth_module-1].authAuthenticate(auth_user_request, request, conn, type); #if 0 proxy_auth = httpHeaderGetStr(&request->header, type); @@ -242,12 +347,22 @@ /* authenticateUserUsername: return a pointer to the username in the */ char * authenticateUserUsername(auth_user_t *auth_user) { - assert (auth_user !=NULL); + if (!auth_user) + return NULL; if (auth_user->auth_module>0) return authscheme_list[auth_user->auth_module-1].authUserUsername(auth_user); return NULL; } +/* authenticateUserRequestUsername: return a pointer to the username in the */ +char * +authenticateUserRequestUsername(auth_user_request_t *auth_user_request) { + assert (auth_user_request !=NULL); + if (!auth_user_request->auth_user) + return NULL; + return authenticateUserUsername(auth_user_request->auth_user); +} + /* returns 0: no output needed 1: send to client @@ -255,11 +370,11 @@ -2: authenticate broken in some fashion */ int -authenticateDirection(auth_user_t *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); +authenticateDirection(auth_user_request_t *auth_user_request) { + if (!auth_user_request) return -2; + if (authenticateUserAuthenticated(auth_user_request)) return 0; + if (auth_user_request->auth_user->auth_module>0) + return authscheme_list[auth_user_request->auth_user->auth_module-1].getdirection(auth_user_request); return -2; } @@ -324,7 +439,7 @@ /* auth_type_t auth_type=err->auth_type; auth_state_t auth_state=err->auth_state; char *authchallenge=err->authchallenge; -*/ auth_user_t *auth_user=err->auth_user; +*/ auth_user_request_t *auth_user_request=err->auth_user_request; int type; switch (err->http_status) { case HTTP_PROXY_AUTHENTICATION_REQUIRED: @@ -341,9 +456,9 @@ return; break; } - debug(29,9)("authenticateFixHeader: headertype:%d authuser:%d\n",type,auth_user); - if ((auth_user !=NULL) && (auth_user->auth_module>0)) - authscheme_list[auth_user->auth_module-1].authFixHeader(auth_user, rep, type, err->request); + debug(29,9)("authenticateFixHeader: headertype:%d authuser:%d\n",type,auth_user_request); + if ((auth_user_request !=NULL) && (auth_user_request->auth_user->auth_module>0)) + authscheme_list[auth_user_request->auth_user->auth_module-1].authFixHeader(auth_user_request, rep, type, err->request); else { int i; authScheme *scheme; @@ -352,7 +467,7 @@ { scheme=Config.authConfig.schemes+i; if (authscheme_list[scheme->Id].Active()) - authscheme_list[scheme->Id].authFixHeader(auth_user,rep,type, + authscheme_list[scheme->Id].authFixHeader(auth_user_request,rep,type, err->request); else debug(29,8)("authenticateFixHeader: Configured scheme %s not Active\n",scheme->typestr); @@ -367,6 +482,7 @@ auth_user->references++; debug (29,6) ("authenticateAuthUserLock auth_user '%d' now at '%d'.\n",auth_user, auth_user->references); } + void authenticateAuthUserUnlock(auth_user_t *auth_user) { debug (29,6) ("authenticateAuthUserUnlock auth_user '%d'.\n",auth_user); @@ -377,14 +493,34 @@ debug(29,1) ("Attempt to lower Auth User %d refcount below 0!\n",auth_user); } debug (29,6) ("authenticateAuthUserUnlock auth_user '%d' now at '%d'.\n",auth_user, auth_user->references); - if (auth_user->references==0) { + if (auth_user->references==0) + authenticateFreeProxyAuthUser(auth_user); +} + +void authenticateAuthUserRequestLock(auth_user_request_t *auth_user_request) +{ + debug (29,6) ("authenticateAuthUserRequestLock auth_user request '%d'.\n",auth_user_request); + assert(auth_user_request!=NULL); + auth_user_request->references++; + debug (29,6) ("authenticateAuthUserRequestLock auth_user request '%d' now at '%d'.\n",auth_user_request, auth_user_request->references); +} + +void authenticateAuthUserRequestUnlock(auth_user_request_t *auth_user_request) +{ + debug (29,6) ("authenticateAuthUserRequestUnlock auth_user request '%d'.\n",auth_user_request); + assert(auth_user_request != NULL); + if (auth_user_request->references>0){ + auth_user_request->references--; + } else { + debug(29,1) ("Attempt to lower Auth User request %d refcount below 0!\n",auth_user_request); + } + debug (29,6) ("authenticateAuthUserRequestUnlock auth_user_request '%d' now at '%d'.\n",auth_user_request, auth_user_request->references); + if (auth_user_request->references==0) { /* not locked anymore */ - if (!auth_user->usernamehash) { - /* they are not in the username hash */ - authenticateFreeProxyAuthUser(auth_user); - } + authenticateAuthUserRequestFree(auth_user_request); } } + int authenticateAuthUserInuse(auth_user_t *auth_user) /* returns 0 for not in use */ { @@ -396,6 +532,7 @@ authenticateAuthUserMerge(auth_user_t *from, auth_user_t *to) { /* XXX combine two authuser structs. Incomplete: it should merge in hash references too and ask the module to merge in scheme data*/ +/* XXX TODO transfer over all outstanding request structures as well */ debug (29,6) ("authenticateAuthUserMerge auth_user '%d' into auth_user '%d'.\n",from,to); to->references+=from->references; from->references=0; @@ -406,7 +543,10 @@ authenticateFreeProxyAuthUser(void *data) { auth_user_t *u = data; + auth_user_request_t *auth_user_request; +#if 0 auth_user_hash_pointer *proxy_auth_hash; +#endif dlink_node *link, *tmplink; assert(data !=NULL); debug(29,6) ("authenticateFreeProxyAuthUser: Freeing auth_user '%d' with refcount '%d'.\n",u,u->references); @@ -421,6 +561,7 @@ * structure */ memFree(u->usernamehash, MEM_AUTH_USER_HASH); } +#if 0 /* were they linked in by one or more proxy-authenticate headers */ link = u->proxy_auth_list.head; while (link) { @@ -434,6 +575,18 @@ xfree(proxy_auth_hash->key); memFree(proxy_auth_hash, MEM_AUTH_USER_HASH); } +#endif + /* remove any outstanding requests */ + link = u->requests.head; + while (link) { + debug(29,6) ("authenticateFreeProxyAuthUser: removing request entry '%d'\n",link->data); + auth_user_request = link->data; + tmplink = link; + link=link->next; + dlinkDelete(tmplink, &u->requests); + dlinkNodeDelete(tmplink); + authenticateAuthUserRequestFree(auth_user_request); + } /* free cached acl results */ aclCacheMatchFlush(&u->proxy_match_cache); if (u->scheme_data && u->auth_module>0) @@ -450,10 +603,12 @@ proxy_auth_username_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); assert(proxy_auth_username_cache); +#if 0 /* First time around, 7921 should be big enough */ proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string); assert(proxy_auth_cache); +#endif eventAdd("User Cache Maintenance", authenticateProxyUserCacheCleanup, NULL, Config.authenticateGCInterval, 1); } } @@ -481,10 +636,11 @@ debug(29,6) ("authenticateProxyUserCacheCleanup: Cache entry:\n\tType: %d\n\tUsername: %s\n\texpires: %d\n\treferences: %d\n", auth_user->auth_type, username, auth_user->expiretime+ Config.authenticateTTL,auth_user->references); if (auth_user->expiretime + Config.authenticateTTL <= current_time.tv_sec) { debug(29,3)("authenticateProxyUserCacheCleanup: Removing user %s from cache due to timeout.\n",username); - if (authenticateAuthUserInuse(auth_user)) + /* the minus 1 accounts for the cache lock */ + if ((authenticateAuthUserInuse(auth_user)-1)) debug(29,3)("authenticateProxyUserCacheCleanup: this cache entry has expired AND has a non-zero ref count.\n"); else - authenticateFreeProxyAuthUser(auth_user); + authenticateAuthUserUnlock(auth_user); } } debug(29,6) ("authenticateProxyUserCacheCleanup: Finished cleaning the user cache.\n"); @@ -512,6 +668,8 @@ } + +#if 0 void authenticateProxyAuthCacheAddLink(const char *key, auth_user_t *auth_user){ auth_user_hash_pointer *proxy_auth_hash; @@ -523,6 +681,7 @@ &proxy_auth_hash->auth_user->proxy_auth_list); hash_join(proxy_auth_cache, (hash_link *) proxy_auth_hash); } +#endif /* * called to add another auth scheme module @@ -554,6 +713,8 @@ usernamehash->auth_user = auth_user; hash_join(proxy_auth_username_cache, (hash_link *) usernamehash); auth_user->usernamehash = usernamehash; + /* lock for presence in the cache */ + authenticateAuthUserLock(auth_user); } @@ -566,21 +727,21 @@ /* TODO: * ip_expire data should be in a struct of it's own - for code reuse */ int -authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_t * auth_user) +authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_request_t * auth_user_request) { char *username=NULL; - if (request_src_addr.s_addr == auth_user->ipaddr.s_addr || auth_user->ip_expiretime+ Config.authenticateIpTTL <= squid_curtime) { + if (request_src_addr.s_addr == auth_user_request->auth_user->ipaddr.s_addr || auth_user_request->auth_user->ip_expiretime+ Config.authenticateIpTTL <= squid_curtime) { /* user has not moved ip or had the ip timeout expire */ - if ((auth_user->auth_type==AUTH_UNKNOWN) || - (auth_user->auth_type==AUTH_BROKEN)) { + if ((auth_user_request->auth_user->auth_type==AUTH_UNKNOWN) || + (auth_user_request->auth_user->auth_type==AUTH_BROKEN)) { debug(29, 1) - ("authenticateCheckProxyAuthIP: broken or unknown auth type %d.\n", auth_user->auth_type); + ("authenticateCheckProxyAuthIP: broken or unknown auth type %d.\n", auth_user_request->auth_user->auth_type); return 0; } - username=authenticateUserUsername(auth_user); + username=authenticateUserRequestUsername(auth_user_request); /* Update IP ttl */ - auth_user->ip_expiretime = squid_curtime; - auth_user->ipaddr = request_src_addr; + auth_user_request->auth_user->ip_expiretime = squid_curtime; + auth_user_request->auth_user->ipaddr = request_src_addr; return 1; } /* we are missing a check: expired IP time is actually ok. let it through 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.2.7 retrieving revision 1.1.1.3.4.1.2.30.2.8 diff -u -r1.1.1.3.4.1.2.30.2.7 -r1.1.1.3.4.1.2.30.2.8 --- squid/src/client_side.c 30 Dec 2000 22:48:18 -0000 1.1.1.3.4.1.2.30.2.7 +++ squid/src/client_side.c 2 Jan 2001 10:57:01 -0000 1.1.1.3.4.1.2.30.2.8 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.1.1.3.4.1.2.30.2.7 2000/12/30 22:48:18 rbcollins Exp $ + * $Id: client_side.c,v 1.1.1.3.4.1.2.30.2.8 2001/01/02 10:57:01 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -223,8 +223,7 @@ RequestMethodStr[http->request->method], http->uri, answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED", AclMatchedName ? AclMatchedName : "NO ACL's"); - if (http->acl_checklist->auth_user) - proxy_auth_msg = http->acl_checklist->auth_user->message; + proxy_auth_msg = authenticateAuthUserRequestMessage(http->acl_checklist->auth_user_request); http->acl_checklist = NULL; if (answer == ACCESS_ALLOWED) { safe_free(http->uri); @@ -266,10 +265,13 @@ err = errorCon(page_id, status); err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; - if (http->conn->auth_user) - err->auth_user=http->conn->auth_user; - else if (http->request->auth_user) - err->auth_user=http->request->auth_user; + if (http->conn->auth_user_request) + err->auth_user_request=http->conn->auth_user_request; + else if (http->request->auth_user_request) + err->auth_user_request=http->request->auth_user_request; + /* lock for the error state */ + if (err->auth_user_request) + authenticateAuthUserRequestLock(err->auth_user_request); #if 0 err->auth_type = http->conn->auth_type; if (http->conn->auth_user) { @@ -280,7 +282,6 @@ if ((http->conn->auth_user) && (http->conn->auth_user->auth_type==AUTH_NTLM)) err->authchallenge = http->conn->auth_user->auth_data.ntlm_auth.authchallenge; #endif - err->proxy_auth_msg = proxy_auth_msg; err->callback_data = NULL; errorAppendEntry(http->entry, err); } @@ -319,7 +320,7 @@ new_request->my_addr = old_request->my_addr; new_request->my_port = old_request->my_port; new_request->flags.redirected = 1; - new_request->auth_user=old_request->auth_user; + new_request->auth_user_request=old_request->auth_user_request; #if 0 if (old_request->authuser[0]) xstrncpy(new_request->authuser, old_request->authuser, @@ -764,8 +765,8 @@ http->al.http.version = request->http_ver; http->al.headers.request = xstrdup(mb.buf); http->al.hier = request->hier; - if (request->auth_user) - http->al.cache.authuser = authenticateUserUsername(request->auth_user); + if (request->auth_user_request) + http->al.cache.authuser = authenticateUserRequestUsername(request->auth_user_request); #if 0 if (request->authuser[0]) http->al.cache.authuser = request->authuser; @@ -829,9 +830,7 @@ clientHttpRequest *http; debug(33, 3) ("connStateFree: FD %d\n", fd); assert(connState != NULL); - if (connState->auth_user) { - authenticateOnCloseConnection(connState); - } + authenticateOnCloseConnection(connState); clientdbEstablished(connState->peer.sin_addr, -1); /* decrement */ while ((http = connState->chr) != NULL) { assert(http->conn == connState); Index: squid/src/errorpage.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/errorpage.c,v retrieving revision 1.1.1.3.10.9.2.3 retrieving revision 1.1.1.3.10.9.2.4 diff -u -r1.1.1.3.10.9.2.3 -r1.1.1.3.10.9.2.4 --- squid/src/errorpage.c 1 Jan 2001 01:55:41 -0000 1.1.1.3.10.9.2.3 +++ squid/src/errorpage.c 2 Jan 2001 10:57:02 -0000 1.1.1.3.10.9.2.4 @@ -1,6 +1,6 @@ /* - * $Id: errorpage.c,v 1.1.1.3.10.9.2.3 2001/01/01 01:55:41 rbcollins Exp $ + * $Id: errorpage.c,v 1.1.1.3.10.9.2.4 2001/01/02 10:57:02 rbcollins Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -363,11 +363,11 @@ safe_free(err->url); safe_free(err->host); safe_free(err->dnsserver_msg); - safe_free(err->proxy_auth_msg); safe_free(err->request_hdrs); wordlistDestroy(&err->ftp.server_msg); safe_free(err->ftp.request); safe_free(err->ftp.reply); + authenticateAuthUserRequestUnlock(err->auth_user_request); if (err->flags.flag_cbdata) cbdataFree(err); else @@ -472,7 +472,7 @@ p = "[not available]"; break; case 'm': - p = err->proxy_auth_msg ? err->proxy_auth_msg : "[not available]"; + p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]"; break; case 'M': p = r ? RequestMethodStr[r->method] : "[unkown method]"; Index: squid/src/globals.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/globals.h,v retrieving revision 1.1.1.3.12.8.2.2 retrieving revision 1.1.1.3.12.8.2.3 diff -u -r1.1.1.3.12.8.2.2 -r1.1.1.3.12.8.2.3 --- squid/src/globals.h 13 Dec 2000 01:23:31 -0000 1.1.1.3.12.8.2.2 +++ squid/src/globals.h 2 Jan 2001 10:57:02 -0000 1.1.1.3.12.8.2.3 @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.1.1.3.12.8.2.2 2000/12/13 01:23:31 rbcollins Exp $ + * $Id: globals.h,v 1.1.1.3.12.8.2.3 2001/01/02 10:57:02 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -154,4 +154,3 @@ extern ssize_t store_maxobjsize; /* -1 */ extern RemovalPolicy *mem_policy; extern hash_table *proxy_auth_username_cache; /* NULL */ -extern hash_table *proxy_auth_cache; /* 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.13 retrieving revision 1.1.1.3.12.17.2.14 diff -u -r1.1.1.3.12.17.2.13 -r1.1.1.3.12.17.2.14 --- squid/src/protos.h 1 Jan 2001 12:05:09 -0000 1.1.1.3.12.17.2.13 +++ squid/src/protos.h 2 Jan 2001 10:57:02 -0000 1.1.1.3.12.17.2.14 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.1.1.3.12.17.2.13 2001/01/01 12:05:09 rbcollins Exp $ + * $Id: protos.h,v 1.1.1.3.12.17.2.14 2001/01/02 10:57:02 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -713,31 +713,37 @@ /* authenticate.c */ extern void authenticateAuthUserMerge(auth_user_t *, auth_user_t *); +extern auth_user_t *authenticateAuthUserNew(const char *); extern int authenticateAuthSchemeId(const char *typestr); -extern void authenticateStart(auth_user_t *, RH *, void *); +extern void authenticateStart(auth_user_request_t *, RH *, void *); extern void authenticateSchemeInit(void); extern void authenticateInit(authConfig *); extern void authenticateShutdown(void); extern void authenticateFixHeader(HttpReply * rep, ErrorState * err); -extern auth_user_t *authenticateGetAuthUser(const char *proxy_auth); -extern auth_user_t *authenticateAuthenticateUser(auth_user_t *auth_user, request_t * request, ConnStateData *conn, http_hdr_type type); +extern auth_user_request_t *authenticateGetAuthUser(const char *proxy_auth); +extern void authenticateAuthenticateUser(auth_user_request_t *, request_t *, ConnStateData *, http_hdr_type); extern void authenticateAuthUserUnlock(auth_user_t *auth_user); extern void authenticateAuthUserLock(auth_user_t *auth_user); +extern void authenticateAuthUserRequestUnlock(auth_user_request_t *); +extern void authenticateAuthUserRequestLock(auth_user_request_t *); +extern char *authenticateAuthUserRequestMessage(auth_user_request_t *); extern int authenticateAuthUserInuse(auth_user_t *auth_user); -extern int authenticateDirection(auth_user_t *auth_user); +extern void authenticateAuthUserRequestSetIp(auth_user_request_t *, struct in_addr); +extern int authenticateDirection(auth_user_request_t *); extern FREE authenticateFreeProxyAuthUser; extern void authenticateFreeProxyAuthUserACLResults(void *data); extern void authenticateProxyUserCacheCleanup(void *); extern void authenticateInitUserCache(); -extern void authenticateProxyAuthCacheAddLink(const char *key, auth_user_t * auth_user); +extern void authenticateProxyAuthCacheAddLink(const char *key, auth_user_t *); extern int authenticateActiveSchemeCount(); extern int authenticateSchemeCount(); extern void authenticateUserNameCacheAdd(auth_user_t *auth_user); -extern int authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_t * auth_user); -extern int authenticateUserAuthenticated(auth_user_t *auth_user); +extern int authenticateCheckAuthUserIP(struct in_addr request_src_addr, auth_user_request_t * auth_user); +extern int authenticateUserAuthenticated(auth_user_request_t *); extern void authenticateUserCacheRestart(); -extern char *authenticateUserUsername(auth_user_t *auth_user); -extern int authenticateValidateUser(auth_user_t * auth_user); +extern char *authenticateUserUsername(auth_user_t *); +extern char *authenticateUserRequestUsername(auth_user_request_t *); +extern int authenticateValidateUser(auth_user_request_t *); extern void authenticateOnCloseConnection(ConnStateData *conn); extern void authSchemeAdd(char *type, AUTHSSETUP * setup); @@ -1108,6 +1114,9 @@ extern void dlinkAdd(void *data, dlink_node *, dlink_list *); extern void dlinkAddTail(void *data, dlink_node *, dlink_list *); extern void dlinkDelete(dlink_node * m, dlink_list * list); +extern void dlinkNodeDelete(dlink_node * m); +extern dlink_node *dlinkNodeNew(); + extern void kb_incr(kb_t *, size_t); extern double gb_to_double(const gb_t *); extern const char *gb_to_str(const gb_t *); Index: squid/src/redirect.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/redirect.c,v retrieving revision 1.1.1.3.4.1.2.2.2.1 retrieving revision 1.1.1.3.4.1.2.2.2.2 diff -u -r1.1.1.3.4.1.2.2.2.1 -r1.1.1.3.4.1.2.2.2.2 --- squid/src/redirect.c 23 Nov 2000 10:37:27 -0000 1.1.1.3.4.1.2.2.2.1 +++ squid/src/redirect.c 2 Jan 2001 10:57:02 -0000 1.1.1.3.4.1.2.2.2.2 @@ -1,6 +1,6 @@ /* - * $Id: redirect.c,v 1.1.1.3.4.1.2.2.2.1 2000/11/23 10:37:27 rbcollins Exp $ + * $Id: redirect.c,v 1.1.1.3.4.1.2.2.2.2 2001/01/02 10:57:02 rbcollins Exp $ * * DEBUG: section 29 Redirector * AUTHOR: Duane Wessels @@ -130,8 +130,8 @@ if (http->request->authuser[0]) r->client_ident = http->request->authuser; #endif - if (http->request->auth_user) - r->client_ident = authenticateUserUsername(http->request->auth_user); + if (http->request->auth_user_request) + r->client_ident = authenticateUserRequestUsername(http->request->auth_user_request); else if (conn->rfc931[0]) { r->client_ident = conn->rfc931; } else { 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.15 retrieving revision 1.1.1.3.4.1.2.26.2.16 diff -u -r1.1.1.3.4.1.2.26.2.15 -r1.1.1.3.4.1.2.26.2.16 --- squid/src/structs.h 1 Jan 2001 09:51:21 -0000 1.1.1.3.4.1.2.26.2.15 +++ squid/src/structs.h 2 Jan 2001 10:57:02 -0000 1.1.1.3.4.1.2.26.2.16 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.15 2001/01/01 09:51:21 rbcollins Exp $ + * $Id: structs.h,v 1.1.1.3.4.1.2.26.2.16 2001/01/02 10:57:02 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -101,9 +101,23 @@ size_t references; /* how many references are outstanding to this instance*/ /* the auth scheme has it's own private data area */ void *scheme_data; + dlink_list requests; +}; + +struct _auth_user_request_t { + /* this is the object passed around by client_side and acl functions */ + /* it has request specific data, and links to user specific data */ + /* the user */ + auth_user_t *auth_user; + /* return a message on the 407 error pages */ char *message; + /* any scheme specific request related data */ + void *scheme_data; + /* how many 'processes' are working on this data */ + size_t references; }; + /* * This defines an auth scheme module */ @@ -122,6 +136,7 @@ AUTHSDIRECTION *getdirection; AUTHSPARSE *parse; AUTHSINIT *init; + AUTHSREQFREE *requestFree; AUTHSSHUTDOWN *donefunc; AUTHSSTART *authStart; AUTHSSTATS *authStats; @@ -215,7 +230,7 @@ request_t *request; ConnStateData *conn; /* hack for ident and NTLM*/ char rfc931[USER_IDENT_SZ]; - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; acl_lookup_state state[ACL_ENUM_MAX]; #if SQUID_SNMP char *snmp_community; @@ -1009,7 +1024,7 @@ auth_type_t auth_type; /* Is this connection based authentication ? if so * what type it is. */ /* note this is ONLY connection based because NTLM is against HTTP spec */ - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; clientHttpRequest *chr; struct sockaddr_in peer; struct sockaddr_in me; @@ -1542,7 +1557,7 @@ #if 0 char authuser[USER_IDENT_SZ]; /* from proxy auth only */ #endif - auth_user_t *auth_user; + auth_user_request_t *auth_user_request; u_short port; String urlpath; char *canonical; @@ -1604,14 +1619,13 @@ err_type type; int page_id; http_status http_status; - auth_user_t * auth_user; + auth_user_request_t * auth_user_request; request_t *request; char *url; int xerrno; char *host; u_short port; char *dnsserver_msg; - char *proxy_auth_msg; time_t ttl; struct in_addr src_addr; char *redirect_url; Index: squid/src/tools.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/tools.c,v retrieving revision 1.1.1.3.10.7.2.2 retrieving revision 1.1.1.3.10.7.2.3 diff -u -r1.1.1.3.10.7.2.2 -r1.1.1.3.10.7.2.3 --- squid/src/tools.c 13 Dec 2000 01:23:31 -0000 1.1.1.3.10.7.2.2 +++ squid/src/tools.c 2 Jan 2001 10:57:02 -0000 1.1.1.3.10.7.2.3 @@ -1,6 +1,6 @@ /* - * $Id: tools.c,v 1.1.1.3.10.7.2.2 2000/12/13 01:23:31 rbcollins Exp $ + * $Id: tools.c,v 1.1.1.3.10.7.2.3 2001/01/02 10:57:02 rbcollins Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -62,6 +62,8 @@ extern void (*failure_notify) (const char *); +MemPool *dlink_node_pool = NULL; + void releaseServerSockets(void) { @@ -753,6 +755,24 @@ return p ? p : "(NULL)"; } +dlink_node * +dlinkNodeNew() +{ + if (dlink_node_pool==NULL) + dlink_node_pool = memPoolCreate("Dlink list nodes", sizeof(dlink_node)); + /* where should we call memPoolDestroy(dlink_node_pool); */ + return memPoolAlloc(dlink_node_pool); +} + +/* the node needs to be unlinked FIRST */ +void +dlinkNodeDelete(dlink_node * m) +{ + if (m==NULL) + return; + memPoolFree(dlink_node_pool, m); +} + void dlinkAdd(void *data, dlink_node * m, dlink_list * list) { Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.1.1.3.12.13.2.11 retrieving revision 1.1.1.3.12.13.2.12 diff -u -r1.1.1.3.12.13.2.11 -r1.1.1.3.12.13.2.12 --- squid/src/typedefs.h 1 Jan 2001 09:51:21 -0000 1.1.1.3.12.13.2.11 +++ squid/src/typedefs.h 2 Jan 2001 10:57:02 -0000 1.1.1.3.12.13.2.12 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.1.1.3.12.13.2.11 2001/01/01 09:51:21 rbcollins Exp $ + * $Id: typedefs.h,v 1.1.1.3.12.13.2.12 2001/01/02 10:57:02 rbcollins Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -64,6 +64,7 @@ typedef struct _acl_deny_info_list acl_deny_info_list; typedef struct _acl_proxy_auth acl_proxy_auth; typedef struct _auth_user_t auth_user_t; +typedef struct _auth_user_request_t auth_user_request_t; typedef struct _auth_user_hash_pointer auth_user_hash_pointer; typedef struct _acl_proxy_auth_match_cache acl_proxy_auth_match_cache; typedef struct _authscheme_entry authscheme_entry_t; @@ -293,20 +294,21 @@ /* authenticate.c authenticate scheme routines typedefs */ typedef int AUTHSACTIVE(); -typedef int AUTHSAUTHED(auth_user_t *); -typedef auth_user_t * AUTHSAUTHUSER(auth_user_t *, request_t *, ConnStateData *, http_hdr_type); -typedef void AUTHSDECODE(auth_user_t *, const char *); -typedef int AUTHSDIRECTION(auth_user_t *); -typedef void AUTHSFIXERR(auth_user_t *, HttpReply *, http_hdr_type, request_t *); +typedef int AUTHSAUTHED(auth_user_request_t *); +typedef void AUTHSAUTHUSER(auth_user_request_t *, request_t *, ConnStateData *, http_hdr_type); +typedef void AUTHSDECODE(auth_user_request_t *, const char *); +typedef int AUTHSDIRECTION(auth_user_request_t *); +typedef void AUTHSFIXERR(auth_user_request_t *, HttpReply *, http_hdr_type, request_t *); typedef void AUTHSFREE(auth_user_t *); typedef void AUTHSFREECONFIG(authScheme *); typedef char *AUTHSUSERNAME(auth_user_t *); typedef void AUTHSONCLOSEC(ConnStateData *); typedef void AUTHSPARSE(authScheme *, int, char *); typedef void AUTHSINIT(authScheme *); +typedef void AUTHSREQFREE(auth_user_request_t *); typedef void AUTHSSETUP(authscheme_entry_t *); typedef void AUTHSSHUTDOWN(void); -typedef void AUTHSSTART(auth_user_t * , RH * , void *); +typedef void AUTHSSTART(auth_user_request_t * , RH * , void *); typedef void AUTHSSTATS(StoreEntry *); /* append/vprintf's for Packer */ Index: squid/src/auth/basic/auth_basic.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/basic/auth_basic.c,v retrieving revision 1.1.2.12 retrieving revision 1.1.2.13 diff -u -r1.1.2.12 -r1.1.2.13 --- squid/src/auth/basic/auth_basic.c 1 Jan 2001 12:05:10 -0000 1.1.2.12 +++ squid/src/auth/basic/auth_basic.c 2 Jan 2001 10:57:02 -0000 1.1.2.13 @@ -127,13 +127,12 @@ } int -authenticateBasicAuthenticated(auth_user_t * auth_user) +authenticateBasicAuthenticated(auth_user_request_t * auth_user_request) { - basic_data *basic_auth=auth_user->scheme_data; - /* if they are in the hash they must be authenticated */ - if ((auth_user->usernamehash) && (basic_auth->credentials_checkedtime+basicConfig->credentialsTTL > squid_curtime)) + basic_data *basic_auth=auth_user_request->auth_user->scheme_data; + if ((auth_user_request->auth_user->flags.credentials_ok==1) && (basic_auth->credentials_checkedtime+basicConfig->credentialsTTL > squid_curtime)) return 1; - debug (29, 7) ("Couldn't find user in cache or credentials need rechecking.\n"); + debug (29, 7) ("User not authenticated or credentials need rechecking.\n"); return 0; } @@ -144,28 +143,45 @@ /* log a basic user in */ -static auth_user_t * -authenticateBasicAuthenticateUser(auth_user_t *auth_user, request_t *request, ConnStateData *conn, http_hdr_type type) { +static void +authenticateBasicAuthenticateUser(auth_user_request_t *auth_user_request, request_t *request, ConnStateData *conn, http_hdr_type type) { +#if 0 auth_user_hash_pointer *usernamehash, *proxy_auth_hash=NULL; - basic_data * basic_auth, *temp_auth; +#endif + auth_user_t *auth_user; + basic_data * basic_auth; +#if 0 +//, *temp_auth; const char * proxy_auth; +#endif + + assert (auth_user_request->auth_user != NULL); + auth_user=auth_user_request->auth_user; + /* if the password is not ok, do an identity */ if (auth_user->flags.credentials_ok!=1) - return auth_user; + return; assert(auth_user->scheme_data != NULL); basic_auth = auth_user->scheme_data; /* are we about to recheck the credentials externally? */ - if (basic_auth->credentials_checkedtime+basicConfig->credentialsTTL<=squid_curtime) - return auth_user; - + if ((basic_auth->credentials_checkedtime+basicConfig->credentialsTTL)<=squid_curtime) + { + debug(29,6)("authBasicAuthenticate: credentials expired - rechecking\n"); + return; + } +#if 0 /* get the header. */ proxy_auth = httpHeaderGetStr(&request->header, type); +#endif - /* password was checked and did match */ - debug(29, 4) ("authenticateBasicAuthenticateuser: user '%s' validated OK\n", + /* we have been through the external helper, and the credentials haven't expired */ + debug(29, 4) ("authenticateBasicAuthenticateuser: user '%s' authenticated\n", basic_auth->username); + + /* Decode now takes care of finding the auth_user struct in the cache */ +#if 0 /* see if this is an existing user with a different proxy_auth string */ if ((usernamehash = hash_lookup(proxy_auth_username_cache, basic_auth->username))) { @@ -200,15 +216,17 @@ authenticateUserNameCacheAdd(auth_user); authenticateProxyAuthCacheAddLink(proxy_auth, auth_user); } - /* auth_user is now linked, we reset these values - * after external auth occurs anyway */ + /* auth_user is now linked, we reset these values */ +#endif + /* after external auth occurs anyway */ auth_user->expiretime = current_time.tv_sec; auth_user->ip_expiretime = squid_curtime; - return auth_user; + return; } -int authenticateBasicDirection(auth_user_t *auth_user) { +int authenticateBasicDirection(auth_user_request_t *auth_user_request) { /* null auth_user is checked for by authenticateDirection */ + auth_user_t * auth_user = auth_user_request->auth_user; basic_data *basic_auth=auth_user->scheme_data; switch (auth_user->flags.credentials_ok) { case 0: /* not checked */ @@ -226,8 +244,9 @@ } void -authenticateBasicFixErrorHeader(auth_user_t *auth_user, HttpReply *rep, http_hdr_type type, request_t * request){ - if (basicConfig->authenticate){ +authenticateBasicFixErrorHeader(auth_user_request_t *auth_user_request, HttpReply *rep, http_hdr_type type, request_t * request){ + if (basicConfig->authenticate) + { debug(29, 5) ("authenticateFixErrorHeader: Sending type:%d header: 'Basic realm=\"%s\"'\n",type,basicConfig->basicAuthRealm); httpHeaderPutStrf(&rep->header, type, "Basic realm=\"%s\"", basicConfig->basicAuthRealm); } @@ -275,9 +294,9 @@ if (*reply == '\0') reply = NULL; } - assert(r->auth_user != NULL); - assert(r->auth_user->auth_type == AUTH_BASIC); - auth_user=r->auth_user; + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_BASIC); + auth_user=r->auth_user_request->auth_user; basic_auth=auth_user->scheme_data; if (reply && (strncasecmp(reply, "OK", 2) == 0)) auth_user->flags.credentials_ok = 1; @@ -348,28 +367,77 @@ return NULL; } +basic_data * +authBasicDataNew() +{ + basic_data *temp; + temp=memPoolAlloc(basic_data_pool); + assert(temp!=NULL); + temp->username=NULL; + temp->passwd=NULL; + return temp; +} + +void +authBasicDataFree(basic_data *basic_auth) +{ +} + +auth_user_t * +authBasicAuthUserFindUsername(const char * username) +{ + auth_user_hash_pointer *usernamehash; + auth_user_t * auth_user; + debug(29,9)("authBasicAuthUserFindUsername: Looking for user '%s'\n",username); + if (username && (usernamehash = hash_lookup(proxy_auth_username_cache, username))) + { + while ((usernamehash->auth_user->auth_type != AUTH_BASIC) && + (usernamehash->next)) + usernamehash=usernamehash->next; + auth_user=NULL; + if (usernamehash->auth_user->auth_type==AUTH_BASIC) + { + auth_user=usernamehash->auth_user; + } + return auth_user; + } + return NULL; +} + + + /* - * Decode a Basic [Proxy-]Auth string, placing the results in the passed - * Auth_user structure. + * Decode a Basic [Proxy-]Auth string, linking the passed auth_user_request structure + * to any existing user structure or creating one if needed. Note that just returning + * will be treated as "cannot decode credentials". Use the message field to return a + * descriptive message to the user. + */ + + +/* there is abit of temporary confusion here: + * the username in memory is currently stored with the credentials, not one set of + * credentials per ip. So a deliberatley bad set of credentials causes a cache purge of + * an other wise good set of credentials. to avoid this we don't alter the cached + * credentials if incoming credentials have no password or an empty password. + * the down side is we can't log the username. TODO: create a auth_user_t struct in memory + * for just long enough to log the bad username and then drop from memory */ static void -authenticateBasicDecodeAuth(auth_user_t *auth_user, const char * proxy_auth) { +authenticateBasicDecodeAuth(auth_user_request_t *auth_user_request, const char * proxy_auth) { char *sent_auth; char *cleartext; - basic_data * basic_auth; - assert(auth_user->auth_type == AUTH_UNKNOWN); - /* basic until proved otherwise */ - auth_user->auth_type = AUTH_BASIC; - /* have we been called before? */ - assert(auth_user->scheme_data == NULL); - auth_user->scheme_data = memPoolAlloc(basic_data_pool); - basic_auth=auth_user->scheme_data; - + basic_data * basic_auth, local_basic; + auth_user_t * auth_user; + dlink_node * node; + + /* decode the username */ /* trim BASIC from string */ while (!xisspace(*proxy_auth)) proxy_auth++; + local_basic.passwd=NULL; + /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) proxy_auth++; @@ -385,36 +453,83 @@ */ strtok(cleartext, "\r\n"); debug(29, 6) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext); - basic_auth->username = xstrndup(cleartext, USER_IDENT_SZ); + local_basic.username = xstrndup(cleartext, USER_IDENT_SZ); xfree(cleartext); - if ((cleartext = strchr(basic_auth->username, ':')) != NULL) + if ((cleartext = strchr(local_basic.username, ':')) != NULL) *(cleartext)++ = '\0'; + local_basic.passwd=cleartext; if (cleartext == NULL) { debug(29, 2) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n", - proxy_auth); - auth_user->auth_type = AUTH_BROKEN; + proxy_auth); + local_basic.passwd=NULL; } if (*cleartext == '\0') { debug(29, 2) ("authenticateBasicDecodeAuth: Disallowing empty password," - "user is '%s'\n", basic_auth->username); - auth_user->auth_type = AUTH_BROKEN; + "user is '%s'\n", local_basic.username); + local_basic.passwd=NULL; } /* 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 we are not returning a filled out structure */ - if (auth_user->auth_type != AUTH_BASIC) + if (local_basic.passwd==NULL) { - if (basic_auth->username) - xfree(basic_auth->username); + if (local_basic.username) + xfree(local_basic.username); +#if 0 memPoolFree(basic_data_pool, basic_auth); auth_user->scheme_data = NULL; +#endif } else { - basic_auth->passwd = xstrndup(cleartext, USER_IDENT_SZ); + local_basic.passwd = xstrndup(cleartext, USER_IDENT_SZ); } - /* we are finished with the proxy_auth */ -// xfree(auth_user->proxy_auth); -// auth_user->proxy_auth = NULL; + + /* now lookup and see if we have a matching auth_user structure in memory. */ + + if ((auth_user=authBasicAuthUserFindUsername(local_basic.username))== NULL) + { + /* the user doesn't exist in the username cache yet */ + debug(29,6)("authBasicDecodeAuth: Creating new user '%s'\n",local_basic.username); + /* new auth_user */ + auth_user=authenticateAuthUserNew("basic"); + /* new scheme data */ + basic_auth=authBasicDataNew(); + /* save the credentials */ + basic_auth->username=local_basic.username; + basic_auth->passwd=local_basic.passwd; + /* link the scheme data in */ + auth_user->scheme_data=basic_auth; + /* set the auth_user type */ + auth_user->auth_type=AUTH_BASIC; + /* current time for timeouts */ + auth_user->expiretime = current_time.tv_sec; + auth_user->ip_expiretime = squid_curtime; + + /* this auth_user struct is the 'lucky one' to get added to the username cache */ + /* the requests after this link to the auth_user */ + /* store user in hash */ + authenticateUserNameCacheAdd(auth_user); + } + else + { + debug(29,6)("authBasicDecodeAuth: Found user '%s' in the user cache as '%d'\n",local_basic.username,auth_user); + xfree(local_basic.username); + basic_auth=auth_user->scheme_data; + if (strcmp(local_basic.passwd,basic_auth->passwd)) + { + debug(29,5)("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n"); + auth_user->flags.credentials_ok=0; + xfree(basic_auth->passwd); + basic_auth->passwd=local_basic.passwd; + } + else + xfree(local_basic.passwd); + } + /* 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); return; } @@ -446,16 +561,16 @@ /* send the initial data to a basic authenticator module */ static void -authenticateBasicStart(auth_user_t * auth_user, RH * handler, void *data) +authenticateBasicStart(auth_user_request_t * auth_user_request, RH * handler, void *data) { authenticateStateData *r = NULL; char buf[8192]; basic_data * basic_auth; - assert(auth_user); + assert(auth_user_request); assert(handler); - assert(auth_user->auth_type==AUTH_BASIC); - assert(auth_user->scheme_data != NULL); - basic_auth = auth_user->scheme_data; + assert(auth_user_request->auth_user->auth_type==AUTH_BASIC); + assert(auth_user_request->auth_user->scheme_data != NULL); + basic_auth = auth_user_request->auth_user->scheme_data; debug(29, 5) ("authenticateStart: '%s:%s'\n", basic_auth->username, basic_auth->passwd); if (basicConfig->authenticate == NULL) { @@ -467,7 +582,7 @@ r->handler = handler; cbdataLock(data); r->data = data; - r->auth_user = auth_user; + r->auth_user_request = auth_user_request; snprintf(buf, 8192, "%s %s\n", basic_auth->username, basic_auth->passwd); helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r); } Index: squid/src/auth/basic/auth_basic.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/auth/basic/auth_basic.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/basic/auth_basic.h 1 Jan 2001 10:48:29 -0000 1.1.2.3 +++ squid/src/auth/basic/auth_basic.h 2 Jan 2001 10:57:02 -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;