This is the patch (indent 1.9.1) and apply to squid-2.5 CVS. Changes: -support for bogus clients in authentication, forcing the use of some scheme for some clients with acls. -authenticateAuthSchemeConfigure() renamed to authenticateAuthSchemeActive(). -New authenticateAuthSchemeConfigure() function.
authentication example: acl basic_auth proxy_auth -b REQUIRED acl ntlm_auth proxy_auth -n REQUIRED acl ip1 src 10.10.10.10 acl ip2 src 10.10.10.11 http_access allow ip1 basic_auth http_access allow ip2 ntlm_auth ..then the basic auth is offered to ip1 and ntlm if offered to ip2 (in authenticateFixHeader()). Please check this and apply if it is OK or tell me how can I do this better, i thinks that it is necessary. Thanks! diff -Nru squid-2.5/src/acl.c squid-2.5-ws/src/acl.c --- squid-2.5/src/acl.c Mon May 12 04:24:37 2003 +++ squid-2.5-ws/src/acl.c Sun Sep 7 13:37:50 2003 @@ -628,11 +628,33 @@ } data = *current; Top = data->names; - if ((t = strtokFile())) { - debug(28, 5) ("aclParseUserList: First token is %s\n", t); + data->flags.schemeid = -1; + while ((t = strtokFile())) { + debug(28, 5) ("aclParseUserList: token is %s\n", t); if (strcmp("-i", t) == 0) { debug(28, 5) ("aclParseUserList: Going case-insensitive\n"); data->flags.case_insensitive = 1; + } else if (strcmp("-b", t) == 0) { + if (!authenticateAuthSchemeConfigured("basic")) { + debug(28, 5) ("aclParseUserList: -b switch ignored, basic auth not configured\n"); + continue; + } + debug(28, 5) ("aclParseUserList: using basic auth\n"); + data->flags.schemeid = authenticateAuthSchemeId("basic"); + } else if (strcmp("-n", t) == 0) { + if (!authenticateAuthSchemeConfigured("ntlm")) { + debug(28, 5) ("aclParseUserList: -n switch ignored, ntlm auth not configured\n"); + continue; + } + debug(28, 5) ("aclParseUserList: using ntlm auth\n"); + data->flags.schemeid = authenticateAuthSchemeId("ntlm"); + } else if (strcmp("-d", t) == 0) { + if (!authenticateAuthSchemeConfigured("digest")) { + debug(28, 5) ("aclParseUserList: -d switch ignored, digest auth not configured\n"); + continue; + } + debug(28, 5) ("aclParseUserList: using digest auth\n"); + data->flags.schemeid = authenticateAuthSchemeId("digest"); } else if (strcmp("REQUIRED", t) == 0) { debug(28, 5) ("aclParseUserList: REQUIRED-type enabled\n"); data->flags.required = 1; @@ -644,15 +666,9 @@ } debug(28, 3) ("aclParseUserList: Case-insensitive-switch is %d\n", data->flags.case_insensitive); - /* we might inherit from a previous declaration */ - - debug(28, 4) ("aclParseUserList: parsing user list\n"); - while ((t = strtokFile())) { - debug(28, 6) ("aclParseUserList: Got token: %s\n", t); - if (data->flags.case_insensitive) - Tolower(t); - Top = splay_insert(xstrdup(t), Top, (SPLAYCMP *) strcmp); - } + debug(28, 3) ("aclParseUserList: scheme ID is %d\n", data->flags.schemeid); + /* we might inherit from a previous declaration, (?, [EMAIL PROTECTED]) */ + debug(28, 4) ("aclParseUserList: user list parsed \n"); data->names = Top; } @@ -1695,6 +1711,7 @@ int answer; checklist->current_acl = list->acl; AclMatchedName = list->acl->name; + AclMatched = list->acl; debug(28, 3) ("aclMatchAclList: checking %s%s\n", list->op ? null_string : "!", list->acl->name); answer = aclMatchAcl(list->acl, checklist); diff -Nru squid-2.5/src/authenticate.c squid-2.5-ws/src/authenticate.c --- squid-2.5/src/authenticate.c Sun May 18 18:49:19 2003 +++ squid-2.5-ws/src/authenticate.c Sun Sep 7 18:53:25 2003 @@ -56,9 +56,8 @@ /* Generic Functions */ - static int -authenticateAuthSchemeConfigured(const char *proxy_auth) +authenticateAuthSchemeActive(const char *proxy_auth) { authScheme *scheme; int i; @@ -71,6 +70,7 @@ return 0; } + int authenticateAuthSchemeId(const char *typestr) { @@ -90,7 +90,7 @@ assert(proxy_auth != NULL); assert(auth_user_request != NULL); /* we need this created for us. */ debug(29, 9) ("authenticateDecodeAuth: header = '%s'\n", proxy_auth); - if (authenticateAuthSchemeConfigured(proxy_auth)) { + if (authenticateAuthSchemeActive(proxy_auth)) { /* we're configured to use this scheme - but is it active ? */ if ((i = authenticateAuthSchemeId(proxy_auth)) != -1) { authscheme_list[i].decodeauth(auth_user_request, proxy_auth); @@ -733,14 +733,26 @@ else { int i; authScheme *scheme; - /* call each configured & running authscheme */ - for (i = 0; i < Config.authConfig.n_configured; i++) { - scheme = Config.authConfig.schemes + i; - if (authscheme_list[scheme->Id].Active()) - authscheme_list[scheme->Id].authFixHeader(NULL, rep, type, - request); + acl_user_data *user_data; + + user_data = AclMatched->data; + if ((AclMatched->type == ACL_PROXY_AUTH || AclMatched->type == ACL_PROXY_AUTH) && + user_data->flags.schemeid >= 0) { + if (authscheme_list[user_data->flags.schemeid].Active()) + authscheme_list[user_data->flags.schemeid].authFixHeader(NULL, + rep, type, request); else - debug(29, 4) ("authenticateFixHeader: Configured scheme %s not Active\n", scheme->typestr); + debug(29, 4) ("authenticateFixHeader: Configured scheme %d not Active\n", user_data->flags.schemeid); + } else { + /* call each configured & running authscheme */ + for (i = 0; i < Config.authConfig.n_configured; i++) { + scheme = Config.authConfig.schemes + i; + if (authscheme_list[scheme->Id].Active()) + authscheme_list[scheme->Id].authFixHeader(NULL, rep, type, + request); + else + debug(29, 4) ("authenticateFixHeader: Configured scheme %s not Active\n", scheme->typestr); + } } } } @@ -754,7 +766,6 @@ if (auth_user_request != NULL) auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE; } - /* call the active auth module and allow it to add a trailer to the request */ void authenticateAddTrailer(HttpReply * rep, auth_user_request_t * auth_user_request, request_t * request, int accelerated) @@ -763,7 +774,6 @@ && (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer)) authscheme_list[auth_user_request->auth_user->auth_module - 1].AddTrailer(auth_user_request, rep, accelerated); } - void authenticateAuthUserLock(auth_user_t * auth_user) { @@ -771,9 +781,8 @@ assert(auth_user != NULL); auth_user->references++; debug(29, 9) ("authenticateAuthUserLock auth_user '%p' now at '%ld'.\n", auth_user, (long int) auth_user->references); -} +} void -void authenticateAuthUserUnlock(auth_user_t * auth_user) { debug(29, 9) ("authenticateAuthUserUnlock auth_user '%p'.\n", auth_user); @@ -795,9 +804,8 @@ assert(auth_user_request != NULL); auth_user_request->references++; debug(29, 9) ("authenticateAuthUserRequestLock auth_user request '%p' now at '%ld'.\n", auth_user_request, (long int) auth_user_request->references); -} +} void -void authenticateAuthUserRequestUnlock(auth_user_request_t * auth_user_request) { debug(29, 9) ("authenticateAuthUserRequestUnlock auth_user request '%p'.\n", auth_user_request); @@ -820,15 +828,13 @@ { assert(auth_user != NULL); return auth_user->references; -} - -/* - * Combine two user structs. ONLY to be called from within a scheme - * module. The scheme module is responsible for ensuring that the - * two users _can_ be merged without invalidating all the request - * scheme data. the scheme is also responsible for merging any user - * related scheme data itself. - */ +} /* + * Combine two user structs. ONLY to be called from within a scheme + * module. The scheme module is responsible for ensuring that the + * two users _can_ be merged without invalidating all the request + * scheme data. the scheme is also responsible for merging any user + * related scheme data itself. + */ void authenticateAuthUserMerge(auth_user_t * from, auth_user_t * to) { @@ -873,8 +879,7 @@ * structure */ memFree(u->usernamehash, MEM_AUTH_USER_HASH); } - /* remove any outstanding requests */ - link = u->requests.head; + /* remove any outstanding requests */ link = u->requests.head; while (link) { debug(29, 5) ("authenticateFreeProxyAuthUser: removing request entry '%p'\n", link->data); auth_user_request = link->data; @@ -906,7 +911,6 @@ eventAdd("User Cache Maintenance", authenticateProxyUserCacheCleanup, NULL, Config.authenticateGCInterval, 1); } } - void authenticateProxyUserCacheCleanup(void *datanotused) { @@ -960,12 +964,9 @@ debug(29, 5) ("authenticateUserCacheRestat: Clearing cache ACL results for user: %s\n", username); aclCacheMatchFlush(&auth_user->proxy_match_cache); } - -} - -/* - * called to add another auth scheme module - */ +} /* + * called to add another auth scheme module + */ void authSchemeAdd(const char *type, AUTHSSETUP * setup) { @@ -974,8 +975,7 @@ /* find the number of currently known authscheme types */ for (i = 0; authscheme_list && authscheme_list[i].typestr; i++) { assert(strcmp(authscheme_list[i].typestr, type) != 0); - } - /* add the new type */ + } /* add the new type */ authscheme_list = xrealloc(authscheme_list, (i + 2) * sizeof(authscheme_entry_t)); memset(&authscheme_list[i], 0, sizeof(authscheme_entry_t)); memset(&authscheme_list[i + 1], 0, sizeof(authscheme_entry_t)); @@ -998,4 +998,16 @@ auth_user->usernamehash = usernamehash; /* lock for presence in the cache */ authenticateAuthUserLock(auth_user); +} int +authenticateAuthSchemeConfigured(const char *proxy_auth) +{ + authScheme *scheme; + int i; + for (i = 0; i < Config.authConfig.n_configured; i++) { + scheme = Config.authConfig.schemes + i; + if ((strncasecmp(proxy_auth, scheme->typestr, strlen(scheme->typestr)) == 0) && + (authscheme_list[scheme->Id].configured())) + return 1; + } + return 0; } diff -Nru squid-2.5/src/cf.data.pre squid-2.5-ws/src/cf.data.pre --- squid-2.5/src/cf.data.pre Tue Sep 2 04:49:32 2003 +++ squid-2.5-ws/src/cf.data.pre Sat Sep 6 23:39:51 2003 @@ -1971,10 +1971,14 @@ # cache_peer_access mycache.mydomain.net allow asexample # cache_peer_access mycache_mydomain.net deny all - acl aclname proxy_auth username ... + acl aclname proxy_auth [-i] [-b | -n | -d ] username ... acl aclname proxy_auth_regex [-i] pattern ... # list of valid usernames # use REQUIRED to accept any valid username. + # -i: case-insensitive + # -b: use basic authentication + # -n: use NTLM authentication + # -d: use digest authentication # # NOTE: when a Proxy-Authentication header is sent but it is not # needed during ACL checking the username is NOT logged @@ -1983,6 +1987,9 @@ # NOTE: proxy_auth requires a EXTERNAL authentication program # to check username/password combinations (see # auth_param directive). + # + # NOTE: If -b, -n or -d is not especified, the three schemes are + # offered to the client. # # WARNING: proxy_auth can't be used in a transparent proxy. It # collides with any authentication done by origin servers. It may diff -Nru squid-2.5/src/globals.h squid-2.5-ws/src/globals.h --- squid-2.5/src/globals.h Mon Jan 13 20:01:13 2003 +++ squid-2.5-ws/src/globals.h Sat Sep 6 23:30:09 2003 @@ -47,6 +47,7 @@ extern char ThisCache2[SQUIDHOSTNAMELEN << 1]; extern char config_input_line[BUFSIZ]; extern const char *AclMatchedName; /* NULL */ +extern acl *AclMatched; /* NULL */ extern const char *DefaultConfigFile; /* DEFAULT_CONFIG_FILE */ extern const char *RequestMethodStr[]; extern const char *ProtocolStr[]; diff -Nru squid-2.5/src/protos.h squid-2.5-ws/src/protos.h --- squid-2.5/src/protos.h Sun Aug 10 18:04:47 2003 +++ squid-2.5-ws/src/protos.h Sun Sep 7 00:47:45 2003 @@ -739,6 +739,7 @@ extern void authSchemeSetup(void); /* authenticate.c */ +extern int authenticateAuthSchemeConfigured(const char *proxy_auth); extern void authenticateAuthUserMerge(auth_user_t *, auth_user_t *); extern auth_user_t *authenticateAuthUserNew(const char *); extern int authenticateAuthSchemeId(const char *typestr); diff -Nru squid-2.5/src/structs.h squid-2.5-ws/src/structs.h --- squid-2.5/src/structs.h Wed Aug 6 10:49:03 2003 +++ squid-2.5-ws/src/structs.h Sun Sep 7 18:52:55 2003 @@ -53,6 +53,7 @@ struct { unsigned int case_insensitive:1; unsigned int required:1; + short int schemeid; } flags; };