mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-22 23:01:43 -04:00
[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:
parent
fa6308bd57
commit
0cfb247368
34 changed files with 1636 additions and 43 deletions
9
CHANGES
9
CHANGES
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
206
lib/dns/include/dns/nta.h
Normal 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 */
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ struct dns_validator {
|
|||
unsigned int depth;
|
||||
unsigned int authcount;
|
||||
unsigned int authfail;
|
||||
isc_stdtime_t start;
|
||||
};
|
||||
|
||||
/*%
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
350
lib/dns/nta.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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] = {
|
||||
|
|
|
|||
|
|
@ -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} \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
598
lib/dns/tests/keytable_test.c
Normal file
598
lib/dns/tests/keytable_test.c
Normal 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());
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue