debugs(28, 5, "aclIpParseIpData: " << t);
- /* Special ACL RHS "all" matches entire Internet */
- if (strcmp(t, "all") == 0) {
- debugs(28, 9, "aclIpParseIpData: magic 'all' found.");
- q->addr1.setAnyAddr();
- q->addr2.setEmpty();
- q->mask.setAnyAddr();
- return q;
- }
-
- /* Detect some old broken strings equivalent to 'all'.
- * treat them nicely. But be loud until its fixed. */
- if (strcmp(t, "0/0") == 0 || strcmp(t, "0.0.0.0/0") == 0 || strcmp(t, "0.0.0.0/0.0.0.0") == 0 ||
- strcmp(t, "0.0.0.0-255.255.255.255") == 0 || strcmp(t, "0.0.0.0-0.0.0.0/0") == 0) {
-
- debugs(28,DBG_CRITICAL, "ERROR: '" << t << "' needs to be replaced by the term 'all'.");
- debugs(28,DBG_CRITICAL, "SECURITY NOTICE: Overriding config setting. Using 'all' instead.");
- q->addr1.setAnyAddr();
- q->addr2.setEmpty();
- q->mask.setAnyAddr();
- return q;
- }
-
- /* Special ACL RHS "ipv4" matches IPv4 Internet
- * A nod to IANA; we include the entire class space in case
- * they manage to find a way to recover and use it */
- if (strcmp(t, "ipv4") == 0) {
- q->mask.setNoAddr();
- q->mask.applyMask(0, AF_INET);
- return q;
- }
-
- /* Special ACL RHS "ipv6" matches IPv6-Unicast Internet */
- if (strcmp(t, "ipv6") == 0) {
- debugs(28, 9, "aclIpParseIpData: magic 'ipv6' found.");
- r = q; // save head of the list for result.
-
- /* 0000::/4 is a mix of localhost and obsolete IPv4-mapping space. Not valid outside this host. */
-
- /* Future global unicast space: 1000::/4 */
- q->addr1 = "1000::";
- q->mask.setNoAddr();
- q->mask.applyMask(4, AF_INET6);
-
- /* Current global unicast space: 2000::/4 = (2000::/4 - 3000::/4) */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "2000::";
- q->mask.setNoAddr();
- q->mask.applyMask(3, AF_INET6);
-
- /* Future global unicast space: 4000::/2 = (4000::/4 - 7000::/4) */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "4000::";
- q->mask.setNoAddr();
- q->mask.applyMask(2, AF_INET6);
-
- /* Future global unicast space: 8000::/2 = (8000::/4 - B000::/4) */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "8000::";
- q->mask.setNoAddr();
- q->mask.applyMask(2, AF_INET6);
-
- /* Future global unicast space: C000::/3 = (C000::/4 - D000::/4) */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "C000::";
- q->mask.setNoAddr();
- q->mask.applyMask(3, AF_INET6);
-
- /* Future global unicast space: E000::/4 */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "E000::";
- q->mask.setNoAddr();
- q->mask.applyMask(4, AF_INET6);
-
- /* F000::/4 is mostly reserved non-unicast. With some exceptions ... */
-
- /* RFC 4193 Unique-Local unicast space: FC00::/7 */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "FC00::";
- q->mask.setNoAddr();
- q->mask.applyMask(7, AF_INET6);
-
- /* Link-Local unicast space: FE80::/10 */
- q->next = new acl_ip_data;
- q = q->next;
- q->addr1 = "FE80::";
- q->mask.setNoAddr();
- q->mask.applyMask(10, AF_INET6);
-
- return r;
- }
-
// IPv4
if (sscanf(t, SCAN_ACL1_4, addr1, addr2, mask) == 3) {
debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN1-v4: " << SCAN_ACL1_4);
return q;
}
+/// handles special ACL data parameters that apply to the whole ACLIP object
+/// \returns true if input token is such a special parameter
+bool
+ACLIP::parseGlobal(const char * const token)
+{
+ // "all" matches entire Internet
+ if (strcmp(token, "all") == 0) {
+ debugs(28, 8, "found " << token);
+ matchAnyIpv4 = true;
+ matchAnyIpv6 = true;
+ // TODO: Ignore all other ACL data parameters, with a once/ACL warning.
+ return true;
+ }
+
+ // "ipv4" matches IPv4 Internet
+ if (strcmp(token, "ipv4") == 0) {
+ debugs(28, 8, "found " << token);
+ matchAnyIpv4 = true;
+ // TODO: Ignore all IPv4 data parameters, with a once/ACL warning.
+ return true;
+ }
+
+ // "ipv4" matches IPv6 Internet
+ if (strcmp(token, "ipv6") == 0) {
+ debugs(28, 8, "found " << token);
+ matchAnyIpv6 = true;
+ // TODO: Ignore all IPv6 data parameters, with a once/ACL warning.
+ return true;
+ }
+
+ /* Detect some old broken strings equivalent to 'all'.
+ * treat them nicely. But be loud until its fixed. */
+ if (strcmp(token, "0/0") == 0 ||
+ strcmp(token, "0.0.0.0/0") == 0 ||
+ strcmp(token, "0.0.0.0/0.0.0.0") == 0 ||
+ strcmp(token, "0.0.0.0-255.255.255.255") == 0 ||
+ strcmp(token, "0.0.0.0-0.0.0.0/0") == 0) {
+
+ debugs(28,DBG_CRITICAL, "ERROR: '" << token << "' needs to be replaced by the term 'all'.");
+ debugs(28,DBG_CRITICAL, "SECURITY NOTICE: Overriding config setting. Using 'all' instead.");
+ matchAnyIpv4 = true;
+ matchAnyIpv6 = true;
+ return true;
+ }
+
+ return false;
+}
+
void
ACLIP::parse()
{
data = new IPSplay();
while (char *t = ConfigParser::strtokFile()) {
+ if (parseGlobal(t))
+ continue;
+
acl_ip_data *q = acl_ip_data::FactoryParse(t);
while (q != nullptr) {
ACLIP::dump() const
{
IpAclDumpVisitor visitor;
+
+ if (matchAnyIpv4 && matchAnyIpv6)
+ visitor.contents.push_back(SBuf("all"));
+ else if (matchAnyIpv4)
+ visitor.contents.push_back(SBuf("ipv4"));
+ else if (matchAnyIpv6)
+ visitor.contents.push_back(SBuf("ipv6"));
+
data->visit(visitor);
return visitor.contents;
}
bool
ACLIP::empty() const
{
- return data->empty();
+ return data->empty() && !matchAnyIpv4 && !matchAnyIpv6;
}
int
ACLIP::match(const Ip::Address &clientip)
{
+ if (matchAnyIpv4) {
+ if (matchAnyIpv6) {
+ debugs(28, 3, clientip << " found, matched 'all'");
+ return true;
+ }
+ if (clientip.isIPv4()) {
+ debugs(28, 3, clientip << " found, matched 'ipv4'");
+ return true;
+ }
+ // fall through to look for an IPv6 match among IP parameters
+ } else if (matchAnyIpv6) {
+ if (clientip.isIPv6()) {
+ debugs(28, 3, clientip << " found, matched 'ipv6'");
+ return true;
+ }
+ // fall through to look for an IPv4 match among IP parameters
+ }
+
static acl_ip_data ClientAddress;
/*
* aclIpAddrNetworkCompare() takes two acl_ip_data pointers as