2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

Add ZONEMD checking options

Add options (not yet functional) to named.conf and the
named-checkzone command line to enable ZONEMD checks.
Update documentation to describe them.
This commit is contained in:
Mark Andrews
2021-06-26 12:45:53 +10:00
committed by Evan Hunt
parent 2c781434a1
commit dbebd26326
14 changed files with 148 additions and 25 deletions

View File

@@ -91,6 +91,7 @@ dns_zoneopt_t zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_CHECKMX |
#endif /* if CHECK_SIBLING */
DNS_ZONEOPT_CHECKSVCB | DNS_ZONEOPT_CHECKWILDCARD |
DNS_ZONEOPT_WARNMXCNAME | DNS_ZONEOPT_WARNSRVCNAME;
dns_zoneopt_t zonemd_options;
static isc_symtab_t *symtab = NULL;
@@ -614,7 +615,9 @@ setup_logging(FILE *errout) {
logconfig, "default_stderr", ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC, ISC_LOGDESTINATION_FILE(errout), 0,
ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_DEFAULT);
if (debug > 1) {
isc_log_setdebuglevel(debug - 1);
}
return ISC_R_SUCCESS;
}
@@ -666,6 +669,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
dns_zone_setclass(zone, rdclass);
dns_zone_setoption(zone, zone_options, true);
dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
dns_zone_setoption(zone, zonemd_options, true);
dns_zone_setmaxttl(zone, maxttl);

View File

@@ -24,6 +24,7 @@
#include <dns/masterdump.h>
#include <dns/types.h>
#include <dns/zone.h>
#include <dns/zonemd.h>
isc_result_t
setup_logging(FILE *errout);
@@ -45,3 +46,4 @@ extern bool docheckmx;
extern bool docheckns;
extern bool dochecksrv;
extern dns_zoneopt_t zone_options;
extern dns_zoneopt_t zonemd_options;

View File

