]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] dnssec-signzone can now add sync records
authorEvan Hunt <each@isc.org>
Tue, 3 Oct 2017 08:11:36 +0000 (01:11 -0700)
committerEvan Hunt <each@isc.org>
Tue, 3 Oct 2017 08:11:36 +0000 (01:11 -0700)
4751. [func] "dnssec-signzone -S" can now automatically add parent
synchronization records (CDS and CDNSKEY) according
to key metadata set using the -Psync and -Dsync
options to dnssec-keygen and dnssec-settime.
[RT #46149]

CHANGES
bin/dnssec/dnssec-signzone.c
bin/tests/system/smartsign/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index bcc9f823d75655ab23098e5cc21e2dd5cf3508ec..bad33a357fe9c9581e3da04eb64394fe48dcd339 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+4751.  [func]          "dnssec-signzone -S" can now automatically add parent
+                       synchronization records (CDS and CDNSKEY) according
+                       to key metadata set using the -Psync and -Dsync
+                       options to dnssec-keygen and dnssec-settime.
+                       [RT #46149]
+
 4750.  [func]          "rndc managed-keys destroy" shuts down RFC 5011 key
                        maintenance and deletes the managed-keys database.
                        If followed by "rndc reconfig" or a server restart,
index 82985f407d6422e05dcfc4d72e0bc4ddce2da2ff..55c97b6deb5ea3f59a53a0384ba8066ef51c0026 100644 (file)
@@ -2591,45 +2591,114 @@ report(const char *format, ...) {
        putc('\n', stderr);
 }
 
+static void
+clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
+       dns_dnsseckey_t *key;
+       while (!ISC_LIST_EMPTY(*list)) {
+               key = ISC_LIST_HEAD(*list);
+               ISC_LIST_UNLINK(*list, key, link);
+               dns_dnsseckey_destroy(mctx, &key);
+       }
+}
+
 static void
 build_final_keylist(void) {
        isc_result_t result;
+       dns_dbnode_t *node = NULL;
        dns_dbversion_t *ver = NULL;
        dns_diff_t diff;
-       dns_dnsseckeylist_t matchkeys;
+       dns_dnsseckeylist_t rmkeys, matchkeys;
        char name[DNS_NAME_FORMATSIZE];
+       dns_rdataset_t cdsset, cdnskeyset, soaset;
+       isc_stdtime_t now;
+       dns_ttl_t ttl;
+
+       ISC_LIST_INIT(rmkeys);
+       ISC_LIST_INIT(matchkeys);
+
+       dns_rdataset_init(&soaset);
+       dns_rdataset_init(&cdsset);
+       dns_rdataset_init(&cdnskeyset);
+
+       isc_stdtime_get(&now);
 
        /*
         * Find keys that match this zone in the key repository.
         */
-       ISC_LIST_INIT(matchkeys);
        result = dns_dnssec_findmatchingkeys(gorigin, directory,
                                             mctx, &matchkeys);
-       if (result == ISC_R_NOTFOUND)
+       if (result == ISC_R_NOTFOUND) {
                result = ISC_R_SUCCESS;
+       }
        check_result(result, "dns_dnssec_findmatchingkeys");
 
        result = dns_db_newversion(gdb, &ver);
        check_result(result, "dns_db_newversion");
 
+       result = dns_db_getoriginnode(gdb, &node);
+       check_result(result, "dns_db_getoriginnode");
+
+       /* Get the SOA record's TTL */
+       result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_soa,
+                                    dns_rdatatype_none, 0, &soaset, NULL);
+       check_result(result, "dns_db_findrdataset");
+       ttl = soaset.ttl;
+       dns_rdataset_disassociate(&soaset);
+
+       /* Get the CDS rdataset */
+       result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds,
+                                    dns_rdatatype_none, 0, &cdsset, NULL);
+       if (result != ISC_R_SUCCESS &&
+           dns_rdataset_isassociated(&cdsset))
+       {
+               dns_rdataset_disassociate(&cdsset);
+       }
+
+       /* Get the CDNSKEY rdataset */
+       result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey,
+                                    dns_rdatatype_none, 0, &cdnskeyset, NULL);
+       if (result != ISC_R_SUCCESS &&
+           dns_rdataset_isassociated(&cdnskeyset))
+       {
+               dns_rdataset_disassociate(&cdnskeyset);
+       }
+
        dns_diff_init(mctx, &diff);
 
        /*
         * Update keylist with information from from the key repository.
         */
