/*
- * $Id: ACL.h,v 1.3 2003/02/12 06:10:58 robertc Exp $
+ * $Id: ACL.h,v 1.4 2003/02/13 08:07:46 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
SQUIDCEXTERN void aclDestroyDenyInfoList(struct _acl_deny_info_list **);
SQUIDCEXTERN void aclDestroyRegexList(struct _relist *data);
SQUIDCEXTERN int aclMatchRegex(relist * data, const char *word);
+wordlist *aclDumpRegexList(relist * data);
SQUIDCEXTERN void aclParseRegexList(void *curlist);
SQUIDCEXTERN wordlist *aclDumpGeneric(const acl *);
SQUIDCEXTERN int aclPurgeMethodInUse(acl_access *);
SQUIDCEXTERN void aclCacheMatchFlush(dlink_list * cache);
-SQUIDCEXTERN int aclAuthenticated(ACLChecklist * checklist);
-void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head);
+extern void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head);
+IPH aclLookupDstIPforASNDone;
+#if USE_IDENT
+IDCB aclLookupIdentDone;
+#endif
+FQDNH aclLookupSrcFQDNDone;
+FQDNH aclLookupDstFQDNDone;
class ACL {
public:
static ACL *Factory (char const *);
static void ParseAclLine(acl ** head);
+ static ACL* FindByName(const char *name);
+
+ /* temporary until we subclass external acl's */
+ static void ExternalAclLookup(ACLChecklist * ch, ACL *, EAH * callback, void *callback_data);
ACL();
ACL (squid_acl const);
virtual wordlist *dumpGeneric() const;
virtual wordlist *dump() const;
virtual bool valid () const;
- virtual void startExternal(ACLChecklist *);
int checklistMatches(ACLChecklist *);
/* only relevant to METHOD acl's */
/* only relecant to ASN acl's */
void startCache();
+ int cacheMatchAcl(dlink_list * cache, ACLChecklist *);
+ virtual int matchForCache(ACLChecklist *checklist);
char name[ACL_NAME_SZ];
char *cfgline;
--- /dev/null
+/*
+ * $Id: ACLChecklist.cc,v 1.1 2003/02/13 08:07:46 robertc Exp $
+ *
+ * DEBUG: section 28 Access Control
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; 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.
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#include "squid.h"
+#include "ACLChecklist.h"
+/* TODO: trim this ! */
+#include "splay.h"
+#include "HttpRequest.h"
+#include "authenticate.h"
+#include "fde.h"
+#include "ACLProxyAuth.h"
+#if USE_IDENT
+#include "ACLIdent.h"
+#endif
+#include "ACLUserData.h"
+
+int
+ACLChecklist::authenticated()
+{
+ http_hdr_type headertype;
+ if (NULL == request) {
+ fatal ("requiresRequest SHOULD have been true for this ACL!!");
+ } else if (!request->flags.accelerated) {
+ /* Proxy authorization on proxy requests */
+ headertype = HDR_PROXY_AUTHORIZATION;
+ } else if (request->flags.internal) {
+ /* WWW authorization on accelerated internal requests */
+ headertype = HDR_AUTHORIZATION;
+ } else {
+#if AUTH_ON_ACCELERATION
+ /* WWW authorization on accelerated requests */
+ headertype = HDR_AUTHORIZATION;
+#else
+ debug(28, 1) ("ACHChecklist::authenticated: authentication not applicable on accelerated requests.\n");
+ return -1;
+#endif
+ }
+ /* get authed here */
+ /* Note: this fills in auth_user_request when applicable */
+ switch (authenticateTryToAuthenticateAndSetAuthUser(&auth_user_request, headertype, request, conn(), src_addr)) {
+ case AUTH_ACL_CANNOT_AUTHENTICATE:
+ debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n");
+ return 0;
+ case AUTH_AUTHENTICATED:
+ return 1;
+ break;
+ case AUTH_ACL_HELPER:
+ debug(28, 4) ("aclMatchAcl: returning 0 sending credentials to helper.\n");
+ changeState (ProxyAuthLookup::Instance());
+ return 0;
+ case AUTH_ACL_CHALLENGE:
+ debug(28, 4) ("aclMatchAcl: returning 0 sending authentication challenge.\n");
+ changeState (ProxyAuthNeeded::Instance());
+ return 0;
+ default:
+ fatal("unexpected authenticateAuthenticate reply\n");
+ return 0;
+ }
+}
+
+allow_t const &
+ACLChecklist::currentAnswer() const
+{
+ return allow_;
+}
+
+void
+ACLChecklist::currentAnswer(allow_t const newAnswer)
+{
+ allow_ = newAnswer;
+}
+
+void
+ACLChecklist::check()
+{
+ /* deny if no rules present */
+ currentAnswer(ACCESS_DENIED);
+ /* NOTE: This holds a cbdata reference to the current access_list
+ * entry, not the whole list.
+ */
+ while (accessList != NULL) {
+ /*
+ * If the _acl_access is no longer valid (i.e. its been
+ * freed because of a reconfigure), then bail on this
+ * access check. For now, return ACCESS_DENIED.
+ */
+ if (!cbdataReferenceValid(accessList)) {
+ cbdataReferenceDone(accessList);
+ break;
+ }
+
+ checkAccessList();
+ if (asyncInProgress())
+ return;
+
+ if (finished()) {
+ /*
+ * We are done. Either the request
+ * is allowed, denied, requires authentication.
+ */
+ debug(28, 3) ("ACLChecklist::check: match found, returning %d\n", currentAnswer());
+ cbdataReferenceDone(accessList); /* A */
+ checkCallback(currentAnswer());
+ /* From here on in, this may be invalid */
+ return;
+ }
+ /*
+ * Reference the next access entry
+ */
+ const acl_access *A = accessList;
+ accessList = cbdataReference(accessList->next);
+ cbdataReferenceDone(A);
+ }
+ /* dropped off the end of the list */
+ debug(28, 3) ("ACLChecklist::check: NO match found, returning %d\n",
+ currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED);
+ checkCallback(currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED);
+}
+
+bool
+ACLChecklist::asyncInProgress() const
+{
+ return async_;
+}
+
+void
+ACLChecklist::asyncInProgress(bool const newAsync)
+{
+ assert (!finished());
+ async_ = newAsync;
+ debug (28,3)("ACLChecklist::asyncInProgress: async set to %d\n",async_);
+}
+
+bool
+ACLChecklist::finished() const
+{
+ return finished_;
+}
+
+void
+ACLChecklist::markFinished()
+{
+ assert (!finished());
+ finished_ = true;
+ debug (28,3)("checklist processing finished\n");
+}
+
+void
+ACLChecklist::checkAccessList()
+{
+ debug(28, 3) ("ACLChecklist::checkAccessList: checking '%s'\n", accessList->cfgline);
+ /* what is our result on a match? */
+ currentAnswer(accessList->allow);
+ /* does the current AND clause match */
+ bool match = matchAclList(accessList->aclList);
+ if (match)
+ markFinished();
+ /* Should be else, but keep the exact same flow as before */
+ checkForAsync();
+}
+
+void
+ACLChecklist::checkForAsync()
+{
+ /* check for async lookups needed. */
+ if (asyncState() != NullState::Instance()) {
+ /* If a state object is here, use it.
+ * When all cases are converted, the if goes away and it
+ * becomes unconditional.
+ * RBC 02 2003
+ */
+ asyncState()->checkForAsync(this);
+ } else if (state[ACL_DST_ASN] == ACL_LOOKUP_NEEDED) {
+ state[ACL_DST_ASN] = ACL_LOOKUP_PENDING;
+ ipcache_nbgethostbyname(request->host,
+ aclLookupDstIPforASNDone, this);
+ asyncInProgress(true);
+ } else if (state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NEEDED) {
+ state[ACL_SRC_DOMAIN] = ACL_LOOKUP_PENDING;
+ fqdncache_nbgethostbyaddr(src_addr,
+ aclLookupSrcFQDNDone, this);
+ asyncInProgress(true);
+ } else if (state[ACL_DST_DOMAIN] == ACL_LOOKUP_NEEDED) {
+ ipcache_addrs *ia;
+ ia = ipcacheCheckNumeric(request->host);
+ if (ia == NULL) {
+ state[ACL_DST_DOMAIN] = ACL_LOOKUP_DONE;
+ } else {
+ dst_addr = ia->in_addrs[0];
+ state[ACL_DST_DOMAIN] = ACL_LOOKUP_PENDING;
+ fqdncache_nbgethostbyaddr(dst_addr,
+ aclLookupDstFQDNDone, this);
+ }
+ asyncInProgress(true);
+#if USE_IDENT
+ } else if (state[ACL_IDENT] == ACL_LOOKUP_NEEDED) {
+ debug(28, 3) ("ACLChecklist::checkForAsync: Doing ident lookup\n");
+ if (conn() && cbdataReferenceValid(conn())) {
+ identStart(&conn()->me, &conn()->peer,
+ aclLookupIdentDone, this);
+ state[ACL_IDENT] = ACL_LOOKUP_PENDING;
+ } else {
+ debug(28, 1) ("ACLChecklist::checkForAsync: Can't start ident lookup. No client connection\n");
+ currentAnswer(ACCESS_DENIED);
+ markFinished();
+ return;
+ }
+ asyncInProgress(true);
+#endif
+ }
+}
+
+void
+ACLChecklist::checkCallback(allow_t answer)
+{
+ PF *callback_;
+ void *cbdata_;
+ debug(28, 3) ("ACLChecklist::checkCallback: answer=%d\n", answer);
+ /* During reconfigure, we can end up not finishing call
+ * sequences into the auth code */
+ if (auth_user_request) {
+ /* the checklist lock */
+ authenticateAuthUserRequestUnlock(auth_user_request);
+ /* it might have been connection based */
+ assert(conn());
+ conn()->auth_user_request = NULL;
+ conn()->auth_type = AUTH_BROKEN;
+ auth_user_request = NULL;
+ }
+ callback_ = callback;
+ callback = NULL;
+ if (cbdataReferenceValidDone(callback_data, &cbdata_))
+ callback_(answer, cbdata_);
+ delete this;
+}
+bool
+ACLChecklist::matchAclList(const acl_list * head)
+{
+ PROF_start(aclMatchAclList);
+ const acl_list *node = head;
+ while (node) {
+ if (!node->matches(this)) {
+ debug(28, 3) ("aclmatchAclList: returning false (AND list entry failed to match)\n");
+ PROF_stop(aclMatchAclList);
+ return false;
+ }
+ node = node->next;
+ }
+ debug(28, 3) ("aclmatchAclList: returning true (AND list satisfied)\n");
+ PROF_stop(aclMatchAclList);
+ return true;
+}
+
+CBDATA_CLASS_INIT(ACLChecklist);
+
+void *
+ACLChecklist::operator new (size_t size)
+{
+ assert (size == sizeof(ACLChecklist));
+ CBDATA_INIT_TYPE(ACLChecklist);
+ ACLChecklist *result = cbdataAlloc(ACLChecklist);
+ /* Mark result as being owned - we want the refcounter to do the delete
+ * call */
+ cbdataReference(result);
+ return result;
+}
+
+void
+ACLChecklist::operator delete (void *address)
+{
+ ACLChecklist *t = static_cast<ACLChecklist *>(address);
+ cbdataFree(address);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (t);
+}
+
+void
+ACLChecklist::deleteSelf() const
+{
+ delete this;
+}
+
+ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL),
+ reply (NULL),
+ auth_user_request (NULL)
+#if SQUID_SNMP
+ ,snmp_community(NULL)
+#endif
+ , callback (NULL),
+ callback_data (NULL),
+ extacl_entry (NULL),
+ conn_(NULL),
+ async_(false),
+ finished_(false),
+ allow_(ACCESS_DENIED),
+ state_(NullState::Instance())
+{
+ memset (&src_addr, '\0', sizeof (struct in_addr));
+ memset (&dst_addr, '\0', sizeof (struct in_addr));
+ memset (&my_addr, '\0', sizeof (struct in_addr));
+ rfc931[0] = '\0';
+ memset (&state, '\0', sizeof (state));
+}
+
+ACLChecklist::~ACLChecklist()
+{
+ assert (!asyncInProgress());
+ if (extacl_entry)
+ cbdataReferenceDone(extacl_entry);
+ if (request)
+ requestUnlink(request);
+ request = NULL;
+ cbdataReferenceDone(conn_);
+ cbdataReferenceDone(accessList);
+}
+
+
+ConnStateData *
+ACLChecklist::conn()
+{
+ return conn_;
+}
+
+void
+ACLChecklist::conn(ConnStateData *aConn)
+{
+ assert (conn() == NULL);
+ conn_ = aConn;
+}
+
+void
+ACLChecklist::AsyncState::changeState (ACLChecklist *checklist, AsyncState *newState) const
+{
+ checklist->changeState(newState);
+}
+
+ACLChecklist::NullState *
+ACLChecklist::NullState::Instance()
+{
+ return &_instance;
+}
+
+void
+ACLChecklist::NullState::checkForAsync(ACLChecklist *) const
+{
+}
+
+ACLChecklist::NullState ACLChecklist::NullState::_instance;
+
+void
+ACLChecklist::changeState (AsyncState *newState)
+{
+ /* only change from null to active and back again,
+ * not active to active.
+ * relax this once conversion to states is complete
+ * RBC 02 2003
+ */
+ assert (state_ == NullState::Instance() || newState == NullState::Instance());
+ state_ = newState;
+}
+
+ACLChecklist::AsyncState *
+ACLChecklist::asyncState() const
+{
+ return state_;
+}
+
+void
+ACLChecklist::nonBlockingCheck(PF * callback_, void *callback_data_)
+{
+ callback = callback_;
+ callback_data = cbdataReference(callback_data_);
+ check();
+}
+
/*
- * $Id: ACLChecklist.h,v 1.2 2003/02/12 06:10:58 robertc Exp $
+ * $Id: ACLChecklist.h,v 1.3 2003/02/13 08:07:46 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
ACLChecklist (ACLChecklist const &);
ACLChecklist &operator=(ACLChecklist const &);
+ void nonBlockingCheck(PF * callback, void *callback_data);
void checkCallback(allow_t answer);
- int matchAclList(const acl_list * list);
+ bool matchAclList(const acl_list * list);
ConnStateData *conn();
void conn(ConnStateData *);
+ int authenticated();
bool asyncInProgress() const;
void asyncInProgress(bool const);
SQUIDCEXTERN ACLChecklist *aclChecklistCreate(const acl_access *,
request_t *,
const char *ident);
-SQUIDCEXTERN void aclNBCheck(ACLChecklist *, PF *, void *);
SQUIDCEXTERN int aclCheckFast(const acl_access *A, ACLChecklist *);
#endif /* SQUID_ACLCHECKLIST_H */
--- /dev/null
+
+/*
+ * $Id: ACLData.h,v 1.1 2003/02/13 08:07:47 robertc Exp $
+ *
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; 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.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#ifndef SQUID_ACLDATA_H
+#define SQUID_ACLDATA_H
+
+class ACLData {
+ public:
+ virtual void deleteSelf() const =0;
+
+ virtual ~ACLData() {}
+ virtual bool match(char const *user) =0;
+ virtual wordlist *dump() =0;
+ virtual void parse() =0;
+ virtual ACLData *clone() const =0;
+};
+
+#endif /* SQUID_ACLDATA_H */
delete this;
}
-acl_ip_data::acl_ip_data () :addr1(no_addr), addr2(no_addr), mask (no_addr), next (NULL) {}
+acl_ip_data::acl_ip_data () :addr1(any_addr), addr2(any_addr), mask (any_addr), next (NULL) {}
acl_ip_data::acl_ip_data (struct in_addr const &anAddress1, struct in_addr const &anAddress2, struct in_addr const &aMask, acl_ip_data *aNext) : addr1(anAddress1), addr2(anAddress2), mask(aMask), next(aNext){}
#include "ACLProxyAuth.h"
#include "authenticate.h"
#include "ACLChecklist.h"
+#include "ACLUserData.h"
+#include "ACLRegexData.h"
MemPool *ACLProxyAuth::Pool(NULL);
void *
ACLProxyAuth::~ACLProxyAuth()
{
- delete data;
+ data->deleteSelf();
+}
+
+ACLProxyAuth::ACLProxyAuth(ACLData *newData) : data (newData) {}
+ACLProxyAuth::ACLProxyAuth (ACLProxyAuth const &old) : data (old.data->clone())
+{
+}
+ACLProxyAuth &
+ACLProxyAuth::operator= (ACLProxyAuth const &rhs)
+{
+ data = rhs.data->clone();
+ return *this;
}
char const *
if (authenticateSchemeCount() == 0) {
debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' "
"because no authentication schemes were compiled.\n", cfgline);
- } else if (authenticateActiveSchemeCount() == 0) {
+ return;
+ }
+ if (authenticateActiveSchemeCount() == 0) {
debug(28, 0) ("aclProxyAuth::parse: IGNORING: Proxy Auth ACL '%s' "
"because no authentication schemes are fully configured.\n", cfgline);
- } else {
- debug(28, 3) ("aclParseUserList: current is null. Creating\n");
- data = new ACLUserData;
- data->parse();
+ return;
}
+ data->parse();
}
-extern int
-aclMatchProxyAuth(void *data, auth_user_request_t * auth_user_request,
- ACLChecklist * checklist, squid_acl acltype);
int
ACLProxyAuth::match(ACLChecklist *checklist)
{
int ti;
- if ((ti = aclAuthenticated(checklist)) != 1)
+ if ((ti = checklist->authenticated()) != 1)
return ti;
- ti = aclMatchProxyAuth(data, checklist->auth_user_request,
- checklist, aclType());
- checklist->auth_user_request = NULL;
+ ti = matchProxyAuth(checklist);
return ti;
}
{
return data != NULL;
}
+
+ProxyAuthNeeded ProxyAuthNeeded::instance_;
+
+ProxyAuthNeeded *
+ProxyAuthNeeded::Instance()
+{
+ return &instance_;
+}
+
+ProxyAuthLookup ProxyAuthLookup::instance_;
+
+ProxyAuthLookup *
+ProxyAuthLookup::Instance()
+{
+ return &instance_;
+}
+
+void
+ProxyAuthLookup::checkForAsync(ACLChecklist *checklist)const
+{
+ checklist->asyncInProgress(true);
+ debug(28, 3)
+ ("ACLChecklist::checkForAsync: checking password via authenticator\n");
+
+ auth_user_request_t *auth_user_request;
+ /* make sure someone created auth_user_request for us */
+ assert(checklist->auth_user_request != NULL);
+ auth_user_request = checklist->auth_user_request;
+
+ assert(authenticateValidateUser(auth_user_request));
+ authenticateStart(auth_user_request, LookupDone, checklist);
+}
+
+void
+ProxyAuthLookup::LookupDone(void *data, char *result)
+{
+ ACLChecklist *checklist = (ACLChecklist *)data;
+ assert (checklist->asyncState() == ProxyAuthLookup::Instance());
+
+ if (result != NULL)
+ fatal("AclLookupProxyAuthDone: Old code floating around somewhere.\nMake clean and if that doesn't work, report a bug to the squid developers.\n");
+ if (!authenticateValidateUser(checklist->auth_user_request) || checklist->conn() == NULL) {
+ /* credentials could not be checked either way
+ * restart the whole process */
+ /* OR the connection was closed, there's no way to continue */
+ authenticateAuthUserRequestUnlock(checklist->auth_user_request);
+ if (checklist->conn()) {
+ checklist->conn()->auth_user_request = NULL;
+ checklist->conn()->auth_type = AUTH_BROKEN;
+ }
+ checklist->auth_user_request = NULL;
+ }
+ checklist->asyncInProgress(false);
+ checklist->changeState (ACLChecklist::NullState::Instance());
+ checklist->check();
+}
+
+void
+ProxyAuthNeeded::checkForAsync(ACLChecklist *checklist) const
+{
+ /* Client is required to resend the request with correct authentication
+ * credentials. (This may be part of a stateful auth protocol.)
+ * The request is denied.
+ */
+ debug(28, 6) ("ACLChecklist::checkForAsync: requiring Proxy Auth header.\n");
+ checklist->currentAnswer(ACCESS_REQ_PROXY_AUTH);
+ checklist->markFinished();
+}
+
+ACL::Prototype ACLProxyAuth::UserRegistryProtoype(&ACLProxyAuth::UserRegistryEntry_, "proxy_auth");
+ACLProxyAuth ACLProxyAuth::UserRegistryEntry_(new ACLUserData);
+ACL::Prototype ACLProxyAuth::RegexRegistryProtoype(&ACLProxyAuth::RegexRegistryEntry_, "proxy_auth_regex");
+ACLProxyAuth ACLProxyAuth::RegexRegistryEntry_(new ACLRegexData);
+
+ACL *
+ACLProxyAuth::clone() const
+{
+ return new ACLProxyAuth(*this);
+}
+
+int
+ACLProxyAuth::matchForCache(ACLChecklist *checklist)
+{
+ return data->match(authenticateUserRequestUsername(checklist->auth_user_request));
+}
+
+/* aclMatchProxyAuth can return two exit codes:
+ * 0 : Authorisation for this ACL failed. (Did not match)
+ * 1 : Authorisation OK. (Matched)
+ */
+int
+ACLProxyAuth::matchProxyAuth(ACLChecklist *checklist)
+{
+ checkAuthForCaching(checklist);
+ /* check to see if we have matched the user-acl before */
+ int result = cacheMatchAcl(&checklist->auth_user_request->auth_user->
+ proxy_match_cache, checklist);
+ checklist->auth_user_request = NULL;
+ return result;
+}
+
+void
+ACLProxyAuth::checkAuthForCaching(ACLChecklist *checklist)const
+{
+ /* for completeness */
+ authenticateAuthUserRequestLock(checklist->auth_user_request);
+ /* consistent parameters ? */
+ assert(authenticateUserAuthenticated(checklist->auth_user_request));
+ /* this check completed */
+ authenticateAuthUserRequestUnlock(checklist->auth_user_request);
+}
+
#ifndef SQUID_ACLPROXYAUTH_H
#define SQUID_ACLPROXYAUTH_H
#include "ACL.h"
-#include "ACLUserData.h"
+#include "ACLData.h"
+#include "ACLChecklist.h"
+
+class ProxyAuthLookup : public ACLChecklist::AsyncState {
+ public:
+ static ProxyAuthLookup *Instance();
+ virtual void checkForAsync(ACLChecklist *)const;
+ private:
+ static ProxyAuthLookup instance_;
+ static void LookupDone(void *data, char *result);
+};
+
+class ProxyAuthNeeded : public ACLChecklist::AsyncState {
+ public:
+ static ProxyAuthNeeded *Instance();
+ virtual void checkForAsync(ACLChecklist *)const;
+ private:
+ static ProxyAuthNeeded instance_;
+};
class ACLProxyAuth : public ACL {
public:
virtual void deleteSelf() const;
~ACLProxyAuth();
+ ACLProxyAuth(ACLData *);
+ ACLProxyAuth (ACLProxyAuth const &);
+ ACLProxyAuth &operator= (ACLProxyAuth const &);
virtual char const *typeString() const;
- virtual squid_acl aclType() const { return ACL_PROXY_AUTH;}
+ virtual squid_acl aclType() const { return ACL_DERIVED;}
virtual void parse();
virtual bool isProxyAuth() const {return true;}
virtual int match(ACLChecklist *checklist);
virtual wordlist *dump() const;
virtual bool valid () const;
+ virtual bool requiresRequest() const {return true;}
+ virtual ACL *clone()const;
+ virtual int matchForCache(ACLChecklist *checklist);
private:
static MemPool *Pool;
- ACLUserData *data;
+ static Prototype UserRegistryProtoype;
+ static ACLProxyAuth UserRegistryEntry_;
+ static Prototype RegexRegistryProtoype;
+ static ACLProxyAuth RegexRegistryEntry_;
+ int matchProxyAuth(ACLChecklist *);
+ void checkAuthForCaching(ACLChecklist *) const;
+ ACLData *data;
};
#endif /* SQUID_ACLPROXYAUTH_H */
--- /dev/null
+/*
+ * $Id: ACLRegexData.cc,v 1.1 2003/02/13 08:07:47 robertc Exp $
+ *
+ * DEBUG: section 28 Access Control
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; 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.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#include "squid.h"
+#include "ACLRegexData.h"
+#include "authenticate.h"
+#include "ACLChecklist.h"
+#include "ACL.h"
+
+MemPool *ACLRegexData::Pool(NULL);
+void *
+ACLRegexData::operator new (size_t byteCount)
+{
+ /* derived classes with different sizes must implement their own new */
+ assert (byteCount == sizeof (ACLRegexData));
+ if (!Pool)
+ Pool = memPoolCreate("ACLRegexData", sizeof (ACLRegexData));
+ return memPoolAlloc(Pool);
+}
+
+void
+ACLRegexData::operator delete (void *address)
+{
+ memPoolFree (Pool, address);
+}
+
+void
+ACLRegexData::deleteSelf() const
+{
+ delete this;
+}
+
+ACLRegexData::~ACLRegexData()
+{
+ aclDestroyRegexList(data);
+}
+
+bool
+ACLRegexData::match(char const *user)
+{
+ return aclMatchRegex(data, user);
+}
+
+wordlist *
+ACLRegexData::dump()
+{
+ return aclDumpRegexList(data);
+}
+
+void
+ACLRegexData::parse()
+{
+ aclParseRegexList(&data);
+}
+
+
+ACLData *
+ACLRegexData::clone() const
+{
+ /* Regex's don't clone yet. */
+ assert (!data);
+ return new ACLRegexData;
+}
--- /dev/null
+
+/*
+ * $Id: ACLRegexData.h,v 1.1 2003/02/13 08:07:47 robertc Exp $
+ *
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; 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.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#ifndef SQUID_ACLREGEXDATA_H
+#define SQUID_ACLREGEXDATA_H
+#include "ACLData.h"
+
+class ACLRegexData : public ACLData {
+ public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ virtual void deleteSelf() const;
+
+ virtual ~ACLRegexData();
+ virtual bool match(char const *user);
+ virtual wordlist *dump();
+ virtual void parse();
+ virtual ACLData *clone() const;
+ private:
+ static MemPool *Pool;
+ relist *data;
+};
+
+#endif /* SQUID_ACLREGEXDATA_H */
names = names->insert(xstrdup(t), splaystrcmp);
}
}
+
+
+ACLUserData *
+ACLUserData::clone() const
+{
+ /* Splay trees don't clone yet. */
+ assert (!names);
+ return new ACLUserData;
+}
#define SQUID_ACLUSERDATA_H
#include "splay.h"
#include "ACL.h"
+#include "ACLData.h"
-class ACLUserData {
+class ACLUserData : public ACLData {
public:
void *operator new(size_t);
void operator delete(void *);
bool match(char const *user);
wordlist *dump();
void parse();
+ virtual ACLUserData *clone() const;
SplayNode<char *> *names;
struct {
--- /dev/null
+
+/*
+ * $Id: ExternalACL.h,v 1.1 2003/02/13 08:07:47 robertc Exp $
+ *
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; 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.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#ifndef SQUID_EXTERNALACL_H
+#define SQUID_EXTERNALACL_H
+#include "ACLChecklist.h"
+class ExternalACLLookup : public ACLChecklist::AsyncState {
+ public:
+ static ExternalACLLookup *Instance();
+ virtual void checkForAsync(ACLChecklist *)const;
+ private:
+ static ExternalACLLookup instance_;
+ static void LookupDone(void *data, void *result);
+};
+#endif /* SQUID_EXTERNALACL_H */
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.am,v 1.57 2003/02/12 06:10:58 robertc Exp $
+# $Id: Makefile.am,v 1.58 2003/02/13 08:07:47 robertc Exp $
#
# Uncomment and customize the following to suit your needs:
#
win32.cc
squid_ACLSOURCES = \
+ ACLData.h \
ACLDestinationIP.cc \
ACLDestinationIP.h \
ACLIP.cc \
ACLMyIP.h \
ACLProxyAuth.cc \
ACLProxyAuth.h \
+ ACLRegexData.cc \
+ ACLRegexData.h \
ACLSourceIP.cc \
ACLSourceIP.h \
ACLUserData.cc \
access_log.cc \
acl.cc \
ACL.h \
+ ACLChecklist.cc \
ACLChecklist.h \
$(squid_ACLSOURCES) \
asn.cc \
ETag.cc \
event.cc \
external_acl.cc \
+ ExternalACL.h \
fd.cc \
fde.cc \
fde.h \
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.285 2003/02/12 06:23:39 robertc Exp $
+# $Id: Makefile.in,v 1.286 2003/02/13 08:07:47 robertc Exp $
#
# Uncomment and customize the following to suit your needs:
#
squid_ACLSOURCES = \
+ ACLData.h \
ACLDestinationIP.cc \
ACLDestinationIP.h \
ACLIP.cc \
ACLMyIP.h \
ACLProxyAuth.cc \
ACLProxyAuth.h \
+ ACLRegexData.cc \
+ ACLRegexData.h \
ACLSourceIP.cc \
ACLSourceIP.h \
ACLUserData.cc \
access_log.cc \
acl.cc \
ACL.h \
+ ACLChecklist.cc \
ACLChecklist.h \
$(squid_ACLSOURCES) \
asn.cc \
ETag.cc \
event.cc \
external_acl.cc \
+ ExternalACL.h \
fd.cc \
fde.cc \
fde.h \
/*
- * $Id: acl.cc,v 1.301 2003/02/12 06:10:58 robertc Exp $
+ * $Id: acl.cc,v 1.302 2003/02/13 08:07:47 robertc Exp $
*
* DEBUG: section 28 Access Control
* AUTHOR: Duane Wessels
#include "HttpRequest.h"
#include "authenticate.h"
#include "fde.h"
-#include "ACLProxyAuth.h"
#if USE_IDENT
#include "ACLIdent.h"
#endif
#include "ACLUserData.h"
+#include "ExternalACL.h"
static void aclParseDomainList(void *curlist);
static void aclParseIntlist(void *curlist);
static void aclParseIntRange(void *curlist);
static void aclDestroyTimeList(acl_time_data * data);
static void aclDestroyIntRange(intrange *);
-static void aclLookupProxyAuthStart(ACLChecklist * checklist);
-static void aclLookupProxyAuthDone(void *data, char *result);
-static acl*aclFindByName(const char *name);
static int aclMatchTime(acl_time_data * data, time_t when);
static int aclMatchDomainList(void *dataptr, const char *);
static int aclMatchIntegerRange(intrange * data, int i);
static wordlist *aclDumpUserMaxIP(void *data);
static int aclMatchUserMaxIP(void *, auth_user_request_t *, struct in_addr);
static squid_acl aclStrToType(const char *s);
-#if USE_IDENT
-static IDCB aclLookupIdentDone;
-#endif
-static IPH aclLookupDstIPforASNDone;
-static FQDNH aclLookupSrcFQDNDone;
-static FQDNH aclLookupDstFQDNDone;
-static EAH aclLookupExternalDone;
+IPH aclLookupDstIPforASNDone;
static wordlist *aclDumpDomainList(void *data);
static wordlist *aclDumpTimeSpecList(acl_time_data *);
-static wordlist *aclDumpRegexList(relist * data);
static wordlist *aclDumpIntlistList(intlist * data);
static wordlist *aclDumpIntRangeList(intrange * data);
static wordlist *aclDumpProtoList(intlist * data);
static splayNode::SPLAYCMP aclArpCompare;
static splayNode::SPLAYWALKEE aclDumpArpListWalkee;
#endif
-static int aclCacheMatchAcl(dlink_list * cache, squid_acl acltype, void *data, char const *MatchParam);
#if USE_SSL
static void aclParseCertList(void *curlist);
static int aclMatchUserCert(void *data, ACLChecklist *);
return ACL_BROWSER;
if (!strcmp(s, "referer_regex"))
return ACL_REFERER_REGEX;
- if (!strcmp(s, "proxy_auth"))
- return ACL_PROXY_AUTH;
- if (!strcmp(s, "proxy_auth_regex"))
- return ACL_PROXY_AUTH_REGEX;
if (!strcmp(s, "src_as"))
return ACL_SRC_ASN;
if (!strcmp(s, "dst_as"))
return "browser";
if (type == ACL_REFERER_REGEX)
return "referer_regex";
- if (type == ACL_PROXY_AUTH_REGEX)
- return "proxy_auth_regex";
if (type == ACL_SRC_ASN)
return "src_as";
if (type == ACL_DST_ASN)
return "ERROR";
}
-static acl *
-aclFindByName(const char *name)
+acl *
+ACL::FindByName(const char *name)
{
acl *a;
for (a = Config.aclList; a; a = a->next)
result = new ACLIdent;
break;
#endif
- case ACL_PROXY_AUTH:
- result = new ACLProxyAuth;
- break;
case ACL_DST_DOMAIN:
case ACL_SRC_DOMAIN:
case ACL_DST_DOM_REGEX:
case ACL_METHOD:
case ACL_BROWSER:
case ACL_REFERER_REGEX:
- case ACL_PROXY_AUTH_REGEX:
case ACL_SRC_ASN:
case ACL_DST_ASN:
#if SQUID_SNMP
debug(28, 0) ("aclParseAclLine: Invalid ACL type '%s'\n", t);
return;
}
- if ((A = aclFindByName(aclname)) == NULL) {
+ if ((A = FindByName(aclname)) == NULL) {
debug(28, 3) ("aclParseAclLine: Creating ACL '%s'\n", aclname);
A = ACL::Factory(t);
xstrncpy(A->name, aclname, ACL_NAME_SZ);
case ACL_IDENT:
#endif
case ACL_DERIVED:
- case ACL_PROXY_AUTH:
- fatal ("unused");
- break;
- case ACL_PROXY_AUTH_REGEX:
- if (authenticateSchemeCount() == 0) {
- debug(28, 0) ("aclParseAclLine: IGNORING: Proxy Auth ACL '%s' \
-because no authentication schemes were compiled.\n", cfgline);
- } else if (authenticateActiveSchemeCount() == 0) {
- debug(28, 0) ("aclParseAclLine: IGNORING: Proxy Auth ACL '%s' \
-because no authentication schemes are fully configured.\n", cfgline);
- } else {
- aclParseRegexList(&data);
- }
+ fatal ("overriden");
break;
#if SQUID_SNMP
case ACL_SNMP_COMMUNITY:
if (NULL == name)
return false;
acl *a;
- if ((a = aclFindByName(name)))
+ if ((a = ACL::FindByName(name)))
return a->isProxyAuth();
return false;
}
bool
ACL::isProxyAuth() const
{
- return aclType() == ACL_PROXY_AUTH_REGEX;
+ return false;
}
/* maex@space.net (05.09.96)
t++;
}
debug(28, 3) ("aclParseAccessLine: looking for ACL name '%s'\n", t);
- a = aclFindByName(t);
+ a = ACL::FindByName(t);
if (a == NULL) {
debug(28, 0) ("%s line %d: %s\n",
cfg_filename, config_lineno, config_input_line);
/* ACL result caching routines */
+int
+ACL::matchForCache(ACLChecklist *checklist)
+{
+ /* This is a fatal to ensure that cacheMatchAcl calls are _only_
+ * made for supported acl types */
+ fatal("aclCacheMatchAcl: unknown or unexpected ACL type");
+ return 0; /* NOTREACHED */
+}
+
/*
* we lookup an acl's cached results, and if we cannot find the acl being
- * checked we check it and cache the result. This function is deliberatly
- * generic to support caching of multiple acl types (but it needs to be more
- * generic still....
- * The Match Param and the cache MUST be tied together by the calling routine.
- * You have been warned :-]
- * Also only Matchxxx that are of the form (void *, void *) can be used.
- * probably some ugly overloading _could_ be done but I'll leave that as an
- * exercise for the reader. Note that caching of time based acl's is not
- * wise due to no expiry occuring to the cache entries until the user expires
- * or a reconfigure takes place.
+ * checked we check it and cache the result. This function is a template
+ * method to support caching of multiple acl types.
+ * Note that caching of time based acl's is not
+ * wise in long lived caches (i.e. the auth_user proxy match cache.
* RBC
*/
-static int
-aclCacheMatchAcl(dlink_list * cache, squid_acl acltype, void *data,
- char const *MatchParam)
+int
+ACL::cacheMatchAcl(dlink_list * cache, ACLChecklist *checklist)
{
- int matchrv;
acl_proxy_auth_match_cache *auth_match;
dlink_node *link;
link = cache->head;
while (link) {
auth_match = (acl_proxy_auth_match_cache *)link->data;
- if (auth_match->acl_data == data) {
- debug(28, 4) ("aclCacheMatchAcl: cache hit on acl '%p'\n", data);
+ if (auth_match->acl_data == this) {
+ debug(28, 4) ("ACL::cacheMatchAcl: cache hit on acl '%p'\n", this);
return auth_match->matchrv;
}
link = link->next;
}
auth_match = NULL;
- /* match the user in the acl. They are not cached. */
- switch (acltype) {
- case ACL_PROXY_AUTH:
- matchrv = ((ACLUserData *)data)->match(MatchParam);
- break;
- case ACL_PROXY_AUTH_REGEX:
- matchrv = aclMatchRegex((relist *)data, MatchParam);
- break;
- default:
- /* This is a fatal to ensure that aclCacheMatchAcl calls are _only_
- * made for supported acl types */
- fatal("aclCacheMatchAcl: unknown or unexpected ACL type");
- return 0; /* NOTREACHED */
- }
auth_match = (acl_proxy_auth_match_cache *)memAllocate(MEM_ACL_PROXY_AUTH_MATCH);
- auth_match->matchrv = matchrv;
- auth_match->acl_data = data;
+ auth_match->matchrv = matchForCache (checklist);
+ auth_match->acl_data = this;
dlinkAddTail(auth_match, &auth_match->link, cache);
- return matchrv;
+ return auth_match->matchrv;
}
void
}
}
-/* aclMatchProxyAuth can return two exit codes:
- * 0 : Authorisation for this ACL failed. (Did not match)
- * 1 : Authorisation OK. (Matched)
- */
-int
-aclMatchProxyAuth(void *data, auth_user_request_t * auth_user_request,
- ACLChecklist * checklist, squid_acl acltype)
-{
- /* checklist is used to register user name when identified, nothing else */
- /* 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
- */
-
- /* for completeness */
- authenticateAuthUserRequestLock(auth_user_request);
-
- /* consistent parameters ? */
- assert(authenticateUserAuthenticated(auth_user_request));
- /* this ACL check completed */
- authenticateAuthUserRequestUnlock(auth_user_request);
- /* check to see if we have matched the user-acl before */
- return aclCacheMatchAcl(&auth_user_request->auth_user->
- proxy_match_cache, acltype, data,
- authenticateUserRequestUsername(auth_user_request));
-}
CBDATA_TYPE(acl_user_ip_data);
return 1;
}
-static void
-aclLookupProxyAuthStart(ACLChecklist * checklist)
-{
- auth_user_request_t *auth_user_request;
- /* make sure someone created auth_user_request for us */
- assert(checklist->auth_user_request != NULL);
- auth_user_request = checklist->auth_user_request;
-
- assert(authenticateValidateUser(auth_user_request));
- authenticateStart(auth_user_request, aclLookupProxyAuthDone, checklist);
-}
-
static int
aclMatchInteger(intlist * data, int i)
{
}
#endif
-int
-aclAuthenticated(ACLChecklist * checklist)
-{
- request_t *r = checklist->request;
- http_hdr_type headertype;
- if (NULL == r) {
- return -1;
- } else if (!r->flags.accelerated) {
- /* Proxy authorization on proxy requests */
- headertype = HDR_PROXY_AUTHORIZATION;
- } else if (r->flags.internal) {
- /* WWW authorization on accelerated internal requests */
- headertype = HDR_AUTHORIZATION;
- } else {
-#if AUTH_ON_ACCELERATION
- /* WWW authorization on accelerated requests */
- headertype = HDR_AUTHORIZATION;
-#else
- debug(28, 1) ("aclAuthenticated: authentication not applicable on accelerated requests.\n");
- return -1;
-#endif
- }
- /* get authed here */
- /* Note: this fills in checklist->auth_user_request when applicable */
- switch (authenticateTryToAuthenticateAndSetAuthUser(&checklist->auth_user_request, headertype, checklist->request, checklist->conn(), checklist->src_addr)) {
- case AUTH_ACL_CANNOT_AUTHENTICATE:
- debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n");
- return 0;
- case AUTH_AUTHENTICATED:
- return 1;
- break;
- case AUTH_ACL_HELPER:
- debug(28, 4) ("aclMatchAcl: returning 0 sending credentials to helper.\n");
- checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_NEEDED;
- return 0;
- case AUTH_ACL_CHALLENGE:
- debug(28, 4) ("aclMatchAcl: returning 0 sending authentication challenge.\n");
- checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_NEEDED;
- return 0;
- default:
- fatal("unexpected authenticateAuthenticate reply\n");
- return -1;
- }
-}
bool
ACL::requiresRequest() const
case ACL_MAX_USER_IP:
case ACL_METHOD:
case ACL_PROTO:
- case ACL_PROXY_AUTH:
- case ACL_PROXY_AUTH_REGEX:
case ACL_REP_MIME_TYPE:
case ACL_REQ_MIME_TYPE:
case ACL_URLPATH_REGEX:
return 0;
return aclMatchRegex((relist *)data, header);
/* NOTREACHED */
- case ACL_PROXY_AUTH_REGEX:
- if ((ti = aclAuthenticated(checklist)) != 1)
- return ti;
- ti = aclMatchProxyAuth(data, checklist->auth_user_request,
- checklist, aclType());
- checklist->auth_user_request = NULL;
- return ti;
- /* NOTREACHED */
case ACL_MAX_USER_IP:
- if ((ti = aclAuthenticated(checklist)) != 1)
+ if ((ti = checklist->authenticated()) != 1)
return ti;
ti = aclMatchUserMaxIP(data, checklist->auth_user_request,
checklist->src_addr);
case ACL_IDENT:
#endif
case ACL_DERIVED:
- case ACL_PROXY_AUTH:
fatal ("overridden");
}
debug(28, 0) ("aclMatchAcl: '%s' has bad type %d\n",
return true;
}
-int
-ACLChecklist::matchAclList(const acl_list * head)
-{
- PROF_start(aclMatchAclList);
- const acl_list *node = head;
- while (node) {
- if (!node->matches(this)) {
- debug(28, 3) ("aclmatchAclList: returning 0 (AND list entry failed to match)\n");
- PROF_stop(aclMatchAclList);
- return 0;
- }
- node = node->next;
- }
- debug(28, 3) ("aclmatchAclList: returning 1 (AND list satisfied)\n");
- PROF_stop(aclMatchAclList);
- return 1;
-}
-
/* Warning: do not cbdata lock checklist here - it
* may be static or on the stack
*/
return allow == ACCESS_DENIED;
}
-allow_t const &
-ACLChecklist::currentAnswer() const
-{
- return allow_;
-}
-
-void
-ACLChecklist::currentAnswer(allow_t const newAnswer)
-{
- allow_ = newAnswer;
-}
-
-void
-ACLChecklist::check()
-{
- /* deny if no rules present */
- currentAnswer(ACCESS_DENIED);
- /* NOTE: This holds a cbdata reference to the current access_list
- * entry, not the whole list.
- */
- while (accessList != NULL) {
- /*
- * If the _acl_access is no longer valid (i.e. its been
- * freed because of a reconfigure), then bail on this
- * access check. For now, return ACCESS_DENIED.
- */
- if (!cbdataReferenceValid(accessList)) {
- cbdataReferenceDone(accessList);
- break;
- }
-
- checkAccessList();
- if (asyncInProgress())
- return;
-
- if (finished()) {
- /*
- * We are done. Either the request
- * is allowed, denied, requires authentication.
- */
- debug(28, 3) ("ACLChecklist::check: match found, returning %d\n", currentAnswer());
- cbdataReferenceDone(accessList); /* A */
- checkCallback(currentAnswer());
- /* From here on in, this may be invalid */
- return;
- }
- /*
- * Reference the next access entry
- */
- const acl_access *A = accessList;
- accessList = cbdataReference(accessList->next);
- cbdataReferenceDone(A);
- }
- /* dropped off the end of the list */
- debug(28, 3) ("ACLChecklist::check: NO match found, returning %d\n",
- currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED);
- checkCallback(currentAnswer() != ACCESS_DENIED ? ACCESS_DENIED : ACCESS_ALLOWED);
-}
-
-bool
-ACLChecklist::asyncInProgress() const
-{
- return async_;
-}
-
-void
-ACLChecklist::asyncInProgress(bool const newAsync)
-{
- assert (!finished());
- async_ = newAsync;
- debug (28,3)("ACLChecklist::asyncInProgress: async set to %d\n",async_);
-}
-
-bool
-ACLChecklist::finished() const
-{
- return finished_;
-}
-
-void
-ACLChecklist::markFinished()
-{
- assert (!finished());
- finished_ = true;
- debug (28,3)("checklist processing finished\n");
-}
-
-void
-ACLChecklist::checkAccessList()
-{
- debug(28, 3) ("ACLChecklist::checkAccessList: checking '%s'\n", accessList->cfgline);
- /* what is our result on a match? */
- currentAnswer(accessList->allow);
- /* does the current AND clause match */
- int match = matchAclList(accessList->aclList);
- if (match)
- markFinished();
- /* Should be else, but keep the exact same flow as before */
- checkForAsync();
-}
-
-void
-ACLChecklist::checkForAsync()
-{
- /* TODO: introduce a state object, with states:
- * synccheck -- null op
- * asyncneeded -- async lookup needed
- * finished -- answer set.
- */
- /* check for async lookups needed. */
- if (asyncState() != NullState::Instance()) {
- /* If a state object is here, use it.
- * When all cases are converted, the if goes away and it
- * becomes unconditional.
- * RBC 02 2003
- */
- asyncState()->checkForAsync(this);
- } else if (state[ACL_DST_ASN] == ACL_LOOKUP_NEEDED) {
- state[ACL_DST_ASN] = ACL_LOOKUP_PENDING;
- ipcache_nbgethostbyname(request->host,
- aclLookupDstIPforASNDone, this);
- } else if (state[ACL_SRC_DOMAIN] == ACL_LOOKUP_NEEDED) {
- state[ACL_SRC_DOMAIN] = ACL_LOOKUP_PENDING;
- fqdncache_nbgethostbyaddr(src_addr,
- aclLookupSrcFQDNDone, this);
- } else if (state[ACL_DST_DOMAIN] == ACL_LOOKUP_NEEDED) {
- ipcache_addrs *ia;
- ia = ipcacheCheckNumeric(request->host);
- if (ia == NULL) {
- state[ACL_DST_DOMAIN] = ACL_LOOKUP_DONE;
- } else {
- dst_addr = ia->in_addrs[0];
- state[ACL_DST_DOMAIN] = ACL_LOOKUP_PENDING;
- fqdncache_nbgethostbyaddr(dst_addr,
- aclLookupDstFQDNDone, this);
- }
- } else if (state[ACL_PROXY_AUTH] == ACL_LOOKUP_NEEDED) {
- debug(28, 3)
- ("ACLChecklist::checkForAsync: checking password via authenticator\n");
- aclLookupProxyAuthStart(this);
- state[ACL_PROXY_AUTH] = ACL_LOOKUP_PENDING;
- } else if (state[ACL_PROXY_AUTH] == ACL_PROXY_AUTH_NEEDED) {
- /* Client is required to resend the request with correct authentication
- * credentials. (This may be part of a stateful auth protocol.
- * The request is denied.
- */
- debug(28, 6) ("ACLChecklist::checkForAsync: requiring Proxy Auth header.\n");
- currentAnswer(ACCESS_REQ_PROXY_AUTH);
- markFinished();
- return;
#if USE_IDENT
- } else if (state[ACL_IDENT] == ACL_LOOKUP_NEEDED) {
- debug(28, 3) ("ACLChecklist::checkForAsync: Doing ident lookup\n");
- if (conn() && cbdataReferenceValid(conn())) {
- identStart(&conn()->me, &conn()->peer,
- aclLookupIdentDone, this);
- state[ACL_IDENT] = ACL_LOOKUP_PENDING;
- } else {
- debug(28, 1) ("ACLChecklist::checkForAsync: Can't start ident lookup. No client connection\n");
- currentAnswer(ACCESS_DENIED);
- markFinished();
- return;
- }
-#endif
- } else if (state[ACL_EXTERNAL] == ACL_LOOKUP_NEEDED) {
- acl *acl = aclFindByName(AclMatchedName);
- assert (acl->aclType() == ACL_EXTERNAL);
- acl->startExternal(this);
- } else {
- return;
- }
- asyncInProgress(true);
-}
-
void
-ACL::startExternal(ACLChecklist *checklist)
-{
- externalAclLookup(checklist, data, aclLookupExternalDone, checklist);
-}
-
-void
-ACLChecklist::checkCallback(allow_t answer)
-{
- PF *callback_;
- void *cbdata_;
- debug(28, 3) ("ACLChecklist::checkCallback: answer=%d\n", answer);
- /* During reconfigure, we can end up not finishing call
- * sequences into the auth code */
- if (auth_user_request) {
- /* the checklist lock */
- authenticateAuthUserRequestUnlock(auth_user_request);
- /* it might have been connection based */
- assert(conn());
- conn()->auth_user_request = NULL;
- conn()->auth_type = AUTH_BROKEN;
- auth_user_request = NULL;
- }
- callback_ = callback;
- callback = NULL;
- if (cbdataReferenceValidDone(callback_data, &cbdata_))
- callback_(answer, cbdata_);
- delete this;
-}
-
-#if USE_IDENT
-static void
aclLookupIdentDone(const char *ident, void *data)
{
ACLChecklist *checklist = (ACLChecklist *)data;
}
#endif
-static void
+void
aclLookupDstIPforASNDone(const ipcache_addrs * ia, void *data)
{
ACLChecklist *checklist = (ACLChecklist *)data;
checklist->check();
}
-static void
+void
aclLookupSrcFQDNDone(const char *fqdn, void *data)
{
ACLChecklist *checklist = (ACLChecklist *)data;
checklist->check();
}
-static void
+void
aclLookupDstFQDNDone(const char *fqdn, void *data)
{
ACLChecklist *checklist = (ACLChecklist *)data;
checklist->check();
}
-static void
-aclLookupProxyAuthDone(void *data, char *result)
-{
- ACLChecklist *checklist = (ACLChecklist *)data;
- checklist->state[ACL_PROXY_AUTH] = ACL_LOOKUP_DONE;
- if (result != NULL)
- fatal("AclLookupProxyAuthDone: Old code floating around somewhere.\nMake clean and if that doesn't work, report a bug to the squid developers.\n");
- if (!authenticateValidateUser(checklist->auth_user_request) || checklist->conn() == NULL) {
- /* credentials could not be checked either way
- * restart the whole process */
- /* OR the connection was closed, there's no way to continue */
- authenticateAuthUserRequestUnlock(checklist->auth_user_request);
- if (checklist->conn()) {
- checklist->conn()->auth_user_request = NULL;
- checklist->conn()->auth_type = AUTH_BROKEN;
- }
- checklist->auth_user_request = NULL;
- }
- checklist->asyncInProgress(false);
- checklist->check();
-}
-
-static void
-aclLookupExternalDone(void *data, void *result)
-{
- ACLChecklist *checklist = (ACLChecklist *)data;
- checklist->state[ACL_EXTERNAL] = ACL_LOOKUP_DONE;
- checklist->extacl_entry = cbdataReference((external_acl_entry *)result);
- checklist->asyncInProgress(false);
- checklist->check();
-}
-
-CBDATA_CLASS_INIT(ACLChecklist);
-
-void *
-ACLChecklist::operator new (size_t size)
-{
- assert (size == sizeof(ACLChecklist));
- CBDATA_INIT_TYPE(ACLChecklist);
- ACLChecklist *result = cbdataAlloc(ACLChecklist);
- /* Mark result as being owned - we want the refcounter to do the delete
- * call */
- cbdataReference(result);
- return result;
-}
-
-void
-ACLChecklist::operator delete (void *address)
-{
- ACLChecklist *t = static_cast<ACLChecklist *>(address);
- cbdataFree(address);
- /* And allow the memory to be freed */
- cbdataReferenceDone (t);
-}
-
-void
-ACLChecklist::deleteSelf() const
-{
- delete this;
-}
-
-ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL),
- reply (NULL),
- auth_user_request (NULL)
-#if SQUID_SNMP
- ,snmp_community(NULL)
-#endif
- , callback (NULL),
- callback_data (NULL),
- extacl_entry (NULL),
- conn_(NULL),
- async_(false),
- finished_(false),
- allow_(ACCESS_DENIED),
- state_(NullState::Instance())
-{
- memset (&src_addr, '\0', sizeof (struct in_addr));
- memset (&dst_addr, '\0', sizeof (struct in_addr));
- memset (&my_addr, '\0', sizeof (struct in_addr));
- rfc931[0] = '\0';
- memset (&state, '\0', sizeof (state));
-}
-
-ACLChecklist::~ACLChecklist()
-{
- assert (!asyncInProgress());
- if (extacl_entry)
- cbdataReferenceDone(extacl_entry);
- if (request)
- requestUnlink(request);
- request = NULL;
- cbdataReferenceDone(conn_);
- cbdataReferenceDone(accessList);
-}
-
-ConnStateData *
-ACLChecklist::conn()
-{
- return conn_;
-}
-
-void
-ACLChecklist::conn(ConnStateData *aConn)
-{
- assert (conn() == NULL);
- conn_ = aConn;
-}
-
/*
* Any ACLChecklist created by aclChecklistCreate() must eventually be
* freed by ACLChecklist::operator delete(). There are two common cases:
return checklist;
}
-void
-aclNBCheck(ACLChecklist * checklist, PF * callback, void *callback_data)
-{
- checklist->callback = callback;
- checklist->callback_data = cbdataReference(callback_data);
- checklist->check();
-}
-
/*********************/
/* Destroy functions */
/*********************/
case ACL_IDENT:
#endif
case ACL_DERIVED:
- case ACL_PROXY_AUTH:
break;
case ACL_TIME:
aclDestroyTimeList((acl_time_data *)data);
#if USE_IDENT
case ACL_IDENT_REGEX:
#endif
- case ACL_PROXY_AUTH_REGEX:
case ACL_URL_REGEX:
case ACL_URLPATH_REGEX:
case ACL_BROWSER:
return W;
}
-static wordlist *
+wordlist *
aclDumpRegexList(relist * data)
{
wordlist *W = NULL;
case ACL_IDENT:
#endif
case ACL_DERIVED:
- case ACL_PROXY_AUTH:
fatal ("unused");
case ACL_TIME:
return aclDumpTimeSpecList((acl_time_data *)data);
- case ACL_PROXY_AUTH_REGEX:
case ACL_URL_REGEX:
case ACL_URLPATH_REGEX:
case ACL_BROWSER:
delete this;
}
-void
-ACLChecklist::AsyncState::changeState (ACLChecklist *checklist, AsyncState *newState) const
-{
- checklist->changeState(newState);
-}
-
-ACLChecklist::NullState *
-ACLChecklist::NullState::Instance()
-{
- return &_instance;
-}
-
-void
-ACLChecklist::NullState::checkForAsync(ACLChecklist *) const
-{
-}
-
-ACLChecklist::NullState ACLChecklist::NullState::_instance;
-
-void
-ACLChecklist::changeState (AsyncState *newState)
-{
- /* only change from null to active and back again,
- * not active to active.
- * relax this once conversion to states is complete
- * RBC 02 2003
- */
- assert (state_ == NullState::Instance() || newState == NullState::Instance());
- state_ = newState;
-}
-
-ACLChecklist::AsyncState *
-ACLChecklist::asyncState() const
-{
- return state_;
-}
-
ACL::Prototype::Prototype() : prototype (NULL), typeString (NULL) {}
ACL::Prototype::Prototype (ACL const *aPrototype, char const *aType) : prototype (aPrototype), typeString (aType)
#
-# $Id: cf.data.pre,v 1.298 2003/02/08 14:42:09 hno Exp $
+# $Id: cf.data.pre,v 1.299 2003/02/13 08:07:47 robertc Exp $
#
#
# SQUID Web Proxy Cache http://www.squid-cache.org/
# 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] username ...
acl aclname proxy_auth_regex [-i] pattern ...
# list of valid usernames
# use REQUIRED to accept any valid username.
/*
- * $Id: client_side_reply.cc,v 1.38 2003/02/08 17:37:36 hno Exp $
+ * $Id: client_side_reply.cc,v 1.39 2003/02/13 08:07:47 robertc Exp $
*
* DEBUG: section 88 Client-side Reply Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
replyChecklist = clientAclChecklistCreate(Config.accessList.reply, http);
replyChecklist->reply = rep;
holdingReply = rep;
- aclNBCheck(replyChecklist, ProcessReply, this);
+ replyChecklist->nonBlockingCheck(ProcessReply, this);
}
void
/*
- * $Id: client_side_request.cc,v 1.15 2003/02/12 06:11:02 robertc Exp $
+ * $Id: client_side_request.cc,v 1.16 2003/02/13 08:07:47 robertc Exp $
*
* DEBUG: section 85 Client-side Request Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
}
context->acl_checklist =
clientAclChecklistCreate(Config.accessList.http, http);
- aclNBCheck(context->acl_checklist, clientAccessCheckDone, context);
+ context->acl_checklist->nonBlockingCheck(clientAccessCheckDone, context);
}
void
if (Config.accessList.noCache && http->request->flags.cachable) {
acl_checklist =
clientAclChecklistCreate(Config.accessList.noCache, http);
- aclNBCheck(acl_checklist, CheckNoCacheDone, cbdataReference(this));
+ acl_checklist->nonBlockingCheck(CheckNoCacheDone, cbdataReference(this));
} else {
CheckNoCacheDone(http->request->flags.cachable, cbdataReference(this));
}
/*
- * $Id: enums.h,v 1.223 2003/02/12 06:11:03 robertc Exp $
+ * $Id: enums.h,v 1.224 2003/02/13 08:07:47 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
ACL_METHOD,
ACL_BROWSER,
ACL_REFERER_REGEX,
- ACL_PROXY_AUTH,
- ACL_PROXY_AUTH_REGEX,
ACL_SRC_ASN,
ACL_DST_ASN,
#if USE_ARP_ACL
/*
- * $Id: external_acl.cc,v 1.25 2003/02/12 06:11:03 robertc Exp $
+ * $Id: external_acl.cc,v 1.26 2003/02/13 08:07:48 robertc Exp $
*
* DEBUG: section 82 External ACL
* AUTHOR: Henrik Nordstrom, MARA Systems AB
*/
#include "squid.h"
+#include "ExternalACL.h"
#include "authenticate.h"
#include "Store.h"
#include "fde.h"
if (acl->def->require_auth) {
int ti;
/* Make sure the user is authenticated */
- if ((ti = aclAuthenticated(ch)) != 1) {
+ if ((ti = ch->authenticated()) != 1) {
debug(82, 2) ("aclMatchExternal: %s user not authenticated (%d)\n", acl->def->name, ti);
return ti;
}
if (!entry) {
debug(82, 2) ("aclMatchExternal: %s(\"%s\") = lookup needed\n", acl->def->name, key);
ch->state[ACL_EXTERNAL] = ACL_LOOKUP_NEEDED;
+ ch->changeState (ExternalACLLookup::Instance());
return 0;
}
external_acl_cache_touch(acl->def, entry);
}
void
-externalAclLookup(ACLChecklist * ch, void *acl_data, EAH * callback, void *callback_data)
+ACL::ExternalAclLookup(ACLChecklist * ch, ACL * me, EAH * callback, void *callback_data)
{
MemBuf buf;
- external_acl_data *acl = static_cast<external_acl_data *>(acl_data);
+ external_acl_data *acl = static_cast<external_acl_data *>(me->data);
external_acl *def = acl->def;
const char *key = makeExternalAclKey(ch, acl);
external_acl_entry *entry = static_cast<external_acl_entry *>(hash_lookup(def->cache, key));
helperShutdown(p->theHelper);
}
}
+
+ExternalACLLookup ExternalACLLookup::instance_;
+ExternalACLLookup *
+ExternalACLLookup::Instance()
+{
+ return &instance_;
+}
+
+void
+ExternalACLLookup::checkForAsync(ACLChecklist *checklist)const
+{
+ assert (checklist->state[ACL_EXTERNAL] == ACL_LOOKUP_NEEDED);
+ acl *acl = ACL::FindByName(AclMatchedName);
+ assert (acl->aclType() == ACL_EXTERNAL);
+ checklist->asyncInProgress(true);
+ ACL::ExternalAclLookup(checklist, acl, LookupDone, checklist);
+}
+
+void
+ExternalACLLookup::LookupDone(void *data, void *result)
+{
+ ACLChecklist *checklist = (ACLChecklist *)data;
+ checklist->state[ACL_EXTERNAL] = ACL_LOOKUP_DONE;
+ checklist->extacl_entry = cbdataReference((external_acl_entry *)result);
+ checklist->asyncInProgress(false);
+ checklist->check();
+}
/*
- * $Id: peer_select.cc,v 1.126 2003/02/12 06:11:04 robertc Exp $
+ * $Id: peer_select.cc,v 1.127 2003/02/13 08:07:48 robertc Exp $
*
* DEBUG: section 44 Peer Selection Algorithm
* AUTHOR: Duane Wessels
Config.accessList.AlwaysDirect,
request,
NULL); /* ident */
- aclNBCheck(ps->acl_checklist,
- peerCheckAlwaysDirectDone,
+ ps->acl_checklist->nonBlockingCheck(peerCheckAlwaysDirectDone,
ps);
return;
} else if (ps->always_direct > 0) {
Config.accessList.NeverDirect,
request,
NULL); /* ident */
- aclNBCheck(ps->acl_checklist,
- peerCheckNeverDirectDone,
+ ps->acl_checklist->nonBlockingCheck(peerCheckNeverDirectDone,
ps);
return;
} else if (ps->never_direct > 0) {