From: Marek VavruĊĦa Date: Mon, 29 Jun 2015 01:00:44 +0000 (+0200) Subject: lib/zonecut: filter ANY and loopback addresses X-Git-Tag: v1.0.0-beta1~96^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0db5e61c45eaeea943f836386635e249663bc823;p=thirdparty%2Fknot-resolver.git lib/zonecut: filter ANY and loopback addresses --- diff --git a/lib/zonecut.c b/lib/zonecut.c index 120e5b2aa..f3b361cd5 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -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 */ diff --git a/tests/test_zonecut.c b/tests/test_zonecut.c index 202899c3a..772de3e99 100644 --- a/tests/test_zonecut.c +++ b/tests/test_zonecut.c @@ -14,6 +14,8 @@ along with this program. If not, see . */ +#include + #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) }; diff --git a/tests/testdata_notimpl/iter_donotq127.rpl b/tests/testdata/iter_donotq127.rpl similarity index 80% rename from tests/testdata_notimpl/iter_donotq127.rpl rename to tests/testdata/iter_donotq127.rpl index 15f9fff60..d8bc79dee 100644 --- a/tests/testdata_notimpl/iter_donotq127.rpl +++ b/tests/testdata/iter_donotq127.rpl @@ -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