]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Treat records below a DNAME as out-of-zone data
authorMichał Kępień <michal@isc.org>
Wed, 13 Jun 2018 10:19:54 +0000 (12:19 +0200)
committerMichał Kępień <michal@isc.org>
Wed, 13 Jun 2018 11:01:54 +0000 (13:01 +0200)
DNAME records indicate bottom of zone and thus no records below a DNAME
should be DNSSEC-signed or included in NSEC(3) chains.  Add a helper
function, has_dname(), for detecting DNAME records at a given node.
Prevent signing DNAME-obscured records.  Check that DNAME-obscured
records are not signed.

(cherry picked from commit 6d8a514ecbd72d1f8b2b12fbbbca5c5f87085abd)

bin/dnssec/dnssec-signzone.c
bin/dnssec/dnssectool.c
bin/dnssec/dnssectool.h
bin/tests/system/verify/tests.sh
bin/tests/system/verify/zones/genzones.sh

index fed91a4b58eb5db1178eb81f4bc54be9dc2363f1..06f0dfeecccdf3627ae5e95f633fbf06d7e59f73 100644 (file)
@@ -1501,8 +1501,14 @@ assignwork(isc_task_t *task, isc_task_t *worker) {
                                        if (!OPTOUT(nsec3flags) ||
                                            secure(name, node))
                                                found = ISC_TRUE;
-                               } else
+                               } else if (has_dname(gdb, gversion, node)) {
+                                       dns_fixedname_init(&fzonecut);
+                                       zonecut = dns_fixedname_name(&fzonecut);
+                                       dns_name_copy(name, zonecut, NULL);
                                        found = ISC_TRUE;
+                               } else {
+                                       found = ISC_TRUE;
+                               }
                        }
                }
 
@@ -1810,6 +1816,9 @@ nsecify(void) {
                        remove_sigs(node, ISC_TRUE, 0);
                        if (generateds)
                                add_ds(name, node, nsttl);
+               } else if (has_dname(gdb, gversion, node)) {
+                       zonecut = dns_fixedname_name(&fzonecut);
+                       dns_name_copy(name, zonecut, NULL);
                }
 
                result = dns_dbiterator_next(dbiter);
@@ -2253,6 +2262,11 @@ nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
                        (void)active_node(node);
                }
 
+               if (has_dname(gdb, gversion, node)) {
+                       zonecut = dns_fixedname_name(&fzonecut);
+                       dns_name_copy(name, zonecut, NULL);
+               }
+
                result = dns_dbiterator_next(dbiter);
                nextnode = NULL;
                while (result == ISC_R_SUCCESS) {
@@ -2287,6 +2301,9 @@ nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
                                        result = dns_dbiterator_next(dbiter);
                                        continue;
                                }
+                       } else if (has_dname(gdb, gversion, nextnode)) {
+                               zonecut = dns_fixedname_name(&fzonecut);
+                               dns_name_copy(nextname, zonecut, NULL);
                        }
                        dns_db_detachnode(gdb, &nextnode);
                        break;
@@ -2385,6 +2402,12 @@ nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
                        dns_db_detachnode(gdb, &node);
                        continue;
                }
+
+               if (has_dname(gdb, gversion, node)) {
+                       zonecut = dns_fixedname_name(&fzonecut);
+                       dns_name_copy(name, zonecut, NULL);
+               }
+
                result = dns_dbiterator_next(dbiter);
                nextnode = NULL;
                while (result == ISC_R_SUCCESS) {
@@ -2415,6 +2438,9 @@ nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
                                        result = dns_dbiterator_next(dbiter);
                                        continue;
                                }
+                       } else if (has_dname(gdb, gversion, nextnode)) {
+                               zonecut = dns_fixedname_name(&fzonecut);
+                               dns_name_copy(nextname, zonecut, NULL);
                        }
                        dns_db_detachnode(gdb, &nextnode);
                        break;
index 77f2f219de78b9cf794a809b32a11dc3bb001760..1758d94be19d895e5774295e67c0d53a221da6e0 100644 (file)
@@ -576,6 +576,21 @@ is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
        return (ISC_TF(result == ISC_R_SUCCESS));
 }
 
+isc_boolean_t
+has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
+       dns_rdataset_t dnameset;
+       isc_result_t result;
+
+       dns_rdataset_init(&dnameset);
+       result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0,
+                                    &dnameset, NULL);
+       if (dns_rdataset_isassociated(&dnameset)) {
+               dns_rdataset_disassociate(&dnameset);
+       }
+
+       return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
 static isc_boolean_t
 goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
        dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
@@ -1730,6 +1745,9 @@ verifyzone(dns_db_t *db, dns_dbversion_t *ver,
                        zonecut = dns_fixedname_name(&fzonecut);
                        dns_name_copy(name, zonecut, NULL);
                        isdelegation = ISC_TRUE;
+               } else if (has_dname(db, ver, node)) {
+                       zonecut = dns_fixedname_name(&fzonecut);
+                       dns_name_copy(name, zonecut, NULL);
                }
                nextnode = NULL;
                result = dns_dbiterator_next(dbiter);
