diff --git a/CHANGES b/CHANGES index 5007ec0568..23976a5918 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5111. [bug] Occluded DNSKEY records could make it into the + delegating NSEC/NSEC3 bitmap. [GL #742] + 5110. [placeholder] 5109. [cleanup] Remove support for RSAMD5 algorithm. [GL #628] diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index 306205c57c..1bbfd203a5 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -66,6 +66,7 @@ rm -f ./ns3/managed-future.example.db rm -f ./ns3/multiple.example.db ./ns3/nsec3-unknown.example.db ./ns3/nsec3.example.db rm -f ./ns3/nsec3.nsec3.example.db rm -f ./ns3/nsec3.optout.example.db +rm -f ./ns3/occluded.example.db rm -f ./ns3/optout-unknown.example.db ./ns3/optout.example.db rm -f ./ns3/optout.nsec3.example.db rm -f ./ns3/optout.optout.example.db diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh index 623228655d..178d819dd6 100644 --- a/bin/tests/system/dnssec/ns2/sign.sh +++ b/bin/tests/system/dnssec/ns2/sign.sh @@ -27,7 +27,7 @@ for subdomain in secure badds bogus dynamic keyless nsec3 optout \ kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \ ttlpatch split-dnssec split-smart expired expiring upper lower \ dnskey-unknown dnskey-nsec3-unknown managed-future revkey \ - dname-at-apex-nsec3 + dname-at-apex-nsec3 occluded do cp "../ns3/dsset-$subdomain.example$TP" . done diff --git a/bin/tests/system/dnssec/ns3/named.conf.in b/bin/tests/system/dnssec/ns3/named.conf.in index 87b10533a0..0218ef1100 100644 --- a/bin/tests/system/dnssec/ns3/named.conf.in +++ b/bin/tests/system/dnssec/ns3/named.conf.in @@ -299,6 +299,11 @@ zone "dname-at-apex-nsec3.example" { file "dname-at-apex-nsec3.example.db.signed"; }; +zone "occluded.example" { + type master; + file "occluded.example.db.signed"; +}; + include "siginterval.conf"; include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns3/occluded.example.db.in b/bin/tests/system/dnssec/ns3/occluded.example.db.in new file mode 100644 index 0000000000..77a1cfb63d --- /dev/null +++ b/bin/tests/system/dnssec/ns3/occluded.example.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a.b A 10.0.0.1 +delegation NS ns + A 10.53.0.3 + AAAA 2002:: diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh index 285d2158e4..31278280e9 100644 --- a/bin/tests/system/dnssec/ns3/sign.sh +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -558,3 +558,18 @@ kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3fk "$zone") zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3 "$zone") cat "$infile" "${kskname}.key" "${zskname}.key" >"$zonefile" "$SIGNER" -P -3 - -o "$zone" "$zonefile" > /dev/null 2>&1 + +# +# A NSEC zone with occuded data at the delegation +# +zone=occluded.example +infile=occluded.example.db.in +zonefile=occluded.example.db +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" "$zone") +keyname=$("$KEYGEN" -q -a RSASHA1 -n ENTITY -T KEY "delegation.$zone") +dnskeyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "delegation.$zone") +$DSFROMKEY "$dnskeyname.key" > "dsset-delegation.${zone}$TP" +cat "$infile" "${kskname}.key" "${zskname}.key" "${keyname}.key" \ + "${dnskeyname}.key" "dsset-delegation.${zone}$TP" >"$zonefile" +"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null 2>&1 diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 4ae9cb0b06..fc5e21e7e2 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -3595,6 +3595,16 @@ n=$((n+1)) test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) +echo_i "check that DNSKEY and other occluded data are excluded from the delegating bitmap ($n)" +ret=0 +dig_with_opts axfr occluded.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 +grep "^delegation.occluded.example..*NSEC.*NS KEY DS RRSIG NSEC$" dig.out.ns3.test$n > /dev/null || ret=1 +grep "^delegation.occluded.example..*DNSKEY.*" dig.out.ns3.test$n > /dev/null || ret=1 +grep "^delegation.occluded.example..*AAAA.*" dig.out.ns3.test$n > /dev/null || ret=1 +n=$((n+1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + # Note: after this check, ns4 will not be validating any more; do not add any # further validation tests employing ns4 below this check. echo_i "check that validation defaults to off when dnssec-enable is off ($n)" diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index a42e5bf263..81ecce2bfc 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -590,7 +590,6 @@ dns_rdatatype_isknown(dns_rdatatype_t type); * */ - isc_result_t dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add, void *arg); @@ -683,6 +682,16 @@ dns_rdatatype_atparent(dns_rdatatype_t type); * */ +bool +dns_rdatatype_atcname(dns_rdatatype_t type); +/*%< + * Return true iff rdata of type 'type' can appear beside a cname. + * + * Requires: + * \li 'type' is a valid rdata type. + * + */ + unsigned int dns_rdatatype_attributes(dns_rdatatype_t rdtype); /*%< @@ -711,10 +720,12 @@ dns_rdatatype_attributes(dns_rdatatype_t rdtype); #define DNS_RDATATYPEATTR_UNKNOWN 0x00000040U /*% Is META, and can only be in a question section */ #define DNS_RDATATYPEATTR_QUESTIONONLY 0x00000080U -/*% is META, and can NOT be in a question section */ +/*% Is META, and can NOT be in a question section */ #define DNS_RDATATYPEATTR_NOTQUESTION 0x00000100U /*% Is present at zone cuts in the parent, not the child */ #define DNS_RDATATYPEATTR_ATPARENT 0x00000200U +/*% Can exist along side a CNAME */ +#define DNS_RDATATYPEATTR_ATCNAME 0x00000400U dns_rdatatype_t dns_rdata_covers(dns_rdata_t *rdata); diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index ea5000fab2..ebd608ae9b 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -2283,6 +2283,14 @@ dns_rdatatype_questiononly(dns_rdatatype_t type) { return (false); } +bool +dns_rdatatype_atcname(dns_rdatatype_t type) { + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATCNAME) != 0) { + return (true); + } + return (false); +} + bool dns_rdatatype_atparent(dns_rdatatype_t type) { if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0) @@ -2310,10 +2318,11 @@ dns_rdatatype_isdnssec(dns_rdatatype_t type) { bool dns_rdatatype_iszonecutauth(dns_rdatatype_t type) { - if ((dns_rdatatype_attributes(type) - & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH)) + if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH) != 0) + { return (true); + } return (false); } diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c index 1927ee46b8..7be66d1f00 100644 --- a/lib/dns/rdata/generic/ds_43.c +++ b/lib/dns/rdata/generic/ds_43.c @@ -16,7 +16,8 @@ #define RDATA_GENERIC_DS_43_C #define RRTYPE_DS_ATTRIBUTES \ - (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT) + ( DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \ + DNS_RDATATYPEATTR_ATPARENT ) #include diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c index 34c0cea017..44cbdf3a5e 100644 --- a/lib/dns/rdata/generic/key_25.c +++ b/lib/dns/rdata/generic/key_25.c @@ -16,7 +16,8 @@ #include -#define RRTYPE_KEY_ATTRIBUTES (0) +#define RRTYPE_KEY_ATTRIBUTES \ + ( DNS_RDATATYPEATTR_ATCNAME | DNS_RDATATYPEATTR_ZONECUTAUTH ) static inline isc_result_t generic_fromtext_key(ARGS_FROMTEXT) { diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c index 05e575b62c..0ba688cec0 100644 --- a/lib/dns/rdata/generic/nsec_47.c +++ b/lib/dns/rdata/generic/nsec_47.c @@ -18,7 +18,9 @@ * The attributes do not include DNS_RDATATYPEATTR_SINGLETON * because we must be able to handle a parent/child NSEC pair. */ -#define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) +#define RRTYPE_NSEC_ATTRIBUTES \ + ( DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \ + DNS_RDATATYPEATTR_ATCNAME ) static inline isc_result_t fromtext_nsec(ARGS_FROMTEXT) { diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c index fb945ff1ed..8bc8d21f3f 100644 --- a/lib/dns/rdata/generic/rrsig_46.c +++ b/lib/dns/rdata/generic/rrsig_46.c @@ -14,7 +14,9 @@ #ifndef RDATA_GENERIC_RRSIG_46_C #define RDATA_GENERIC_RRSIG_46_C -#define RRTYPE_RRSIG_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) +#define RRTYPE_RRSIG_ATTRIBUTES \ + ( DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \ + DNS_RDATATYPEATTR_ATCNAME ) static inline isc_result_t fromtext_rrsig(ARGS_FROMTEXT) { diff --git a/lib/dns/tests/rdata_test.c b/lib/dns/tests/rdata_test.c index 46c30a4ad5..0c4906c3cd 100644 --- a/lib/dns/tests/rdata_test.c +++ b/lib/dns/tests/rdata_test.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -1499,6 +1500,90 @@ wks(void **state) { dns_rdatatype_wks, sizeof(dns_rdata_in_wks_t)); } +static void +atcname(void **state) { + unsigned int i; + UNUSED(state); +#define UNR "# Unexpected result from dns_rdatatype_atcname for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_atcname((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_nsec: + case dns_rdatatype_key: + case dns_rdatatype_rrsig: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + + } +#undef UNR +} + +static void +atparent(void **state) { + unsigned int i; + UNUSED(state); +#define UNR "# Unexpected result from dns_rdatatype_atparent for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_atparent((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_ds: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + + } +#undef UNR +} + +static void +iszonecutauth(void **state) { + unsigned int i; + UNUSED(state); +#define UNR "# Unexpected result from dns_rdatatype_iszonecutauth for type %u\n" + for (i = 0; i < 0xffffU; i++) { + bool tf = dns_rdatatype_iszonecutauth((dns_rdatatype_t)i); + switch (i) { + case dns_rdatatype_ns: + case dns_rdatatype_ds: + case dns_rdatatype_nsec: + case dns_rdatatype_key: + case dns_rdatatype_rrsig: + if (!tf) { + print_message(UNR, i); + } + assert_true(tf); + break; + default: + if (tf) { + print_message(UNR, i); + } + assert_false(tf); + break; + } + + } +#undef UNR +} + int main(void) { const struct CMUnitTest tests[] = { @@ -1516,6 +1601,9 @@ main(void) { cmocka_unit_test_setup_teardown(nsec3, _setup, _teardown), cmocka_unit_test_setup_teardown(nxt, _setup, _teardown), cmocka_unit_test_setup_teardown(wks, _setup, _teardown), + cmocka_unit_test_setup_teardown(atcname, NULL, NULL), + cmocka_unit_test_setup_teardown(atparent, NULL, NULL), + cmocka_unit_test_setup_teardown(iszonecutauth, NULL, NULL), }; return (cmocka_run_group_tests(tests, NULL, NULL)); diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 9642fa48cc..72a93d225f 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -826,6 +826,7 @@ dns_rdataslab_fromrdataset dns_rdataslab_merge dns_rdataslab_size dns_rdataslab_subtract +dns_rdatatype_atcname dns_rdatatype_atparent dns_rdatatype_attributes dns_rdatatype_format diff --git a/lib/ns/update.c b/lib/ns/update.c index a387dfd11d..2a3c7d244f 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -798,8 +798,10 @@ static isc_result_t cname_compatibility_action(void *data, dns_rdataset_t *rrset) { UNUSED(data); if (rrset->type != dns_rdatatype_cname && - ! dns_rdatatype_isdnssec(rrset->type)) + ! dns_rdatatype_atcname(rrset->type)) + { return (ISC_R_EXISTS); + } return (ISC_R_SUCCESS); } @@ -2852,7 +2854,7 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_rdatatype_cname, 0, &flag)); if (flag && - ! dns_rdatatype_isdnssec(rdata.type)) + ! dns_rdatatype_atcname(rdata.type)) { update_log(client, zone, LOGLEVEL_PROTOCOL,