mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 18:19:42 +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.
|
3881. [bug] Address memory leak with UPDATE error handling.
|
||||||
[RT #36303]
|
[RT #36303]
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
static char defaultconf[] = "\
|
static char defaultconf[] = "\
|
||||||
options {\n\
|
options {\n\
|
||||||
automatic-interface-scan yes;\n\
|
automatic-interface-scan yes;\n\
|
||||||
|
bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
|
||||||
# blackhole {none;};\n"
|
# blackhole {none;};\n"
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
" coresize default;\n\
|
" coresize default;\n\
|
||||||
@ -78,8 +79,9 @@ options {\n\
|
|||||||
memstatistics-file \"named.memstats\";\n\
|
memstatistics-file \"named.memstats\";\n\
|
||||||
multiple-cnames no;\n\
|
multiple-cnames no;\n\
|
||||||
# named-xfer <obsolete>;\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\
|
# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
|
||||||
bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
|
|
||||||
port 53;\n\
|
port 53;\n\
|
||||||
prefetch 2 9;\n\
|
prefetch 2 9;\n\
|
||||||
recursing-file \"named.recursing\";\n\
|
recursing-file \"named.recursing\";\n\
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id$ */
|
|
||||||
|
|
||||||
/*! \file */
|
/*! \file */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
@ -826,7 +826,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
|
|||||||
return (ISC_R_UNEXPECTED);
|
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) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||||
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
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)
|
if (result == ISC_R_SUCCESS)
|
||||||
CHECK(mustbesecure(obj, view->resolver));
|
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;
|
obj = NULL;
|
||||||
result = ns_config_get(maps, "preferred-glue", &obj);
|
result = ns_config_get(maps, "preferred-glue", &obj);
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
@ -3626,6 +3636,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
|
|||||||
} else {
|
} else {
|
||||||
empty_zones_enable = ISC_FALSE;
|
empty_zones_enable = ISC_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty_zones_enable && !lwresd_g_useresolvconf) {
|
if (empty_zones_enable && !lwresd_g_useresolvconf) {
|
||||||
const char *empty;
|
const char *empty;
|
||||||
int empty_zone = 0;
|
int empty_zone = 0;
|
||||||
@ -7768,6 +7779,7 @@ isc_result_t
|
|||||||
ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
||||||
dns_view_t *view;
|
dns_view_t *view;
|
||||||
dns_keytable_t *secroots = NULL;
|
dns_keytable_t *secroots = NULL;
|
||||||
|
dns_ntatable_t *ntatable = NULL;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
@ -7801,11 +7813,25 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
|||||||
result = ISC_R_SUCCESS;
|
result = ISC_R_SUCCESS;
|
||||||
continue;
|
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);
|
result = dns_keytable_dump(secroots, fp);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
fprintf(fp, " dumpsecroots failed: %s\n",
|
fprintf(fp, " dumpsecroots failed: %s\n",
|
||||||
isc_result_totext(result));
|
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)
|
if (ptr != NULL)
|
||||||
ptr = next_token(&args, " \t");
|
ptr = next_token(&args, " \t");
|
||||||
@ -7814,6 +7840,8 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) {
|
|||||||
cleanup:
|
cleanup:
|
||||||
if (secroots != NULL)
|
if (secroots != NULL)
|
||||||
dns_keytable_detach(&secroots);
|
dns_keytable_detach(&secroots);
|
||||||
|
if (ntatable != NULL)
|
||||||
|
dns_ntatable_detach(&ntatable);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
(void)isc_stdio_close(fp);
|
(void)isc_stdio_close(fp);
|
||||||
if (result == ISC_R_SUCCESS)
|
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_view_t *view;
|
||||||
dns_ntatable_t *ntatable = NULL;
|
dns_ntatable_t *ntatable = NULL;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
char *ptr, *nametext, *viewname;
|
char *ptr, *nametext = NULL, *viewname;
|
||||||
isc_stdtime_t now, when;
|
isc_stdtime_t now, when;
|
||||||
isc_time_t t;
|
isc_time_t t;
|
||||||
char tbuf[64];
|
char tbuf[64];
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
|
isc_boolean_t dump = ISC_FALSE, force = ISC_FALSE;
|
||||||
dns_fixedname_t fn;
|
dns_fixedname_t fn;
|
||||||
dns_name_t *ntaname;
|
dns_name_t *ntaname;
|
||||||
dns_ttl_t ntattl;
|
dns_ttl_t ntattl;
|
||||||
isc_textregion_t tr;
|
isc_boolean_t ttlset = ISC_FALSE;
|
||||||
|
|
||||||
|
UNUSED(force);
|
||||||
|
|
||||||
dns_fixedname_init(&fn);
|
dns_fixedname_init(&fn);
|
||||||
ntaname = dns_fixedname_name(&fn);
|
ntaname = dns_fixedname_name(&fn);
|
||||||
@ -9790,7 +9821,77 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
|||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return (ISC_R_UNEXPECTEDEND);
|
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. */
|
/* Get the NTA name. */
|
||||||
|
if (nametext == NULL)
|
||||||
nametext = next_token(&args, " \t");
|
nametext = next_token(&args, " \t");
|
||||||
if (nametext == NULL)
|
if (nametext == NULL)
|
||||||
return (ISC_R_UNEXPECTEDEND);
|
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));
|
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. */
|
/* Look for the view name. */
|
||||||
viewname = next_token(&args, " \t");
|
viewname = next_token(&args, " \t");
|
||||||
|
|
||||||
/* Set up the NTA */
|
|
||||||
isc_stdtime_get(&now);
|
isc_stdtime_get(&now);
|
||||||
when = now + ntattl;
|
|
||||||
|
|
||||||
result = isc_task_beginexclusive(server->task);
|
result = isc_task_beginexclusive(server->task);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
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)
|
strcmp(view->name, viewname) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (view->nta_lifetime == 0 || view->nta_recheck == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ttlset)
|
||||||
|
ntattl = view->nta_lifetime;
|
||||||
|
|
||||||
if (ntatable != NULL)
|
if (ntatable != NULL)
|
||||||
dns_ntatable_detach(&ntatable);
|
dns_ntatable_detach(&ntatable);
|
||||||
|
|
||||||
@ -9851,12 +9942,14 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) {
|
|||||||
nametext, view->name,
|
nametext, view->name,
|
||||||
isc_result_totext(result));
|
isc_result_totext(result));
|
||||||
|
|
||||||
|
if (ntattl != 0) {
|
||||||
|
CHECK(dns_ntatable_add(ntatable, ntaname,
|
||||||
|
force, now, ntattl));
|
||||||
|
|
||||||
|
when = now + ntattl;
|
||||||
isc_time_set(&t, when, 0);
|
isc_time_set(&t, when, 0);
|
||||||
isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
|
isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
|
||||||
|
|
||||||
if (ntattl > 0) {
|
|
||||||
CHECK(dns_ntatable_add(ntatable, ntaname, when));
|
|
||||||
|
|
||||||
CHECK(putstr(text, "Negative trust anchor added: "));
|
CHECK(putstr(text, "Negative trust anchor added: "));
|
||||||
CHECK(putstr(text, nametext));
|
CHECK(putstr(text, nametext));
|
||||||
CHECK(putstr(text, "/"));
|
CHECK(putstr(text, "/"));
|
||||||
|
@ -463,10 +463,9 @@
|
|||||||
<term><userinput>secroots <optional><replaceable>view ...</replaceable></optional></userinput></term>
|
<term><userinput>secroots <optional><replaceable>view ...</replaceable></optional></userinput></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Dump the server's security roots to the secroots
|
Dump the server's security roots and negative trust anchors
|
||||||
file for the specified views. If no view is
|
to the secroots file for the specified views. If no view is
|
||||||
specified, security roots for all
|
specified, all views are dumped.
|
||||||
views are dumped.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -597,12 +596,19 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<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>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Sets a DNSSEC negative trust anchor (NTA)
|
Sets a DNSSEC negative trust anchor (NTA)
|
||||||
for <option>domain</option>, with a lifetime of
|
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>
|
||||||
<para>
|
<para>
|
||||||
A negative trust anchor selectively disables
|
A negative trust anchor selectively disables
|
||||||
@ -617,13 +623,40 @@
|
|||||||
restarted (NTA's do not persist across restarts).
|
restarted (NTA's do not persist across restarts).
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
TTL-style suffixes can be used to specify
|
An existing NTA can be removed by using the
|
||||||
<option>duration</option> in seconds, minutes, or hours.
|
<option>-remove</option> option.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If the specified domain already has an NTA, its duration
|
An NTA's lifetime can be specified with the
|
||||||
will be updated to the new value. Setting
|
<option>-lifetime</option> option. TTL-style
|
||||||
<option>duration</option> to zero will delete the NTA.
|
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>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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=`grep "dlv.isc.org/RSAMD5/.* ; managed" ns2/named.secroots | wc -l`
|
||||||
[ "$linecount" -eq 2 ] || ret=1
|
[ "$linecount" -eq 2 ] || ret=1
|
||||||
linecount=`cat ns2/named.secroots | wc -l`
|
linecount=`cat ns2/named.secroots | wc -l`
|
||||||
[ "$linecount" -eq 13 ] || ret=1
|
[ "$linecount" -eq 28 ] || ret=1
|
||||||
n=`expr $n + 1`
|
n=`expr $n + 1`
|
||||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||||
status=`expr $status + $ret`
|
status=`expr $status + $ret`
|
||||||
|
@ -65,6 +65,10 @@ ns.insecure A 10.53.0.3
|
|||||||
bogus NS ns.bogus
|
bogus NS ns.bogus
|
||||||
ns.bogus A 10.53.0.3
|
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
|
; A dynamic secure subdomain
|
||||||
dynamic NS dynamic
|
dynamic NS dynamic
|
||||||
dynamic A 10.53.0.3
|
dynamic A 10.53.0.3
|
||||||
|
@ -26,11 +26,10 @@ zonefile=example.db
|
|||||||
|
|
||||||
( cd ../ns3 && $SHELL sign.sh )
|
( cd ../ns3 && $SHELL sign.sh )
|
||||||
|
|
||||||
for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown \
|
for subdomain in secure badds bogus dynamic keyless nsec3 optout \
|
||||||
optout-unknown multiple rsasha256 rsasha512 kskonly update-nsec3 \
|
nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \
|
||||||
auto-nsec auto-nsec3 secure.below-cname ttlpatch split-dnssec \
|
kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \
|
||||||
split-smart expired expiring upper lower
|
ttlpatch split-dnssec split-smart expired expiring upper lower
|
||||||
|
|
||||||
do
|
do
|
||||||
cp ../ns3/dsset-$subdomain.example. .
|
cp ../ns3/dsset-$subdomain.example. .
|
||||||
done
|
done
|
||||||
|
@ -28,5 +28,6 @@ ns A 10.53.0.3
|
|||||||
|
|
||||||
a A 10.0.0.1
|
a A 10.0.0.1
|
||||||
b A 10.0.0.2
|
b A 10.0.0.2
|
||||||
|
c A 10.0.0.3
|
||||||
d A 10.0.0.4
|
d A 10.0.0.4
|
||||||
z A 10.0.0.26
|
z A 10.0.0.26
|
||||||
|
@ -68,6 +68,12 @@ zone "bogus.example" {
|
|||||||
allow-update { any; };
|
allow-update { any; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
zone "badds.example" {
|
||||||
|
type master;
|
||||||
|
file "badds.example.db.signed";
|
||||||
|
allow-update { any; };
|
||||||
|
};
|
||||||
|
|
||||||
zone "dynamic.example" {
|
zone "dynamic.example" {
|
||||||
type master;
|
type master;
|
||||||
file "dynamic.example.db.signed";
|
file "dynamic.example.db.signed";
|
||||||
|
@ -26,7 +26,11 @@ ns3 A 10.53.0.3
|
|||||||
|
|
||||||
a A 10.0.0.1
|
a A 10.0.0.1
|
||||||
b A 10.0.0.2
|
b A 10.0.0.2
|
||||||
|
c A 10.0.0.3
|
||||||
d A 10.0.0.4
|
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
|
z A 10.0.0.26
|
||||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||||
x CNAME a
|
x CNAME a
|
||||||
|
@ -459,3 +459,18 @@ zonefile=siginterval.example.db
|
|||||||
kskname=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
|
kskname=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
|
||||||
zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
|
zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
|
||||||
cp $infile $zonefile
|
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-validation yes;
|
||||||
dnssec-must-be-secure mustbesecure.example 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
|
# 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
|
# 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.
|
# 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 "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 "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 ../ns3 && cp -f siginterval1.conf siginterval.conf
|
||||||
cd ../ns4 && cp -f named1.conf named.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=`grep "./RSAMD5/$keyid ; trusted" ns4/named.secroots | wc -l`
|
||||||
[ "$linecount" -eq 1 ] || ret=1
|
[ "$linecount" -eq 1 ] || ret=1
|
||||||
linecount=`cat ns4/named.secroots | wc -l`
|
linecount=`cat ns4/named.secroots | wc -l`
|
||||||
[ "$linecount" -eq 5 ] || ret=1
|
[ "$linecount" -eq 10 ] || ret=1
|
||||||
n=`expr $n + 1`
|
n=`expr $n + 1`
|
||||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||||
status=`expr $status + $ret`
|
status=`expr $status + $ret`
|
||||||
@ -1654,26 +1654,88 @@ status=`expr $status + $ret`
|
|||||||
|
|
||||||
echo "I:checking positive and negative validation with negative trust anchors ($n)"
|
echo "I:checking positive and negative validation with negative trust anchors ($n)"
|
||||||
ret=0
|
ret=0
|
||||||
|
#
|
||||||
# check correct initial behavior
|
# check correct initial behavior
|
||||||
|
#
|
||||||
$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
|
$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
|
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
|
$DIG $DIGOPTS badds.example. soa @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
|
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
|
# 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
|
# 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.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
|
||||||
$DIG $DIGOPTS a.secure.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
|
||||||
grep "flags:[^;]* ad[^;]*;" 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
|
||||||
echo "I: waiting for NTA expiration"
|
grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1
|
||||||
sleep 15
|
$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
|
||||||
# check correct behavior after expiry
|
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1
|
||||||
$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
|
$DIG $DIGOPTS a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1
|
||||||
grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1
|
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1
|
||||||
$DIG $DIGOPTS b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
|
echo "I: dumping secroots"
|
||||||
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null || ret=1
|
$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`
|
n=`expr $n + 1`
|
||||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||||
status=`expr $status + $ret`
|
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> max-refresh-time <replaceable>number</replaceable> ; </optional>
|
||||||
<optional> min-retry-time <replaceable>number</replaceable> ; </optional>
|
<optional> min-retry-time <replaceable>number</replaceable> ; </optional>
|
||||||
<optional> max-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> port <replaceable>ip_port</replaceable>; </optional>
|
||||||
<optional> dscp <replaceable>ip_dscp</replaceable></optional> ;
|
<optional> dscp <replaceable>ip_dscp</replaceable></optional> ;
|
||||||
<optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
|
<optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
|
||||||
@ -5746,6 +5748,69 @@ options {
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><command>max-zone-ttl</command></term>
|
<term><command>max-zone-ttl</command></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -783,6 +783,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
|||||||
const char *str;
|
const char *str;
|
||||||
dns_name_t *name;
|
dns_name_t *name;
|
||||||
isc_buffer_t b;
|
isc_buffer_t b;
|
||||||
|
isc_uint32_t lifetime;
|
||||||
|
|
||||||
static intervaltable intervals[] = {
|
static intervaltable intervals[] = {
|
||||||
{ "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
{ "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)
|
if (tresult != ISC_R_SUCCESS)
|
||||||
result = tresult;
|
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);
|
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);
|
result = isc_task_create(taskmgr, 1, &dbtask);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_db;
|
goto cleanup_db;
|
||||||
|
|
||||||
|
isc_task_setname(dbtask, "cache_dbtask", NULL);
|
||||||
dns_db_settask(cache->db, dbtask);
|
dns_db_settask(cache->db, dbtask);
|
||||||
isc_task_detach(&dbtask);
|
isc_task_detach(&dbtask);
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,31 @@
|
|||||||
* DNSSEC validation.
|
* DNSSEC validation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <isc/buffer.h>
|
||||||
#include <isc/lang.h>
|
#include <isc/lang.h>
|
||||||
#include <isc/magic.h>
|
#include <isc/magic.h>
|
||||||
#include <isc/refcount.h>
|
#include <isc/refcount.h>
|
||||||
#include <isc/rwlock.h>
|
#include <isc/rwlock.h>
|
||||||
#include <isc/stdtime.h>
|
#include <isc/stdtime.h>
|
||||||
|
#include <isc/task.h>
|
||||||
|
#include <isc/timer.h>
|
||||||
|
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
#include <dns/rdataset.h>
|
||||||
|
#include <dns/resolver.h>
|
||||||
|
#include <dns/view.h>
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
struct dns_ntatable {
|
struct dns_ntatable {
|
||||||
/* Unlocked. */
|
/* Unlocked. */
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
isc_mem_t *mctx;
|
dns_view_t *view;
|
||||||
isc_rwlock_t rwlock;
|
isc_rwlock_t rwlock;
|
||||||
|
isc_uint32_t recheck;
|
||||||
|
isc_taskmgr_t *taskmgr;
|
||||||
|
isc_timermgr_t *timermgr;
|
||||||
|
isc_task_t *task;
|
||||||
/* Locked by rwlock. */
|
/* Locked by rwlock. */
|
||||||
isc_uint32_t references;
|
isc_uint32_t references;
|
||||||
dns_rbt_t *table;
|
dns_rbt_t *table;
|
||||||
@ -51,23 +61,18 @@ struct dns_ntatable {
|
|||||||
#define NTATABLE_MAGIC ISC_MAGIC('N', 'T', 'A', 't')
|
#define NTATABLE_MAGIC ISC_MAGIC('N', 'T', 'A', 't')
|
||||||
#define VALID_NTATABLE(nt) ISC_MAGIC_VALID(nt, NTATABLE_MAGIC)
|
#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
|
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:
|
* 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
|
*\li ntatablep != NULL && *ntatablep == NULL
|
||||||
*
|
*
|
||||||
@ -116,10 +121,13 @@ dns_ntatable_detach(dns_ntatable_t **ntatablep);
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
|
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',
|
* 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:
|
* Notes:
|
||||||
*
|
*
|
||||||
@ -191,15 +199,15 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
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
|
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
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ typedef struct dns_fetchevent {
|
|||||||
#define DNS_FETCHOPT_WANTNSID 0x080 /*%< Request NSID */
|
#define DNS_FETCHOPT_WANTNSID 0x080 /*%< Request NSID */
|
||||||
#define DNS_FETCHOPT_PREFETCH 0x100 /*%< Do prefetch */
|
#define DNS_FETCHOPT_PREFETCH 0x100 /*%< Do prefetch */
|
||||||
#define DNS_FETCHOPT_NOCDFLAG 0x200 /*%< Don't set CD flag. */
|
#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 */
|
/* Reserved in use by adb.c 0x00400000 */
|
||||||
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
|
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
|
||||||
|
@ -174,6 +174,7 @@ struct dns_validator {
|
|||||||
#define DNS_VALIDATOR_DLV 0x0001U
|
#define DNS_VALIDATOR_DLV 0x0001U
|
||||||
#define DNS_VALIDATOR_DEFER 0x0002U
|
#define DNS_VALIDATOR_DEFER 0x0002U
|
||||||
#define DNS_VALIDATOR_NOCDFLAG 0x0004U
|
#define DNS_VALIDATOR_NOCDFLAG 0x0004U
|
||||||
|
#define DNS_VALIDATOR_NONTA 0x0008U /*% Ignore NTA table */
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
@ -152,6 +152,8 @@ struct dns_view {
|
|||||||
isc_boolean_t requestsit;
|
isc_boolean_t requestsit;
|
||||||
dns_ttl_t maxcachettl;
|
dns_ttl_t maxcachettl;
|
||||||
dns_ttl_t maxncachettl;
|
dns_ttl_t maxncachettl;
|
||||||
|
isc_uint32_t nta_lifetime;
|
||||||
|
isc_uint32_t nta_recheck;
|
||||||
dns_ttl_t prefetch_trigger;
|
dns_ttl_t prefetch_trigger;
|
||||||
dns_ttl_t prefetch_eligible;
|
dns_ttl_t prefetch_eligible;
|
||||||
in_port_t dstport;
|
in_port_t dstport;
|
||||||
@ -1076,7 +1078,8 @@ dns_view_iscacheshared(dns_view_t *view);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
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.
|
* 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
|
isc_result_t
|
||||||
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
|
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
|
* Is 'name' at or beneath a trusted key, and not covered by a valid
|
||||||
* negative trust anchor? Put answer in '*secure_domain'.
|
* 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:
|
* Requires:
|
||||||
* \li 'view' is valid.
|
* \li 'view' is valid.
|
||||||
*
|
*
|
||||||
|
344
lib/dns/nta.c
344
lib/dns/nta.c
@ -18,20 +18,42 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <isc/buffer.h>
|
||||||
#include <isc/log.h>
|
#include <isc/log.h>
|
||||||
#include <isc/mem.h>
|
#include <isc/mem.h>
|
||||||
#include <isc/rwlock.h>
|
#include <isc/rwlock.h>
|
||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
|
#include <isc/task.h>
|
||||||
#include <isc/time.h>
|
#include <isc/time.h>
|
||||||
|
#include <isc/timer.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#include <dns/db.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
#include <dns/nta.h>
|
#include <dns/nta.h>
|
||||||
#include <dns/fixedname.h>
|
#include <dns/fixedname.h>
|
||||||
#include <dns/name.h>
|
#include <dns/name.h>
|
||||||
#include <dns/rbt.h>
|
#include <dns/rbt.h>
|
||||||
|
#include <dns/rdataset.h>
|
||||||
|
#include <dns/resolver.h>
|
||||||
#include <dns/result.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
|
static void
|
||||||
nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
||||||
unsigned int refs;
|
unsigned int refs;
|
||||||
@ -42,7 +64,22 @@ nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
|
|||||||
*ntap = NULL;
|
*ntap = NULL;
|
||||||
isc_refcount_decrement(&nta->refcount, &refs);
|
isc_refcount_decrement(&nta->refcount, &refs);
|
||||||
if (refs == 0) {
|
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);
|
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));
|
isc_mem_put(mctx, nta, sizeof(dns_nta_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,32 +93,41 @@ free_nta(void *data, void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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;
|
dns_ntatable_t *ntatable;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
/*
|
|
||||||
* Create an NTA table.
|
|
||||||
*/
|
|
||||||
|
|
||||||
REQUIRE(ntatablep != NULL && *ntatablep == NULL);
|
REQUIRE(ntatablep != NULL && *ntatablep == NULL);
|
||||||
|
|
||||||
ntatable = isc_mem_get(mctx, sizeof(*ntatable));
|
ntatable = isc_mem_get(view->mctx, sizeof(*ntatable));
|
||||||
if (ntatable == NULL)
|
if (ntatable == NULL)
|
||||||
return (ISC_R_NOMEMORY);
|
return (ISC_R_NOMEMORY);
|
||||||
|
|
||||||
ntatable->table = NULL;
|
ntatable->task = NULL;
|
||||||
result = dns_rbt_create(mctx, free_nta, mctx, &ntatable->table);
|
result = isc_task_create(taskmgr, 0, &ntatable->task);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_ntatable;
|
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);
|
result = isc_rwlock_init(&ntatable->rwlock, 0, 0);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_rbt;
|
goto cleanup_rbt;
|
||||||
|
|
||||||
ntatable->mctx = NULL;
|
ntatable->timermgr = timermgr;
|
||||||
isc_mem_attach(mctx, &ntatable->mctx);
|
ntatable->taskmgr = taskmgr;
|
||||||
|
|
||||||
|
ntatable->view = view;
|
||||||
ntatable->references = 1;
|
ntatable->references = 1;
|
||||||
|
|
||||||
ntatable->magic = NTATABLE_MAGIC;
|
ntatable->magic = NTATABLE_MAGIC;
|
||||||
*ntatablep = ntatable;
|
*ntatablep = ntatable;
|
||||||
|
|
||||||
@ -90,8 +136,11 @@ dns_ntatable_create(isc_mem_t *mctx, dns_ntatable_t **ntatablep) {
|
|||||||
cleanup_rbt:
|
cleanup_rbt:
|
||||||
dns_rbt_destroy(&ntatable->table);
|
dns_rbt_destroy(&ntatable->table);
|
||||||
|
|
||||||
|
cleanup_task:
|
||||||
|
isc_task_detach(&ntatable->task);
|
||||||
|
|
||||||
cleanup_ntatable:
|
cleanup_ntatable:
|
||||||
isc_mem_put(mctx, ntatable, sizeof(*ntatable));
|
isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -132,43 +181,187 @@ dns_ntatable_detach(dns_ntatable_t **ntatablep) {
|
|||||||
if (destroy) {
|
if (destroy) {
|
||||||
dns_rbt_destroy(&ntatable->table);
|
dns_rbt_destroy(&ntatable->table);
|
||||||
isc_rwlock_destroy(&ntatable->rwlock);
|
isc_rwlock_destroy(&ntatable->rwlock);
|
||||||
|
if (ntatable->task != NULL)
|
||||||
|
isc_task_detach(&ntatable->task);
|
||||||
|
ntatable->timermgr = NULL;
|
||||||
|
ntatable->taskmgr = NULL;
|
||||||
ntatable->magic = 0;
|
ntatable->magic = 0;
|
||||||
isc_mem_putanddetach(&ntatable->mctx,
|
isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
|
||||||
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
|
isc_result_t
|
||||||
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
|
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;
|
isc_result_t result;
|
||||||
dns_nta_t *nta = NULL;
|
dns_nta_t *nta = NULL;
|
||||||
dns_rbtnode_t *node;
|
dns_rbtnode_t *node;
|
||||||
|
dns_view_t *view;
|
||||||
|
|
||||||
REQUIRE(VALID_NTATABLE(ntatable));
|
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)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
nta->expiry = expiry;
|
nta->expiry = now + lifetime;
|
||||||
|
|
||||||
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
|
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
|
||||||
|
|
||||||
node = NULL;
|
node = NULL;
|
||||||
result = dns_rbt_addnode(ntatable->table, name, &node);
|
result = dns_rbt_addnode(ntatable->table, name, &node);
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
if (!force)
|
||||||
|
(void)settimer(ntatable, nta, lifetime);
|
||||||
node->data = nta;
|
node->data = nta;
|
||||||
nta = NULL;
|
nta = NULL;
|
||||||
} else if (result == ISC_R_EXISTS) {
|
} else if (result == ISC_R_EXISTS) {
|
||||||
dns_nta_t *n = node->data;
|
dns_nta_t *n = node->data;
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
|
if (!force)
|
||||||
|
(void)settimer(ntatable, nta, lifetime);
|
||||||
node->data = nta;
|
node->data = nta;
|
||||||
nta = NULL;
|
nta = NULL;
|
||||||
} else {
|
} else {
|
||||||
n->expiry = nta->expiry;
|
n->expiry = nta->expiry;
|
||||||
nta_detach(ntatable->mctx, &nta);
|
nta_detach(view->mctx, &nta);
|
||||||
}
|
}
|
||||||
result = ISC_R_SUCCESS;
|
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);
|
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
|
||||||
|
|
||||||
if (nta != NULL)
|
if (nta != NULL)
|
||||||
nta_detach(ntatable->mctx, &nta);
|
nta_detach(view->mctx, &nta);
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -268,6 +461,13 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
|||||||
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
|
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
|
||||||
"deleting expired NTA at %s", nb);
|
"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);
|
result = delete(ntatable, foundname);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
|
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
|
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;
|
isc_result_t result;
|
||||||
dns_rbtnode_t *node;
|
dns_rbtnode_t *node;
|
||||||
dns_rbtnodechain_t chain;
|
dns_rbtnodechain_t chain;
|
||||||
|
isc_boolean_t first = ISC_TRUE;
|
||||||
|
isc_stdtime_t now;
|
||||||
|
|
||||||
REQUIRE(VALID_NTATABLE(ntatable));
|
REQUIRE(VALID_NTATABLE(ntatable));
|
||||||
|
|
||||||
|
isc_stdtime_get(&now);
|
||||||
|
|
||||||
RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
|
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);
|
result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL);
|
||||||
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
|
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -300,15 +504,80 @@ dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
|
|||||||
if (node->data != NULL) {
|
if (node->data != NULL) {
|
||||||
dns_nta_t *n = (dns_nta_t *) node->data;
|
dns_nta_t *n = (dns_nta_t *) node->data;
|
||||||
char nbuf[DNS_NAME_FORMATSIZE], tbuf[80];
|
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;
|
isc_time_t t;
|
||||||
|
|
||||||
dns_name_init(&name, NULL);
|
dns_fixedname_init(&fn);
|
||||||
dns_rbt_namefromnode(node, &name);
|
name = dns_fixedname_name(&fn);
|
||||||
dns_name_format(&name, nbuf, sizeof(nbuf));
|
dns_rbt_fullnamefromnode(node, name);
|
||||||
|
dns_name_format(name, nbuf, sizeof(nbuf));
|
||||||
isc_time_set(&t, n->expiry, 0);
|
isc_time_set(&t, n->expiry, 0);
|
||||||
isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
|
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);
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
||||||
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
|
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);
|
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
|
||||||
return (result);
|
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
|
static isc_result_t
|
||||||
issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
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;
|
dns_name_t suffix;
|
||||||
unsigned int labels;
|
unsigned int labels;
|
||||||
@ -1841,7 +1842,7 @@ issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||||||
name = &suffix;
|
name = &suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (dns_view_issecuredomain(view, name, now, issecure));
|
return (dns_view_issecuredomain(view, name, now, checknta, issecure));
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
@ -1944,10 +1945,13 @@ resquery_send(resquery_t *query) {
|
|||||||
else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0)
|
else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0)
|
||||||
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
|
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
|
||||||
else if (res->view->enablevalidation &&
|
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,
|
result = issecuredomain(res->view, &fctx->name,
|
||||||
fctx->type, query->start.seconds,
|
fctx->type, query->start.seconds,
|
||||||
&secure_domain);
|
checknta, &secure_domain);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
secure_domain = ISC_FALSE;
|
secure_domain = ISC_FALSE;
|
||||||
if (res->view->dlv != NULL)
|
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_task_t *task;
|
||||||
isc_boolean_t fail;
|
isc_boolean_t fail;
|
||||||
unsigned int valoptions = 0;
|
unsigned int valoptions = 0;
|
||||||
|
isc_boolean_t checknta = ISC_TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The appropriate bucket lock must be held.
|
* 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?
|
* 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) {
|
if (res->view->enablevalidation) {
|
||||||
result = issecuredomain(res->view, name, fctx->type,
|
result = issecuredomain(res->view, name, fctx->type,
|
||||||
now, &secure_domain);
|
now, checknta, &secure_domain);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
if (!secure_domain && res->view->dlv != NULL) {
|
if (!secure_domain && res->view->dlv != NULL) {
|
||||||
valoptions = DNS_VALIDATOR_DLV;
|
valoptions |= DNS_VALIDATOR_DLV;
|
||||||
secure_domain = ISC_TRUE;
|
secure_domain = ISC_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5362,6 +5372,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
|||||||
dns_fetchevent_t *event;
|
dns_fetchevent_t *event;
|
||||||
isc_uint32_t ttl;
|
isc_uint32_t ttl;
|
||||||
unsigned int valoptions = 0;
|
unsigned int valoptions = 0;
|
||||||
|
isc_boolean_t checknta = ISC_TRUE;
|
||||||
|
|
||||||
FCTXTRACE("ncache_message");
|
FCTXTRACE("ncache_message");
|
||||||
|
|
||||||
@ -5384,14 +5395,19 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
|||||||
/*
|
/*
|
||||||
* Is DNSSEC validation required for this name?
|
* 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) {
|
if (fctx->res->view->enablevalidation) {
|
||||||
result = issecuredomain(res->view, name, fctx->type,
|
result = issecuredomain(res->view, name, fctx->type,
|
||||||
now, &secure_domain);
|
now, checknta, &secure_domain);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
if (!secure_domain && res->view->dlv != NULL) {
|
if (!secure_domain && res->view->dlv != NULL) {
|
||||||
valoptions = DNS_VALIDATOR_DLV;
|
valoptions |= DNS_VALIDATOR_DLV;
|
||||||
secure_domain = ISC_TRUE;
|
secure_domain = ISC_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8275,6 +8291,7 @@ dns_resolver_create(dns_view_t *view,
|
|||||||
result = isc_task_create(taskmgr, 0, &task);
|
result = isc_task_create(taskmgr, 0, &task);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup_primelock;
|
goto cleanup_primelock;
|
||||||
|
isc_task_setname(task, "resolver_task", NULL);
|
||||||
|
|
||||||
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
||||||
task, spillattimer_countdown, res,
|
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 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
|
* Test utilities. In general, these assume input parameters are valid
|
||||||
* (checking with ATF_REQUIRE_EQ, thus aborting if not) and unlikely run time
|
* (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 */
|
/* Common setup: create a keytable and ntatable to test with a few keys */
|
||||||
static void
|
static void
|
||||||
create_tables() {
|
create_tables() {
|
||||||
|
isc_result_t result;
|
||||||
dst_key_t *key = NULL;
|
dst_key_t *key = NULL;
|
||||||
isc_stdtime_t now;
|
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_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 */
|
/* Add a normal key */
|
||||||
create_key(257, 3, 5, "example.com", keystr1, &key);
|
create_key(257, 3, 5, "example.com", keystr1, &key);
|
||||||
@ -139,7 +146,7 @@ create_tables() {
|
|||||||
isc_stdtime_get(&now);
|
isc_stdtime_get(&now);
|
||||||
ATF_REQUIRE_EQ(dns_ntatable_add(ntatable,
|
ATF_REQUIRE_EQ(dns_ntatable_add(ntatable,
|
||||||
str2name("insecure.example"),
|
str2name("insecure.example"),
|
||||||
now + 3600),
|
ISC_FALSE, now, 3600),
|
||||||
ISC_R_SUCCESS);
|
ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +156,8 @@ destroy_tables() {
|
|||||||
dns_ntatable_detach(&ntatable);
|
dns_ntatable_detach(&ntatable);
|
||||||
if (keytable != NULL)
|
if (keytable != NULL)
|
||||||
dns_keytable_detach(&keytable);
|
dns_keytable_detach(&keytable);
|
||||||
|
|
||||||
|
dns_view_detach(&view);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -167,7 +176,7 @@ ATF_TC_BODY(add, tc) {
|
|||||||
|
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -246,7 +255,7 @@ ATF_TC_HEAD(delete, tc) {
|
|||||||
ATF_TC_BODY(delete, tc) {
|
ATF_TC_BODY(delete, tc) {
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/* dns_keytable_delete requires exact match */
|
/* dns_keytable_delete requires exact match */
|
||||||
@ -279,7 +288,7 @@ ATF_TC_BODY(deletekeynode, tc) {
|
|||||||
|
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/* key name doesn't match */
|
/* key name doesn't match */
|
||||||
@ -340,7 +349,7 @@ ATF_TC_BODY(find, tc) {
|
|||||||
|
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -432,7 +441,7 @@ ATF_TC_BODY(issecuredomain, tc) {
|
|||||||
"null.example", "sub.null.example", NULL};
|
"null.example", "sub.null.example", NULL};
|
||||||
|
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -476,7 +485,7 @@ ATF_TC_HEAD(dump, tc) {
|
|||||||
ATF_TC_BODY(dump, tc) {
|
ATF_TC_BODY(dump, tc) {
|
||||||
UNUSED(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();
|
create_tables();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -508,12 +517,15 @@ ATF_TC_BODY(nta, tc) {
|
|||||||
result = dns_test_makeview("view", &view);
|
result = dns_test_makeview("view", &view);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
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);
|
result = dns_view_initsecroots(view, mctx);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
result = dns_view_getsecroots(view, &keytable);
|
result = dns_view_getsecroots(view, &keytable);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
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);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
result = dns_view_getntatable(view, &ntatable);
|
result = dns_view_getntatable(view, &ntatable);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
@ -524,20 +536,21 @@ ATF_TC_BODY(nta, tc) {
|
|||||||
|
|
||||||
isc_stdtime_get(&now);
|
isc_stdtime_get(&now);
|
||||||
result = dns_ntatable_add(ntatable,
|
result = dns_ntatable_add(ntatable,
|
||||||
str2name("insecure.example"), now + 1);
|
str2name("insecure.example"),
|
||||||
|
ISC_FALSE, now, 1);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
/* Should be secure */
|
/* Should be secure */
|
||||||
result = dns_view_issecuredomain(view,
|
result = dns_view_issecuredomain(view,
|
||||||
str2name("test.secure.example"),
|
str2name("test.secure.example"),
|
||||||
now, &issecure);
|
now, ISC_TRUE, &issecure);
|
||||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||||
ATF_CHECK(issecure);
|
ATF_CHECK(issecure);
|
||||||
|
|
||||||
/* Should not be secure */
|
/* Should not be secure */
|
||||||
result = dns_view_issecuredomain(view,
|
result = dns_view_issecuredomain(view,
|
||||||
str2name("test.insecure.example"),
|
str2name("test.insecure.example"),
|
||||||
now, &issecure);
|
now, ISC_TRUE, &issecure);
|
||||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||||
ATF_CHECK(!issecure);
|
ATF_CHECK(!issecure);
|
||||||
|
|
||||||
@ -554,17 +567,17 @@ ATF_TC_BODY(nta, tc) {
|
|||||||
/* As of now + 2, the NTA should be clear */
|
/* As of now + 2, the NTA should be clear */
|
||||||
result = dns_view_issecuredomain(view,
|
result = dns_view_issecuredomain(view,
|
||||||
str2name("test.insecure.example"),
|
str2name("test.insecure.example"),
|
||||||
now + 2, &issecure);
|
now + 2, ISC_TRUE, &issecure);
|
||||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||||
ATF_CHECK(issecure);
|
ATF_CHECK(issecure);
|
||||||
|
|
||||||
/* Now check deletion */
|
/* Now check deletion */
|
||||||
result = dns_ntatable_add(ntatable,
|
result = dns_ntatable_add(ntatable, str2name("new.example"),
|
||||||
str2name("new.example"), now + 3600);
|
ISC_FALSE, now, 3600);
|
||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
||||||
now, &issecure);
|
now, ISC_TRUE, &issecure);
|
||||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||||
ATF_CHECK(!issecure);
|
ATF_CHECK(!issecure);
|
||||||
|
|
||||||
@ -572,7 +585,7 @@ ATF_TC_BODY(nta, tc) {
|
|||||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
result = dns_view_issecuredomain(view, str2name("test.new.example"),
|
||||||
now, &issecure);
|
now, ISC_TRUE, &issecure);
|
||||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||||
ATF_CHECK(issecure);
|
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)
|
if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0)
|
||||||
fopts |= DNS_FETCHOPT_NOCDFLAG;
|
fopts |= DNS_FETCHOPT_NOCDFLAG;
|
||||||
|
|
||||||
|
if ((val->options & DNS_VALIDATOR_NONTA) != 0)
|
||||||
|
fopts |= DNS_FETCHOPT_NONTA;
|
||||||
|
|
||||||
validator_logcreate(val, name, type, caller, "fetch");
|
validator_logcreate(val, name, type, caller, "fetch");
|
||||||
return (dns_resolver_createfetch(val->view->resolver, name, type,
|
return (dns_resolver_createfetch(val->view->resolver, name, type,
|
||||||
NULL, NULL, NULL, fopts,
|
NULL, NULL, NULL, fopts,
|
||||||
@ -3164,7 +3167,8 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
return (DNS_R_NOVALIDSIG);
|
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);
|
return (DNS_R_NTACOVERED);
|
||||||
|
|
||||||
while (dns_name_countlabels(dlvname) >=
|
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->provideixfr = ISC_TRUE;
|
||||||
view->maxcachettl = 7 * 24 * 3600;
|
view->maxcachettl = 7 * 24 * 3600;
|
||||||
view->maxncachettl = 3 * 3600;
|
view->maxncachettl = 3 * 3600;
|
||||||
|
view->nta_lifetime = 0;
|
||||||
|
view->nta_recheck = 0;
|
||||||
view->prefetch_eligible = 0;
|
view->prefetch_eligible = 0;
|
||||||
view->prefetch_trigger = 0;
|
view->prefetch_trigger = 0;
|
||||||
view->dstport = 53;
|
view->dstport = 53;
|
||||||
@ -1776,11 +1778,14 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
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));
|
REQUIRE(DNS_VIEW_VALID(view));
|
||||||
if (view->ntatable_priv != NULL)
|
if (view->ntatable_priv != NULL)
|
||||||
dns_ntatable_detach(&view->ntatable_priv);
|
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
|
isc_result_t
|
||||||
@ -1825,7 +1830,8 @@ dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
|
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_result_t result;
|
||||||
isc_boolean_t secure = ISC_FALSE;
|
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)
|
if (result != ISC_R_SUCCESS)
|
||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
if (secure && view->ntatable_priv != NULL &&
|
if (checknta && secure && view->ntatable_priv != NULL &&
|
||||||
dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
|
dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
|
||||||
secure = ISC_FALSE;
|
secure = ISC_FALSE;
|
||||||
|
|
||||||
|
@ -483,7 +483,6 @@ dns_nsec_isset
|
|||||||
dns_nsec_nseconly
|
dns_nsec_nseconly
|
||||||
dns_nsec_setbit
|
dns_nsec_setbit
|
||||||
dns_nsec_typepresent
|
dns_nsec_typepresent
|
||||||
dns_nta_create
|
|
||||||
dns_ntatable_add
|
dns_ntatable_add
|
||||||
dns_ntatable_attach
|
dns_ntatable_attach
|
||||||
dns_ntatable_covered
|
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_sockaddr4wild;
|
||||||
static cfg_type_t cfg_type_sockaddr6wild;
|
static cfg_type_t cfg_type_sockaddr6wild;
|
||||||
static cfg_type_t cfg_type_statschannels;
|
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_view;
|
||||||
static cfg_type_t cfg_type_viewopts;
|
static cfg_type_t cfg_type_viewopts;
|
||||||
static cfg_type_t cfg_type_zone;
|
static cfg_type_t cfg_type_zone;
|
||||||
@ -1544,6 +1545,8 @@ view_clauses[] = {
|
|||||||
{ "max-udp-size", &cfg_type_uint32, 0 },
|
{ "max-udp-size", &cfg_type_uint32, 0 },
|
||||||
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
|
{ "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
|
||||||
{ "minimal-responses", &cfg_type_boolean, 0 },
|
{ "minimal-responses", &cfg_type_boolean, 0 },
|
||||||
|
{ "nta-recheck", &cfg_type_ttlval, 0 },
|
||||||
|
{ "nta-lifetime", &cfg_type_ttlval, 0 },
|
||||||
{ "prefetch", &cfg_type_prefetch, 0 },
|
{ "prefetch", &cfg_type_prefetch, 0 },
|
||||||
{ "preferred-glue", &cfg_type_astring, 0 },
|
{ "preferred-glue", &cfg_type_astring, 0 },
|
||||||
{ "no-case-compress", &cfg_type_bracketed_aml, 0 },
|
{ "no-case-compress", &cfg_type_bracketed_aml, 0 },
|
||||||
@ -3182,7 +3185,7 @@ static cfg_type_t cfg_type_masterselement = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static isc_result_t
|
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;
|
isc_result_t result;
|
||||||
cfg_obj_t *obj = NULL;
|
cfg_obj_t *obj = NULL;
|
||||||
isc_uint32_t ttl;
|
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 = {
|
static cfg_type_t cfg_type_ttlval = {
|
||||||
"maxttlval", parse_maxttlval, cfg_print_uint64, cfg_doc_terminal,
|
"ttlval", parse_ttlval, cfg_print_uint64, cfg_doc_terminal,
|
||||||
&cfg_rep_uint64, NULL };
|
&cfg_rep_uint64, NULL
|
||||||
|
};
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
parse_maxttl(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
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