From: Mark Andrews Date: Wed, 1 Dec 2021 13:34:38 +0000 (+1100) Subject: Reject NSEC records with next field with \000 label X-Git-Tag: v9.17.21~5^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0aaaa8768f317db2a92fd311122889f6cb8afe50;p=thirdparty%2Fbind9.git Reject NSEC records with next field with \000 label A number of DNS implementation produce NSEC records with bad type maps that don't contain types that exist at the name leading to NODATA responses being synthesize instead of the records in the zone. NSEC records with these bad type maps often have the NSEC NSEC field set to '\000.QNAME'. We look for the first label of this pattern. e.g. example.com NSEC \000.example.com SOA NS NSEC RRSIG example.com RRRSIG NSEC ... example.com SOA ... example.com RRRSIG SOA ... example.com NS ... example.com RRRSIG NS ... example.com A ... example.com RRRSIG A ... A is missing from the type map. This introduces a temporary option 'reject-000-label' to control this behaviour. --- diff --git a/bin/named/config.c b/bin/named/config.c index 6a8fc599fb7..e93ad273edb 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -177,6 +177,7 @@ options {\n\ query-source address *;\n\ query-source-v6 address *;\n\ recursion true;\n\ + reject-000-label yes;\n\ request-expire true;\n\ request-ixfr true;\n\ require-server-cookie no;\n\ diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index f02d52d4256..6c1ec9b2601 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -388,6 +388,7 @@ OPTIONS recursing-file quoted_string; recursion boolean; recursive-clients integer; + reject-000-label boolean;// deprecated request-expire boolean; request-ixfr boolean; request-nsid boolean; @@ -793,6 +794,7 @@ VIEW window integer; }; recursion boolean; + reject-000-label boolean;// deprecated request-expire boolean; request-ixfr boolean; request-nsid boolean; diff --git a/bin/named/server.c b/bin/named/server.c index 852d7dbf54f..f7db73faf93 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -4456,6 +4456,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, INSIST(result == ISC_R_SUCCESS); view->acceptexpired = cfg_obj_asboolean(obj); + obj = NULL; + result = named_config_get(maps, "reject-000-label", &obj); + INSIST(result == ISC_R_SUCCESS); + view->reject_000_label = cfg_obj_asboolean(obj); + obj = NULL; /* 'optionmaps', not 'maps': don't check named_g_defaults yet */ (void)named_config_get(optionmaps, "dnssec-validation", &obj); diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 279ae583d3b..97f4e925945 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -2100,6 +2100,16 @@ Boolean Options default is ``no``. Setting this option to ``yes`` leaves ``named`` vulnerable to replay attacks. +``reject-000-label`` + This can be used to control whether NSEC records which have the + ``next`` field starting with the ``\\000`` label are cached for + ``synth-from-dnssec``. There are a number of DNSSEC implementations + that generate bad NSEC type maps where the ``next`` field starts with + the ``\\000`` label and between BIND 9.18 and BIND 9.20 there will be + a campaign to get these servers corrected. In BIND 9.18 this defaults + to ``yes``. In BIND 9.20 (BIND 9.19) this will default to ``no`` and + in BIND 9.22 (BIND 9.21) this option will be removed. + ``querylog`` Query logging provides a complete log of all incoming queries and all query errors. This provides more insight into the server's activity, but with a @@ -2247,6 +2257,16 @@ Boolean Options named caching broken NSEC records from negative responses from servers that emit broken NSEC records with missing types that actually exist. + ``reject-000-label`` can be used to control whether NSEC records + which have the ``next`` field starting with the ``\\000`` label + are cached for ``synth-from-dnssec``. There are a number of + DNSSEC implementations that generate bad NSEC type maps where + the ``next`` field starts with the ``\\000`` label and between + BIND 9.18 and BIND 9.20 there will be a campaign to get these + servers corrected. In BIND 9.18 this defaults to ``yes``. In + BIND 9.20 (BIND 9.19) this will default to ``no`` and in BIND 9.22 + (BIND 9.21) this option will be removed. + .. note:: DNSSEC validation must be enabled for this option to be effective. This initial implementation only covers synthesis of answers from NSEC records; synthesis from NSEC3 is planned for the future. This diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index 52c1da4f401..ebfc33e9754 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -455,6 +455,7 @@ options { recursing\-file quoted_string; recursion boolean; recursive\-clients integer; + reject\-000\-label boolean;// deprecated request\-expire boolean; request\-ixfr boolean; request\-nsid boolean; @@ -896,6 +897,7 @@ view string [ class ] { window integer; }; recursion boolean; + reject\-000\-label boolean;// deprecated request\-expire boolean; request\-ixfr boolean; request\-nsid boolean; diff --git a/doc/misc/options b/doc/misc/options index 52485fd3386..f015f926a04 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -313,6 +313,7 @@ options { recursing-file ; recursion ; recursive-clients ; + reject-000-label ; // deprecated request-expire ; request-ixfr ; request-nsid ; @@ -673,6 +674,7 @@ view [ ] { window ; }; recursion ; + reject-000-label ; // deprecated request-expire ; request-ixfr ; request-nsid ; diff --git a/doc/misc/options.active b/doc/misc/options.active index 68aafb9ec92..882c2473481 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -311,6 +311,7 @@ options { recursing-file ; recursion ; recursive-clients ; + reject-000-label ; // deprecated request-expire ; request-ixfr ; request-nsid ; @@ -669,6 +670,7 @@ view [ ] { window ; }; recursion ; + reject-000-label ; // deprecated request-expire ; request-ixfr ; request-nsid ; diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst index 8e69a096864..862461f6900 100644 --- a/doc/misc/options.grammar.rst +++ b/doc/misc/options.grammar.rst @@ -231,6 +231,7 @@ recursing-file ; recursion ; recursive-clients ; + reject-000-label ; // deprecated request-expire ; request-ixfr ; request-nsid ; diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index f1ec93877f3..43deee1039f 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -130,6 +130,7 @@ struct dns_view { bool synthfromdnssec; bool trust_anchor_telemetry; bool root_key_sentinel; + bool reject_000_label; dns_transfer_format_t transfer_format; dns_acl_t *cacheacl; dns_acl_t *cacheonacl; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e8b17aae19b..64fe5d0b580 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -5210,6 +5210,32 @@ check_soa_and_dnskey(dns_rdataset_t *nsecset) { return (true); } +/* + * Look for NSEC next name that starts with the label '\000'. + */ +static bool +has_000_label(dns_rdataset_t *nsecset) { + dns_rdataset_t rdataset; + isc_result_t result; + + dns_rdataset_init(&rdataset); + dns_rdataset_clone(nsecset, &rdataset); + + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + if (rdata.length > 1 && rdata.data[0] == 1 && + rdata.data[1] == 0) { + dns_rdataset_disassociate(&rdataset); + return (true); + } + } + dns_rdataset_disassociate(&rdataset); + return (false); +} + /* * The validator has finished. */ @@ -5645,6 +5671,17 @@ answer_response: !check_soa_and_dnskey(rdataset)) { continue; } + + /* + * Look for \000 label in next name. + */ + if (rdataset->type == dns_rdatatype_nsec && + fctx->res->view->reject_000_label && + has_000_label(rdataset)) + { + continue; + } + result = dns_db_findnode(fctx->cache, name, true, &nsnode); if (result != ISC_R_SUCCESS) { diff --git a/lib/dns/view.c b/lib/dns/view.c index de5464f288c..5b6ef543888 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -240,6 +240,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, view->synthfromdnssec = true; view->trust_anchor_telemetry = true; view->root_key_sentinel = true; + view->reject_000_label = true; view->new_zone_dir = NULL; view->new_zone_file = NULL; view->new_zone_db = NULL; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index ee0f3091f3b..bf53b119d6f 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2118,6 +2118,7 @@ static cfg_clausedef_t view_clauses[] = { { "queryport-pool-updateinterval", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "rate-limit", &cfg_type_rrl, 0 }, { "recursion", &cfg_type_boolean, 0 }, + { "reject-000-label", &cfg_type_boolean, CFG_CLAUSEFLAG_DEPRECATED }, { "request-nsid", &cfg_type_boolean, 0 }, { "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "require-server-cookie", &cfg_type_boolean, 0 },