[master] rndc nta

3867.	[func]		"rndc nta" can now be used to set a temporary
			negative trust anchor, which disables DNSSEC
			validation below a specified name for a specified
			period of time (not exceeding 24 hours).  This
			can be used when validation for a domain is known
			to be failing due to a configuration error on
			the part of the domain owner rather than a
			spoofing attack. [RT #29358]
This commit is contained in:
Evan Hunt 2014-05-29 22:22:53 -07:00
parent fa6308bd57
commit 0cfb247368
34 changed files with 1636 additions and 43 deletions

View file

@ -1,3 +1,12 @@
3867. [func] "rndc nta" can now be used to set a temporary
negative trust anchor, which disables DNSSEC
validation below a specified name for a specified
period of time (not exceeding 24 hours). This
can be used when validation for a domain is known
to be failing due to a configuration error on
the part of the domain owner rather than a
spoofing attack. [RT #29358]
3866. [bug] Named could die on disk full in generate_session_key.
[RT #36119]

View file

@ -213,6 +213,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
result = ns_server_signing(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {
result = ns_server_zonestatus(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_NTA)) {
result = ns_server_nta(ns_g_server, command, text);
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,

View file

@ -67,6 +67,7 @@
#define NS_COMMAND_SYNC "sync"
#define NS_COMMAND_SIGNING "signing"
#define NS_COMMAND_ZONESTATUS "zonestatus"
#define NS_COMMAND_NTA "nta"
isc_result_t
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);

View file

@ -392,4 +392,11 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text);
*/
isc_result_t
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t *text);
/*%
* Adds a Negative Trust Anchor (NTA) for a specified name and
* duration, in a particular view if specified, or in all views.
*/
isc_result_t
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text);
#endif /* NAMED_SERVER_H */

View file

@ -78,6 +78,7 @@
#include <dns/lib.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/nta.h>
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/portlist.h>
@ -94,6 +95,7 @@
#include <dns/stats.h>
#include <dns/tkey.h>
#include <dns/tsig.h>
#include <dns/ttl.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
@ -824,6 +826,14 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
return (ISC_R_UNEXPECTED);
}
result = dns_view_initntatable(view, mctx);
if (result != ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"couldn't create NTA table");
return (ISC_R_UNEXPECTED);
}
if (auto_dlv && view->rdclass == dns_rdataclass_in) {
const cfg_obj_t *builtin_keys = NULL;
const cfg_obj_t *builtin_managed_keys = NULL;
@ -9756,3 +9766,133 @@ ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t *text) {
dns_zone_detach(&zone);
return (result);
}
isc_result_t
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;
isc_stdtime_t now, when;
isc_time_t t;
char tbuf[64];
const char *msg = NULL;
dns_fixedname_t fn;
dns_name_t *ntaname;
dns_ttl_t ntattl;
isc_textregion_t tr;
dns_fixedname_init(&fn);
ntaname = dns_fixedname_name(&fn);
/* Skip the command name. */
ptr = next_token(&args, " \t");
if (ptr == NULL)
return (ISC_R_UNEXPECTEDEND);
/* Get the NTA name. */
nametext = next_token(&args, " \t");
if (nametext == NULL)
return (ISC_R_UNEXPECTEDEND);
if (strcmp(nametext, ".") == 0)
ntaname = dns_rootname;
else {
isc_buffer_t b;
isc_buffer_init(&b, nametext, strlen(nametext));
isc_buffer_add(&b, strlen(nametext));
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);
for (view = ISC_LIST_HEAD(server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link))
{
if (viewname != NULL &&
strcmp(view->name, viewname) != 0)
continue;
if (ntatable != NULL)
dns_ntatable_detach(&ntatable);
result = dns_view_getntatable(view, &ntatable);
if (result == ISC_R_NOTFOUND) {
result = ISC_R_SUCCESS;
continue;
}
result = dns_view_flushnode(view, ntaname, ISC_TRUE);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"flush tree '%s' in cache view '%s': %s",
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, when));
CHECK(putstr(text, "Negative trust anchor added: "));
CHECK(putstr(text, nametext));
CHECK(putstr(text, "/"));
CHECK(putstr(text, view->name));
CHECK(putstr(text, ", expires "));
CHECK(putstr(text, tbuf));
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"added NTA '%s' (%d sec) in view '%s'",
nametext, ntattl, view->name);
} else {
CHECK(dns_ntatable_delete(ntatable, ntaname));
CHECK(putstr(text, "Negative trust anchor removed: "));
CHECK(putstr(text, nametext));
CHECK(putstr(text, "/"));
CHECK(putstr(text, view->name));
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"removed NTA '%s' in view %s",
nametext, view->name);
}
if (isc_buffer_availablelength(text) == 0)
return (ISC_R_NOSPACE);
isc_buffer_putuint8(text, 0);
}
isc_task_endexclusive(server->task);
if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
isc_buffer_putstr(text, msg);
cleanup:
if (ntatable != NULL)
dns_ntatable_detach(&ntatable);
return (result);
}

View file

@ -596,6 +596,38 @@
</listitem>
</varlistentry>
<varlistentry>
<term><userinput>nta <replaceable>domain</replaceable> <replaceable>duration</replaceable> </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).
</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>
TTL-style suffixes can be used to specify
<option>duration</option> in seconds, minutes, or hours.
</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.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><userinput>tsig-list</userinput></term>
<listitem>

View file

@ -25,6 +25,7 @@ test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
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
cd ../ns3 && cp -f siginterval1.conf siginterval.conf
cd ../ns4 && cp -f named1.conf named.conf

View file

