Commit 8d414d15 authored by Mark Andrews's avatar Mark Andrews

1600. [bug] Duplicate zone pre-load checks were not case

                        insensitive.

1599.   [bug]           Fix memory leak on error path when checking named.conf.

1598.   [func]          Specify that certain parts of the namespace must
                        be secure (dnssec-must-be-secure).
parent b4fe7caa
......@@ -32,11 +32,13 @@
"allow-recursion" active' warning from view "_bind".
[RT# 10920]
1600. [placeholder] rt10861.
1600. [bug] Duplicate zone pre-load checks were not case
insensitive.
1599. [placeholder] rt10861.
1599. [bug] Fix memory leak on error path when checking named.conf.
1598. [placeholder] rt10861.
1598. [func] Specify that certain parts of the namespace must
be secure (dnssec-must-be-secure).
1597. [placeholder] rt6496a
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.421 2004/04/10 05:03:27 marka Exp $ */
/* $Id: server.c,v 1.422 2004/04/15 23:40:21 marka Exp $ */
#include <config.h>
......@@ -376,6 +376,39 @@ configure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config,
return (result);
}
static isc_result_t
mustbesecure(cfg_obj_t *mbs, dns_resolver_t *resolver)
{
cfg_listelt_t *element;
cfg_obj_t *obj;
const char *str;
dns_fixedname_t fixed;
dns_name_t *name;
isc_boolean_t value;
isc_result_t result;
isc_buffer_t b;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
for (element = cfg_list_first(mbs);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
str = cfg_obj_asstring(cfg_tuple_get(obj, "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));
value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
CHECK(dns_resolver_setmustbesecure(resolver, name, value));
}
result = ISC_R_SUCCESS;
cleanup:
return (result);
}
/*
* Get a dispatch appropriate for the resolver of a given view.
......@@ -1164,9 +1197,15 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
* For now, there is only one kind of trusted keys, the
* "security roots".
*/
if (view->enablednssec)
if (view->enablednssec) {
CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
&view->secroots));
dns_resolver_resetmustbesecure(view->resolver);
obj = NULL;
result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
if (result == ISC_R_SUCCESS)
CHECK(mustbesecure(obj, view->resolver));
}
obj = NULL;
result = ns_config_get(maps, "max-cache-ttl", &obj);
......
......@@ -13,7 +13,7 @@
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: example.db.in,v 1.13 2004/03/05 05:00:15 marka Exp $
; $Id: example.db.in,v 1.14 2004/04/15 23:40:22 marka Exp $
$TTL 300 ; 5 minutes
@ IN SOA mname1. . (
......@@ -66,6 +66,10 @@ ns.bogus A 10.53.0.3
dynamic NS dynamic
dynamic A 10.53.0.3
; A insecure subdomain
mustbesecure NS ns.mustbesecure
ns.mustbesecure A 10.53.0.3
z A 10.0.0.26
keyless NS ns.keyless
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.25 2004/03/10 02:19:54 marka Exp $ */
/* $Id: named.conf,v 1.26 2004/04/15 23:40:22 marka Exp $ */
// NS3
......@@ -74,4 +74,9 @@ zone "keyless.example" {
file "keyless.example.db.signed";
};
zone "mustbesecure.example" {
type master;
file "mustbesecure.example.db";
};
include "trusted.conf";
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.22 2004/03/10 02:19:54 marka Exp $ */
/* $Id: named.conf,v 1.23 2004/04/15 23:40:23 marka Exp $ */
// NS4
......@@ -31,6 +31,7 @@ options {
listen-on-v6 { none; };
recursion yes;
dnssec-enable yes;
dnssec-must-be-secure mustbesecure.example yes;
};
zone "." {
......
......@@ -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.243 2004/03/30 02:13:44 marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.244 2004/04/15 23:40:23 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
......@@ -2759,6 +2759,7 @@ statement in the <filename>named.conf</filename> file:</para>
<optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable>; </optional>
<optional> dnssec-enable <replaceable>yes_or_no</replaceable>; </optional>
<optional> dnssec-lookaside <replaceable>domain</replaceable>; </optional>
<optional> dnssec-must-be-secure <replaceable>domain yes_or_no</replaceable>; </optional>
<optional> forward ( <replaceable>only</replaceable> | <replaceable>first</replaceable> ); </optional>
<optional> forwarders { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
<optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ) ; ... }; </optional>
......@@ -2990,6 +2991,17 @@ name and a DLV record is looked up. If the DLV record validates
a DNSKEY (similarly to the way a DS record does) the DNSKEY RRset is deemed to be trusted.
</para></listitem></varlistentry>
<varlistentry><term><command>dnssec-must-be-secure</command></term>
<listitem><para>
Specify heirachies which must / may not be secure (signed and validated).
If <userinput>yes</userinput> then named will only accept answers if they
are secure.
If <userinput>no</userinput> then normal dnssec validation applies
allowing for insecure answers to be accepted.
The specified domain must be under a <command>trusted-key</command> or
<command>dnssec-lookaside</command> must be active.
</para></listitem></varlistentry>
</variablelist>
<sect3 id="boolean_options"><title>Boolean Options</title>
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.44 2004/03/10 02:19:55 marka Exp $ */
/* $Id: check.c,v 1.45 2004/04/15 23:40:24 marka Exp $ */
#include <config.h>
......@@ -42,6 +42,13 @@
#include <bind9/check.h>
static void
freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
UNUSED(type);
UNUSED(value);
isc_mem_free(userarg, key);
}
static isc_result_t
check_orderent(cfg_obj_t *ent, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
......@@ -272,6 +279,67 @@ disabled_algorithms(cfg_obj_t *disabled, isc_log_t *logctx) {
return (result);
}
static isc_result_t
mustbesecure(cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
isc_mem_t *mctx)
{
cfg_obj_t *obj;
char namebuf[DNS_NAME_FORMATSIZE];
const char *str;
dns_fixedname_t fixed;
dns_name_t *name;
isc_buffer_t b;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
isc_symvalue_t symvalue;
char *key;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
obj = cfg_tuple_get(secure, "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;
} else {
dns_name_format(name, namebuf, sizeof(namebuf));
key = isc_mem_strdup(mctx, namebuf);
if (key == NULL)
return (ISC_R_NOMEMORY);
symvalue.as_pointer = secure;
tresult = isc_symtab_define(symtab, key, 1, symvalue,
isc_symexists_reject);
if (tresult == ISC_R_EXISTS) {
const char *file;
unsigned int line;
RUNTIME_CHECK(isc_symtab_lookup(symtab, key, 1,
&symvalue) == ISC_R_SUCCESS);
isc_mem_free(mctx, key);
file = cfg_obj_file(symvalue.as_pointer);
line = cfg_obj_line(symvalue.as_pointer);
if (file == NULL)
file = "<unknown file>";
cfg_obj_log(secure, logctx, ISC_LOG_ERROR,
"dnssec-must-be-secure '%s': already "
"exists previous definition: %s:%u",
namebuf, file, line);
result = tresult;
} else if (tresult != ISC_R_SUCCESS) {
isc_mem_free(mctx, key);
result = tresult;
}
}
return (result);
}
typedef struct {
const char *name;
unsigned int scale;
......@@ -279,7 +347,7 @@ typedef struct {
} intervaltable;
static isc_result_t
check_options(cfg_obj_t *options, isc_log_t *logctx) {
check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
unsigned int i;
......@@ -406,6 +474,31 @@ check_options(cfg_obj_t *options, isc_log_t *logctx) {
result = tresult;
}
}
/*
* Check dnssec-must-be-secure.
*/
obj = NULL;
(void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
if (obj != NULL) {
isc_symtab_t *symtab = NULL;
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
ISC_FALSE, &symtab);
if (tresult != ISC_R_SUCCESS)
result = tresult;
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
tresult = mustbesecure(obj, symtab, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
if (symtab != NULL)
isc_symtab_destroy(&symtab);
}
return (result);
}
......@@ -703,7 +796,8 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
zname, file, line);
result = ISC_R_FAILURE;
} else if (tresult != ISC_R_SUCCESS) {
isc_mem_strdup(mctx, key);
isc_mem_free(mctx, key);
return (tresult);
}
}
......@@ -818,7 +912,7 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
/*
* Check various options.
*/
tresult = check_options(zoptions, logctx);
tresult = check_options(zoptions, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
......@@ -886,13 +980,6 @@ check_keylist(cfg_obj_t *keys, isc_symtab_t *symtab, isc_log_t *logctx) {
return (result);
}
static void
freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
UNUSED(type);
UNUSED(value);
isc_mem_free(userarg, key);
}
static isc_result_t
check_servers(cfg_obj_t *servers, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
......@@ -969,7 +1056,7 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
* there are no duplicate zones.
*/
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
ISC_TRUE, &symtab);
ISC_FALSE, &symtab);
if (tresult != ISC_R_SUCCESS)
return (ISC_R_NOMEMORY);
......@@ -1067,9 +1154,9 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
}
if (vconfig != NULL)
tresult = check_options(vconfig, logctx);
tresult = check_options(vconfig, logctx, mctx);
else
tresult = check_options(config, logctx);
tresult = check_options(config, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
......@@ -1095,7 +1182,7 @@ bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
(void)cfg_map_get(config, "options", &options);
if (options != NULL &&
check_options(options, logctx) != ISC_R_SUCCESS)
check_options(options, logctx, mctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
(void)cfg_map_get(config, "server", &servers);
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.40 2004/03/05 05:09:46 marka Exp $ */
/* $Id: resolver.h,v 1.41 2004/04/15 23:40:26 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
......@@ -416,6 +416,16 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
* crypto libraries if not specifically disabled.
*/
void
dns_resolver_resetmustbesecure(dns_resolver_t *resolver);
isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
isc_boolean_t value);
isc_boolean_t
dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name);
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.h,v 1.104 2004/03/22 01:46:01 marka Exp $ */
/* $Id: result.h,v 1.105 2004/04/15 23:40:26 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
......@@ -141,8 +141,9 @@
#define DNS_R_BADNAME (ISC_RESULTCLASS_DNS + 97)
#define DNS_R_DYNAMIC (ISC_RESULTCLASS_DNS + 98)
#define DNS_R_UNKNOWNCOMMAND (ISC_RESULTCLASS_DNS + 99)
#define DNS_R_MUSTBESECURE (ISC_RESULTCLASS_DNS + 100)
#define DNS_R_NRESULTS 100 /* Number of results */
#define DNS_R_NRESULTS 101 /* Number of results */
/*
* DNS wire format rcodes.
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.h,v 1.27 2004/03/10 02:19:56 marka Exp $ */
/* $Id: validator.h,v 1.28 2004/04/15 23:40:26 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
......@@ -121,6 +121,7 @@ struct dns_validator {
dns_fixedname_t wild;
ISC_LINK(dns_validator_t) link;
dns_rdataset_t * dlv;
isc_boolean_t mustbesecure;
};
ISC_LANG_BEGINDECLS
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.285 2004/04/15 01:58:24 marka Exp $ */
/* $Id: resolver.c,v 1.286 2004/04/15 23:40:24 marka Exp $ */
#include <config.h>
......@@ -288,10 +288,14 @@ struct dns_resolver {
isc_uint32_t lame_ttl;
ISC_LIST(alternate_t) alternates;
isc_uint16_t udpsize;
#if USE_ALGLOG
#if USE_ALGLOCK
isc_rwlock_t alglock;
#endif
dns_rbt_t * algorithms;
#if USE_MBSLOCK
isc_rwlock_t mbslock;
#endif
dns_rbt_t * mustbesecure;
/* Locked by lock. */
unsigned int references;
isc_boolean_t exiting;
......@@ -5438,6 +5442,13 @@ destroy(dns_resolver_t *res) {
isc_mem_put(res->mctx, a, sizeof(*a));
}
dns_resolver_reset_algorithms(res);
dns_resolver_resetmustbesecure(res);
#if USE_ALGLOCK
isc_rwlock_destroy(&res->alglock);
#endif
#if USE_MBSLOCK
isc_rwlock_destroy(&res->mbslock);
#endif
res->magic = 0;
isc_mem_put(res->mctx, res, sizeof(*res));
}
......@@ -5518,6 +5529,7 @@ dns_resolver_create(dns_view_t *view,
ISC_LIST_INIT(res->alternates);
res->udpsize = RECV_BUFFER_SIZE;
res->algorithms = NULL;
res->mustbesecure = NULL;
res->nbuckets = ntasks;
res->activebuckets = ntasks;
......@@ -5576,6 +5588,11 @@ dns_resolver_create(dns_view_t *view,
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
#endif
#if USE_MBSLOCK
result = isc_rwlock_init(&res->mbslock, 0, 0);
if (result != ISC_R_SUCCESS)
goto cleanup_alglock;
#endif
res->magic = RES_MAGIC;
......@@ -5583,9 +5600,15 @@ dns_resolver_create(dns_view_t *view,
return (ISC_R_SUCCESS);
#if USE_MBSLOCK
cleanup_alglock:
#if USE_ALGLOCK
isc_rwlock_destroy(&res->alglock);
#endif
#endif
#if USE_ALGLOCK || USE_MBSLOCK
cleanup_primelock:
DESTROYLOCK(&res->nlock);
DESTROYLOCK(&res->primelock);
#endif
cleanup_nlock:
......@@ -6286,14 +6309,12 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
REQUIRE(VALID_RESOLVER(resolver));
if (resolver->algorithms == NULL)
return (dst_algorithm_supported(alg));
#if USE_ALGLOCK
RWLOCK(&resolver->alglock, isc_rwlocktype_read)
RWLOCK(&resolver->alglock, isc_rwlocktype_read);
#endif
result = dns_rbt_findname(resolver->algorithms, name,
DNS_RBTFIND_NOEXACT, NULL, &data);
if (resolver->algorithms == NULL)
goto unlock;
result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
len = alg/8 + 2;
mask = 1 << (alg%8);
......@@ -6301,10 +6322,77 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
found = ISC_TRUE;
}
unlock:
#if USE_ALGLOCK
RWUNLOCK(&resolver->alglock, isc_rwlocktype_read)
RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
#endif
if (found)
return (ISC_FALSE);
return (dst_algorithm_supported(alg));
}
void
dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
#if USE_MBSLOCK
RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
if (resolver->mustbesecure != NULL)
dns_rbt_destroy(&resolver->mustbesecure);
#if USE_MBSLOCK
RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
}
static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
isc_boolean_t value)
{
isc_result_t result;
REQUIRE(VALID_RESOLVER(resolver));
#if USE_MBSLOCK
RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
if (resolver->mustbesecure == NULL) {
result = dns_rbt_create(resolver->mctx, NULL, NULL,
&resolver->mustbesecure);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
result = dns_rbt_addname(resolver->mustbesecure, name,
value ? &yes : &no);
cleanup:
#if USE_MBSLOCK
RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
return (result);
}
isc_boolean_t
dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
void *data = NULL;
isc_boolean_t value = ISC_FALSE;
isc_result_t result;
REQUIRE(VALID_RESOLVER(resolver));
#if USE_MBSLOCK
RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
#endif
if (resolver->mustbesecure == NULL)
goto unlock;
result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
value = *(isc_boolean_t*)data;
unlock:
#if USE_MBSLOCK
RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
#endif
return (value);
}
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.c,v 1.115 2004/03/22 01:46:01 marka Exp $ */
/* $Id: result.c,v 1.116 2004/04/15 23:40:25 marka Exp $ */
#include <config.h>
......@@ -148,7 +148,9 @@ static const char *text[DNS_R_NRESULTS] = {
"bad owner name (check-names)", /* 96 DNS_R_BADOWNERNAME */
"bad name (check-names)", /* 97 DNS_R_BADNAME */
"dynamic zone", /* 98 DNS_R_DYNAMIC */
"unknown command" /* 99 DNS_R_UNKNOWNCOMMAND */
"unknown command", /* 99 DNS_R_UNKNOWNCOMMAND */
"must-be-secure" /* 100 DNS_R_MUSTBESECURE */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.c,v 1.120 2004/04/15 01:58:24 marka Exp $ */
/* $Id: validator.c,v 1.121 2004/04/15 23:40:25 marka Exp $ */
#include <config.h>
......@@ -348,8 +348,14 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
*/
tname = dns_fixedname_name(&devent->foundname