]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/zonecut: filter ANY and loopback addresses
authorMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 29 Jun 2015 01:00:44 +0000 (03:00 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 29 Jun 2015 01:00:44 +0000 (03:00 +0200)
lib/zonecut.c
tests/test_zonecut.c
tests/testdata/iter_donotq127.rpl [moved from tests/testdata_notimpl/iter_donotq127.rpl with 80% similarity]

index 120e5b2aade6c34324a8c500d3ee5fd87ce373d7..f3b361cd54790b9b6b9a59d01bccb4ab4a1eda6b 100644 (file)
@@ -143,6 +143,26 @@ int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src)
        return map_walk((map_t *)&src->nsset, copy_addr_set, dst);
 }
 
+/** @internal Filter ANY or loopback addresses. */
+static bool is_valid_addr(uint8_t *addr, size_t len)
+{
+       if (len == sizeof(struct in_addr)) {
+               /* Filter ANY and 127.0.0.0/8 */
+               uint32_t ip_host = ntohl(*(uint32_t *)(addr));
+               if (ip_host == 0 || (ip_host & 0xff000000) == 0x7f000000) {
+                       return false;
+               }
+       } else if (len == sizeof(struct in6_addr)) {
+               struct in6_addr ip6_mask;
+               memset(&ip6_mask, 0, sizeof(ip6_mask));
+               /* All except last byte are zeroed, last byte defines ANY/::1 */
+               if (memcmp(addr, ip6_mask.s6_addr, sizeof(ip6_mask.s6_addr) - 1) == 0) {
+                       return (addr[len - 1] > 1);
+               }
+       }
+       return true;
+}
+
 int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata)
 {
        if (!cut || !ns) {
@@ -162,9 +182,14 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
        if (rdata == NULL) {
                return kr_ok();
        }
-       /* Check for duplicates */
+       /* Check for invalid */
        uint16_t rdlen = knot_rdata_rdlen(rdata);
-       if (pack_obj_find(pack, knot_rdata_data(rdata), rdlen)) {
+       uint8_t *raw_addr = knot_rdata_data(rdata);
+       if (!is_valid_addr(raw_addr, rdlen)) {
+               return kr_error(EILSEQ);
+       }
+       /* Check for duplicates */
+       if (pack_obj_find(pack, raw_addr, rdlen)) {
                return kr_ok();
        }
        /* Push new address */
index 202899c3a4341321802c34b74ccad07e6be2a763..772de3e99d8f07ddef1c188d706c5e311783a474 100644 (file)
@@ -14,6 +14,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <netinet/in.h>
+
 #include "tests/test.h"
 #include "lib/zonecut.h"
 
@@ -33,6 +35,40 @@ static void test_zonecut_params(void **state)
        assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, NULL, NULL, 0), 0);
 }
 
+#define TEST_IP(cut, ip, expect) { \
+       knot_rdata_t rdata[knot_rdata_array_size(sizeof(ip))]; \
+       knot_rdata_init(rdata, sizeof(ip), (uint8_t *)&ip, 0); \
+       assert_int_equal(kr_zonecut_add(&(cut), (const uint8_t *)"\x02cz", rdata), (expect)); \
+} while (0)
+
+static void test_zonecut_filter(void **state)
+{
+       struct kr_zonecut cut;
+       kr_zonecut_init(&cut, (const uint8_t *)"", NULL);
+
+       /* IPv4 */
+       uint32_t ip4 = 0; /* 0.0.0.0 */
+       TEST_IP(cut, ip4, kr_error(EILSEQ));
+       ip4 = htonl(0x7f000002); /* 127.0.0.2 */
+       TEST_IP(cut, ip4, kr_error(EILSEQ));
+       ip4 = htonl(0x7fffffff); /* 127.255.255.255 */
+       TEST_IP(cut, ip4, kr_error(EILSEQ));
+       ip4 = htonl(0xff000001); /* 255.0.0.1 */
+       TEST_IP(cut, ip4, 0);
+       /* IPv6 */
+       struct in6_addr ip6;
+       memset(&ip6, 0, sizeof(ip6)); /* :: */
+       TEST_IP(cut, ip6.s6_addr, kr_error(EILSEQ));
+       ip6.s6_addr[15] = 0x01; /* ::1 */
+       TEST_IP(cut, ip6.s6_addr, kr_error(EILSEQ));
+       ip6.s6_addr[15] = 0x02; /* ::2 */
+       TEST_IP(cut, ip6.s6_addr, 0);
+
+       kr_zonecut_deinit(&cut);
+}
+
+#undef TEST_IP
+
 static void test_zonecut_copy(void **state)
 {
        const knot_dname_t *root = (const uint8_t *)"";
@@ -56,6 +92,7 @@ int main(void)
 {
        const UnitTest tests[] = {
                unit_test(test_zonecut_params),
+               unit_test(test_zonecut_filter),
                unit_test(test_zonecut_copy)
        };
 
similarity index 80%
rename from tests/testdata_notimpl/iter_donotq127.rpl
rename to tests/testdata/iter_donotq127.rpl
index 15f9fff60860d70355b95c1756429e09d4583bf1..d8bc79dee172c7b347d9bb28092ad4c4018d32b7 100644 (file)
@@ -28,11 +28,12 @@ ENTRY_END
 
 ENTRY_BEGIN
 MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
 SECTION QUESTION
-a.gtld-servers.net. IN AAAA
-SECTION ANSWER
+a.gtld-servers.net.    IN      AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
 ENTRY_END
 
 ENTRY_BEGIN
@@ -63,6 +64,26 @@ SECTION ADDITIONAL
 a.gtld-servers.net.    IN      A       192.5.6.30
 ENTRY_END
 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com.        IN      AAAA
+SECTION AUTHORITY
+com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns2.example.com.       IN      AAAA
+SECTION AUTHORITY
+com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
 ENTRY_BEGIN
 MATCH opcode subdomain
 ADJUST copy_id copy_query
@@ -77,6 +98,7 @@ SECTION ADDITIONAL
 ns.example.com.                IN      A       127.255.255.255
 ns2.example.com.       IN      A       127.0.0.2
 ENTRY_END
+
 RANGE_END
 
 ; ns.example.com.
@@ -110,6 +132,17 @@ example.com.       IN NS   ns.example.com.
 SECTION ADDITIONAL
 ns.example.com.                IN      A       1.2.3.4
 ENTRY_END
+
+RANGE_END
+
+; ns.example.com trap
+RANGE_BEGIN 0 100
+       ADDRESS 127.255.255.255
+RANGE_END
+
+; ns.example.com trap
+RANGE_BEGIN 0 100
+       ADDRESS 127.0.0.2
 RANGE_END
 
 STEP 1 QUERY