From: Matthijs Mekking Date: Tue, 21 Feb 2023 07:50:04 +0000 (+0100) Subject: dnssec-signzone can now create multiple CDS RRs X-Git-Tag: v9.19.11~14^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1633b71b071086bf53acfbce808fa3c99f8cd50;p=thirdparty%2Fbind9.git dnssec-signzone can now create multiple CDS RRs 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:", where is a valid digest type. Duplicates are suppressed. --- diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index edcbf44069c..7c9ab5c8707 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -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': diff --git a/bin/dnssec/dnssec-signzone.rst b/bin/dnssec/dnssec-signzone.rst index 4354cdea1e8..c10c61b7f97 100644 --- a/bin/dnssec/dnssec-signzone.rst +++ b/bin/dnssec/dnssec-signzone.rst @@ -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:``, + 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 diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index c4554185fcc..fddf026dbed 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -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