*/
#include "squid.h"
-#include "CacheManager.h"
+#include "mgr/Registration.h"
#include "ExternalACL.h"
#include "ExternalACLEntry.h"
-#include "AuthUserRequest.h"
+#include "auth/UserRequest.h"
#include "SquidTime.h"
#include "Store.h"
#include "fde.h"
-#include "ACLChecklist.h"
-#include "ACL.h"
+#include "acl/FilledChecklist.h"
+#include "acl/Acl.h"
#if USE_IDENT
-#include "ACLIdent.h"
+#include "ident/AclIdent.h"
#endif
+#include "ip/tools.h"
#include "client_side.h"
+#include "comm/Connection.h"
#include "HttpRequest.h"
#include "HttpReply.h"
-#include "authenticate.h"
+#include "auth/Acl.h"
+#include "auth/Gadgets.h"
#include "helper.h"
#include "MemBuf.h"
+#include "rfc1738.h"
#include "URLScheme.h"
#include "wordlist.h"
typedef struct _external_acl_format external_acl_format;
-static char *makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data);
+static char *makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data);
static void external_acl_cache_delete(external_acl * def, external_acl_entry * entry);
static int external_acl_entry_expired(external_acl * def, external_acl_entry * entry);
static int external_acl_grace_expired(external_acl * def, external_acl_entry * entry);
wordlist *cmdline;
- int children;
-
- int concurrency;
+ HelperChildConfig children;
helper *theHelper;
dlink_list queue;
+ /**
+ * Configuration flag. May only be altered by the configuration parser.
+ *
+ * Indicates that all uses of this external_acl_type helper require authentication
+ * details to be processed. If none are available its a fail match.
+ */
bool require_auth;
enum {
QUOTE_METHOD_URL
} quote;
- IpAddress local_addr;
+ Ip::Address local_addr;
};
struct _external_acl_format {
#endif
EXT_ACL_SRC,
EXT_ACL_SRCPORT,
+#if USE_SQUID_EUI
+ EXT_ACL_SRCEUI48,
+ EXT_ACL_SRCEUI64,
+#endif
EXT_ACL_MYADDR,
EXT_ACL_MYPORT,
EXT_ACL_URI,
if (p->theHelper) {
helperShutdown(p->theHelper);
- helperFree(p->theHelper);
+ delete p->theHelper;
p->theHelper = NULL;
}
/* set defaults */
a->ttl = DEFAULT_EXTERNAL_ACL_TTL;
a->negative_ttl = -1;
- a->children = DEFAULT_EXTERNAL_ACL_CHILDREN;
+ a->cache_size = 256*1024;
+ a->children.n_max = DEFAULT_EXTERNAL_ACL_CHILDREN;
+ a->children.n_startup = a->children.n_max;
+ a->children.n_idle = 1;
a->local_addr.SetLocalhost();
a->quote = external_acl::QUOTE_METHOD_URL;
-
token = strtok(NULL, w_space);
if (!token)
} else if (strncmp(token, "negative_ttl=", 13) == 0) {
a->negative_ttl = atoi(token + 13);
} else if (strncmp(token, "children=", 9) == 0) {
- a->children = atoi(token + 9);
+ a->children.n_max = atoi(token + 9);
+ debugs(0, 0, "WARNING: external_acl_type option children=N has been deprecated in favor of children-max=N and children-startup=N");
+ } else if (strncmp(token, "children-max=", 13) == 0) {
+ a->children.n_max = atoi(token + 13);
+ } else if (strncmp(token, "children-startup=", 17) == 0) {
+ a->children.n_startup = atoi(token + 17);
+ } else if (strncmp(token, "children-idle=", 14) == 0) {
+ a->children.n_idle = atoi(token + 14);
} else if (strncmp(token, "concurrency=", 12) == 0) {
- a->concurrency = atoi(token + 12);
+ a->children.concurrency = atoi(token + 12);
} else if (strncmp(token, "cache=", 6) == 0) {
a->cache_size = atoi(token + 6);
} else if (strncmp(token, "grace=", 6) == 0) {
debugs(3, 0, "WARNING: Error converting " << a->local_addr << " to IPv4 in " << a->name );
}
} else if (strcmp(token, "ipv6") == 0) {
-#if !USE_IPV6
- debugs(3, 0, "WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->name );
-#else
- (void)0;
-#endif
+ if (!Ip::EnableIpv6)
+ debugs(3, 0, "WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->name );
+ // else nothing to do.
} else {
break;
}
token = strtok(NULL, w_space);
}
+ /* check that child startup value is sane. */
+ if (a->children.n_startup > a->children.n_max)
+ a->children.n_startup = a->children.n_max;
+
+ /* check that child idle value is sane. */
+ if (a->children.n_idle > a->children.n_max)
+ a->children.n_idle = a->children.n_max;
+ if (a->children.n_idle < 1)
+ a->children.n_idle = 1;
+
if (a->negative_ttl == -1)
a->negative_ttl = a->ttl;
format->type = _external_acl_format::EXT_ACL_SRC;
else if (strcmp(token, "%SRCPORT") == 0)
format->type = _external_acl_format::EXT_ACL_SRCPORT;
+#if USE_SQUID_EUI
+ else if (strcmp(token, "%SRCEUI48") == 0)
+ format->type = _external_acl_format::EXT_ACL_SRCEUI48;
+ else if (strcmp(token, "%SRCEUI64") == 0)
+ format->type = _external_acl_format::EXT_ACL_SRCEUI64;
+#endif
else if (strcmp(token, "%MYADDR") == 0)
format->type = _external_acl_format::EXT_ACL_MYADDR;
else if (strcmp(token, "%MYPORT") == 0)
format->type = _external_acl_format::EXT_ACL_METHOD;
#if USE_SSL
-
else if (strcmp(token, "%USER_CERT") == 0)
format->type = _external_acl_format::EXT_ACL_USER_CERT_RAW;
else if (strcmp(token, "%USER_CERTCHAIN") == 0)
format->type = _external_acl_format::EXT_ACL_USER_CERT;
format->header = xstrdup(token + 11);
}
-
#endif
else if (strcmp(token, "%EXT_USER") == 0)
format->type = _external_acl_format::EXT_ACL_EXT_USER;
else {
+ debugs(0,0, "ERROR: Unknown Format token " << token);
self_destruct();
}
if (node->grace)
storeAppendPrintf(sentry, " grace=%d", node->grace);
- if (node->children != DEFAULT_EXTERNAL_ACL_CHILDREN)
- storeAppendPrintf(sentry, " children=%d", node->children);
+ if (node->children.n_max != DEFAULT_EXTERNAL_ACL_CHILDREN)
+ storeAppendPrintf(sentry, " children-max=%d", node->children.n_max);
+
+ if (node->children.n_startup != 1)
+ storeAppendPrintf(sentry, " children-startup=%d", node->children.n_startup);
+
+ if (node->children.n_idle != (node->children.n_max + node->children.n_startup) )
+ storeAppendPrintf(sentry, " children-idle=%d", node->children.n_idle);
- if (node->concurrency)
- storeAppendPrintf(sentry, " concurrency=%d", node->concurrency);
+ if (node->children.concurrency)
+ storeAppendPrintf(sentry, " concurrency=%d", node->children.concurrency);
if (node->cache)
storeAppendPrintf(sentry, " cache=%d", node->cache_size);
DUMP_EXT_ACL_TYPE(SRC);
DUMP_EXT_ACL_TYPE(SRCPORT);
+#if USE_SQUID_EUI
+ DUMP_EXT_ACL_TYPE(SRCEUI48);
+ DUMP_EXT_ACL_TYPE(SRCEUI64);
+#endif
+
DUMP_EXT_ACL_TYPE(MYADDR);
DUMP_EXT_ACL_TYPE(MYPORT);
DUMP_EXT_ACL_TYPE(URI);
}
static int
-aclMatchExternal(external_acl_data *acl, ACLChecklist * ch);
-static int
-aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
+aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *ch)
{
int result;
external_acl_entry *entry;
if (acl->def->require_auth) {
int ti;
/* Make sure the user is authenticated */
+ debugs(82, 3, "aclMatchExternal: " << acl->def->name << " check user authenticated.");
- if ((ti = ch->authenticated()) != 1) {
+ if ((ti = AuthenticateAcl(ch)) != 1) {
debugs(82, 2, "aclMatchExternal: " << acl->def->name << " user not authenticated (" << ti << ")");
return ti;
}
+ debugs(82, 3, "aclMatchExternal: " << acl->def->name << " user is authenticated.");
}
key = makeExternalAclKey(ch, acl);
- if (acl->def->require_auth)
- AUTHUSERREQUESTUNLOCK(ch->auth_user_request, "ACLChecklist via aclMatchExternal");
-
if (!key) {
/* Not sufficient data to process */
return -1;
debugs(82, 2, "aclMatchExternal: \"" << key << "\": entry=@" <<
entry << ", age=" << (entry ? (long int) squid_curtime - entry->date : 0));
- if (acl->def->theHelper->stats.queue_size <= acl->def->theHelper->n_running) {
+ if (acl->def->theHelper->stats.queue_size <= (int)acl->def->theHelper->childs.n_active) {
debugs(82, 2, "aclMatchExternal: \"" << key << "\": queueing a call.");
ch->changeState (ExternalACLLookup::Instance());
if (entry->log.size())
ch->request->extacl_log = entry->log;
+
+ if (entry->message.size())
+ ch->request->extacl_message = entry->message;
}
return result;
int
ACLExternal::match(ACLChecklist *checklist)
{
- return aclMatchExternal (data, checklist);
+ return aclMatchExternal (data, Filled(checklist));
}
wordlist *
}
static char *
-makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
+makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data)
{
static MemBuf mb;
char buf[256];
switch (format->type) {
case _external_acl_format::EXT_ACL_LOGIN:
- assert (ch->auth_user_request);
+ assert (ch->auth_user_request != NULL);
str = ch->auth_user_request->username();
break;
#if USE_IDENT
str = buf;
break;
+#if USE_SQUID_EUI
+ case _external_acl_format::EXT_ACL_SRCEUI48:
+ if (request->client_eui48.encode(buf, sizeof(buf)))
+ str = buf;
+ break;
+
+ case _external_acl_format::EXT_ACL_SRCEUI64:
+ if (request->client_eui64.encode(buf, sizeof(buf)))
+ str = buf;
+ break;
+#endif
+
case _external_acl_format::EXT_ACL_MYADDR:
str = request->my_addr.NtoA(buf, sizeof(buf));
break;
case _external_acl_format::EXT_ACL_USER_CERT_RAW:
- if (ch->conn() != NULL) {
- SSL *ssl = fd_table[ch->conn()->fd].ssl;
+ if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+ SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
if (ssl)
str = sslGetUserCertificatePEM(ssl);
case _external_acl_format::EXT_ACL_USER_CERTCHAIN_RAW:
- if (ch->conn() != NULL) {
- SSL *ssl = fd_table[ch->conn()->fd].ssl;
+ if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+ SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
if (ssl)
str = sslGetUserCertificateChainPEM(ssl);
case _external_acl_format::EXT_ACL_USER_CERT:
- if (ch->conn() != NULL) {
- SSL *ssl = fd_table[ch->conn()->fd].ssl;
+ if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+ SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
if (ssl)
str = sslGetUserAttribute(ssl, format->header);
case _external_acl_format::EXT_ACL_CA_CERT:
- if (ch->conn() != NULL) {
- SSL *ssl = fd_table[ch->conn()->fd].ssl;
+ if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+ SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
if (ssl)
str = sslGetCAAttribute(ssl, format->header);
}
void
-ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callback, void *callback_data)
+ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH * callback, void *callback_data)
{
MemBuf buf;
external_acl_data *acl = me->data;
externalAclState *oldstate = NULL;
bool graceful = 0;
+ ACLFilledChecklist *ch = Filled(checklist);
if (acl->def->require_auth) {
int ti;
/* Make sure the user is authenticated */
+ debugs(82, 3, "aclMatchExternal: " << acl->def->name << " check user authenticated.");
- if ((ti = ch->authenticated()) != 1) {
+ if ((ti = AuthenticateAcl(ch)) != 1) {
debugs(82, 1, "externalAclLookup: " << acl->def->name <<
" user authentication failure (" << ti << ", ch=" << ch << ")");
callback(callback_data, NULL);
return;
}
+ debugs(82, 3, "aclMatchExternal: " << acl->def->name << " user is authenticated.");
}
const char *key = makeExternalAclKey(ch, acl);
} else {
/* Check for queue overload */
- if (def->theHelper->stats.queue_size >= def->theHelper->n_running) {
+ if (def->theHelper->stats.queue_size >= (int)def->theHelper->childs.n_running) {
debugs(82, 1, "externalAclLookup: '" << def->name << "' queue overload (ch=" << ch << ")");
cbdataFree(state);
callback(callback_data, entry);
static void
externalAclRegisterWithCacheManager(void)
{
- CacheManager::GetInstance()->
- registerAction("external_acl",
- "External ACL stats",
- externalAclStats, 0, 1);
+ Mgr::RegisterAction("external_acl",
+ "External ACL stats",
+ externalAclStats, 0, 1);
}
void
p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4);
if (!p->theHelper)
- p->theHelper = helperCreate(p->name);
+ p->theHelper = new helper(p->name);
p->theHelper->cmdline = p->cmdline;
- p->theHelper->n_to_start = p->children;
-
- p->theHelper->concurrency = p->concurrency;
+ p->theHelper->childs = p->children;
p->theHelper->ipc_type = IPC_TCP_SOCKET;
void
ExternalACLLookup::LookupDone(void *data, void *result)
{
- ACLChecklist *checklist = (ACLChecklist *)data;
+ ACLFilledChecklist *checklist = Filled(static_cast<ACLChecklist*>(data));
checklist->extacl_entry = cbdataReference((external_acl_entry *)result);
checklist->asyncInProgress(false);
checklist->changeState (ACLChecklist::NullState::Instance());