mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
dnssec-signzone now updates ZONEMD records
If the zone already contains ZONEMD records, they will be updated when signing the zone. If not, ZONEMD records can be added by using the "-Z" option: for instance, "dnssec-signzone -Z - -S example.com". Also, dnssec-verify now verifies the ZONEMD records, if any are present. If run with the "-Z" flag, ZONEMD is mandatory, and the zone will be rejected if it is not present. Some zones in the mirror system test are now signed with ZONEMD.
This commit is contained in:
@@ -173,6 +173,7 @@ static bool set_maxttl = false;
|
||||
static dns_ttl_t maxttl = 0;
|
||||
static bool no_max_check = false;
|
||||
static const char *sync_records = "cdnskey,cds:sha-256";
|
||||
static bool add_zonemd = false;
|
||||
|
||||
#define INCSTAT(counter) \
|
||||
if (printstats) { \
|
||||
@@ -1215,6 +1216,8 @@ signname(dns_dbnode_t *node, bool apex, dns_name_t *name) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
fatal("'%s': Non-apex DNSKEY RRset\n", namebuf);
|
||||
} else if (rdataset.type == dns_rdatatype_zonemd && apex) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
signset(&del, &add, node, name, &rdataset);
|
||||
@@ -1472,10 +1475,42 @@ presign(void) {
|
||||
|
||||
/*%
|
||||
* Clean up the iterator and global state after the tasks complete.
|
||||
*
|
||||
* Update ZONEMD if present.
|
||||
*/
|
||||
static void
|
||||
postsign(void) {
|
||||
isc_result_t result;
|
||||
dns_diff_t diff;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdataset_t rdataset = DNS_RDATASET_INIT;
|
||||
|
||||
dns_dbiterator_destroy(&gdbiter);
|
||||
|
||||
dns_diff_init(isc_g_mctx, &diff);
|
||||
|
||||
result = dns_update_zonemd(gdb, gversion, &diff);
|
||||
check_result(result, "dns_update_zonemd");
|
||||
dns_diff_clear(&diff);
|
||||
|
||||
result = dns_db_getoriginnode(gdb, &node);
|
||||
check_result(result, "dns_db_findnode");
|
||||
|
||||
result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_zonemd,
|
||||
0, (isc_stdtime_t)0, &rdataset, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
signset(&diff, &diff, node, gorigin, &rdataset);
|
||||
}
|
||||
|
||||
result = dns_diff_applysilently(&diff, gdb, gversion);
|
||||
check_result(result, "dns_diff_applysilently");
|
||||
|
||||
if (dns_rdataset_isassociated(&rdataset)) {
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
}
|
||||
|
||||
dns_db_detachnode(&node);
|
||||
dns_diff_clear(&diff);
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -2100,6 +2135,88 @@ nsec3clean(dns_name_t *name, dns_dbnode_t *node, unsigned int hashalg,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
addzonemd(uint8_t scheme, uint8_t digest_type) {
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdata_zonemd_t zonemd;
|
||||
dns_rdatalist_t zmlist;
|
||||
dns_rdataset_t zmset = DNS_RDATASET_INIT;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
unsigned char digest[64] = { 0 };
|
||||
unsigned char zmbuf[6 + sizeof(digest)];
|
||||
isc_buffer_t b;
|
||||
isc_result_t result;
|
||||
dns_ttl_t ttl = 0;
|
||||
|
||||
/* Is there already a ZONEMD? */
|
||||
result = dns_db_getoriginnode(gdb, &node);
|
||||
check_result(result, "dns_db_getoriginnode()");
|
||||
result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_zonemd,
|
||||
0, 0, &zmset, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
DNS_RDATASET_FOREACH(&zmset) {
|
||||
dns_rdataset_current(&zmset, &rdata);
|
||||
(void)dns_rdata_tostruct(&rdata, &zonemd, NULL);
|
||||
/*
|
||||
* Does the scheme/digest_type pair already exist?
|
||||
*/
|
||||
if (zonemd.scheme == scheme &&
|
||||
zonemd.digest_type == digest_type)
|
||||
{
|
||||
dns_rdataset_disassociate(&zmset);
|
||||
dns_db_detachnode(&node);
|
||||
return;
|
||||
}
|
||||
dns_rdata_init(&rdata);
|
||||
}
|
||||
/*
|
||||
* Remember the rdataset's ttl.
|
||||
*/
|
||||
ttl = zmset.ttl;
|
||||
dns_rdataset_disassociate(&zmset);
|
||||
}
|
||||
|
||||
/* No, so add a dummy */
|
||||
zonemd.common.rdclass = gclass;
|
||||
zonemd.common.rdtype = dns_rdatatype_zonemd;
|
||||
zonemd.mctx = NULL;
|
||||
zonemd.serial = 0;
|
||||
zonemd.scheme = scheme;
|
||||
zonemd.digest_type = digest_type;
|
||||
zonemd.digest = digest;
|
||||
|
||||
switch (digest_type) {
|
||||
case DNS_ZONEMD_DIGEST_SHA384:
|
||||
zonemd.length = ISC_SHA384_DIGESTLENGTH;
|
||||
break;
|
||||
case DNS_ZONEMD_DIGEST_SHA512:
|
||||
zonemd.length = ISC_SHA512_DIGESTLENGTH;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, zmbuf, sizeof(zmbuf));
|
||||
result = dns_rdata_fromstruct(&rdata, gclass, dns_rdatatype_zonemd,
|
||||
&zonemd, &b);
|
||||
check_result(result, "dns_rdata_fromstruct()");
|
||||
|
||||
dns_rdatalist_init(&zmlist);
|
||||
zmlist.rdclass = rdata.rdclass;
|
||||
zmlist.type = rdata.type;
|
||||
zmlist.ttl = ttl;
|
||||
ISC_LIST_APPEND(zmlist.rdata, &rdata, link);
|
||||
dns_rdatalist_tordataset(&zmlist, &zmset);
|
||||
|
||||
result = dns_db_addrdataset(gdb, node, gversion, 0, &zmset,
|
||||
DNS_DBADD_MERGE, NULL);
|
||||
if (result == DNS_R_UNCHANGED) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
check_result(result, "addnsec3param: dns_db_addrdataset()");
|
||||
dns_db_detachnode(&node);
|
||||
}
|
||||
|
||||
static void
|
||||
rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add,
|
||||
dns_diff_t *del) {
|
||||
@@ -3272,6 +3389,7 @@ main(int argc, char *argv[]) {
|
||||
bool set_optout = false;
|
||||
bool set_iter = false;
|
||||
bool nonsecify = false;
|
||||
uint8_t zonemd_scheme[2] = { 0 }, zonemd_digest[2] = { 0 };
|
||||
|
||||
atomic_init(&shuttingdown, false);
|
||||
atomic_init(&finished, false);
|
||||
@@ -3282,8 +3400,8 @@ main(int argc, char *argv[]) {
|
||||
* Unused letters: Bb G J l q Yy (and F is reserved).
|
||||
* l was previously used for DLV lookaside.
|
||||
*/
|
||||
#define CMDLINE_FLAGS \
|
||||
"3:AaCc:Dd:E:e:f:FgG:hH:i:I:j:J:K:k: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:m:M:n:N:o:O:PpQqRr:s:ST:tuU:v:" \
|
||||
"VX:xzZ:"
|
||||
|
||||
/*
|
||||
@@ -3529,8 +3647,13 @@ main(int argc, char *argv[]) {
|
||||
printstats = true;
|
||||
break;
|
||||
|
||||
case 'U': /* Undocumented for testing only. */
|
||||
unknownalg = true;
|
||||
case 'U': /* Undocumented test options */
|
||||
if (!strcmp(isc_commandline_argument, "nonsecify")) {
|
||||
nonsecify = true;
|
||||
}
|
||||
if (!strcmp(isc_commandline_argument, "unknownalg")) {
|
||||
unknownalg = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@@ -3561,6 +3684,57 @@ main(int argc, char *argv[]) {
|
||||
ignore_kskflag = true;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
add_zonemd = true;
|
||||
if (strcasecmp(isc_commandline_argument,
|
||||
"simple-sha384") == 0 ||
|
||||
strcasecmp(isc_commandline_argument, "sha384") ==
|
||||
0 ||
|
||||
strcmp(isc_commandline_argument, "-") == 0)
|
||||
{
|
||||
for (size_t i = 0;
|
||||
i < ARRAY_SIZE(zonemd_scheme); i++)
|
||||
{
|
||||
if (zonemd_scheme[i] ==
|
||||
DNS_ZONEMD_SCHEME_SIMPLE &&
|
||||
zonemd_digest[i] ==
|
||||
DNS_ZONEMD_DIGEST_SHA384)
|
||||
{
|
||||
break;
|
||||
} else if (zonemd_scheme[i] == 0) {
|
||||
zonemd_scheme[i] =
|
||||
DNS_ZONEMD_SCHEME_SIMPLE;
|
||||
zonemd_digest[i] =
|
||||
DNS_ZONEMD_DIGEST_SHA384;
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(isc_commandline_argument,
|
||||
"simple-sha512") == 0 ||
|
||||
strcasecmp(isc_commandline_argument,
|
||||
"sha512") == 0)
|
||||
{
|
||||
for (size_t i = 0;
|
||||
i < ARRAY_SIZE(zonemd_scheme); i++)
|
||||
{
|
||||
if (zonemd_scheme[i] ==
|
||||
DNS_ZONEMD_SCHEME_SIMPLE &&
|
||||
zonemd_digest[i] ==
|
||||
DNS_ZONEMD_DIGEST_SHA512)
|
||||
{
|
||||
break;
|
||||
} else if (zonemd_scheme[i] == 0) {
|
||||
zonemd_scheme[i] =
|
||||
DNS_ZONEMD_SCHEME_SIMPLE;
|
||||
zonemd_digest[i] =
|
||||
DNS_ZONEMD_DIGEST_SHA512;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fatal("unknown ZONEMD scheme/digest");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
|
||||
fatal("setting FIPS mode failed");
|
||||
@@ -3582,12 +3756,6 @@ main(int argc, char *argv[]) {
|
||||
/* Does not return. */
|
||||
version(isc_commandline_progname);
|
||||
|
||||
case 'Z': /* Undocumented test options */
|
||||
if (!strcmp(isc_commandline_argument, "nonsecify")) {
|
||||
nonsecify = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: unhandled option -%c\n",
|
||||
isc_commandline_progname,
|
||||
@@ -3875,6 +4043,14 @@ main(int argc, char *argv[]) {
|
||||
/* Remove duplicates and cap TTLs at maxttl */
|
||||
cleanup_zone();
|
||||
|
||||
if (add_zonemd) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(zonemd_scheme); i++) {
|
||||
if (zonemd_scheme[i] != 0) {
|
||||
addzonemd(zonemd_scheme[i], zonemd_digest[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nonsecify) {
|
||||
if (IS_NSEC3) {
|
||||
nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
|
||||
|
@@ -21,7 +21,7 @@ dnssec-signzone - DNSSEC zone signing tool
|
||||
Synopsis
|
||||
~~~~~~~~
|
||||
|
||||
:program:`dnssec-signzone` [**-a**] [**-c** class] [**-d** directory] [**-D**] [**-e** end-time] [**-f** output-file] [**-F**] [**-g**] [**-G sync-records**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-J** filename] [**-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** end-time] [**-f** output-file] [**-F**] [**-g**] [**-G sync-records**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-J** filename] [**-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**] [**-Z**] [**-3** salt] [**-H** iterations] [**-A**] {zonefile} [key...]
|
||||
|
||||
Description
|
||||
~~~~~~~~~~~
|
||||
@@ -401,6 +401,16 @@ Options
|
||||
all records. This is useful when using the :option:`-u` option to modify an
|
||||
NSEC3 chain which previously had OPTOUT set.
|
||||
|
||||
.. option:: -Z method
|
||||
|
||||
This option causes a ZONEMD record to be added to the signed zone,
|
||||
if there wasn't a ZONEMD already present. The ``method`` parameter
|
||||
indicates the scheme and digest type to use: valid options are
|
||||
``simple-sha384`` (or ``sha384``, or ``-``) for scheme SIMPLE
|
||||
and digest type SHA384, and ``simple-sha512`` (or ``sha512``)
|
||||
for scheme SIMPLE and digest type SHA512. Multiple ``-Z`` options
|
||||
can be used simultaneously to add multiple ZONEMD records.
|
||||
|
||||
.. option:: zonefile
|
||||
|
||||
This option sets the file containing the zone to be signed.
|
||||
|
@@ -57,6 +57,7 @@
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/soa.h>
|
||||
#include <dns/time.h>
|
||||
#include <dns/zone.h>
|
||||
#include <dns/zoneverify.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
@@ -134,6 +135,37 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
check_zonemd(const char *file, const char *jfile, const dns_name_t *origin,
|
||||
dns_rdataclass_t rdclass, bool required) {
|
||||
dns_zone_t *zone = NULL;
|
||||
dns_zoneopt_t options = DNS_ZONEOPT_ZONEMD_CHECK |
|
||||
DNS_ZONEOPT_ZONEMD_DNSSEC;
|
||||
isc_result_t result;
|
||||
|
||||
if (required) {
|
||||
options |= DNS_ZONEOPT_ZONEMD_REQUIRED;
|
||||
}
|
||||
|
||||
dns_zone_create(&zone, isc_g_mctx, 0);
|
||||
dns_zone_settype(zone, dns_zone_primary);
|
||||
dns_zone_setoption(zone, options, true);
|
||||
dns_zone_setorigin(zone, origin);
|
||||
dns_zone_setclass(zone, rdclass);
|
||||
|
||||
const char *dbtype[] = { ZONEDB_DEFAULT };
|
||||
dns_zone_setdbtype(zone, 1, (const char *const *)dbtype);
|
||||
|
||||
dns_zone_setfile(zone, file, NULL, inputformat,
|
||||
&dns_master_style_default);
|
||||
dns_zone_setjournal(zone, jfile);
|
||||
|
||||
result = dns_zone_load(zone, false);
|
||||
dns_zone_detach(&zone);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ISC_NORETURN static void
|
||||
usage(void);
|
||||
|
||||
@@ -167,14 +199,15 @@ main(int argc, char *argv[]) {
|
||||
char *origin = NULL, *file = NULL;
|
||||
char *inputformatstr = NULL;
|
||||
isc_result_t result;
|
||||
char *classname = NULL;
|
||||
dns_rdataclass_t rdclass;
|
||||
char *endp;
|
||||
dns_rdataclass_t rdclass = dns_rdataclass_in;
|
||||
bool zonemd = false, require_zonemd = false;
|
||||
dns_dbnode_t *node = NULL;
|
||||
char *endp = NULL;
|
||||
int ch;
|
||||
|
||||
isc_commandline_init(argc, argv);
|
||||
|
||||
#define CMDLINE_FLAGS "c:E:hJ:m:o:I:qv:Vxz"
|
||||
#define CMDLINE_FLAGS "c:E:hJ:m:o:I:qv:VxzZ"
|
||||
|
||||
/*
|
||||
* Process memory debugging argument first.
|
||||
@@ -206,7 +239,7 @@ main(int argc, char *argv[]) {
|
||||
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
classname = isc_commandline_argument;
|
||||
rdclass = strtoclass(isc_commandline_argument);
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
@@ -248,6 +281,10 @@ main(int argc, char *argv[]) {
|
||||
ignore_kskflag = true;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
require_zonemd = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
if (isc_commandline_option != '?') {
|
||||
fprintf(stderr, "%s: invalid argument -%c\n",
|
||||
@@ -274,8 +311,6 @@ main(int argc, char *argv[]) {
|
||||
|
||||
now = isc_stdtime_now();
|
||||
|
||||
rdclass = strtoclass(classname);
|
||||
|
||||
setup_logging();
|
||||
|
||||
argc -= isc_commandline_index;
|
||||
@@ -320,6 +355,17 @@ main(int argc, char *argv[]) {
|
||||
result = dns_db_newversion(gdb, &gversion);
|
||||
check_result(result, "dns_db_newversion()");
|
||||
|
||||
dns_rdataset_t zmset = DNS_RDATASET_INIT;
|
||||
result = dns_db_getoriginnode(gdb, &node);
|
||||
check_result(result, "dns_db_getoriginnode()");
|
||||
result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_zonemd,
|
||||
0, 0, &zmset, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
zonemd = true;
|
||||
dns_rdataset_disassociate(&zmset);
|
||||
}
|
||||
dns_db_detachnode(&node);
|
||||
|
||||
result = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, NULL,
|
||||
isc_g_mctx, ignore_kskflag,
|
||||
keyset_kskonly, report);
|
||||
@@ -327,6 +373,14 @@ main(int argc, char *argv[]) {
|
||||
dns_db_closeversion(gdb, &gversion, false);
|
||||
dns_db_detach(&gdb);
|
||||
|
||||
if (zonemd && result == ISC_R_SUCCESS) {
|
||||
result = check_zonemd(file, journal, gorigin, gclass,
|
||||
require_zonemd);
|
||||
report("ZONEMD verification: %s", isc_result_totext(result));
|
||||
} else if (!zonemd && require_zonemd) {
|
||||
fatal("Valid ZONEMD required but not present");
|
||||
}
|
||||
|
||||
if (verbose > 10) {
|
||||
isc_mem_stats(isc_g_mctx, stdout);
|
||||
}
|
||||
|
@@ -27,8 +27,9 @@ Description
|
||||
~~~~~~~~~~~
|
||||
|
||||
:program:`dnssec-verify` verifies that a zone is fully signed for each
|
||||
algorithm found in the DNSKEY RRset for the zone, and that the
|
||||
NSEC/NSEC3 chains are complete.
|
||||
algorithm found in the DNSKEY RRset for the zone, that the
|
||||
NSEC/NSEC3 chains are complete, and, if a ZONEMD record is present,
|
||||
that it is valid.
|
||||
|
||||
Options
|
||||
~~~~~~~
|
||||
@@ -94,6 +95,11 @@ Options
|
||||
key; the same key may be used for both purposes. This corresponds to
|
||||
the :option:`-z option in dnssec-signzone <dnssec-signzone -z>`.
|
||||
|
||||
.. option:: -Z
|
||||
|
||||
This option indicates that a valid ZONEMD record must be present
|
||||
in the zone.
|
||||
|
||||
.. option:: zonefile
|
||||
|
||||
This option indicates the file containing the zone to be signed.
|
||||
|
16
bin/tests/system/checkconf/bad-kasp-zonemd.conf
Normal file
16
bin/tests/system/checkconf/bad-kasp-zonemd.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
dnssec-policy "wrong" {
|
||||
zonemd sha384;
|
||||
};
|
@@ -253,7 +253,7 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -3 - -PU -o "$zone" "$zonefile" >/dev/null
|
||||
"$SIGNER" -z -3 - -P -U unknownalg -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
#
|
||||
# A optout nsec3 zone with a unknown nsec3 hash algorithm (-U).
|
||||
@@ -266,7 +266,7 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -3 - -PU -A -o "$zone" "$zonefile" >/dev/null
|
||||
"$SIGNER" -z -3 - -P -U unknownalg -A -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
#
|
||||
# A zone that is signed with an unknown DNSKEY algorithm.
|
||||
@@ -375,7 +375,7 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -3 - -o "$zone" -PU -O full -f ${zonefile}.tmp "$zonefile" >/dev/null
|
||||
"$SIGNER" -z -3 - -o "$zone" -P -U unknownalg -O full -f ${zonefile}.tmp "$zonefile" >/dev/null
|
||||
|
||||
awk '$4 == "DNSKEY" { $7 = 100; print } $4 == "RRSIG" { $6 = 100; print } { print }' ${zonefile}.tmp >${zonefile}.signed
|
||||
|
||||
|
20
bin/tests/system/dnssectools/signer/general/test13.zone
Normal file
20
bin/tests/system/dnssectools/signer/general/test13.zone
Normal file
@@ -0,0 +1,20 @@
|
||||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; 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 https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
; This is a zone which has two DNSKEY records, both of which have
|
||||
; existing private key files available. They should be loaded automatically
|
||||
; and the zone correctly signed.
|
||||
;
|
||||
$TTL 3600
|
||||
example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
|
||||
example.com. IN ZONEMD 0 1 1 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
$include Kexample.com.+010+18240.key
|
||||
$include Kexample.com.+010+28633.key
|
21
bin/tests/system/dnssectools/signer/general/test14.zone
Normal file
21
bin/tests/system/dnssectools/signer/general/test14.zone
Normal file
@@ -0,0 +1,21 @@
|
||||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; 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 https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
; This is a zone which has two DNSKEY records, both of which have
|
||||
; existing private key files available. They should be loaded automatically
|
||||
; and the zone correctly signed.
|
||||
;
|
||||
$TTL 3600
|
||||
example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300
|
||||
example.com. IN ZONEMD 0 1 1 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
example.com. IN ZONEMD 0 1 2 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
$include Kexample.com.+010+18240.key
|
||||
$include Kexample.com.+010+28633.key
|
@@ -245,6 +245,40 @@ n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_ic "check that dnssec-signzone updates a ZONEMD record ($n)"
|
||||
ret=0
|
||||
(
|
||||
cd signer/general || exit 1
|
||||
rm -f signed.zone
|
||||
$SIGNER -f signed.zone -o example.com. test13.zone >signer.out.$n
|
||||
count=$(grep -c "ZONEMD.90000 1 1 " signed.zone)
|
||||
test $count -eq 1 || exit 1
|
||||
count=$(grep -c "RRSIG.ZONEMD" signed.zone)
|
||||
test $count -eq 1 || exit 1
|
||||
test -f signed.zone
|
||||
) || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_ic "check that dnssec-signzone updates both ZONEMD records ($n)"
|
||||
ret=0
|
||||
(
|
||||
cd signer/general || exit 1
|
||||
rm -f signed.zone
|
||||
$SIGNER -f signed.zone -o example.com. test14.zone >signer.out.$n
|
||||
count=$(grep -c "ZONEMD.90000 1 1 " signed.zone)
|
||||
test $count -eq 1 || exit 1
|
||||
count=$(grep -c "ZONEMD.90000 1 2 " signed.zone)
|
||||
test $count -eq 1 || exit 1
|
||||
count=$(grep -c "RRSIG.ZONEMD" signed.zone)
|
||||
test $count -eq 1 || exit 1
|
||||
test -f signed.zone
|
||||
) || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
get_default_algorithm_key_ids_from_sigs() {
|
||||
zone=$1
|
||||
|
||||
|
@@ -59,8 +59,13 @@ for variant in addzone axfr ixfr load reconfig untrusted; do
|
||||
|
||||
cat $infile $keyname1.key $keyname2.key >$zonefile
|
||||
|
||||
# for axfr and ixfr variants, add a ZONEMD record
|
||||
if [ "$variant" = "axfr" -o "$variant" = "ixfr" ]; then
|
||||
zopt="-Z-"
|
||||
fi
|
||||
|
||||
# Prepare a properly signed version of the zone ("*.original.signed").
|
||||
$SIGNER -P -o $zone $zonefile >/dev/null
|
||||
$SIGNER $zopt -P -o $zone $zonefile >/dev/null
|
||||
cp $zonefile.signed $zonefile.original.signed
|
||||
# Prepare a version of the zone with a bogus SOA RRSIG ("*.bad.signed").
|
||||
sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_BAD}/;" $zonefile.signed >$zonefile.bad.signed
|
||||
|
@@ -62,7 +62,7 @@ keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone)
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
# do not regenerate NSEC chain as there in a minimal NSEC record present
|
||||
$SIGNER -P -Z nonsecify -o $zone $zonefile >/dev/null
|
||||
$SIGNER -P -U nonsecify -o $zone $zonefile >/dev/null
|
||||
|
||||
zone=soa-without-dnskey
|
||||
infile=soa-without-dnskey.db.in
|
||||
@@ -72,7 +72,7 @@ keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone)
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
# do not regenerate NSEC chain as there in a minimal NSEC record present
|
||||
$SIGNER -P -Z nonsecify -o $zone $zonefile >/dev/null
|
||||
$SIGNER -P -U nonsecify -o $zone $zonefile >/dev/null
|
||||
|
||||
zone=.
|
||||
infile=root.db.in
|
||||
|
@@ -184,3 +184,37 @@ def test_verify_j_reads_journal_file():
|
||||
]
|
||||
).stdout.decode("utf-8")
|
||||
assert "Loading zone 'updated' from file 'zones/updated.other'" in output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"zone",
|
||||
[
|
||||
"ksk+zsk.zonemd.nsec",
|
||||
"ksk+zsk.zonemd.nsec3",
|
||||
],
|
||||
)
|
||||
def test_verify_zonemd(zone):
|
||||
output = isctest.run.cmd(
|
||||
[VERIFY, "-o", zone, f"zones/{zone}.good"],
|
||||
raise_on_exception=False,
|
||||
log_stdout=True,
|
||||
)
|
||||
stream = (output.stdout + output.stderr).decode("utf-8").replace("\n", "")
|
||||
assert "ZONEMD verification: success" in stream
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"zone",
|
||||
[
|
||||
"ksk+zsk.nsec",
|
||||
"ksk+zsk.nsec3",
|
||||
],
|
||||
)
|
||||
def test_verify_no_zonemd(zone):
|
||||
output = isctest.run.cmd(
|
||||
[VERIFY, "-Zo", zone, f"zones/{zone}.good"],
|
||||
raise_on_exception=False,
|
||||
log_stdout=True,
|
||||
)
|
||||
stream = (output.stdout + output.stderr).decode("utf-8").replace("\n", "")
|
||||
assert "Valid ZONEMD required but not present" in stream
|
||||
|
@@ -169,7 +169,7 @@ ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg2.out$n) || dumpit kg2.out
|
||||
cat unsigned.db $ksk.key $zsk.key >$file
|
||||
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk >s.out$n || dumpit s.out$n
|
||||
awk '$4 == "NSEC" { $5 = "'$zone'."; print } { print }' ${file} >${file}.tmp
|
||||
$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
$SIGNER -Px -U nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
|
||||
# bad nsec bitmap
|
||||
setup ksk+zsk.nsec.bad-bitmap bad
|
||||
@@ -178,7 +178,7 @@ ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg2.out$n) || dumpit kg2.out
|
||||
cat unsigned.db $ksk.key $zsk.key >$file
|
||||
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk >s.out$n || dumpit s.out$n
|
||||
awk '$4 == "NSEC" && /SOA/ { $6=""; print } { print }' ${file} >${file}.tmp
|
||||
$SIGNER -Px -Z nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
$SIGNER -Px -U nonsecify -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
|
||||
# extra NSEC record out side of zone
|
||||
setup ksk+zsk.nsec.out-of-zone-nsec bad
|
||||
@@ -187,7 +187,7 @@ ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg2.out$n) || dumpit kg2.out
|
||||
cat unsigned.db $ksk.key $zsk.key >$file
|
||||
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk >s.out$n || dumpit s.out$n
|
||||
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 || dumpit s.out$n
|
||||
$SIGNER -Px -U nonsecify -O full -o ${zone} -f ${file} ${file} $zsk >s.out$n || dumpit s.out$n
|
||||
|
||||
# extra NSEC record below bottom of zone
|
||||
setup ksk+zsk.nsec.below-bottom-of-zone-nsec bad
|
||||
@@ -196,7 +196,7 @@ ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg2.out$n) || dumpit kg2.out
|
||||
cat unsigned.db $ksk.key $zsk.key >$file
|
||||
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk >s.out$n || dumpit s.out$n
|
||||
echo "ns.sub.${zone}. 3600 IN NSEC ${zone}. A AAAA" >>${file}
|
||||
$SIGNER -Px -Z nonsecify -O full -o ${zone} -f ${file}.tmp ${file} $zsk >s.out$n || dumpit s.out$n
|
||||
$SIGNER -Px -U nonsecify -O full -o ${zone} -f ${file}.tmp ${file} $zsk >s.out$n || dumpit s.out$n
|
||||
# dnssec-signzone signs any node with a NSEC record.
|
||||
awk '$1 ~ /^ns.sub/ && $4 == "RRSIG" && $5 != "NSEC" { next; } { print; }' ${file}.tmp >${file}
|
||||
|
||||
@@ -207,7 +207,7 @@ ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} 2>kg2.out$n) || dumpit kg2.out
|
||||
cat unsigned.db $ksk.key $zsk.key >$file
|
||||
$SIGNER -P -O full -o ${zone} -f ${file} ${file} $ksk >s.out$n || 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 || dumpit s.out$n
|
||||
$SIGNER -Px -U nonsecify -O full -o ${zone} -f ${file} ${file} $zsk >s.out$n || 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
|
||||
@@ -223,7 +223,7 @@ awk '
|
||||
$4 == "NSEC3" && $9 == "'$a'" { $9 = "'$b'"; print; next; }
|
||||
$4 == "NSEC3" && NF == 9 { next; }
|
||||
{ print; }' ${file} >${file}.tmp
|
||||
$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
$SIGNER -3 - -Px -U nonsecify -O full -o ${zone} -f ${file} ${file}.tmp $zsk >s.out$n || dumpit s.out$n
|
||||
|
||||
# extra NSEC3 record
|
||||
setup ksk+zsk.nsec3.extra-nsec3 bad
|
||||
@@ -242,7 +242,7 @@ $4 == "NSEC3" && NF == 9 {
|
||||
}' ${file} >${file}.tmp
|
||||
cat ${file}.tmp >>${file}
|
||||
rm -f ${file}.tmp
|
||||
$SIGNER -3 - -Px -Z nonsecify -O full -o ${zone} -f ${file} ${file} $zsk >s.out$n || dumpit s.out$n
|
||||
$SIGNER -3 - -Px -U nonsecify -O full -o ${zone} -f ${file} ${file} $zsk >s.out$n || dumpit s.out$n
|
||||
|
||||
# sign and verify with journal file
|
||||
setup updated other
|
||||
@@ -254,3 +254,15 @@ sed -e '/serial/s/0/1/' $file >${file}.update
|
||||
echo "extra 3600 IN A 4.3.2.1" >>${file}.update
|
||||
$SIGNER -SPx -o ${zone} -f ${file}.update ${file}.update >s.out$n || dumpit s.out$n
|
||||
$MAKEJOURNAL updated ${file} ${file}.update ${file}.jnl >mj.out$n 2>&1 || dumpit mj.out$n
|
||||
|
||||
# NSEC zone with ZONEMD.
|
||||
setup ksk+zsk.zonemd.nsec good
|
||||
$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} >kg1.out$n 2>&1 || dumpit kg1.out$n
|
||||
$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} >kg2.out$n 2>&1 || dumpit kg2.out$n
|
||||
$SIGNER -Z simple-sha384 -SPx -o ${zone} -f ${file} unsigned.db >s.out$n || dumpit s.out$n
|
||||
|
||||
# NSEC3 zone with ZONEMD.
|
||||
setup ksk+zsk.zonemd.nsec3 good
|
||||
$KEYGEN -a ${DEFAULT_ALGORITHM} ${zone} >kg1.out$n 2>&1 || dumpit kg1.out$n
|
||||
$KEYGEN -a ${DEFAULT_ALGORITHM} -fK ${zone} >kg2.out$n 2>&1 || dumpit kg2.out$n
|
||||
$SIGNER -3 - -Z simple-sha512 -SPx -o ${zone} -f ${file} unsigned.db >s.out$n || dumpit s.out$n
|
||||
|
Reference in New Issue
Block a user