From 73e67ee0261cefcd36f83ba0c75d249b7a61b953 Mon Sep 17 00:00:00 2001 From: wessels <> Date: Tue, 18 Aug 1998 04:04:52 +0000 Subject: [PATCH] external proxy_auth code from Arjan --- src/Makefile.in | 16 +++- src/acl.cc | 229 +++++++++++++++++++++++------------------------- src/cache_cf.cc | 27 ++++-- src/cf.data.pre | 71 ++++++++++++--- src/defines.h | 9 +- src/enums.h | 7 +- src/main.cc | 6 +- src/protos.h | 9 +- src/structs.h | 14 +-- 9 files changed, 236 insertions(+), 152 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 7c535a9217..c624227a39 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.157 1998/07/31 00:15:31 wessels Exp $ +# $Id: Makefile.in,v 1.158 1998/08/17 22:04:52 wessels Exp $ # # Uncomment and customize the following to suit your needs: # @@ -26,6 +26,7 @@ DNSSERVER_EXE = dnsserver$(exec_suffix) UNLINKD_EXE = unlinkd$(exec_suffix) PINGER_EXE = pinger$(exec_suffix) CACHEMGR_EXE = cachemgr$(cgi_suffix) +NCSA_AUTH_EXE = ncsa_auth$(exec_suffix) DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf DEFAULT_MIME_TABLE = $(sysconfdir)/mime.conf @@ -40,6 +41,8 @@ DEFAULT_UNLINKD = $(libexecdir)/$(UNLINKD_EXE) DEFAULT_ICON_DIR = $(sysconfdir)/icons DEFAULT_ERROR_DIR = $(sysconfdir)/errors DEFAULT_MIB_PATH = $(sysconfdir)/mib.txt +DEFAULT_AUTH_PROGRAM = $(bindir)/$(NCSA_AUTH_EXE) +DEFAULT_PASSWD_FILE = $(sysconfdir)/passwd CC = @CC@ MAKEDEPEND = @MAKEDEPEND@ @@ -72,9 +75,10 @@ CLIENT_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) DNSSERVER_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) PINGER_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) STD_APP_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) +AUTH_LIBS = -L../lib -lmiscutil $(CRYPTLIB) $(XTRA_LIBS) PROGS = $(SQUID_EXE) $(CLIENT_EXE) -UTILS = $(DNSSERVER_EXE) $(UNLINKD_EXE) +UTILS = $(DNSSERVER_EXE) $(UNLINKD_EXE) $(NCSA_AUTH_EXE) SUID_UTILS = $(PINGER_EXE) CGIPROGS = $(CACHEMGR_EXE) OBJS = \ @@ -82,6 +86,7 @@ OBJS = \ acl.o \ asn.o \ @ASYNC_OBJS@ \ + authenticate.o \ cache_cf.o \ CacheDigest.o \ cache_manager.o \ @@ -220,6 +225,9 @@ $(PINGER_EXE): pinger.o $(UNLINKD_EXE): unlinkd-daemon.o $(CC) $(LDFLAGS) unlinkd-daemon.o -o $@ +$(NCSA_AUTH_EXE): ncsa_auth.o hash.o debug.o globals.o + $(CC) $(LDFLAGS) ncsa_auth.o hash.o debug.o globals.o -o $@ $(AUTH_LIBS) + unlinkd-daemon.o: unlinkd.c $(CC) -c $(CFLAGS) -DUNLINK_DAEMON $(srcdir)/unlinkd.c -o $@ @@ -250,7 +258,9 @@ cf.data: cf.data.pre Makefile s%@DEFAULT_SWAP_DIR@%$(DEFAULT_SWAP_DIR)%g;\ s%@DEFAULT_ICON_DIR@%$(DEFAULT_ICON_DIR)%g;\ s%@DEFAULT_MIB_PATH@%$(DEFAULT_MIB_PATH)%g;\ - s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g" < $(srcdir)/cf.data.pre >$@ + s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g;\ + s%@DEFAULT_AUTH_PROGRAM@%$(DEFAULT_AUTH_PROGRAM)%g;\ + s%@DEFAULT_PASSWD_FILE@%$(DEFAULT_PASSWD_FILE)%g" < $(srcdir)/cf.data.pre >$@ install-mkdirs: -@if test ! -d $(prefix); then \ diff --git a/src/acl.cc b/src/acl.cc index 5d3b7d12f9..9c78e18769 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,6 +1,6 @@ /* - * $Id: acl.cc,v 1.175 1998/08/14 19:25:13 wessels Exp $ + * $Id: acl.cc,v 1.176 1998/08/17 22:04:54 wessels Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -60,7 +60,7 @@ static IPH aclLookupDstIPDone; static IPH aclLookupDstIPforASNDone; static FQDNH aclLookupSrcFQDNDone; static FQDNH aclLookupDstFQDNDone; -static int aclReadProxyAuth(acl_proxy_auth * p); +static void aclProxyAuthDone(void *data, char *result); static wordlist *aclDumpIpList(acl_ip_data * ip); static wordlist *aclDumpDomainList(void *data); static wordlist *aclDumpTimeSpecList(acl_time_data *); @@ -646,39 +646,36 @@ aclParseDomainList(void *curlist) #endif /* USE_SPLAY_TREE */ -/* check for change password file each 300 seconds */ -#define CHECK_PROXY_FILE_TIME 300 +/* default proxy_auth timeout is 3600 seconds */ +#define PROXY_AUTH_TIMEOUT 3600 + static void aclParseProxyAuth(void *data) { acl_proxy_auth *p; acl_proxy_auth **q = data; char *t; + + p = xcalloc(1, sizeof(acl_proxy_auth)); + + /* read timeout value (if any) */ t = strtok(NULL, w_space); - if (t) { - p = xcalloc(1, sizeof(acl_proxy_auth)); - p->filename = xstrdup(t); - p->last_time = 0; - p->change_time = 0; - t = strtok(NULL, w_space); - if (t == NULL) { - p->check_interval = CHECK_PROXY_FILE_TIME; - } else { - p->check_interval = atoi(t); - } - if (p->check_interval < 1) - p->check_interval = 1; - p->hash = 0; /* force creation of a new hash table */ - if (aclReadProxyAuth(p)) { - *q = p; - return; - } else { - debug(28, 0) ("cannot read proxy_auth %s, ignoring\n", p->filename); - } + if (t == NULL) { + p->timeout = PROXY_AUTH_TIMEOUT; } else { - debug(28, 0) ("no filename in acl proxy_auth, ignoring\n"); + p->timeout = atoi(t); + } + /* the minimum timeout is 10 seconds */ + if (p->timeout < 10) + p->timeout = 10; + + /* First time around, 7921 should be big enough */ + if ((p->hash = hash_create((HASHCMP *) strcmp, 7921, hash_string)) < 0) { + debug(28, 0) ("aclParseProxyAuth: cannot create hash table, turning proxy_auth off\n"); + *q = NULL; + return; } - *q = NULL; + *q = p; return; } @@ -1116,6 +1113,13 @@ aclMatchIdent(wordlist * data, const char *ident) return 0; } +/* aclMatchProxyAuth can return three exit codes: + * 0 : No such user; invalid Proxy-authorization: header; + * ask for Proxy-Authorization: header + * 1 : user validated OK + * -1 : check the password for this user via an external authenticator + */ + static int aclMatchProxyAuth(acl_proxy_auth * p, aclCheck_t * checklist) { @@ -1136,51 +1140,65 @@ aclMatchProxyAuth(acl_proxy_auth * p, aclCheck_t * checklist) strtok(sent_auth, "\n"); cleartext = uudecode(sent_auth); xfree(sent_auth); - debug(28, 3) ("aclMatchProxyAuth: cleartext = '%s'\n", cleartext); + debug(28, 6) ("aclMatchProxyAuth: cleartext = '%s'\n", cleartext); xstrncpy(sent_user, cleartext, USER_IDENT_SZ); xfree(cleartext); if ((passwd = strchr(sent_user, ':')) != NULL) *passwd++ = '\0'; if (passwd == NULL) { - debug(28, 3) ("aclMatchProxyAuth: No passwd in auth blob\n"); + debug(28, 1) ("aclMatchProxyAuth: no passwd in proxy authorization header\n"); return 0; } - debug(28, 5) ("aclMatchProxyAuth: checking user %s\n", sent_user); + debug(28, 5) ("aclMatchProxyAuth: checking user '%s'\n", sent_user); /* copy username to checklist for logging on client-side */ xstrncpy(checklist->request->user_ident, sent_user, USER_IDENT_SZ); - /* reread password file if necessary */ - aclReadProxyAuth(p); + + /* see if we already know this user */ u = hash_lookup(p->hash, sent_user); if (NULL == u) { - /* User doesn't exist; deny them */ - debug(28, 4) ("aclMatchProxyAuth: user %s does not exist\n", sent_user); - return 0; - } - /* See if we've already validated them */ - *passwd |= 0x80; - if (0 == strcmp(u->passwd, passwd)) { - debug(28, 5) ("aclMatchProxyAuth: user %s previously validated\n", + /* user not yet known, ask external authenticator */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' not yet known\n", sent_user); + } else { + /* user already known, check password with the cached one */ + if ((0 == strcmp(u->passwd, passwd)) && + (u->expiretime > current_time.tv_sec)) { + debug(28, 5) ("aclMatchProxyAuth: user '%s' previously validated\n", + sent_user); + return 1; + } + /* password mismatch/timeout */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' password mismatch/timeout\n", sent_user); - return 1; + /* remove this user from the hash, making him unknown */ + hash_remove_link(p->hash, (hash_link *) u); + aclFreeProxyAuthUser(u); + } + + /* we've got an unknown user now */ + if (checklist->auth_user == NULL) { + /* we must still check this user's password */ + u = memAllocate(MEM_ACL_PROXY_AUTH_USER); + u->user = xstrdup(sent_user); + u->passwd = xstrdup(passwd); + u->passwd_ok = 0; + u->expiretime = 0; + checklist->auth_user = u; + debug(28, 4) ("aclMatchProxyAuth: going to ask authenticator\n"); + return -1; } - *passwd &= (~0x80); -#if HAVE_CRYPT - if (strcmp(u->passwd, crypt(passwd, u->passwd))) { -#else - if (strcmp(u->passwd, passwd)) { -#endif - /* Passwords differ, deny access */ - p->last_time = 0; /* Trigger a check of the password file */ - debug(28, 4) ("aclMatchProxyAuth: authentication failed: user %s: " - "passwords differ\n", sent_user); + /* checklist->auth_user has just been checked, check result */ + if (checklist->auth_user->passwd_ok == -1) { + /* password was checked but did not match */ + debug(28, 4) ("aclMatchProxyAuth: authentication failed for user '%s'\n", + sent_user); return 0; } - *passwd |= 0x80; - debug(28, 5) ("aclMatchProxyAuth: user %s validated OK\n", sent_user); - hash_remove_link(p->hash, (hash_link *) u); - safe_free(u->passwd); - u->passwd = xstrdup(passwd); - hash_join(p->hash, (hash_link *) u); + /* checklist->auth_user->passwd_ok == 1, passwd check OK */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' validated OK\n", sent_user); + /* store validated user in hash, after filling in expiretime */ + checklist->auth_user->expiretime = current_time.tv_sec + p->timeout; + hash_join(p->hash, (hash_link *) checklist->auth_user); + return 1; } @@ -1344,15 +1362,20 @@ aclMatchAcl(acl * acl, aclCheck_t * checklist) return aclMatchRegex(acl->data, checklist->browser); /* NOTREACHED */ case ACL_PROXY_AUTH: - if (!aclMatchProxyAuth(acl->data, checklist)) { + k = aclMatchProxyAuth(acl->data, checklist); + if (k == 0) { /* no such user OR we need a proxy authentication header */ - checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_NEEDED; + checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_NEEDED; return 0; - } else { + } else if (k == 1) { /* register that we used the proxy authentication header */ - checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_DONE; + checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_USED; EBIT_SET(r->flags, REQ_USED_PROXY_AUTH); return 1; + } else if (k == -1) { + /* register that we need to check the password */ + checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_CHECK; + return 0; } /* NOTREACHED */ case ACL_SNMP_COMM: @@ -1472,17 +1495,25 @@ aclCheck(aclCheck_t * checklist) checklist); return; } + /* extra case for proxy_auth */ + if (checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_CHECK) { + debug(28, 3) ("aclCheck: checking password via authenticator\n"); + authenticateStart(checklist->auth_user, aclProxyAuthDone, + checklist); + return; + } /* * We are done with this _acl_access entry. Either the request * is allowed, denied, or we move on to the next entry. */ cbdataUnlock(A); - if (checklist->state[ACL_PROXY_AUTH] == ACL_LOOKUP_NEEDED) { + if (checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_NEEDED) { allow = ACCESS_REQ_PROXY_AUTH; debug(28, 3) ("aclCheck: match pending, returning %d\n", allow); aclCheckCallback(checklist, allow); return; } + /* checklist->state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_USED */ if (match) { debug(28, 3) ("aclCheck: match found, returning %d\n", allow); aclCheckCallback(checklist, allow); @@ -1533,6 +1564,7 @@ aclLookupDstIPDone(const ipcache_addrs * ia, void *data) checklist->state[ACL_DST_IP] = ACL_LOOKUP_DONE; aclCheck(checklist); } + static void aclLookupDstIPforASNDone(const ipcache_addrs * ia, void *data) { @@ -1557,6 +1589,19 @@ aclLookupDstFQDNDone(const char *fqdn, void *data) aclCheck(checklist); } +static void +aclProxyAuthDone(void *data, char *result) +{ + aclCheck_t *checklist = data; + checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_DONE; + debug(28, 4) ("aclProxyAuthDone: result = %s\n", result); + if (result && (strncasecmp(result, "OK", 2) == 0)) + checklist->auth_user->passwd_ok = 1; + else + checklist->auth_user->passwd_ok = -1; + aclCheck(checklist); +} + aclCheck_t * aclChecklistCreate(const acl_access * A, request_t * request, @@ -1565,7 +1610,7 @@ aclChecklistCreate(const acl_access * A, const char *ident) { int i; - aclCheck_t *checklist = xcalloc(1, sizeof(aclCheck_t));; + aclCheck_t *checklist = xcalloc(1, sizeof(aclCheck_t)); cbdataAdd(checklist, MEM_NONE); checklist->access_list = A; /* @@ -1582,6 +1627,7 @@ aclChecklistCreate(const acl_access * A, xstrncpy(checklist->browser, user_agent, BROWSERNAMELEN); if (ident) xstrncpy(checklist->ident, ident, USER_IDENT_SZ); + checklist->auth_user = NULL; /* init to NULL */ return checklist; } @@ -1658,7 +1704,6 @@ aclDestroyProxyAuth(acl_proxy_auth * p) hashFreeItems(p->hash, aclFreeProxyAuthUser); hashFreeMemory(p->hash); p->hash = NULL; - safe_free(p->filename); safe_free(p); } @@ -1795,62 +1840,6 @@ aclDomainCompare(const void *data, splayNode * n) #endif /* SPLAY_TREE */ -/* Original ProxyAuth code by Jon Thackray */ -/* Generalized to ACL's by Arjan.deVet */ -static int -aclReadProxyAuth(acl_proxy_auth * p) -{ - struct stat buf; - static char *passwords = NULL; - char *user = NULL; - char *passwd = NULL; - FILE *f = NULL; - if ((squid_curtime - p->last_time) < p->check_interval) - return 1; - if (0 != stat(p->filename, &buf)) { - debug(28, 0) ("aclReadProxyAuth: can't access proxy_auth file %s, turning authentication off\n", p->filename); - return 0; - } - if (buf.st_mtime == p->change_time) { - debug(28, 5) ("aclReadProxyAuth: %s not changed (old=%d,new=%d)\n", - p->filename, (int) p->change_time, (int) buf.st_mtime); - p->last_time = squid_curtime; - return 1; - } - debug(28, 1) ("aclReadProxyAuth: reloading changed proxy authentication file %s\n", p->filename); - p->change_time = buf.st_mtime; - if (NULL != p->hash) { - hashFreeItems(p->hash, aclFreeProxyAuthUser); - hashFreeMemory(p->hash); - } - p->hash = hash_create((HASHCMP *) strcmp, 7921, hash_string); - assert(NULL != p->hash); - passwords = xmalloc((size_t) buf.st_size + 2); - f = fopen(p->filename, "r"); - fread(passwords, (size_t) buf.st_size, 1, f); - *(passwords + buf.st_size) = '\0'; - strcat(passwords, "\n"); - fclose(f); - user = strtok(passwords, ":"); - passwd = strtok(NULL, "\n"); - debug(28, 5) ("aclReadProxyAuth: adding new passwords to hash table\n"); - while (user != NULL) { - if ((int) strlen(user) > 1 && passwd && (int) strlen(passwd) > 1) { - acl_proxy_auth_user *u; - u = memAllocate(MEM_ACL_PROXY_AUTH_USER); - u->user = xstrdup(user); - u->passwd = xstrdup(passwd); - debug(28, 6) ("aclReadProxyAuth: adding %s, %s to hash table\n", user, passwd); - hash_join(p->hash, (hash_link *) u); - } - user = strtok(NULL, ":"); - passwd = strtok(NULL, "\n"); - } - xfree(passwords); - return 1; -} - - /* compare a host and a domain */ #if defined(USE_SPLAY_TREE) @@ -2087,7 +2076,7 @@ aclDumpProxyAuthList(acl_proxy_auth * data) char buf[MAXPATHLEN]; wordlist *w = xcalloc(1, sizeof(wordlist)); assert(data != NULL); - snprintf(buf, sizeof(buf), "%s %d\n", data->filename, data->check_interval); + snprintf(buf, sizeof(buf), "%d\n", data->timeout); w->key = xstrdup(buf); *T = w; T = &w->next; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 25744f0f52..119cb28b11 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.296 1998/08/17 21:35:49 wessels Exp $ + * $Id: cache_cf.cc,v 1.297 1998/08/17 22:04:55 wessels Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -267,6 +267,17 @@ configDoConfigure(void) Config.redirectChildren = DefaultRedirectChildrenMax; } } + if (Config.Program.authenticate) { + if (Config.authenticateChildren < 1) { + Config.authenticateChildren = 0; + safe_free(Config.Program.authenticate); + } else if (Config.authenticateChildren > DefaultAuthenticateChildrenMax) { + debug(3, 0) ("WARNING: authenticate_children was set to a bad value: %d\n", + Config.authenticateChildren); + debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultAuthenticateChildrenMax); + Config.authenticateChildren = DefaultAuthenticateChildrenMax; + } + } if (Config.Accel.host) { snprintf(buf, BUFSIZ, "http://%s:%d", Config.Accel.host, Config.Accel.port); Config2.Accel.prefix = xstrdup(buf); @@ -311,19 +322,21 @@ configDoConfigure(void) requirePathnameExists("unlinkd_program", Config.Program.unlinkd); if (Config.Program.redirect) requirePathnameExists("redirect_program", Config.Program.redirect); + if (Config.Program.authenticate) + requirePathnameExists("authenticate_program", Config.Program.authenticate); requirePathnameExists("Icon Directory", Config.icons.directory); requirePathnameExists("Error Directory", Config.errorDirectory); for (R = Config.Refresh; R; R = R->next) { - if (!R->flags.override_expire) + if (!R->flags.override_expire) continue; - debug(22,1)("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n"); - break; + debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n"); + break; } for (R = Config.Refresh; R; R = R->next) { - if (!R->flags.override_lastmod) + if (!R->flags.override_lastmod) continue; - debug(22,1)("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n"); - break; + debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n"); + break; } } diff --git a/src/cf.data.pre b/src/cf.data.pre index f1d30a68ba..f2170e4ae8 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.96 1998/08/17 21:27:31 wessels Exp $ +# $Id: cf.data.pre,v 1.97 1998/08/17 22:04:56 wessels Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -921,6 +921,47 @@ DOC_START redirect_children 5 DOC_END +NAME: authenticate_program +TYPE: string +LOC: Config.Program.authenticate +DEFAULT: none +DOC_START + Specify the location of the executable for the authenticator. + Such a program reads a line containing "username password" + and replies "OK" or "ERR" in an endless loop. + If you use an authenticator, make sure you have 1 acl of type + proxy_auth. + By default, the authenticator_program is not used. + +authenticate_program @DEFAULT_AUTH_PROGRAM@ +DOC_END + + +NAME: authenticate_options +TYPE: wordlist +LOC: Config.Program.authenticate_options +DEFAULT: none +DOC_START + Command line options for the authenticate program. + +authenticate_options @DEFAULT_PASSWD_FILE@ +DOC_END + + +NAME: authenticate_children +TYPE: int +DEFAULT: 5 +LOC: Config.authenticateChildren +DOC_START + The number of authenticator processes to spawn (default 5). If you + start too few Squid will have to wait for them to process a backlog + of usercode/password verifications, slowing it down. When password + verifications are done via a (slow) network you are likely to need + lots of authenticator processes. + +authenticate_children 5 +DOC_END + COMMENT_START OPTIONS FOR TUNING THE CACHE ----------------------------------------------------------------------------- @@ -1300,17 +1341,22 @@ DOC_START # cache_peer_acl mycache.mydomain.net asexample # cache_peer_acl mycache_mydomain.net !all - acl aclname proxy_auth passwd_file [ refresh ] - # 'passwd_file' is an Apache-style file of passwords for - # authenticated proxy access. Looks like user:password, with - # the password being standard crypt() format. 'refresh' is - # the time in seconds to check for a changes in the file - # (default = 300 secs). When using a proxy_auth ACL in an - # ACL list, make sure it is the *last* in the list and the - # only proxy_auth ACL in the list. NOTE: when a - # Proxy-Authentication header is sent but it is not needed - # during ACL checking the username is NOT logged in - # access.log. + acl aclname proxy_auth [ refresh ] + # Use an EXTERNAL authentication program to check username/password + # combinations (see authenticate_program). + # + # 'timeout' is the time a checked username/password combination + # remains cached (default = 3600 secs). If a wrong password + # is given for a cached user, the user gets removed from the + # username/password cache forcing a revalidation. + # + # When using a proxy_auth ACL in an http_access rule, make sure + # it is the *last* in the list and the only proxy_auth ACL in + # the list. + # + # NOTE: when a Proxy-Authentication header is sent but it is not + # needed during ACL checking the username is NOT logged + # in access.log. acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 @@ -1319,6 +1365,7 @@ acl myexample dst_as 1241 acl SSL_ports port 443 563 acl Dangerous_ports port 7 9 19 acl CONNECT method CONNECT +acl password proxy_auth 300 DOC_END NAME: http_access diff --git a/src/defines.h b/src/defines.h index 9adf6b62b0..4308108a49 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,6 +1,6 @@ /* - * $Id: defines.h,v 1.62 1998/07/22 20:53:54 wessels Exp $ + * $Id: defines.h,v 1.63 1998/08/17 22:04:57 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -53,6 +53,7 @@ #define DefaultDnsChildrenMax 32 /* 32 processes */ #define DefaultRedirectChildrenMax 32 /* 32 processes */ +#define DefaultAuthenticateChildrenMax 32 /* 32 processes */ #define MAXHTTPPORTS 12 #define COMM_OK (0) @@ -150,6 +151,12 @@ #define REDIRECT_PENDING 1 #define REDIRECT_DONE 2 +#define AUTHENTICATE_AV_FACTOR 1000 + +#define AUTHENTICATE_NONE 0 +#define AUTHENTICATE_PENDING 1 +#define AUTHENTICATE_DONE 2 + #define CONNECT_PORT 443 #define current_stacksize(stack) ((stack)->top - (stack)->base) diff --git a/src/enums.h b/src/enums.h index eaff66dfff..38aa578046 100644 --- a/src/enums.h +++ b/src/enums.h @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.117 1998/08/17 19:19:34 wessels Exp $ + * $Id: enums.h,v 1.118 1998/08/17 22:04:58 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -113,7 +113,10 @@ typedef enum { ACL_LOOKUP_NONE, ACL_LOOKUP_NEEDED, ACL_LOOKUP_PENDING, - ACL_LOOKUP_DONE + ACL_LOOKUP_DONE, + ACL_PROXY_AUTH_NEEDED, + ACL_PROXY_AUTH_USED, + ACL_PROXY_AUTH_CHECK } acl_lookup_state; enum { diff --git a/src/main.cc b/src/main.cc index 9acb4e7880..587c780b4a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.268 1998/08/11 20:07:03 wessels Exp $ + * $Id: main.cc,v 1.269 1998/08/17 22:04:59 wessels Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -316,6 +316,7 @@ mainReconfigure(void) #endif dnsShutdownServers(NULL); redirectShutdownServers(NULL); + authenticateShutdownServers(NULL); storeDirCloseSwapLogs(); errorFree(); parseConfigFile(ConfigFile); @@ -325,6 +326,7 @@ mainReconfigure(void) errorInitialize(); /* reload error pages */ dnsOpenServers(); redirectOpenServers(); + authenticateOpenServers(); serverConnectionsOpen(); if (theOutIcpConnection >= 0 && (!Config2.Accel.on || Config.onoff.accel_with_proxy)) neighbors_open(theOutIcpConnection); @@ -400,6 +402,7 @@ mainInitialize(void) fqdncache_init(); dnsOpenServers(); redirectOpenServers(); + authenticateOpenServers(); useragentOpenLog(); httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ httpAnonInitModule(); /* must go before accepting requests */ @@ -567,6 +570,7 @@ main(int argc, char **argv) serverConnectionsClose(); eventAdd("dnsShutdownServers", dnsShutdownServers, NULL, 0.0, 1); eventAdd("redirectShutdownServers", redirectShutdownServers, NULL, 0.0, 1); + eventAdd("authenticateShutdownServers", authenticateShutdownServers, NULL, 0.0, 1); eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1); } eventRun(); diff --git a/src/protos.h b/src/protos.h index fb93f5931e..42d2edcca9 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.248 1998/08/17 16:44:09 wessels Exp $ + * $Id: protos.h,v 1.249 1998/08/17 22:05:01 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -645,6 +645,13 @@ extern void redirectStats(StoreEntry *); extern int redirectUnregister(const char *url, void *); extern void redirectFreeMemory(void); +extern void authenticateStart(acl_proxy_auth_user *, RH *, void *); +extern void authenticateOpenServers(void); +extern void authenticateShutdownServers(void *); +extern void authenticateStats(StoreEntry *); +extern int authenticateUnregister(const char *url, void *); +extern void authenticateFreeMemory(void); + extern void refreshAddToList(const char *, int, time_t, int, time_t); extern int refreshCheck(const StoreEntry *, request_t *, time_t delta); extern time_t refreshWhen(const StoreEntry * entry); diff --git a/src/structs.h b/src/structs.h index 227f13f0a1..656eb35941 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.200 1998/08/17 21:27:33 wessels Exp $ + * $Id: structs.h,v 1.201 1998/08/17 22:05:02 wessels Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -57,10 +57,7 @@ struct _acl_name_list { }; struct _acl_proxy_auth { - char *filename; - time_t last_time; - time_t change_time; - int check_interval; + int timeout; /* timeout value for cached usercode:password entries */ hash_table *hash; }; @@ -68,7 +65,10 @@ struct _acl_proxy_auth_user { /* first two items must be same as hash_link */ char *user; acl_proxy_auth_user *next; + /* extra fields for proxy_auth */ char *passwd; + int passwd_ok; /* 1 = passwd checked OK */ + long expiretime; }; struct _acl_deny_info_list { @@ -170,6 +170,7 @@ struct _aclCheck_t { request_t *request; char ident[USER_IDENT_SZ]; char browser[BROWSERNAMELEN]; + acl_proxy_auth_user *auth_user; acl_lookup_state state[ACL_ENUM_MAX]; PF *callback; void *callback_data; @@ -282,11 +283,14 @@ struct _SquidConfig { struct { char *dnsserver; char *redirect; + char *authenticate; + wordlist *authenticate_options; char *pinger; char *unlinkd; } Program; int dnsChildren; int redirectChildren; + int authenticateChildren; struct { char *host; u_short port; -- 2.47.3