From: Amos Jeffries Date: Tue, 10 Mar 2009 14:29:30 +0000 (+1300) Subject: Bug 2559: Problem parsing /0 and /0.0.0.0 X-Git-Tag: SQUID_3_2_0_1~1125 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2c1b95902551d7636f02dd658abcb202ce2e9c32;p=thirdparty%2Fsquid.git Bug 2559: Problem parsing /0 and /0.0.0.0 netmask strikes again. Squid was parsing /0 on an IPv4 as mask /0.0.0.0 before v4-mapping the mask to /96 IPv6. Which is invalid CIDR size for IPv4 and maps back as 0.0.0.0/32 there during ACL matching. This affects any input of /0 and equivalents but in a fail-closed way. Force /0 to the magic noaddr mask regardless of the protocol. Also adds a lot of level-9 debugs for tracing other issues in IP ACL parse --- diff --git a/src/ACLIP.cc b/src/ACLIP.cc index c1372098eb..3f9d56410c 100644 --- a/src/ACLIP.cc +++ b/src/ACLIP.cc @@ -266,6 +266,7 @@ acl_ip_data::FactoryParse(const char *t) /* Special ACL RHS "all" matches entire Internet */ if (strcasecmp(t, "all") == 0) { + debugs(28, 9, "aclIpParseIpData: magic 'all' found."); q->addr1.SetAnyAddr(); q->addr2.SetEmpty(); q->mask.SetAnyAddr(); @@ -275,39 +276,51 @@ acl_ip_data::FactoryParse(const char *t) #if USE_IPV6 /* Special ACL RHS "ipv6" matches IPv6-Unicast Internet */ if (strcasecmp(t, "ipv6") == 0) { + debugs(28, 9, "aclIpParseIpData: magic 'ipv6' found."); t = "2000::/3"; + /* AYJ: due to the nature os IPv6 this will not always work, + * we may need to turn recursive to catch all the valid v6 sub-nets. */ } #endif // IPv4 if (sscanf(t, SCAN_ACL1_4, addr1, addr2, mask) == 3) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN1-v4: " << SCAN_ACL1_4); iptype=AF_INET; } else if (sscanf(t, SCAN_ACL2_4, addr1, addr2, &c) >= 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN2-v4: " << SCAN_ACL2_4); mask[0] = '\0'; iptype=AF_INET; } else if (sscanf(t, SCAN_ACL3_4, addr1, mask) == 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN3-v4: " << SCAN_ACL3_4); addr2[0] = '\0'; iptype=AF_INET; } else if (sscanf(t, SCAN_ACL4_4, addr1,&c) == 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN4-v4: " << SCAN_ACL4_4); addr2[0] = '\0'; mask[0] = '\0'; iptype=AF_INET; // IPv6 } else if (sscanf(t, SCAN_ACL1_6, addr1, addr2, mask) == 3) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN1-v4: " << SCAN_ACL1_6); iptype=AF_INET6; } else if (sscanf(t, SCAN_ACL2_6, addr1, addr2, &c) >= 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN2-v4: " << SCAN_ACL2_6); mask[0] = '\0'; iptype=AF_INET6; } else if (sscanf(t, SCAN_ACL3_6, addr1, mask) == 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN3-v4: " << SCAN_ACL3_6); addr2[0] = '\0'; iptype=AF_INET6; } else if (sscanf(t, SCAN_ACL4_6, addr1, mask) == 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: SCAN4-v4: " << SCAN_ACL4_6); addr2[0] = '\0'; iptype=AF_INET6; // Neither } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) { + debugs(28, 9, "aclIpParseIpData: '" << t << "' matched: non-IP pattern: %[^/]/%s"); addr2[0] = '\0'; } else if (sscanf(t, "%s", addr1) == 1) { /* @@ -420,6 +433,8 @@ acl_ip_data::FactoryParse(const char *t) if (changed) debugs(28, 0, "aclIpParseIpData: WARNING: Netmask masks away part of the specified IP in '" << t << "'"); + debugs(28,9, HERE << "Parsed: " << q->addr1 << "-" << q->addr2 << "/" << q->mask << "(/" << q->mask.GetCIDR() <<")"); + /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */ /* Same as IPv6 (not so trivial to depict) */ return q; diff --git a/src/ip/IpAddress.cc b/src/ip/IpAddress.cc index ee7dcd4a8e..2cf158280f 100644 --- a/src/ip/IpAddress.cc +++ b/src/ip/IpAddress.cc @@ -208,6 +208,12 @@ bool IpAddress::ApplyMask(const unsigned int cidr, int mtype) if (cidr > 32 && mtype == AF_INET) return false; + if (cidr == 0) { + /* CIDR /0 is NoAddr regardless of the IPv4/IPv6 protocol */ + SetNoAddr(); + return true; + } + clearbits = (uint8_t)( (mtype==AF_INET6?128:32) -cidr); // short-cut