diff -Nru old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/Makefile.in new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/Makefile.in --- old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/Makefile.in Thu Jan 1 01:00:00 1970 +++ new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/Makefile.in Fri Oct 5 11:40:33 2001 @@ -0,0 +1,81 @@ + +OBJS = group_ldap_auth.o +LIBS = -lldap -llber +LDAP_EXE = group_ldap_auth + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +exec_suffix = @exec_suffix@ +cgi_suffix = @cgi_suffix@ +top_srcdir = @top_srcdir@ +bindir = @bindir@ +libexecdir = @libexecdir@ +sysconfdir = @sysconfdir@ +localstatedir = @localstatedir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +MAKEDEPEND = @MAKEDEPEND@ +INSTALL = @INSTALL@ +INSTALL_BIN = @INSTALL_PROGRAM@ +INSTALL_FILE = @INSTALL_DATA@ +INSTALL_SUID = @INSTALL_PROGRAM@ -o root -m 4755 +RANLIB = @RANLIB@ +LN_S = @LN_S@ +PERL = @PERL@ +CRYPTLIB = @CRYPTLIB@ +REGEXLIB = @REGEXLIB@ +PTHREADLIB = @PTHREADLIB@ +MALLOCLIB = @LIB_MALLOC@ +AC_CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +XTRA_LIBS = @XTRA_LIBS@ +XTRA_OBJS = @XTRA_OBJS@ +MV = @MV@ +RM = @RM@ +SHELL = /bin/sh + + +all: $(LDAP_EXE) + +$(LDAP_EXE): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +install-mkdirs: + -@if test ! -d $(prefix); then \ + echo "mkdir $(prefix)"; \ + mkdir $(prefix); \ + fi + -@if test ! -d $(libexecdir); then \ + echo "mkdir $(libexecdir)"; \ + mkdir $(libexecdir); \ + fi + +# Michael Lupp wants to know about additions +# to the install target. +install: all install-mkdirs + @for f in $(LDAP_EXE); do \ + if test -f $(libexecdir)/$$f; then \ + echo $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \ + $(MV) $(libexecdir)/$$f $(libexecdir)/-$$f; \ + fi; \ + echo $(INSTALL_BIN) $$f $(libexecdir); \ + $(INSTALL_BIN) $$f $(libexecdir); \ + if test -f $(libexecdir)/-$$f; then \ + echo $(RM) -f $(libexecdir)/-$$f; \ + $(RM) -f $(libexecdir)/-$$f; \ + fi; \ + done + +clean: + -$(RM) -f $(OBJS) + -$(RM) -f $(LDAP_EXE) + +distclean: clean + -$(RM) -f Makefile + + + + + diff -Nru old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/README new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/README --- old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/README Thu Jan 1 01:00:00 1970 +++ new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/README Fri Oct 5 11:40:33 2001 @@ -0,0 +1,153 @@ +The group_ldap_auth module performs user and group authentication to an ldap +server. It supports static and dynamic groups. + + +BUILD INSTRUCTIONS +------------------ + +This module requires the openldap libraries (http://www.openldap.org) to build. +Once they have been installed, build with: + + % make + % make install + + +USAGE +----- + +This module does not use the auth_module communication module, and requires +squid 2.3-STABLE3-ldap_auth. The diff file you used to get his module patched +2.3-STABLE3 source tree to 2.3-STABLE3-ldap_auth. If you received this module +through some other means, go to http://www.fatgut.org/squid/group_ldap_auth/ +to get the full diff. + +The search base, ldap server, and (optionally) the ldap port (default is 389) +are specified along with the path to the module with the ldap_auth_program +directive in squid.conf. example: + + ldap_auth_program /usr/local/squid/bin/group_ldap_auth o=siroe.com \ + ldap.siroe.com 389 + +To tell squid to use ldap_auth, use the ldap_auth acl directive: + + acl aclname ldap_auth (((static | dynamic) group) | username) ... + +Use REQUIRED to accept any valid username. A list of groups and/or users can +be specified here. The group must be prefaced with either static or dynamic to +define the group type. Group names with spaces in them should be enclosed by +single quotes ("'"). Examples: + + acl user_acl ldap_auth REQUIRED + - requires the user to be in the ldap db, and the password to be valid + + acl users_acl ldap_auth joed janed toc + - requires the user to be one of {joed, janed, toc}, the user to be + in the ldap db, and the password to be valid + + acl group_acl ldap_auth static 'product managers' dynamic uid=j* + - requires the user to be a member of the static product managers group + or a member of the dynamic uid=j* group (all user id's starting with j). + The user must also exist in the ldap db and have a valid password. + +Users and groups can be mixed in an acl statement, but the special REQUIRED +parameter cannot be mixed. Examples: + + acl users_groups_acl ldap_auth frank john joe static 'useful managers' + *VALID* + + acl invalid_acl ldap_auth REQUIRED frank john joe + *INVALID* + + +There are other configuration options that affect ldap_auth: + +ldap_auth_children + + The number of ldap authenticator processes to spawn (default 5). + If you start too few Squid will have to wait for them to process + a backlog of user/password verifications, slowing it down. When + password verifications are done via a slow network or you have + ldap_auth acls with several groups you are likely to need lots of + ldap authenticator processes. + +ldap_auth_cache_size + + The size of the ldap username/password/group cache in entries (default 64). + +ldap_auth_cache_ttl + + The number of seconds a checked ldap username/password/group combination + remains cached (default 3600). If a wrong password is given for a cached + user, the user gets removed from the username/password/group cache forcing + a revalidation. + +ldap_auth_cache_ip_ttl + + With this option you control how long a ldap authentication + will be bound to a specific IP address. If a request using + the same user name is received during this time then access + will be denied and both users are required to reauthenticate + them selves. The idea behind this is to make it annoying + for people to share their password to their friends, but + yet allow a dialup user to reconnect on a different dialup + port. + + The default is 0 to disable the check. Recommended value + if you have dialup users are no more than 60 (seconds). If + all your users are stationary then higher values may be + used. + + +HOW IT WORKS +------------ + +The module communicates with squid though the squid helper system: squid writes data +to the modules stdin, the module writes results back to its stdout. The other auth +modules use a simple communications protocol: squid writes "username password" to the +module, the module writes back "OK" or "ERR". For group authentication to work, more +information needs to be passed between squid and the module. So the ldap_auth acl +directive was added to complement the proxy_auth directive. + +When communicating with this module when processing the ldap_auth directive, squid +writes messages of the form: + + username password groupcount grouptype #groupname# grouptype #groupname# ... + +where groupcount specifies the number of groups that follow, grouptype is either s +(for static) or d (for dynamic), and groupnames are bracketed by #'s. Example: + + jack SeCrEt 3 s #poor password choosers# s #localusers# d #ou=people# + +or + + jack SeCrEt 0 + +if there are no groups to be checked. + +The module reads this info, and first verifies the user is in the database. If this +fails, a failure flag is returned to squid. If this lookup succeeds, the module +checks the membership of each group until the user is found or all groups have been +tried. Static groups in the directory can have an objectclass of either groupOfNames +or groupOfUniqueNames, and the member uids must be uniqueMember attributes of the +group. If the user is not found in any of the groups, a failure flag is returned. +If the user is found among the groups, the module attempts to bind to the directory +as that user with the supplied password. If that step succeeds, a pass flag is +returned to squid along with the group that the user was found in (if any). Upon +failure, the module returns: + + f + +upon success, the module returns: + + p groupname + +or, if no groups were provided by squid and the user authenticated okay: + + p + + +FOR MORE INFO +------------- + +Go to http://www.fatgut.org/squid/group_ldap_auth/, or email +tocrawle@users.sourceforge.net. diff -Nru old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/group_ldap_auth.c new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/group_ldap_auth.c --- old/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/group_ldap_auth.c Thu Jan 1 01:00:00 1970 +++ new/squid-2.4.STABLE2/auth_modules/GROUP_LDAP/group_ldap_auth.c Fri Oct 5 11:40:33 2001 @@ -0,0 +1,317 @@ +/* + + group_ldap_auth: user and group authentication via ldap for squid proxy server + + Author: Tobias Crawley + tocrawle@users.sourceforge.net + http://www.fatgut.org/squid/group_ldap_auth/ + + Based on squid_ldap_auth.c by: + Glen Newton + glen.newton@nrc.ca + Advanced Services + CISTI + National Research Council + + Usage: group_ldap_auth [] + + Dependencies: You need to get the OpenLDAP libraries + from http://www.openldap.org + + License: group_ldap_auth is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, + or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#define USE_LOG 1 + +struct _grouplist +{ + char type; + char *group; + struct _grouplist *next; +}; + +typedef struct _grouplist grouplist; + +int checkLDAP(LDAP * ld, char *userid, char *password, grouplist * glist, + char **group, char *searchBase); + +#ifdef USE_LOG +FILE *logfd = NULL; +#endif + +int +main(int argc, char **argv) +{ + char buf[256]; + char *user, *passwd, *group, *tmpstrptr, *p; + char *ldapServer; + int groupcount = 0; + grouplist *glist = NULL, *currgroup = NULL; + int ldapPort = LDAP_PORT; + LDAP *ld; + char *searchBase; + int err = 0; + int i; +#ifdef USE_LOG + char logfile[256]; +#endif + setbuf(stdout, NULL); + + if (argc < 3 || argc > 4) { + fprintf(stderr, + "Usage: squid_ldap_auth search_base ldap_server_name [ldap_server_port]\n"); + exit(1); + } +#ifdef USE_LOG + /* setup a log file */ + sprintf(logfile, "/tmp/squid_ldap_auth_log.%d", (int) getpid()); + logfd = fopen(logfile, "w"); +#endif + + searchBase = (char *) argv[1]; + ldapServer = (char *) argv[2]; + if (argc == 4) { + ldapPort = atoi((char *) argv[3]); + } + + if ((ld = ldap_open(ldapServer, ldapPort)) == NULL) { + fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n", + ldapServer, ldapPort); + exit(1); + } + ldap_simple_bind_s(ld, "", ""); +#ifdef USE_LOG + fprintf(logfd, "bound to %s:%d\n", ldapServer, ldapPort); +#endif + + while (fgets(buf, 256, stdin) != NULL) { +#ifdef USE_LOG + fprintf(logfd, "received %s", buf); +#endif + + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; /* strip \n */ + + if ((user = strtok(buf, " ")) == NULL) { + printf("f\n"); + continue; + } + if ((passwd = strtok(NULL, " ")) == NULL) { + printf("f\n"); + continue; + } + if ((tmpstrptr = strtok(NULL, " ")) == NULL) { + printf("f\n"); + continue; + } + groupcount = atoi(tmpstrptr); + for (i = 0; i < groupcount; i++) { + if (!glist) { + currgroup = glist = (grouplist *) malloc(sizeof(grouplist)); + } else { + currgroup->next = (grouplist *) malloc(sizeof(grouplist)); + currgroup = currgroup->next; + } + currgroup->next = NULL; + + if ((tmpstrptr = strtok(NULL, " ")) == NULL) { + printf("f\n"); + continue; + } + currgroup->type = tmpstrptr[0]; + + if ((currgroup->group = strtok(NULL, "#\0")) == NULL) { + printf("f\n"); + continue; + } + } + group = NULL; + err = checkLDAP(ld, user, passwd, glist, &group, searchBase); +#ifdef USE_LOG + fprintf(logfd, "checkLdap returned %d %s\n", err, + (group == NULL) ? "" : group); +#endif + + if (err == 0) { + if (group == NULL) { + printf("p\n"); + } else { + printf("p %s\n", group); + } + } else { + printf("f\n"); + } + + /* free the glist */ + while (glist != NULL) { + currgroup = glist->next; + free(glist); + glist = currgroup; + } + glist = currgroup = NULL; + + ldap_simple_bind_s(ld, "", ""); +#ifdef USE_LOG + fflush(logfd); +#endif + } +#ifdef USE_LOG + fclose(logfd); +#endif + ldap_unbind(ld); +} + + + +int +checkLDAP(LDAP * ld, char *userid, char *password, grouplist * glist, + char **group, char *searchBase) +{ + char filter[1024]; + char *attrs[2]; + char *userdn; + LDAPMessage *result; + int entryCount = 0; + char **vals, **prevals; + char found = 0; + char *resultdn; + + /* verify user exists */ + sprintf(filter, "(uid=%s)", userid); +#ifdef USE_LOG + fprintf(logfd, "searching for user with filter %s\n", filter); +#endif + attrs[0] = NULL; + if (ldap_search_s(ld, searchBase, LDAP_SCOPE_SUBTREE, filter, attrs, 0, + &result) != LDAP_SUCCESS) { + return 1; + } + + /* get the user's dn */ + if ((result = ldap_first_entry(ld, result)) == NULL) { + return 2; + } + if ((userdn = ldap_get_dn(ld, result)) == NULL) { + return 3; + } + + if (glist != NULL) { + + while (glist != NULL && !found) { + if (glist->type == 'd') { + + attrs[0] = NULL; +#ifdef USE_LOG + fprintf(logfd, + "searching for dynamic group %s\n", + glist->group); +#endif + if (ldap_search_s(ld, searchBase, LDAP_SCOPE_SUBTREE, glist->group, + attrs, 0, &result) != LDAP_SUCCESS) { + free(userdn); + return 4; + } + + entryCount = ldap_count_entries(ld, result); + + if (entryCount > 0) { + result = ldap_first_entry(ld, result); + while (result != NULL && !found) { + resultdn = ldap_get_dn(ld, result); + if (!strcmp(userdn, resultdn)) { + found = 1; + *group = glist->group; + } + + free(resultdn); + + result = ldap_next_entry(ld, result); + + } + } + + } else { + /* static group */ + sprintf(filter, + "(& (cn=%s) (| (objectclass=groupofuniquenames) (objectclass=groupofnames)))", + glist->group); + attrs[0] = strdup("member"); + attrs[1] = NULL; +#ifdef USE_LOG + fprintf(logfd, + "searching for static group %s using filter %s\n", + glist->group, filter); +#endif + if (ldap_search_s(ld, searchBase, LDAP_SCOPE_SUBTREE, filter, + attrs, 0, &result) != LDAP_SUCCESS) { + free(userdn); + free(attrs[0]); + return 4; + } + + + entryCount = ldap_count_entries(ld, result); + + if (entryCount > 0) { + result = ldap_first_entry(ld, result); + while (result != NULL && !found) { + prevals = vals = + ldap_get_values(ld, result, "member"); + while (vals != NULL && *vals != NULL && !found) { + if (!strcmp(userdn, *vals)) { + found = 1; + *group = glist->group; + } + *vals++; + } + ldap_value_free(prevals); + + result = ldap_next_entry(ld, result); + + } + } + + free(attrs[0]); + } + + + +#ifdef USE_LOG + if (!found) + fprintf(logfd, "user %s not found in group %s\n", userdn, + glist->group); + else + fprintf(logfd, "user %s found in group %s\n", userdn, + glist->group); +#endif + glist = glist->next; + + } + + if (!found) { + free(userdn); + return 5; + } + } + +#ifdef USE_LOG + fprintf(logfd, "binding as %s\n", userdn); +#endif + if (ldap_simple_bind_s(ld, userdn, password) != LDAP_SUCCESS) { + free(userdn); + return 6; + } + + free(userdn); + return 0; +} + + diff -Nru old/squid-2.4.STABLE2/configure new/squid-2.4.STABLE2/configure --- old/squid-2.4.STABLE2/configure Sun Jun 10 20:33:51 2001 +++ new/squid-2.4.STABLE2/configure Fri Oct 5 11:40:56 2001 @@ -658,7 +658,7 @@ -# From configure.in Revision: 1.205.2.9 +# From configure.in Revision: 1.205.2.10 ac_aux_dir= for ac_dir in cfgaux $srcdir/cfgaux; do if test -f $ac_dir/install-sh; then @@ -2753,7 +2753,7 @@ int main() { /* Ultrix mips cc rejects this. */ -typedef int charset[2]; const charset x; +typedef int charset[2]; const charset x = {0,0}; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; @@ -3280,7 +3280,7 @@ #include "confdefs.h" #include int main() { -char *p = alloca(2 * sizeof(int)); +void *p = alloca(2 * sizeof(int)); ; return 0; } EOF if { (eval echo configure:3287: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then diff -Nru old/squid-2.4.STABLE2/include/version.h new/squid-2.4.STABLE2/include/version.h --- old/squid-2.4.STABLE2/include/version.h Fri Aug 24 20:04:32 2001 +++ new/squid-2.4.STABLE2/include/version.h Fri Oct 5 11:40:33 2001 @@ -4,7 +4,7 @@ * SQUID_VERSION - String for version id of this distribution */ #ifndef SQUID_VERSION -#define SQUID_VERSION "2.4.STABLE2" +#define SQUID_VERSION "2.4.STABLE2-ldap_auth" #endif #ifndef SQUID_RELEASE_TIME diff -Nru old/squid-2.4.STABLE2/src/Makefile.in new/squid-2.4.STABLE2/src/Makefile.in --- old/squid-2.4.STABLE2/src/Makefile.in Wed Apr 4 09:01:12 2001 +++ new/squid-2.4.STABLE2/src/Makefile.in Fri Oct 5 11:40:33 2001 @@ -93,6 +93,7 @@ acl.o \ asn.o \ authenticate.o \ + ldap_authenticate.o \ cache_cf.o \ CacheDigest.o \ cache_manager.o \ diff -Nru old/squid-2.4.STABLE2/src/acl.c new/squid-2.4.STABLE2/src/acl.c --- old/squid-2.4.STABLE2/src/acl.c Tue Aug 21 07:55:47 2001 +++ new/squid-2.4.STABLE2/src/acl.c Fri Oct 5 11:40:33 2001 @@ -39,11 +39,13 @@ static int aclFromFile = 0; static FILE *aclFile; static hash_table *proxy_auth_cache = NULL; +static hash_table *ldap_auth_cache = NULL; static void aclParseDomainList(void *curlist); static void aclParseIpList(void *curlist); static void aclParseIntlist(void *curlist); static void aclParseWordList(void *curlist); +static void aclParseLdapWordList(void *curlist); static void aclParseProtoList(void *curlist); static void aclParseMethodList(void *curlist); static void aclParseTimeSpec(void *curlist); @@ -53,6 +55,7 @@ static void aclDestroyTimeList(acl_time_data * data); static void aclDestroyIntRange(intrange *); static FREE aclFreeProxyAuthUser; +static FREE aclFreeLdapAuthUser; static struct _acl *aclFindByName(const char *name); static int aclMatchAcl(struct _acl *, aclCheck_t *); static int aclMatchIntegerRange(intrange * data, int i); @@ -77,6 +80,8 @@ static FQDNH aclLookupDstFQDNDone; static void aclLookupProxyAuthStart(aclCheck_t * checklist); static void aclLookupProxyAuthDone(void *data, char *result); +static void aclLookupLdapAuthStart(aclCheck_t * checklist); +static void aclLookupLdapAuthDone(void *data, char *result); static wordlist *aclDumpIpList(void *); static wordlist *aclDumpDomainList(void *data); static wordlist *aclDumpTimeSpecList(acl_time_data *); @@ -149,6 +154,79 @@ } } +/* works like strtokFile, but single quotes are assumed to wrap names + with spaces. Necessary for ldap groups, which can have spaces. +*/ +static char * +strtokLdapFile(void) +{ + char *t = NULL; + static char *r = NULL; + char c; + LOCAL_ARRAY(char, buf, 256); + + /* wrest control of the string from that bastard strtok */ + if (r == NULL) + r = strtok(NULL, ""); + + if (r == NULL || *r == '\0') { + r = NULL; + return NULL; + } + + t = r; + + strtok_again: + if (!aclFromFile) { + while (*r && (*r == ' ' || *r == '\n' || *r == '\r' || *r == '\t')) + r++; + + + if (*r == '\"' || *r == '\'') { + c = *r; + t = ++r; + while (*r && *r != c) + r++; + *(r++) = '\0'; + if (c == '\"') { + if ((aclFile = fopen(t, "r")) == NULL) { + debug(28, 0) ("strtokLdapFile: %s not found\n", t); + return (NULL); + } + aclFromFile = 1; + } else { + return t; + } + } else { + while (*r && *r != ' ' && *r != '\n' && *r != '\r' && *r != '\t') + r++; + *(r++) = '\0'; + + return t; + } + } + + /* aclFromFile */ + if (fgets(buf, 256, aclFile) == NULL) { + /* stop reading from file */ + fclose(aclFile); + aclFromFile = 0; + goto strtok_again; + } else { + t = buf; + /* skip leading and trailing white space */ + t += strspn(buf, w_space); + t[strcspn(t, w_space)] = '\0'; + /* skip comments */ + if (*t == '#') + goto strtok_again; + /* skip blank lines */ + if (!*t) + goto strtok_again; + return t; + } +} + static squid_acl aclStrToType(const char *s) { @@ -198,6 +276,8 @@ return ACL_PROXY_AUTH; if (!strcmp(s, "proxy_auth_regex")) return ACL_PROXY_AUTH_REGEX; + if (!strcmp(s, "ldap_auth")) + return ACL_LDAP_AUTH; if (!strcmp(s, "src_as")) return ACL_SRC_ASN; if (!strcmp(s, "dst_as")) @@ -262,6 +342,8 @@ return "proxy_auth"; if (type == ACL_PROXY_AUTH_REGEX) return "proxy_auth_regex"; + if (type == ACL_LDAP_AUTH) + return "ldap_auth"; if (type == ACL_SRC_ASN) return "src_as"; if (type == ACL_DST_ASN) @@ -637,6 +719,14 @@ wordlistAdd(curlist, t); } +static void +aclParseLdapWordList(void *curlist) +{ + char *t = NULL; + while ((t = strtokLdapFile())) + wordlistAdd(curlist, t); +} + /**********************/ /* aclParseDomainList */ /**********************/ @@ -763,6 +853,16 @@ assert(proxy_auth_cache); } break; + case ACL_LDAP_AUTH: + aclParseLdapWordList(&A->data); + if (!ldap_auth_cache) { + ldap_auth_cache = + hash_create((HASHCMP *) strcmp, + Config.ldapAuthCacheSize * sizeof(acl_ldap_auth_user), + hash_string); + assert(ldap_auth_cache); + } + break; #if SQUID_SNMP case ACL_SNMP_COMMUNITY: aclParseWordList(&A->data); @@ -835,6 +935,17 @@ return 0; } +/* does name lookup, returns if it is a ldap_auth acl */ +int +aclIsLdapAuth(const char *name) +{ + acl *a; + if (NULL == name) + return 0; + if ((a = aclFindByName(name))) + return a->type == ACL_LDAP_AUTH; + return 0; +} /* maex@space.net (05.09.96) * get the info for redirecting "access denied" to info pages @@ -1031,14 +1142,83 @@ return 0; } + static int +aclMatchLdapUserAndGroup(wordlist * data, const char *user, const char *group) +{ + if (user == NULL) + return 0; + debug(28, 3) ("aclMatchLdapUser: checking user '%s' group '%s'\n", user, + group); + while (data) { + debug(28, 3) ("aclMatchLdapUser: looking for '%s'\n", data->key); + if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0' + && strcmp(user, "-") != 0) + return 1; + if ((strcasecmp(data->key, "static") == 0 + || strcasecmp(data->key, "dynamic") == 0) + && data->next != NULL) { + data = data->next; /* skip to the group name */ + if (group != NULL && strcasecmp(data->key, group) == 0) { + /* users group matched */ + return 1; + } + } + + if (strcmp(data->key, user) == 0) + return 1; + data = data->next; + } + return 0; +} + +/* used to walk down a word list looking for ldap groups. + * groups are prefaced in the list with either "static" + * or "dynamic", depending on type. + * The position of he next starting point is set in data, and + * this pointer should be passed again to get the next group. + * If the group returned is dynamic, isDynamic will be set to 1. + */ +char * +aclNextLdapGroup(wordlist ** data, int *isDynamic) +{ + wordlist *w = NULL; + char *ret = NULL; + int isdy = 1; + + if (data == NULL || *data == NULL) + return NULL; + + w = *data; + + while (w) { + if (((isdy = strcasecmp(w->key, "dynamic")) == 0 || + strcasecmp(w->key, "static") == 0) && w->next != NULL) { + if (isdy == 0) + *isDynamic = 1; + else + *isDynamic = 0; + w = w->next; + ret = w->key; + *data = w->next; + + return ret; + } + w = w->next; + } + + *data = NULL; + + return NULL; +} + static int aclDecodeProxyAuth(const char *proxy_auth, char **user, char **password, char *buf, size_t bufsize) { char *sent_auth; char *cleartext; + debug(28, 6) ("aclDecodeProxyAuth: header = '%s'\n", proxy_auth); if (proxy_auth == NULL) return 0; - debug(28, 6) ("aclDecodeProxyAuth: header = '%s'\n", proxy_auth); if (strncasecmp(proxy_auth, "Basic ", 6) != 0) { debug(28, 1) ("aclDecodeProxyAuth: Unsupported proxy-auth sheme, '%s'\n", proxy_auth); return 0; @@ -1234,6 +1414,209 @@ checklist); } +/* aclMatchLdapAuth can return three exit codes: + * 0 : user denied access + * 1 : user validated OK + * -1 : check the password for this user via an external authenticator + * -2 : invalid Proxy-authorization: header; + * ask for Proxy-Authorization: header + */ + +static int +aclMatchLdapAuth(void * data, const char *proxy_auth, acl_ldap_auth_user * ldap_user, aclCheck_t * checklist, squid_acl acltype) +{ + /* checklist is used to register user name when identified, nothing else */ + LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); + char *user, *password, *group; + wordlist *nextgroup; + int dummyint; + LOCAL_ARRAY(char, usergroup, 256); + + if (!aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, + sizeof(login_buf))) + /* No or invalid Proxy-Auth header */ + return -2; + + /* store pointer to group list here, to be used later */ + checklist->group_list = data; + + debug(28, 5) ("aclMatchLdapAuth: checking user '%s'\n", user); + + if (ldap_user) { + /* + * This should be optimized to a boolean argument indicating that the + * password is invalid, instead of passing full acl_ldap_auth_user + * structures, and all messing with checklist->ldap_auth should + * be restricted the functions that deal with the authenticator. + */ + assert(ldap_user == checklist->ldap_user); + checklist->ldap_user = NULL; /* get rid of that special reference */ + /* Check result from external validation */ + if (ldap_user->auth_ok != 1) { + /* password and group checked but auth failed */ + assert(ldap_user->auth_ok == 0); + debug(28, 4) + ("aclMatchLdapAuth: authentication failed for user '%s' group '%s'\n", + user, (ldap_user->group == NULL) ? "NONE" : ldap_user->group); + aclFreeLdapAuthUser(ldap_user); + /* + * copy username to request for logging on client-side + * unless ident is known (do not override ident with + * false proxy auth names) + */ + if (!*checklist->request->user_ident) + xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); + return -2; + } else { + /* auth succeeded */ + debug(28, + 4) ("aclMatchLdapAuth: user '%s' group '%s' validated OK\n", + user, (ldap_user->group == NULL) ? "NONE" : ldap_user->group); + /* store validated user in hash, after filling in expiretime */ + xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); + ldap_user->expiretime = + current_time.tv_sec + Config.ldapAuthCacheTTL; + ldap_user->ip_expiretime = + squid_curtime + Config.ldapAuthCacheIpTTL; + ldap_user->ipaddr = checklist->src_addr; + /* set up the hash key using the user and group */ + if (ldap_user->group == NULL) { + ldap_user->hash.key = xstrdup(ldap_user->user); + } else { + ldap_user->hash.key = + xmalloc(strlen(ldap_user->user) + strlen(ldap_user->group) + + 1); + strcpy(ldap_user->hash.key, ldap_user->user); + strcat(ldap_user->hash.key, ldap_user->group); + } + + hash_join(ldap_auth_cache, &ldap_user->hash); + /* Continue checking below, as normal */ + } + } else { + nextgroup = data; + + /* see if we already know this user for any of the groups in the acl */ + while (ldap_user == NULL && nextgroup != NULL) { + group = aclNextLdapGroup(&nextgroup, &dummyint); + strcpy(usergroup, user); + if (group != NULL) { + strcat(usergroup, group); + } + + ldap_user = hash_lookup(ldap_auth_cache, usergroup); + } + } + + if (!ldap_user) { + /* user not yet known, ask external authenticator */ + debug(28, 4) ("aclMatchLdapAuth: user '%s' not yet known\n", user); + return -1; + } else if ((0 == strcmp(ldap_user->passwd, password)) && + (ldap_user->expiretime > current_time.tv_sec)) { + if (checklist->src_addr.s_addr == ldap_user->ipaddr.s_addr + || ldap_user->ip_expiretime <= squid_curtime) { + /* user already known and valid */ + debug(28, 5) ("aclMatchLdapAuth: user '%s' previously validated\n", + user); + /* Update IP ttl */ + ldap_user->ip_expiretime = + squid_curtime + Config.ldapAuthCacheIpTTL; + ldap_user->ipaddr = checklist->src_addr; + /* copy username to request for logging on client-side */ + xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); + return aclMatchLdapUserAndGroup(data, user, ldap_user->group); + } else { + /* user has switched to another IP addr */ + debug(28, + 1) ("aclMatchLdapAuth: user '%s' has changed IP address\n", + user); + /* remove this user from the hash, making him unknown */ + hash_remove_link(ldap_auth_cache, (hash_link *) ldap_user); + aclFreeLdapAuthUser(ldap_user); + /* require the user to reauthenticate */ + return -2; + } + } else { + /* password mismatch/timeout */ + debug(28, 4) ("aclMatchLdapAuth: user '%s' password mismatch/timeout\n", + user); + /* remove this user from the hash, making him unknown */ + hash_remove_link(ldap_auth_cache, (hash_link *) ldap_user); + aclFreeLdapAuthUser(ldap_user); + /* ask the external authenticator in case the password is changed */ + /* wrong password will be trapped above so this does not loop */ + return -1; + } + /* NOTREACHED */ + +} + +static void +aclLookupLdapAuthStart(aclCheck_t * checklist) +{ + LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); + const char *proxy_auth; + char *user, *password; + int ok; + int groupcount = 0; + int is_dynamic = 0; + char *group, *groupstr = NULL; + wordlist *nextgroup; + acl_ldap_auth_user *ldap_user; + + assert(!checklist->ldap_user); + if (!checklist->request->flags.accelerated) { + /* Proxy auth on proxy requests */ + proxy_auth = httpHeaderGetStr(&checklist->request->header, + HDR_PROXY_AUTHORIZATION); + } else { + /* WWW auth on accelerated requests */ + proxy_auth = httpHeaderGetStr(&checklist->request->header, + HDR_AUTHORIZATION); + } + ok = aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, + sizeof(login_buf)); + /* + * if aclDecodeProxyAuth() fails, the same call should have failed + * in aclMatchProxyAuth, and we should never get this far. + */ + assert(ok); + + nextgroup = checklist->group_list; + + while ((group = aclNextLdapGroup(&nextgroup, &is_dynamic)) != NULL) { + groupcount++; + if (!groupstr) { + groupstr = (char *) xmalloc(strlen(group) + 6); + *groupstr = '\0'; + } else { + groupstr = (char *) xrealloc(groupstr, strlen(groupstr) + + strlen(group) + 5); + } + + strcat(groupstr, is_dynamic ? " d #" : " s #"); + strcat(groupstr, group); + strcat(groupstr, "#"); + } + + debug(28, 4) + ("aclLookupLdapAuthStart: going to ask ldap authenticator about user '%s'\n", + user); + /* we must still check this user's password */ + ldap_user = memAllocate(MEM_ACL_LDAP_AUTH_USER); + ldap_user->hash.key = NULL; + ldap_user->user = xstrdup(user); + ldap_user->passwd = xstrdup(password); + ldap_user->auth_ok = -1; + ldap_user->group = NULL; + ldap_user->expiretime = -1; + checklist->ldap_user = ldap_user; + ldapAuthenticateStart(checklist->ldap_user, groupcount, groupstr, + aclLookupLdapAuthDone, checklist); + xfree(groupstr); +} + static int aclMatchInteger(intlist * data, int i) { @@ -1351,7 +1734,6 @@ default: break; } - debug(28, 3) ("aclMatchAcl: checking '%s'\n", ae->cfgline); switch (ae->type) { case ACL_SRC_IP: return aclMatchIp(&ae->data, checklist->src_addr); @@ -1540,6 +1922,62 @@ return 0; } /* NOTREACHED */ + case ACL_LDAP_AUTH: + if (NULL == r) { + return -1; + } else if (!r->flags.accelerated) { + /* Proxy authorization on proxy requests */ + header = httpHeaderGetStr(&checklist->request->header, + HDR_PROXY_AUTHORIZATION); + } else if (r->flags.internal) { + /* WWW authorization on accelerated internal requests */ + header = httpHeaderGetStr(&checklist->request->header, + HDR_AUTHORIZATION); + } else { +#if AUTH_ON_ACCELERATION + /* WWW authorization on accelerated requests */ + header = httpHeaderGetStr(&checklist->request->header, + HDR_AUTHORIZATION); +#else + debug(28, 1) + ("aclMatchAcl: ldap_auth %s not applicable on accelerated requests.\n", + ae->name); + return -1; +#endif + } + /* + * Register that we used the proxy authentication header so that + * it is not forwarded to the next proxy + */ + r->flags.used_proxy_auth = 1; + /* Check the password */ + switch (aclMatchLdapAuth(ae->data, + header, + checklist->ldap_user, + checklist, + ae->type)) { + case 0: + /* Correct password, but was not allowed in this ACL */ + return 0; + case 1: + /* user validated OK */ + return 1; + case -2: + /* no such user OR we need a proxy authentication header */ + checklist->state[ACL_LDAP_AUTH] = ACL_PROXY_AUTH_NEEDED; + /* + * XXX This is a bit oddly done.. should perhaps use different + * return codes here + */ + return 0; + case -1: + /* + * we need to validate the password + */ + checklist->state[ACL_LDAP_AUTH] = ACL_LOOKUP_NEEDED; + return 0; + } + /* NOTREACHED */ #if SQUID_SNMP case ACL_SNMP_COMMUNITY: return aclMatchWordList(ae->data, checklist->snmp_community); @@ -1664,15 +2102,19 @@ aclLookupDstFQDNDone, checklist); return; + } else if (checklist->state[ACL_LDAP_AUTH] == ACL_LOOKUP_NEEDED) { + debug(28, 3) ("aclCheck: checking password via ldap authenticator\n"); + aclLookupLdapAuthStart(checklist); + checklist->state[ACL_LDAP_AUTH] = ACL_LOOKUP_PENDING; + return; } else if (checklist->state[ACL_PROXY_AUTH] == ACL_LOOKUP_NEEDED) { debug(28, 3) ("aclCheck: checking password via authenticator\n"); aclLookupProxyAuthStart(checklist); checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_PENDING; return; - } else if (checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_NEEDED) { - /* Special case. Client is required to resend the request - * with authentication. The request is denied. - */ + } else if (checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_NEEDED || + checklist->state[ACL_LDAP_AUTH] == ACL_PROXY_AUTH_NEEDED) { + debug(28, 3) ("aclCheck: Client is required to resend the request with authentication. The request is denied.\n"); allow = ACCESS_REQ_PROXY_AUTH; match = -1; } @@ -1809,6 +2251,34 @@ aclCheck(checklist); } +static void +aclLookupLdapAuthDone(void *data, char *result) +{ + aclCheck_t *checklist = data; + char *group; + debug(28, 4) ("aclLookupLdapAuthDone: result = %s\n", + result ? result : "NULL"); + if (result) { + if (strncasecmp(result, "p", 1) == 0) { + checklist->ldap_user->auth_ok = 1; + checklist->state[ACL_LDAP_AUTH] = ACL_LOOKUP_DONE; + /* if a group was returned, store it in the ldap_user */ + if ((group = strchr(result, ' ')) != NULL) { + checklist->ldap_user->group = xstrdup(++group); + } + } else if (strncasecmp(result, "f", 1) == 0) { + checklist->ldap_user->auth_ok = 0; + checklist->state[ACL_LDAP_AUTH] = ACL_LOOKUP_DONE; + } + } else { + /* XXX print error message about failed ldap_auth attempt? */ + checklist->ldap_user->auth_ok = 0; + checklist->state[ACL_LDAP_AUTH] = ACL_LOOKUP_DONE; + } + + aclCheck(checklist); +} + aclCheck_t * aclChecklistCreate(const acl_access * A, request_t * request, @@ -1890,6 +2360,17 @@ } static void +aclFreeLdapAuthUser(void *data) +{ + acl_ldap_auth_user *u = data; + xfree(u->hash.key); + xfree(u->user); + xfree(u->passwd); + xfree(u->group); + memFree(u, MEM_ACL_LDAP_AUTH_USER); +} + +static void aclFreeIpData(void *p) { memFree(p, MEM_ACL_IP_DATA); @@ -1920,6 +2401,7 @@ #if USE_IDENT case ACL_IDENT: #endif + case ACL_LDAP_AUTH: case ACL_PROXY_AUTH: wordlistDestroy((wordlist **) & a->data); break; @@ -2248,6 +2730,7 @@ break; #endif case ACL_PROXY_AUTH: + case ACL_LDAP_AUTH: return wordlistDup(a->data); break; case ACL_TIME: diff -Nru old/squid-2.4.STABLE2/src/cf.data.pre new/squid-2.4.STABLE2/src/cf.data.pre --- old/squid-2.4.STABLE2/src/cf.data.pre Wed Apr 4 09:01:12 2001 +++ new/squid-2.4.STABLE2/src/cf.data.pre Fri Oct 5 11:40:33 2001 @@ -1194,6 +1194,91 @@ the userid will not be forced to reauthenticate. DOC_END +NAME: ldap_auth_program +TYPE: wordlist +LOC: Config.Program.ldapAuth +DEFAULT: none +DOC_START + Specify the command for the external ldap user and group + authenticator. If you use an authenticator, make sure you have + 1 acl of type ldap_auth. By default, the ldap_auth_program is + not used. + + To use the group ldap authenticator, jump over to the + ../auth_modules/GROUP_LDAP directory and + type: + % make + % make install + + Then, set this line to something like + + ldap_auth_program @DEFAULT_PREFIX@/bin/group_ldap_auth searchbase ldapserver port + + +ldap_auth_program @DEFAULT_PREFIX@/bin/group_ldap_auth o=mydomain.com ldap 389 +DOC_END + +NAME: ldap_auth_children +TYPE: int +LOC: Config.ldapAuthChildren +DEFAULT: 5 +DOC_START + The number of ldap authenticator processes to spawn (default 5). + If you start too few Squid will have to wait for them to process + a backlog of user/password verifications, slowing it down. When + password verifications are done via a slow network or you have + ldap_auth acls with several groups you are likely to need lots of + ldap authenticator processes. + +ldap_auth_children 5 +DOC_END + +NAME: ldap_auth_cache_size +TYPE: int +LOC: Config.ldapAuthCacheSize +DEFAULT: 64 +DOC_START + The size of the ldap username/password/group cache in entries + (default 64). + +ldap_auth_cache_size 64 +DOC_END + +NAME: ldap_auth_cache_ttl +TYPE: int +LOC: Config.ldapAuthCacheTTL +DEFAULT: 3600 +DOC_START + The number of seconds a checked ldap username/password/group + combination remains cached (default 3600). If a wrong password is + given for a cached user, the user gets removed from the username + /password/group cache forcing a revalidation. + +ldap_auth_cache_ttl 3600 +DOC_END + +NAME: ldap_auth_cache_ip_ttl +TYPE: int +LOC: Config.ldapAuthCacheIpTTL +DEFAULT: 0 +DOC_START + With this option you control how long a ldap authentication + will be bound to a specific IP address. If a request using + the same user name is received during this time then access + will be denied and both users are required to reauthenticate + them selves. The idea behind this is to make it annoying + for people to share their password to their friends, but + yet allow a dialup user to reconnect on a different dialup + port. + + The default is 0 to disable the check. Recommended value + if you have dialup users are no more than 60 (seconds). If + all your users are stationary then higher values may be + used. + +ldap_auth_cache_ip_ttl 0 +DOC_END + COMMENT_START OPTIONS FOR TUNING THE CACHE ----------------------------------------------------------------------------- @@ -1689,6 +1774,26 @@ # authenticate_program). # # WARNING: proxy_auth can't be used in a transparent proxy. It + # collides with any authentication done by origin servers. It may + # seem like it works at first, but it doesn't. + + acl aclname ldap_auth (((static | dynamic) group) | username) ... + # list of usernames or groups + # Use REQUIRED to accept any valid username. + # + # A list of groups and/or users can be specified here. The group + # must be prefaced with either static or dynamic to define the group + # type. + # + # NOTE: when a Proxy-Authentication header is sent but it is not + # needed during ACL checking the username is NOT logged + # in access.log. + # + # NOTE: ldap_auth requires a EXTERNAL authentication program + # to check username/password combinations (see + # ldap_auth_program). + # + # WARNING: ldap_auth can't be used in a transparent proxy. It # collides with any authentication done by origin servers. It may # seem like it works at first, but it doesn't. diff -Nru old/squid-2.4.STABLE2/src/client_side.c new/squid-2.4.STABLE2/src/client_side.c --- old/squid-2.4.STABLE2/src/client_side.c Sat Apr 21 01:21:41 2001 +++ new/squid-2.4.STABLE2/src/client_side.c Fri Oct 5 11:40:33 2001 @@ -243,7 +243,8 @@ http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); - if (answer == ACCESS_REQ_PROXY_AUTH || aclIsProxyAuth(AclMatchedName)) { + if (answer == ACCESS_REQ_PROXY_AUTH || aclIsProxyAuth(AclMatchedName) || + aclIsLdapAuth(AclMatchedName)) { if (!http->flags.accel) { /* Proxy authorisation needed */ status = HTTP_PROXY_AUTHENTICATION_REQUIRED; diff -Nru old/squid-2.4.STABLE2/src/enums.h new/squid-2.4.STABLE2/src/enums.h --- old/squid-2.4.STABLE2/src/enums.h Fri Jan 12 01:51:47 2001 +++ new/squid-2.4.STABLE2/src/enums.h Fri Oct 5 11:40:33 2001 @@ -115,6 +115,7 @@ ACL_BROWSER, ACL_PROXY_AUTH, ACL_PROXY_AUTH_REGEX, + ACL_LDAP_AUTH, ACL_SRC_ASN, ACL_DST_ASN, ACL_SRC_ARP, @@ -518,6 +519,7 @@ MEM_ACL_LIST, MEM_ACL_NAME_LIST, MEM_ACL_PROXY_AUTH_USER, + MEM_ACL_LDAP_AUTH_USER, MEM_ACL_TIME_DATA, MEM_CACHEMGR_PASSWD, #if USE_CACHE_DIGESTS diff -Nru old/squid-2.4.STABLE2/src/ldap_authenticate.c new/squid-2.4.STABLE2/src/ldap_authenticate.c --- old/squid-2.4.STABLE2/src/ldap_authenticate.c Thu Jan 1 01:00:00 1970 +++ new/squid-2.4.STABLE2/src/ldap_authenticate.c Fri Oct 5 11:40:34 2001 @@ -0,0 +1,146 @@ + +/* + * + * DEBUG: section 29 Authenticator + * AUTHOR: Tobias Crawley + * + * based upon authenticate.c by Duane Wessels + * + * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from the + * Internet community. Development is led by Duane Wessels of the + * National Laboratory for Applied Network Research and funded by the + * National Science Foundation. Squid is Copyrighted (C) 1998 by + * Duane Wessels and the University of California San Diego. Please + * see the COPYRIGHT file for full details. Squid incorporates + * software developed and/or copyrighted by other sources. Please see + * the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +typedef struct +{ + void *data; + acl_ldap_auth_user *ldap_user; + RH *handler; +} +ldapAuthenticateStateData; + +static HLPCB ldapAuthenticateHandleReply; +static void ldapAuthenticateStateFree(ldapAuthenticateStateData * r); +static helper *ldapAuthenticators = NULL; + +static void +ldapAuthenticateHandleReply(void *data, char *reply) +{ + ldapAuthenticateStateData *r = data; + int valid; + + debug(29, 5) ("ldapAuthenticateHandleReply: {%s}\n", + reply ? reply : ""); + if (reply && *reply == '\0') { + reply = NULL; + } + valid = cbdataValid(r->data); + cbdataUnlock(r->data); + if (valid) + r->handler(r->data, reply); + ldapAuthenticateStateFree(r); +} + +static void +ldapAuthenticateStateFree(ldapAuthenticateStateData * r) +{ + cbdataFree(r); +} + +static void +ldapAuthenticateStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "ldapAuthenticator Statistics:\n"); + helperStats(sentry, ldapAuthenticators); +} + +/**** PUBLIC FUNCTIONS ****/ + + +void +ldapAuthenticateStart(acl_ldap_auth_user * ldap_user, int groupcount, + char *groupstr, RH * handler, void *data) +{ + ldapAuthenticateStateData *r = NULL; + char *buf; + int bufsize = 0; + assert(ldap_user); + assert(handler); + debug(29, 5) ("ldapAuthenticateStart: '%s:%s'\n", ldap_user->user, + ldap_user->passwd); + if (Config.Program.ldapAuth == NULL) { + handler(data, NULL); + return; + } + r = xcalloc(1, sizeof(ldapAuthenticateStateData)); + cbdataAdd(r, cbdataXfree, 0); + r->handler = handler; + cbdataLock(data); + r->data = data; + r->ldap_user = ldap_user; + bufsize = strlen(r->ldap_user->user) + 1 + strlen(r->ldap_user->passwd) + + 2 + groupcount / 10 + ((groupcount > 0 && groupstr) ? + strlen(groupstr) : 0) + 2; + buf = (char *) xmalloc(bufsize); + snprintf(buf, bufsize, "%s %s %d%s\n", r->ldap_user->user, + r->ldap_user->passwd, groupcount, (groupcount > 0 && groupstr) ? + groupstr : ""); + helperSubmit(ldapAuthenticators, buf, ldapAuthenticateHandleReply, r); + xfree(buf); +} + +void +ldapAuthenticateInit(void) +{ + static int init = 0; + if (!Config.Program.ldapAuth) + return; + if (ldapAuthenticators == NULL) + ldapAuthenticators = helperCreate("ldapAuthenticator"); + ldapAuthenticators->cmdline = Config.Program.ldapAuth; + ldapAuthenticators->n_to_start = Config.ldapAuthChildren; + ldapAuthenticators->ipc_type = IPC_TCP_SOCKET; + helperOpenServers(ldapAuthenticators); + if (!init) { + cachemgrRegister("ldapAuthenticator", + "User ldapAuthenticator Stats", ldapAuthenticateStats, 0, 1); + init++; + } +} + +void +ldapAuthenticateShutdown(void) +{ + if (!ldapAuthenticators) + return; + helperShutdown(ldapAuthenticators); + if (!shutting_down) + return; + helperFree(ldapAuthenticators); + ldapAuthenticators = NULL; +} diff -Nru old/squid-2.4.STABLE2/src/main.c new/squid-2.4.STABLE2/src/main.c --- old/squid-2.4.STABLE2/src/main.c Sun May 20 02:09:59 2001 +++ new/squid-2.4.STABLE2/src/main.c Fri Oct 5 11:40:33 2001 @@ -344,6 +344,7 @@ #endif redirectShutdown(); authenticateShutdown(); + ldapAuthenticateShutdown(); storeDirCloseSwapLogs(); errorClean(); mimeFreeMemory(); @@ -359,6 +360,7 @@ #endif redirectInit(); authenticateInit(); + ldapAuthenticateInit(); #if USE_WCCP wccpInit(); #endif @@ -385,6 +387,7 @@ #endif redirectShutdown(); authenticateShutdown(); + ldapAuthenticateShutdown(); _db_rotate_log(); /* cache.log */ storeDirWriteCleanLogs(1); storeLogRotate(); /* store.log */ @@ -400,6 +403,7 @@ #endif redirectInit(); authenticateInit(); + ldapAuthenticateInit(); } static void @@ -489,6 +493,7 @@ #endif redirectInit(); authenticateInit(); + ldapAuthenticateInit(); useragentOpenLog(); refererOpenLog(); httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ @@ -711,6 +716,7 @@ #endif redirectShutdown(); authenticateShutdown(); + ldapAuthenticateShutdown(); eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1); } eventRun(); diff -Nru old/squid-2.4.STABLE2/src/mem.c new/squid-2.4.STABLE2/src/mem.c --- old/squid-2.4.STABLE2/src/mem.c Fri Jan 12 01:51:50 2001 +++ new/squid-2.4.STABLE2/src/mem.c Fri Oct 5 11:40:33 2001 @@ -206,6 +206,8 @@ memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0); memDataInit(MEM_ACL_PROXY_AUTH_USER, "acl_proxy_auth_user", sizeof(acl_proxy_auth_user), 0); + memDataInit(MEM_ACL_LDAP_AUTH_USER, "acl_ldap_auth_user", + sizeof(acl_ldap_auth_user), 0); memDataInit(MEM_CACHEMGR_PASSWD, "cachemgr_passwd", sizeof(cachemgr_passwd), 0); #if USE_CACHE_DIGESTS diff -Nru old/squid-2.4.STABLE2/src/protos.h new/squid-2.4.STABLE2/src/protos.h --- old/squid-2.4.STABLE2/src/protos.h Sun May 20 02:09:59 2001 +++ new/squid-2.4.STABLE2/src/protos.h Fri Oct 5 11:40:33 2001 @@ -58,6 +58,7 @@ extern void aclParseAccessLine(struct _acl_access **); extern void aclParseAclLine(acl **); extern int aclIsProxyAuth(const char *name); +extern int aclIsLdapAuth(const char *name); extern int aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name); extern void aclParseDenyInfoLine(struct _acl_deny_info_list **); extern void aclDestroyDenyInfoList(struct _acl_deny_info_list **); @@ -701,6 +702,10 @@ extern void authenticateStart(acl_proxy_auth_user *, RH *, void *); extern void authenticateInit(void); extern void authenticateShutdown(void); + +extern void ldapAuthenticateStart(acl_ldap_auth_user *, int, char *, RH *, void *); +extern void ldapAuthenticateInit(void); +extern void ldapAuthenticateShutdown(void); extern void refreshAddToList(const char *, int, time_t, int, time_t); extern int refreshIsCachable(const StoreEntry *); diff -Nru old/squid-2.4.STABLE2/src/structs.h new/squid-2.4.STABLE2/src/structs.h --- old/squid-2.4.STABLE2/src/structs.h Wed Apr 4 09:01:12 2001 +++ new/squid-2.4.STABLE2/src/structs.h Fri Oct 5 11:40:33 2001 @@ -71,6 +71,19 @@ time_t ip_expiretime; }; +struct _acl_ldap_auth_user { + hash_link hash; /* must be first */ + /* extra fields for ldap_auth */ + char *user; + char *passwd; + int auth_ok; /* 1 = passwd and group checked OK */ + char *group; + int group_is_dynamic; /* 1 = the group is dynamic */ + long expiretime; + struct in_addr ipaddr; /* IP addr this user authenticated from */ + time_t ip_expiretime; +}; + struct _acl_deny_info_list { int err_page_id; char *err_page_name; @@ -148,6 +161,8 @@ char ident[USER_IDENT_SZ]; #endif acl_proxy_auth_user *auth_user; + acl_ldap_auth_user *ldap_user; + wordlist *group_list; acl_lookup_state state[ACL_ENUM_MAX]; #if SQUID_SNMP char *snmp_community; @@ -317,6 +332,7 @@ #endif wordlist *redirect; wordlist *authenticate; + wordlist *ldapAuth; #if USE_ICMP char *pinger; #endif @@ -332,6 +348,10 @@ int authenticateChildren; time_t authenticateTTL; time_t authenticateIpTTL; + int ldapAuthChildren; + int ldapAuthCacheSize; + time_t ldapAuthCacheTTL; + time_t ldapAuthCacheIpTTL; struct { int single_host; char *host; diff -Nru old/squid-2.4.STABLE2/src/typedefs.h new/squid-2.4.STABLE2/src/typedefs.h --- old/squid-2.4.STABLE2/src/typedefs.h Thu Mar 1 22:49:26 2001 +++ new/squid-2.4.STABLE2/src/typedefs.h Fri Oct 5 11:40:33 2001 @@ -63,6 +63,7 @@ typedef struct _acl_deny_info_list acl_deny_info_list; typedef struct _acl_proxy_auth acl_proxy_auth; typedef struct _acl_proxy_auth_user acl_proxy_auth_user; +typedef struct _acl_ldap_auth_user acl_ldap_auth_user; typedef struct _acl_arp_data acl_arp_data; typedef struct _acl acl; typedef struct _acl_snmp_comm acl_snmp_comm;