Hello,
This patch implements a new 'has' ACL.
This ACL detects presence of request, response or ALE transaction
components.
The feature specification and related discussion can be found at:
http://lists.squid-cache.org/pipermail/squid-dev/2017-May/008559.html
Regards,
Eduard.
A new 'has' ACL was implemented.
This ACL detects presence of request, response or ALE transaction
components. Since many ACLs require some of these components, lack of
them in a transaction may spoil the check and confuse admin with
warnings like "... ACL is used in context without an HTTP request".
Using 'has' ACL should help dealing with these problems caused by
component-less transactions.
Also: addressed TODO in item #3 of trunk revision 14752.
=== modified file 'src/AclRegs.cc'
--- src/AclRegs.cc 2017-01-30 12:46:15 +0000
+++ src/AclRegs.cc 2017-04-30 11:11:06 +0000
@@ -17,60 +17,62 @@
#include "acl/AdaptationService.h"
#include "acl/AdaptationServiceData.h"
#endif
#include "acl/AllOf.h"
#include "acl/AnnotateClient.h"
#include "acl/AnnotateTransaction.h"
#include "acl/AnnotationData.h"
#include "acl/AnyOf.h"
#if USE_SQUID_EUI
#include "acl/Arp.h"
#include "acl/Eui64.h"
#endif
#if USE_OPENSSL
#include "acl/AtStep.h"
#include "acl/AtStepData.h"
#endif
#include "acl/Asn.h"
#include "acl/Browser.h"
#include "acl/Checklist.h"
#include "acl/ConnectionsEncrypted.h"
#include "acl/Data.h"
#include "acl/DestinationAsn.h"
#include "acl/DestinationDomain.h"
#include "acl/DestinationIp.h"
#include "acl/DomainData.h"
#if USE_AUTH
#include "acl/ExtUser.h"
#endif
#include "acl/FilledChecklist.h"
#include "acl/Gadgets.h"
+#include "acl/HasComponent.h"
+#include "acl/HasComponentData.h"
#include "acl/HierCode.h"
#include "acl/HierCodeData.h"
#include "acl/HttpHeaderData.h"
#include "acl/HttpRepHeader.h"
#include "acl/HttpReqHeader.h"
#include "acl/HttpStatus.h"
#include "acl/IntRange.h"
#include "acl/Ip.h"
#include "acl/LocalIp.h"
#include "acl/LocalPort.h"
#include "acl/MaxConnection.h"
#include "acl/Method.h"
#include "acl/MethodData.h"
#include "acl/MyPortName.h"
#include "acl/Note.h"
#include "acl/NoteData.h"
#include "acl/PeerName.h"
#include "acl/Protocol.h"
#include "acl/ProtocolData.h"
#include "acl/Random.h"
#include "acl/Referer.h"
#include "acl/RegexData.h"
#include "acl/ReplyHeaderStrategy.h"
#include "acl/ReplyMimeType.h"
#include "acl/RequestHeaderStrategy.h"
#include "acl/RequestMimeType.h"
#include "acl/SourceAsn.h"
#include "acl/SourceDomain.h"
#include "acl/SourceIp.h"
#include "acl/SquidError.h"
@@ -217,30 +219,33 @@ ACLMaxUserIP ACLMaxUserIP::RegistryEntry
ACL::Prototype ACLTag::RegistryProtoype(&ACLTag::RegistryEntry_, "tag");
ACLStrategised<const char *> ACLTag::RegistryEntry_(new ACLStringData, ACLTagStrategy::Instance(), "tag");
ACL::Prototype Acl::AnyOf::RegistryProtoype(&Acl::AnyOf::RegistryEntry_, "any-of");
Acl::AnyOf Acl::AnyOf::RegistryEntry_;
ACL::Prototype Acl::AllOf::RegistryProtoype(&Acl::AllOf::RegistryEntry_, "all-of");
Acl::AllOf Acl::AllOf::RegistryEntry_;
ACL::Prototype ACLNote::RegistryProtoype(&ACLNote::RegistryEntry_, "note");
ACLStrategised<NotePairs::Entry *> ACLNote::RegistryEntry_(new ACLNoteData, ACLNoteStrategy::Instance(), "note");
ACL::Prototype ACLAnnotateClient::RegistryProtoype(&ACLAnnotateClient::RegistryEntry_, "annotate_client");
ACLStrategised<NotePairs::Entry *> ACLAnnotateClient::RegistryEntry_(new ACLAnnotationData, ACLAnnotateClientStrategy::Instance(), "annotate_client");
ACL::Prototype ACLAnnotateTransaction::RegistryProtoype(&ACLAnnotateTransaction::RegistryEntry_, "annotate_transaction");
ACLStrategised<NotePairs::Entry *> ACLAnnotateTransaction::RegistryEntry_(new ACLAnnotationData, ACLAnnotateTransactionStrategy::Instance(), "annotate_transaction");
#if USE_ADAPTATION
ACL::Prototype ACLAdaptationService::RegistryProtoype(&ACLAdaptationService::RegistryEntry_, "adaptation_service");
ACLStrategised<const char *> ACLAdaptationService::RegistryEntry_(new ACLAdaptationServiceData, ACLAdaptationServiceStrategy::Instance(), "adaptation_service");
#endif
ACL::Prototype ACLSquidError::RegistryProtoype(&ACLSquidError::RegistryEntry_, "squid_error");
ACLStrategised<err_type> ACLSquidError::RegistryEntry_(new ACLSquidErrorData, ACLSquidErrorStrategy::Instance(), "squid_error");
ACL::Prototype Acl::ConnectionsEncrypted::RegistryProtoype(&Acl::ConnectionsEncrypted::RegistryEntry_, "connections_encrypted");
Acl::ConnectionsEncrypted Acl::ConnectionsEncrypted::RegistryEntry_("connections_encrypted");
+ACL::Prototype ACLHasComponent::RegistryProtoype(&ACLHasComponent::RegistryEntry_, "has");
+ACLStrategised<ACLChecklist *> ACLHasComponent::RegistryEntry_(new ACLHasComponentData, ACLHasComponentStrategy::Instance(), "has");
+
=== added file 'src/acl/HasComponent.cc'
--- src/acl/HasComponent.cc 1970-01-01 00:00:00 +0000
+++ src/acl/HasComponent.cc 2017-05-04 14:28:12 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "acl/HasComponent.h"
+#include "acl/HasComponentData.h"
+
+int
+ACLHasComponentStrategy::match(ACLData<MatchType> * &data, ACLFilledChecklist *checklist, ACLFlags &flags)
+{
+ ACLHasComponentData *cdata = dynamic_cast<ACLHasComponentData*>(data);
+ assert(cdata);
+ return cdata->match(checklist);
+}
+
+ACLHasComponentStrategy *
+ACLHasComponentStrategy::Instance()
+{
+ return &Instance_;
+}
+
+ACLHasComponentStrategy ACLHasComponentStrategy::Instance_;
+
=== added file 'src/acl/HasComponent.h'
--- src/acl/HasComponent.h 1970-01-01 00:00:00 +0000
+++ src/acl/HasComponent.h 2017-05-04 14:44:45 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_ACLHASCOMPONENT_H
+#define SQUID_ACLHASCOMPONENT_H
+
+#include "acl/Strategised.h"
+#include "acl/Strategy.h"
+
+/// \ingroup ACLAPI
+class ACLHasComponentStrategy : public ACLStrategy<ACLChecklist *>
+{
+public:
+ static ACLHasComponentStrategy *Instance();
+ ACLHasComponentStrategy(ACLHasComponentStrategy const &) = delete;
+ ACLHasComponentStrategy& operator=(ACLHasComponentStrategy const &) = delete;
+ virtual int match(ACLData<MatchType> * &, ACLFilledChecklist *, ACLFlags &);
+
+private:
+ static ACLHasComponentStrategy Instance_;
+ ACLHasComponentStrategy() { }
+};
+
+/// \ingroup ACLAPI
+class ACLHasComponent
+{
+private:
+ static ACL::Prototype RegistryProtoype;
+ static ACLStrategised<ACLChecklist *> RegistryEntry_;
+};
+
+#endif
+
=== added file 'src/acl/HasComponentData.cc'
--- src/acl/HasComponentData.cc 1970-01-01 00:00:00 +0000
+++ src/acl/HasComponentData.cc 2017-05-04 14:37:06 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "acl/HasComponentData.h"
+#include "cache_cf.h"
+#include "ConfigParser.h"
+#include "sbuf/Algorithms.h"
+
+ACLHasComponentData::ACLHasComponentData()
+ : componentMethods(coEnd, nullptr)
+{ }
+
+void
+ACLHasComponentData::parse()
+{
+ const char *tok = ConfigParser::NextToken();
+ if (!tok) {
+ debugs(28, DBG_CRITICAL, "FATAL: \"has\" acl argument missing");
+ self_destruct();
+ return;
+ }
+ if (ConfigParser::PeekAtToken()) {
+ debugs(28, DBG_CRITICAL, "FATAL: multiple components not supported for \"has\" acl");
+ self_destruct();
+ return;
+ }
+ parseComponent(tok);
+}
+
+bool
+ACLHasComponentData::match(ACLChecklist *checklist)
+{
+ for (const auto method: componentMethods)
+ if (method && (checklist->*method)())
+ return true;
+ return false;
+}
+
+SBufList
+ACLHasComponentData::dump() const
+{
+ SBufList sl;
+ if (componentMethods.at(coRequest))
+ sl.push_back(SBuf("request"));
+ if (componentMethods.at(coResponse))
+ sl.push_back(SBuf("response"));
+ if (componentMethods.at(coAle))
+ sl.push_back(SBuf("ALE"));
+ return sl;
+}
+
+void
+ACLHasComponentData::parseComponent(const char *token)
+{
+ if (strcmp(token, "request") == 0)
+ componentMethods[coRequest] = &ACLChecklist::hasRequest;
+ else if (strcmp(token, "response") == 0)
+ componentMethods[coResponse] = &ACLChecklist::hasReply;
+ else if (strcmp(token, "ALE") == 0)
+ componentMethods[coAle] = &ACLChecklist::hasAle;
+ else {
+ debugs(28, DBG_CRITICAL, "FATAL: unsupported component '" << token << "' for 'has' acl");
+ self_destruct();
+ }
+}
+
+ACLData<ACLChecklist *> *
+ACLHasComponentData::clone() const
+{
+ return new ACLHasComponentData(*this);
+}
+
=== added file 'src/acl/HasComponentData.h'
--- src/acl/HasComponentData.h 1970-01-01 00:00:00 +0000
+++ src/acl/HasComponentData.h 2017-05-04 14:36:47 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_ACLHASCOMPONENTDATA_H
+#define SQUID_ACLHASCOMPONENTDATA_H
+
+#include "acl/Checklist.h"
+#include "acl/Data.h"
+
+/// \ingroup ACLAPI
+class ACLHasComponentData : public ACLData<ACLChecklist *>
+{
+ MEMPROXY_CLASS(ACLHasComponentData);
+
+public:
+ ACLHasComponentData();
+
+ /* ACLData<M> API */
+ virtual bool match(ACLChecklist *) override;
+ virtual SBufList dump() const override;
+ virtual void parse() override;
+ virtual bool empty() const override { return false; }
+ virtual ACLData<ACLChecklist *> *clone() const override;
+
+private:
+ enum ComponentKind { coRequest = 0, coResponse, coAle, coEnd };
+ void parseComponent(const char *token);
+
+ typedef bool (ACLChecklist::*ComponentCheck)() const;
+ /// component check callbacks, ordered by component kind ID
+ std::vector<ComponentCheck> componentMethods;
+};
+
+#endif
+
=== modified file 'src/acl/Makefile.am'
--- src/acl/Makefile.am 2017-01-30 12:46:15 +0000
+++ src/acl/Makefile.am 2017-04-30 11:11:27 +0000
@@ -48,60 +48,64 @@ libacls_la_SOURCES = \
StringData.h \
Time.cc \
Time.h \
TimeData.cc \
TimeData.h \
AllOf.cc \
AllOf.h \
AnnotateClient.cc \
AnnotateClient.h \
AnnotateTransaction.cc \
AnnotateTransaction.h \
AnnotationData.cc \
AnnotationData.h \
AnyOf.cc \
AnyOf.h \
Asn.cc \
Asn.h \
Browser.cc \
Browser.h \
ConnectionsEncrypted.cc \
ConnectionsEncrypted.h \
DestinationAsn.h \
DestinationDomain.cc \
DestinationDomain.h \
DestinationIp.cc \
DestinationIp.h \
DomainData.cc \
DomainData.h \
ExtUser.cc \
ExtUser.h \
+ HasComponent.cc \
+ HasComponent.h \
+ HasComponentData.cc \
+ HasComponentData.h \
HierCodeData.cc \
HierCodeData.h \
HierCode.cc \
HierCode.h \
HttpHeaderData.cc \
HttpHeaderData.h \
HttpRepHeader.cc \
HttpRepHeader.h \
HttpReqHeader.cc \
HttpReqHeader.h \
HttpStatus.cc \
HttpStatus.h \
Ip.cc \
Ip.h \
LocalIp.cc \
LocalIp.h \
LocalPort.cc \
LocalPort.h \
MaxConnection.cc \
MaxConnection.h \
Method.cc \
MethodData.cc \
MethodData.h \
Method.h \
MyPortName.cc \
MyPortName.h \
Note.h \
Note.cc \
NoteData.h \
NoteData.cc \
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2017-03-16 07:52:37 +0000
+++ src/cf.data.pre 2017-05-04 14:25:32 +0000
@@ -1272,60 +1272,87 @@ DOC_START
# and all future master transactions on the annotated connection.
# See the annotate_transaction ACL for details.
#
# For example, the following configuration avoids rewriting URLs
# of transactions bumped by SslBump:
#
# # First, mark bumped connections:
# acl markBumped annotate_client bumped=true
# ssl_bump peek acl1
# ssl_bump stare acl2
# ssl_bump bump acl3 markBumped
# ssl_bump splice all
#
# # Second, do not send marked transactions to the redirector:
# acl markedBumped note bumped true
# url_rewrite_access deny markedBumped
#
# # Note that the following would not have worked because acl3 alone
# # does not determine whether the connection is going to be bumped:
# url_rewrite_access deny acl3 # Wrong!
acl aclname adaptation_service service ...
# Matches the name of any icap_service, ecap_service,
# adaptation_service_set, or adaptation_service_chain that Squid
# has used (or attempted to use) for the master transaction.
# This ACL must be defined after the corresponding adaptation
# service is named in squid.conf. This ACL is usable with
# adaptation_meta because it starts matching immediately after
# the service has been selected for adaptation.
+ acl aclname has component
+ # matches a transaction "component" [fast]
+ #
+ # Supported transaction components are:
+ # request: transaction has a request header (at least)
+ # response: transaction has a response header (at least)
+ # ALE: transaction has an internally-generated Access Log Entry
+ # structure; bugs notwithstanding, all transaction have it
+ #
+ # For example, the following configuration helps when dealing with HTTP
+ # clients that close connections without sending a request header:
+ #
+ # acl hasRequest has request
+ # acl logMe note important_transaction
+ # # avoid "logMe ACL is used in context without an HTTP request" warnings
+ # access_log ... logformat=detailed hasRequest logMe
+ # # log request-less transactions, instead of ignoring them
+ # access_log ... logformat=brief !hasRequest
+ #
+ # Multiple components are not supported for one "acl" rule, but
+ # can be specified (and are ORed) using multiple same-name rules:
+ #
+ # # OK, this strange logging daemon needs request or response,
+ # # but can work without either a request or a response:
+ # acl hasWhatMyLoggingDaemonNeeds has request
+ # acl hasWhatMyLoggingDaemonNeeds has response
+
IF USE_OPENSSL
acl aclname ssl_error errorname
# match against SSL certificate validation error [fast]
#
# For valid error names see in @DEFAULT_ERROR_DIR@/templates/error-details.txt
# template file.
#
# The following can be used as shortcuts for certificate properties:
# [ssl::]certHasExpired: the "not after" field is in the past
# [ssl::]certNotYetValid: the "not before" field is in the future
# [ssl::]certUntrusted: The certificate issuer is not to be trusted.
# [ssl::]certSelfSigned: The certificate is self signed.
# [ssl::]certDomainMismatch: The certificate CN domain does not
# match the name the name of the host we are connecting to.
#
# The ssl::certHasExpired, ssl::certNotYetValid, ssl::certDomainMismatch,
# ssl::certUntrusted, and ssl::certSelfSigned can also be used as
# predefined ACLs, just like the 'all' ACL.
#
# NOTE: The ssl_error ACL is only supported with sslproxy_cert_error,
# sslproxy_cert_sign, and sslproxy_cert_adapt options.
acl aclname server_cert_fingerprint [-sha1] fingerprint
# match against server SSL certificate fingerprint [fast]
#
# The fingerprint is the digest of the DER encoded version
# of the whole certificate. The user should use the form: XX:XX:...
# Optional argument specifies the digest algorithm to use.
# The SHA1 digest algorithm is the default and is currently
# the only algorithm supported (-sha1).
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev