mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 10:10:06 +00:00
[master] complete NTA work
3882. [func] By default, negative trust anchors will be tested periodically to see whether data below them can be validated, and if so, they will be allowed to expire early. The "rndc nta -force" option overrides this behvaior. The default NTA lifetime and the recheck frequency can be configured by the "nta-lifetime" and "nta-recheck" options. [RT #36146]
This commit is contained in:
parent
8eb2d262dc
commit
b8a9632333
8
CHANGES
8
CHANGES
@ -1,3 +1,11 @@
|
||||
3882. [func] By default, negative trust anchors will be tested
|
||||
periodically to see whether data below them can be
|
||||
validated, and if so, they will be allowed to
|
||||
expire early. The "rndc nta -force" option
|
||||
overrides this behvaior. The default NTA lifetime
|
||||
and the recheck frequency can be configured by the
|
||||
"nta-lifetime" and "nta-recheck" options. [RT #36146]
|
||||
|
||||
3881. [bug] Address memory leak with UPDATE error handling.
|
||||
[RT #36303]
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
static char defaultconf[] = "\
|
||||
options {\n\
|
||||
automatic-interface-scan yes;\n\
|
||||
bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
|
||||
# blackhole {none;};\n"
|
||||
#ifndef WIN32
|
||||
" coresize default;\n\
|
||||
@ -78,8 +79,9 @@ options {\n\
|
||||
memstatistics-file \"named.memstats\";\n\
|
||||
multiple-cnames no;\n\
|
||||
# named-xfer <obsolete>;\n\
|
||||
nta-lifetime 3600;\n\
|
||||
nta-recheck 300;\n\
|
||||
# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
|
||||
bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
|
||||
port 53;\n\
|
||||
prefetch 2 9;\n\
|
||||
recursing-file \"named.recursing\";\n\
|
||||
|
@ -15,8 +15,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
@ -826,7 +826,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
|
||||
result = dns_view_initntatable(view, mctx);
|
||||
result = dns_view_initntatable(view, ns_g_taskmgr, ns_g_timermgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
@ -3566,6 +3566,16 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
||||
if (result == ISC_R_SUCCESS)
|
||||
CHECK(mustbesecure(obj, view->resolver));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "nta-recheck", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
view->nta_recheck = cfg_obj_asuint32(obj);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "nta-lifetime", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
view->nta_lifetime = cfg_obj_asuint32(obj);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "preferred-glue", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
@ -3626,6 +3636,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
||||
} else {
|
||||
empty_zones_enable = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (empty_zones_enable && !lwresd_g_useresolvconf) {
|
||||
const char *empty;
|
||||
int empty_zone = 0;
|
||||
@ -7768,6 +7779,7 @@ isc_result_t
|
||||
ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
||||
dns_view_t *view;
|
||||
dns_keytable_t *secroots = NULL;
|
||||
dns_ntatable_t *ntatable = NULL;
|
||||
isc_result_t result;
|
||||
char *ptr;
|
||||
FILE *fp = NULL;
|
||||
@ -7801,11 +7813,25 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
||||
result = ISC_R_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
fprintf(fp, "\n Start view %s\n\n", view->name);
|
||||
fprintf(fp, "\n Start view %s\n", view->name);
|
||||
fprintf(fp, " Secure roots:\n\n");
|
||||
result = dns_keytable_dump(secroots, fp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fprintf(fp, " dumpsecroots failed: %s\n",
|
||||
isc_result_totext(result));
|
||||
|
||||
if (ntatable != NULL)
|
||||
dns_ntatable_detach(&ntatable);
|
||||
result = dns_view_getntatable(view, &ntatable);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
result = ISC_R_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
fprintf(fp, "\n Negative trust anchors:\n\n");
|
||||
result = dns_ntatable_dump(ntatable, fp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fprintf(fp, " dumpntatable failed: %s\n",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
if (ptr != NULL)
|
||||
ptr = next_token(&args, " \t");
|
||||
@ -7814,6 +7840,8 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
||||
cleanup:
|
||||
if (secroots != NULL)
|
||||
dns_keytable_detach(&secroots);
|
||||
if (ntatable != NULL)
|
||||
dns_ntatable_detach(&ntatable);
|
||||
if (fp != NULL)
|
||||
(void)isc_stdio_close(fp);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
@ -9772,15 +9800,18 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
||||
dns_view_t *view;
|
||||
dns_ntatable_t *ntatable = NULL;
|
||||
isc_result_t result;
|
||||
char *ptr, *nametext, *viewname;
|
||||
char *ptr, *nametext = NULL, *viewname;
|
||||
isc_stdtime_t now, when;
|
||||
isc_time_t t;
|
||||
char tbuf[64];
|
||||
const char *msg = NULL;
|
||||
isc_boolean_t dump = ISC_FALSE, force = ISC_FALSE;
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *ntaname;
|
||||
dns_ttl_t ntattl;
|
||||
isc_textregion_t tr;
|
||||
isc_boolean_t ttlset = ISC_FALSE;
|
||||
|
||||
UNUSED(force);
|
||||
|
||||
dns_fixedname_init(&fn);
|
||||
ntaname = dns_fixedname_name(&fn);
|
||||
@ -9790,8 +9821,78 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
||||
if (ptr == NULL)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
|
||||
for (;;) {
|
||||
size_t len;
|
||||
|
||||
/* Check for options */
|
||||
ptr = next_token(&args, " \t");
|
||||
if (ptr == NULL)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
|
||||
len = strlen(ptr);
|
||||
|
||||
if (strncasecmp(ptr, "-dump", len) == 0)
|
||||
dump = ISC_TRUE;
|
||||
else if (strncasecmp(ptr, "-remove", len) == 0) {
|
||||
ntattl = 0;
|
||||
ttlset = ISC_TRUE;
|
||||
} else if (strncasecmp(ptr, "-force", len) == 0) {
|
||||
force = ISC_TRUE;
|
||||
continue;
|
||||
} else if (strncasecmp(ptr, "-lifetime", len) == 0) {
|
||||
isc_textregion_t tr;
|
||||
|
||||
ptr = next_token(&args, " \t");
|
||||
if (ptr == NULL) {
|
||||
msg = "No lifetime specified";
|
||||
CHECK(ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
|
||||
tr.base = ptr;
|
||||
tr.length = strlen(ptr);
|
||||
result = dns_ttl_fromtext(&tr, &ntattl);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
msg = "could not parse NTA lifetime";
|
||||
CHECK(result);
|
||||
}
|
||||
|
||||
if (ntattl > 86400) {
|
||||
msg = "NTA lifetime cannot exceed one day";
|
||||
CHECK(ISC_R_RANGE);
|
||||
}
|
||||
|
||||
ttlset = ISC_TRUE;
|
||||
continue;
|
||||
} else
|
||||
nametext = ptr;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If -dump was specified, list NTA's and return
|
||||
*/
|
||||
if (dump) {
|
||||
for (view = ISC_LIST_HEAD(server->viewlist);
|
||||
view != NULL;
|
||||
view = ISC_LIST_NEXT(view, link))
|
||||
{
|
||||
if (ntatable != NULL)
|
||||
dns_ntatable_detach(&ntatable);
|
||||
result = dns_view_getntatable(view, &ntatable);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
result = ISC_R_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
CHECK(dns_ntatable_totext(ntatable, text));
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Get the NTA name. */
|
||||
nametext = next_token(&args, " \t");
|
||||
if (nametext == NULL)
|
||||
nametext = next_token(&args, " \t");
|
||||
if (nametext == NULL)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
|
||||
@ -9804,26 +9905,10 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
||||
CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, 0, NULL));
|
||||
}
|
||||
|
||||
/* Get the NTA duration. */
|
||||
ptr = next_token(&args, " \t");
|
||||
if (ptr == NULL)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
|
||||
tr.base = ptr;
|
||||
tr.length = strlen(ptr);
|
||||
CHECK(dns_ttl_fromtext(&tr, &ntattl));
|
||||
|
||||
if (ntattl > 86400) {
|
||||
msg = "NTA cannot exceed one day";
|
||||
CHECK(ISC_R_RANGE);
|
||||
}
|
||||
|
||||
/* Look for the view name. */
|
||||
viewname = next_token(&args, " \t");
|
||||
|
||||
/* Set up the NTA */
|
||||
isc_stdtime_get(&now);
|
||||
when = now + ntattl;
|
||||
|
||||
result = isc_task_beginexclusive(server->task);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
@ -9835,6 +9920,12 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
||||
strcmp(view->name, viewname) != 0)
|
||||
continue;
|
||||
|
||||
if (view->nta_lifetime == 0 || view->nta_recheck == 0)
|
||||
continue;
|
||||
|
||||
if (!ttlset)
|
||||
ntattl = view->nta_lifetime;
|
||||
|
||||
if (ntatable != NULL)
|
||||
dns_ntatable_detach(&ntatable);
|
||||
|
||||
@ -9851,11 +9942,13 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
||||
nametext, view->name,
|
||||
isc_result_totext(result));
|
||||
|
||||
isc_time_set(&t, when, 0);
|
||||
isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
|
||||
if (ntattl != 0) {
|
||||
CHECK(dns_ntatable_add(ntatable, ntaname,
|
||||
force, now, ntattl));
|
||||
|
||||
if (ntattl > 0) {
|
||||
CHECK(dns_ntatable_add(ntatable, ntaname, when));
|
||||
when = now + ntattl;
|
||||
isc_time_set(&t, when, 0);
|
||||
isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
|
||||
|
||||
CHECK(putstr(text, "Negative trust anchor added: "));
|
||||
CHECK(putstr(text, nametext));
|
||||
|
@ -463,10 +463,9 @@
|
||||
<term><userinput>secroots <optional><replaceable>view ...</replaceable></optional></userinput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Dump the server's security roots to the secroots
|
||||
file for the specified views. If no view is
|
||||
specified, security roots for all
|
||||
views are dumped.
|
||||
Dump the server's security roots and negative trust anchors
|
||||
to the secroots file for the specified views. If no view is
|
||||
specified, all views are dumped.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -597,12 +596,19 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><userinput>nta <replaceable>domain</replaceable> <replaceable>duration</replaceable> </userinput></term>
|
||||
<term><userinput>nta
|
||||
<optional>( -d | -f | -r | -l <replaceable>duration</replaceable>)</optional>
|
||||
<replaceable>domain</replaceable>
|
||||
<optional><replaceable>view</replaceable></optional>
|
||||
</userinput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets a DNSSEC negative trust anchor (NTA)
|
||||
for <option>domain</option>, with a lifetime of
|
||||
<option>duration</option> (up to a limit of one day).
|
||||
<option>lifetime</option>. The default lifetime is
|
||||
configured in <file>named.conf</file> via the
|
||||
<option>nta-lifetime</option>, and defaults to
|
||||
one hour. The lifetime cannot exceed one day.
|
||||
</para>
|
||||
<para>
|
||||
A negative trust anchor selectively disables
|
||||
@ -617,13 +623,40 @@
|
||||
restarted (NTA's do not persist across restarts).
|
||||
</para>
|
||||
<para>
|
||||
TTL-style suffixes can be used to specify
|
||||
<option>duration</option> in seconds, minutes, or hours.
|
||||
An existing NTA can be removed by using the
|
||||
<option>-remove</option> option.
|
||||
</para>
|
||||
<para>
|
||||
If the specified domain already has an NTA, its duration
|
||||
will be updated to the new value. Setting
|
||||
<option>duration</option> to zero will delete the NTA.
|
||||
An NTA's lifetime can be specified with the
|
||||
<option>-lifetime</option> option. TTL-style
|
||||
suffixes can be used to specify the lifetime in
|
||||
seconds, minutes, or hours. If the specified NTA
|
||||
already exists, its lifetime will be updated to the
|
||||
new value. Setting <option>lifetime</option> to zero
|
||||
is equivalent to <option>-remove</option>.
|
||||
</para>
|
||||
<para>
|
||||
If <option>-dump</option> is used, any other arguments
|
||||
are ignored, and a list of existing NTAs is printed
|
||||
(note that this may include NTAs that are expired but
|
||||
have not yet been cleaned up).
|
||||
</para>
|
||||
<para>
|
||||
Normally, <command>named</command> will periodically
|
||||
test to see whether data below an NTA can now be
|
||||
validated (see the <option>nta-recheck</option> option
|
||||
in the Administrator Reference Manual for details).
|
||||
If data can be validated, then the NTA is regarded as
|
||||
no longer necessary, and will be allowed to expire
|
||||
early. The <option>-force</option> overrides this
|
||||
behavior and forces an NTA to persist for its entire
|
||||
lifetime, regardless of whether data could be
|
||||
validated if the NTA were not present.
|
||||
</para>
|
||||
<para>
|
||||
All of these options can be shortened, i.e., to
|
||||
<option>-l</option>, <option>-r</option>, <option>-d</option>,
|
||||
and <option>-f</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -51,7 +51,7 @@ linecount=`grep "\./RSAMD5/.* ; managed" ns2/named.secroots | wc -l`
|
||||
linecount=`grep "dlv.isc.org/RSAMD5/.* ; managed" ns2/named.secroots | wc -l`
|
||||
[ "$linecount" -eq 2 ] || ret=1
|
||||
linecount=`cat ns2/named.secroots | wc -l`
|
||||
[ "$linecount" -eq 13 ] || ret=1
|
||||
[ "$linecount" -eq 28 ] || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
@ -65,6 +65,10 @@ ns.insecure A 10.53.0.3
|
||||
bogus NS ns.bogus
|
||||
ns.bogus A 10.53.0.3
|
||||
|
||||
; A subdomain with a corrupt DS
|
||||
badds NS ns.badds
|
||||
ns.badds A 10.53.0.3
|
||||
|
||||
; A dynamic secure subdomain
|
||||
dynamic NS dynamic
|
||||
dynamic A 10.53.0.3
|
||||
|
@ -26,11 +26,10 @@ zonefile=example.db
|
||||
|
||||
( cd ../ns3 && $SHELL sign.sh )
|
||||
|
||||
for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown \
|
||||
optout-unknown multiple rsasha256 rsasha512 kskonly update-nsec3 \
|
||||
auto-nsec auto-nsec3 secure.below-cname ttlpatch split-dnssec \
|
||||
split-smart expired expiring upper lower
|
||||
|
||||
for subdomain in secure badds bogus dynamic keyless nsec3 optout \
|
||||
nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \
|
||||
kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \
|
||||
ttlpatch split-dnssec split-smart expired expiring upper lower
|
||||
do
|
||||
cp ../ns3/dsset-$subdomain.example. .
|
||||
done
|
||||
|
@ -28,5 +28,6 @@ ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
c A 10.0.0.3
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
|
@ -68,6 +68,12 @@ zone "bogus.example" {
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
zone "badds.example" {
|
||||
type master;
|
||||
file "badds.example.db.signed";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
zone "dynamic.example" {
|
||||
type master;
|
||||
file "dynamic.example.db.signed";
|
||||
|
@ -26,7 +26,11 @@ ns3 A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
c A 10.0.0.3
|
||||
d A 10.0.0.4
|
||||
e A 10.0.0.5
|
||||
f A 10.0.0.6
|
||||
g A 10.0.0.7
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
|
@ -459,3 +459,18 @@ zonefile=siginterval.example.db
|
||||
kskname=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
|
||||
zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
|
||||
cp $infile $zonefile
|
||||
|
||||
#
|
||||
# A zone with a bad DS in the parent
|
||||
# (sourced from bogus.example.db.in)
|
||||
#
|
||||
zone=badds.example.
|
||||
infile=bogus.example.db.in
|
||||
zonefile=badds.example.db
|
||||
|
||||
keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
|
||||
|
||||
cat $infile $keyname.key >$zonefile
|
||||
|
||||
$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
|
||||
sed -e 's/bogus/badds/g' < dsset-bogus.example. > dsset-badds.example.
|
||||
|
@ -34,6 +34,9 @@ options {
|
||||
dnssec-validation yes;
|
||||
dnssec-must-be-secure mustbesecure.example yes;
|
||||
|
||||
nta-lifetime 10s;
|
||||
nta-recheck 7s;
|
||||
|
||||
# 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.
|
||||
|
@ -26,6 +26,7 @@ cd ns1 && $SHELL sign.sh
|
||||
|
||||
echo "a.bogus.example. A 10.0.0.22" >>../ns3/bogus.example.db.signed
|
||||
echo "b.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed
|
||||
echo "c.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed
|
||||
|
||||
cd ../ns3 && cp -f siginterval1.conf siginterval.conf
|
||||
cd ../ns4 && cp -f named1.conf named.conf
|
||||
|
@ -1568,7 +1568,7 @@ keyid=`cat ns1/managed.key.id`
|
||||
linecount=`grep "./RSAMD5/$keyid ; trusted" ns4/named.secroots | wc -l`
|
||||
[ "$linecount" -eq 1 ] || ret=1
|
||||
linecount=`cat ns4/named.secroots | wc -l`
|
||||
[ "$linecount" -eq 5 ] || ret=1
|
||||
[ "$linecount" -eq 10 ] || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
@ -1654,26 +1654,88 @@ status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking positive and negative validation with negative trust anchors ($n)"
|
||||
ret=0
|
||||
#
|
||||
# check correct initial behavior
|
||||
#
|
||||
$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
|
||||
|
||||
#
|
||||
# add negative trust anchors
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta bogus.example 15s 2>&1 | sed 's/^/I:ns4 /'
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta secure.example 15s 2>&1 | sed 's/^/I:ns4 /'
|
||||
#
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -f -l 15s bogus.example 2>&1 | sed 's/^/I:ns4 /'
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta badds.example 2>&1 | sed 's/^/I:ns4 /'
|
||||
lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l`
|
||||
[ "$lines" -eq 2 ] || ret=1
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta secure.example 2>&1 | sed 's/^/I:ns4 /'
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta fakenode.secure.example 2>&1 | sed 's/^/I:ns4 /'
|
||||
lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l`
|
||||
[ "$lines" -eq 4 ] || ret=1
|
||||
|
||||
#
|
||||
# check behavior with NTA's in place
|
||||
$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
|
||||
$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
|
||||
echo "I: waiting for NTA expiration"
|
||||
sleep 15
|
||||
# check correct behavior after expiry
|
||||
$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null || ret=1
|
||||
#
|
||||
$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
|
||||
$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1
|
||||
$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1
|
||||
$DIG $DIGOPTS a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1
|
||||
echo "I: dumping secroots"
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 secroots | sed 's/^/I:ns4 /'
|
||||
grep "bogus.example: expiry" ns4/named.secroots > /dev/null || ret=1
|
||||
grep "badds.example: expiry" ns4/named.secroots > /dev/null || ret=1
|
||||
grep "secure.example: expiry" ns4/named.secroots > /dev/null || ret=1
|
||||
grep "fakenode.secure.example: expiry" ns4/named.secroots > /dev/null || ret=1
|
||||
echo "I: waiting for NTA rechecks/expirations"
|
||||
|
||||
#
|
||||
# secure.example and badds.example used default nta-duration
|
||||
# (configured as 10s in ns4/named1.conf), but nta recheck interval
|
||||
# is configured to 7s, so at t=8 the NTAs for secure.example and
|
||||
# fakenode.secure.example should both be lifted, but badds.example
|
||||
# should still be going.
|
||||
#
|
||||
sleep 8
|
||||
$DIG $DIGOPTS b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.8 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS b.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.9 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 > /dev/null || ret=1
|
||||
grep "status: NXDOMAIN" dig.out.ns4.test$n.9 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.10 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.10 > /dev/null && ret=1
|
||||
|
||||
#
|
||||
# bogus.example was set to expire in 15s, so at t=11
|
||||
# it should still be NTA'd, but badds.example used the default
|
||||
# lifetime of 10s, so it should revert to SERVFAIL now.
|
||||
#
|
||||
sleep 3
|
||||
$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1
|
||||
$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.12 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS c.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.13 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 > /dev/null || ret=1
|
||||
|
||||
#
|
||||
# at t=16, all the NTAs should have expired.
|
||||
#
|
||||
sleep 5
|
||||
# check correct behavior after bogus.example expiry
|
||||
$DIG $DIGOPTS d.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.14 || ret=1
|
||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 > /dev/null || ret=1
|
||||
$DIG $DIGOPTS c.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.15 || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n.15 > /dev/null || ret=1
|
||||
# check nta table has been cleaned up now
|
||||
lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l`
|
||||
[ "$lines" -eq 0 ] || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
@ -4939,6 +4939,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
<optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
|
||||
<optional> min-retry-time <replaceable>number</replaceable> ; </optional>
|
||||
<optional> max-retry-time <replaceable>number</replaceable> ; </optional>
|
||||
<optional> nta-lifetime <replaceable>duration</replaceable> ; </optional>
|
||||
<optional> nta-recheck <replaceable>duration</replaceable> ; </optional>
|
||||
<optional> port <replaceable>ip_port</replaceable>; </optional>
|
||||
<optional> dscp <replaceable>ip_dscp</replaceable></optional> ;
|
||||
<optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
|
||||
@ -5746,6 +5748,69 @@ options {
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>nta-lifetime</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Species the default lifetime, in seconds,
|
||||
that will be used for negative trust anchors added
|
||||
via <command>rndc nta</command>.
|
||||
</para>
|
||||
<para>
|
||||
A negative trust anchor selectively disables
|
||||
DNSSEC validation for zones that known to be
|
||||
failing because of misconfiguration rather than
|
||||
an attack. When data to be validated is
|
||||
at or below an active NTA (and above any other
|
||||
configured trust anchors), <command>named</command> will
|
||||
abort the DNSSEC validation process and treat the data as
|
||||
insecure rather than bogus. This continues until the
|
||||
NTA's lifetime is elapsed, or until the server is
|
||||
restarted (NTA's do not persist across restarts).
|
||||
</para>
|
||||
<para>
|
||||
For convienience, TTL-style time unit suffixes can be
|
||||
used to specify the NTA lifetime in seconds, minutes
|
||||
or hours. <option>nta-lifetime</option> defaults to
|
||||
one hour. It cannot exceed one day.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>nta-recheck</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Species how often to check whether negative
|
||||
trust anchors added via <command>rndc nta</command>
|
||||
are still necessary.
|
||||
</para>
|
||||
<para>
|
||||
A negative trust anchor is normally used when a
|
||||
domain has stopped validating due to operator error;
|
||||
it temporarily disables DNSSEC validation for that
|
||||
domain. In the interest of ensuring that DNSSEC
|
||||
validation is turned back on as soon as possible,
|
||||
<command>named</command> will periodically send a
|
||||
query to the domain, ignoring negative trust anchors,
|
||||
to find out whether it can now be validated. If so,
|
||||
the negative trust anchor is allowed to expire early.
|
||||
</para>
|
||||
<para>
|
||||
Validity checks can be disabled for an indivdiual
|
||||
NTA by using <command>rndc nta -f</command>, or
|
||||
for all NTA's by setting <option>nta-recheck</option>
|
||||
to zero.
|
||||
</para>
|
||||
<para>
|
||||
For convienience, TTL-style time unit suffixes can be
|
||||
used to specify the NTA recheck interval in seconds,
|
||||
minutes or hours. The default is five minutes.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term><command>max-zone-ttl</command></term>
|
||||
<listitem>
|
||||
|
@ -783,6 +783,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
||||
const char *str;
|
||||
dns_name_t *name;
|
||||
isc_buffer_t b;
|
||||
isc_uint32_t lifetime;
|
||||
|
||||
static intervaltable intervals[] = {
|
||||
{ "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
||||
@ -1153,6 +1154,38 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(options, "nta-lifetime", &obj);
|
||||
if (obj != NULL) {
|
||||
lifetime = cfg_obj_asuint32(obj);
|
||||
if (lifetime > 86400) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"'nta-lifetime' cannot exceed one day");
|
||||
result = ISC_R_RANGE;
|
||||
} else if (lifetime == 0) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"'nta-lifetime' may not be zero");
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(options, "nta-recheck", &obj);
|
||||
if (obj != NULL) {
|
||||
isc_uint32_t recheck = cfg_obj_asuint32(obj);
|
||||
if (recheck > 86400) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"'nta-recheck' cannot exceed one day");
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
|
||||
if (recheck > lifetime)
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
||||
"'nta-recheck' (%d seconds) is "
|
||||
"greater than 'nta-lifetime' "
|
||||
"(%d seconds)", recheck, lifetime);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
@ -300,6 +300,8 @@ dns_cache_create3(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
|
||||
result = isc_task_create(taskmgr, 1, &dbtask);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_db;
|
||||
|
||||
isc_task_setname(dbtask, "cache_dbtask", NULL);
|
||||
dns_db_settask(cache->db, dbtask);
|
||||
isc_task_detach(&dbtask);
|
||||
}
|
||||
|
@ -28,21 +28,31 @@
|
||||
* DNSSEC validation.
|
||||
*/
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/timer.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
struct dns_ntatable {
|
||||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
dns_view_t *view;
|
||||
isc_rwlock_t rwlock;
|
||||
isc_uint32_t recheck;
|
||||
isc_taskmgr_t *taskmgr;
|
||||
isc_timermgr_t *timermgr;
|
||||
isc_task_t *task;
|
||||
/* Locked by rwlock. */
|
||||
isc_uint32_t references;
|
||||
dns_rbt_t *table;
|
||||
@ -51,23 +61,18 @@ struct dns_ntatable {
|
||||
#define NTATABLE_MAGIC ISC_MAGIC('N', 'T', 'A', 't')
|
||||
#define VALID_NTATABLE(nt) ISC_MAGIC_VALID(nt, NTATABLE_MAGIC)
|
||||
|
||||
struct dns_nta {
|
||||
unsigned int magic;
|
||||
isc_refcount_t refcount;
|
||||
isc_stdtime_t expiry;
|
||||
};
|
||||
|
||||
#define NTA_MAGIC ISC_MAGIC('N', 'T', 'A', 'n')
|
||||
#define VALID_NTA(nn) ISC_MAGIC_VALID(nn, NTA_MAGIC)
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_create(isc_mem_t *mctx, dns_ntatable_t **ntatablep);
|
||||
dns_ntatable_create(dns_view_t *view,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
|
||||
dns_ntatable_t **ntatablep);
|
||||
/*%<
|
||||
* Create an NTA table.
|
||||
* Create an NTA table in view 'view'.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*\li 'view' is a valid view.
|
||||
*
|
||||
*\li 'tmgr' is a valid timer manager.
|
||||
*
|
||||
*\li ntatablep != NULL && *ntatablep == NULL
|
||||
*
|
||||
@ -116,10 +121,13 @@ dns_ntatable_detach(dns_ntatable_t **ntatablep);
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
|
||||
isc_uint32_t expiry);
|
||||
isc_boolean_t force, isc_stdtime_t now,
|
||||
isc_uint32_t lifetime);
|
||||
/*%<
|
||||
* Add a negative trust anchor to 'ntatable' for name 'name',
|
||||
* which will expire at time 'expiry'.
|
||||
* which will expire at time 'now' + 'lifetime'. If 'force' is ISC_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.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
@ -191,15 +199,15 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp);
|
||||
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf);
|
||||
/*%<
|
||||
* Dump the NTA table on fp.
|
||||
* Dump the NTA table to buffer 'buf'
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_nta_create(isc_mem_t *mctx, dns_nta_t **target);
|
||||
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp);
|
||||
/*%<
|
||||
* Allocate space for an NTA
|
||||
* Dump the NTA table to the file opened as 'fp'.
|
||||
*/
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
|
@ -98,6 +98,7 @@ typedef struct dns_fetchevent {
|
||||
#define DNS_FETCHOPT_WANTNSID 0x080 /*%< Request NSID */
|
||||
#define DNS_FETCHOPT_PREFETCH 0x100 /*%< Do prefetch */
|
||||
#define DNS_FETCHOPT_NOCDFLAG 0x200 /*%< Don't set CD flag. */
|
||||
#define DNS_FETCHOPT_NONTA 0x400 /*%< Ignore NTA table. */
|
||||
|
||||
/* Reserved in use by adb.c 0x00400000 */
|
||||
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
|
||||
|
@ -174,6 +174,7 @@ struct dns_validator {
|
||||
#define DNS_VALIDATOR_DLV 0x0001U
|
||||
#define DNS_VALIDATOR_DEFER 0x0002U
|
||||
#define DNS_VALIDATOR_NOCDFLAG 0x0004U
|
||||
#define DNS_VALIDATOR_NONTA 0x0008U /*% Ignore NTA table */
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
|
@ -152,6 +152,8 @@ struct dns_view {
|
||||
isc_boolean_t requestsit;
|
||||
dns_ttl_t maxcachettl;
|
||||
dns_ttl_t maxncachettl;
|
||||
isc_uint32_t nta_lifetime;
|
||||
isc_uint32_t nta_recheck;
|
||||
dns_ttl_t prefetch_trigger;
|
||||
dns_ttl_t prefetch_eligible;
|
||||
in_port_t dstport;
|
||||
@ -1076,7 +1078,8 @@ dns_view_iscacheshared(dns_view_t *view);
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_view_initntatable(dns_view_t *view, isc_mem_t *mctx);
|
||||
dns_view_initntatable(dns_view_t *view,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
|
||||
/*%<
|
||||
* Initialize the negative trust anchor table for the view.
|
||||
*
|
||||
@ -1144,11 +1147,15 @@ dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp);
|
||||
|
||||
isc_result_t
|
||||
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
|
||||
isc_stdtime_t now, isc_boolean_t *secure_domain);
|
||||
isc_stdtime_t now, isc_boolean_t checknta,
|
||||
isc_boolean_t *secure_domain);
|
||||
/*%<
|
||||
* Is 'name' at or beneath a trusted key, and not covered by a valid
|
||||
* negative trust anchor? Put answer in '*secure_domain'.
|
||||
*
|
||||
* If 'checknta' is ISC_FALSE, ignore the NTA table in determining
|
||||
* whether this is a secure domain.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'view' is valid.
|
||||
*
|
||||
|
344
lib/dns/nta.c
344
lib/dns/nta.c
@ -18,20 +18,42 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/nta.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rbt.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
struct dns_nta {
|
||||
unsigned int magic;
|
||||
isc_refcount_t refcount;
|
||||
dns_ntatable_t *ntatable;
|
||||
isc_timer_t *timer;
|
||||
dns_fetch_t *fetch;
|
||||
dns_rdataset_t rdataset;
|
||||
dns_rdataset_t sigrdataset;
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name;
|
||||
isc_stdtime_t expiry;
|
||||
};
|
||||
|
||||
#define NTA_MAGIC ISC_MAGIC('N', 'T', 'A', 'n')
|
||||
#define VALID_NTA(nn) ISC_MAGIC_VALID(nn, NTA_MAGIC)
|
||||
|
||||
static void
|
||||
nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
||||
unsigned int refs;
|
||||
@ -42,7 +64,22 @@ nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
||||
*ntap = NULL;
|
||||
isc_refcount_decrement(&nta->refcount, &refs);
|
||||
if (refs == 0) {
|
||||
nta->magic = 0;
|
||||
if (nta->timer != NULL) {
|
||||
(void) isc_timer_reset(nta->timer,
|
||||
isc_timertype_inactive,
|
||||
NULL, NULL, ISC_TRUE);
|
||||
isc_timer_detach(&nta->timer);
|
||||
}
|
||||
isc_refcount_destroy(&nta->refcount);
|
||||
if (dns_rdataset_isassociated(&nta->rdataset))
|
||||
dns_rdataset_disassociate(&nta->rdataset);
|
||||
if (dns_rdataset_isassociated(&nta->sigrdataset))
|
||||
dns_rdataset_disassociate(&nta->sigrdataset);
|
||||
if (nta->fetch != NULL) {
|
||||
dns_resolver_cancelfetch(nta->fetch);
|
||||
dns_resolver_destroyfetch(&nta->fetch);
|
||||
}
|
||||
isc_mem_put(mctx, nta, sizeof(dns_nta_t));
|
||||
}
|
||||
}
|
||||
@ -56,32 +93,41 @@ free_nta(void *data, void *arg) {
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_create(isc_mem_t *mctx, dns_ntatable_t **ntatablep) {
|
||||
dns_ntatable_create(dns_view_t *view,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
|
||||
dns_ntatable_t **ntatablep)
|
||||
{
|
||||
dns_ntatable_t *ntatable;
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
* Create an NTA table.
|
||||
*/
|
||||
|
||||
REQUIRE(ntatablep != NULL && *ntatablep == NULL);
|
||||
|
||||
ntatable = isc_mem_get(mctx, sizeof(*ntatable));
|
||||
ntatable = isc_mem_get(view->mctx, sizeof(*ntatable));
|
||||
if (ntatable == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
ntatable->table = NULL;
|
||||
result = dns_rbt_create(mctx, free_nta, mctx, &ntatable->table);
|
||||
ntatable->task = NULL;
|
||||
result = isc_task_create(taskmgr, 0, &ntatable->task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_ntatable;
|
||||
isc_task_setname(ntatable->task, "ntatable", ntatable);
|
||||
|
||||
ntatable->table = NULL;
|
||||
result = dns_rbt_create(view->mctx, free_nta, view->mctx,
|
||||
&ntatable->table);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_task;
|
||||
|
||||
result = isc_rwlock_init(&ntatable->rwlock, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rbt;
|
||||
|
||||
ntatable->mctx = NULL;
|
||||
isc_mem_attach(mctx, &ntatable->mctx);
|
||||
ntatable->timermgr = timermgr;
|
||||
ntatable->taskmgr = taskmgr;
|
||||
|
||||
ntatable->view = view;
|
||||
ntatable->references = 1;
|
||||
|
||||
ntatable->magic = NTATABLE_MAGIC;
|
||||
*ntatablep = ntatable;
|
||||
|
||||
@ -90,8 +136,11 @@ dns_ntatable_create(isc_mem_t *mctx, dns_ntatable_t **ntatablep) {
|
||||
cleanup_rbt:
|
||||
dns_rbt_destroy(&ntatable->table);
|
||||
|
||||
cleanup_task:
|
||||
isc_task_detach(&ntatable->task);
|
||||
|
||||
cleanup_ntatable:
|
||||
isc_mem_put(mctx, ntatable, sizeof(*ntatable));
|
||||
isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
|
||||
|
||||
return (result);
|
||||
}
|
||||
@ -132,43 +181,187 @@ dns_ntatable_detach(dns_ntatable_t **ntatablep) {
|
||||
if (destroy) {
|
||||
dns_rbt_destroy(&ntatable->table);
|
||||
isc_rwlock_destroy(&ntatable->rwlock);
|
||||
if (ntatable->task != NULL)
|
||||
isc_task_detach(&ntatable->task);
|
||||
ntatable->timermgr = NULL;
|
||||
ntatable->taskmgr = NULL;
|
||||
ntatable->magic = 0;
|
||||
isc_mem_putanddetach(&ntatable->mctx,
|
||||
ntatable, sizeof(*ntatable));
|
||||
isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_done(isc_task_t *task, isc_event_t *event) {
|
||||
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
|
||||
dns_nta_t *nta = devent->ev_arg;
|
||||
isc_result_t eresult = devent->result;
|
||||
dns_ntatable_t *ntatable = nta->ntatable;
|
||||
isc_stdtime_t now;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
if (dns_rdataset_isassociated(&nta->rdataset))
|
||||
dns_rdataset_disassociate(&nta->rdataset);
|
||||
if (dns_rdataset_isassociated(&nta->sigrdataset))
|
||||
dns_rdataset_disassociate(&nta->sigrdataset);
|
||||
dns_resolver_destroyfetch(&nta->fetch);
|
||||
|
||||
if (devent->node != NULL)
|
||||
dns_db_detachnode(devent->db, &devent->node);
|
||||
if (devent->db != NULL)
|
||||
dns_db_detach(&devent->db);
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
switch (eresult) {
|
||||
case ISC_R_SUCCESS:
|
||||
case DNS_R_NCACHENXDOMAIN:
|
||||
case DNS_R_NXDOMAIN:
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
case DNS_R_NXRRSET:
|
||||
isc_stdtime_get(&now);
|
||||
nta->expiry = now;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're expiring before the next recheck, we might
|
||||
* as well stop the timer now.
|
||||
*/
|
||||
if (nta->timer != NULL && nta->expiry - now < ntatable->recheck)
|
||||
(void) isc_timer_reset(nta->timer, isc_timertype_inactive,
|
||||
NULL, NULL, ISC_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
checkbogus(isc_task_t *task, isc_event_t *event) {
|
||||
dns_nta_t *nta = event->ev_arg;
|
||||
dns_ntatable_t *ntatable = nta->ntatable;
|
||||
dns_view_t *view = ntatable->view;
|
||||
|
||||
if (nta->fetch != NULL) {
|
||||
dns_resolver_cancelfetch(nta->fetch);
|
||||
dns_resolver_destroyfetch(&nta->fetch);
|
||||
}
|
||||
if (dns_rdataset_isassociated(&nta->rdataset))
|
||||
dns_rdataset_disassociate(&nta->rdataset);
|
||||
if (dns_rdataset_isassociated(&nta->sigrdataset))
|
||||
dns_rdataset_disassociate(&nta->sigrdataset);
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
(void)dns_resolver_createfetch(view->resolver, nta->name,
|
||||
dns_rdatatype_nsec,
|
||||
NULL, NULL, NULL,
|
||||
DNS_FETCHOPT_NONTA,
|
||||
task, fetch_done, nta,
|
||||
&nta->rdataset,
|
||||
&nta->sigrdataset,
|
||||
&nta->fetch);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
settimer(dns_ntatable_t *ntatable, dns_nta_t *nta, isc_uint32_t lifetime) {
|
||||
isc_result_t result;
|
||||
isc_interval_t interval;
|
||||
dns_view_t *view;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
REQUIRE(VALID_NTA(nta));
|
||||
|
||||
if (ntatable->timermgr == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
view = ntatable->view;
|
||||
if (view->nta_recheck == 0 || lifetime <= view->nta_recheck)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
isc_interval_set(&interval, view->nta_recheck, 0);
|
||||
result = isc_timer_create(ntatable->timermgr, isc_timertype_ticker,
|
||||
NULL, &interval, ntatable->task,
|
||||
checkbogus, nta, &nta->timer);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
nta_create(dns_ntatable_t *ntatable, dns_name_t *name, dns_nta_t **target) {
|
||||
isc_result_t result;
|
||||
dns_nta_t *nta = NULL;
|
||||
dns_view_t *view;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
view = ntatable->view;
|
||||
|
||||
nta = isc_mem_get(view->mctx, sizeof(dns_nta_t));
|
||||
if (nta == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
nta->ntatable = ntatable;
|
||||
nta->expiry = 0;
|
||||
nta->timer = NULL;
|
||||
nta->fetch = NULL;
|
||||
dns_rdataset_init(&nta->rdataset);
|
||||
dns_rdataset_init(&nta->sigrdataset);
|
||||
|
||||
result = isc_refcount_init(&nta->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(view->mctx, nta, sizeof(dns_nta_t));
|
||||
return (result);
|
||||
}
|
||||
|
||||
dns_fixedname_init(&nta->fn);
|
||||
nta->name = dns_fixedname_name(&nta->fn);
|
||||
dns_name_copy(name, nta->name, NULL);
|
||||
|
||||
nta->magic = NTA_MAGIC;
|
||||
|
||||
*target = nta;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
|
||||
isc_uint32_t expiry)
|
||||
isc_boolean_t force, isc_stdtime_t now,
|
||||
isc_uint32_t lifetime)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_nta_t *nta = NULL;
|
||||
dns_rbtnode_t *node;
|
||||
dns_view_t *view;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
|
||||
result = dns_nta_create(ntatable->mctx, &nta);
|
||||
view = ntatable->view;
|
||||
|
||||
result = nta_create(ntatable, name, &nta);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
nta->expiry = expiry;
|
||||
nta->expiry = now + lifetime;
|
||||
|
||||
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
|
||||
|
||||
node = NULL;
|
||||
result = dns_rbt_addnode(ntatable->table, name, &node);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (!force)
|
||||
(void)settimer(ntatable, nta, lifetime);
|
||||
node->data = nta;
|
||||
nta = NULL;
|
||||
} else if (result == ISC_R_EXISTS) {
|
||||
dns_nta_t *n = node->data;
|
||||
if (n == NULL) {
|
||||
if (!force)
|
||||
(void)settimer(ntatable, nta, lifetime);
|
||||
node->data = nta;
|
||||
nta = NULL;
|
||||
} else {
|
||||
n->expiry = nta->expiry;
|
||||
nta_detach(ntatable->mctx, &nta);
|
||||
nta_detach(view->mctx, &nta);
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
@ -176,7 +369,7 @@ dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
|
||||
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
|
||||
|
||||
if (nta != NULL)
|
||||
nta_detach(ntatable->mctx, &nta);
|
||||
nta_detach(view->mctx, &nta);
|
||||
|
||||
return (result);
|
||||
}
|
||||
@ -268,6 +461,13 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
||||
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
|
||||
"deleting expired NTA at %s", nb);
|
||||
|
||||
if (nta->timer != NULL) {
|
||||
(void) isc_timer_reset(nta->timer,
|
||||
isc_timertype_inactive,
|
||||
NULL, NULL, ISC_TRUE);
|
||||
isc_timer_detach(&nta->timer);
|
||||
}
|
||||
|
||||
result = delete(ntatable, foundname);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
|
||||
@ -283,15 +483,19 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
|
||||
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf) {
|
||||
isc_result_t result;
|
||||
dns_rbtnode_t *node;
|
||||
dns_rbtnodechain_t chain;
|
||||
isc_boolean_t first = ISC_TRUE;
|
||||
isc_stdtime_t now;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
|
||||
dns_rbtnodechain_init(&chain, ntatable->mctx);
|
||||
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;
|
||||
@ -300,15 +504,80 @@ dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
|
||||
if (node->data != NULL) {
|
||||
dns_nta_t *n = (dns_nta_t *) node->data;
|
||||
char nbuf[DNS_NAME_FORMATSIZE], tbuf[80];
|
||||
dns_name_t name;
|
||||
char obuf[DNS_NAME_FORMATSIZE + 200];
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name;
|
||||
isc_time_t t;
|
||||
|
||||
dns_name_init(&name, NULL);
|
||||
dns_rbt_namefromnode(node, &name);
|
||||
dns_name_format(&name, nbuf, sizeof(nbuf));
|
||||
dns_fixedname_init(&fn);
|
||||
name = dns_fixedname_name(&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 : expiry %s\n", nbuf, tbuf);
|
||||
|
||||
snprintf(obuf, sizeof(obuf), "%s%s: %s %s",
|
||||
first ? "" : "\n", nbuf,
|
||||
n->expiry < now ? "expired" : "expiry",
|
||||
tbuf);
|
||||
first = ISC_FALSE;
|
||||
if (strlen(obuf) >= isc_buffer_availablelength(buf)) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto cleanup;
|
||||
} else
|
||||
isc_buffer_putstr(buf, obuf);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (isc_buffer_availablelength(buf) != 0)
|
||||
isc_buffer_putuint8(buf, 0);
|
||||
|
||||
cleanup:
|
||||
dns_rbtnodechain_invalidate(&chain);
|
||||
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
|
||||
return (result);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
dns_fixedname_init(&fn);
|
||||
name = dns_fixedname_name(&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) {
|
||||
@ -323,28 +592,3 @@ dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
|
||||
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_nta_create(isc_mem_t *mctx, dns_nta_t **target) {
|
||||
isc_result_t result;
|
||||
dns_nta_t *nta = NULL;
|
||||
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
nta = isc_mem_get(mctx, sizeof(dns_nta_t));
|
||||
if (nta == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
nta->expiry = 0;
|
||||
|
||||
result = isc_refcount_init(&nta->refcount, 1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, nta, sizeof(dns_nta_t));
|
||||
return (result);
|
||||
}
|
||||
|
||||
nta->magic = NTA_MAGIC;
|
||||
|
||||
*target = nta;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
@ -1823,7 +1823,8 @@ compute_cc(resquery_t *query, unsigned char *sit, size_t len) {
|
||||
|
||||
static isc_result_t
|
||||
issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
||||
isc_stdtime_t now, isc_boolean_t *issecure)
|
||||
isc_stdtime_t now, isc_boolean_t checknta,
|
||||
isc_boolean_t *issecure)
|
||||
{
|
||||
dns_name_t suffix;
|
||||
unsigned int labels;
|
||||
@ -1841,7 +1842,7 @@ issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
||||
name = &suffix;
|
||||
}
|
||||
|
||||
return (dns_view_issecuredomain(view, name, now, issecure));
|
||||
return (dns_view_issecuredomain(view, name, now, checknta, issecure));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@ -1944,10 +1945,13 @@ resquery_send(resquery_t *query) {
|
||||
else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0)
|
||||
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
|
||||
else if (res->view->enablevalidation &&
|
||||
((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0)) {
|
||||
((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0))
|
||||
{
|
||||
isc_boolean_t checknta =
|
||||
ISC_TF((query->options & DNS_FETCHOPT_NONTA) == 0);
|
||||
result = issecuredomain(res->view, &fctx->name,
|
||||
fctx->type, query->start.seconds,
|
||||
&secure_domain);
|
||||
checknta, &secure_domain);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
secure_domain = ISC_FALSE;
|
||||
if (res->view->dlv != NULL)
|
||||
@ -4833,6 +4837,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
|
||||
isc_task_t *task;
|
||||
isc_boolean_t fail;
|
||||
unsigned int valoptions = 0;
|
||||
isc_boolean_t checknta = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* The appropriate bucket lock must be held.
|
||||
@ -4849,14 +4854,19 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
|
||||
/*
|
||||
* Is DNSSEC validation required for this name?
|
||||
*/
|
||||
if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
|
||||
valoptions |= DNS_VALIDATOR_NONTA;
|
||||
checknta = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (res->view->enablevalidation) {
|
||||
result = issecuredomain(res->view, name, fctx->type,
|
||||
now, &secure_domain);
|
||||
now, checknta, &secure_domain);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
if (!secure_domain && res->view->dlv != NULL) {
|
||||
valoptions = DNS_VALIDATOR_DLV;
|
||||
valoptions |= DNS_VALIDATOR_DLV;
|
||||
secure_domain = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
@ -5362,6 +5372,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
dns_fetchevent_t *event;
|
||||
isc_uint32_t ttl;
|
||||
unsigned int valoptions = 0;
|
||||
isc_boolean_t checknta = ISC_TRUE;
|
||||
|
||||
FCTXTRACE("ncache_message");
|
||||
|
||||
@ -5384,14 +5395,19 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
/*
|
||||
* Is DNSSEC validation required for this name?
|
||||
*/
|
||||
if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
|
||||
valoptions |= DNS_VALIDATOR_NONTA;
|
||||
checknta = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (fctx->res->view->enablevalidation) {
|
||||
result = issecuredomain(res->view, name, fctx->type,
|
||||
now, &secure_domain);
|
||||
now, checknta, &secure_domain);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
if (!secure_domain && res->view->dlv != NULL) {
|
||||
valoptions = DNS_VALIDATOR_DLV;
|
||||
valoptions |= DNS_VALIDATOR_DLV;
|
||||
secure_domain = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
@ -8275,6 +8291,7 @@ dns_resolver_create(dns_view_t *view,
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_primelock;
|
||||
isc_task_setname(task, "resolver_task", NULL);
|
||||
|
||||
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
||||
task, spillattimer_countdown, res,
|
||||
|
@ -50,6 +50,8 @@ static const dns_keytag_t keytag1 = 30591;
|
||||
|
||||
static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/inaJpYv7vH XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/ItBfh/hL2lm Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi79532Qeklxh x8pXWdeAaRU=";
|
||||
|
||||
static dns_view_t *view = NULL;
|
||||
|
||||
/*
|
||||
* Test utilities. In general, these assume input parameters are valid
|
||||
* (checking with ATF_REQUIRE_EQ, thus aborting if not) and unlikely run time
|
||||
@ -119,11 +121,16 @@ create_key(isc_uint16_t flags, isc_uint8_t proto, isc_uint8_t alg,
|
||||
/* Common setup: create a keytable and ntatable to test with a few keys */
|
||||
static void
|
||||
create_tables() {
|
||||
isc_result_t result;
|
||||
dst_key_t *key = NULL;
|
||||
isc_stdtime_t now;
|
||||
|
||||
result = dns_test_makeview("view", &view);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_ntatable_create(mctx, &ntatable), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_ntatable_create(view, taskmgr, timermgr,
|
||||
&ntatable), ISC_R_SUCCESS);
|
||||
|
||||
/* Add a normal key */
|
||||
create_key(257, 3, 5, "example.com", keystr1, &key);
|
||||
@ -139,7 +146,7 @@ create_tables() {
|
||||
isc_stdtime_get(&now);
|
||||
ATF_REQUIRE_EQ(dns_ntatable_add(ntatable,
|
||||
str2name("insecure.example"),
|
||||
now + 3600),
|
||||
ISC_FALSE, now, 3600),
|
||||
ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@ -149,6 +156,8 @@ destroy_tables() {
|
||||
dns_ntatable_detach(&ntatable);
|
||||
if (keytable != NULL)
|
||||
dns_keytable_detach(&keytable);
|
||||
|
||||
dns_view_detach(&view);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -167,7 +176,7 @@ ATF_TC_BODY(add, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/*
|
||||
@ -246,7 +255,7 @@ ATF_TC_HEAD(delete, tc) {
|
||||
ATF_TC_BODY(delete, tc) {
|
||||
UNUSED(tc);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/* dns_keytable_delete requires exact match */
|
||||
@ -279,7 +288,7 @@ ATF_TC_BODY(deletekeynode, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/* key name doesn't match */
|
||||
@ -340,7 +349,7 @@ ATF_TC_BODY(find, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/*
|
||||
@ -432,7 +441,7 @@ ATF_TC_BODY(issecuredomain, tc) {
|
||||
"null.example", "sub.null.example", NULL};
|
||||
|
||||
UNUSED(tc);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/*
|
||||
@ -476,7 +485,7 @@ ATF_TC_HEAD(dump, tc) {
|
||||
ATF_TC_BODY(dump, tc) {
|
||||
UNUSED(tc);
|
||||
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS);
|
||||
create_tables();
|
||||
|
||||
/*
|
||||
@ -508,12 +517,15 @@ ATF_TC_BODY(nta, tc) {
|
||||
result = dns_test_makeview("view", &view);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &view->task);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = dns_view_initsecroots(view, mctx);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = dns_view_getsecroots(view, &keytable);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = dns_view_initntatable(view, mctx);
|
||||
result = dns_view_initntatable(view, taskmgr, timermgr);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = dns_view_getntatable(view, &ntatable);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
@ -524,20 +536,21 @@ ATF_TC_BODY(nta, tc) {
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
result = dns_ntatable_add(ntatable,
|
||||
str2name("insecure.example"), now + 1);
|
||||
str2name("insecure.example"),
|
||||
ISC_FALSE, now, 1);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
/* Should be secure */
|
||||
result = dns_view_issecuredomain(view,
|
||||
str2name("test.secure.example"),
|
||||
now, &issecure);
|
||||
now, ISC_TRUE, &issecure);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_CHECK(issecure);
|
||||
|
||||
/* Should not be secure */
|
||||
result = dns_view_issecuredomain(view,
|
||||
str2name("test.insecure.example"),
|
||||
now, &issecure);
|
||||
now, ISC_TRUE, &issecure);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_CHECK(!issecure);
|
||||
|
||||
@ -554,17 +567,17 @@ ATF_TC_BODY(nta, tc) {
|
||||
/* As of now + 2, the NTA should be clear */
|
||||
result = dns_view_issecuredomain(view,
|
||||
str2name("test.insecure.example"),
|
||||
now + 2, &issecure);
|
||||
now + 2, ISC_TRUE, &issecure);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_CHECK(issecure);
|
||||
|
||||
/* Now check deletion */
|
||||
result = dns_ntatable_add(ntatable,
|
||||
str2name("new.example"), now + 3600);
|
||||
result = dns_ntatable_add(ntatable, str2name("new.example"),
|
||||
ISC_FALSE, now, 3600);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
||||
now, &issecure);
|
||||
now, ISC_TRUE, &issecure);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_CHECK(!issecure);
|
||||
|
||||
@ -572,7 +585,7 @@ ATF_TC_BODY(nta, tc) {
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
||||
now, &issecure);
|
||||
now, ISC_TRUE, &issecure);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
ATF_CHECK(issecure);
|
||||
|
||||
|
@ -1139,6 +1139,9 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
|
||||
if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0)
|
||||
fopts |= DNS_FETCHOPT_NOCDFLAG;
|
||||
|
||||
if ((val->options & DNS_VALIDATOR_NONTA) != 0)
|
||||
fopts |= DNS_FETCHOPT_NONTA;
|
||||
|
||||
validator_logcreate(val, name, type, caller, "fetch");
|
||||
return (dns_resolver_createfetch(val->view->resolver, name, type,
|
||||
NULL, NULL, NULL, fopts,
|
||||
@ -3164,7 +3167,8 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
|
||||
return (DNS_R_NOVALIDSIG);
|
||||
}
|
||||
|
||||
if (dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv))
|
||||
if (((val->options & DNS_VALIDATOR_NONTA) == 0) &&
|
||||
dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv))
|
||||
return (DNS_R_NTACOVERED);
|
||||
|
||||
while (dns_name_countlabels(dlvname) >=
|
||||
|
@ -192,6 +192,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view->provideixfr = ISC_TRUE;
|
||||
view->maxcachettl = 7 * 24 * 3600;
|
||||
view->maxncachettl = 3 * 3600;
|
||||
view->nta_lifetime = 0;
|
||||
view->nta_recheck = 0;
|
||||
view->prefetch_eligible = 0;
|
||||
view->prefetch_trigger = 0;
|
||||
view->dstport = 53;
|
||||
@ -1776,11 +1778,14 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_view_initntatable(dns_view_t *view, isc_mem_t *mctx) {
|
||||
dns_view_initntatable(dns_view_t *view,
|
||||
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
|
||||
{
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
if (view->ntatable_priv != NULL)
|
||||
dns_ntatable_detach(&view->ntatable_priv);
|
||||
return (dns_ntatable_create(mctx, &view->ntatable_priv));
|
||||
return (dns_ntatable_create(view, taskmgr, timermgr,
|
||||
&view->ntatable_priv));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@ -1825,7 +1830,8 @@ dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
|
||||
|
||||
isc_result_t
|
||||
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
|
||||
isc_stdtime_t now, isc_boolean_t *secure_domain)
|
||||
isc_stdtime_t now, isc_boolean_t checknta,
|
||||
isc_boolean_t *secure_domain)
|
||||
{
|
||||
isc_result_t result;
|
||||
isc_boolean_t secure = ISC_FALSE;
|
||||
@ -1845,7 +1851,7 @@ dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
if (secure && view->ntatable_priv != NULL &&
|
||||
if (checknta && secure && view->ntatable_priv != NULL &&
|
||||
dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
|
||||
secure = ISC_FALSE;
|
||||
|
||||
|
@ -483,7 +483,6 @@ dns_nsec_isset
|
||||
dns_nsec_nseconly
|
||||
dns_nsec_setbit
|
||||
dns_nsec_typepresent
|
||||
dns_nta_create
|
||||
dns_ntatable_add
|
||||
dns_ntatable_attach
|
||||
dns_ntatable_covered
|
||||
|
@ -136,6 +136,7 @@ static cfg_type_t cfg_type_sizenodefault;
|
||||
static cfg_type_t cfg_type_sockaddr4wild;
|
||||
static cfg_type_t cfg_type_sockaddr6wild;
|
||||
static cfg_type_t cfg_type_statschannels;
|
||||
static cfg_type_t cfg_type_ttlval;
|
||||
static cfg_type_t cfg_type_view;
|
||||
static cfg_type_t cfg_type_viewopts;
|
||||
static cfg_type_t cfg_type_zone;
|
||||
@ -1544,6 +1545,8 @@ view_clauses[] = {
|
||||
{ "max-udp-size", &cfg_type_uint32, 0 },
|
||||
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
|
||||
{ "minimal-responses", &cfg_type_boolean, 0 },
|
||||
{ "nta-recheck", &cfg_type_ttlval, 0 },
|
||||
{ "nta-lifetime", &cfg_type_ttlval, 0 },
|
||||
{ "prefetch", &cfg_type_prefetch, 0 },
|
||||
{ "preferred-glue", &cfg_type_astring, 0 },
|
||||
{ "no-case-compress", &cfg_type_bracketed_aml, 0 },
|
||||
@ -3182,7 +3185,7 @@ static cfg_type_t cfg_type_masterselement = {
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
parse_maxttlval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
parse_ttlval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
cfg_obj_t *obj = NULL;
|
||||
isc_uint32_t ttl;
|
||||
@ -3213,15 +3216,16 @@ parse_maxttlval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
}
|
||||
|
||||
/*%
|
||||
* A size value (number + optional unit).
|
||||
* A TTL value (number + optional unit).
|
||||
*/
|
||||
static cfg_type_t cfg_type_maxttlval = {
|
||||
"maxttlval", parse_maxttlval, cfg_print_uint64, cfg_doc_terminal,
|
||||
&cfg_rep_uint64, NULL };
|
||||
static cfg_type_t cfg_type_ttlval = {
|
||||
"ttlval", parse_ttlval, cfg_print_uint64, cfg_doc_terminal,
|
||||
&cfg_rep_uint64, NULL
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
parse_maxttl(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
return (parse_enum_or_other(pctx, type, &cfg_type_maxttlval, ret));
|
||||
return (parse_enum_or_other(pctx, type, &cfg_type_ttlval, ret));
|
||||
}
|
||||
|
||||
/*%
|
||||
|
Loading…
x
Reference in New Issue
Block a user