Merge branch 'backport-sentinel' into 'v9_11'

Backport root-key-sentinel

See merge request isc-projects/bind9!334
This commit is contained in:
Mark Andrews 2018-06-04 21:57:16 -04:00
commit 0a613754e4
28 changed files with 853 additions and 5 deletions

View file

@ -31,6 +31,9 @@
4930. [bug] Remove a bogus check in nslookup command line
argument processing. [GL #206]
4926. [func] Add root key sentinel support. To disable, add
'root-key-sentinel no;' to named.conf. [GL #37]
4922. [bug] dnstap: Log the destination address of client
packets rather than the interface address.
[GL #197]

View file

@ -193,6 +193,7 @@ options {\n\
request-ixfr true;\n\
require-server-cookie no;\n\
# rfc2308-type1 <obsolete>;\n\
root-key-sentinel yes;\n\
servfail-ttl 1;\n\
# sortlist <none>\n\
# topology <none>\n\

View file

@ -74,7 +74,9 @@ struct ns_query {
isc_boolean_t authoritative;
isc_boolean_t is_zone;
} redirect;
dns_keytag_t root_key_sentinel_keyid;
isc_boolean_t root_key_sentinel_is_ta;
isc_boolean_t root_key_sentinel_not_ta;
};
#define NS_QUERYATTR_RECURSIONOK 0x0001

View file

@ -33,6 +33,7 @@
#include <dns/dns64.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/keytable.h>
#include <dns/message.h>
#include <dns/ncache.h>
#include <dns/nsec3.h>
@ -467,6 +468,9 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
client->query.isreferral = ISC_FALSE;
client->query.dns64_options = 0;
client->query.dns64_ttl = ISC_UINT32_MAX;
client->query.root_key_sentinel_keyid = 0;
client->query.root_key_sentinel_is_ta = ISC_FALSE;
client->query.root_key_sentinel_not_ta = ISC_FALSE;
}
static void
@ -3015,7 +3019,6 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
return (eresult);
}
static isc_result_t
query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
dns_trust_t trust, dns_ttl_t ttl)
@ -3091,6 +3094,58 @@ query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
return (ISC_R_SUCCESS);
}
static isc_boolean_t
get_root_key_sentinel_id(ns_client_t *client, const char *ndata) {
unsigned int v = 0;
int i;
for (i = 0; i < 5; i++) {
if (ndata[i] < '0' || ndata[i] > '9') {
return (ISC_FALSE);
}
v *= 10;
v += ndata[i] - '0';
}
if (v > 65535U) {
return (ISC_FALSE);
}
client->query.root_key_sentinel_keyid = v;
return (ISC_TRUE);
}
/*%
* Find out if the query is for a root key sentinel and if so, record the type
* of root key sentinel query and the key id that is being checked for.
*
* The code is assuming a zero padded decimal field of width 5.
*/
static void
root_key_sentinel_detect(ns_client_t *client) {
const char *ndata = (const char *)client->query.qname->ndata;
if (client->query.qname->length > 30 && ndata[0] == 29 &&
strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0)
{
if (!get_root_key_sentinel_id(client, ndata + 25)) {
return;
}
client->query.root_key_sentinel_is_ta = ISC_TRUE;
ns_client_log(client, NS_LOGCATEGORY_TAT,
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
"root-key-sentinel-is-ta query label found");
} else if (client->query.qname->length > 31 && ndata[0] == 30 &&
strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0)
{
if (!get_root_key_sentinel_id(client, ndata + 26)) {
return;
}
client->query.root_key_sentinel_not_ta = ISC_TRUE;
ns_client_log(client, NS_LOGCATEGORY_TAT,
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
"root-key-sentinel-not-ta query label found");
}
}
/*
* Mark the RRsets as secure. Update the cache (db) to reflect the
* change in trust level.
@ -3940,6 +3995,92 @@ free_devent(ns_client_t *client, isc_event_t **eventp,
isc_event_free(eventp);
}
/*%
* Check the configured trust anchors for a root zone trust anchor
* with a key id that matches client->query.root_key_sentinel_keyid.
*
* Return ISC_TRUE when found, otherwise return ISC_FALSE.
*/
static isc_boolean_t
has_ta(ns_client_t *client) {
dns_keytable_t *keytable = NULL;
dns_keynode_t *keynode = NULL;
isc_result_t result;
result = dns_view_getsecroots(client->view, &keytable);
if (result != ISC_R_SUCCESS) {
return (ISC_FALSE);
}
result = dns_keytable_find(keytable, dns_rootname, &keynode);
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dns_keytag_t keyid = dst_key_id(dns_keynode_key(keynode));
if (keyid == client->query.root_key_sentinel_keyid) {
dns_keytable_detachkeynode(keytable, &keynode);
dns_keytable_detach(&keytable);
return (ISC_TRUE);
}
result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
dns_keytable_detachkeynode(keytable, &keynode);
keynode = nextnode;
}
dns_keytable_detach(&keytable);
return (ISC_FALSE);
}
/*%
* Check if a root key sentinel SERVFAIL should be returned.
*/
static isc_boolean_t
root_key_sentinel_return_servfail(ns_client_t *client, isc_boolean_t is_zone,
dns_rdataset_t *rdataset, isc_result_t result)
{
/*
* Are we looking at a "root-key-sentinel" query?
*/
if (!client->query.root_key_sentinel_is_ta &&
!client->query.root_key_sentinel_not_ta)
{
return (ISC_FALSE);
}
/*
* We only care about the query if 'result' indicates we have a cached
* answer.
*/
switch (result) {
case ISC_R_SUCCESS:
case DNS_R_CNAME:
case DNS_R_DNAME:
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
break;
default:
return (ISC_FALSE);
}
/*
* Do we meet the specified conditions to return SERVFAIL?
*/
if (!is_zone && rdataset->trust == dns_trust_secure &&
((client->query.root_key_sentinel_is_ta && !has_ta(client)) ||
(client->query.root_key_sentinel_not_ta && has_ta(client))))
{
return (ISC_TRUE);
}
/*
* As special processing may only be triggered by the original QNAME,
* disable it after following a CNAME/DNAME.
*/
client->query.root_key_sentinel_is_ta = ISC_FALSE;
client->query.root_key_sentinel_not_ta = ISC_FALSE;
return (ISC_FALSE);
}
static void
query_resume(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
@ -6936,6 +7077,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
goto cleanup;
}
/*
* Setup for root key sentinel processing.
*/
if (client->view->root_key_sentinel &&
client->query.restarts == 0 &&
(qtype == dns_rdatatype_a ||
qtype == dns_rdatatype_aaaa) &&
(client->message->flags & DNS_MESSAGEFLAG_CD) == 0)
{
root_key_sentinel_detect(client);
}
/*
* First we must find the right database.
*/
@ -7393,6 +7546,21 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
norpz:
/*
* If required, handle special "root-key-sentinel-is-ta-<keyid>" and
* "root-key-sentinel-not-ta-<keyid>" labels by returning SERVFAIL.
*/
if (root_key_sentinel_return_servfail(client, is_zone,
rdataset, result))
{
/*
* Don't record this response in the SERVFAIL cache.
*/
client->attributes |= NS_CLIENTATTR_NOSETFC;
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
switch (result) {
case ISC_R_SUCCESS:
/*
@ -9404,7 +9572,7 @@ ns_query_start(ns_client_t *client) {
client->query.attributes &= ~NS_QUERYATTR_SECURE;
/*
* Set NS_CLIENTATTR_WANTDNSSEC if the client has set AD in the query.
* Set NS_CLIENTATTR_WANTAD if the client has set AD in the query.
* This allows AD to be returned on queries without DO set.
*/
if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)

View file

@ -4255,6 +4255,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
INSIST(result == ISC_R_SUCCESS);
view->trust_anchor_telemetry = cfg_obj_asboolean(obj);
obj = NULL;
result = ns_config_get(maps, "root-key-sentinel", &obj);
INSIST(result == ISC_R_SUCCESS);
view->root_key_sentinel = cfg_obj_asboolean(obj);
CHECK(configure_view_acl(vconfig, config, ns_g_config,
"allow-query-cache-on", NULL, actx,
ns_g_mctx, &view->cacheonacl));

View file

@ -65,7 +65,7 @@ PARALLEL = rpzrecurse dnssec \
masterfile masterformat metadata mkeys \
names notify nslookup nsupdate nzd2nzf \
pending pipelined \
reclimit redirect resolver rndc rpz \
reclimit redirect resolver rndc rootkeysentinel rpz \
rrchecker rrl rrsetorder rsabigexponent runtime \
sfcache smartsign sortlist \
spf staticstub statistics statschannel stub \

View file

@ -100,7 +100,7 @@ PARALLELDIRS="acl additional addzone allow-query autosign \
masterfile masterformat metadata mkeys \
names notify nslookup nsupdate nzd2nzf \
pending pipelined \
reclimit redirect resolver rndc rpz rpzrecurse \
reclimit redirect resolver rndc rootkeysentinel rpz rpzrecurse \
rrchecker rrl rrsetorder rsabigexponent runtime \
sfcache smartsign sortlist \
spf staticstub statistics statschannel stub \
@ -233,6 +233,12 @@ echo_i() {
done
}
echo_ic() {
echo "$@" | while read LINE ; do
echoinfo "I:$SYSTESTDIR: $LINE"
done
}
cat_i() {
while read LINE ; do
echoinfo "I:$SYSTESTDIR:$LINE"

View file

@ -0,0 +1,23 @@
#!/bin/sh
#
# 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.
rm -f dig.out.ns?.test*
rm -f */dsset-*
rm -f */named.conf
rm -f */named.memstats
rm -f */named.run
rm -f */trusted.conf
rm -f ns1/K.*
rm -f ns1/root.db
rm -f ns1/root.db.signed
rm -f ns2/Kexample.*
rm -f ns2/example.db
rm -f ns2/example.db.signed

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
dnssec-enable yes;
dnssec-validation yes;
};
zone "." {
type master;
file "root.db.signed";
};
include "trusted.conf";

