bool httpStateIsValid();
void clientAccessCheck();
void clientAccessCheck2();
- void clientAccessCheckDone(int answer);
+ void clientAccessCheckDone(const allow_t &answer);
void clientRedirectStart();
void clientRedirectDone(char *result);
void checkNoCache();
- void checkNoCacheDone(int answer);
+ void checkNoCacheDone(const allow_t &answer);
#if USE_ADAPTATION
void adaptationAccessCheck();
if (conn->fd >= 0 && fd_table[conn->fd].closing() && flag != COMM_ERR_CLOSING) {
debugs(5, 3, HERE << "converting late call to COMM_ERR_CLOSING: " << conn);
flag = COMM_ERR_CLOSING;
- size = 0;
}
return true; // now we are in sync and can handle the call
}
if (http->getConn() != NULL)
ch.conn(http->getConn());
- if (DelayPools::delay_data[pool].theComposite().getRaw() && ch.fastCheck()) {
+ if (DelayPools::delay_data[pool].theComposite().getRaw() && ch.fastCheck() == ACCESS_ALLOWED) {
DelayId result (pool + 1);
CompositePoolNode::CompositeSelectionDetails details;
ACLFilledChecklist checklist(hm->access_list, request, NULL);
- if (checklist.fastCheck()) {
+ if (checklist.fastCheck() == ACCESS_ALLOWED) {
/* aclCheckFast returns true for allow. */
retval = 1;
} else if (NULL == hm->replacement) {
ch.reply = HTTPMSGLOCK(this); // XXX: this lock makes method non-const
for (acl_size_t *l = Config.ReplyBodySize; l; l = l -> next) {
/* if there is no ACL list or if the ACLs listed match use this size value */
- if (!l->aclList || ch.matchAclListFast(l->aclList)) {
+ if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
debugs(58, 4, HERE << "bodySizeMax=" << bodySizeMax);
bodySizeMax = l->size; // may be -1
break;
for (acl_size_t *l = Config.rangeOffsetLimit; l; l = l -> next) {
/* if there is no ACL list or if the ACLs listed match use this limit value */
- if (!l->aclList || ch.matchAclListFast(l->aclList)) {
+ if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
rangeOffsetLimit = l->size; // may be -1
break;
HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from);
/// \ingroup ServerProtocolICPAPI
-int icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request);
+bool icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request);
/// \ingroup ServerProtocolICPAPI
SQUIDCEXTERN void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from);
#ifndef SQUID_PEERSELECTSTATE_H
#define SQUID_PEERSELECTSTATE_H
+#include "acl/Checklist.h"
#include "Array.h"
#include "cbdata.h"
#include "comm/forward.h"
ps_state();
HttpRequest *request;
StoreEntry *entry;
- int always_direct;
- int never_direct;
- int direct;
+ allow_t always_direct;
+ allow_t never_direct;
+ int direct; // TODO: fold always_direct/never_direct/prefer_direct into this now that ACL can do a multi-state result.
PSC *callback;
void *callback_data;
typedef enum {
ACCESS_DENIED,
ACCESS_ALLOWED,
+ ACCESS_DUNNO,
ACCESS_REQ_PROXY_AUTH
} allow_t;
}
void
-ACLChecklist::check()
+ACLChecklist::matchNonBlocking()
{
if (checking())
return;
{
preCheck();
/* does the current AND clause match */
- matchAclListSlow(accessList->aclList);
+ matchAclList(accessList->aclList, false);
}
void
void
ACLChecklist::checkCallback(allow_t answer)
{
- PF *callback_;
+ ACLCB *callback_;
void *cbdata_;
debugs(28, 3, "ACLChecklist::checkCallback: " << this << " answer=" << answer);
delete this;
}
-void
-ACLChecklist::matchAclListSlow(const ACLList * list)
-{
- matchAclList(list, false);
-}
-
void
ACLChecklist::matchAclList(const ACLList * head, bool const fast)
{
* NP: this should probably be made Async now.
*/
void
-ACLChecklist::nonBlockingCheck(PF * callback_, void *callback_data_)
+ACLChecklist::nonBlockingCheck(ACLCB * callback_, void *callback_data_)
{
callback = callback_;
callback_data = cbdataReference(callback_data_);
- check();
+ matchNonBlocking();
+}
+
+allow_t const &
+ACLChecklist::fastCheck(const ACLList * list)
+{
+ PROF_start(aclCheckFast);
+ currentAnswer(ACCESS_DUNNO);
+ matchAclList(list, true);
+ // assume ALLOWED on matches due to not having an acl_access object
+ if (finished())
+ currentAnswer(ACCESS_ALLOWED);
+ PROF_stop(aclCheckFast);
+ return currentAnswer();
}
/* Warning: do not cbdata lock this here - it
* may be static or on the stack
*/
-int
+allow_t const &
ACLChecklist::fastCheck()
{
PROF_start(aclCheckFast);
- currentAnswer(ACCESS_DENIED);
+ currentAnswer(ACCESS_DUNNO);
+
debugs(28, 5, "aclCheckFast: list: " << accessList);
const acl_access *acl = cbdataReference(accessList);
while (acl != NULL && cbdataReferenceValid(acl)) {
currentAnswer(acl->allow);
- if (matchAclListFast(acl->aclList)) {
+ matchAclList(acl->aclList, true);
+ if (finished()) {
PROF_stop(aclCheckFast);
cbdataReferenceDone(acl);
- return currentAnswer() == ACCESS_ALLOWED;
+ return currentAnswer();
}
/*
cbdataReferenceDone(A);
}
- debugs(28, 5, "aclCheckFast: no matches, returning: " << (currentAnswer() == ACCESS_DENIED));
-
+ debugs(28, 5, "aclCheckFast: no matches, returning: " << currentAnswer());
PROF_stop(aclCheckFast);
- return currentAnswer() == ACCESS_DENIED;
+
+ return currentAnswer();
}
{
return !cbdataReferenceValid(callback_data);
}
-
-bool
-ACLChecklist::matchAclListFast(const ACLList * list)
-{
- matchAclList(list, true);
- return finished();
-}
-
-
#include "acl/Acl.h"
+/// ACL checklist callback
+typedef void ACLCB(allow_t, void *);
+
/** \ingroup ACLAPI
Base class for maintaining Squid and transaction state for access checks.
Provides basic ACL checking methods. Its only child, ACLFilledChecklist,
* The callback specified will be called with true/false
* when the results of the ACL tests are known.
*/
- void nonBlockingCheck(PF * callback, void *callback_data);
+ void nonBlockingCheck(ACLCB * callback, void *callback_data);
/**
* Trigger a blocking access check for a set of *_access options.
* knowledge of the ACL usage rather than depend on this default.
* That will also save on work setting up ACLChecklist fields for a no-op.
*
- * \retval 1/true Access Allowed
- * \retval 0/false Access Denied
+ * \retval ACCESS_DUNNO Unable to determine any result
+ * \retval ACCESS_ALLOWED Access Allowed
+ * \retval ACCESS_DENIED Access Denied
*/
- int fastCheck();
+ allow_t const & fastCheck();
/**
- * Trigger a blocking access check for a single ACL line (a AND b AND c).
+ * A version of fastCheck() for use when there is a one-line set of ACLs
+ * to be tested and a match determins the result action to be done.
*
- * ACLs which cannot be satisfied directly from available data are ignored.
- * This means any proxy_auth, external_acl, DNS lookups, Ident lookups etc
- * which have not already been performed and cached will not be checked.
- *
- * \retval 1/true Access Allowed
- * \retval 0/false Access Denied
+ * \retval ACCESS_DUNNO Unable to determine any result
+ * \retval ACCESS_ALLOWED ACLs all matched
*/
- bool matchAclListFast(const ACLList * list);
-
- /**
- * Attempt to check the current checklist against current data.
- * This is the core routine behind all ACL test routines.
- * As much as possible of current tests are performed immediately
- * and the result is maybe delayed to wait for async lookups.
- *
- * When all tests are done callback is presented with one of:
- * - ACCESS_ALLOWED Access explicitly Allowed
- * - ACCESS_DENIED Access explicitly Denied
- */
- void check();
+ allow_t const & fastCheck(const ACLList * list);
bool asyncInProgress() const;
void asyncInProgress(bool const);
public:
const acl_access *accessList;
- PF *callback;
+ ACLCB *callback;
void *callback_data;
+ /**
+ * Attempt to check the current checklist against current data.
+ * This is the core routine behind all ACL test routines.
+ * As much as possible of current tests are performed immediately
+ * and the result is maybe delayed to wait for async lookups.
+ *
+ * When all tests are done callback is presented with one of:
+ * - ACCESS_ALLOWED Access explicitly Allowed
+ * - ACCESS_DENIED Access explicitly Denied
+ */
+ void matchNonBlocking();
+
private: /* internal methods */
void preCheck();
void matchAclList(const ACLList * list, bool const fast);
- void matchAclListSlow(const ACLList * list);
bool async_;
bool finished_;
checklist->changeState (ACLChecklist::NullState::Instance());
checklist->markDestinationDomainChecked();
checklist->request->recordLookup(details);
- checklist->check();
+ checklist->matchNonBlocking();
}
checklist->request->recordLookup(details);
checklist->asyncInProgress(false);
checklist->changeState (ACLChecklist::NullState::Instance());
- checklist->check();
+ checklist->matchNonBlocking();
}
for (B = *head, T = head; B; T = &B->next, B = B->next);
*T = A;
- /* We lock _acl_access structures in ACLChecklist::check() */
+ /* We lock _acl_access structures in ACLChecklist::matchNonBlocking() */
}
void
checklist->changeState (ACLChecklist::NullState::Instance());
checklist->markSourceDomainChecked();
checklist->request->recordLookup(details);
- checklist->check();
+ checklist->matchNonBlocking();
}
}
void
-Adaptation::AccessCheck::AccessCheckCallbackWrapper(int answer, void *data)
+Adaptation::AccessCheck::AccessCheckCallbackWrapper(allow_t answer, void *data)
{
debugs(93, 8, HERE << "callback answer=" << answer);
AccessCheck *ac = (AccessCheck*)data;
*/
// convert to async call to get async call protections and features
- typedef UnaryMemFunT<AccessCheck, int> MyDialer;
+ typedef UnaryMemFunT<AccessCheck, allow_t> MyDialer;
AsyncCall::Pointer call =
asyncCall(93,7, "Adaptation::AccessCheck::noteAnswer",
- MyDialer(ac, &Adaptation::AccessCheck::noteAnswer,
- answer==ACCESS_ALLOWED));
+ MyDialer(ac, &Adaptation::AccessCheck::noteAnswer, answer));
ScheduleCallHere(call);
}
/// process the results of the ACL check
void
-Adaptation::AccessCheck::noteAnswer(int answer)
+Adaptation::AccessCheck::noteAnswer(allow_t answer)
{
Must(!candidates.empty()); // the candidate we were checking must be there
debugs(93,5, HERE << topCandidate() << " answer=" << answer);
- if (answer) { // the rule matched
+ if (answer == ACCESS_ALLOWED) { // the rule matched
ServiceGroupPointer g = topGroup();
if (g != NULL) { // the corresponding group found
callBack(g);
#ifndef SQUID_ADAPTATION__ACCESS_CHECK_H
#define SQUID_ADAPTATION__ACCESS_CHECK_H
+#include "acl/Acl.h"
#include "base/AsyncJob.h"
#include "adaptation/Elements.h"
#include "adaptation/forward.h"
public:
void checkCandidates();
- static void AccessCheckCallbackWrapper(int, void*);
- void noteAnswer(int answer);
+ static void AccessCheckCallbackWrapper(allow_t, void*);
+ void noteAnswer(allow_t answer);
protected:
// AsyncJob API
new ACLFilledChecklist(TheConfig.repeat, info.icapRequest, dash_str);
cl->reply = HTTPMSGLOCK(info.icapReply);
- const bool result = cl->fastCheck();
+ bool result = cl->fastCheck() == ACCESS_ALLOWED;
delete cl;
return result;
}
{
if (IcapLogfileStatus == LOG_ENABLE) {
ACLChecklist *checklist = new ACLFilledChecklist(::Config.accessList.icap, al.request, dash_str);
- if (!::Config.accessList.icap || checklist->fastCheck()) {
+ if (!::Config.accessList.icap || checklist->fastCheck() == ACCESS_ALLOWED) {
finalizeLogInfo();
icapLogLog(&al, checklist);
}
checklist->asyncInProgress(false);
checklist->changeState (ACLChecklist::NullState::Instance());
- checklist->check();
+ checklist->matchNonBlocking();
}
void
if (al.reply)
checklist->reply = HTTPMSGLOCK(al.reply);
- if (!Config.accessList.log || checklist->fastCheck()) {
+ if (!Config.accessList.log || checklist->fastCheck() == ACCESS_ALLOWED) {
if (request)
al.adapted_request = HTTPMSGLOCK(request);
accessLogLog(&al, checklist);
ACLFilledChecklist identChecklist(Ident::TheConfig.identLookup, NULL, NULL);
identChecklist.src_addr = client->remote;
identChecklist.my_addr = client->local;
- if (identChecklist.fastCheck())
+ if (identChecklist.fastCheck() == ACCESS_ALLOWED)
Ident::Start(client, clientIdentDone, result);
}
#endif
/* it was said several times that client write limiter does not work if client_db is disabled */
ClientDelayPools& pools(Config.ClientDelay.pools);
- for (unsigned int pool = 0; pool < pools.size(); pool++) {
-
- /* pools require explicit 'allow' to assign a client into them */
- if (!pools[pool].access)
- continue; // warned in ClientDelayConfig::Finalize()
-
- ACLFilledChecklist ch(pools[pool].access, NULL, NULL);
-
- // TODO: we check early to limit error response bandwith but we
- // should recheck when we can honor delay_pool_uses_indirect
-
- ch.src_addr = details->remote;
- ch.my_addr = details->local;
+ ACLFilledChecklist ch(NULL, NULL, NULL);
- if (ch.fastCheck()) {
+ // TODO: we check early to limit error response bandwith but we
+ // should recheck when we can honor delay_pool_uses_indirect
+ // TODO: we should also pass the port details for myportname here.
+ ch.src_addr = details->remote;
+ ch.my_addr = details->local;
- /* request client information from db after we did all checks
- this will save hash lookup if client failed checks */
- ClientInfo * cli = clientdbGetInfo(details->remote);
- assert(cli);
-
- /* put client info in FDE */
- fd_table[details->fd].clientInfo = cli;
+ for (unsigned int pool = 0; pool < pools.size(); pool++) {
- /* setup write limiter for this request */
- const double burst = floor(0.5 +
- (pools[pool].highwatermark * Config.ClientDelay.initial)/100.0);
- cli->setWriteLimiter(pools[pool].rate, burst, pools[pool].highwatermark);
- break;
+ /* pools require explicit 'allow' to assign a client into them */
+ if (pools[pool].access) {
+ ch.accessList = pools[pool].access;
+ allow_t answer = ch.fastCheck();
+ if (answer == ACCESS_ALLOWED) {
+
+ /* request client information from db after we did all checks
+ this will save hash lookup if client failed checks */
+ ClientInfo * cli = clientdbGetInfo(details->remote);
+ assert(cli);
+
+ /* put client info in FDE */
+ fd_table[details->fd].clientInfo = cli;
+
+ /* setup write limiter for this request */
+ const double burst = floor(0.5 +
+ (pools[pool].highwatermark * Config.ClientDelay.initial)/100.0);
+ cli->setWriteLimiter(pools[pool].rate, burst, pools[pool].highwatermark);
+ break;
+ } else {
+ debugs(83, 4, HERE << "Delay pool " << pool << " skipped because ACL " << answer);
+ }
}
}
}
http->logType == LOG_TCP_DENIED_REPLY ||
alwaysAllowResponse(reply->sline.status)) {
headers_sz = reply->hdr_sz;
- processReplyAccessResult(1);
+ processReplyAccessResult(ACCESS_ALLOWED);
return;
}
/** check for absent access controls (permit by default) */
if (!Config.accessList.reply) {
- processReplyAccessResult(1);
+ processReplyAccessResult(ACCESS_ALLOWED);
return;
}
}
void
-clientReplyContext::ProcessReplyAccessResult (int rv, void *voidMe)
+clientReplyContext::ProcessReplyAccessResult(allow_t rv, void *voidMe)
{
clientReplyContext *me = static_cast<clientReplyContext *>(voidMe);
me->processReplyAccessResult(rv);
}
void
-clientReplyContext::processReplyAccessResult(bool accessAllowed)
+clientReplyContext::processReplyAccessResult(const allow_t &accessAllowed)
{
debugs(88, 2, "The reply for " << RequestMethodStr(http->request->method)
- << " " << http->uri << " is "
- << ( accessAllowed ? "ALLOWED" : "DENIED")
- << ", because it matched '"
+ << " " << http->uri << " is " << accessAllowed << ", because it matched '"
<< (AclMatchedName ? AclMatchedName : "NO ACL's") << "'" );
- if (!accessAllowed) {
+ if (accessAllowed != ACCESS_ALLOWED) {
ErrorState *err;
err_type page_id;
page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName, 1);
StoreIOBuffer holdingBuffer;
HttpReply *reply;
void processReplyAccess();
- static PF ProcessReplyAccessResult;
- void processReplyAccessResult(bool accessAllowed);
+ static ACLCB ProcessReplyAccessResult;
+ void processReplyAccessResult(const allow_t &accessAllowed);
void cloneReply();
void buildReplyHeader ();
bool alwaysAllowResponse(http_status sline) const;
static const char *const crlf = "\r\n";
#if FOLLOW_X_FORWARDED_FOR
-static void
-clientFollowXForwardedForCheck(int answer, void *data);
+static void clientFollowXForwardedForCheck(allow_t answer, void *data);
#endif /* FOLLOW_X_FORWARDED_FOR */
CBDATA_CLASS_INIT(ClientRequestContext);
/* Local functions */
/* other */
-static void clientAccessCheckDoneWrapper(int, void *);
+static void clientAccessCheckDoneWrapper(allow_t, void *);
#if USE_SSL
-static void sslBumpAccessCheckDoneWrapper(int, void *);
+static void sslBumpAccessCheckDoneWrapper(allow_t, void *);
#endif
static int clientHierarchical(ClientHttpRequest * http);
static void clientInterpretRequestHeaders(ClientHttpRequest * http);
static RH clientRedirectDoneWrapper;
-static PF checkNoCacheDoneWrapper;
+static void checkNoCacheDoneWrapper(allow_t, void *);
extern "C" CSR clientGetMoreData;
extern "C" CSS clientReplyStatus;
extern "C" CSD clientReplyDetach;
* ++ indirect_client_addr contains the remote direct client from the trusted peers viewpoint.
*/
static void
-clientFollowXForwardedForCheck(int answer, void *data)
+clientFollowXForwardedForCheck(allow_t answer, void *data)
{
ClientRequestContext *calloutContext = (ClientRequestContext *) data;
}
void
-clientAccessCheckDoneWrapper(int answer, void *data)
+clientAccessCheckDoneWrapper(allow_t answer, void *data)
{
ClientRequestContext *calloutContext = (ClientRequestContext *) data;
}
void
-ClientRequestContext::clientAccessCheckDone(int answer)
+ClientRequestContext::clientAccessCheckDone(const allow_t &answer)
{
acl_checklist = NULL;
err_type page_id;
http_status status;
debugs(85, 2, "The request " <<
RequestMethodStr(http->request->method) << " " <<
- http->uri << " is " <<
- (answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED") <<
+ http->uri << " is " << answer <<
", because it matched '" <<
(AclMatchedName ? AclMatchedName : "NO ACL's") << "'" );
#endif
static void
-clientRedirectAccessCheckDone(int answer, void *data)
+clientRedirectAccessCheckDone(allow_t answer, void *data)
{
ClientRequestContext *context = (ClientRequestContext *)data;
ClientHttpRequest *http = context->http;
acl_checklist->nonBlockingCheck(checkNoCacheDoneWrapper, this);
} else {
/* unless otherwise specified, we try to cache. */
- checkNoCacheDone(1);
+ checkNoCacheDone(ACCESS_ALLOWED);
}
}
static void
-checkNoCacheDoneWrapper(int answer, void *data)
+checkNoCacheDoneWrapper(allow_t answer, void *data)
{
ClientRequestContext *calloutContext = (ClientRequestContext *) data;
}
void
-ClientRequestContext::checkNoCacheDone(int answer)
+ClientRequestContext::checkNoCacheDone(const allow_t &answer)
{
acl_checklist = NULL;
- http->request->flags.cachable = answer;
+ http->request->flags.cachable = (answer == ACCESS_ALLOWED);
http->doCallouts();
}
* as ACLFilledChecklist callback
*/
static void
-sslBumpAccessCheckDoneWrapper(int answer, void *data)
+sslBumpAccessCheckDoneWrapper(allow_t answer, void *data)
{
ClientRequestContext *calloutContext = static_cast<ClientRequestContext *>(data);
checklist->extacl_entry = cbdataReference((external_acl_entry *)result);
checklist->asyncInProgress(false);
checklist->changeState (ACLChecklist::NullState::Instance());
- checklist->check();
+ checklist->matchNonBlocking();
}
/* This registers "external" in the registry. To do dynamic definitions
ACLFilledChecklist ch(Config.accessList.miss, request, NULL);
ch.src_addr = request->client_addr;
ch.my_addr = request->my_addr;
- int answer = ch.fastCheck();
-
- if (answer == 0) {
+ if (ch.fastCheck() == ACCESS_DENIED) {
err_type page_id;
page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName, 1);
return;
}
- request->flags.pinned = 0;
+ request->flags.pinned = 0; // XXX: what if the ConnStateData set this to flag existing credentials?
+ // XXX: answer: the peer selection *should* catch it and give us only the pinned peer. so we reverse the =0 step below.
+ // XXX: also, logs will now lie if pinning is broken and leads to an error message.
if (serverDestinations[0]->peerType == PINNED) {
ConnStateData *pinned_connection = request->pinnedConnection();
assert(pinned_connection);
acl_tos *l;
for (l = head; l; l = l->next) {
- if (!l->aclList || ch->matchAclListFast(l->aclList))
+ if (!l->aclList || ch->fastCheck(l->aclList) == ACCESS_ALLOWED)
return l->tos;
}
acl_nfmark *l;
for (l = head; l; l = l->next) {
- if (!l->aclList || ch->matchAclListFast(l->aclList))
+ if (!l->aclList || ch->fastCheck(l->aclList) == ACCESS_ALLOWED)
return l->nfmark;
}
if (conn->remote.IsIPv4() != l->addr.IsIPv4()) continue;
/* check ACLs for this outgoing address */
- if (!l->aclList || ch.matchAclListFast(l->aclList)) {
+ if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
conn->local = l->addr;
return;
}
return d;
}
-static int
-htcpAccessCheck(acl_access * acl, htcpSpecifier * s, Ip::Address &from)
+static bool
+htcpAccessAllowed(acl_access * acl, htcpSpecifier * s, Ip::Address &from)
{
/* default deny if no access list present */
if (!acl)
- return 0;
+ return false;
ACLFilledChecklist checklist(acl, s->request, NULL);
checklist.src_addr = from;
checklist.my_addr.SetNoAddr();
- int result = checklist.fastCheck();
- return result;
+ return (checklist.fastCheck() == ACCESS_ALLOWED);
}
static void
return;
}
- if (!htcpAccessCheck(Config.accessList.htcp, s, from)) {
+ if (!htcpAccessAllowed(Config.accessList.htcp, s, from)) {
debugs(31, 2, "htcpHandleTstRequest: Access denied");
htcpLogHtcp(from, dhdr->opcode, LOG_UDP_DENIED, s->uri);
htcpFreeSpecifier(s);
return;
}
- if (!htcpAccessCheck(Config.accessList.htcp_clr, s, from)) {
+ if (!htcpAccessAllowed(Config.accessList.htcp_clr, s, from)) {
debugs(31, 2, "htcpHandleClr: Access denied");
htcpLogHtcp(from, hdr->opcode, LOG_UDP_DENIED, s->uri);
htcpFreeSpecifier(s);
}
}
-int
+bool
icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request)
{
/* absent an explicit allow, we deny all */
if (!Config.accessList.icp)
- return 0;
+ return true;
ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
checklist.src_addr = from;
checklist.my_addr.SetNoAddr();
- int result = checklist.fastCheck();
- return result;
+ return (checklist.fastCheck() == ACCESS_ALLOWED);
}
char const *
checklist->asyncInProgress(false);
checklist->changeState(ACLChecklist::NullState::Instance());
- checklist->check();
+ checklist->matchNonBlocking();
}
#endif /* USE_IDENT */
xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN);
for (; log; log = log->next) {
- if (checklist && log->aclList && !checklist->matchAclListFast(log->aclList))
+ if (log->aclList && checklist && checklist->fastCheck(log->aclList) != ACCESS_ALLOWED)
continue;
if (log->logfile) {
/* count mcast group peers every 15 minutes */
#define MCAST_COUNT_RATE 900
-int peerAllowedToUse(const peer *, HttpRequest *);
+bool peerAllowedToUse(const peer *, HttpRequest *);
static int peerWouldBePinged(const peer *, HttpRequest *);
static void neighborRemove(peer *);
static void neighborAlive(peer *, const MemObject *, const icp_common_t *);
return p->type;
}
-/*
- * peerAllowedToUse
- *
- * this function figures out if it is appropriate to fetch REQUEST
- * from PEER.
+/**
+ * \return Whether it is appropriate to fetch REQUEST from PEER.
*/
-int
+bool
peerAllowedToUse(const peer * p, HttpRequest * request)
{
const struct _domain_ping *d = NULL;
- int do_ping = 1;
assert(request != NULL);
if (neighborType(p, request) == PEER_SIBLING) {
debugs(15, 2, "peerAllowedToUse(" << p->name << ", " << request->GetHost() << ") : multicast-siblings optimization match");
#endif
if (request->flags.nocache)
- return 0;
+ return false;
if (request->flags.refresh)
- return 0;
+ return false;
if (request->flags.loopdetect)
- return 0;
+ return false;
if (request->flags.need_validation)
- return 0;
+ return false;
}
// CONNECT requests are proxy requests. Not to be forwarded to origin servers.
// Unless the destination port matches, in which case we MAY perform a 'DIRECT' to this peer.
if (p->options.originserver && request->method == METHOD_CONNECT && request->port != p->in_addr.GetPort())
- return 0;
+ return false;
if (p->peer_domain == NULL && p->access == NULL)
- return do_ping;
-
- do_ping = 0;
+ return true;
+ bool do_ping = false;
for (d = p->peer_domain; d; d = d->next) {
if (0 == matchDomainName(request->GetHost(), d->domain)) {
do_ping = d->do_ping;
do_ping = !d->do_ping;
}
- if (p->peer_domain && 0 == do_ping)
- return do_ping;
+ if (p->peer_domain && !do_ping)
+ return false;
if (p->access == NULL)
return do_ping;
#endif
- return checklist.fastCheck();
+ return (checklist.fastCheck() == ACCESS_ALLOWED);
}
/* Return TRUE if it is okay to send an ICP request to this peer. */
}
static void
-peerCheckNeverDirectDone(int answer, void *data)
+peerCheckNeverDirectDone(allow_t answer, void *data)
{
ps_state *psstate = (ps_state *) data;
psstate->acl_checklist = NULL;
debugs(44, 3, "peerCheckNeverDirectDone: " << answer);
- psstate->never_direct = answer ? 1 : -1;
+ psstate->never_direct = answer;
peerSelectFoo(psstate);
}
static void
-peerCheckAlwaysDirectDone(int answer, void *data)
+peerCheckAlwaysDirectDone(allow_t answer, void *data)
{
ps_state *psstate = (ps_state *)data;
psstate->acl_checklist = NULL;
debugs(44, 3, "peerCheckAlwaysDirectDone: " << answer);
- psstate->always_direct = answer ? 1 : -1;
+ psstate->always_direct = answer;
peerSelectFoo(psstate);
}
/** If we don't known whether DIRECT is permitted ... */
if (ps->direct == DIRECT_UNKNOWN) {
- if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) {
+ if (ps->always_direct == ACCESS_DUNNO && Config.accessList.AlwaysDirect) {
/** check always_direct; */
ps->acl_checklist = new ACLFilledChecklist(
Config.accessList.AlwaysDirect,
NULL); /* ident */
ps->acl_checklist->nonBlockingCheck(peerCheckAlwaysDirectDone, ps);
return;
- } else if (ps->always_direct > 0) {
+ } else if (ps->always_direct == ACCESS_ALLOWED) {
/** if always_direct says YES, do that. */
ps->direct = DIRECT_YES;
- } else if (ps->never_direct == 0 && Config.accessList.NeverDirect) {
+ } else if (ps->never_direct == ACCESS_DUNNO && Config.accessList.NeverDirect) {
/** check never_direct; */
ps->acl_checklist = new ACLFilledChecklist(
Config.accessList.NeverDirect,
ps->acl_checklist->nonBlockingCheck(peerCheckNeverDirectDone,
ps);
return;
- } else if (ps->never_direct > 0) {
+ } else if (ps->never_direct == ACCESS_ALLOWED) {
/** if always_direct says NO, do that. */
ps->direct = DIRECT_NO;
} else if (request->flags.no_direct) {
peerSelectDnsPaths(ps);
}
-int peerAllowedToUse(const peer * p, HttpRequest * request);
+bool peerAllowedToUse(const peer * p, HttpRequest * request);
/**
* peerSelectPinned
ps_state::ps_state() : request (NULL),
entry (NULL),
- always_direct (0),
- never_direct (0),
+ always_direct(ACCESS_DUNNO),
+ never_direct(ACCESS_DUNNO),
direct (0),
callback (NULL),
callback_data (NULL),
u_char *Community;
u_char *buf = rq->buf;
int len = rq->len;
- int allow = 0;
+ allow_t allow = ACCESS_DENIED;
+
+ if (!Config.accessList.snmp) {
+ debugs(49, DBG_IMPORTANT, "WARNING: snmp_access not configured. agent query DENIED from : " << rq->from);
+ return;
+ }
debugs(49, 5, HERE << "Called.");
PDU = snmp_pdu_create(0);
/* Check if we have explicit permission to access SNMP data.
* default (set above) is to deny all */
- if (Community && Config.accessList.snmp) {
+ if (Community) {
ACLFilledChecklist checklist(Config.accessList.snmp, NULL, NULL);
checklist.src_addr = rq->from;
checklist.snmp_community = (char *) Community;
allow = checklist.fastCheck();
- }
- if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
- rq->community = Community;
- rq->PDU = PDU;
- debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
- snmpConstructReponse(rq);
+ if (allow == ACCESS_ALLOWED && (snmp_coexist_V2toV1(PDU))) {
+ rq->community = Community;
+ rq->PDU = PDU;
+ debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
+ snmpConstructReponse(rq);
+ } else {
+ debugs(49, DBG_IMPORTANT, "WARNING: SNMP agent query DENIED from : " << rq->from);
+ }
+ xfree(Community);
+
} else {
- debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from);
+ debugs(49, DBG_IMPORTANT, "WARNING: Failed SNMP agent query from : " << rq->from);
snmp_free_pdu(PDU);
}
-
- if (Community)
- xfree(Community);
}
/*
if (check) {
Filled(check)->ssl_error = error_no;
- if (check->fastCheck()) {
+ if (check->fastCheck() == ACCESS_ALLOWED) {
debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
ok = 1;
} else {
Ip::Address theIcpPublicHostID;
HttpRequest* icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from) STUB_RETVAL(NULL)
-int icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request) STUB_RETVAL(0)
+bool icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request) STUB_RETVAL(false)
void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from) STUB
icp_opcode icpGetCommonOpcode() STUB_RETVAL(ICP_INVALID)
int icpUdpSend(int, const Ip::Address &, icp_common_t *, log_type, int) STUB_RETVAL(0)
/* Create state structure. */
TunnelStateData *tunnelState = NULL;
ErrorState *err = NULL;
- int answer;
HttpRequest *request = http->request;
char *url = http->uri;
ACLFilledChecklist ch(Config.accessList.miss, request, NULL);
ch.src_addr = request->client_addr;
ch.my_addr = request->my_addr;
- answer = ch.fastCheck();
-
- if (answer == 0) {
+ if (ch.fastCheck() == ACCESS_DENIED) {
debugs(26, 4, HERE << "MISS access forbidden.");
err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN, request);
*status_ptr = HTTP_FORBIDDEN;