]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
dnssec-signzone can now create multiple CDS RRs
authorMatthijs Mekking <matthijs@isc.org>
Tue, 21 Feb 2023 07:50:04 +0000 (08:50 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Tue, 28 Feb 2023 08:38:31 +0000 (09:38 +0100)
Change the commandline option -G to take a string that determines what
sync records should be published. It is a comma-separated string with
each element being either "cdnskey", or "cds:<algorithm>", where
<algorithm> is a valid digest type. Duplicates are suppressed.

bin/dnssec/dnssec-signzone.c
bin/dnssec/dnssec-signzone.rst
bin/tests/system/kasp/ns3/setup.sh

index edcbf44069c9c95942619c3b2a7c1987c786deff..7c9ab5c870730de557b3a23edd6907dd17e9bb72 100644 (file)
@@ -173,7 +173,7 @@ static bool output_stdout = false;
 static bool set_maxttl = false;
 static dns_ttl_t maxttl = 0;
 static bool no_max_check = false;
-static bool ignore_sync = false;
+static const char *sync_records = "cdnskey,cds:sha-256";
 
 #define INCSTAT(counter)            \
        if (printstats) {           \
@@ -2733,6 +2733,51 @@ clear_keylist(dns_dnsseckeylist_t *list) {
        }
 }
 
+static void
+add_digest(char *str, size_t dlen, dns_kasp_digestlist_t *digests,
+          bool *cdnskey) {
+       isc_result_t result;
+       isc_textregion_t r;
+       dns_dsdigest_t alg;
+       dns_kasp_digest_t *digest;
+
+       if (dlen == 7 && strncmp(str, "cdnskey", dlen) == 0) {
+               *cdnskey = true;
+               return;
+       }
+
+       if (dlen < 5 || strncmp(str, "cds:", 4) != 0) {
+               fatal("digest must specify cds:algorithm ('%.*s')", (int)dlen,
+                     str);
+       }
+
+       r.base = str + 4;
+       r.length = dlen - 4;
+       result = dns_dsdigest_fromtext(&alg, &r);
+       if (result == DNS_R_UNKNOWN) {
+               fatal("bad digest '%.*s'", (int)dlen, str);
+       } else if (result != ISC_R_SUCCESS) {
+               fatal("bad digest '%.*s': %s", (int)dlen, str,
+                     isc_result_totext(result));
+       } else if (!dst_ds_digest_supported(alg)) {
+               fatal("unsupported digest '%.*s'", (int)dlen, str);
+       }
+
+       /* Suppress duplicates */
+       for (dns_kasp_digest_t *d = ISC_LIST_HEAD(*digests); d != NULL;
+            d = ISC_LIST_NEXT(d, link))
+       {
+               if (d->digest == alg) {
+                       return;
+               }
+       }
+
+       digest = isc_mem_get(mctx, sizeof(*digest));
+       digest->digest = alg;
+       ISC_LINK_INIT(digest, link);
+       ISC_LIST_APPEND(*digests, digest, link);
+}
+
 static void
 build_final_keylist(void) {
        isc_result_t result;
@@ -2743,23 +2788,38 @@ build_final_keylist(void) {
        char name[DNS_NAME_FORMATSIZE];
        dns_rdataset_t cdsset, cdnskeyset, soaset;
        dns_kasp_digestlist_t digests;
-       dns_kasp_digest_t digest = {
-               .digest = DNS_DSDIGEST_SHA256,
-               .link = ISC_LINK_INITIALIZER,
-       };
+       dns_kasp_digest_t *d, *d_next;
+       bool cdnskey = false;
 
        ISC_LIST_INIT(rmkeys);
        ISC_LIST_INIT(matchkeys);
-
        ISC_LIST_INIT(digests);
-       if (!ignore_sync) {
-               ISC_LIST_APPEND(digests, &digest, link);
-       }
 
        dns_rdataset_init(&soaset);
        dns_rdataset_init(&cdsset);
        dns_rdataset_init(&cdnskeyset);
 
+       if (strlen(sync_records) > 0) {
+               const char delim = ',';
+               char *digest;
+               char *s;
+               size_t dlen;
+
+               DE_CONST(sync_records, digest);
+       next_digest:
+               s = strchr(digest, delim);
+               if (s == NULL) {
+                       dlen = strlen(digest);
+                       add_digest(digest, dlen, &digests, &cdnskey);
+                       goto findkeys;
+               }
+               dlen = s - digest;
+               add_digest(digest, dlen, &digests, &cdnskey);
+               digest = s + 1;
+               goto next_digest;
+       }
+
+findkeys:
        /*
         * Find keys that match this zone in the key repository.
         */
@@ -2828,8 +2888,10 @@ build_final_keylist(void) {
        clear_keylist(&rmkeys);
        clear_keylist(&matchkeys);
 
-       if (!ignore_sync) {
-               ISC_LIST_UNLINK(digests, &digest, link);
+       for (d = ISC_LIST_HEAD(digests); d != NULL; d = d_next) {
+               d_next = ISC_LIST_NEXT(d, link);
+               ISC_LIST_UNLINK(digests, d, link);
+               isc_mem_put(mctx, d, sizeof(*d));
        }
        INSIST(ISC_LIST_EMPTY(digests));
 }
@@ -3162,6 +3224,8 @@ usage(void) {
        fprintf(stderr, "\t-g:\t");
        fprintf(stderr, "update DS records based on child zones' "
                        "dsset-* files\n");
+       fprintf(stderr, "\t-G sync-records:\t");
+       fprintf(stderr, "what CDNSKEY and CDS to publish\n");
        fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
        fprintf(stderr, "\t\tRRSIG start time "
                        "- absolute|offset (now - 1 hour)\n");
@@ -3303,8 +3367,8 @@ main(int argc, char *argv[]) {
        atomic_init(&finished, false);
 
        /* Unused letters: Bb G J q Yy (and F is reserved). */
-#define CMDLINE_FLAGS                                                         \
-       "3:AaCc:Dd:E:e:f:FgGhH:i:I:j:J:K:k:L:l:m:M:n:N:o:O:PpQqRr:s:ST:tuUv:" \
+#define CMDLINE_FLAGS                                                          \
+       "3:AaCc:Dd:E:e:f:FgG:hH:i:I:j:J:K:k:L:l:m:M:n:N:o:O:PpQqRr:s:ST:tuUv:" \
        "VX:xzZ:"
 
        /*
@@ -3411,7 +3475,7 @@ main(int argc, char *argv[]) {
                        break;
 
                case 'G':
-                       ignore_sync = true;
+                       sync_records = isc_commandline_argument;
                        break;
 
                case 'H':
index 4354cdea1e8ae647a020ebe34dc24da53f630f20..c10c61b7f972be64277df1e3b8d90bfbe0c8bea1 100644 (file)
@@ -21,7 +21,7 @@ dnssec-signzone - DNSSEC zone signing tool
 Synopsis
 ~~~~~~~~
 
-:program:`dnssec-signzone` [**-a**] [**-c** class] [**-d** directory] [**-D**] [**-E** engine] [**-e** end-time] [**-f** output-file] [**-g**] [**-G**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-K** directory] [**-k** key] [**-L** serial] [**-M** maxttl] [**-N** soa-serial-format] [**-o** origin] [**-O** output-format] [**-P**] [**-Q**] [**-q**] [**-R**] [**-S**] [**-s** start-time] [**-T** ttl] [**-t**] [**-u**] [**-v** level] [**-V**] [**-X** extended end-time] [**-x**] [**-z**] [**-3** salt] [**-H** iterations] [**-A**] {zonefile} [key...]
+:program:`dnssec-signzone` [**-a**] [**-c** class] [**-d** directory] [**-D**] [**-E** engine] [**-e** end-time] [**-f** output-file] [**-g**] [**-G sync-records**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-K** directory] [**-k** key] [**-L** serial] [**-M** maxttl] [**-N** soa-serial-format] [**-o** origin] [**-O** output-format] [**-P**] [**-Q**] [**-q**] [**-R**] [**-S**] [**-s** start-time] [**-T** ttl] [**-t**] [**-u**] [**-v** level] [**-V**] [**-X** extended end-time] [**-x**] [**-z**] [**-3** salt] [**-H** iterations] [**-A**] {zonefile} [key...]
 
 Description
 ~~~~~~~~~~~
@@ -76,9 +76,12 @@ Options
    This option indicates that DS records for child zones should be generated from a ``dsset-`` or ``keyset-``
    file. Existing DS records are removed.
 
-.. option:: -G
+.. option:: -G sync-records
 
-   This option indicates that CDS and CDNSKEY records should not be generated from the given key set.
+   This option indicates which CDS and CDNSKEY records should be generated. ``sync-records`` is a
+   comma-separated string with the following allowed items: ``cdnskey``, and ``cds:<digest-type>``,
+   where ``digest-type`` is an allowed algorithm such as SHA-256 (2), or SHA-384 (4).
+   Only works in combination with smart signing (``-S``).
 
 .. option:: -K directory
 
index c4554185fcca110996b1504b4af5deb03176c9ff..fddf026dbedd4bca8f5a219d036ad9c6c6117494 100644 (file)
@@ -888,7 +888,7 @@ $SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > s
 cat template.db.in "${CSK}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384"  -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 2:
 # It is time to introduce the new CSK.
@@ -916,7 +916,7 @@ $SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > s
 cat template.db.in "${CSK}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384"  -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 3:
 # It is time to submit the DS and to roll signatures.
@@ -971,7 +971,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 4:
 # Some time later all the ZRRSIG records should be from the new CSK, and the
@@ -1018,7 +1018,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 5:
 # After the DS is swapped in step 4, also the KRRSIG records can be removed.
@@ -1054,7 +1054,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 6:
 # After the retire interval has passed the predecessor DNSKEY can be
@@ -1098,7 +1098,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 7:
 # Some time later the predecessor DNSKEY enters the HIDDEN state.
@@ -1133,7 +1133,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 8:
 # The predecessor DNSKEY can be purged.
@@ -1168,7 +1168,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 #
 # The zones at csk-roll2.autosign represent the various steps of a CSK rollover
@@ -1187,7 +1187,7 @@ $SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > s
 cat template.db.in "${CSK}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 2:
 # It is time to introduce the new CSK.
@@ -1215,7 +1215,7 @@ $SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" > s
 cat template.db.in "${CSK}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 3:
 # It is time to submit the DS and to roll signatures.
@@ -1270,7 +1270,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 4:
 # Some time later all the ZRRSIG records should be from the new CSK, and the
@@ -1318,7 +1318,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 5:
 # Some time later the DS can be swapped and the old DNSKEY can be removed from
@@ -1355,7 +1355,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 6:
 # Some time later the predecessor DNSKEY enters the HIDDEN state.
@@ -1391,7 +1391,7 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
 
 # Step 7:
 # The predecessor DNSKEY can be purged, but purge-keys is disabled.
@@ -1426,4 +1426,4 @@ cat template.db.in "${CSK1}.key" "${CSK2}.key" > "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >> "$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >> "$infile"
 cp $infile $zonefile
-$SIGNER -S -z -x -G -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1
+$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1