@ -1648,6 +1648,33 @@ ret=0
$DIG $DIGOPTS ns algroll. @10.53.0.4 > dig.out.ns4.test$n || ret=1
grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking positive and negative validation with negative trust anchors ($n)"
ret=0
# 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
# 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 /'
# 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
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`

View file

@ -10756,6 +10756,10 @@ rate-limit {
level are inherited by all views, but keys defined in a view
are only used within that view.
</para>
<para>
Validation below specified names can be temporarily disabled
by using <command>rndc nta</command>.
</para>
</sect2>
<sect2>

View file

@ -69,8 +69,8 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
iptable.@O@ journal.@O@ keydata.@O@ keytable.@O@ \
lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \
portlist.@O@ private.@O@ \
name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \
order.@O@ peer.@O@ portlist.@O@ private.@O@ \
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \
request.@O@ resolver.@O@ result.@O@ rootns.@O@ \
@ -106,7 +106,8 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \
dlz.c dns64.c dnssec.c ds.c forward.c geoip.c \
iptable.c journal.c keydata.c keytable.c lib.c log.c \
lookup.c master.c masterdump.c message.c \
name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \
name.c ncache.c nsec.c nsec3.c nta.c \
order.c peer.c portlist.c \
rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \
rdataset.c rdatasetiter.c rdataslab.c request.c \
resolver.c result.c rootns.c rpz.c rrl.c rriterator.c \

View file

@ -77,7 +77,8 @@
static dst_func_t *dst_t_func[DST_MAX_ALGS];
static isc_entropy_t *dst_entropy_pool = NULL;
static unsigned int dst_entropy_flags = 0;
static isc_boolean_t dst_initialized = ISC_FALSE;
isc_boolean_t dst_initialized = ISC_FALSE;
void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);

View file

@ -386,7 +386,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable,
isc_result_t
dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
isc_boolean_t *wantdnssecp);
dns_name_t *foundname, isc_boolean_t *wantdnssecp);
/*%<
* Is 'name' at or beneath a trusted key?
*
@ -396,12 +396,16 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
*
*\li 'name' is a valid absolute name.
*
*\li '*wantsdnssecp' is a valid isc_boolean_t.
*\li 'foundanme' is NULL or is a pointer to an initialized dns_name_t
*
*\li '*wantsdnssecp' is a valid isc_boolean_t.
* Ensures:
*
*\li On success, *wantsdnssecp will be ISC_TRUE if and only if 'name'
* is at or beneath a trusted key.
* is at or beneath a trusted key. If 'foundname' is not NULL, then
* it will be updated to contain the name of the closest enclosing
* trust anchor.
*
* Returns:
*

View file

@ -78,6 +78,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
#define DNS_LOGMODULE_DNSSEC (&dns_modules[27])
#define DNS_LOGMODULE_CRYPTO (&dns_modules[28])
#define DNS_LOGMODULE_PACKETS (&dns_modules[29])
#define DNS_LOGMODULE_NTA (&dns_modules[30])
ISC_LANG_BEGINDECLS

206
lib/dns/include/dns/nta.h Normal file
View file

@ -0,0 +1,206 @@
/*
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef DNS_NTA_H
#define DNS_NTA_H 1
/*****
***** Module Info
*****/
/*! \file
* \brief
* The NTA module provides services for storing and retrieving negative
* trust anchors, and determine whether a given domain is subject to
* DNSSEC validation.
*/
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/stdtime.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
struct dns_ntatable {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
isc_rwlock_t rwlock;
/* Locked by rwlock. */
isc_uint32_t references;
dns_rbt_t *table;
};
#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);
/*%<
* Create an NTA table.
*
* Requires:
*
*\li 'mctx' is a valid memory context.
*
*\li ntatablep != NULL && *ntatablep == NULL
*
* Ensures:
*
*\li On success, *ntatablep is a valid, empty NTA table.
*
* Returns:
*
*\li ISC_R_SUCCESS
*\li Any other result indicates failure.
*/
void
dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp);
/*%<
* Attach *targetp to source.
*
* Requires:
*
*\li 'source' is a valid ntatable.
*
*\li 'targetp' points to a NULL dns_ntatable_t *.
*
* Ensures:
*
*\li *targetp is attached to source.
*/
void
dns_ntatable_detach(dns_ntatable_t **ntatablep);
/*%<
* Detach *ntatablep from its ntatable.
*
* Requires:
*
*\li 'ntatablep' points to a valid ntatable.
*
* Ensures:
*
*\li *ntatablep is NULL.
*
*\li If '*ntatablep' is the last reference to the ntatable,
* all resources used by the ntatable will be freed
*/
isc_result_t
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
isc_uint32_t expiry);
/*%<
* Add a negative trust anchor to 'ntatable' for name 'name',
* which will expire at time 'expiry'.
*
* Notes:
*
*\li If an NTA already exists in the table, its expiry time
* is updated.
*
* Requires:
*
*\li 'ntatable' points to a valid ntatable.
*
*\li 'name' points to a valid name.
*
* Returns:
*
*\li ISC_R_SUCCESS
*
*\li Any other result indicates failure.
*/
isc_result_t
dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *keyname);
/*%<
* Delete node(s) from 'ntatable' matching name 'keyname'
*
* Requires:
*
*\li 'ntatable' points to a valid ntatable.
*
*\li 'name' is not NULL
*
* Returns:
*
*\li ISC_R_SUCCESS
*
*\li Any other result indicates failure.
*/
isc_result_t
dns_ntatable_deletenta(dns_ntatable_t *ntatable, dns_name_t *name);
/*%<
* Delete node from 'ntatable' matching the name 'name'
*
* Requires:
*
*\li 'ntatable' points to a valid ntatable.
*\li 'name' is a valid name.
*
* Returns:
*
*\li ISC_R_SUCCESS
*
*\li Any other result indicates failure.
*/
isc_boolean_t
dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
dns_name_t *name, dns_name_t *anchor);
/*%<
* Return ISC_TRUE if 'name' is below a non-expired negative trust
* anchor which in turn is at or below 'anchor'.
*
* If 'ntatable' has not been initialized, return ISC_FALSE.
*
* Requires:
*
*\li 'ntatable' is NULL or is a valid ntatable.
*
*\li 'name' is a valid absolute name.
*/
isc_result_t
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp);
/*%<
* Dump the NTA table on fp.
*/
isc_result_t
dns_nta_create(isc_mem_t *mctx, dns_nta_t **target);
/*%<
* Allocate space for an NTA
*/
ISC_LANG_ENDDECLS
#endif /* DNS_NTA_H */

View file

@ -153,8 +153,9 @@
#define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107)
#define DNS_R_NOTDYNAMIC (ISC_RESULTCLASS_DNS + 108)
#define DNS_R_BADEUI (ISC_RESULTCLASS_DNS + 109)
#define DNS_R_NTACOVERED (ISC_RESULTCLASS_DNS + 110)
#define DNS_R_NRESULTS 110 /*%< Number of results */
#define DNS_R_NRESULTS 111 /*%< Number of results */
/*
* DNS wire format rcodes.

View file

@ -99,6 +99,8 @@ typedef isc_region_t dns_label_t;
typedef struct dns_lookup dns_lookup_t;
typedef struct dns_name dns_name_t;
typedef ISC_LIST(dns_name_t) dns_namelist_t;
typedef struct dns_nta dns_nta_t;
typedef struct dns_ntatable dns_ntatable_t;
typedef isc_uint16_t dns_opcode_t;
typedef unsigned char dns_offsets_t[128];
typedef struct dns_order dns_order_t;

View file

@ -165,6 +165,7 @@ struct dns_validator {
unsigned int depth;
unsigned int authcount;
unsigned int authfail;
isc_stdtime_t start;
};
/*%

View file

@ -98,10 +98,11 @@ struct dns_view {
dns_db_t * hints;
/*
* security roots.
* security roots and negative trust anchors.
* internal use only; access via * dns_view_getsecroots()
*/
dns_keytable_t * secroots_priv;
dns_ntatable_t * ntatable_priv;
isc_mutex_t lock;
isc_boolean_t frozen;
@ -1075,16 +1076,48 @@ dns_view_iscacheshared(dns_view_t *view);
*/
isc_result_t
dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx);
dns_view_initntatable(dns_view_t *view, isc_mem_t *mctx);
/*%<
* Initialize security roots for the view. (Note that secroots is
* NULL until this function is called, so any function using
* secroots must check its validity first. One way to do this is
* use dns_view_getsecroots() and check its return value.)
* Initialize the negative trust anchor table for the view.
*
* Requires:
* \li 'view' is valid.
*
* Returns:
*\li ISC_R_SUCCESS
*\li Any other result indicates failure
*/
isc_result_t
dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp);
/*%<
* Get the negative trust anchor table for this view. Returns
* ISC_R_NOTFOUND if the table not been initialized for the view.
*
* '*ntp' is attached on success; the caller is responsible for
* detaching it with dns_ntatable_detach().
*
* Requires:
* \li 'view' is valid.
* \li 'nta' is not NULL and '*nta' is NULL.
*
* Returns:
*\li ISC_R_SUCCESS
*\li ISC_R_NOTFOUND
*/
isc_result_t
dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx);
/*%<
* Initialize security roots for the view, detaching any previously
* existing security roots first. (Note that secroots_priv is
* NULL until this function is called, so any function using
* security roots must check that they have been initialized first.
* One way to do this is use dns_view_getsecroots() and check its
* return value.)
*
* Requires:
* \li 'view' is valid.
* \li 'view->secroots' is NULL.
*
* Returns:
*\li ISC_R_SUCCESS
@ -1111,10 +1144,10 @@ 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_boolean_t *secure_domain);
isc_stdtime_t now, isc_boolean_t *secure_domain);
/*%<
* Is 'name' at or beneath a trusted key? Put answer in
* '*secure_domain'.
* Is 'name' at or beneath a trusted key, and not covered by a valid
* negative trust anchor? Put answer in '*secure_domain'.
*
* Requires:
* \li 'view' is valid.
@ -1124,6 +1157,20 @@ dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
*\li Any other value indicates failure
*/
isc_boolean_t
dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
dns_name_t *name, dns_name_t *anchor);
/*%<
* Is there a current negative trust anchor above 'name' and below 'anchor'?
*
* Requires:
* \li 'view' is valid.
*
* Returns:
*\li ISC_R_TRUE
*\li ISC_R_FALSE
*/
void
dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);

View file

@ -524,10 +524,10 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
isc_result_t
dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
isc_boolean_t *wantdnssecp)
dns_name_t *foundname, isc_boolean_t *wantdnssecp)
{
isc_result_t result;
void *data;
dns_rbtnode_t *node = NULL;
/*
* Is 'name' at or beneath a trusted key?
@ -539,11 +539,10 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
data = NULL;
result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
result = dns_rbt_findnode(keytable->table, name, foundname, &node,
NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
INSIST(data != NULL);
INSIST(node->data != NULL);
*wantdnssecp = ISC_TRUE;
result = ISC_R_SUCCESS;
} else if (result == ISC_R_NOTFOUND) {

View file

@ -84,6 +84,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
{ "dns/dnssec", 0 },
{ "dns/crypto", 0 },
{ "dns/packets", 0 },
{ "dns/nta", 0 },
{ NULL, 0 }
};

350
lib/dns/nta.c Normal file
View file

@ -0,0 +1,350 @@
/*
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*! \file */
#include <config.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/rwlock.h>
#include <isc/string.h>
#include <isc/time.h>
#include <isc/util.h>
#include <dns/log.h>
#include <dns/nta.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rbt.h>
#include <dns/result.h>
static void
nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
unsigned int refs;
dns_nta_t *nta = *ntap;
REQUIRE(VALID_NTA(nta));
*ntap = NULL;
isc_refcount_decrement(&nta->refcount, &refs);
if (refs == 0) {
isc_refcount_destroy(&nta->refcount);
isc_mem_put(mctx, nta, sizeof(dns_nta_t));
}
}
static void
free_nta(void *data, void *arg) {
dns_nta_t *nta = (dns_nta_t *) data;
isc_mem_t *mctx = (isc_mem_t *) arg;
nta_detach(mctx, &nta);
}
isc_result_t
dns_ntatable_create(isc_mem_t *mctx, 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));
if (ntatable == NULL)
return (ISC_R_NOMEMORY);
ntatable->table = NULL;
result = dns_rbt_create(mctx, free_nta, mctx, &ntatable->table);
if (result != ISC_R_SUCCESS)
goto cleanup_ntatable;
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->references = 1;
ntatable->magic = NTATABLE_MAGIC;
*ntatablep = ntatable;
return (ISC_R_SUCCESS);
cleanup_rbt:
dns_rbt_destroy(&ntatable->table);
cleanup_ntatable:
isc_mem_put(mctx, ntatable, sizeof(*ntatable));
return (result);
}
void
dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp) {
REQUIRE(VALID_NTATABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
RWLOCK(&source->rwlock, isc_rwlocktype_write);
INSIST(source->references > 0);
source->references++;
INSIST(source->references != 0);
RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
*targetp = source;
}
void
dns_ntatable_detach(dns_ntatable_t **ntatablep) {
isc_boolean_t destroy = ISC_FALSE;
dns_ntatable_t *ntatable;
REQUIRE(ntatablep != NULL && VALID_NTATABLE(*ntatablep));
ntatable = *ntatablep;
*ntatablep = NULL;
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
INSIST(ntatable->references > 0);
ntatable->references--;
if (ntatable->references == 0)
destroy = ISC_TRUE;
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
if (destroy) {
dns_rbt_destroy(&ntatable->table);
isc_rwlock_destroy(&ntatable->rwlock);
ntatable->magic = 0;
isc_mem_putanddetach(&ntatable->mctx,
ntatable, sizeof(*ntatable));
}
}
isc_result_t
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
isc_uint32_t expiry)
{
isc_result_t result;
dns_nta_t *nta = NULL;
dns_rbtnode_t *node;
REQUIRE(VALID_NTATABLE(ntatable));
result = dns_nta_create(ntatable->mctx, &nta);
if (result != ISC_R_SUCCESS)
return (result);
nta->expiry = expiry;
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
node = NULL;
result = dns_rbt_addnode(ntatable->table, name, &node);
if (result == ISC_R_SUCCESS) {
node->data = nta;
nta = NULL;
} else if (result == ISC_R_EXISTS) {
dns_nta_t *n = node->data;
if (n == NULL) {
node->data = nta;
nta = NULL;
} else {
n->expiry = nta->expiry;
nta_detach(ntatable->mctx, &nta);
}
result = ISC_R_SUCCESS;
}
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
if (nta != NULL)
nta_detach(ntatable->mctx, &nta);
return (result);
}
/*
* Caller must hold a write lock on rwlock.
*/
static isc_result_t
delete(dns_ntatable_t *ntatable, dns_name_t *name) {
isc_result_t result;
dns_rbtnode_t *node = NULL;
REQUIRE(VALID_NTATABLE(ntatable));
REQUIRE(name != NULL);
result = dns_rbt_findnode(ntatable->table, name, NULL, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL)
result = dns_rbt_deletenode(ntatable->table,
node, ISC_FALSE);
else
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_PARTIALMATCH)
result = ISC_R_NOTFOUND;
return (result);
}
isc_result_t
dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *name) {
isc_result_t result;
RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
result = delete(ntatable, name);
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
return (result);
}
isc_boolean_t
dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
dns_name_t *name, dns_name_t *anchor)
{
isc_result_t result;
dns_fixedname_t fn;
dns_rbtnode_t *node;
dns_name_t *foundname;
dns_nta_t *nta = NULL;
isc_boolean_t answer = ISC_FALSE;
isc_rwlocktype_t locktype = isc_rwlocktype_read;
REQUIRE(ntatable == NULL || VALID_NTATABLE(ntatable));
REQUIRE(dns_name_isabsolute(name));
if (ntatable == NULL)
return (ISC_FALSE);
dns_fixedname_init(&fn);
foundname = dns_fixedname_name(&fn);
relock:
RWLOCK(&ntatable->rwlock, locktype);
again:
node = NULL;
result = dns_rbt_findnode(ntatable->table, name, foundname, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == DNS_R_PARTIALMATCH) {
if (dns_name_issubdomain(foundname, anchor))
result = ISC_R_SUCCESS;
}
if (result == ISC_R_SUCCESS) {
nta = (dns_nta_t *) node->data;
answer = ISC_TF(nta->expiry > now);
}
/* Deal with expired NTA */
if (result == ISC_R_SUCCESS && !answer) {
char nb[DNS_NAME_FORMATSIZE];
if (locktype == isc_rwlocktype_read) {
RWUNLOCK(&ntatable->rwlock, locktype);
locktype = isc_rwlocktype_write;
goto relock;
}
dns_name_format(foundname, nb, sizeof(nb));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
"deleting expired NTA at %s", nb);
result = delete(ntatable, foundname);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
"deleting NTA failed: %s",
isc_result_totext(result));
}
goto again;
}
RWUNLOCK(&ntatable->rwlock, locktype);
return (answer);
}
isc_result_t
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
isc_result_t result;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
REQUIRE(VALID_NTATABLE(ntatable));
RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain, ntatable->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_name_t name;
isc_time_t t;
dns_name_init(&name, NULL);
dns_rbt_namefromnode(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);
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
break;
}
}
cleanup:
dns_rbtnodechain_invalidate(&chain);
RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
return (result);
}
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(nta));
return (result);
}
nta->magic = NTA_MAGIC;
*target = nta;
return (ISC_R_SUCCESS);
}

View file

@ -1821,6 +1821,29 @@ compute_cc(resquery_t *query, unsigned char *sit, size_t len) {
}
#endif
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)
{
dns_name_t suffix;
unsigned int labels;
/*
* For DS variants we need to check fom the parent domain,
* since there may be a negative trust anchor for the name,
* while the enclosing domain where the DS record lives is
* under a secure entry point.
*/
labels = dns_name_countlabels(name);
if (dns_rdatatype_atparent(type) && labels > 1) {
dns_name_init(&suffix, NULL);
dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
name = &suffix;
}
return (dns_view_issecuredomain(view, name, now, issecure));
}
static isc_result_t
resquery_send(resquery_t *query) {
fetchctx_t *fctx;
@ -1922,8 +1945,9 @@ resquery_send(resquery_t *query) {
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
else if (res->view->enablevalidation &&
((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0)) {
result = dns_view_issecuredomain(res->view, &fctx->name,
&secure_domain);
result = issecuredomain(res->view, &fctx->name,
fctx->type, query->start.seconds,
&secure_domain);
if (result != ISC_R_SUCCESS)
secure_domain = ISC_FALSE;
if (res->view->dlv != NULL)
@ -4825,8 +4849,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
* Is DNSSEC validation required for this name?
*/
if (res->view->enablevalidation) {
result = dns_view_issecuredomain(res->view, name,
&secure_domain);
result = issecuredomain(res->view, name, fctx->type,
now, &secure_domain);
if (result != ISC_R_SUCCESS)
return (result);
@ -5360,8 +5384,8 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
* Is DNSSEC validation required for this name?
*/
if (fctx->res->view->enablevalidation) {
result = dns_view_issecuredomain(res->view, name,
&secure_domain);
result = issecuredomain(res->view, name, fctx->type,
now, &secure_domain);
if (result != ISC_R_SUCCESS)
return (result);

View file

@ -163,6 +163,7 @@ static const char *text[DNS_R_NRESULTS] = {
"expired", /*%< 107 DNS_R_EXPIRED */
"not dynamic", /*%< 108 DNS_R_NOTDYNAMIC */
"bad EUI" /*%< 109 DNS_R_BADEUI */
"covered by negative trust anchor" /*%< 110 DNS_R_NTACOVERED */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {

View file

@ -45,6 +45,7 @@ SRCS = db_test.c \
dnstest.c \
geoip_test.c \
gost_test.c \
keytable_test.c \
master_test.c \
nsec3_test.c \
private_test.c \
@ -66,6 +67,7 @@ TARGETS = db_test@EXEEXT@ \
dispatch_test@EXEEXT@ \
geoip_test@EXEEXT@ \
gost_test@EXEEXT@ \
keytable_test@EXEEXT@ \
master_test@EXEEXT@ \
nsec3_test@EXEEXT@ \
private_test@EXEEXT@ \
@ -94,6 +96,11 @@ master_test@EXEEXT@: master_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
master_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
keytable_test@EXEEXT@: keytable_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
keytable_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
time_test@EXEEXT@: time_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
time_test.@O@ dnstest.@O@ ${DNSLIBS} \

View file

@ -43,8 +43,6 @@
#include <dns/view.h>
#include <dns/zone.h>
#include <dst/dst.h>
#include "dnstest.h"
isc_mem_t *mctx = NULL;
@ -187,6 +185,26 @@ dns_test_end(void) {
isc_mem_destroy(&mctx);
}
/*
* Create a view.
*/
isc_result_t
dns_test_makeview(const char *name, dns_view_t **viewp)
{
isc_result_t result;
dns_view_t *view = NULL;
CHECK(dns_view_create(mctx, dns_rdataclass_in, name, &view));
*viewp = view;
return (ISC_R_SUCCESS);
cleanup:
if (view != NULL)
dns_view_detach(&view);
return (result);
}
/*
* Create a zone with origin 'name', return a pointer to the zone object in
* 'zonep'. If 'view' is set, add the zone to that view; otherwise, create

View file

@ -57,6 +57,9 @@ dns_test_begin(FILE *logfile, isc_boolean_t create_managers);
void
dns_test_end(void);
isc_result_t
dns_test_makeview(const char *name, dns_view_t **viewp);
isc_result_t
dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view,
isc_boolean_t keepview);

View file

@ -0,0 +1,598 @@
/*
* Copyright (c) 2014 Infoblox Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*! \file */
#include <config.h>
#include <atf-c.h>
#include <unistd.h>
#include <stdio.h>
#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/util.h>
#include <dns/name.h>
#include <dns/fixedname.h>
#include <dns/keytable.h>
#include <dns/nta.h>
#include <dns/rdataclass.h>
#include <dns/rdatastruct.h>
#include <dns/rootns.h>
#include <dns/view.h>
#include <dst/dst.h>
#include "dnstest.h"
dns_keytable_t *keytable = NULL;
dns_ntatable_t *ntatable = NULL;
static const char *keystr1 = "BQEAAAABok+vaUC9neRv8yeT/FEGgN7svR8s7VBUVSBd8NsAiV8AlaAg O5FHar3JQd95i/puZos6Vi6at9/JBbN8qVmO2AuiXxVqfxMKxIcy+LEB 0Vw4NaSJ3N3uaVREso6aTSs98H/25MjcwLOr7SFfXA7bGhZatLtYY/xu kp6Km5hMfkE=";
static const dns_keytag_t keytag1 = 30591;
static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/inaJpYv7vH XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/ItBfh/hL2lm Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi79532Qeklxh x8pXWdeAaRU=";
/*
* Test utilities. In general, these assume input parameters are valid
* (checking with ATF_REQUIRE_EQ, thus aborting if not) and unlikely run time
* errors (such as memory allocation failure) won't happen. This helps keep
* the test code concise.
*/
/*
* Utility to convert C-string to dns_name_t. Return a pointer to
* static data, and so is not thread safe.
*/
static dns_name_t *
str2name(const char *namestr) {
static dns_fixedname_t fname;
static dns_name_t *name;
static isc_buffer_t namebuf;
void *deconst_namestr;
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
DE_CONST(namestr, deconst_namestr); /* OK, since we don't modify it */
isc_buffer_init(&namebuf, deconst_namestr, strlen(deconst_namestr));
isc_buffer_add(&namebuf, strlen(namestr));
ATF_REQUIRE_EQ(dns_name_fromtext(name, &namebuf, dns_rootname, 0,
NULL), ISC_R_SUCCESS);
return (name);
}
static void
create_key(isc_uint16_t flags, isc_uint8_t proto, isc_uint8_t alg,
const char *keynamestr, const char *keystr, dst_key_t **target)
{
dns_rdata_dnskey_t keystruct;
unsigned char keydata[4096];
isc_buffer_t keydatabuf;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
isc_region_t r;
const dns_rdataclass_t rdclass = dns_rdataclass_in; /* for brevity */
keystruct.common.rdclass = rdclass;
keystruct.common.rdtype = dns_rdatatype_dnskey;
keystruct.mctx = NULL;
ISC_LINK_INIT(&keystruct.common, link);
keystruct.flags = flags;
keystruct.protocol = proto;
keystruct.algorithm = alg;
isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
ATF_REQUIRE_EQ(isc_base64_decodestring(keystr, &keydatabuf),
ISC_R_SUCCESS);
isc_buffer_usedregion(&keydatabuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
ATF_REQUIRE_EQ(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dst_key_fromdns(str2name(keynamestr), rdclass,
&rrdatabuf, mctx, target),
ISC_R_SUCCESS);
}
/* Common setup: create a keytable and ntatable to test with a few keys */
static void
create_tables() {
dst_key_t *key = NULL;
isc_stdtime_t now;
ATF_REQUIRE_EQ(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_ntatable_create(mctx, &ntatable), ISC_R_SUCCESS);
/* Add a normal key */
create_key(257, 3, 5, "example.com", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
ISC_R_SUCCESS);
/* Add a null key */
ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable,
str2name("null.example")),
ISC_R_SUCCESS);
/* Add a negative trust anchor, duration 1 hour */
isc_stdtime_get(&now);
ATF_REQUIRE_EQ(dns_ntatable_add(ntatable,
str2name("insecure.example"),
now + 3600),
ISC_R_SUCCESS);
}
static void
destroy_tables() {
if (ntatable != NULL)
dns_ntatable_detach(&ntatable);
if (keytable != NULL)
dns_keytable_detach(&keytable);
}
/*
* Individual unit tests
*/
ATF_TC(add);
ATF_TC_HEAD(add, tc) {
atf_tc_set_md_var(tc, "descr", "add keys to the keytable");
}
ATF_TC_BODY(add, tc) {
dst_key_t *key = NULL;
dns_keynode_t *keynode = NULL;
dns_keynode_t *next_keynode = NULL;
dns_keynode_t *null_keynode = NULL;
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/*
* Get the keynode for the example.com key. There's no other key for
* the name, so nextkeynode() should return NOTFOUND.
*/
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"),
&keynode), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode), ISC_R_NOTFOUND);
/*
* Try to add the same key. This should have no effect, so
* nextkeynode() should still return NOTFOUND.
*/
create_key(257, 3, 5, "example.com", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode), ISC_R_NOTFOUND);
/* Add another key (different keydata) */
dns_keytable_detachkeynode(keytable, &keynode);
create_key(257, 3, 5, "example.com", keystr2, &key);
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"),
&keynode), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode), ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &next_keynode);
/*
* Add a normal key to a name that has a null key. The null key node
* will be updated with the normal key.
*/
dns_keytable_detachkeynode(keytable, &keynode);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
&null_keynode), ISC_R_SUCCESS);
create_key(257, 3, 5, "null.example", keystr2, &key);
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
&keynode), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(keynode, null_keynode); /* should be the same node */
ATF_REQUIRE(dns_keynode_key(keynode) != NULL); /* now have a key */
dns_keytable_detachkeynode(keytable, &null_keynode);
/*
* Try to add a null key to a name that already has a key. It's
* effectively no-op, so the same key node is still there, with no
* no next node.
* (Note: this and above checks confirm that if a name has a null key
* that's the only key for the name).
*/
ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable,
str2name("null.example")),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
&null_keynode), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(keynode, null_keynode);
ATF_REQUIRE(dns_keynode_key(keynode) != NULL);
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode), ISC_R_NOTFOUND);
dns_keytable_detachkeynode(keytable, &null_keynode);
dns_keytable_detachkeynode(keytable, &keynode);
destroy_tables();
dns_test_end();
}
ATF_TC(delete);
ATF_TC_HEAD(delete, tc) {
atf_tc_set_md_var(tc, "descr", "delete keys from the keytable");
}
ATF_TC_BODY(delete, tc) {
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/* dns_keytable_delete requires exact match */
ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.org")),
ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("s.example.com")),
ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")),
ISC_R_SUCCESS);
/* works also for nodes with a null key */
ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("null.example")),
ISC_R_SUCCESS);
/* or a negative trust anchor */
ATF_REQUIRE_EQ(dns_ntatable_delete(ntatable,
str2name("insecure.example")),
ISC_R_SUCCESS);
destroy_tables();
dns_test_end();
}
ATF_TC(deletekeynode);
ATF_TC_HEAD(deletekeynode, tc) {
atf_tc_set_md_var(tc, "descr", "delete key nodes from the keytable");
}
ATF_TC_BODY(deletekeynode, tc) {
dst_key_t *key = NULL;
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/* key name doesn't match */
create_key(257, 3, 5, "example.org", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_NOTFOUND);
dst_key_free(&key);
/* subdomain match is the same as no match */
create_key(257, 3, 5, "sub.example.com", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_NOTFOUND);
dst_key_free(&key);
/* name matches but key doesn't match (resulting in PARTIALMATCH) */
create_key(257, 3, 5, "example.com", keystr2, &key);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
DNS_R_PARTIALMATCH);
dst_key_free(&key);
/*
* exact match. after deleting the node the internal rbt node will be
* empty, and any delete or deletekeynode attempt should result in
* NOTFOUND.
*/
create_key(257, 3, 5, "example.com", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")),
ISC_R_NOTFOUND);
dst_key_free(&key);
/*
* The only null key node for a name can be deleted as long as the
* passed key name matches.
*/
create_key(257, 3, 5, "null.example", keystr1, &key);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key),
ISC_R_NOTFOUND);
dst_key_free(&key);
destroy_tables();
dns_test_end();
}
ATF_TC(find);
ATF_TC_HEAD(find, tc) {
atf_tc_set_md_var(tc, "descr", "check find-variant operations");
}
ATF_TC_BODY(find, tc) {
dns_keynode_t *keynode = NULL;
dns_fixedname_t fname;
dns_name_t *name;
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/*
* dns_keytable_find() requires exact name match. It matches node
* that has a null key, too. But it doesn't match a negative trust
* anchor.
*/
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.org"),
&keynode), ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("sub.example.com"),
&keynode), ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"),
&keynode), ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &keynode);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
&keynode), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_keynode_key(keynode), NULL);
dns_keytable_detachkeynode(keytable, &keynode);
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("insecure.example"),
&keynode), ISC_R_NOTFOUND);
/*
* dns_keytable_finddeepestmatch() allows partial match. Also match
* nodes with a null key or a negative trust anchor.
*/
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable,
str2name("example.com"),
name), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), ISC_TRUE);
ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable,
str2name("s.example.com"),
name), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), ISC_TRUE);
ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable,
str2name("example.org"),
name), ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable,
str2name("null.example"),
name), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(dns_name_equal(name, str2name("null.example")),
ISC_TRUE);
/*
* dns_keytable_findkeynode() requires exact name, algorithm, keytag
* match. If algorithm or keytag doesn't match, should result in
* PARTIALMATCH. Same for a node with a null key or a negative trust
* anchor.
*/
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("example.org"),
5, keytag1, &keynode),
ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("sub.example.com"),
5, keytag1, &keynode),
ISC_R_NOTFOUND);
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("example.com"),
4, keytag1, &keynode),
DNS_R_PARTIALMATCH); /* different algorithm */
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("example.com"),
5, keytag1 + 1, &keynode),
DNS_R_PARTIALMATCH); /* different keytag */
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("null.example"),
5, 0, &keynode),
DNS_R_PARTIALMATCH); /* null key */
ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable,
str2name("example.com"),
5, keytag1, &keynode),
ISC_R_SUCCESS); /* complete match */
dns_keytable_detachkeynode(keytable, &keynode);
destroy_tables();
dns_test_end();
}
ATF_TC(issecuredomain);
ATF_TC_HEAD(issecuredomain, tc) {
atf_tc_set_md_var(tc, "descr", "check issecuredomain()");
}
ATF_TC_BODY(issecuredomain, tc) {
isc_boolean_t issecure;
const char **n;
const char *names[] = {"example.com", "sub.example.com",
"null.example", "sub.null.example", NULL};
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/*
* Domains that are an exact or partial match of a key name are
* considered secure. It's the case even if the key is null
* (validation will then fail, but that's actually the intended effect
* of installing a null key).
*/
for (n = names; *n != NULL; n++) {
ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable,
str2name(*n),
NULL,
&issecure),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(issecure, ISC_TRUE);
}
/*
* Domains that are an exact or partial match of a negative trust
* anchor are considered insecure.
*/
ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable,
str2name("insecure.example"),
NULL,
&issecure),
ISC_R_SUCCESS);
ATF_REQUIRE_EQ(issecure, ISC_FALSE);
ATF_REQUIRE_EQ(dns_keytable_issecuredomain(
keytable, str2name("sub.insecure.example"),
NULL, &issecure), ISC_R_SUCCESS);
ATF_REQUIRE_EQ(issecure, ISC_FALSE);
destroy_tables();
dns_test_end();
}
ATF_TC(dump);
ATF_TC_HEAD(dump, tc) {
atf_tc_set_md_var(tc, "descr", "check dns_keytable_dump()");
}
ATF_TC_BODY(dump, tc) {
UNUSED(tc);
ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_FALSE), ISC_R_SUCCESS);
create_tables();
/*
* Right now, we only confirm the dump attempt doesn't cause disruption
* (so we don't check the dump content).
*/
ATF_REQUIRE_EQ(dns_keytable_dump(keytable, stdout), ISC_R_SUCCESS);
destroy_tables();
dns_test_end();
}
ATF_TC(nta);
ATF_TC_HEAD(nta, tc) {
atf_tc_set_md_var(tc, "descr", "check negative trust anchors");
}
ATF_TC_BODY(nta, tc) {
isc_result_t result;
dst_key_t *key = NULL;
isc_boolean_t issecure, covered;
dns_view_t *view = NULL;
isc_stdtime_t now;
UNUSED(tc);
result = dns_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_test_makeview("view", &view);
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);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_view_getntatable(view, &ntatable);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
create_key(257, 3, 5, "example", keystr1, &key);
result = dns_keytable_add(keytable, ISC_FALSE, &key);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
isc_stdtime_get(&now);
result = dns_ntatable_add(ntatable,
str2name("insecure.example"), now + 1);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* Should be secure */
result = dns_view_issecuredomain(view,
str2name("test.secure.example"),
now, &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);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(!issecure);
/* NTA covered */
covered = dns_view_ntacovers(view, now, str2name("insecure.example"),
dns_rootname);
ATF_CHECK(covered);
/* Not NTA covered */
covered = dns_view_ntacovers(view, now, str2name("secure.example"),
dns_rootname);
ATF_CHECK(!covered);
/* As of now + 2, the NTA should be clear */
result = dns_view_issecuredomain(view,
str2name("test.insecure.example"),
now + 2, &issecure);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(issecure);
/* Now check deletion */
result = dns_ntatable_add(ntatable,
str2name("new.example"), now + 3600);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_view_issecuredomain(view, str2name("test.new.example"),
now, &issecure);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(!issecure);
result = dns_ntatable_delete(ntatable, str2name("new.example"));
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = dns_view_issecuredomain(view, str2name("test.new.example"),
now, &issecure);
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
ATF_CHECK(issecure);
/* Clean up */
dns_ntatable_detach(&ntatable);
dns_keytable_detach(&keytable);
dns_view_detach(&view);
dns_test_end();
}
/*
* Main
*/
ATF_TP_ADD_TCS(tp) {
ATF_TP_ADD_TC(tp, add);
ATF_TP_ADD_TC(tp, delete);
ATF_TP_ADD_TC(tp, deletekeynode);
ATF_TP_ADD_TC(tp, find);
ATF_TP_ADD_TC(tp, issecuredomain);
ATF_TP_ADD_TC(tp, dump);
ATF_TP_ADD_TC(tp, nta);
return (atf_no_error());
}

View file

@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
#include <config.h>
#include <isc/base32.h>
@ -1649,12 +1647,9 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
validator_log(val, ISC_LOG_DEBUG(3),
"failed to verify rdataset");
else {
isc_stdtime_t now;
isc_stdtime_get(&now);
dns_rdataset_trimttl(event->rdataset,
event->sigrdataset,
val->siginfo, now,
val->siginfo, val->start,
val->view->acceptexpired);
}
@ -3075,6 +3070,11 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
markanswer(val, "startfinddlvsep (1)");
return (ISC_R_SUCCESS);
}
if (result == DNS_R_NTACOVERED) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV covered by NTA");
validator_done(val, ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
dns_result_totext(result));
@ -3164,6 +3164,9 @@ 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))
return (DNS_R_NTACOVERED);
while (dns_name_countlabels(dlvname) >=
dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
dns_name_format(dlvname, namebuf, sizeof(namebuf));
@ -3780,6 +3783,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_fixedname_init(&val->wild);
dns_fixedname_init(&val->nearest);
dns_fixedname_init(&val->closest);
isc_stdtime_get(&val->start);
ISC_LINK_INIT(val, link);
val->magic = VALIDATOR_MAGIC;

View file

@ -45,6 +45,7 @@
#include <dns/keyvalues.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/nta.h>
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/rrl.h>
@ -110,6 +111,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
}
}
view->secroots_priv = NULL;
view->ntatable_priv = NULL;
view->fwdtable = NULL;
result = dns_fwdtable_create(mctx, &view->fwdtable);
if (result != ISC_R_SUCCESS) {
@ -444,6 +446,8 @@ destroy(dns_view_t *view) {
dns_stats_detach(&view->resquerystats);
if (view->secroots_priv != NULL)
dns_keytable_detach(&view->secroots_priv);
if (view->ntatable_priv != NULL)
dns_ntatable_detach(&view->ntatable_priv);
for (dns64 = ISC_LIST_HEAD(view->dns64);
dns64 != NULL;
dns64 = ISC_LIST_HEAD(view->dns64)) {
@ -1771,6 +1775,24 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
dns_stats_attach(view->resquerystats, statsp);
}
isc_result_t
dns_view_initntatable(dns_view_t *view, isc_mem_t *mctx) {
REQUIRE(DNS_VIEW_VALID(view));
if (view->ntatable_priv != NULL)
dns_ntatable_detach(&view->ntatable_priv);
return (dns_ntatable_create(mctx, &view->ntatable_priv));
}
isc_result_t
dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ntp != NULL && *ntp == NULL);
if (view->ntatable_priv == NULL)
return (ISC_R_NOTFOUND);
dns_ntatable_attach(view->ntatable_priv, ntp);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
REQUIRE(DNS_VIEW_VALID(view));
@ -1789,15 +1811,46 @@ dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
return (ISC_R_SUCCESS);
}
isc_boolean_t
dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
dns_name_t *name, dns_name_t *anchor)
{
REQUIRE(DNS_VIEW_VALID(view));
if (view->ntatable_priv == NULL)
return (ISC_FALSE);
return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor));
}
isc_result_t
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
isc_boolean_t *secure_domain) {
isc_stdtime_t now, isc_boolean_t *secure_domain)
{
isc_result_t result;
isc_boolean_t secure = ISC_FALSE;
dns_fixedname_t fn;
dns_name_t *anchor;
REQUIRE(DNS_VIEW_VALID(view));
if (view->secroots_priv == NULL)
return (ISC_R_NOTFOUND);
return (dns_keytable_issecuredomain(view->secroots_priv, name,
secure_domain));
dns_fixedname_init(&fn);
anchor = dns_fixedname_name(&fn);
result = dns_keytable_issecuredomain(view->secroots_priv, name,
anchor, &secure);
if (result != ISC_R_SUCCESS)
return (result);
if (secure && view->ntatable_priv != NULL &&
dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
secure = ISC_FALSE;
*secure_domain = secure;
return (ISC_R_SUCCESS);
}
void

View file

@ -483,6 +483,14 @@ dns_nsec_isset
dns_nsec_nseconly
dns_nsec_setbit
dns_nsec_typepresent
dns_nta_create
dns_ntatable_add
dns_ntatable_attach
dns_ntatable_covered
dns_ntatable_create
dns_ntatable_delete
dns_ntatable_detach
dns_ntatable_dump
dns_opcode_totext
dns_opcodestats_create
dns_opcodestats_dump

View file

@ -276,6 +276,10 @@ SOURCE=..\include\dns\nsec3.h
# End Source File
# Begin Source File
SOURCE=..\include\dns\nta.h
# End Source File
# Begin Source File
SOURCE=..\include\dns\order.h
# End Source File
# Begin Source File
@ -614,6 +618,10 @@ SOURCE=..\nsec3.c
# End Source File
# Begin Source File
SOURCE=..\nta.c
# End Source File
# Begin Source File
SOURCE=..\order.c
# End Source File
# Begin Source File

View file

@ -166,6 +166,7 @@ CLEAN :
-@erase "$(INTDIR)\ncache.obj"
-@erase "$(INTDIR)\nsec.obj"
-@erase "$(INTDIR)\nsec3.obj"
-@erase "$(INTDIR)\nta.obj"
@IF OPENSSL
-@erase "$(INTDIR)\openssl_link.obj"
-@erase "$(INTDIR)\openssldh_link.obj"
@ -315,6 +316,7 @@ LINK32_OBJS= \
"$(INTDIR)\ncache.obj" \
"$(INTDIR)\nsec.obj" \
"$(INTDIR)\nsec3.obj" \
"$(INTDIR)\nta.obj" \
"$(INTDIR)\order.obj" \
"$(INTDIR)\peer.obj" \
"$(INTDIR)\portlist.obj" \
@ -504,6 +506,8 @@ CLEAN :
-@erase "$(INTDIR)\nsec.sbr"
-@erase "$(INTDIR)\nsec3.obj"
-@erase "$(INTDIR)\nsec3.sbr"
-@erase "$(INTDIR)\nta.obj"
-@erase "$(INTDIR)\nta.sbr"
@IF OPENSSL
-@erase "$(INTDIR)\openssl_link.obj"
-@erase "$(INTDIR)\openssl_link.sbr"
@ -705,6 +709,7 @@ BSC32_SBRS= \
"$(INTDIR)\ncache.sbr" \
"$(INTDIR)\nsec.sbr" \
"$(INTDIR)\nsec3.sbr" \
"$(INTDIR)\nta.sbr" \
"$(INTDIR)\order.sbr" \
"$(INTDIR)\peer.sbr" \
"$(INTDIR)\portlist.sbr" \
@ -820,6 +825,7 @@ LINK32_OBJS= \
"$(INTDIR)\ncache.obj" \
"$(INTDIR)\nsec.obj" \
"$(INTDIR)\nsec3.obj" \
"$(INTDIR)\nta.obj" \
"$(INTDIR)\order.obj" \
"$(INTDIR)\peer.obj" \
"$(INTDIR)\portlist.obj" \
@ -1557,6 +1563,24 @@ SOURCE=..\nsec3.c
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF
SOURCE=..\nta.c
!IF "$(CFG)" == "libdns - @PLATFORM@ Release"
"$(INTDIR)\nta.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ELSEIF "$(CFG)" == "libdns - @PLATFORM@ Debug"
"$(INTDIR)\nta.obj" "$(INTDIR)\nta.sbr" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF
SOURCE=..\order.c

View file

@ -137,6 +137,9 @@
<ClCompile Include="..\nsec3.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\nta.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClCompile Include="..\order.c">
<Filter>Library Source Files</Filter>
</ClCompile>
@ -469,6 +472,9 @@
<ClInclude Include="..\include\dns\nsec3.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\dns\nta.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\dns\opcode.h">
<Filter>Library Header Files</Filter>
</ClInclude>
@ -639,4 +645,4 @@
<Filter>Dst Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View file

@ -152,6 +152,7 @@
<ClCompile Include="..\ncache.c" />
<ClCompile Include="..\nsec.c" />
<ClCompile Include="..\nsec3.c" />
<ClCompile Include="..\nta.c" />
@IF OPENSSL
<ClCompile Include="..\openssldh_link.c" />
<ClCompile Include="..\openssldsa_link.c" />
@ -269,6 +270,7 @@
<ClInclude Include="..\include\dns\ncache.h" />
<ClInclude Include="..\include\dns\nsec.h" />
<ClInclude Include="..\include\dns\nsec3.h" />
<ClInclude Include="..\include\dns\nta.h" />
<ClInclude Include="..\include\dns\opcode.h" />
<ClInclude Include="..\include\dns\order.h" />
<ClInclude Include="..\include\dns\peer.h" />
@ -325,4 +327,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>