--------------------- PatchSet 2664 Date: 2001/07/25 10:25:23 Author: rbcollins Branch: ntlm Tag: (none) Log: Refactor MatchProxyAuth into an authenticate component and an authorise component Members: src/acl.c:1.1.1.3.12.57->1.1.1.3.12.58 src/enums.h:1.1.1.3.12.27->1.1.1.3.12.28 Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.3.12.57 retrieving revision 1.1.1.3.12.58 diff -u -r1.1.1.3.12.57 -r1.1.1.3.12.58 --- squid/src/acl.c 20 Jul 2001 13:25:41 -0000 1.1.1.3.12.57 +++ squid/src/acl.c 25 Jul 2001 10:25:23 -0000 1.1.1.3.12.58 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.3.12.57 2001/07/20 13:25:41 rbcollins Exp $ + * $Id: acl.c,v 1.1.1.3.12.58 2001/07/25 10:25:23 rbcollins Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1179,59 +1179,60 @@ */ #include "auth/ntlm/auth_ntlm.h" -/* aclMatchProxyAuth can return four exit codes: - * 0 : Authenticated OK, Authorisation for this ACL failed. - * 1 : Authenticated OK, Authorisation OK. - * -1 : send data to an external authenticator - * -2 : send data to the client - */ -static int -aclMatchProxyAuth(void *data, http_hdr_type headertype, - auth_user_request_t * auth_user_request, aclCheck_t * checklist, - squid_acl acltype) +/* returns one of + * AUTH_ACL_CHALLENGE, + * AUTH_ACL_HELPER, + * AUTH_ACL_CANNOT_AUTHENTICATE, + * AUTH_AUTHENTICATED + * + * How to use: In your proxy-auth dependent acl code, use the following + * construct: + * int rv; + * if ((rv = AuthenticateAuthenticate()) != AUTH_AUTHENTICATED) + * return rv; + * + * when this code is reached, the request/connection is authenticated. + * + * if you have non-acl code, but want to force authentication, you need a + * callback mechanism like the acl testing routines that will send a 40[1|7] to + * the client when rv==AUTH_ACL_CHALLENGE, and will communicate with + * the authenticateStart routine for rv==AUTH_ACL_HELPER + */ +static auth_acl_t +AuthenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t *request, ConnStateData *conn) { - /* checklist is used to register user name when identified, nothing else */ - const char *proxy_auth; - /* consistent parameters ? */ - assert(auth_user_request == checklist->auth_user_request); - - /* General program flow in proxy_auth acls - * 1. Consistency checks: are we getting sensible data - * 2. Call the authenticate* functions to establish a authenticated user - * 4. look up the username in acltype (and cache the result against the - * username - */ - + const char * proxy_auth; assert(headertype != 0); - proxy_auth = httpHeaderGetStr(&checklist->request->header, headertype); + proxy_auth = httpHeaderGetStr(&request->header, headertype); - if (checklist->conn == NULL) { + if (conn == NULL) { debug(28, 1) ("aclMatchProxyAuth: no connection data, cannot process authentication\n"); - /* + /* * deny access: clientreadrequest requires conn data, and it is always * compiled in so we should have it too. */ - return 0; + return AUTH_ACL_CANNOT_AUTHENTICATE; } + /* * a note on proxy_auth logix here: * proxy_auth==NULL -> unauthenticated request || already authenticated connection * so we test for an authenticated connection when we recieve no authentication * header. */ - if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(auth_user_request ? auth_user_request : checklist->conn->auth_user_request))) - || (checklist->conn->auth_type == AUTH_BROKEN)) { - /* no header or authentication failed/got corrupted - restart */ - checklist->conn->auth_type = AUTH_UNKNOWN; - debug(28, 4) ("aclMatchProxyAuth: broken auth or no proxy_auth header. Requesting auth header.\n"); - /* something wrong with the AUTH credentials. Force a new attempt */ - checklist->auth_user_request = NULL; - checklist->conn->auth_user_request = NULL; - if (auth_user_request) { - /* unlock the ACL lock */ - authenticateAuthUserRequestUnlock(auth_user_request); - } - return -2; + if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(*auth_user_request ? *auth_user_request : conn->auth_user_request))) + || (conn->auth_type == AUTH_BROKEN)) { + /* no header or authentication failed/got corrupted - restart */ + conn->auth_type = AUTH_UNKNOWN; + debug(28, 4) ("aclMatchProxyAuth: broken auth or no proxy_auth header. Requesting auth header.\n"); + /* something wrong with the AUTH credentials. Force a new attempt */ + conn->auth_user_request = NULL; + if (*auth_user_request) { + /* unlock the ACL lock */ + authenticateAuthUserRequestUnlock(*auth_user_request); + auth_user_request = NULL; + } + return AUTH_ACL_CHALLENGE; } /* @@ -1239,110 +1240,146 @@ * FIXME: This breaks the abstraction model. Even if it is just for bug hunting * It's really really ugly. */ - if (proxy_auth && checklist->conn->auth_user_request && - authenticateUserAuthenticated(checklist->conn->auth_user_request) - && strcmp(proxy_auth, ((ntlm_request_t *)(checklist->conn->auth_user_request->scheme_data))->ntlmauthenticate)) { - debug(28,1) ("aclMatchProxyAuth: DUPLICATE AUTH - authentication header on already authenticated connection!. Current user '%s' proxy_auth %s, authenticate request %s\n", authenticateUserRequestUsername(checklist->conn->auth_user_request), proxy_auth, ((ntlm_request_t *)(checklist->conn->auth_user_request->scheme_data))->ntlmauthenticate); - /* remove this request struct - the link is already authed and it can't be to + if (proxy_auth && conn->auth_user_request && + authenticateUserAuthenticated(conn->auth_user_request) + && strcmp(proxy_auth, ((ntlm_request_t *)(conn->auth_user_request->scheme_data))->ntlmauthenticate)) { + debug(28,1) ("aclMatchProxyAuth: DUPLICATE AUTH - authentication header on already authenticated connection!. Current user '%s' proxy_auth %s, authenticate request %s\n", authenticateUserRequestUsername(conn->auth_user_request), proxy_auth, ((ntlm_request_t *)(conn->auth_user_request->scheme_data))->ntlmauthenticate); + /* remove this request struct - the link is already authed and it can't be to * reauth. - */ - - /* This should _only_ ever occur on the first pass through aclMatchProxyAuth */ - assert(auth_user_request == NULL); - /* unlock the conn lock on the auth_user_request */ - authenticateAuthUserRequestUnlock(checklist->conn->auth_user_request); - /* mark the conn as non-authed. */ - checklist->conn->auth_user_request=NULL; - /* Set the connection auth type */ - checklist->conn->auth_type = AUTH_UNKNOWN; - + */ + + /* This should _only_ ever occur on the first pass through aclMatchProxyAuth */ + assert(*auth_user_request == NULL); + /* unlock the conn lock on the auth_user_request */ + authenticateAuthUserRequestUnlock(conn->auth_user_request); + /* mark the conn as non-authed. */ + conn->auth_user_request=NULL; + /* Set the connection auth type */ + conn->auth_type = AUTH_UNKNOWN; } /* 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, 9) ("aclMatchProxyAuth: header %s.\n", proxy_auth); - if (auth_user_request == NULL) { - debug(28, 9) ("aclMatchProxyAuth: This is a new request on FD:%d\n", - checklist->conn->fd); - if ((!checklist->request->auth_user_request) - && (checklist->conn->auth_type == AUTH_UNKNOWN)) { - /* beginning of a new request check */ - debug(28, 4) ("aclMatchProxyAuth: no connection authentication type\n"); - if (!authenticateValidateUser(auth_user_request = - authenticateGetAuthUser(proxy_auth))) { - /* the decode might have left a username for logging, or a message to - * the user */ - if (authenticateUserRequestUsername(auth_user_request)) { - /* lock the user for the request structure link */ - authenticateAuthUserRequestLock(auth_user_request); - checklist->request->auth_user_request = auth_user_request; - /* unlock the ACL reference. */ - authenticateAuthUserRequestUnlock(auth_user_request); - } - return -2; - } - /* the user_request comes prelocked for the caller to GetAuthUser (us) */ - } else if (checklist->request->auth_user_request) { - auth_user_request = checklist->request->auth_user_request; - /* lock the user request for this ACL processing */ - authenticateAuthUserRequestLock(auth_user_request); - } else { - if (checklist->conn->auth_user_request != NULL) { - auth_user_request = checklist->conn->auth_user_request; - /* lock the user request for this ACL processing */ - authenticateAuthUserRequestLock(auth_user_request); - } else { - /* failed connection based authentication */ - debug(28, 4) ("aclMatchProxyAuth: Auth user request %d conn-auth user request %d conn type %d authentication failed.\n", - auth_user_request, checklist->conn->auth_user_request, - checklist->conn->auth_type); - authenticateAuthUserRequestUnlock(checklist->auth_user_request); - checklist->auth_user_request=NULL; - return -2; - } - } + if (*auth_user_request == NULL) { + debug(28, 9) ("aclMatchProxyAuth: This is a new request on FD:%d\n", + conn->fd); + if ((!request->auth_user_request) + && (conn->auth_type == AUTH_UNKNOWN)) { + /* beginning of a new request check */ + debug(28, 4) ("aclMatchProxyAuth: no connection authentication type\n"); + if (!authenticateValidateUser(*auth_user_request = + authenticateGetAuthUser(proxy_auth))) { + /* the decode might have left a username for logging, or a message to + * the user */ + if (authenticateUserRequestUsername(*auth_user_request)) { + /* lock the user for the request structure link */ + authenticateAuthUserRequestLock(*auth_user_request); + request->auth_user_request = *auth_user_request; + /* unlock the ACL reference. */ + authenticateAuthUserRequestUnlock(*auth_user_request); + } + return AUTH_ACL_CHALLENGE; + } + /* the user_request comes prelocked for the caller to GetAuthUser (us) */ + } else if (request->auth_user_request) { + *auth_user_request = request->auth_user_request; + /* lock the user request for this ACL processing */ + authenticateAuthUserRequestLock(*auth_user_request); + } else { + if (conn->auth_user_request != NULL) { + *auth_user_request = conn->auth_user_request; + /* lock the user request for this ACL processing */ + authenticateAuthUserRequestLock(*auth_user_request); + } else { + /* failed connection based authentication */ + debug(28, 4) ("aclMatchProxyAuth: Auth user request %d conn-auth user request %d conn type %d authentication failed.\n", + *auth_user_request, conn->auth_user_request, conn->auth_type); + authenticateAuthUserRequestUnlock(*auth_user_request); + *auth_user_request=NULL; + return AUTH_ACL_CHALLENGE; + } + } + } + + if (!authenticateUserAuthenticated(*auth_user_request)) { + /* User not logged in. Log them in */ + authenticateAuthenticateUser(*auth_user_request, request, + conn, headertype); + switch (authenticateDirection(*auth_user_request)) { + case 1: + /* this ACL check is finished. Unlock. */ + authenticateAuthUserRequestUnlock(*auth_user_request); + return AUTH_ACL_CHALLENGE; + case -1: + /* we are partway through authentication within squid, + * the *auth_user_request variables stores the auth_user_request + * for the callback to here - Do not Unlock */ + return AUTH_ACL_HELPER; + case -2: + /* this ACL check is finished. Unlock. */ + authenticateAuthUserRequestUnlock(*auth_user_request); + return AUTH_ACL_CHALLENGE; + } + /* on 0 the authentication is finished - fallthrough */ + /* See of user authentication failed for some reason */ + if (!authenticateUserAuthenticated(*auth_user_request)) { + if ((authenticateUserRequestUsername(*auth_user_request))) { + if (!request->auth_user_request) { + /* lock the user for the request structure link */ + authenticateAuthUserRequestLock(*auth_user_request); + request->auth_user_request = *auth_user_request; + } + } + /* this ACL check is finished. Unlock. */ + authenticateAuthUserRequestUnlock(*auth_user_request); + return AUTH_ACL_CHALLENGE; + } } + + return AUTH_AUTHENTICATED; +} + +/* aclMatchProxyAuth can return four exit codes: + * 0 : Authenticated OK, Authorisation for this ACL failed. + * 1 : Authenticated OK, Authorisation OK. + * -1 : send data to an external authenticator + * -2 : send data to the client + */ +static int +aclMatchProxyAuth(void *data, http_hdr_type headertype, + 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; + int rv; + /* consistent parameters ? */ + assert(auth_user_request == checklist->auth_user_request); + + /* General program flow in proxy_auth acls + * 1. Consistency checks: are we getting sensible data + * 2. Call the authenticate* functions to establish a authenticated user + * 4. look up the username in acltype (and cache the result against the + * username + */ + + if ((rv = AuthenticateAuthenticate(&checklist->auth_user_request, headertype, checklist->request, checklist->conn)) != AUTH_AUTHENTICATED) + return rv; + + + proxy_auth = httpHeaderGetStr(&checklist->request->header, headertype); + + /* get the auth_user_request */ + auth_user_request = checklist->auth_user_request; /* Clear the reference in the checklist */ checklist->auth_user_request = NULL; - if (!authenticateUserAuthenticated(auth_user_request)) { - /* User not logged in. Log them in */ - authenticateAuthUserRequestSetIp(auth_user_request, + + /* This needs to move into a new ACL in some way + 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. */ - 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_request = auth_user_request; - /* we will be called back here. Do not Unlock */ - return -1; - case -2: - /* this ACL check is finished. Unlock. */ - authenticateAuthUserRequestUnlock(auth_user_request); - return -2; - } /* on 0 the authentication is finished - fallthrough */ - /* See of user authentication failed for some reason */ - if (!authenticateUserAuthenticated(auth_user_request)) { - if ((!checklist->rfc931[0]) && - (authenticateUserRequestUsername(auth_user_request))) { - 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; - } - } - /* this ACL check is finished. Unlock. */ - authenticateAuthUserRequestUnlock(auth_user_request); - return -2; + */ - } - } - /* User authenticated ok */ assert(authenticateUserAuthenticated(auth_user_request)); /* copy username to request for logging on client-side */ Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.1.1.3.12.27 retrieving revision 1.1.1.3.12.28 diff -u -r1.1.1.3.12.27 -r1.1.1.3.12.28 --- squid/src/enums.h 18 May 2001 10:01:17 -0000 1.1.1.3.12.27 +++ squid/src/enums.h 25 Jul 2001 10:25:23 -0000 1.1.1.3.12.28 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.1.1.3.12.27 2001/05/18 10:01:17 rbcollins Exp $ + * $Id: enums.h,v 1.1.1.3.12.28 2001/07/25 10:25:23 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -506,6 +506,13 @@ } allow_t; typedef enum { + AUTH_ACL_CHALLENGE = -2, + AUTH_ACL_HELPER = -1, + AUTH_ACL_CANNOT_AUTHENTICATE = 0, + AUTH_AUTHENTICATED = 1, +} auth_acl_t; + +typedef enum { AUTH_UNKNOWN, /* default */ AUTH_BASIC, AUTH_NTLM,