--------------------- PatchSet 1051 Date: 2001/01/03 13:12:33 Author: rbcollins Branch: auth_rewrite Tag: (none) Log: final fix for the race on basic scheme credential requests Members: src/acl.c:1.1.1.3.12.26.2.15->1.1.1.3.12.26.2.16 src/auth/basic/auth_basic.c:1.1.2.16->1.1.2.17 src/auth/basic/auth_basic.h:1.1.2.4->1.1.2.5 Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3.12.26.2.15 retrieving revision 1.1.1.3.12.26.2.16 diff -u -r1.1.1.3.12.26.2.15 -r1.1.1.3.12.26.2.16 --- squid/src/acl.c 3 Jan 2001 12:17:10 -0000 1.1.1.3.12.26.2.15 +++ squid/src/acl.c 3 Jan 2001 13:12:33 -0000 1.1.1.3.12.26.2.16 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3.12.26.2.15 2001/01/03 12:17:10 rbcollins Exp $ + * $Id: acl.c,v 1.1.1.3.12.26.2.16 2001/01/03 13:12:33 rbcollins Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1287,31 +1287,38 @@ } /* User authenticated ok */ assert(authenticateUserAuthenticated(auth_user_request)); +#if 0 + /* timeout checking on the credentials is done by the scheme during + * decode/authenticate */ + /* timeout checking on time_since_last_request is done by the auth framework + * by not reusing the existing user during decode iff the interval is too long */ /* conn based auth can't time out during a connection */ if ((checklist->conn->auth_user_request) || (auth_user_request->auth_user->expiretime + Config.authenticateTTL > 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_request) { - /* lock the user for the request structure link */ - authenticateAuthUserRequestLock(auth_user_request); - checklist->request->auth_user_request=auth_user_request; - } - if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user_request)) { - /* Once the match is completed we have finished with the - * auth_user structure */ - /* this ACL check completed */ - authenticateAuthUserRequestUnlock(auth_user_request); - /* check to see if we have matched the user-acl before */ - return - aclCacheMatchAcl(&auth_user_request->auth_user->proxy_match_cache, - acltype, data, authenticateUserRequestUsername(auth_user_request)); - } - /* this acl check completed */ +#endif + + /* copy username to request for logging on client-side */ + /* the credentials are correct at this point */ + if (!checklist->request->auth_user_request) { + /* lock the user for the request structure link */ + authenticateAuthUserRequestLock(auth_user_request); + checklist->request->auth_user_request=auth_user_request; + } + if (authenticateCheckAuthUserIP(checklist->src_addr, auth_user_request)) { + /* Once the match is completed we have finished with the + * auth_user structure */ + /* this ACL check completed */ authenticateAuthUserRequestUnlock(auth_user_request); - return 0; - + /* check to see if we have matched the user-acl before */ + return + aclCacheMatchAcl(&auth_user_request->auth_user->proxy_match_cache, + acltype, data, authenticateUserRequestUsername(auth_user_request)); + } + /* this acl check completed */ + authenticateAuthUserRequestUnlock(auth_user_request); + return 0; +#if 0 } else { /* timeout */ fatalf("user credentials not used for too long in acl.c - currently broken\n" @@ -1339,6 +1346,7 @@ /* unreachable code. Spit a debug info and fatal squid out of here */ fatal("acl unreachable code!"); return -2; +#endif } static void 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.16 retrieving revision 1.1.2.17 diff -u -r1.1.2.16 -r1.1.2.17 --- squid/src/auth/basic/auth_basic.c 2 Jan 2001 13:34:18 -0000 1.1.2.16 +++ squid/src/auth/basic/auth_basic.c 3 Jan 2001 13:12:34 -0000 1.1.2.17 @@ -235,8 +235,8 @@ if (basic_auth->credentials_checkedtime+basicConfig->credentialsTTL<=squid_curtime) return -1; return 0; - case 2: /* partway through checking. Invalid for basic */ - return -2; + case 2: /* paused while waiting for a username:password check on another request*/ + return -1; case 3: /* authentication process failed. */ return -2; } @@ -285,6 +285,7 @@ authenticateStateData *r = data; auth_user_t *auth_user; basic_data *basic_auth; + auth_basic_queue_node *node,*tmpnode; int valid; char *t = NULL; debug(29, 5) ("authenticateBasicHandleReply: {%s}\n", reply ? reply : ""); @@ -301,12 +302,23 @@ if (reply && (strncasecmp(reply, "OK", 2) == 0)) auth_user->flags.credentials_ok = 1; else - auth_user->flags.credentials_ok = 2; + auth_user->flags.credentials_ok = 3; basic_auth->credentials_checkedtime=squid_curtime; valid = cbdataValid(r->data); cbdataUnlock(r->data); if (valid) r->handler(r->data, NULL); + node=basic_auth->auth_queue; + while (node) + { + tmpnode=node->next; + valid = cbdataValid(node->data); + cbdataUnlock(node->data); + if (valid) + node->handler(node->data, NULL); + xfree(node); + node=tmpnode; + } #if 0 if (valid) r->handler(r->data, reply); @@ -375,6 +387,7 @@ assert(temp!=NULL); temp->username=NULL; temp->passwd=NULL; + temp->auth_queue=NULL; return temp; } @@ -592,12 +605,33 @@ handler(data, NULL); return; } - r = xcalloc(1, sizeof(authenticateStateData)); - cbdataAdd(r, cbdataXfree, 0); - r->handler = handler; - cbdataLock(data); - r->data = data; - r->auth_user_request = auth_user_request; - snprintf(buf, 8192, "%s %s\n", basic_auth->username, basic_auth->passwd); - helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r); + /* check to see if the auth_user already has a request outstanding */ + if (auth_user_request->auth_user->flags.credentials_ok==2) + { + /* there is a request with the same credentials already being verified */ + auth_basic_queue_node *node; + node=xmalloc(sizeof(auth_basic_queue_node)); + assert(node); + /* save the details */ + node->next=basic_auth->auth_queue; + basic_auth->auth_queue=node; + node->auth_user_request=auth_user_request; + node->handler=handler; + node->data=data; + cbdataLock(data); + return; + } + else + { + r = xcalloc(1, sizeof(authenticateStateData)); + cbdataAdd(r, cbdataXfree, 0); + r->handler = handler; + cbdataLock(data); + r->data = data; + r->auth_user_request = auth_user_request; + /* mark the user as haveing verification in progress */ + auth_user_request->auth_user->flags.credentials_ok=2; + 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.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid/src/auth/basic/auth_basic.h 2 Jan 2001 10:57:02 -0000 1.1.2.4 +++ squid/src/auth/basic/auth_basic.h 3 Jan 2001 13:12:34 -0000 1.1.2.5 @@ -14,11 +14,21 @@ RH *handler; } authenticateStateData; +typedef struct _auth_basic_queue_node auth_basic_queue_node; + +/* queue of auth requests waiting for verification to occur */ +struct _auth_basic_queue_node { + auth_basic_queue_node *next; + auth_user_request_t * auth_user_request; + RH * handler; + void *data; +}; struct _basic_data { char *username; char *passwd; time_t credentials_checkedtime; + auth_basic_queue_node *auth_queue; }; /* configuration runtime data */ @@ -33,6 +43,7 @@ typedef struct _basic_data basic_data; + #if 0 struct _ntlm_helper_state_t { char *challenge; /* the challenge to use with this helper */