index 21274359f7e7cdd80d08448d196b21abd2eeb4aa..d9ecd7f3da2247e46516cb3102c3802927374b15 100644 (file)
@@ -93,6 +93,13 @@ isc_boolean_t
 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
                      dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp);
 
+/*%
+ * Return ISC_TRUE if version 'ver' of database 'db' contains a DNAME RRset at
+ * 'node'; return ISC_FALSE otherwise.
+ */
+isc_boolean_t
+has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node);
+
 void
 verifyzone(dns_db_t *db, dns_dbversion_t *ver,
                   dns_name_t *origin, isc_mem_t *mctx,
index 450b49a60b33b582e0c3fe1e6ac476e94e778e39..da8a23ad436c4aefecf8d3a475f31d6972c0a5bd 100644 (file)
@@ -63,7 +63,7 @@ do
                expect1="signature has expired"
                expect2="No self-signed .*DNSKEY found"
                ;;
-       *.out-of-zone-nsec|*.below-bottom-of-zone-nsec)
+       *.out-of-zone-nsec|*.below-bottom-of-zone-nsec|*.below-dname-nsec)
                expect1="unexpected NSEC RRset at"
                ;;
        *.nsec.broken-chain)
index a7ce8fb3663b46dbf15838d1fc89f7827cd6a5f6..26cfc25b72c2c8a12a6f045fe9c69633aeffd1fe 100644 (file)
@@ -47,6 +47,13 @@ $KEYGEN -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
 $KEYGEN -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
 $SIGNER -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
 
+setup ksk+zsk.nsec.apex-dname good
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
+cp unsigned.db ${file}.tmp
+echo "@ DNAME data" >> ${file}.tmp
+$SIGNER -SP -o ${zone} -f ${file} ${file}.tmp > s.out$n 2>&1 || dumpit s.out$n
+
 # A set of nsec3 zones.
 setup zsk-only.nsec3 good
 $KEYGEN -3 -r $RANDFILE ${zone}> kg.out$n 2>&1 || dumpit kg.out$n
@@ -61,11 +68,18 @@ $KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
 $KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
 $SIGNER -3 - -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
 
-setup ksk+zsk.outout good
+setup ksk+zsk.optout good
 $KEYGEN -3 -r $RANDFILE ${zone} > kg1.out$n 2>&1 || dumpit kg1.out$n
 $KEYGEN -3 -r $RANDFILE -fK ${zone} > kg2.out$n 2>&1 || dumpit kg2.out$n
 $SIGNER -3 - -A -SPx -o ${zone} -f ${file} unsigned.db > s.out$n 2>&1 || dumpit s.out$n
 
+setup ksk+zsk.nsec3.apex-dname good
+zsk=`$KEYGEN -3 -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -3 -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
+cp unsigned.db ${file}.tmp
+echo "@ DNAME data" >> ${file}.tmp
+$SIGNER -3 - -SP -o ${zone} -f ${file} ${file}.tmp > s.out$n 2>&1 || dumpit s.out$n
+
 # A set of zones with only DNSKEY records.
 setup zsk-only.dnskeyonly bad
 key1=`$KEYGEN -r $RANDFILE ${zone} 2>kg.out` || dumpit kg.out$n
@@ -156,7 +170,7 @@ $SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s
 echo "out-of-zone. 3600 IN NSEC ${zone}. A" >> ${file}
 $SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
 
-# extra NSEC record below bottom of one
+# extra NSEC record below bottom of zone
 setup ksk+zsk.nsec.below-bottom-of-zone-nsec bad
 zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
 ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
@@ -167,6 +181,15 @@ $SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file}.tmp ${file} $zsk > s.out$
 # dnssec-signzone signs any node with a NSEC record.
 awk '$1 ~ /^ns.sub/ && $4 == "RRSIG" && $5 != "NSEC" { next; } { print; }' ${file}.tmp > ${file}
 
+# extra NSEC record below DNAME
+setup ksk+zsk.nsec.below-dname-nsec bad
+zsk=`$KEYGEN -r $RANDFILE ${zone} 2> kg1.out$n` || dumpit kg1.out$n
+ksk=`$KEYGEN -r $RANDFILE -fK ${zone} 2> kg2.out$n` || dumpit kg2.out$n
+cat unsigned.db $ksk.key $zsk.key > $file
+$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk > s.out$n 2>&1 || dumpit s.out$n
+echo "sub.dname.${zone}. 3600 IN NSEC ${zone}. TXT" >> ${file}
+$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk > s.out$n 2>&1 || dumpit s.out$n
+
 # missing NSEC3 record at empty node
 # extract the hash fields from the empty node's NSEC 3 record then fix up
 # the NSEC3 chain to remove it