@@ -66,7 +66,7 @@ usage(void);
static void
usage(void) {
fprintf(stderr,
"usage: %s [-djqvD] [-c class] "
"usage: %s [-djqvDz] [-c class] "
"[-f inputformat] [-F outputformat] [-J filename] "
"[-s (full|relative)] [-t directory] [-w directory] "
"[-k (ignore|warn|fail)] [-m (ignore|warn|fail)] "
@@ -136,8 +136,8 @@ main(int argc, char **argv) {
isc_commandline_errprint = false;
while ((c = isc_commandline_parse(argc, argv,
"c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:C:"
"DF:M:R:S:T:W:")) != EOF)
"c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:z:"
"C:DF:M:R:S:T:W:")) != EOF)
{
switch (c) {
case 'c':
@@ -414,6 +414,18 @@ main(int argc, char **argv) {
}
break;
case 'z':
if (ARGCMP("fail")) {
zone_options |= DNS_ZONEOPT_ZONEMD_CHECK;
} else if (ARGCMP("ignore")) {
zone_options &= ~DNS_ZONEOPT_ZONEMD_CHECK;
} else {
fprintf(stderr, "invalid argument to -Z: %s\n",
isc_commandline_argument);
exit(EXIT_FAILURE);
}
break;
case '?':
if (isc_commandline_option != '?') {
fprintf(stderr, "%s: invalid argument -%c\n",

View File

@@ -23,7 +23,7 @@ named-checkzone - zone file validation tool
Synopsis
~~~~~~~~
:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {zonename} {filename}
:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] [**-z** mode] {zonename} {filename}
Description
~~~~~~~~~~~
@@ -220,6 +220,12 @@ Options
wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn``
(the default) and ``ignore``.
.. option:: -z mode
This option specifies whether to check the contents of a zone against
the cryptographic hash in a ZONEMD record (:rfc:`8976`).
Possible modes are ``fail`` and ``ignore`` (the default).
.. option:: zonename
This indicates the domain name of the zone being checked.

View File

@@ -23,7 +23,7 @@ named-compilezone - zone file converting tool
Synopsis
~~~~~~~~
:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {**-o** filename} {zonename} {filename}
:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] [**-z** mode] {**-o** filename} {zonename} {filename}
Description
~~~~~~~~~~~
@@ -224,6 +224,18 @@ Options
wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn``
and ``ignore`` (the default).
.. option:: -z option
This option specifies whether to check the contents of a zone against
the cryptographic hash in a ZONEMD record (:rfc:`8976`). This is
off by default. Up to four options can be active simultaneously;
these options are: ``check`` (check the contents of the zone against
the ZONEMD hash if a ZONEMD record is present), ``required`` (reject
a zone if ZONEMD is *not* present), ``dnssec-only`` (reject a zone if
ZONEMD is present but the zone is not DNSSEC-signed), and
``accept-expired`` (allow expired RRSIG records when verifying the
ZONEMD hash).
.. option:: zonename
This indicates the domain name of the zone being checked.

View File

@@ -256,6 +256,9 @@ options {\n\
try-tcp-refresh yes; /* BIND 8 compat */\n\
zero-no-soa-ttl yes;\n\
zone-statistics terse;\n\
check-zonemd yes;\n\
check-zonemd-dnssec yes;\n\
require-zonemd no;\n\
};\n\
"

View File

@@ -1494,6 +1494,24 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
dns_zone_setrad(zone, rad);
}
}
obj = NULL;
result = named_config_get(maps, "check-zonemd", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setoption(zone, DNS_ZONEOPT_ZONEMD_CHECK,
cfg_obj_asboolean(obj));
obj = NULL;
result = named_config_get(maps, "check-zonemd-dnssec", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setoption(zone, DNS_ZONEOPT_ZONEMD_DNSSEC,
cfg_obj_asboolean(obj));
obj = NULL;
result = named_config_get(maps, "require-zonemd", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setoption(zone, DNS_ZONEOPT_ZONEMD_REQUIRED,
cfg_obj_asboolean(obj));
} else if (ztype == dns_zone_redirect) {
dns_zone_setnotifytype(zone, dns_notifytype_no);

View File

@@ -2725,6 +2725,31 @@ Boolean Options
the ``dohpath`` parameter exists when the ``alpn`` indicates
that it should be present. The default is ``yes``.
.. namedconf:statement:: check-zonemd
:tags: zone
:short: Specifies whether to check zone contents against the ZONEMD record.
This option indicates that a zone's contents should be checked
against the cryptographic hash in a ZONEMD record, if such a record
is present, when it is loaded or transferred. This helps to ensure
integrity of the zone data. The default is ``yes``.
.. namedconf:statement:: check-zonemd-dnssec
:tags: zone
:short: Require DNSSEC signatures for ZONEMD records.
When this option is set to the default value of ``yes``, zones
containing ZONEMD records will be rejected if they are not
DNSSEC-signed. (Note that this is not optional for zones of type
``mirror``: if the option is disabled, it will be silently ignored.)
.. namedconf:statement:: require-zonemd
:tags: zone
:short: Controls whether a ZONEMD record is required to be present in the zone.
This indicates that a ZONEMD record **must** be present in a
zone when it is loaded or transferred. The default is ``no``.
.. namedconf:statement:: zero-no-soa-ttl
:tags: zone, query, server
:short: Specifies whether to set the time to live (TTL) of the SOA record to zero, when returning authoritative negative responses to SOA queries.
@@ -6829,17 +6854,18 @@ Zone Types
:short: Contains a DNSSEC-validated duplicate of the main data for a zone.
A mirror zone is similar to a zone of :any:`type secondary`, except its
data is subject to DNSSEC validation before being used in answers.
Validation is applied to the entire zone during the zone transfer
process, and again when the zone file is loaded from disk upon
restarting :iscman:`named`. If validation of a new version of a mirror zone
fails, a retransfer is scheduled; in the meantime, the most recent
correctly validated version of that zone is used until it either
expires or a newer version validates correctly. If no usable zone
data is available for a mirror zone, due to either transfer failure
or expiration, traditional DNS recursion is used to look up the
answers instead. Mirror zones cannot be used in a view that does not
have recursion enabled.
data is subject to cryptographic validation before being used in
answers. The zone contents must be verified by a signed and
validated ZONEMD record, or else DNSSEC validation must be applied
to the entire zone, both during the zone transfer process and again when
the zone file is loaded from disk upon restarting :iscman:`named`.
If validation of a new version of a mirror zone fails, a retransfer is
scheduled; in the meantime, the most recent correctly validated version
of that zone is used until it either expires or a newer version
validates correctly. If no usable zone data is available for a mirror
zone, due to either transfer failure or expiration, traditional DNS
recursion is used to look up the answers instead. Mirror zones cannot be
used in a view that does not have recursion enabled.
Answers coming from a mirror zone look almost exactly like answers
from a zone of :any:`type secondary`, with the notable exceptions that
@@ -7102,6 +7128,15 @@ Zone Options
:any:`check-sibling`
See the description of :any:`check-sibling` in :ref:`boolean_options`.
:any:`check-zonemd`
See the description of :any:`check-zonemd` in :ref:`boolean_options`.
:any:`check-zonemd-dnssec`
See the description of :any:`check-zonemd-dnssec` in :ref:`boolean_options`.
:any:`require-zonemd`
See the description of :any:`require-zonemd` in :ref:`boolean_options`.
:any:`zero-no-soa-ttl`
See the description of :any:`zero-no-soa-ttl` in :ref:`boolean_options`.
@@ -7387,6 +7422,7 @@ Zone Options
:any:`send-report-channel`
See the description of :any:`send-report-channel` in :namedconf:ref:`options`.
.. _zone_templates:
Zone Templates

View File

@@ -7,6 +7,8 @@ zone <string> [ <class> ] {
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
check-names ( fail | warn | ignore );
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
database <string>;
file <quoted_string>;
ixfr-from-differences <boolean>;
@@ -38,6 +40,7 @@ zone <string> [ <class> ] {
request-expire <boolean>;
request-ixfr <boolean>;
request-ixfr-max-diffs <integer>;
require-zonemd <boolean>;
template <string>;
transfer-source ( <ipv4_address> | * );
transfer-source-v6 ( <ipv6_address> | * );

View File

@@ -96,6 +96,8 @@ options {
check-srv-cname ( fail | warn | ignore );
check-svcb <boolean>;
check-wildcard <boolean>;
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
clients-per-query <integer>;
cookie-algorithm ( siphash24 );
cookie-secret <string>; // may occur multiple times
@@ -258,6 +260,7 @@ options {
request-nsid <boolean>;
request-zoneversion <boolean>;
require-server-cookie <boolean>;
require-zonemd <boolean>;
resolver-query-timeout <integer>;
resolver-use-dns64 <boolean>;
response-padding { <address_match_element>; ... } block-size <integer>;
@@ -380,6 +383,8 @@ template <string> {
check-srv-cname ( fail | warn | ignore );
check-svcb <boolean>;
check-wildcard <boolean>;
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
checkds ( explicit | <boolean> );
database <string>;
dlz <string>;
@@ -431,6 +436,7 @@ template <string> {
request-expire <boolean>;
request-ixfr <boolean>;
request-ixfr-max-diffs <integer>;
require-zonemd <boolean>;
send-report-channel <string>;
serial-update-method ( date | increment | unixtime );
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
@@ -492,6 +498,8 @@ view <string> [ <class> ] {
check-srv-cname ( fail | warn | ignore );
check-svcb <boolean>;
check-wildcard <boolean>;
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
clients-per-query <integer>;
deny-answer-addresses { <address_match_element>; ... } [ except-from { <string>; ... } ];
deny-answer-aliases { <string>; ... } [ except-from { <string>; ... } ];
@@ -630,6 +638,7 @@ view <string> [ <class> ] {
request-nsid <boolean>;
request-zoneversion <boolean>;
require-server-cookie <boolean>;
require-zonemd <boolean>;
resolver-query-timeout <integer>;
resolver-use-dns64 <boolean>;
response-padding { <address_match_element>; ... } block-size <integer>;

View File

@@ -15,6 +15,8 @@ zone <string> [ <class> ] {
check-srv-cname ( fail | warn | ignore );
check-svcb <boolean>;
check-wildcard <boolean>;
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
checkds ( explicit | <boolean> );
database <string>;
dlz <string>;
@@ -54,6 +56,7 @@ zone <string> [ <class> ] {
parental-source ( <ipv4_address> | * );
parental-source-v6 ( <ipv6_address> | * );
provide-zoneversion <boolean>;
require-zonemd <boolean>;
send-report-channel <string>;
serial-update-method ( date | increment | unixtime );
sig-signing-nodes <integer>;

View File

@@ -7,6 +7,8 @@ zone <string> [ <class> ] {
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
check-names ( fail | warn | ignore );
check-zonemd <boolean>;
check-zonemd-dnssec <boolean>;
checkds ( explicit | <boolean> );
database <string>;
dlz <string>;
@@ -55,6 +57,7 @@ zone <string> [ <class> ] {
request-expire <boolean>;
request-ixfr <boolean>;
request-ixfr-max-diffs <integer>;
require-zonemd <boolean>;
send-report-channel <string>;
sig-signing-nodes <integer>;
sig-signing-signatures <integer>;

View File

@@ -96,14 +96,20 @@ typedef enum {
DNS_ZONEOPT_LOGREPORTS = 1 << 23, /* Log error-reporting queries */
DNS_ZONEOPT_DNSKEYKSKONLY = 1 << 24, /*%< dnssec-dnskey-kskonly */
DNS_ZONEOPT_CHECKDUPRR = 1 << 25, /*%< check-dup-records */
DNS_ZONEOPT_CHECKDUPRRFAIL = 1 << 26, /*%< fatal check-dup-records
* failures */
DNS_ZONEOPT_CHECKSPF = 1 << 27, /*%< check SPF records */
DNS_ZONEOPT_CHECKTTL = 1 << 28, /*%< check max-zone-ttl */
DNS_ZONEOPT_AUTOEMPTY = 1 << 29, /*%< automatic empty zone */
DNS_ZONEOPT_CHECKSVCB = 1 << 30, /*%< check SVBC records */
DNS_ZONEOPT_ZONEVERSION = 1U << 31, /*%< enable zoneversion */
DNS_ZONEOPT_FULLSIGN = 1ULL << 32, /*%< fully sign zone */
DNS_ZONEOPT_CHECKDUPRRFAIL = 1 << 26, /*%< fatal check-dup-records
* failures */
DNS_ZONEOPT_CHECKSPF = 1 << 27, /*%< check SPF records */
DNS_ZONEOPT_CHECKTTL = 1 << 28, /*%< check max-zone-ttl */
DNS_ZONEOPT_AUTOEMPTY = 1 << 29, /*%< automatic empty zone */
DNS_ZONEOPT_CHECKSVCB = 1 << 30, /*%< check SVBC records */
DNS_ZONEOPT_ZONEVERSION = 1U << 31, /*%< enable zoneversion */
DNS_ZONEOPT_FULLSIGN = 1ULL << 32, /*%< fully sign zone */
DNS_ZONEOPT_ZONEMD_CHECK = 1ULL << 33, /*%< zonemd check */
DNS_ZONEOPT_ZONEMD_DNSSEC = 1ULL << 34, /*%< zonemd DNSSEC only */
DNS_ZONEOPT_ZONEMD_REQUIRED = 1ULL << 35, /*%< zonemd required */
DNS_ZONEOPT_ZONEMD_NOEXPIRED = 1ULL << 36, /*%< don't allow expired
* RRSIG when verifying
* zonemd */
DNS_ZONEOPT___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
} dns_zoneopt_t;

View File

@@ -2410,6 +2410,12 @@ static cfg_clausedef_t zone_clauses[] = {
{ "zone-statistics", &cfg_type_zonestat,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
{ "check-zonemd", &cfg_type_boolean,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ "check-zonemd-dnssec", &cfg_type_boolean,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ "require-zonemd", &cfg_type_boolean,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ NULL, NULL, 0 }
};