31#include <unordered_map>
36class NamedAcls:
public std::unordered_map<SBuf, Acl::Node::Pointer,
37 CaseInsensitiveSBufHash, CaseInsensitiveSBufEqual,
38 PoolingAllocator< std::pair<const SBuf, Acl::Node::Pointer> > > {
48typedef std::map<TypeName, Maker, TypeNameCmp>
Makers;
63 const auto pos =
TheMakers().find(typeName);
67 auto *result = (pos->second)(pos->first);
68 debugs(28, 4, typeName <<
'=' << result);
111 if (keyStorage.
caseCmp(newKey) == 0)
114 throw TextException(
ToSBuf(
"Attempt to change the value of the ", keyParameterName,
" argument in a subsequent acl declaration:",
117 Debug::Extra,
"advice: Use a dedicated ACL name for each distinct ", keyParameterName,
118 " (and group those ACLs together using an 'any-of' ACL)."),
125 static const auto none =
new SBuf(
"[no-ACL]");
149 fatal (
"unusable Acl::Node::new");
153void Acl::Node::operator
delete(
void *)
155 fatal (
"unusable Acl::Node::delete");
162 debugs(28, 8,
"no named ACLs to find " << name);
168 debugs(28, 8,
"no ACL named " << name);
172 debugs(28, 8, result->second <<
" is named " << name);
174 return result->second.getRaw();
179 debugs(28, 8,
"constructing, this=" <<
this);
191 debugs(28, 5,
"checking " << name);
196 if (!checklist->
hasAle() && requiresAle()) {
198 "context without an ALE state. Assuming mismatch.");
199 }
else if (!checklist->
hasRequest() && requiresRequest()) {
201 "context without an HTTP request. Assuming mismatch.");
202 }
else if (!checklist->
hasReply() && requiresReply()) {
204 "context without an HTTP response. Assuming mismatch.");
211 result =
const_cast<Node*
>(
this)->match(checklist);
215 debugs(28, 3,
"checked: " << name <<
" = " << result << extra);
247 ParseNamed(parser, *namedAcls, aclname);
265 if (strcmp(theType,
"myip") == 0) {
267 while (p !=
nullptr) {
269 if (p->flags.natIntercept)
270 debugs(28,
DBG_CRITICAL,
"WARNING: 'myip' ACL is not reliable for interception proxies. Please use 'myportname' instead.");
273 debugs(28,
DBG_IMPORTANT,
"WARNING: UPGRADE: ACL 'myip' type has been renamed to 'localip' and matches the IP the client connected to.");
275 }
else if (strcmp(theType,
"myport") == 0) {
277 while (p !=
nullptr) {
280 if (p->flags.natIntercept)
281 debugs(28,
DBG_CRITICAL,
"WARNING: 'myport' ACL is not reliable for interception proxies. Please use 'myportname' instead.");
284 theType =
"localport";
285 debugs(28,
DBG_IMPORTANT,
"WARNING: UPGRADE: ACL 'myport' type has been renamed to 'localport' and matches the port the client connected to.");
286 }
else if (strcmp(theType,
"proto") == 0 && aclname.
cmp(
"manager") == 0) {
290 }
else if (strcmp(theType,
"clientside_mark") == 0) {
291 debugs(28,
DBG_IMPORTANT,
"WARNING: UPGRADE: ACL 'clientside_mark' type has been renamed to 'client_connection_mark'.");
292 theType =
"client_connection_mark";
295 auto A = FindByName(aclname);
298 debugs(28, 3,
"aclParseAclLine: Creating ACL '" << aclname <<
"'");
303 if (strcmp (A->typeString(),theType) ) {
304 debugs(28,
DBG_CRITICAL,
"aclParseAclLine: ACL '" << A->name <<
"' already exists with different type.");
309 debugs(28, 3,
"aclParseAclLine: Appending to '" << aclname <<
"'");
326 fatalf(
"ERROR: Invalid ACL: %s\n",
330 const auto insertion = namedAcls.emplace(A->name, A);
338 for (
const auto &nameAndAcl: *namedAcls) {
339 debugs(3, 3, directiveName <<
' ' << nameAndAcl.first);
340 nameAndAcl.second->dumpWhole(directiveName, os);
350 *namedAcls =
nullptr;
363 for (
const auto lineOption: lineOptions()) {
364 lineOption->unconfigure();
365 allOptions.push_back(lineOption);
375 os << directiveName <<
' ' << name <<
' ' << typeString() << options() <<
376 asList(dump()).prefixedBy(
" ").delimitedBy(
" ") <<
387 fatal(
"aclCacheMatchAcl: unknown or unexpected ACL type");
411 debugs(28, 4,
"cache hit on acl '" << name <<
"' (" <<
this <<
")");
420 debugs(28, 4,
"miss for acl '" << name <<
"'. Adding result " << auth_match->
matchrv);
431 debugs(28, 8,
"aclCacheMatchFlush called for cache " << cache);
466 debugs(28, 8,
"destructing " << name <<
", this=" <<
this);
476 nameAndAcl.second->prepareForUse();
#define Assure(condition)
void CallParser(const CodeContext::Pointer &parsingContext, Fun &&parse)
#define Here()
source code location of the caller
auto asList(const Container &c)
a helper to ease AsList object creation
AnyP::PortCfgPointer HttpPortList
list of Squid http(s)_port configured
char config_input_line[BUFSIZ]
virtual bool hasReply() const =0
void setLastCheckedName(const SBuf &name)
remember the name of the last ACL being evaluated
bool asyncInProgress() const
async call has been started and has not finished (or failed) yet
virtual void verifyAle() const =0
warns if there are uninitialized ALE components and fills them
virtual bool hasAle() const =0
virtual bool hasRequest() const =0
const SBuf & lastCheckDescription() const
describes the ACL that was evaluated last while obtaining this answer (for debugging)
std::optional< SBuf > lastCheckedName
the name of the ACL (if any) that was evaluated last while obtaining this answer
parsed "acl aclname ..." directives indexed by aclname
virtual bool isProxyAuth() const
virtual int matchForCache(ACLChecklist *checklist)
bool matches(ACLChecklist *checklist) const
virtual bool requiresReply() const
whether our (i.e. shallow) match() requires checklist to have a reply
int cacheMatchAcl(dlink_list *cache, ACLChecklist *)
void dumpWhole(const char *directiveName, std::ostream &)
virtual bool requiresAle() const
whether our (i.e. shallow) match() requires checklist to have a AccessLogEntry
static void ParseNamed(ConfigParser &, NamedAcls &, const SBuf &name)
parses acl directive parts that follow aclname
void context(const SBuf &aName, const char *configuration)
sets user-specified ACL name and squid.conf context
virtual bool valid() const
virtual bool requiresRequest() const
whether our (i.e. shallow) match() requires checklist to have a request
static void ParseNamedAcl(ConfigParser &, NamedAcls *&)
parses acl directive parts that follow directive name (i.e. "acl")
void parseFlags()
configures Acl::Node options, throwing on configuration errors
static Acl::Node * FindByName(const SBuf &)
A configured ACL with a given name or nil.
CodeContext of the being-parsed acl directive.
SBuf name_
the aclname parameter of the being-parsed acl directive
std::ostream & detailCodeContext(std::ostream &os) const override
appends human-friendly context description line(s) to a cache.log record
ScopedId codeContextGist() const override
ParsingContext(const SBuf &name)
Acl::Node type name comparison functor.
bool operator()(TypeName a, TypeName b) const
static SBuf CurrentLocation()
static char * NextToken()
static std::ostream & Extra(std::ostream &)
static auto Make(Args &&... args)
int caseCmp(const SBuf &S, const size_type n) const
shorthand version for case-insensitive compare()
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Acl::NamedAcls * namedAcls
acl aclname acltype ...
an std::runtime_error with thrower location info
#define DBG_PARSE_NOTE(x)
#define debugs(SECTION, LEVEL, CONTENT)
void dlinkDelete(dlink_node *m, dlink_list *list)
void dlinkAddTail(void *data, dlink_node *m, dlink_list *list)
void fatal(const char *message)
void fatalf(const char *fmt,...)
void aclCacheMatchFlush(dlink_list *cache)
void RegisterMaker(TypeName typeName, Maker maker)
use the given Acl::Node Maker for all ACLs of the named type
static Makers & TheMakers()
registered Acl::Node Makers
static Acl::Node * Make(TypeName typeName)
creates an Acl::Node object of the named (and already registered) Node child type
void DumpNamedAcls(std::ostream &, const char *directiveName, NamedAcls *)
report the given list of "acl" directives (using squid.conf syntax)
Node *(*)(TypeName typeName) Maker
a "factory" function for making Acl::Node objects (of some Node child type)
const char * TypeName
the ACL type name known to admins
void ParseFlags(const Options &options)
void SetKey(SBuf &keyStorage, const char *keyParameterName, const char *newKey)
void FreeNamedAcls(NamedAcls **)
delete the given list of "acl" directives
std::map< TypeName, Maker, TypeNameCmp > Makers
Acl::Node makers indexed by Node type name.
std::vector< const Option * > Options
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf