47#ifndef DEFAULT_EXTERNAL_ACL_TTL
48#define DEFAULT_EXTERNAL_ACL_TTL 1 * 60 * 60
50#ifndef DEFAULT_EXTERNAL_ACL_CHILDREN
51#define DEFAULT_EXTERNAL_ACL_CHILDREN 5
133 format(
"external_acl_type"),
138 cache_size(256*1024),
143 quote(
Format::LOG_QUOTE_URL)
192 if (strncmp(token,
"ttl=", 4) == 0) {
193 a->
ttl = atoi(token + 4);
194 }
else if (strncmp(token,
"negative_ttl=", 13) == 0) {
196 }
else if (strncmp(token,
"children=", 9) == 0) {
198 debugs(0,
DBG_CRITICAL,
"WARNING: external_acl_type option children=N has been deprecated in favor of children-max=N and children-startup=N");
199 }
else if (strncmp(token,
"children-max=", 13) == 0) {
201 }
else if (strncmp(token,
"children-startup=", 17) == 0) {
203 }
else if (strncmp(token,
"children-idle=", 14) == 0) {
205 }
else if (strncmp(token,
"concurrency=", 12) == 0) {
207 }
else if (strncmp(token,
"queue-size=", 11) == 0) {
210 }
else if (strncmp(token,
"cache=", 6) == 0) {
212 }
else if (strncmp(token,
"grace=", 6) == 0) {
213 a->
grace = atoi(token + 6);
214 }
else if (strcmp(token,
"protocol=2.5") == 0) {
216 }
else if (strcmp(token,
"protocol=3.0") == 0) {
217 debugs(3,
DBG_PARSE_NOTE(2),
"WARNING: external_acl_type option protocol=3.0 is deprecated. Remove this from your config.");
219 }
else if (strcmp(token,
"quote=url") == 0) {
220 debugs(3,
DBG_PARSE_NOTE(2),
"WARNING: external_acl_type option quote=url is deprecated. Remove this from your config.");
222 }
else if (strcmp(token,
"quote=shell") == 0) {
223 debugs(3,
DBG_PARSE_NOTE(2),
"WARNING: external_acl_type option quote=shell is deprecated. Use protocol=2.5 if still needed.");
228 }
else if (strcmp(token,
"ipv4") == 0) {
232 }
else if (strcmp(token,
"ipv6") == 0) {
234 debugs(3,
DBG_CRITICAL,
"WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->
name );
266 bool data_used =
false;
274 (*fmt)->
space =
true;
278 (*fmt)->quote = a->
quote;
282 if (strncmp(token,
"%USER_CERT_", 11) == 0) {
284 (*fmt)->data.string =
xstrdup(token + 11);
285 (*fmt)->data.header.header = (*fmt)->data.string;
286 }
else if (strncmp(token,
"%USER_CA_CERT_", 14) == 0) {
288 (*fmt)->data.string =
xstrdup(token + 14);
289 (*fmt)->data.header.header = (*fmt)->data.string;
290 }
else if (strncmp(token,
"%CA_CERT_", 9) == 0) {
293 (*fmt)->data.string =
xstrdup(token + 9);
294 (*fmt)->data.header.header = (*fmt)->data.string;
297 if (strncmp(token,
"%<{", 3) == 0) {
301 const size_t parsedLen = (*fmt)->parse(tmp.
c_str(), "e);
306 }
else if (strncmp(token,
"%>{", 3) == 0) {
310 const size_t parsedLen = (*fmt)->parse(tmp.
c_str(), "e);
319 const size_t len = (*fmt)->parse(token, "e);
320 assert(len == strlen(token));
332 fmt = &((*fmt)->next);
363 list = &(*list)->
next;
377 if (!
node->local_addr.isIPv6())
385 if (
node->negative_ttl !=
node->ttl)
394 if (
node->children.n_startup != 0)
397 if (
node->children.n_idle != 1)
400 if (
node->children.concurrency != 0)
409 node->format.dump(sentry,
nullptr,
false);
411 for (word =
node->cmdline; word; word = word->
next)
431 if (strcmp(
node->name, name) == 0)
442 assert(anEntry !=
nullptr);
539 debugs(28,
DBG_CRITICAL,
"ERROR: Cannot use proxy auth because no authentication schemes were compiled.");
544 debugs(28,
DBG_CRITICAL,
"ERROR: Cannot use proxy auth because no authentication schemes are fully configured.");
598 debugs(82, 3,
"cannot resume matching; external_acl gone");
607 if (entry !=
nullptr) {
608 if (entry->
def == acl->
def) {
613 if (strcmp(key, (
char*)entry->
key) != 0) {
614 debugs(82, 9,
"entry key='" << (
char *)entry->
key <<
"', our key='" << key <<
"' do not match. Discarded.");
620 debugs(82, 9,
"entry " << entry <<
" not valid or not ours. Discarded.");
621 if (entry !=
nullptr) {
622 debugs(82, 9,
"entry def=" << entry->
def <<
", our def=" << acl->
def);
624 debugs(82, 9,
"entry key='" << (
char *)entry->
key <<
"', our key='" << key <<
"'");
631 debugs(82, 9,
"No helper entry available");
635 debugs(82, 3, acl->
def->
name <<
" check user authenticated.");
638 debugs(82, 2, acl->
def->
name <<
" user not authenticated (" << ti <<
")");
660 debugs(82, 4,
"no need to wait for the refresh of '" <<
661 key <<
"' in '" << acl->
def->
name <<
"' (ch=" << ch <<
").");
665 debugs(82, 2, acl->
def->
name <<
"(\"" << key <<
"\") = lookup needed");
669 debugs(82, 2,
"\"" << key <<
"\": queueing a call.");
671 debugs(82, 2,
"\"" << key <<
"\": no async support!");
672 debugs(82, 2,
"\"" << key <<
"\": return -1.");
677 "' queue full. Request rejected '" << key <<
"'.");
682 "' queue full. Using stale result. '" << key <<
"'.");
690 debugs(82, 4,
"entry = { date=" <<
691 (
long unsigned int) entry->
date <<
692 ", result=" << entry->
result <<
693 " tag=" << entry->
tag <<
694 " log=" << entry->
log <<
" }");
726 checklist->
markFinished(answer,
"aclMatchExternal exception");
740 s.
Printf(
" %s", arg->key);
780 for (
auto arg = acl_data->
arguments; arg; arg = arg->next) {
786 sb.
append(quoted, strlen(quoted));
826 ttl = (ttl * (100 - def->
grace)) / 100;
854 debugs(82, 2,
"external_acl_cache_add: Adding '" << key <<
"' = " << data.
result);
856 if (entry !=
nullptr) {
857 debugs(82, 3,
"updating existing entry");
948 debugs(82, 2,
"reply=" << reply);
962 if (label !=
nullptr && *label !=
'\0')
963 entryData.
tag = label;
966 if (label !=
nullptr && *label !=
'\0')
970 if (label !=
nullptr && *label !=
'\0')
971 entryData.
log = label;
975 if (label !=
nullptr && *label !=
'\0')
976 entryData.
user = label;
979 if (label !=
nullptr && *label !=
'\0')
997 state->
queue =
nullptr;
1010 const auto &me =
dynamic_cast<const ACLExternal&
>(acl);
1024 debugs(82, 2, (inBackground ?
"bg" :
"fg") <<
" lookup in '" <<
1025 def->
name <<
"' for '" << key <<
"'");
1034 if (strcmp(key, oldstatetmp->
key) == 0) {
1035 oldstate = oldstatetmp;
1043 if (oldstate && inBackground) {
1044 debugs(82, 7,
"'" << def->
name <<
"' queue is already being refreshed (ch=" << ch <<
")");
1050 if (!inBackground) {
1058 oldstate->
queue = state;
1065 debugs(82, 4,
"externalAclLookup: looking up for '" << key <<
"' in '" << def->
name <<
"'.");
1068 debugs(82, 7,
"'" << def->
name <<
"' submit to helper failed");
1079 debugs(82, 4,
"externalAclLookup: will wait for the result of '" << key <<
1080 "' in '" << def->
name <<
"' (ch=" << ch <<
").");
1090 p->theHelper->packStatsInto(sentry);
1099 "External ACL stats",
1113 p->theHelper->cmdline = p->cmdline;
1115 p->theHelper->childs.updateLimits(p->children);
1119 p->theHelper->addr = p->local_addr;
1121 p->theHelper->openSessions();
void EAH(void *data, const ExternalACLEntryPointer &result)
ACLFilledChecklist * Filled(ACLChecklist *checklist)
convenience and safety wrapper for dynamic_cast<ACLFilledChecklist*>
void UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &helperNotes)
Acl::Answer AuthenticateAcl(ACLChecklist *ch, const Acl::Node &acl)
int authenticateActiveSchemeCount(void)
int authenticateSchemeCount(void)
void parse_wordlist(wordlist **list)
int cbdataReferenceValid(const void *p)
#define cbdataReferenceDone(var)
#define cbdataReference(var)
#define CBDATA_CLASS_INIT(type)
#define cbdataReferenceValidDone(var, ptr)
#define CBDATA_CLASS(type)
void markFinished(const Acl::Answer &newAnswer, const char *reason)
void resumeNonBlockingCheck()
bool keepMatching() const
Whether we should continue to match tree nodes or stop/pause.
bool goAsync(AsyncStarter, const Acl::Node &)
bool empty() const override
bool isProxyAuth() const override
static void LookupDone(void *data, const ExternalACLEntryPointer &)
Called when an async lookup returns.
void startLookup(ACLFilledChecklist *, external_acl_data *, bool inBackground) const
static void StartLookup(ACLFilledChecklist &, const Acl::Node &)
ACLExternal(char const *)
Acl::Answer aclMatchExternal(external_acl_data *, ACLFilledChecklist *) const
char * makeExternalAclKey(ACLFilledChecklist *, external_acl_data *) const
char const * typeString() const override
bool valid() const override
int match(ACLChecklist *checklist) override
Matches the actual data in checklist against this Acl::Node.
void parse() override
parses node representation in squid.conf; dies on failures
SBufList dump() const override
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
ExternalACLEntryPointer extacl_entry
HttpRequest::Pointer request
SBuf lastAclName
string for external_acl_type ACL format code
SBuf lastAclData
string for external_acl_type DATA format code
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
static void DisableMacros()
Do not allow macros inside quoted strings.
static char * NextToken()
static void EnableMacros()
Allow macros inside quoted strings.
static char * strtokFile()
NotePairs notes
list of all kv-pairs returned by the helper
NotePairs notes
list of all kv-pairs returned by the helper
void update(ExternalACLEntryData const &)
static Pointer Make(const char *name)
Helper::ResultCode result
The helper response 'result' field.
CbcPointer< ConnStateData > clientConnectionManager
void init(mb_size_t szInit, mb_size_t szMax)
void append(const NotePairs *src)
Append the entries of the src NotePairs list to our list.
const char * findFirst(const char *noteKey) const
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
void push_back(char)
Append a single character. The character may be NUL (\0).
size_type length() const
Returns the number of bytes stored in SBuf.
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
SBuf & append(const SBuf &S)
external_acl * externalAclHelperList
char const * termedBuf() const
externalAclState(external_acl *aDef, const char *aKey)
external_acl_data(external_acl *const aDef)
Helper::Client::Pointer theHelper
Helper::ChildConfig children
void add(const ExternalACLEntryPointer &)
bool maybeCacheable(const Acl::Answer &) const
#define DBG_PARSE_NOTE(x)
#define debugs(SECTION, LEVEL, CONTENT)
void dlinkDelete(dlink_node *m, dlink_list *list)
void dlinkAdd(void *data, dlink_node *m, dlink_list *list)
void externalAclInit(void)
static void externalAclRegisterWithCacheManager(void)
void parse_externalAclHelper(external_acl **list)
static void externalAclHandleReply(void *data, const Helper::Reply &reply)
static void externalAclStats(StoreEntry *sentry)
static int external_acl_grace_expired(external_acl *def, const ExternalACLEntryPointer &entry)
static void external_acl_cache_delete(external_acl *def, const ExternalACLEntryPointer &entry)
static void copyResultsFromEntry(const HttpRequest::Pointer &req, const ExternalACLEntryPointer &entry)
void free_externalAclHelper(external_acl **list)
#define DEFAULT_EXTERNAL_ACL_CHILDREN
static void external_acl_cache_touch(external_acl *def, const ExternalACLEntryPointer &entry)
static int external_acl_entry_expired(external_acl *def, const ExternalACLEntryPointer &entry)
static ExternalACLEntryPointer external_acl_cache_add(external_acl *def, const char *key, ExternalACLEntryData const &data)
static external_acl * find_externalAclHelper(const char *name)
#define DEFAULT_EXTERNAL_ACL_TTL
void dump_externalAclHelper(StoreEntry *sentry, const char *name, const external_acl *list)
void externalAclShutdown(void)
const char * external_acl_message
void hashFreeMemory(hash_table *)
hash_link * hash_lookup(hash_table *, const void *)
hash_table * hash_create(HASHCMP *, int, HASHHASH *)
int HASHCMP(const void *, const void *)
void hash_join(hash_table *, hash_link *)
void hash_remove_link(hash_table *, hash_link *)
void helperShutdown(const Helper::Client::Pointer &hlp)
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
#define rfc1738_escape(x)
std::list< SBuf > SBufList
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
const char * wordlistAdd(wordlist **list, const char *key)
void wordlistDestroy(wordlist **list)
destroy a wordlist