-       dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
+       dns_dnssec_updatekeys(&keylist, &matchkeys, &rmkeys, gorigin, keyttl,
                              &diff, ignore_kskflag, mctx, report);
 
+       /*
+        * Update keylist with sync records.
+        */
+       dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset,
+                             now, ttl, &diff, mctx);
+
        dns_name_format(gorigin, name, sizeof(name));
 
        result = dns_diff_applysilently(&diff, gdb, ver);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                fatal("failed to update DNSKEY RRset at node '%s': %s",
                      name, isc_result_totext(result));
+       }
 
+       dns_db_detachnode(gdb, &node);
        dns_db_closeversion(gdb, &ver, ISC_TRUE);
 
        dns_diff_clear(&diff);
+
+       if (dns_rdataset_isassociated(&cdsset)) {
+               dns_rdataset_disassociate(&cdsset);
+       }
+       if (dns_rdataset_isassociated(&cdnskeyset)) {
+               dns_rdataset_disassociate(&cdnskeyset);
+       }
+
+       clear_keylist(&rmkeys, mctx);
+       clear_keylist(&matchkeys, mctx);
 }
 
 static void
@@ -3616,8 +3685,9 @@ main(int argc, char *argv[]) {
         *    do not have private keys associated and were
         *    not specified on the command line.
         */
-       if (argc == 0 || smartsign)
+       if (argc == 0 || smartsign) {
                loadzonekeys(!smartsign, ISC_FALSE);
+       }
        loadexplicitkeys(argv, argc, ISC_FALSE);
        loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
        loadzonekeys(!smartsign, ISC_TRUE);
@@ -3627,8 +3697,9 @@ main(int argc, char *argv[]) {
         * key files with metadata, and merge them with the keylist
         * we have now.
         */
-       if (smartsign)
+       if (smartsign) {
                build_final_keylist();
+       }
 
        /* Now enumerate the key list */
        for (key = ISC_LIST_HEAD(keylist);
index 5614ba1edfbb9d29ab5073bc2f14051bae274e5c..e2ece3c456821726067237500257d86b540e4d95 100644 (file)
@@ -51,6 +51,9 @@ echo I:revoking key
 cksk3=`$KEYGEN -q -a rsasha1 -r $RANDFILE -fk $czone`
 cksk4=`$REVOKE $cksk3`
 
+echo I:setting up sync key
+cksk5=`$KEYGEN -q -a rsasha1 -r $RANDFILE -fk -P now+1mo -A now+1mo -Psync now $czone`
+
 echo I:generating parent keys
 pzsk=`$KEYGEN -q -a rsasha1 -r $RANDFILE $pzone`
 pksk=`$KEYGEN -q -a rsasha1 -r $RANDFILE -fk $pzone`
@@ -337,5 +340,22 @@ grep -w "$ckpublished" dnskey.sigs > /dev/null || ret=1
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:checking sync record publication"
+ret=0
+grep CDNSKEY $cfile.signed > /dev/null || ret=1
+grep CDS $cfile.signed > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking sync record deletion"
+ret=0
+$SETTIME -P now -A now -Dsync now ${cksk5} > /dev/null
+$SIGNER -Sg -r $RANDFILE -o $czone -f $cfile.new $cfile.signed > /dev/null 2>&1
+mv $cfile.new $cfile.signed
+grep CDNSKEY $cfile.signed > /dev/null && ret=1
+grep CDS $cfile.signed > /dev/null && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 [ $status -eq 0 ] || exit 1
index 11dfa4e861991a4e65e7128f788d2767838bdcad..6ffa87d3d8c244fca6b903cc7e007d237fa4d749 100644 (file)
          etc. [RT #32456]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         <command>dnssec-signzone -S</command> can now add or remove
+         synchronization records (CDS and CDNSKEY) based on key metadata
+         set by the <command>-Psync</command> and <command>-Dsync</command>
+         options to <command>dnssec-keygen</command>,
+         <command>dnssec-settime</command>, etc. [RT #46149]
+       </para>
+      </listitem>
     </itemizedlist>
   </section>