From eaac2057c7881b051b52bcd3948a9ede449e63e6 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Mon, 30 Apr 2018 16:10:17 -0700 Subject: [PATCH 1/3] option to disable validation under specified names - added new 'validate-except' option, which configures an NTA with expiry of 0xffffffff. NTAs with that value in the expiry field do not expire, are are not written out when saving the NTA table and are not dumped by rndc secroots --- bin/named/named.conf.docbook | 46 ++++----- bin/named/server.c | 76 +++++++++++--- bin/tests/system/checkconf/good.conf | 3 + doc/arm/Bv9ARM-book.xml | 18 ++++ doc/arm/options.grammar.xml | 25 +++-- doc/arm/static-stub.zoneopt.xml | 2 +- doc/misc/options | 58 +++++------ doc/misc/static-stub.zoneopt | 2 +- lib/dns/include/dns/nta.h | 9 +- lib/dns/nta.c | 142 ++++++++++----------------- lib/isccfg/namedconf.c | 3 +- 11 files changed, 208 insertions(+), 176 deletions(-) diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 8587f7283c..0a6c7bde3e 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -13,7 +13,7 @@ - 2018-05-29 + 2018-06-21 ISC @@ -224,9 +224,9 @@ options { coresize ( default | unlimited | sizeval ); datasize ( default | unlimited | sizeval ); deny-answer-addresses { address_match_element; ... } [ - except-from { quoted_string; ... } ]; - deny-answer-aliases { quoted_string; ... } [ except-from { - quoted_string; ... } ]; + except-from { string; ... } ]; + deny-answer-aliases { string; ... } [ except-from { string; ... + } ]; dialup ( notify | notify-passive | passive | refresh | boolean ); directory quoted_string; disable-algorithms string { string; @@ -257,14 +257,12 @@ options { dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); - dnstap { ( all | auth | client | forwarder | - resolver ) [ ( query | response ) ]; ... }; - dnstap-identity ( quoted_string | none | - hostname ); - dnstap-output ( file | unix ) quoted_string [ - size ( unlimited | size ) ] [ versions ( - unlimited | integer ) ] [ suffix ( increment - | timestamp ) ]; + dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | + response ) ]; ... }; + dnstap-identity ( quoted_string | none | hostname ); + dnstap-output ( file | unix ) quoted_string [ size ( unlimited | + size ) ] [ versions ( unlimited | integer ) ] [ suffix ( + increment | timestamp ) ]; dnstap-version ( quoted_string | none ); dscp integer; dual-stack-servers [ port integer ] { ( quoted_string [ port @@ -362,7 +360,7 @@ options { preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; - qname-minimization ( strict | relaxed | disabled ); + qname-minimization ( strict | relaxed | disabled | off ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -413,7 +411,7 @@ options { nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; - root-delegation-only [ exclude { quoted_string; ... } ]; + root-delegation-only [ exclude { string; ... } ]; root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; @@ -463,6 +461,7 @@ options { use-v4-udp-ports { portrange; ... }; use-v6-udp-ports { portrange; ... }; v6-bias integer; + validate-except { string; ... }; version ( quoted_string | none ); zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; @@ -574,9 +573,9 @@ view string [ class ] { cleaning-interval integer; clients-per-query integer; deny-answer-addresses { address_match_element; ... } [ - except-from { quoted_string; ... } ]; - deny-answer-aliases { quoted_string; ... } [ except-from { - quoted_string; ... } ]; + except-from { string; ... } ]; + deny-answer-aliases { string; ... } [ except-from { string; ... + } ]; dialup ( notify | notify-passive | passive | refresh | boolean ); disable-algorithms string { string; ... }; @@ -610,8 +609,8 @@ view string [ class ] { dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); - dnstap { ( all | auth | client | forwarder | - resolver ) [ ( query | response ) ]; ... }; + dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | + response ) ]; ... }; dual-stack-servers [ port integer ] { ( quoted_string [ port integer ] [ dscp integer ] | ipv4_address [ port integer ] [ dscp integer ] | ipv6_address [ port @@ -689,7 +688,7 @@ view string [ class ] { preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; - qname-minimization ( strict | relaxed | disabled ); + qname-minimization ( strict | relaxed | disabled | off ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -735,7 +734,7 @@ view string [ class ] { nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; - root-delegation-only [ exclude { quoted_string; ... } ]; + root-delegation-only [ exclude { string; ... } ]; root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; @@ -797,6 +796,7 @@ view string [ class ] { update-check-ksk boolean; use-alt-transfer-source boolean; v6-bias integer; + validate-except { string; ... }; zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; zone string [ class ] { @@ -878,7 +878,7 @@ view string [ class ] { serial-update-method ( date | increment | unixtime ); server-addresses { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; - server-names { quoted_string; ... }; + server-names { string; ... }; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; @@ -982,7 +982,7 @@ zone string [ class ] { serial-update-method ( date | increment | unixtime ); server-addresses { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; - server-names { quoted_string; ... }; + server-names { string; ... }; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; diff --git a/bin/named/server.c b/bin/named/server.c index 4660ad557d..2145578736 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3692,6 +3692,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, isc_dscp_t dscp4 = -1, dscp6 = -1; dns_dyndbctx_t *dctx = NULL; unsigned int resolver_param; + dns_ntatable_t *ntatable = NULL; const char *qminmode = NULL; REQUIRE(DNS_VIEW_VALID(view)); @@ -5348,8 +5349,35 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0, NULL)); view->redirectzone = name; - } else + } else { view->redirectzone = NULL; + } + + /* + * Exceptions to DNSSEC validation. + */ + obj = NULL; + result = named_config_get(maps, "validate-except", &obj); + if (result == ISC_R_SUCCESS) { + result = dns_view_getntatable(view, &ntatable); + } + if (result == ISC_R_SUCCESS) { + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + dns_fixedname_t fntaname; + dns_name_t *ntaname; + + ntaname = dns_fixedname_initname(&fntaname); + obj = cfg_listelt_value(element); + CHECK(dns_name_fromstring(ntaname, + cfg_obj_asstring(obj), + 0, NULL)); + CHECK(dns_ntatable_add(ntatable, ntaname, + true, 0, 0xffffffffU)); + } + } #ifdef HAVE_DNSTAP /* @@ -5362,35 +5390,51 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, result = ISC_R_SUCCESS; cleanup: - if (clients != NULL) + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + if (clients != NULL) { dns_acl_detach(&clients); - if (mapped != NULL) + } + if (mapped != NULL) { dns_acl_detach(&mapped); - if (excluded != NULL) + } + if (excluded != NULL) { dns_acl_detach(&excluded); - if (ring != NULL) + } + if (ring != NULL) { dns_tsigkeyring_detach(&ring); - if (zone != NULL) + } + if (zone != NULL) { dns_zone_detach(&zone); - if (dispatch4 != NULL) + } + if (dispatch4 != NULL) { dns_dispatch_detach(&dispatch4); - if (dispatch6 != NULL) + } + if (dispatch6 != NULL) { dns_dispatch_detach(&dispatch6); - if (resstats != NULL) + } + if (resstats != NULL) { isc_stats_detach(&resstats); - if (resquerystats != NULL) + } + if (resquerystats != NULL) { dns_stats_detach(&resquerystats); - if (order != NULL) + } + if (order != NULL) { dns_order_detach(&order); - if (cmctx != NULL) + } + if (cmctx != NULL) { isc_mem_detach(&cmctx); - if (hmctx != NULL) + } + if (hmctx != NULL) { isc_mem_detach(&hmctx); - - if (cache != NULL) + } + if (cache != NULL) { dns_cache_detach(&cache); - if (dctx != NULL) + } + if (dctx != NULL) { dns_dyndb_destroyctx(&dctx); + } return (result); } diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf index 6d58e43550..8fb844fb2f 100644 --- a/bin/tests/system/checkconf/good.conf +++ b/bin/tests/system/checkconf/good.conf @@ -65,6 +65,9 @@ options { max-cache-size 20000000000000; nta-lifetime 604800; nta-recheck 604800; + validate-except { + "corp"; + }; transfer-source 0.0.0.0 dscp 63; zone-statistics none; }; diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index a0e195efd1..0ee094c4a6 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -6646,6 +6646,24 @@ options { + + validate-except + + + Specifies a list of domain names at and beneath which DNSSEC + validation should not be performed, + regardless of the presence of a trust anchor at or above + those names. This may be used, for example, when configuring + a top-level domain intended only for local use, so that the + lack of a secure delegation for that domain in the root zone + will not cause validation failures. (This is similar + to setting a negative trust anchor, except that it is a + permanent configuration, whereas negative trust anchors + expire and are removed after a set period of time.) + + + + dnssec-accept-expired diff --git a/doc/arm/options.grammar.xml b/doc/arm/options.grammar.xml index ef3f33ce9b..41c115c4a0 100644 --- a/doc/arm/options.grammar.xml +++ b/doc/arm/options.grammar.xml @@ -63,9 +63,9 @@ coresize ( default | unlimited | sizeval ); datasize ( default | unlimited | sizeval ); deny-answer-addresses { address_match_element; ... } [ - except-from { quoted_string; ... } ]; - deny-answer-aliases { quoted_string; ... } [ except-from { - quoted_string; ... } ]; + except-from { string; ... } ]; + deny-answer-aliases { string; ... } [ except-from { string; ... + } ]; dialup ( notify | notify-passive | passive | refresh | boolean ); directory quoted_string; disable-algorithms string { string; @@ -96,14 +96,12 @@ dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); - dnstap { ( all | auth | client | forwarder | - resolver ) [ ( query | response ) ]; ... }; - dnstap-identity ( quoted_string | none | - hostname ); - dnstap-output ( file | unix ) quoted_string [ - size ( unlimited | size ) ] [ versions ( - unlimited | integer ) ] [ suffix ( increment - | timestamp ) ]; + dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | + response ) ]; ... }; + dnstap-identity ( quoted_string | none | hostname ); + dnstap-output ( file | unix ) quoted_string [ size ( unlimited | + size ) ] [ versions ( unlimited | integer ) ] [ suffix ( + increment | timestamp ) ]; dnstap-version ( quoted_string | none ); dscp integer; dual-stack-servers [ port integer ] { ( quoted_string [ port @@ -202,7 +200,7 @@ preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; - qname-minimization ( strict | relaxed | disabled ); + qname-minimization ( strict | relaxed | disabled | off ); query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; @@ -253,7 +251,7 @@ nsip-enable boolean ] [ nsdname-enable boolean ] [ dnsrps-enable boolean ] [ dnsrps-options { unspecified-text } ]; - root-delegation-only [ exclude { quoted_string; ... } ]; + root-delegation-only [ exclude { string; ... } ]; root-key-sentinel boolean; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; @@ -303,6 +301,7 @@ use-v4-udp-ports { portrange; ... }; use-v6-udp-ports { portrange; ... }; v6-bias integer; + validate-except { string; ... }; version ( quoted_string | none ); zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; diff --git a/doc/arm/static-stub.zoneopt.xml b/doc/arm/static-stub.zoneopt.xml index 84e9bb0f41..4aadf68936 100644 --- a/doc/arm/static-stub.zoneopt.xml +++ b/doc/arm/static-stub.zoneopt.xml @@ -19,7 +19,7 @@ forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; max-records integer; server-addresses { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; - server-names { quoted_string; ... }; + server-names { string; ... }; zone-statistics ( full | terse | none | boolean ); }; diff --git a/doc/misc/options b/doc/misc/options index 41686fb475..c0ad48b30a 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -113,9 +113,9 @@ options { datasize ( default | unlimited | ); deallocate-on-exit ; // obsolete deny-answer-addresses { ; ... } [ - except-from { ; ... } ]; - deny-answer-aliases { ; ... } [ except-from { - ; ... } ]; + except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... + } ]; dialup ( notify | notify-passive | passive | refresh | ); directory ; disable-algorithms { ; @@ -146,15 +146,13 @@ options { dnssec-secure-to-insecure ; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); - dnstap { ( all | auth | client | forwarder | - resolver ) [ ( query | response ) ]; ... }; // not configured - dnstap-identity ( | none | - hostname ); // not configured - dnstap-output ( file | unix ) [ - size ( unlimited | ) ] [ versions ( - unlimited | ) ] [ suffix ( increment - | timestamp ) ]; // not configured - dnstap-version ( | none ); // not configured + dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | + response ) ]; ... }; + dnstap-identity ( | none | hostname ); + dnstap-output ( file | unix ) [ size ( unlimited | + ) ] [ versions ( unlimited | ) ] [ suffix ( + increment | timestamp ) ]; + dnstap-version ( | none ); dscp ; dual-stack-servers [ port ] { ( [ port ] [ dscp ] | [ port @@ -178,14 +176,14 @@ options { forward ( first | only ); forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; - fstrm-set-buffer-hint ; // not configured - fstrm-set-flush-timeout ; // not configured - fstrm-set-input-queue-size ; // not configured - fstrm-set-output-notify-threshold ; // not configured - fstrm-set-output-queue-model ( mpsc | spsc ); // not configured - fstrm-set-output-queue-size ; // not configured - fstrm-set-reopen-interval ; // not configured - geoip-directory ( | none ); // not configured + fstrm-set-buffer-hint ; + fstrm-set-flush-timeout ; + fstrm-set-input-queue-size ; + fstrm-set-output-notify-threshold ; + fstrm-set-output-queue-model ( mpsc | spsc ); + fstrm-set-output-queue-size ; + fstrm-set-reopen-interval ; + geoip-directory ( | none ); geoip-use-ecs ; // obsolete glue-cache ; has-old-clients ; // obsolete @@ -321,7 +319,7 @@ options { dnsrps-enable ] [ dnsrps-options { } ]; rfc2308-type1 ; // not yet implemented - root-delegation-only [ exclude { ; ... } ]; + root-delegation-only [ exclude { ; ... } ]; root-key-sentinel ; rrset-order { [ class ] [ type ] [ name ] ; ... }; @@ -380,6 +378,7 @@ options { use-v4-udp-ports { ; ... }; use-v6-udp-ports { ; ... }; v6-bias ; + validate-except { ; ... }; version ( | none ); zero-no-soa-ttl ; zero-no-soa-ttl-cache ; @@ -478,9 +477,9 @@ view [ ] { cleaning-interval ; clients-per-query ; deny-answer-addresses { ; ... } [ - except-from { ; ... } ]; - deny-answer-aliases { ; ... } [ except-from { - ; ... } ]; + except-from { ; ... } ]; + deny-answer-aliases { ; ... } [ except-from { ; ... + } ]; dialup ( notify | notify-passive | passive | refresh | ); disable-algorithms { ; ... }; // may occur multiple times @@ -514,8 +513,8 @@ view [ ] { dnssec-secure-to-insecure ; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); - dnstap { ( all | auth | client | forwarder | - resolver ) [ ( query | response ) ]; ... }; // not configured + dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | + response ) ]; ... }; dual-stack-servers [ port ] { ( [ port ] [ dscp ] | [ port ] [ dscp ] | [ port @@ -651,7 +650,7 @@ view [ ] { dnsrps-enable ] [ dnsrps-options { } ]; rfc2308-type1 ; // not yet implemented - root-delegation-only [ exclude { ; ... } ]; + root-delegation-only [ exclude { ; ... } ]; root-key-sentinel ; rrset-order { [ class ] [ type ] [ name ] ; ... }; @@ -718,6 +717,7 @@ view [ ] { use-alt-transfer-source ; use-queryport-pool ; // obsolete v6-bias ; + validate-except { ; ... }; zero-no-soa-ttl ; zero-no-soa-ttl-cache ; zone [ ] { @@ -805,7 +805,7 @@ view [ ] { serial-update-method ( date | increment | unixtime ); server-addresses { ( | ) [ port ]; ... }; - server-names { ; ... }; + server-names { ; ... }; sig-signing-nodes ; sig-signing-signatures ; sig-signing-type ; @@ -910,7 +910,7 @@ zone [ ] { serial-update-method ( date | increment | unixtime ); server-addresses { ( | ) [ port ]; ... }; - server-names { ; ... }; + server-names { ; ... }; sig-signing-nodes ; sig-signing-signatures ; sig-signing-type ; diff --git a/doc/misc/static-stub.zoneopt b/doc/misc/static-stub.zoneopt index 74abe0b137..809daf38e7 100644 --- a/doc/misc/static-stub.zoneopt +++ b/doc/misc/static-stub.zoneopt @@ -6,6 +6,6 @@ zone [ ] { forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; max-records ; server-addresses { ( | ) [ port ]; ... }; - server-names { ; ... }; + server-names { ; ... }; zone-statistics ( full | terse | none | ); }; diff --git a/lib/dns/include/dns/nta.h b/lib/dns/include/dns/nta.h index 8221aade87..21af6499c3 100644 --- a/lib/dns/include/dns/nta.h +++ b/lib/dns/include/dns/nta.h @@ -122,9 +122,12 @@ dns_ntatable_add(dns_ntatable_t *ntatable, const dns_name_t *name, uint32_t lifetime); /*%< * Add a negative trust anchor to 'ntatable' for name 'name', - * which will expire at time 'now' + 'lifetime'. If 'force' is false, - * then the name will be checked periodically to see if it's bogus; - * if not, then the NTA will be allowed to expire early. + * which will expire at time 'now' + 'lifetime'. If 'force' is true, + * then the NTA will persist for the entire specified lifetime. + * If it is false, then the name will be queried periodically and + * validation will be attempted to see whether it's still bogus; + * if validation is successful, the NTA will be allowed to expire + * early and validation below the NTA will resume. * * Notes: * diff --git a/lib/dns/nta.c b/lib/dns/nta.c index 6cede2a6a7..f90a80a909 100644 --- a/lib/dns/nta.c +++ b/lib/dns/nta.c @@ -547,20 +547,28 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) { dns_name_t *name; isc_time_t t; - name = dns_fixedname_initname(&fn); - dns_rbt_fullnamefromnode(node, name); - dns_name_format(name, nbuf, sizeof(nbuf)); - isc_time_set(&t, n->expiry, 0); - isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); + /* + * Skip "validate-except" entries. + */ + if (n->expiry != 0xffffffffU) { + name = dns_fixedname_initname(&fn); + dns_rbt_fullnamefromnode(node, name); + dns_name_format(name, nbuf, sizeof(nbuf)); + isc_time_set(&t, n->expiry, 0); + isc_time_formattimestamp(&t, tbuf, + sizeof(tbuf)); - snprintf(obuf, sizeof(obuf), "%s%s: %s %s", - first ? "" : "\n", nbuf, - n->expiry <= now ? "expired" : "expiry", - tbuf); - first = false; - result = putstr(buf, obuf); - if (result != ISC_R_SUCCESS) - goto cleanup; + snprintf(obuf, sizeof(obuf), "%s%s: %s %s", + first ? "" : "\n", nbuf, + n->expiry <= now + ? "expired" + : "expiry", + tbuf); + first = false; + result = putstr(buf, obuf); + if (result != ISC_R_SUCCESS) + goto cleanup; + } } result = dns_rbtnodechain_next(&chain, NULL, NULL); if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { @@ -576,56 +584,6 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) { return (result); } -#if 0 -isc_result_t -dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) { - isc_result_t result; - dns_rbtnode_t *node; - dns_rbtnodechain_t chain; - isc_stdtime_t now; - - REQUIRE(VALID_NTATABLE(ntatable)); - - isc_stdtime_get(&now); - - RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); - dns_rbtnodechain_init(&chain, ntatable->view->mctx); - result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) - goto cleanup; - for (;;) { - dns_rbtnodechain_current(&chain, NULL, NULL, &node); - if (node->data != NULL) { - dns_nta_t *n = (dns_nta_t *) node->data; - char nbuf[DNS_NAME_FORMATSIZE], tbuf[80]; - dns_fixedname_t fn; - dns_name_t *name; - isc_time_t t; - - name = dns_fixedname_initname(&fn); - dns_rbt_fullnamefromnode(node, name); - dns_name_format(name, nbuf, sizeof(nbuf)); - isc_time_set(&t, n->expiry, 0); - isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); - fprintf(fp, "%s: %s %s\n", nbuf, - n->expiry <= now ? "expired" : "expiry", - tbuf); - } - result = dns_rbtnodechain_next(&chain, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; - break; - } - } - - cleanup: - dns_rbtnodechain_invalidate(&chain); - RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read); - return (result); -} -#endif - isc_result_t dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) { isc_result_t result; @@ -674,35 +632,41 @@ dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp) { for (;;) { dns_rbtnodechain_current(&chain, NULL, NULL, &node); if (node->data != NULL) { + isc_buffer_t b; + char nbuf[DNS_NAME_FORMATSIZE + 1], tbuf[80]; + dns_fixedname_t fn; + dns_name_t *name; dns_nta_t *n = (dns_nta_t *) node->data; - if (n->expiry > now) { - isc_buffer_t b; - char nbuf[DNS_NAME_FORMATSIZE + 1], tbuf[80]; - dns_fixedname_t fn; - dns_name_t *name; - name = dns_fixedname_initname(&fn); - dns_rbt_fullnamefromnode(node, name); - - isc_buffer_init(&b, nbuf, sizeof(nbuf)); - result = dns_name_totext(name, false, &b); - if (result != ISC_R_SUCCESS) - goto skip; - - /* Zero terminate. */ - isc_buffer_putuint8(&b, 0); - - isc_buffer_init(&b, tbuf, sizeof(tbuf)); - dns_time32_totext(n->expiry, &b); - - /* Zero terminate. */ - isc_buffer_putuint8(&b, 0); - - fprintf(fp, "%s %s %s\n", nbuf, - n->forced ? "forced" : "regular", - tbuf); - written = true; + /* + * Skip this node if the expiry is already in the + * past, or if this is a "validate-except" entry. + */ + if (n->expiry <= now || n->expiry == 0xffffffffU) { + goto skip; } + + name = dns_fixedname_initname(&fn); + dns_rbt_fullnamefromnode(node, name); + + isc_buffer_init(&b, nbuf, sizeof(nbuf)); + result = dns_name_totext(name, false, &b); + if (result != ISC_R_SUCCESS) + goto skip; + + /* Zero terminate. */ + isc_buffer_putuint8(&b, 0); + + isc_buffer_init(&b, tbuf, sizeof(tbuf)); + dns_time32_totext(n->expiry, &b); + + /* Zero terminate. */ + isc_buffer_putuint8(&b, 0); + + fprintf(fp, "%s %s %s\n", nbuf, + n->forced ? "forced" : "regular", + tbuf); + written = true; } skip: result = dns_rbtnodechain_next(&chain, NULL, NULL); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 0c026f8991..3f6336d898 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1155,7 +1155,7 @@ options_clauses[] = { static cfg_type_t cfg_type_namelist = { "namelist", cfg_parse_bracketed_list, cfg_print_bracketed_list, - cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_qstring + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring }; static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist }; @@ -1976,6 +1976,7 @@ view_clauses[] = { { "trust-anchor-telemetry", &cfg_type_boolean, CFG_CLAUSEFLAG_EXPERIMENTAL }, { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, + { "validate-except", &cfg_type_namelist, 0 }, { "v6-bias", &cfg_type_uint32, 0 }, { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 }, { NULL, NULL, 0 } From 7ecd699e815adcd0d5efdf778c3d0142ff980887 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Mon, 30 Apr 2018 17:43:52 -0700 Subject: [PATCH 2/3] add a system test --- bin/tests/system/dnssec/ns2/corp.db | 21 +++++++++++++++++++++ bin/tests/system/dnssec/ns2/named.conf.in | 5 +++++ bin/tests/system/dnssec/ns4/named1.conf.in | 7 +++++++ bin/tests/system/dnssec/tests.sh | 15 ++++++++++++++- util/copyrights | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 bin/tests/system/dnssec/ns2/corp.db diff --git a/bin/tests/system/dnssec/ns2/corp.db b/bin/tests/system/dnssec/ns2/corp.db new file mode 100644 index 0000000000..70c96299c2 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/corp.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +www A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns2/named.conf.in b/bin/tests/system/dnssec/ns2/named.conf.in index 329424dccf..4f05632818 100644 --- a/bin/tests/system/dnssec/ns2/named.conf.in +++ b/bin/tests/system/dnssec/ns2/named.conf.in @@ -158,4 +158,9 @@ zone "cdnskey-auto.secure" { allow-update { any; }; }; +zone "corp" { + type master; + file "corp.db"; +}; + include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns4/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in index 9f851b09c9..f74a4058ce 100644 --- a/bin/tests/system/dnssec/ns4/named1.conf.in +++ b/bin/tests/system/dnssec/ns4/named1.conf.in @@ -28,6 +28,8 @@ options { nta-lifetime 12s; nta-recheck 9s; + validate-except { corp; }; + # Note: We only reference the bind.keys file here to confirm that it # is *not* being used. It contains the real root key, and we're # using a local toy root zone for the tests, so it wouldn't work. @@ -50,4 +52,9 @@ zone "." { file "../../common/root.hint"; }; +zone "corp" { + type static-stub; + server-addresses { 10.53.0.2; }; +}; + include "trusted.conf"; diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index c87700e120..41d4643a11 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1764,6 +1764,15 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +echo_i "checking validate-except in an insecure local domain ($n)" +ret=0 +$DIG $DIGOPTS ns www.corp @10.53.0.4 > dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + echo_i "checking positive and negative validation with negative trust anchors ($n)" ret=0 @@ -2165,10 +2174,14 @@ fi echo_i "sleeping for an additional 4 seconds for ns4 to fully startup" sleep 4 -# dump the NTA to a file +# dump the NTA to a file (omit validate-except entries) +echo_i "testing 'rndc nta'" $RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null +# "corp" is configured as a validate-except domain and thus should be +# omitted. only "secure.example" should be in the dump at this point. lines=`wc -l < rndc.out.ns4.test$n.1` [ "$lines" -eq 1 ] || ret=1 +grep 'secure.example' rndc.out.ns4.test$n.1 > /dev/null || ret=1 ts=`awk '{print $3" "$4}' < rndc.out.ns4.test$n.1` # rndc nta outputs localtime, so append the timezone ts_with_zone="$ts `date +%z`" diff --git a/util/copyrights b/util/copyrights index 42f83b1a3a..149114649e 100644 --- a/util/copyrights +++ b/util/copyrights @@ -990,6 +990,7 @@ ./bin/tests/system/dnssec/ns2/cds.secure.db.in ZONE 2015,2016,2018 ./bin/tests/system/dnssec/ns2/child.nsec3.example.db ZONE 2006,2008,2016,2018 ./bin/tests/system/dnssec/ns2/child.optout.example.db ZONE 2006,2008,2016,2018 +./bin/tests/system/dnssec/ns2/corp.db ZONE 2018 ./bin/tests/system/dnssec/ns2/dlv.db.in ZONE 2004,2007,2016,2018 ./bin/tests/system/dnssec/ns2/dst.example.db.in ZONE 2004,2007,2016,2018 ./bin/tests/system/dnssec/ns2/example.db.in ZONE 2000,2001,2002,2004,2007,2008,2009,2010,2011,2012,2013,2014,2016,2018 From 4eb0897c909a7643b30bdc46c21ab354d5f66689 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Mon, 30 Apr 2018 18:17:35 -0700 Subject: [PATCH 3/3] CHANGES, release notes, README --- CHANGES | 4 ++++ README | 3 +++ README.md | 3 +++ doc/arm/notes.xml | 8 ++++++++ 4 files changed, 18 insertions(+) diff --git a/CHANGES b/CHANGES index 6956376258..f032524123 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +5010. [func] New "validate-except" option specifies a list of + domains beneath which DNSSEC validation should not + be performed. [GL #237] + 5009. [bug] Upon an OpenSSL failure, the first error in the OpenSSL error queue was not logged. [GL #476] diff --git a/README b/README index c9f5421264..ba5f29d9f1 100644 --- a/README +++ b/README @@ -114,6 +114,9 @@ of changes from BIND 9.12 and earlier releases. New features include: subject to DNSSEC validation and are not treated as authoritative data when answering. This makes it easier to configure a local copy of the root zone as described in RFC 7706. + * QNAME minimization is now supported + * The "validate-except" option allows configuration of domains below + which DNSSEC validation should not be performed. In addition, cryptographic support has been modernized. BIND now uses the best available pseudo-random number generator for the platform on which diff --git a/README.md b/README.md index b283ff98c8..e06941f40d 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,9 @@ include: DNSSEC validation and are not treated as authoritative data when answering. This makes it easier to configure a local copy of the root zone as described in RFC 7706. +* QNAME minimization is now supported +* The "validate-except" option allows configuration of domains below which + DNSSEC validation should not be performed. In addition, cryptographic support has been modernized. BIND now uses the best available pseudo-random number generator for the platform on which diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index 8a1f647af5..de2760cbe5 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -143,6 +143,14 @@ loss of security. + + + The validate-except option specifies a list of + domains beneath which DNSSEC validation should not be performed, + regardless of whether a trust anchor has been configured above + them. [GL #237] + +