2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 07:35:26 +00:00

1558. [func] New DNSSEC 'disable-algorithms'. Support entry into

child zones for which we don't have a supported
                        algorithm.  Such child zones are treated as unsigned.

1557.   [func]          Implement missing DNSSEC tests for
                        * NOQNAME proof with wildcard answers.
                        * NOWILDARD proof with NXDOMAIN.
                        Cache and return NOQNAME with wildcard answers.
This commit is contained in:
Mark Andrews
2004-01-14 02:06:51 +00:00
parent 1f1b47a2ba
commit 35541328a8
29 changed files with 1289 additions and 234 deletions

View File

@@ -1,3 +1,12 @@
1558. [func] New DNSSEC 'disable-algorithms'. Support entry into
child zones for which we don't have a supported
algorithm. Such child zones are treated as unsigned.
1557. [func] Implement missing DNSSEC tests for
* NOQNAME proof with wildcard answers.
* NOWILDARD proof with NXDOMAIN.
Cache and return NOQNAME with wildcard answers.
1556. [placeholder] rt6427
1555. [func] 'rrset-order cyclic' no longer has a random starting

View File

@@ -17,7 +17,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnssec-signzone.c,v 1.172 2004/01/05 05:14:51 marka Exp $ */
/* $Id: dnssec-signzone.c,v 1.173 2004/01/14 02:06:48 marka Exp $ */
#include <config.h>
@@ -729,19 +729,6 @@ nsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type,
return (answer);
}
static void
warnwild(const char *name) {
static int warned = 0;
fprintf(stderr, "%s: warning: wildcard name seen: %s\n",
program, name);
if (warned++ != 0)
return;
fprintf(stderr, "%s: warning: BIND 9 doesn't properly "
"validate responses containing wildcards.\n",
program);
}
static isc_boolean_t
delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
dns_rdataset_t nsset;
@@ -782,9 +769,6 @@ signname(dns_dbnode_t *node, dns_name_t *name) {
dns_name_format(name, namestr, sizeof(namestr));
if (dns_name_iswildcard(name))
warnwild(namestr);
atorigin = dns_name_equal(name, gorigin);
/*

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.h,v 1.34 2002/11/27 09:52:46 marka Exp $ */
/* $Id: query.h,v 1.35 2004/01/14 02:06:49 marka Exp $ */
#ifndef NAMED_QUERY_H
#define NAMED_QUERY_H 1
@@ -64,7 +64,7 @@ struct ns_query {
#define NS_QUERYATTR_QUERYOKVALID 0x0040
#define NS_QUERYATTR_QUERYOK 0x0080
#define NS_QUERYATTR_WANTRECURSION 0x0100
/* unused */
#define NS_QUERYATTR_SECURE 0x0200
#define NS_QUERYATTR_NOAUTHORITY 0x0400
#define NS_QUERYATTR_NOADDITIONAL 0x0800

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.248 2003/10/25 00:31:06 jinmei Exp $ */
/* $Id: query.c,v 1.249 2004/01/14 02:06:48 marka Exp $ */
#include <config.h>
@@ -69,6 +69,8 @@
NS_QUERYATTR_NOAUTHORITY) != 0)
#define NOADDITIONAL(c) (((c)->query.attributes & \
NS_QUERYATTR_NOADDITIONAL) != 0)
#define SECURE(c) (((c)->query.attributes & \
NS_QUERYATTR_SECURE) != 0)
#if 0
#define CTRACE(m) isc_log_write(ns_g_lctx, \
@@ -241,7 +243,8 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
query_maybeputqname(client);
client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
NS_QUERYATTR_CACHEOK);
NS_QUERYATTR_CACHEOK |
NS_QUERYATTR_SECURE);
client->query.restarts = 0;
client->query.timerset = ISC_FALSE;
client->query.origqname = NULL;
@@ -1337,6 +1340,10 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
query_releasename(client, namep);
}
if (rdataset->trust != dns_trust_secure &&
(section == DNS_SECTION_ANSWER ||
section == DNS_SECTION_AUTHORITY))
client->query.attributes &= ~NS_QUERYATTR_SECURE;
/*
* Note: we only add SIGs if we've added the type they cover, so
* we do not need to check if the SIG rdataset is already in the
@@ -1728,6 +1735,11 @@ query_addbestns(ns_client_t *client) {
(sigrdataset != NULL && sigrdataset->trust == dns_trust_pending)))
goto cleanup;
if (WANTDNSSEC(client) && SECURE(client) &&
(rdataset->trust == dns_trust_glue ||
(sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)))
goto cleanup;
query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
DNS_SECTION_AUTHORITY);
@@ -2245,13 +2257,51 @@ setup_query_sortlist(ns_client_t *client) {
dns_message_setsortorder(client->message, order, order_arg);
}
static void
query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
isc_buffer_t *dbuf, b;
dns_name_t *fname;
dns_rdataset_t *nsec, *nsecsig;
isc_result_t result = ISC_R_NOMEMORY;
CTRACE("query_addnoqnameproof");
fname = NULL;
nsec = NULL;
nsecsig = NULL;
dbuf = query_getnamebuf(client);
if (dbuf == NULL)
goto cleanup;
fname = query_newname(client, dbuf, &b);
nsec = query_newrdataset(client);
nsecsig = query_newrdataset(client);
if (fname == NULL || nsec == NULL || nsecsig == NULL)
goto cleanup;
result = dns_rdataset_getnoqname(rdataset, fname, nsec, nsecsig);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
query_addrrset(client, &fname, &nsec, &nsecsig, dbuf,
DNS_SECTION_AUTHORITY);
cleanup:
if (nsec != NULL)
query_putrdataset(client, &nsec);
if (nsecsig != NULL)
query_putrdataset(client, &nsecsig);
if (fname != NULL)
query_releasename(client, &fname);
}
/*
* Do the bulk of query processing for the current query of 'client'.
* If 'event' is non-NULL, we are returning from recursion and 'qtype'
* is ignored. Otherwise, 'qtype' is the query type.
*/
static void
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) {
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
{
dns_db_t *db, *zdb;
dns_dbnode_t *node;
dns_rdatatype_t type;
@@ -2276,6 +2326,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdata_dname_t dname;
unsigned int options;
isc_boolean_t empty_wild;
dns_rdataset_t *noqname;
CTRACE("query_find");
@@ -2852,8 +2903,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
NULL);
need_wildcardproof = ISC_TRUE;
}
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0 &&
WANTDNSSEC(client))
noqname = rdataset;
else
noqname = NULL;
query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
DNS_SECTION_ANSWER);
if (noqname != NULL)
query_addnoqnameproof(client, noqname);
/*
* We set the PARTIALANSWER attribute so that if anything goes
* wrong later on, we'll return what we've got so far.
@@ -3124,8 +3182,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
sigrdatasetp = &sigrdataset;
else
sigrdatasetp = NULL;
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0 &&
WANTDNSSEC(client))
noqname = rdataset;
else
noqname = NULL;
query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
DNS_SECTION_ANSWER);
if (noqname != NULL)
query_addnoqnameproof(client, noqname);
/*
* We shouldn't ever fail to add 'rdataset'
* because it's already in the answer.
@@ -3385,6 +3450,13 @@ ns_query_start(ns_client_t *client) {
client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
}
/*
* Allow glue NS records to be added to the authority section
* if the answer is secure.
*/
if (message->flags & DNS_MESSAGEFLAG_CD)
client->query.attributes &= ~NS_QUERYATTR_SECURE;
/*
* This is an ordinary query.
*/

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.407 2004/01/05 06:56:44 marka Exp $ */
/* $Id: server.c,v 1.408 2004/01/14 02:06:49 marka Exp $ */
#include <config.h>
@@ -28,6 +28,7 @@
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/lex.h>
#include <isc/parseint.h>
#include <isc/print.h>
#include <isc/resource.h>
#include <isc/stdio.h>
@@ -56,6 +57,7 @@
#include <dns/rdatastruct.h>
#include <dns/resolver.h>
#include <dns/rootns.h>
#include <dns/secalg.h>
#include <dns/stats.h>
#include <dns/tkey.h>
#include <dns/view.h>
@@ -583,6 +585,52 @@ configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
return (result);
}
static isc_result_t
disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
isc_result_t result;
cfg_obj_t *algorithms;
cfg_listelt_t *element;
const char *str;
dns_fixedname_t fixed;
dns_name_t *name;
isc_buffer_t b;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
algorithms = cfg_tuple_get(disabled, "algorithms");
for (element = cfg_list_first(algorithms);
element != NULL;
element = cfg_list_next(element))
{
isc_textregion_t r;
dns_secalg_t alg;
r.base = cfg_obj_asstring(cfg_listelt_value(element));
r.length = strlen(r.base);
result = dns_secalg_fromtext(&alg, &r);
if (result != ISC_R_SUCCESS) {
isc_uint8_t ui;
result = isc_parse_uint8(&ui, r.base, 10);
alg = ui;
}
if (result != ISC_R_SUCCESS) {
cfg_obj_log(cfg_listelt_value(element),
ns_g_lctx, ISC_LOG_ERROR,
"invalid algorithm");
CHECK(result);
}
CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
}
cleanup:
return (result);
}
/*
* Configure 'view' according to 'vconfig', taking defaults from 'config'
* where values are missing in 'vconfig'.
@@ -603,6 +651,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
cfg_obj_t *forwarders;
cfg_obj_t *alternates;
cfg_obj_t *zonelist;
cfg_obj_t *disabled;
cfg_obj_t *obj;
cfg_listelt_t *element;
in_port_t port;
@@ -794,6 +843,20 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
udpsize = 4096;
dns_resolver_setudpsize(view->resolver, udpsize);
/*
* Set supported DNSSEC algorithms.
*/
dns_resolver_reset_algorithms(view->resolver);
disabled = NULL;
(void)ns_config_get(maps, "disable-algorithms", &disabled);
if (disabled != NULL) {
for (element = cfg_list_first(disabled);
element != NULL;
element = cfg_list_next(element))
CHECK(disable_algorithms(cfg_listelt_value(element),
view->resolver));
}
/*
* A global or view "forwarders" option, if present,
* creates an entry for "." in the forwarding table.

View File

@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.16 2003/10/26 21:33:45 marka Exp $
# $Id: sign.sh,v 1.17 2004/01/14 02:06:49 marka Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
@@ -51,3 +51,4 @@ EOF
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf
cp trusted.conf ../ns6/trusted.conf

View File

@@ -13,7 +13,7 @@
; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
; WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
; $Id: example.db.in,v 1.11 2002/02/20 03:33:53 marka Exp $
; $Id: example.db.in,v 1.12 2004/01/14 02:06:49 marka Exp $
$TTL 300 ; 5 minutes
@ IN SOA mname1. . (
@@ -70,3 +70,5 @@ z A 10.0.0.26
keyless NS ns.keyless
ns.keyless A 10.53.0.3
*.wild A 10.0.0.27

View File

@@ -13,7 +13,7 @@
; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
; WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
; $Id: private.secure.example.db.in,v 1.6 2001/01/09 21:42:53 bwelling Exp $
; $Id: private.secure.example.db.in,v 1.7 2004/01/14 02:06:49 marka Exp $
$TTL 300 ; 5 minutes
@ IN SOA mname1. . (
@@ -30,3 +30,5 @@ a A 10.0.0.1
b A 10.0.0.2
d A 10.0.0.4
z A 10.0.0.26
private2secure-nxdomain CNAME r.example.
*.wild CNAME s.example.

View File

@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: tests.sh,v 1.41 2002/07/19 06:20:24 marka Exp $
# $Id: tests.sh,v 1.42 2004/01/14 02:06:49 marka Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
@@ -48,6 +48,16 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking positive wildcard validation ($n)"
ret=0
$DIG $DIGOPTS a.wild.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
$DIG $DIGOPTS a.wild.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
grep "flags:.*ad.*QUERY" 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 negative validation ($n)"
ret=0
$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
@@ -58,6 +68,16 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking negative wildcard validation ($n)"
ret=0
$DIG $DIGOPTS b.wild.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
$DIG $DIGOPTS b.wild.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
grep "flags:.*ad.*QUERY" 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`
# Check the insecure.example domain
echo "I:checking 1-server insecurity proof ($n)"
@@ -382,6 +402,45 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking that lookups succeed after disabling a algorithm works ($n)"
ret=0
$DIG $DIGOPTS +noauth example. SOA @10.53.0.2 \
> dig.out.ns2.test$n || ret=1
$DIG $DIGOPTS +noauth example. SOA @10.53.0.6 \
> dig.out.ns6.test$n || ret=1
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
# Note - this is looking for failure, hence the &&
grep "flags:.*ad.*QUERY" dig.out.ns6.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 privately secure to nxdomain works ($n)"
ret=0
$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \
> dig.out.ns2.test$n || ret=1
$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
> dig.out.ns4.test$n || ret=1
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
# Note - this is looking for failure, hence the &&
grep "flags:.*ad.*QUERY" 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 privately secure wilcard to nxdomain works ($n)"
ret=0
$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.2 \
> dig.out.ns2.test$n || ret=1
$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.4 \
> dig.out.ns4.test$n || ret=1
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
# Note - this is looking for failure, hence the &&
grep "flags:.*ad.*QUERY" 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`
# Run a minimal update test if possible. This is really just
# a regression test for RT #2399; more tests should be added.

View File

@@ -15,7 +15,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: ifconfig.sh,v 1.42 2003/07/30 01:38:47 marka Exp $
# $Id: ifconfig.sh,v 1.43 2004/01/14 02:06:49 marka Exp $
#
# Set up interface aliases for bind9 system tests.
@@ -57,7 +57,7 @@ esac
case "$1" in
start|up)
for ns in 1 2 3 4 5
for ns in 1 2 3 4 5 6
do
if test -n "$base"
then
@@ -117,7 +117,7 @@ case "$1" in
;;
stop|down)
for ns in 5 4 3 2 1
for ns in 6 5 4 3 2 1
do
if test -n "$base"
then

View File

@@ -2,7 +2,7 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
<!-- File: $Id: Bv9ARM-book.xml,v 1.231 2003/10/07 03:34:30 marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.232 2004/01/14 02:06:49 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
@@ -2818,6 +2818,7 @@ statement in the <filename>named.conf</filename> file:</para>
<optional> edns-udp-size <replaceable>number</replaceable>; </optional>
<optional> root-delegation-only <optional> exclude { <replaceable>namelist</replaceable> } </optional> ; </optional>
};
<optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>; <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
</programlisting>
</sect2>
@@ -2955,8 +2956,14 @@ options {
};
</programlisting>
</listitem></varlistentry>
</variablelist>
<varlistentry><term><command>disable-algorithms</command></term>
<listitem><para>
Disable the specified DNSSEC algorithms at and below the specified name.
Multiple <command>disable-algorithms</command> statements are allowed.
Only the most specific will be applied.
</para></listitem></varlistentry>
</variablelist>
<sect3 id="boolean_options"><title>Boolean Options</title>

View File

@@ -79,6 +79,7 @@ options {
<integer>] | <ipv4_address> [port <integer>] | <ipv6_address> [port <integer>] ); ... };
edns-udp-size <integer>;
root-delegation-only [ exclude { <quoted_string>; ... } ];
disable-algorithms <string> { <string>; ... };
allow-query { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
@@ -255,6 +256,7 @@ view <string> <optional_class> {
<integer>] | <ipv4_address> [port <integer>] | <ipv6_address> [port <integer>] ); ... };
edns-udp-size <integer>;
root-delegation-only [ exclude { <quoted_string>; ... } ];
disable-algorithms <string> { <string>; ... };
allow-query { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.41 2003/09/25 18:16:47 jinmei Exp $ */
/* $Id: check.c,v 1.42 2004/01/14 02:06:49 marka Exp $ */
#include <config.h>
@@ -26,6 +26,7 @@
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/parseint.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
@@ -35,6 +36,7 @@
#include <dns/fixedname.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/secalg.h>
#include <isccfg/cfg.h>
@@ -219,6 +221,57 @@ check_forward(cfg_obj_t *options, isc_log_t *logctx) {
return (ISC_R_SUCCESS);
}
static isc_result_t
disabled_algorithms(cfg_obj_t *disabled, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
cfg_listelt_t *element;
const char *str;
isc_buffer_t b;
dns_fixedname_t fixed;
dns_name_t *name;
cfg_obj_t *obj;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
obj = cfg_tuple_get(disabled, "name");
str = cfg_obj_asstring(obj);
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", str);
result = tresult;
}
obj = cfg_tuple_get(disabled, "algorithms");
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
isc_textregion_t r;
dns_secalg_t alg;
isc_result_t tresult;
r.base = cfg_obj_asstring(cfg_listelt_value(element));
r.length = strlen(r.base);
tresult = dns_secalg_fromtext(&alg, &r);
if (tresult != ISC_R_SUCCESS) {
isc_uint8_t ui;
result = isc_parse_uint8(&ui, r.base, 10);
}
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(cfg_listelt_value(element), logctx,
ISC_LOG_ERROR, "invalid algorithm");
result = tresult;
}
}
return (result);
}
typedef struct {
const char *name;
unsigned int scale;
@@ -228,8 +281,10 @@ typedef struct {
static isc_result_t
check_options(cfg_obj_t *options, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
unsigned int i;
cfg_obj_t *obj = NULL;
cfg_listelt_t *element;
static intervaltable intervals[] = {
{ "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
@@ -289,7 +344,6 @@ check_options(cfg_obj_t *options, isc_log_t *logctx) {
dns_fixedname_t fixed;
dns_name_t *name;
isc_buffer_t b;
isc_result_t tresult;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
@@ -312,6 +366,24 @@ check_options(cfg_obj_t *options, isc_log_t *logctx) {
}
}
}
/*
* Set supported DNSSEC algorithms.
*/
obj = NULL;
(void)cfg_map_get(options, "disable-algorithms", &obj);
if (obj != NULL) {
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
tresult = disabled_algorithms(obj, logctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
}
return (result);
}

View File

@@ -16,7 +16,7 @@
*/
/*
* $Id: dnssec.c,v 1.78 2003/10/25 00:31:09 jinmei Exp $
* $Id: dnssec.c,v 1.79 2004/01/14 02:06:50 marka Exp $
*/
@@ -337,9 +337,9 @@ cleanup_signature:
}
isc_result_t
dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_boolean_t ignoretime, isc_mem_t *mctx,
dns_rdata_t *sigrdata)
dns_rdata_t *sigrdata, dns_name_t *wild)
{
dns_rdata_rrsig_t sig;
dns_fixedname_t fnewname;
@@ -351,7 +351,7 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_result_t ret;
unsigned char data[300];
dst_context_t *ctx = NULL;
int labels;
int labels = 0;
isc_uint32_t flags;
REQUIRE(name != NULL);
@@ -489,9 +489,30 @@ cleanup_context:
cleanup_struct:
dns_rdata_freestruct(&sig);
if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
if (wild != NULL)
RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
dns_fixedname_name(&fnewname),
wild, NULL) == ISC_R_SUCCESS);
ret = DNS_R_FROMWILDCARD;
}
return (ret);
}
isc_result_t
dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_boolean_t ignoretime, isc_mem_t *mctx,
dns_rdata_t *sigrdata)
{
isc_result_t result;
result = dns_dnssec_verify2(name, set, key, ignoretime, mctx,
sigrdata, NULL);
if (result == DNS_R_FROMWILDCARD)
result = ISC_R_SUCCESS;
return (result);
}
#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
== DNS_KEYOWNER_ZONE)

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnssec.h,v 1.24 2002/02/20 03:34:30 marka Exp $ */
/* $Id: dnssec.h,v 1.25 2004/01/14 02:06:50 marka Exp $ */
#ifndef DNS_DNSSEC_H
#define DNS_DNSSEC_H 1
@@ -83,6 +83,11 @@ isc_result_t
dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_boolean_t ignoretime, isc_mem_t *mctx,
dns_rdata_t *sigrdata);
isc_result_t
dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_boolean_t ignoretime, isc_mem_t *mctx,
dns_rdata_t *sigrdata, dns_name_t *wild);
/*
* Verifies the SIG record covering this rdataset signed by a specific
* key. This does not determine if the key's owner is authorized to
@@ -95,10 +100,14 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
* 'key' is a valid key
* 'mctx' is not NULL
* 'sigrdata' is a valid rdata containing a SIG record
* 'wild' if non-NULL then is a valid and has a buffer.
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* DNS_R_FROMWILDCARD - the signature is valid and is from
* a wildcard expansion. dns_dnssec_verify2() only.
* 'wild' contains the name of the wildcard if non-NULL.
* DNS_R_SIGINVALID - the signature fails to verify
* DNS_R_SIGEXPIRED - the signature has expired
* DNS_R_SIGFUTURE - the signature's validity period has not begun

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataset.h,v 1.48 2004/01/12 04:19:42 marka Exp $ */
/* $Id: rdataset.h,v 1.49 2004/01/14 02:06:50 marka Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
@@ -68,6 +68,12 @@ typedef struct dns_rdatasetmethods {
void (*clone)(dns_rdataset_t *source,
dns_rdataset_t *target);
unsigned int (*count)(dns_rdataset_t *rdataset);
isc_result_t (*addnoqname)(dns_rdataset_t *rdataset,
dns_name_t *name);
isc_result_t (*getnoqname)(dns_rdataset_t *rdataset,
dns_name_t *name,
dns_rdataset_t *nsec,
dns_rdataset_t *nsecsig);
} dns_rdatasetmethods_t;
#define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R')
@@ -113,6 +119,7 @@ struct dns_rdataset {
void * private3;
unsigned int privateuint4;
void * private5;
void * private6;
};
/*
@@ -137,6 +144,7 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_RANDOMIZE 0x0800
#define DNS_RDATASETATTR_CHASE 0x1000 /* Used by resolver. */
#define DNS_RDATASETATTR_NXDOMAIN 0x2000
#define DNS_RDATASETATTR_NOQNAME 0x4000
/*
* _OMITDNSSEC:
@@ -429,6 +437,31 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
* Any error that dns_rdata_additionaldata() can return.
*/
isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
/*
* Return the noqname proof for this record.
*
* Requires:
* 'rdataset' to be valid and DNS_RDATASETATTR_NOQNAME to be set.
* 'name' to be valid.
* 'nsec' and 'nsecsig' to be valid and not associated.
*/
isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
/*
* Associate a noqname proof with this record.
* Sets DNS_RDATASETATTR_NOQNAME if successful.
* Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
* the 'nsec' and 'rrsig(nsec)' ttl.
*
* Requires:
* 'rdataset' to be valid and DNS_RDATASETATTR_NOQNAME to be set.
* 'name' to be valid and have NSEC and RRSIG(NSEC) rdatasets.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_RDATASET_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.37 2003/02/26 02:03:59 marka Exp $ */
/* $Id: resolver.h,v 1.38 2004/01/14 02:06:50 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@@ -383,6 +383,35 @@ dns_resolver_getudpsize(dns_resolver_t *resolver);
* Get the current EDNS UDP buffer size.
*/
void
dns_resolver_reset_algorithms(dns_resolver_t *resolver);
/*
* Clear the disabled DNSSEC algorithms.
*/
isc_result_t
dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
unsigned int alg);
/*
* Mark the give DNSSEC algorithm as disabled and below 'name'.
* Valid algorithms are less than 256.
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_RANGE
* ISC_R_NOMEMORY
*/
isc_boolean_t
dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
unsigned int alg);
/*
* Check if the given algorithm is supported by this resolver.
* This checks if the algorithm has been disabled via
* dns_resolver_disable_algorithm() then the underlying
* crypto libraries if not specifically disabled.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.h,v 1.99 2003/09/30 05:56:17 marka Exp $ */
/* $Id: result.h,v 1.100 2004/01/14 02:06:50 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
@@ -136,8 +136,9 @@
#define DNS_R_EMPTYNAME (ISC_RESULTCLASS_DNS + 92)
#define DNS_R_EMPTYWILD (ISC_RESULTCLASS_DNS + 93)
#define DNS_R_BADBITMAP (ISC_RESULTCLASS_DNS + 94)
#define DNS_R_FROMWILDCARD (ISC_RESULTCLASS_DNS + 95)
#define DNS_R_NRESULTS 95 /* Number of results */
#define DNS_R_NRESULTS 96 /* Number of results */
/*
* DNS wire format rcodes.

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.h,v 1.24 2003/09/30 05:56:17 marka Exp $ */
/* $Id: validator.h,v 1.25 2004/01/14 02:06:51 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
@@ -74,8 +74,12 @@ typedef struct dns_validatorevent {
dns_rdataset_t * rdataset;
dns_rdataset_t * sigrdataset;
dns_message_t * message;
dns_name_t * proofs[3];
} dns_validatorevent_t;
#define DNS_VALIDATOR_NOQNAMEPROOF 0
#define DNS_VALIDATOR_NODATAPROOF 1
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
/*
* A validator object represents a validation in procgress.
@@ -114,6 +118,7 @@ struct dns_validator {
dns_rdataset_t frdataset;
dns_rdataset_t fsigrdataset;
dns_fixedname_t fname;
dns_fixedname_t wild;
ISC_LINK(dns_validator_t) link;
};

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.191 2004/01/12 04:19:42 marka Exp $ */
/* $Id: rbtdb.c,v 1.192 2004/01/14 02:06:50 marka Exp $ */
/*
* Principal Author: Bob Halley
@@ -94,6 +94,12 @@ typedef isc_uint32_t rbtdb_rdatatype_t;
#define RBTDB_RDATATYPE_NCACHEANY \
RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)
struct noqname {
dns_name_t name;
void * nsec;
void * nsecsig;
};
typedef struct rdatasetheader {
/*
* Locked by the owning node's lock.
@@ -103,6 +109,7 @@ typedef struct rdatasetheader {
rbtdb_rdatatype_t type;
isc_uint16_t attributes;
dns_trust_t trust;
struct noqname *noqname;
/*
* We don't use the LIST macros, because the LIST structure has
* both head and tail pointers, and is doubly linked.
@@ -249,6 +256,10 @@ static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
static unsigned int rdataset_count(dns_rdataset_t *rdataset);
static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
dns_name_t *name,
dns_rdataset_t *nsec,
dns_rdataset_t *nsecsig);
static dns_rdatasetmethods_t rdataset_methods = {
rdataset_disassociate,
@@ -256,7 +267,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
rdataset_next,
rdataset_current,
rdataset_clone,
rdataset_count
rdataset_count,
NULL,
rdataset_getnoqname
};
static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
@@ -561,10 +574,28 @@ add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
return (changed);
}
static inline void
free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
if (dns_name_dynamic(&(*noqname)->name))
dns_name_free(&(*noqname)->name, mctx);
if ((*noqname)->nsec != NULL)
isc_mem_put(mctx, (*noqname)->nsec,
dns_rdataslab_size((*noqname)->nsec, 0));
if ((*noqname)->nsec != NULL)
isc_mem_put(mctx, (*noqname)->nsecsig,
dns_rdataslab_size((*noqname)->nsecsig, 0));
isc_mem_put(mctx, *noqname, sizeof(**noqname));
*noqname = NULL;
}
static inline void
free_rdataset(isc_mem_t *mctx, rdatasetheader_t *rdataset) {
unsigned int size;
if (rdataset->noqname != NULL)
free_noqname(mctx, &rdataset->noqname);
if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
size = sizeof(*rdataset);
else
@@ -1372,6 +1403,13 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
*/
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
/*
* Add noqname proof.
*/
rdataset->private6 = header->noqname;
if (rdataset->private6 != NULL)
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
}
static inline isc_result_t
@@ -3812,11 +3850,13 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Don't replace existing NS, A and AAAA RRsets
* in the cache if they are already exist. This
* prevents named being locked to old servers.
* Don't lower trust of existing record if the
* update is forced.
*/
if (IS_CACHE(rbtdb) && header->ttl > now &&
header->type == dns_rdatatype_ns &&
!header_nx && !newheader_nx &&
header->trust == newheader->trust &&
header->trust >= newheader->trust &&
dns_rdataslab_equalx((unsigned char *)header,
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)),
@@ -3828,6 +3868,11 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
*/
if (header->ttl > newheader->ttl)
header->ttl = newheader->ttl;
if (header->noqname == NULL &&
newheader->noqname != NULL) {
header->noqname = newheader->noqname;
newheader->noqname = NULL;
}
free_rdataset(rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
@@ -3838,7 +3883,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
(header->type == dns_rdatatype_a ||
header->type == dns_rdatatype_aaaa) &&
!header_nx && !newheader_nx &&
header->trust == newheader->trust &&
header->trust >= newheader->trust &&
dns_rdataslab_equal((unsigned char *)header,
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)))) {
@@ -3848,6 +3893,11 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
*/
if (header->ttl > newheader->ttl)
header->ttl = newheader->ttl;
if (header->noqname == NULL &&
newheader->noqname != NULL) {
header->noqname = newheader->noqname;
newheader->noqname = NULL;
}
free_rdataset(rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
@@ -3952,6 +4002,51 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
return (ISC_FALSE);
}
static inline isc_result_t
addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
dns_rdataset_t *rdataset)
{
struct noqname *noqname;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_t name;
dns_rdataset_t nsec, nsecsig;
isc_result_t result;
isc_region_t r;
dns_name_init(&name, NULL);
dns_rdataset_init(&nsec);
dns_rdataset_init(&nsecsig);
result = dns_rdataset_getnoqname(rdataset, &name, &nsec, &nsecsig);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
noqname = isc_mem_get(mctx, sizeof(*noqname));
if (noqname == NULL)
return (ISC_R_NOMEMORY);
dns_name_init(&noqname->name, NULL);
noqname->nsec = NULL;
noqname->nsecsig = NULL;
result = dns_name_dup(&name, mctx, &noqname->name);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_rdataslab_fromrdataset(&nsec, mctx, &r, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
noqname->nsec = r.base;
result = dns_rdataslab_fromrdataset(&nsecsig, mctx, &r, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
noqname->nsecsig = r.base;
dns_rdataset_disassociate(&nsec);
dns_rdataset_disassociate(&nsecsig);
newheader->noqname = noqname;
return (ISC_R_SUCCESS);
cleanup:
free_noqname(mctx, &noqname);
return(result);
}
static isc_result_t
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
@@ -3984,6 +4079,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
newheader->attributes = 0;
newheader->noqname = NULL;
newheader->count = 0;
if (rbtversion != NULL) {
newheader->serial = rbtversion->serial;
@@ -3994,6 +4090,13 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->trust = rdataset->trust;
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
result = addnoqname(rbtdb, newheader, rdataset);
if (result != ISC_R_SUCCESS) {
free_rdataset(rbtdb->common.mctx, newheader);
return (result);
}
}
}
/*
@@ -4051,6 +4154,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->attributes = 0;
newheader->serial = rbtversion->serial;
newheader->trust = 0;
newheader->noqname = NULL;
newheader->count = 0;
LOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
@@ -4121,6 +4225,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
newheader->trust = 0;
newheader->serial = rbtversion->serial;
newheader->noqname = NULL;
newheader->count = 0;
} else {
free_rdataset(rbtdb->common.mctx, newheader);
@@ -4186,6 +4291,7 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
newheader->type = RBTDB_RDATATYPE_VALUE(type, covers);
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
newheader->trust = 0;
newheader->noqname = NULL;
if (rbtversion != NULL)
newheader->serial = rbtversion->serial;
else
@@ -4266,6 +4372,7 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
newheader->attributes = 0;
newheader->trust = rdataset->trust;
newheader->serial = 1;
newheader->noqname = NULL;
newheader->count = 0;
result = add(rbtdb, node, rbtdb->current_version, newheader,
@@ -4782,6 +4889,49 @@ rdataset_count(dns_rdataset_t *rdataset) {
return (count);
}
static isc_result_t
rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
{
dns_db_t *db = rdataset->private1;
dns_dbnode_t *node = rdataset->private2;
dns_dbnode_t *cloned_node;
struct noqname *noqname = rdataset->private6;
attachnode(db, node, &cloned_node);
attachnode(db, node, &cloned_node);
nsec->methods = &rdataset_methods;
nsec->rdclass = db->rdclass;
nsec->type = dns_rdatatype_nsec;
nsec->covers = 0;
nsec->ttl = rdataset->ttl;
nsec->trust = rdataset->trust;
nsec->private1 = rdataset->private1;
nsec->private2 = rdataset->private2;
nsec->private3 = noqname->nsec;
nsec->privateuint4 = 0;
nsec->private5 = NULL;
nsec->private6 = NULL;
nsecsig->methods = &rdataset_methods;
nsecsig->rdclass = db->rdclass;
nsecsig->type = dns_rdatatype_rrsig;
nsecsig->covers = dns_rdatatype_nsec;
nsecsig->ttl = rdataset->ttl;
nsecsig->trust = rdataset->trust;
nsecsig->private1 = rdataset->private1;
nsecsig->private2 = rdataset->private2;
nsecsig->private3 = noqname->nsecsig;
nsecsig->privateuint4 = 0;
nsecsig->private5 = NULL;
nsec->private6 = NULL;
dns_name_clone(&noqname->name, name);
return (ISC_R_SUCCESS);
}
/*
* Rdataset Iterator Methods

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdatalist.c,v 1.26 2003/02/26 23:52:29 marka Exp $ */
/* $Id: rdatalist.c,v 1.27 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -23,6 +23,7 @@
#include <isc/util.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
@@ -35,7 +36,9 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_next,
isc__rdatalist_current,
isc__rdatalist_clone,
isc__rdatalist_count
isc__rdatalist_count,
isc__rdatalist_addnoqname,
isc__rdatalist_getnoqname
};
void
@@ -150,3 +153,72 @@ isc__rdatalist_count(dns_rdataset_t *rdataset) {
return (count);
}
isc_result_t
isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
dns_rdataset_t *nsec = NULL;
dns_rdataset_t *nsecsig = NULL;
dns_rdataset_t *rdset;
dns_ttl_t ttl;
for (rdset = ISC_LIST_HEAD(name->list);
rdset != NULL;
rdset = ISC_LIST_NEXT(rdset, link))
{
if (rdset->rdclass != rdataset->rdclass)
continue;
if (rdset->type == dns_rdatatype_nsec)
nsec = rdset;
if (rdset->type == dns_rdatatype_rrsig &&
rdset->covers == dns_rdatatype_nsec)
nsecsig = rdset;
}
if (nsec == NULL || nsecsig == NULL)
return (ISC_R_NOTFOUND);
/*
* Minimise ttl.
*/
ttl = rdataset->ttl;
if (nsec->ttl < ttl)
ttl = nsec->ttl;
if (nsecsig->ttl < ttl)
ttl = nsecsig->ttl;
rdataset->ttl = nsec->ttl = nsecsig->ttl = ttl;
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
rdataset->private6 = name;
return (ISC_R_SUCCESS);
}
isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
{
dns_rdataclass_t rdclass = rdataset->rdclass;
dns_rdataset_t *tnsec = NULL;
dns_rdataset_t *tnsecsig = NULL;
dns_name_t *noqname = rdataset->private6;
REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
(void)dns_name_dynamic(noqname); /* Sanity Check. */
for (rdataset = ISC_LIST_HEAD(noqname->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
if (rdataset->rdclass != rdclass)
continue;
if (rdataset->type == dns_rdatatype_nsec)
tnsec = rdataset;
if (rdataset->type == dns_rdatatype_rrsig &&
rdataset->covers == dns_rdatatype_nsec)
tnsecsig = rdataset;
}
if (tnsec == NULL || tnsecsig == NULL)
return (ISC_R_NOTFOUND);
dns_name_clone(noqname, name);
dns_rdataset_clone(tnsec, nsec);
dns_rdataset_clone(tnsecsig, nsecsig);
return (ISC_R_SUCCESS);
}

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdatalist_p.h,v 1.3 2001/01/09 21:51:22 bwelling Exp $ */
/* $Id: rdatalist_p.h,v 1.4 2004/01/14 02:06:50 marka Exp $ */
#ifndef DNS_RDATALIST_P_H
#define DNS_RDATALIST_P_H
@@ -43,6 +43,13 @@ isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target);
unsigned int
isc__rdatalist_count(dns_rdataset_t *rdataset);
isc_result_t
isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
ISC_LANG_ENDDECLS
#endif /* DNS_RDATALIST_P_H */

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataset.c,v 1.69 2004/01/12 04:19:42 marka Exp $ */
/* $Id: rdataset.c,v 1.70 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -55,6 +55,7 @@ dns_rdataset_init(dns_rdataset_t *rdataset) {
rdataset->private3 = NULL;
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
rdataset->private6 = NULL;
}
void
@@ -108,6 +109,7 @@ dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
rdataset->private3 = NULL;
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
rdataset->private6 = NULL;
}
isc_boolean_t
@@ -169,7 +171,9 @@ static dns_rdatasetmethods_t question_methods = {
question_cursor,
question_current,
question_clone,
question_count
question_count,
NULL,
NULL
};
void
@@ -585,3 +589,24 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
return (ISC_R_SUCCESS);
}
isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL);
if (rdataset->methods->addnoqname == NULL)
return (ISC_R_NOTIMPLEMENTED);
return((rdataset->methods->addnoqname)(rdataset, name));
}
isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
{
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL);
if (rdataset->methods->getnoqname == NULL)
return (ISC_R_NOTIMPLEMENTED);
return((rdataset->methods->getnoqname)(rdataset, name, nsec, nsecsig));
}

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataslab.c,v 1.33 2003/02/26 23:52:29 marka Exp $ */
/* $Id: rdataslab.c,v 1.34 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -239,7 +239,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
rdataset_next,
rdataset_current,
rdataset_clone,
rdataset_count
rdataset_count,
NULL,
NULL
};
void

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.275 2004/01/05 07:45:34 marka Exp $ */
/* $Id: resolver.c,v 1.276 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -35,6 +35,7 @@
#include <dns/ncache.h>
#include <dns/opcode.h>
#include <dns/peer.h>
#include <dns/rbt.h>
#include <dns/rcode.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
@@ -286,6 +287,10 @@ struct dns_resolver {
isc_uint32_t lame_ttl;
ISC_LIST(alternate_t) alternates;
isc_uint16_t udpsize;
#if USE_ALGLOG
isc_rwlock_t alglock;
#endif
dns_rbt_t * algorithms;
/* Locked by lock. */
unsigned int references;
isc_boolean_t exiting;
@@ -2847,6 +2852,8 @@ clone_results(fetchctx_t *fctx) {
isc_result_t result;
dns_name_t *name, *hname;
FCTXTRACE("clone_results");
/*
* Set up any other events to have the same data as the first
* event.
@@ -2939,6 +2946,10 @@ validated(isc_task_t *task, isc_event_t *event) {
isc_boolean_t chaining;
isc_boolean_t sentresponse;
isc_uint32_t ttl;
dns_dbnode_t *nsnode = NULL;
dns_name_t *name;
dns_rdataset_t *rdataset;
dns_rdataset_t *sigrdataset;
UNUSED(task); /* for now */
@@ -3069,6 +3080,14 @@ validated(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("validation OK");
if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
result = dns_rdataset_addnoqname(vevent->rdataset,
vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
vevent->sigrdataset->ttl = vevent->rdataset->ttl;
}
/*
* The data was already cached as pending data.
* Re-cache it as secure and bind the cached
@@ -3116,6 +3135,49 @@ validated(isc_task_t *task, isc_event_t *event) {
goto cleanup_event;
}
/*
* Cache any NS records that happened to be validate.
*/
result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
while (result == ISC_R_SUCCESS) {
name = NULL;
dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
&name);
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
if (rdataset->type != dns_rdatatype_ns ||
rdataset->trust != dns_trust_secure)
continue;
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
if (sigrdataset->type != dns_rdatatype_rrsig ||
sigrdataset->covers != dns_rdatatype_ns)
continue;
break;
}
if (sigrdataset == NULL ||
sigrdataset->trust != dns_trust_secure)
continue;
result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
&nsnode);
if (result != ISC_R_SUCCESS)
continue;
result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
now, rdataset, 0, NULL);
if (result == ISC_R_SUCCESS)
result = dns_db_addrdataset(fctx->cache, nsnode,
NULL, now,
sigrdataset, 0,
NULL);
dns_db_detachnode(fctx->cache, &nsnode);
}
result = dns_message_nextname(fctx->rmessage,
DNS_SECTION_AUTHORITY);
}
result = ISC_R_SUCCESS;
answer_response:
@@ -4568,15 +4630,10 @@ answer_response(fetchctx_t *fctx) {
rdataset,
check_related,
fctx);
}
}
/*
* Since we've found a non-external name in the
* authority section, we should stop looking, even
* if we didn't find any NS or SIG NS.
*/
done = ISC_TRUE;
}
}
}
result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
}
if (result == ISC_R_NOMORE)
@@ -5297,6 +5354,7 @@ destroy(dns_resolver_t *res) {
dns_name_free(&a->_u._n.name, res->mctx);
isc_mem_put(res->mctx, a, sizeof(*a));
}
dns_resolver_reset_algorithms(res);
res->magic = 0;
isc_mem_put(res->mctx, res, sizeof(*res));
}
@@ -5376,6 +5434,7 @@ dns_resolver_create(dns_view_t *view,
res->lame_ttl = 0;
ISC_LIST_INIT(res->alternates);
res->udpsize = RECV_BUFFER_SIZE;
res->algorithms = NULL;
res->nbuckets = ntasks;
res->activebuckets = ntasks;
@@ -5429,12 +5488,23 @@ dns_resolver_create(dns_view_t *view,
if (result != ISC_R_SUCCESS)
goto cleanup_nlock;
#if USE_ALGLOCK
result = isc_rwlock_init(&res->alglock, 0, 0);
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
#endif
res->magic = RES_MAGIC;
*resp = res;
return (ISC_R_SUCCESS);
#if USE_ALGLOCK
cleanup_primelock:
DESTROYLOCK(&res->nlock);
#endif
cleanup_nlock:
DESTROYLOCK(&res->nlock);
@@ -6040,3 +6110,118 @@ dns_resolver_getudpsize(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->udpsize);
}
static void
free_algorithm(void *node, void *arg) {
unsigned char *algorithms = node;
isc_mem_t *mctx = arg;
isc_mem_put(mctx, algorithms, *algorithms);
}
void
dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
#if USE_ALGLOCK
RWLOCK(&resolver->alglock, isc_rwlocktype_write);
#endif
if (resolver->algorithms != NULL)
dns_rbt_destroy(&resolver->algorithms);
#if USE_ALGLOCK
RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
#endif
}
isc_result_t
dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
unsigned int alg)
{
unsigned int len, mask;
unsigned char *new;
unsigned char *algorithms;
isc_result_t result;
dns_rbtnode_t *node = NULL;
REQUIRE(VALID_RESOLVER(resolver));
if (alg > 255)
return (ISC_R_RANGE);
#if USE_ALGLOCK
RWLOCK(&resolver->alglock, isc_rwlocktype_write);
#endif
if (resolver->algorithms == NULL) {
result = dns_rbt_create(resolver->mctx, free_algorithm,
resolver->mctx, &resolver->algorithms);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
len = alg/8 + 2;
mask = 1 << (alg%8);
result = dns_rbt_addnode(resolver->algorithms, name, &node);
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
algorithms = node->data;
if (algorithms == NULL || len > *algorithms) {
new = isc_mem_get(resolver->mctx, len);
if (new == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
memset(new, 0, len);
if (algorithms != NULL)
memcpy(new, algorithms, *algorithms);
new[len-1] |= mask;
*new = len;
node->data = new;
if (algorithms != NULL)
isc_mem_put(resolver->mctx, algorithms,
*algorithms);
} else
algorithms[len-1] |= mask;
}
result = ISC_R_SUCCESS;
cleanup:
#if USE_ALGLOCK
RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
#endif
return (result);
};
isc_boolean_t
dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
unsigned int alg)
{
unsigned int len, mask;
unsigned char *algorithms;
void *data = NULL;
isc_result_t result;
isc_boolean_t found = ISC_FALSE;
REQUIRE(VALID_RESOLVER(resolver));
if (resolver->algorithms == NULL)
return (dst_algorithm_supported(alg));
#if USE_ALGLOCK
RWLOCK(&resolver->alglock, isc_rwlocktype_read)
#endif
result = dns_rbt_findname(resolver->algorithms, name,
DNS_RBTFIND_NOEXACT, NULL, &data);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
len = alg/8 + 2;
mask = 1 << (alg%8);
algorithms = data;
if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
found = ISC_TRUE;
}
#if USE_ALGLOCK
RWUNLOCK(&resolver->alglock, isc_rwlocktype_read)
#endif
if (found)
return (ISC_FALSE);
return (dst_algorithm_supported(alg));
};

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.c,v 1.110 2003/10/17 03:46:44 marka Exp $ */
/* $Id: result.c,v 1.111 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -142,7 +142,9 @@ static const char *text[DNS_R_NRESULTS] = {
"chase DS servers", /* 91 DNS_R_CHASEDSSERVERS */
"empty name", /* 92 DNS_R_EMPTYNAME */
"empty wild", /* 93 DNS_R_EMPTYWILD */
"bad bitmap" /* 94 DNS_R_BADBITMAP */
"bad bitmap", /* 94 DNS_R_BADBITMAP */
"from wildcard" /* 95 DNS_R_FROMWILDCARD */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: sdb.c,v 1.40 2003/09/30 05:56:13 marka Exp $ */
/* $Id: sdb.c,v 1.41 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -1352,7 +1352,9 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_next,
isc__rdatalist_current,
rdataset_clone,
isc__rdatalist_count
isc__rdatalist_count,
isc__rdatalist_addnoqname,
isc__rdatalist_getnoqname
};
static void

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.c,v 1.114 2003/10/25 00:31:11 jinmei Exp $ */
/* $Id: validator.c,v 1.115 2004/01/14 02:06:50 marka Exp $ */
#include <config.h>
@@ -45,11 +45,24 @@
#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
#define VALATTR_SHUTDOWN 0x01
#define VALATTR_FOUNDNONEXISTENCE 0x02
#define VALATTR_TRIEDVERIFY 0x04
#define VALATTR_NEGATIVE 0x08
#define VALATTR_INSECURITY 0x10
#define VALATTR_SHUTDOWN 0x0001
#define VALATTR_FOUNDNONEXISTENCE 0x0002
#define VALATTR_TRIEDVERIFY 0x0004
#define VALATTR_NEGATIVE 0x0008
#define VALATTR_INSECURITY 0x0010
#define VALATTR_NEEDNOQNAME 0x0100
#define VALATTR_NEEDNOWILDCARD 0x0200
#define VALATTR_NEEDNODATA 0x0400
#define VALATTR_FOUNDNOQNAME 0x1000
#define VALATTR_FOUNDNOWILDCARD 0x2000
#define VALATTR_FOUNDNODATA 0x4000
#define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
static void
@@ -432,104 +445,83 @@ dsvalidated(isc_task_t *task, isc_event_t *event) {
destroy(val);
}
static isc_boolean_t
nsecprovesnonexistence(dns_validator_t *val, dns_name_t *nsecname,
dns_rdataset_t *nsecset)
/*
* Return ISC_R_SUCCESS if we can determine that the name doesn't exist
* or we can determine whether there is data or not at the name.
* If the name does not exist return the wildcard name.
*/
static isc_result_t
nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
dns_rdataset_t *nsecset, isc_boolean_t *exists,
isc_boolean_t *data, dns_name_t *wild)
{
int order;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_boolean_t isnxdomain;
isc_result_t result;
dns_namereln_t relation;
unsigned int olabels, nlabels, labels;
dns_rdata_nsec_t nsec;
isc_boolean_t atparent;
INSIST(DNS_MESSAGE_VALID(val->event->message));
if (val->event->message->rcode == dns_rcode_nxdomain)
isnxdomain = ISC_TRUE;
else
isnxdomain = ISC_FALSE;
REQUIRE(exists != NULL);
REQUIRE(data != NULL);
result = dns_rdataset_first(nsecset);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"failure processing NSEC set");
return (ISC_FALSE);
return (result);
}
dns_rdataset_current(nsecset, &rdata);
validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
relation = dns_name_fullcompare(val->event->name, nsecname,
&order, &olabels);
relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
if (order < 0) {
/*
* The name is not within the NSEC range.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC does not cover name, before NSEC");
return (ISC_R_IGNORE);
}
if (order == 0) {
/*
* The names are the same. Look for the type present bit.
* The names are the same.
*/
atparent = dns_rdatatype_atparent(val->event->type);
if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
{
if (!atparent) {
/*
* This NSEC record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
if (isnxdomain) {
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC record seen at nonexistent name");
return (ISC_FALSE);
"ignoring parent nsec");
return (ISC_R_IGNORE);
}
if (val->event->type >= 128) {
validator_log(val, ISC_LOG_DEBUG(3), "invalid type %d",
val->event->type);
return (ISC_FALSE);
} else if (atparent) {
/*
* This NSEC record is from the child.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring child nsec");
return (ISC_R_IGNORE);
}
*exists = ISC_TRUE;
*data = dns_nsec_typepresent(&rdata, val->event->type);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exists (owner) data=%d",
*data);
return (ISC_R_SUCCESS);
}
if (dns_nsec_typepresent(&rdata, val->event->type)) {
validator_log(val, ISC_LOG_DEBUG(3),
"type should not be present");
return (ISC_FALSE);
}
validator_log(val, ISC_LOG_DEBUG(3), "nsec bitmask ok");
} else if (order > 0) {
dns_rdata_nsec_t nsec;
/*
* The NSEC owner name is less than the nonexistent name.
*/
if (!isnxdomain) {
/*
* Is this a empty node?
*/
result = dns_rdata_tostruct(&rdata, &nsec, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
relation = dns_name_fullcompare(&nsec.next,
val->event->name,
&order, &nlabels);
if (order > 0 && relation == dns_namereln_subdomain) {
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves empty node, ok");
return (ISC_TRUE);
}
/*
* Look for empty wildcard matches.
*/
labels = dns_name_countlabels(&nsec.next);
if (nlabels >= olabels && nlabels + 1 < labels) {
dns_name_t wild;
dns_name_init(&wild, NULL);
dns_name_getlabelsequence(&nsec.next,
labels - 1 - nlabels,
nlabels + 1,
&wild);
if (dns_name_iswildcard(&wild)) {
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves empty wildcard, ok");
return (ISC_TRUE);
}
}
/*
* We are not a empty name.
*/
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"missing NSEC record at name");
return (ISC_FALSE);
}
if (dns_name_issubdomain(val->event->name, nsecname) &&
if (relation == dns_namereln_subdomain &&
dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
{
@@ -538,48 +530,63 @@ nsecprovesnonexistence(dns_validator_t *val, dns_name_t *nsecname,
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring parent nsec");
return (ISC_FALSE);
validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
return (ISC_R_IGNORE);
}
result = dns_rdata_tostruct(&rdata, &nsec, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
dns_rdata_reset(&rdata);
relation = dns_name_fullcompare(&nsec.next, val->event->name,
&order, &nlabels);
if (order <= 0) {
/*
* The NSEC next name is less than the nonexistent
* name. This is only ok if the next name is the zone
* name.
*/
if (!dns_name_equal(val->soaname, &nsec.next)) {
validator_log(val, ISC_LOG_DEBUG(3),
"next name is not greater");
return (result);
relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
if (order == 0) {
dns_rdata_freestruct(&nsec);
return (ISC_FALSE);
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring nsec matches next name");
return (ISC_R_IGNORE);
}
validator_log(val, ISC_LOG_DEBUG(3),
"nsec points to zone apex, ok");
} else if (relation == dns_namereln_subdomain) {
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves empty node, bad");
if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
/*
* The name is not within the NSEC range.
*/
dns_rdata_freestruct(&nsec);
return (ISC_FALSE);
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring nsec because name is past end of range");
return (ISC_R_IGNORE);
}
if (order > 0 && relation == dns_namereln_subdomain) {
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exist (empty)");
dns_rdata_freestruct(&nsec);
*exists = ISC_TRUE;
*data = ISC_FALSE;
return (ISC_R_SUCCESS);
}
if (wild != NULL) {
dns_name_t common;
dns_name_init(&common, NULL);
if (olabels > nlabels) {
labels = dns_name_countlabels(nsecname);
dns_name_getlabelsequence(nsecname, labels - olabels,
olabels, &common);
} else {
labels = dns_name_countlabels(&nsec.next);
dns_name_getlabelsequence(&nsec.next, labels - nlabels,
nlabels, &common);
}
result = dns_name_concatenate(dns_wildcardname, &common,
wild, NULL);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"failure generating wilcard name");
return (result);
}
}
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
} else {
validator_log(val, ISC_LOG_DEBUG(3),
"nsec owner name is not less");
/*
* The NSEC owner name is greater than the supposedly
* nonexistent name. This NSEC is irrelevant.
*/
return (ISC_FALSE);
}
return (ISC_TRUE);
*exists = ISC_FALSE;
return (ISC_R_SUCCESS);
}
static void
@@ -589,6 +596,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
dns_rdataset_t *rdataset, *sigrdataset;
isc_boolean_t want_destroy;
isc_result_t result;
isc_boolean_t exists, data;
UNUSED(task);
INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
@@ -616,11 +624,35 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
validator_done(val, result);
}
} else {
if (val->soaname != NULL && val->nsecset != NULL &&
(val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0 &&
nsecprovesnonexistence(val, devent->name, rdataset))
val->attributes |= VALATTR_FOUNDNONEXISTENCE;
dns_name_t **proofs = val->event->proofs;
if (rdataset->trust == dns_trust_secure)
val->seensig = ISC_TRUE;
if (val->nsecset != NULL &&
rdataset->trust == dns_trust_secure &&
((val->attributes & VALATTR_NEEDNODATA) != 0 ||
(val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
(val->attributes & VALATTR_FOUNDNODATA) == 0 &&
(val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
nsecnoexistnodata(val, val->event->name, devent->name,
rdataset, &exists, &data,
dns_fixedname_name(&val->wild))
== ISC_R_SUCCESS)
{
if (exists && !data) {
val->attributes |= VALATTR_FOUNDNODATA;
if (NEEDNODATA(val))
proofs[DNS_VALIDATOR_NODATAPROOF] =
devent->name;
}
if (!exists) {
val->attributes |= VALATTR_FOUNDNOQNAME;
if (NEEDNOQNAME(val))
proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
devent->name;
}
}
result = nsecvalidate(val, ISC_TRUE);
if (result != DNS_R_WAIT)
validator_done(val, result);
@@ -987,13 +1019,22 @@ isselfsigned(dns_validator_t *val) {
static isc_result_t
verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata) {
isc_result_t result;
dns_fixedname_t fixed;
val->attributes |= VALATTR_TRIEDVERIFY;
result = dns_dnssec_verify(val->event->name, val->event->rdataset,
key, ISC_FALSE, val->view->mctx, rdata);
dns_fixedname_init(&fixed);
result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
key, ISC_FALSE, val->view->mctx, rdata,
dns_fixedname_name(&fixed));
validator_log(val, ISC_LOG_DEBUG(3),
"verify rdataset: %s",
isc_result_totext(result));
if (result == DNS_R_FROMWILDCARD) {
if (!dns_name_equal(val->event->name,
dns_fixedname_name(&fixed)))
val->attributes |= VALATTR_NEEDNOQNAME;
result = ISC_R_SUCCESS;
}
return (result);
}
@@ -1046,9 +1087,12 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
/*
* At this point we could check that the signature algorithm
* was known and "sufficiently good". For now, any algorithm
* is acceptable.
* was known and "sufficiently good".
*/
if (!dns_resolver_algorithm_supported(val->view->resolver,
event->name,
val->siginfo->algorithm))
continue;
if (!resume) {
result = get_key(val, val->siginfo);
@@ -1067,7 +1111,6 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
validator_log(val, ISC_LOG_DEBUG(3),
"marking as answer");
return (ISC_R_SUCCESS);
}
do {
@@ -1122,7 +1165,16 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
}
}
val->key = NULL;
if (result == ISC_R_SUCCESS) {
if ((val->attributes & VALATTR_NEEDNOQNAME) != 0) {
if (val->event->message == NULL) {
validator_log(val, ISC_LOG_DEBUG(3),
"no message available for noqname proof");
return (DNS_R_NOVALIDSIG);
}
validator_log(val, ISC_LOG_DEBUG(3),
"looking for noqname proof");
return (nsecvalidate(val, ISC_FALSE));
} else if (result == ISC_R_SUCCESS) {
event->rdataset->trust = dns_trust_secure;
event->sigrdataset->trust = dns_trust_secure;
validator_log(val, ISC_LOG_DEBUG(3),
@@ -1170,6 +1222,7 @@ validatezonekey(dns_validator_t *val, isc_boolean_t resume) {
dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dst_key_t *dstkey;
isc_boolean_t supported_algorithm;
UNUSED(resume);
@@ -1311,6 +1364,8 @@ validatezonekey(dns_validator_t *val, isc_boolean_t resume) {
* verification.
*/
supported_algorithm = ISC_FALSE;
for (result = dns_rdataset_first(val->dsset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(val->dsset))
@@ -1319,6 +1374,13 @@ validatezonekey(dns_validator_t *val, isc_boolean_t resume) {
dns_rdataset_current(val->dsset, &dsrdata);
(void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
if (!dns_resolver_algorithm_supported(val->view->resolver,
val->event->name,
ds.algorithm))
continue;
supported_algorithm = ISC_TRUE;
dns_rdataset_init(&trdataset);
dns_rdataset_clone(val->event->rdataset, &trdataset);
@@ -1356,15 +1418,9 @@ validatezonekey(dns_validator_t *val, isc_boolean_t resume) {
dns_rdataset_current(val->event->sigrdataset,
&sigrdata);
(void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
if (ds.key_tag == sig.keyid &&
ds.algorithm == sig.algorithm)
break;
}
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"no SIG matching DS key");
if (ds.key_tag != sig.keyid &&
ds.algorithm != sig.algorithm)
continue;
}
dstkey = NULL;
result = dns_dnssec_keyfromrdata(val->event->name,
@@ -1379,15 +1435,25 @@ validatezonekey(dns_validator_t *val, isc_boolean_t resume) {
result = verify(val, dstkey, &sigrdata);
dst_key_free(&dstkey);
if (result == ISC_R_SUCCESS)
break;
}
dns_rdataset_disassociate(&trdataset);
if (result == ISC_R_SUCCESS)
break;
validator_log(val, ISC_LOG_DEBUG(3), "no SIG matching DS key");
}
if (result == ISC_R_SUCCESS) {
event->rdataset->trust = dns_trust_secure;
event->sigrdataset->trust = dns_trust_secure;
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
return (result);
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
val->event->rdataset->trust = dns_trust_answer;
val->event->sigrdataset->trust = dns_trust_answer;
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm (ds)");
return (ISC_R_SUCCESS);
} else
return (DNS_R_NOVALIDSIG);
}
@@ -1412,6 +1478,78 @@ start_positive_validation(dns_validator_t *val) {
return (validatezonekey(val, ISC_FALSE));
}
static isc_result_t
checkwildcard(dns_validator_t *val) {
dns_name_t *name, *wild;
dns_message_t *message = val->event->message;
isc_result_t result;
isc_boolean_t exists, data;
char namebuf[DNS_NAME_FORMATSIZE];
wild = dns_fixedname_name(&val->wild);
dns_name_format(wild, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
result == ISC_R_SUCCESS;
result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
{
dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
name = NULL;
dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
if (rdataset->type != dns_rdatatype_nsec)
continue;
val->nsecset = rdataset;
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
{
if (sigrdataset->type == dns_rdatatype_rrsig &&
sigrdataset->covers == rdataset->type)
break;
}
if (sigrdataset == NULL)
continue;
if (rdataset->trust != dns_trust_secure)
continue;
if (((val->attributes & VALATTR_NEEDNODATA) != 0 ||
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
(val->attributes & VALATTR_FOUNDNODATA) == 0 &&
(val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
nsecnoexistnodata(val, wild, name, rdataset,
&exists, &data, NULL)
== ISC_R_SUCCESS)
{
dns_name_t **proofs = val->event->proofs;
if (exists && !data)
val->attributes |= VALATTR_FOUNDNODATA;
if (exists && !data && NEEDNODATA(val))
proofs[DNS_VALIDATOR_NODATAPROOF] =
name;
if (!exists)
val->attributes |=
VALATTR_FOUNDNOWILDCARD;
if (!exists && NEEDNOQNAME(val))
proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
name;
return (ISC_R_SUCCESS);
}
}
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
return (result);
}
static isc_result_t
nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
dns_name_t *name;
@@ -1437,8 +1575,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
rdataset = ISC_LIST_NEXT(val->currentset, link);
val->currentset = NULL;
resume = ISC_FALSE;
}
else
} else
rdataset = ISC_LIST_HEAD(name->list);
for (;
@@ -1465,7 +1602,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
}
if (sigrdataset == NULL)
continue;
val->seensig = ISC_TRUE;
/*
* If a signed zone is missing the zone key, bad
* things could happen. A query for data in the zone
@@ -1508,6 +1644,46 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
if (result != ISC_R_SUCCESS)
return (result);
/*
* Do we only need to check for NOQNAME?
*/
if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
(val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
(val->attributes & VALATTR_NEEDNOQNAME) != 0) {
if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"noqname proof found");
validator_log(val, ISC_LOG_DEBUG(3),
"marking as secure");
val->event->rdataset->trust = dns_trust_secure;
val->event->sigrdataset->trust = dns_trust_secure;
return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3),
"noqname proof not found");
return (DNS_R_NOVALIDNSEC);
}
/*
* Do we need to check for the wildcard?
*/
if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
(((val->attributes & VALATTR_NEEDNODATA) != 0 &&
(val->attributes & VALATTR_FOUNDNODATA) == 0) ||
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
result = checkwildcard(val);
if (result != ISC_R_SUCCESS)
return (result);
}
if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
(val->attributes & VALATTR_FOUNDNODATA) != 0) ||
((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
(val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
(val->attributes & VALATTR_FOUNDNOWILDCARD) != 0))
val->attributes |= VALATTR_FOUNDNONEXISTENCE;
if ((val->attributes & VALATTR_FOUNDNONEXISTENCE) == 0) {
if (!val->seensig && val->soaset != NULL) {
result = create_validator(val, name, dns_rdatatype_soa,
@@ -1528,6 +1704,27 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
}
}
static isc_boolean_t
check_ds_algorithm(dns_validator_t *val, dns_name_t *name,
dns_rdataset_t *rdataset) {
dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdata_ds_t ds;
isc_result_t result;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_rdataset_current(rdataset, &dsrdata);
(void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
if (dns_resolver_algorithm_supported(val->view->resolver,
name, ds.algorithm))
return (ISC_TRUE);
dns_rdata_reset(&dsrdata);
}
return (ISC_FALSE);
}
static isc_result_t
proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
isc_result_t result;
@@ -1552,6 +1749,15 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
dns_name_countlabels(dns_fixedname_name(&secroot)) + 1;
} else {
validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
if (val->frdataset.trust >= dns_trust_secure &&
!check_ds_algorithm(val, dns_fixedname_name(&val->fname),
&val->frdataset)) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm (ds)");
val->event->rdataset->trust = dns_trust_answer;
result = ISC_R_SUCCESS;
goto out;
}
val->labels++;
}
@@ -1561,14 +1767,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
{
char namebuf[DNS_NAME_FORMATSIZE];
if (val->labels == dns_name_countlabels(val->event->name)) {
tname = val->event->name;
} else {
dns_fixedname_init(&val->fname);
tname = dns_fixedname_name(&val->fname);
if (val->labels == dns_name_countlabels(val->event->name))
dns_name_copy(val->event->name, tname, NULL);
else
dns_name_split(val->event->name, val->labels,
NULL, tname);
}
dns_name_format(tname, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3),
@@ -1601,8 +1806,18 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
* There is a DS here. Verify that it's secure and
* continue.
*/
if (val->frdataset.trust >= dns_trust_secure)
if (val->frdataset.trust >= dns_trust_secure) {
if (!check_ds_algorithm(val, tname,
&val->frdataset)) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm (ds)");
val->event->rdataset->trust =
dns_trust_answer;
result = ISC_R_SUCCESS;
goto out;
}
continue;
}
else if (!dns_rdataset_isassociated(&val->fsigrdataset))
{
result = DNS_R_NOVALIDSIG;
@@ -1728,6 +1943,11 @@ validator_start(isc_task_t *task, isc_event_t *event) {
"attempting negative response validation");
val->attributes |= VALATTR_NEGATIVE;
if (val->event->message->rcode == dns_rcode_nxdomain) {
val->attributes |= VALATTR_NEEDNOQNAME;
val->attributes |= VALATTR_NEEDNOWILDCARD;
} else
val->attributes |= VALATTR_NEEDNODATA;
result = nsecvalidate(val, ISC_FALSE);
} else {
/*
@@ -1790,6 +2010,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
event->rdataset = rdataset;
event->sigrdataset = sigrdataset;
event->message = message;
memset(event->proofs, 0, sizeof(event->proofs));
result = isc_mutex_init(&val->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_event;
@@ -1817,6 +2038,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
val->seensig = ISC_FALSE;
dns_rdataset_init(&val->frdataset);
dns_rdataset_init(&val->fsigrdataset);
dns_fixedname_init(&val->wild);
ISC_LINK_INIT(val, link);
val->magic = VALIDATOR_MAGIC;

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.24 2003/09/25 18:16:50 jinmei Exp $ */
/* $Id: namedconf.c,v 1.25 2004/01/14 02:06:51 marka Exp $ */
#include <config.h>
@@ -618,6 +618,21 @@ static cfg_type_t cfg_type_optional_exclude = {
"optional_exclude", parse_optional_keyvalue, print_keyvalue,
doc_optional_keyvalue, &cfg_rep_list, &exclude_kw };
static cfg_type_t cfg_type_algorithmlist = {
"algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
static cfg_tuplefielddef_t disablealgorithm_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "algorithms", &cfg_type_algorithmlist, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_disablealgorithm = {
"disablealgorithm", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
&cfg_rep_tuple, disablealgorithm_fields
};
/*
* Clauses that can be found within the 'view' statement,
* with defaults in the 'options' statement.
@@ -661,6 +676,8 @@ view_clauses[] = {
{ "dual-stack-servers", &cfg_type_nameportiplist, 0 },
{ "edns-udp-size", &cfg_type_uint32, 0 },
{ "root-delegation-only", &cfg_type_optional_exclude, 0 },
{ "disable-algorithms", &cfg_type_disablealgorithm,
CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 }
};