View file

@ -0,0 +1,22 @@
; 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 300
. IN SOA marka.isc.org. a.root.servers.nil. (
2018031400 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
example. NS ns2.example.
ns2.example. A 10.53.0.2

View file

@ -0,0 +1,43 @@
#!/bin/sh -e
#
# 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.
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
zone=.
infile=root.db.in
zonefile=root.db
keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
keyid=`expr ${keyname} : 'K.+008+\(.*\)'`
(cd ../ns2 && $SHELL sign.sh ${keyid:-00000} )
cp ../ns2/dsset-example$TP .
cat $infile $keyname.key > $zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
# Configure the resolving server with a trusted key.
cat $keyname.key | grep -v '^; ' | $PERL -n -e '
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
local $key = join("", @rest);
print <<EOF
trusted-keys {
"$dn" $flags $proto $alg "$key";
};
EOF
' > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf

View file

@ -0,0 +1,19 @@
; 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 300 ; 5 minutes
@ IN SOA mname1. . (
2018031400 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
recursion no;
notify yes;
dnssec-enable yes;
dnssec-validation yes;
};
zone "example" {
type master;
file "example.db.signed";
};
include "trusted.conf";

View file

@ -0,0 +1,40 @@
#!/bin/sh -e
#
# 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.
oldid=${1:-00000}
newid=`expr \( ${oldid} + 1000 \) % 65536`
newid=`expr "0000${newid}" : '.*\(.....\)$'`
badid=`expr \( ${oldid} + 7777 \) % 65536`
badid=`expr "0000${badid}" : '.*\(.....\)$'`
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
zone=example.
infile=example.db.in
zonefile=example.db
keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone`
cat $infile $keyname1.key $keyname2.key >$zonefile
echo root-key-sentinel-is-ta-$oldid A 10.53.0.1 >> $zonefile
echo root-key-sentinel-not-ta-$oldid A 10.53.0.2 >> $zonefile
echo root-key-sentinel-is-ta-$newid A 10.53.0.3 >> $zonefile
echo root-key-sentinel-not-ta-$newid A 10.53.0.4 >> $zonefile
echo old-is-ta CNAME root-key-sentinel-is-ta-$oldid >> $zonefile
echo old-not-ta CNAME root-key-sentinel-not-ta-$oldid >> $zonefile
echo new-is-ta CNAME root-key-sentinel-is-ta-$newid >> $zonefile
echo new-not-ta CNAME root-key-sentinel-not-ta-$newid >> $zonefile
echo bad-is-ta CNAME root-key-sentinel-is-ta-$badid >> $zonefile
echo bad-not-ta CNAME root-key-sentinel-not-ta-$badid >> $zonefile
$SIGNER -P -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null

View file

@ -0,0 +1,11 @@
; 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.
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1

View file

@ -0,0 +1,32 @@
/*
* 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.
*/
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
dnssec-enable yes;
dnssec-validation yes;
root-key-sentinel yes;
};
zone "." {
type hint;
file "hint.db";
};
include "trusted.conf";

View file

@ -0,0 +1,11 @@
; 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.
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1

View file

@ -0,0 +1,32 @@
/*
* 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.
*/
options {
query-source address 10.53.0.4;
notify-source 10.53.0.4;
transfer-source 10.53.0.4;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
recursion yes;
notify yes;
dnssec-enable yes;
dnssec-validation yes;
root-key-sentinel no;
};
zone "." {
type hint;
file "hint.db";
};
include "trusted.conf";

View file

@ -0,0 +1,15 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
exec $SHELL ../testcrypto.sh

View file

@ -0,0 +1,25 @@
#!/bin/sh -e
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
$SHELL clean.sh
test -r $RANDFILE || $GENRANDOM 800 $RANDFILE
copy_setports ns1/named.conf.in ns1/named.conf
copy_setports ns2/named.conf.in ns2/named.conf
copy_setports ns3/named.conf.in ns3/named.conf
copy_setports ns4/named.conf.in ns4/named.conf
cd ns1
$SHELL sign.sh

View file

@ -0,0 +1,286 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
status=0
n=0
rm -f dig.out.*
DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}"
newtest() {
n=`expr $n + 1`
case $# in
1)
echo_i "$1 ($n)"
;;
2)
echo_i "$1"
echo_ic "$2 ($n)"
;;
esac
ret=0
}
newtest "get test ids"
$DIG $DIGOPTS . dnskey +short +rrcomm @10.53.0.1 > dig.out.ns1.test$n || ret=1
oldid=`sed -n 's/.*key id = //p' < dig.out.ns1.test$n`
oldid=`expr "0000${oldid}" : '.*\(.....\)$'`
newid=`expr \( ${oldid} + 1000 \) % 65536`
newid=`expr "0000${newid}" : '.*\(.....\)$'`
badid=`expr \( ${oldid} + 7777 \) % 65536`
badid=`expr "0000${badid}" : '.*\(.....\)$'`
echo_i "test id: oldid=${oldid} (configured)"
echo_i "test id: newid=${newid} (not configured)"
echo_i "test id: badid=${badid}"
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check authoritative server (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.2 example SOA > dig.out.ns2.test$n
grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check test zone resolves with 'root-key-sentinel yes;'" " (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 example SOA > dig.out.ns3.test$n
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with old ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with new ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${newid}.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${badid}.example A > dig.out.ns3.test$n || ret=1
grep "status: SERVFAIL" dig.out.ns3.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with bad ta, CD=1 and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${badid}.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${bad}.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-72345.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-72345.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-1234.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-1234.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 old-is-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 old-not-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 new-is-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.3 new-not-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 bad-is-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.3 bad-not-ta.example A > dig.out.ns3.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check test zone resolves with 'root-key-sentinel no;'" " (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 example SOA > dig.out.ns4.test$n
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${oldid}.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${oldid}.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${newid}.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${newid}.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${badid}.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${bad}.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-72345.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-72345.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-1234.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-1234.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 old-is-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 old-not-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 new-is-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)"
$DIG $DIGOPTS @10.53.0.4 new-not-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 bad-is-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)"
$DIG $DIGOPTS @10.53.0.4 bad-not-ta.example A > dig.out.ns4.test$n || ret=1
grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View file

@ -5952,6 +5952,17 @@ options {
</listitem>
</varlistentry>
<varlistentry>
<term><command>root-key-sentinel</command></term>
<listitem>
<para>
Respond to root key sentinel probes as described in
draft-ietf-dnsop-kskroll-sentinel-08. The default is
<userinput>yes</userinput>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>maintain-ixfr-base</command></term>
<listitem>

View file

@ -119,6 +119,18 @@
</itemizedlist>
</section>
<section xml:id="relnotes_features"><info><title>New Features</title></info>
<itemizedlist>
<listitem>
<para>
Add root key sentinel support which enables resolvers to test
which trust anchors are configured for the root. To disable, add
'root-key-sentinel no;' to named.conf. [GL #37]
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="relnotes_removed"><info><title>Removed Features</title></info>
<itemizedlist>
<listitem>

View file

@ -307,6 +307,7 @@ options {
qname-wait-recurse <boolean> ] [ recursive-only <boolean> ];
rfc2308-type1 <boolean>; // not yet implemented
root-delegation-only [ exclude { <quoted_string>; ... } ];
root-key-sentinel <boolean>;
rrset-order { [ class <string> ] [ type <string> ] [ name
<quoted_string> ] <string> <string>; ... };
secroots-file <quoted_string>;
@ -607,6 +608,7 @@ view <string> [ <class> ] {
min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [
qname-wait-recurse <boolean> ] [ recursive-only <boolean> ];
rfc2308-type1 <boolean>; // not yet implemented
root-key-sentinel <boolean>;
root-delegation-only [ exclude { <quoted_string>; ... } ];
rrset-order { [ class <string> ] [ type <string> ] [ name
<quoted_string> ] <string> <string>; ... };

View file

@ -126,6 +126,7 @@ struct dns_view {
isc_boolean_t acceptexpired;
isc_boolean_t requireservercookie;
isc_boolean_t trust_anchor_telemetry;
isc_boolean_t root_key_sentinel;
dns_transfer_format_t transfer_format;
dns_acl_t * cacheacl;
dns_acl_t * cacheonacl;

View file

@ -239,6 +239,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->sendcookie = ISC_TRUE;
view->requireservercookie = ISC_FALSE;
view->trust_anchor_telemetry = ISC_TRUE;
view->root_key_sentinel = ISC_TRUE;
view->new_zone_file = NULL;
view->new_zone_db = NULL;
view->new_zone_dbenv = NULL;

View file

@ -1806,6 +1806,7 @@ view_clauses[] = {
{ "response-policy", &cfg_type_rpz, 0 },
{ "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "root-delegation-only", &cfg_type_optional_exclude, 0 },
{ "root-key-sentinel", &cfg_type_boolean, 0 },
{ "rrset-order", &cfg_type_rrsetorder, 0 },
{ "send-cookie", &cfg_type_boolean, 0 },
{ "servfail-ttl", &cfg_type_ttlval, 0 },

View file

@ -1877,6 +1877,20 @@
./bin/tests/system/rndc/ns6/named.conf.in CONF-C 2016,2018
./bin/tests/system/rndc/setup.sh SH 2011,2012,2013,2014,2016,2018
./bin/tests/system/rndc/tests.sh SH 2011,2012,2013,2014,2015,2016,2017,2018
./bin/tests/system/rootkeysentinel/clean.sh SH 2018
./bin/tests/system/rootkeysentinel/ns1/named.conf.in CONF-C 2018
./bin/tests/system/rootkeysentinel/ns1/root.db.in ZONE 2018
./bin/tests/system/rootkeysentinel/ns1/sign.sh SH 2018
./bin/tests/system/rootkeysentinel/ns2/example.db.in ZONE 2018
./bin/tests/system/rootkeysentinel/ns2/named.conf.in CONF-C 2018
./bin/tests/system/rootkeysentinel/ns2/sign.sh SH 2018
./bin/tests/system/rootkeysentinel/ns3/hint.db ZONE 2018
./bin/tests/system/rootkeysentinel/ns3/named.conf.in CONF-C 2018
./bin/tests/system/rootkeysentinel/ns4/hint.db ZONE 2018
./bin/tests/system/rootkeysentinel/ns4/named.conf.in CONF-C 2018
./bin/tests/system/rootkeysentinel/prereq.sh SH 2018
./bin/tests/system/rootkeysentinel/setup.sh SH 2018
./bin/tests/system/rootkeysentinel/tests.sh SH 2018
./bin/tests/system/rpz/clean.sh SH 2011,2012,2013,2014,2016,2018
./bin/tests/system/rpz/ns1/named.conf.in CONF-C 2018
./bin/tests/system/rpz/ns1/root.db ZONE 2011,2012,2013,2016,2018