2001-03-01 23:46:49 +00:00
|
|
|
/*
|
2007-03-14 23:46:54 +00:00
|
|
|
* Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
|
2004-03-05 05:14:21 +00:00
|
|
|
* Copyright (C) 2001-2003 Internet Software Consortium.
|
2001-03-01 23:46:49 +00:00
|
|
|
*
|
2007-06-18 23:47:57 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
2001-03-01 23:46:49 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
2004-03-05 05:14:21 +00:00
|
|
|
* 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.
|
2001-03-01 23:46:49 +00:00
|
|
|
*/
|
|
|
|
|
2007-06-18 23:47:57 +00:00
|
|
|
/* $Id: check.c,v 1.80 2007/06/18 23:47:39 tbox Exp $ */
|
2005-04-27 04:57:32 +00:00
|
|
|
|
|
|
|
/*! \file */
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2002-02-06 05:58:06 +00:00
|
|
|
#include <isc/buffer.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isc/log.h>
|
2002-02-12 13:17:23 +00:00
|
|
|
#include <isc/mem.h>
|
2002-03-04 05:07:06 +00:00
|
|
|
#include <isc/netaddr.h>
|
2004-01-14 02:06:51 +00:00
|
|
|
#include <isc/parseint.h>
|
2002-02-12 13:17:23 +00:00
|
|
|
#include <isc/region.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isc/result.h>
|
2002-03-04 05:07:06 +00:00
|
|
|
#include <isc/sockaddr.h>
|
2001-03-08 00:55:50 +00:00
|
|
|
#include <isc/symtab.h>
|
2001-03-03 23:09:23 +00:00
|
|
|
#include <isc/util.h>
|
2001-09-20 15:17:07 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
#include <dns/acl.h>
|
2002-02-06 05:58:06 +00:00
|
|
|
#include <dns/fixedname.h>
|
2002-03-08 00:54:48 +00:00
|
|
|
#include <dns/rdataclass.h>
|
|
|
|
#include <dns/rdatatype.h>
|
2004-01-14 02:06:51 +00:00
|
|
|
#include <dns/secalg.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
#include <isccfg/aclconf.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isccfg/cfg.h>
|
2001-09-20 15:17:07 +00:00
|
|
|
|
|
|
|
#include <bind9/check.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2007-03-14 05:57:10 +00:00
|
|
|
#ifndef DNS_RDATASET_FIXED
|
|
|
|
#define DNS_RDATASET_FIXED 1
|
|
|
|
#endif
|
|
|
|
|
2004-04-15 23:40:27 +00:00
|
|
|
static void
|
|
|
|
freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
|
|
|
|
UNUSED(type);
|
|
|
|
UNUSED(value);
|
|
|
|
isc_mem_free(userarg, key);
|
|
|
|
}
|
|
|
|
|
2002-03-08 00:54:48 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
|
2002-03-08 00:54:48 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
isc_textregion_t r;
|
|
|
|
dns_fixedname_t fixed;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2002-03-08 00:54:48 +00:00
|
|
|
dns_rdataclass_t rdclass;
|
|
|
|
dns_rdatatype_t rdtype;
|
|
|
|
isc_buffer_t b;
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
obj = cfg_tuple_get(ent, "class");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
|
|
|
|
DE_CONST(cfg_obj_asstring(obj), r.base);
|
|
|
|
r.length = strlen(r.base);
|
|
|
|
tresult = dns_rdataclass_fromtext(&rdclass, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid class '%s'",
|
|
|
|
r.base);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "type");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
|
|
|
|
DE_CONST(cfg_obj_asstring(obj), r.base);
|
|
|
|
r.length = strlen(r.base);
|
|
|
|
tresult = dns_rdatatype_fromtext(&rdtype, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid type '%s'",
|
|
|
|
r.base);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "name");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid name '%s'", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "order");
|
|
|
|
if (!cfg_obj_isstring(obj) ||
|
|
|
|
strcasecmp("order", cfg_obj_asstring(obj)) != 0) {
|
|
|
|
cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: keyword 'order' missing");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "ordering");
|
|
|
|
if (!cfg_obj_isstring(obj)) {
|
|
|
|
cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: missing ordering");
|
|
|
|
result = ISC_R_FAILURE;
|
2007-03-14 05:57:10 +00:00
|
|
|
} else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
|
|
|
|
#if !DNS_RDATASET_FIXED
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"rrset-order: order 'fixed' not fully implemented");
|
|
|
|
#endif
|
|
|
|
} else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
|
2002-03-08 00:54:48 +00:00
|
|
|
strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid order '%s'",
|
|
|
|
cfg_obj_asstring(obj));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_order(const cfg_obj_t *options, isc_log_t *logctx) {
|
2002-03-08 00:54:48 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2002-03-08 00:54:48 +00:00
|
|
|
|
|
|
|
if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
tresult = check_orderent(cfg_listelt_value(element), logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2003-01-16 03:59:28 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *alternates = NULL;
|
|
|
|
const cfg_obj_t *value;
|
|
|
|
const cfg_obj_t *obj;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str;
|
2003-01-16 03:59:28 +00:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
|
|
|
|
(void)cfg_map_get(options, "dual-stack-servers", &alternates);
|
|
|
|
|
|
|
|
if (alternates == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(alternates, "port");
|
|
|
|
if (cfg_obj_isuint32(obj)) {
|
|
|
|
isc_uint32_t val = cfg_obj_asuint32(obj);
|
|
|
|
if (val > ISC_UINT16_MAX) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port '%u' out of range", val);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
obj = cfg_tuple_get(alternates, "addresses");
|
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element)) {
|
|
|
|
value = cfg_listelt_value(element);
|
|
|
|
if (cfg_obj_issockaddr(value))
|
|
|
|
continue;
|
|
|
|
obj = cfg_tuple_get(value, "name");
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
isc_buffer_init(&buffer, str, strlen(str));
|
|
|
|
isc_buffer_add(&buffer, strlen(str));
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
name = dns_fixedname_name(&fixed);
|
|
|
|
tresult = dns_name_fromtext(name, &buffer, dns_rootname,
|
|
|
|
ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad name '%s'", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
obj = cfg_tuple_get(value, "port");
|
|
|
|
if (cfg_obj_isuint32(obj)) {
|
|
|
|
isc_uint32_t val = cfg_obj_asuint32(obj);
|
|
|
|
if (val > ISC_UINT16_MAX) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port '%u' out of range", val);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_forward(const cfg_obj_t *options, isc_log_t *logctx) {
|
|
|
|
const cfg_obj_t *forward = NULL;
|
|
|
|
const cfg_obj_t *forwarders = NULL;
|
2001-03-09 19:07:30 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(options, "forward", &forward);
|
|
|
|
(void)cfg_map_get(options, "forwarders", &forwarders);
|
|
|
|
|
|
|
|
if (forward != NULL && forwarders == NULL) {
|
|
|
|
cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
|
|
|
|
"no matching 'forwarders' statement");
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2004-01-14 02:06:51 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
|
2004-01-14 02:06:51 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
2004-01-14 02:06:51 +00:00
|
|
|
const char *str;
|
|
|
|
isc_buffer_t b;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2004-01-14 02:06:51 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2005-08-23 02:36:11 +00:00
|
|
|
DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
|
2004-01-14 02:06:51 +00:00
|
|
|
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,
|
2005-08-23 02:36:11 +00:00
|
|
|
ISC_LOG_ERROR, "invalid algorithm '%s'",
|
|
|
|
r.base);
|
2004-01-14 02:06:51 +00:00
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-06-04 02:31:43 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
nameexist(const cfg_obj_t *obj, const char *name, int value,
|
|
|
|
isc_symtab_t *symtab, const char *fmt, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx)
|
2004-06-04 02:31:43 +00:00
|
|
|
{
|
|
|
|
char *key;
|
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
|
|
|
key = isc_mem_strdup(mctx, name);
|
|
|
|
if (key == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = obj;
|
2004-06-04 02:31:43 +00:00
|
|
|
result = isc_symtab_define(symtab, key, value, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
|
|
|
|
&symvalue) == ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2004-06-04 02:31:43 +00:00
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
file = "<unknown file>";
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
|
|
|
|
isc_mem_free(mctx, key);
|
|
|
|
result = ISC_R_EXISTS;
|
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, key);
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-04-15 23:40:27 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
|
2004-04-15 23:40:27 +00:00
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2004-04-15 23:40:27 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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));
|
2004-06-04 02:31:43 +00:00
|
|
|
result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2004-04-15 23:40:27 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", str);
|
|
|
|
} else {
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
2004-06-04 02:31:43 +00:00
|
|
|
result = nameexist(secure, namebuf, 1, symtab,
|
|
|
|
"dnssec-must-be-secure '%s': already "
|
|
|
|
"exists previous definition: %s:%u",
|
|
|
|
logctx, mctx);
|
2004-04-15 23:40:27 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
|
|
|
|
const cfg_obj_t *voptions, const cfg_obj_t *config,
|
|
|
|
isc_log_t *logctx, isc_mem_t *mctx)
|
2005-01-11 03:46:11 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *aclobj = NULL;
|
|
|
|
const cfg_obj_t *options;
|
2005-01-11 03:46:11 +00:00
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
|
|
|
|
if (zconfig != NULL) {
|
|
|
|
options = cfg_tuple_get(zconfig, "options");
|
|
|
|
cfg_map_get(options, aclname, &aclobj);
|
|
|
|
}
|
|
|
|
if (voptions != NULL && aclobj == NULL)
|
|
|
|
cfg_map_get(voptions, aclname, &aclobj);
|
|
|
|
if (config != NULL && aclobj == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL)
|
|
|
|
cfg_map_get(options, aclname, &aclobj);
|
|
|
|
}
|
|
|
|
if (aclobj == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
2005-09-12 02:04:41 +00:00
|
|
|
result = cfg_acl_fromconfig(aclobj, config, logctx, actx, mctx, &acl);
|
2005-01-11 03:46:11 +00:00
|
|
|
if (acl != NULL)
|
|
|
|
dns_acl_detach(&acl);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
|
|
|
const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
|
2005-01-11 03:46:11 +00:00
|
|
|
{
|
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
|
|
|
int i = 0;
|
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
static const char *acls[] = { "allow-query", "allow-query-on",
|
|
|
|
"allow-query-cache", "allow-query-cache-on",
|
|
|
|
"blackhole", "match-clients", "match-destinations",
|
|
|
|
"sortlist", NULL };
|
2005-01-11 03:46:11 +00:00
|
|
|
|
|
|
|
while (acls[i] != NULL) {
|
2005-09-12 02:04:41 +00:00
|
|
|
tresult = checkacl(acls[i++], actx, NULL, voptions, config,
|
2005-01-11 03:46:11 +00:00
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
/*
|
|
|
|
* Check allow-recursion and allow-recursion-on acls, and also log a
|
|
|
|
* warning if they're inconsistent with the "recursion" option.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
|
|
|
const char *viewname, const cfg_obj_t *config,
|
|
|
|
isc_log_t *logctx, isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
const cfg_obj_t *options, *aclobj, *obj = NULL;
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
|
|
|
isc_boolean_t recursion;
|
|
|
|
const char *forview = " for view ";
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
static const char *acls[] = { "allow-recursion", "allow-recursion-on",
|
|
|
|
NULL };
|
|
|
|
|
|
|
|
if (voptions != NULL)
|
|
|
|
cfg_map_get(voptions, "recursion", &obj);
|
|
|
|
if (obj == NULL && config != NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL)
|
|
|
|
cfg_map_get(options, "recursion", &obj);
|
|
|
|
}
|
|
|
|
if (obj == NULL)
|
|
|
|
recursion = ISC_TRUE;
|
|
|
|
else
|
|
|
|
recursion = cfg_obj_asboolean(obj);
|
|
|
|
|
|
|
|
if (viewname == NULL) {
|
|
|
|
viewname = "";
|
|
|
|
forview = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; acls[i] != NULL; i++) {
|
|
|
|
aclobj = options = NULL;
|
|
|
|
acl = NULL;
|
|
|
|
|
|
|
|
if (voptions != NULL)
|
|
|
|
cfg_map_get(voptions, acls[i], &aclobj);
|
|
|
|
if (config != NULL && aclobj == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL)
|
|
|
|
cfg_map_get(options, acls[i], &aclobj);
|
|
|
|
}
|
|
|
|
if (aclobj == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tresult = cfg_acl_fromconfig(aclobj, config, logctx,
|
|
|
|
actx, mctx, &acl);
|
|
|
|
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
|
|
|
|
if (acl == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (recursion == ISC_FALSE &&
|
|
|
|
(acl->length != 1 ||
|
|
|
|
acl->elements[0].type != dns_aclelementtype_any ||
|
|
|
|
acl->elements[0].negative != ISC_TRUE)) {
|
|
|
|
cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
|
|
|
|
"both \"recursion no;\" and "
|
|
|
|
"\"%s\" active%s%s",
|
|
|
|
acls[i], forview, viewname);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acl != NULL)
|
|
|
|
dns_acl_detach(&acl);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
unsigned int scale;
|
2001-11-09 03:34:55 +00:00
|
|
|
unsigned int max;
|
2001-06-04 21:51:27 +00:00
|
|
|
} intervaltable;
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
|
2001-06-04 21:51:27 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2004-01-14 02:06:51 +00:00
|
|
|
isc_result_t tresult;
|
2001-06-04 21:51:27 +00:00
|
|
|
unsigned int i;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
const cfg_listelt_t *element;
|
2004-06-04 02:31:43 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2005-08-18 00:57:31 +00:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
const char *str;
|
|
|
|
dns_name_t *name;
|
|
|
|
isc_buffer_t b;
|
2001-06-04 21:51:27 +00:00
|
|
|
|
|
|
|
static intervaltable intervals[] = {
|
2001-11-09 03:34:55 +00:00
|
|
|
{ "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "heartbeat-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "interface-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "max-transfer-idle-in", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "max-transfer-idle-out", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "max-transfer-time-in", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "max-transfer-time-out", 60, 28 * 24 * 60 }, /* 28 days */
|
|
|
|
{ "sig-validity-interval", 86400, 10 * 366 }, /* 10 years */
|
|
|
|
{ "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */
|
2001-06-04 21:51:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that fields specified in units of time other than seconds
|
|
|
|
* have reasonable values.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
|
|
|
|
isc_uint32_t val;
|
2001-12-29 04:49:51 +00:00
|
|
|
obj = NULL;
|
2001-06-04 21:51:27 +00:00
|
|
|
(void)cfg_map_get(options, intervals[i].name, &obj);
|
|
|
|
if (obj == NULL)
|
|
|
|
continue;
|
|
|
|
val = cfg_obj_asuint32(obj);
|
2001-11-09 03:34:55 +00:00
|
|
|
if (val > intervals[i].max) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%u' is out of range (0..%u)",
|
|
|
|
intervals[i].name, val,
|
|
|
|
intervals[i].max);
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
} else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
|
2001-06-04 21:51:27 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%d' is out of range",
|
|
|
|
intervals[i].name, val);
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
}
|
2002-04-26 00:40:37 +00:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "preferred-glue", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
const char *str;
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
if (strcasecmp(str, "a") != 0 &&
|
|
|
|
strcasecmp(str, "aaaa") != 0 &&
|
|
|
|
strcasecmp(str, "none") != 0)
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"preferred-glue unexpected value '%s'",
|
|
|
|
str);
|
|
|
|
}
|
2003-09-19 12:39:49 +00:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "root-delegation-only", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
if (!cfg_obj_isvoid(obj)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *exclude;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str;
|
2003-09-19 12:39:49 +00:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
isc_buffer_t b;
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
name = dns_fixedname_name(&fixed);
|
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element)) {
|
|
|
|
exclude = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(exclude);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-14 02:06:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-18 00:57:31 +00:00
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
name = dns_fixedname_name(&fixed);
|
|
|
|
|
2004-03-10 02:19:58 +00:00
|
|
|
/*
|
|
|
|
* Check the DLV zone name.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "dnssec-lookaside", &obj);
|
|
|
|
if (obj != NULL) {
|
2004-06-04 02:31:43 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
|
|
|
|
ISC_TRUE, &symtab);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2004-03-10 02:19:58 +00:00
|
|
|
result = tresult;
|
2004-06-04 02:31:43 +00:00
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
const char *dlv;
|
|
|
|
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
|
|
|
|
dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain"));
|
|
|
|
isc_buffer_init(&b, dlv, strlen(dlv));
|
|
|
|
isc_buffer_add(&b, strlen(dlv));
|
|
|
|
tresult = dns_name_fromtext(name, &b, dns_rootname,
|
|
|
|
ISC_TRUE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", dlv);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
if (symtab != NULL) {
|
|
|
|
tresult = nameexist(obj, dlv, 1, symtab,
|
|
|
|
"dnssec-lookaside '%s': "
|
|
|
|
"already exists previous "
|
|
|
|
"definition: %s:%u",
|
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS &&
|
|
|
|
result == ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* XXXMPA to be removed when multiple lookaside
|
|
|
|
* namespaces are supported.
|
|
|
|
*/
|
|
|
|
if (!dns_name_equal(dns_rootname, name)) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnssec-lookaside '%s': "
|
|
|
|
"non-root not yet supported", dlv);
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
dlv = cfg_obj_asstring(cfg_tuple_get(obj,
|
|
|
|
"trust-anchor"));
|
|
|
|
isc_buffer_init(&b, dlv, strlen(dlv));
|
|
|
|
isc_buffer_add(&b, strlen(dlv));
|
|
|
|
tresult = dns_name_fromtext(name, &b, dns_rootname,
|
|
|
|
ISC_TRUE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", dlv);
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
2004-03-10 02:19:58 +00:00
|
|
|
}
|
2004-06-04 02:31:43 +00:00
|
|
|
if (symtab != NULL)
|
|
|
|
isc_symtab_destroy(&symtab);
|
2004-03-10 02:19:58 +00:00
|
|
|
}
|
2004-04-15 23:40:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2005-08-18 00:57:31 +00:00
|
|
|
/*
|
|
|
|
* Check empty zone configuration.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "empty-server", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"empty-server: invalid name '%s'", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "empty-contact", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"empty-contact: invalid name '%s'", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "disable-empty-zone", &obj);
|
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"disable-empty-zone: invalid name '%s'",
|
|
|
|
str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2003-02-26 06:04:03 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_result_t result;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *masters = NULL;
|
|
|
|
const cfg_listelt_t *elt;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
result = cfg_map_get(cctx, "masters", &masters);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
for (elt = cfg_list_first(masters);
|
|
|
|
elt != NULL;
|
|
|
|
elt = cfg_list_next(elt)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *list;
|
2003-02-26 06:04:03 +00:00
|
|
|
const char *listname;
|
|
|
|
|
|
|
|
list = cfg_listelt_value(elt);
|
|
|
|
listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
|
|
|
|
|
|
|
|
if (strcasecmp(listname, name) == 0) {
|
|
|
|
*ret = list;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
|
|
|
|
isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
|
2003-02-26 06:04:03 +00:00
|
|
|
{
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
isc_uint32_t count = 0;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
isc_symvalue_t symvalue;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_listelt_t **stack = NULL;
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_uint32_t stackcount = 0, pushed = 0;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *list;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
REQUIRE(countp != NULL);
|
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
|
2005-11-03 22:59:53 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
*countp = count;
|
2003-02-26 06:04:03 +00:00
|
|
|
return (result);
|
2005-11-03 22:59:53 +00:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
newlist:
|
|
|
|
list = cfg_tuple_get(obj, "addresses");
|
|
|
|
element = cfg_list_first(list);
|
|
|
|
resume:
|
|
|
|
for ( ;
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *listname;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *addr;
|
|
|
|
const cfg_obj_t *key;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
addr = cfg_tuple_get(cfg_listelt_value(element),
|
|
|
|
"masterselement");
|
|
|
|
key = cfg_tuple_get(cfg_listelt_value(element), "key");
|
|
|
|
|
|
|
|
if (cfg_obj_issockaddr(addr)) {
|
|
|
|
count++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!cfg_obj_isvoid(key)) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"unexpected token '%s'",
|
|
|
|
cfg_obj_asstring(key));
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
listname = cfg_obj_asstring(addr);
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = addr;
|
2003-02-26 06:04:03 +00:00
|
|
|
tresult = isc_symtab_define(symtab, listname, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS)
|
|
|
|
continue;
|
|
|
|
tresult = get_masters_def(config, listname, &obj);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
|
|
|
|
"unable to find masters list '%s'",
|
|
|
|
listname);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Grow stack? */
|
|
|
|
if (stackcount == pushed) {
|
|
|
|
void * new;
|
|
|
|
isc_uint32_t newlen = stackcount + 16;
|
|
|
|
size_t newsize, oldsize;
|
|
|
|
|
|
|
|
newsize = newlen * sizeof(*stack);
|
|
|
|
oldsize = stackcount * sizeof(*stack);
|
|
|
|
new = isc_mem_get(mctx, newsize);
|
|
|
|
if (new == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
if (stackcount != 0) {
|
|
|
|
memcpy(new, stack, oldsize);
|
|
|
|
isc_mem_put(mctx, stack, oldsize);
|
|
|
|
}
|
|
|
|
stack = new;
|
|
|
|
stackcount = newlen;
|
|
|
|
}
|
|
|
|
stack[pushed++] = cfg_list_next(element);
|
|
|
|
goto newlist;
|
|
|
|
}
|
|
|
|
if (pushed != 0) {
|
|
|
|
element = stack[--pushed];
|
|
|
|
goto resume;
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (stack != NULL)
|
|
|
|
isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
*countp = count;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2005-07-28 05:42:20 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
|
2005-07-28 05:42:20 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_listelt_t *element2;
|
2005-07-28 05:42:20 +00:00
|
|
|
dns_fixedname_t fixed;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str;
|
2005-07-28 05:42:20 +00:00
|
|
|
isc_buffer_t b;
|
|
|
|
|
|
|
|
for (element = cfg_list_first(policy);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *stmt = cfg_listelt_value(element);
|
|
|
|
const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
|
|
|
|
const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
|
|
|
|
const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
|
|
|
|
const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
|
2005-07-28 05:42:20 +00:00
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
str = cfg_obj_asstring(identity);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name", str);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
str = cfg_obj_asstring(dname);
|
|
|
|
isc_buffer_init(&b, str, strlen(str));
|
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
|
|
|
dns_rootname, ISC_FALSE, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name", str);
|
|
|
|
result = tresult;
|
|
|
|
}
|
2006-08-21 00:11:43 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS &&
|
|
|
|
strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 &&
|
|
|
|
!dns_name_iswildcard(dns_fixedname_name(&fixed))) {
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a wildcard", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2005-07-28 05:42:20 +00:00
|
|
|
|
|
|
|
for (element2 = cfg_list_first(typelist);
|
|
|
|
element2 != NULL;
|
|
|
|
element2 = cfg_list_next(element2))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *typeobj;
|
2005-07-28 05:42:20 +00:00
|
|
|
isc_textregion_t r;
|
|
|
|
dns_rdatatype_t type;
|
|
|
|
|
|
|
|
typeobj = cfg_listelt_value(element2);
|
2005-08-23 02:36:11 +00:00
|
|
|
DE_CONST(cfg_obj_asstring(typeobj), r.base);
|
|
|
|
r.length = strlen(r.base);
|
2005-07-28 05:42:20 +00:00
|
|
|
|
|
|
|
tresult = dns_rdatatype_fromtext(&type, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
|
2005-08-23 02:36:11 +00:00
|
|
|
"'%s' is not a valid type", r.base);
|
2005-07-28 05:42:20 +00:00
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
#define MASTERZONE 1
|
|
|
|
#define SLAVEZONE 2
|
|
|
|
#define STUBZONE 4
|
|
|
|
#define HINTZONE 8
|
|
|
|
#define FORWARDZONE 16
|
2003-09-17 05:24:43 +00:00
|
|
|
#define DELEGATIONZONE 32
|
2005-01-11 03:46:11 +00:00
|
|
|
#define CHECKACL 64
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
int allowed;
|
|
|
|
} optionstable;
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|
|
|
const cfg_obj_t *config, isc_symtab_t *symtab,
|
|
|
|
dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
|
|
|
|
isc_log_t *logctx, isc_mem_t *mctx)
|
2001-09-20 15:17:07 +00:00
|
|
|
{
|
2001-03-01 23:46:49 +00:00
|
|
|
const char *zname;
|
|
|
|
const char *typestr;
|
|
|
|
unsigned int ztype;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zoptions;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2001-03-04 21:18:30 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_result_t tresult;
|
2001-03-01 23:46:49 +00:00
|
|
|
unsigned int i;
|
2001-09-20 15:17:07 +00:00
|
|
|
dns_rdataclass_t zclass;
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_fixedname_t fixedname;
|
|
|
|
isc_buffer_t b;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
static optionstable options[] = {
|
2005-01-11 03:46:11 +00:00
|
|
|
{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL },
|
|
|
|
{ "allow-notify", SLAVEZONE | CHECKACL },
|
|
|
|
{ "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
|
2001-03-01 23:46:49 +00:00
|
|
|
{ "notify", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "also-notify", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
|
2003-09-19 05:53:28 +00:00
|
|
|
{ "delegation-only", HINTZONE | STUBZONE },
|
2001-03-01 23:46:49 +00:00
|
|
|
{ "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
|
|
|
|
{ "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
|
|
|
|
{ "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "max-ixfr-log-size", MASTERZONE | SLAVEZONE },
|
2001-10-11 04:52:21 +00:00
|
|
|
{ "notify-source", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "notify-source-v6", MASTERZONE | SLAVEZONE },
|
2001-10-11 01:55:03 +00:00
|
|
|
{ "transfer-source", SLAVEZONE | STUBZONE },
|
|
|
|
{ "transfer-source-v6", SLAVEZONE | STUBZONE },
|
2001-03-01 23:46:49 +00:00
|
|
|
{ "max-transfer-time-in", SLAVEZONE | STUBZONE },
|
|
|
|
{ "max-transfer-time-out", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "max-transfer-idle-in", SLAVEZONE | STUBZONE },
|
|
|
|
{ "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "max-retry-time", SLAVEZONE | STUBZONE },
|
|
|
|
{ "min-retry-time", SLAVEZONE | STUBZONE },
|
|
|
|
{ "max-refresh-time", SLAVEZONE | STUBZONE },
|
|
|
|
{ "min-refresh-time", SLAVEZONE | STUBZONE },
|
|
|
|
{ "sig-validity-interval", MASTERZONE },
|
|
|
|
{ "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
|
2005-01-11 03:46:11 +00:00
|
|
|
{ "allow-update", MASTERZONE | CHECKACL },
|
|
|
|
{ "allow-update-forwarding", SLAVEZONE | CHECKACL },
|
2004-11-22 05:03:11 +00:00
|
|
|
{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
|
2004-10-07 02:15:14 +00:00
|
|
|
{ "journal", MASTERZONE | SLAVEZONE },
|
2001-03-01 23:46:49 +00:00
|
|
|
{ "ixfr-base", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "masters", SLAVEZONE | STUBZONE },
|
|
|
|
{ "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
|
|
|
|
{ "update-policy", MASTERZONE },
|
|
|
|
{ "database", MASTERZONE | SLAVEZONE | STUBZONE },
|
2002-01-21 11:00:25 +00:00
|
|
|
{ "key-directory", MASTERZONE },
|
2005-01-09 23:40:04 +00:00
|
|
|
{ "check-wildcard", MASTERZONE },
|
2005-05-19 04:59:05 +00:00
|
|
|
{ "check-mx", MASTERZONE },
|
|
|
|
{ "integrity-check", MASTERZONE },
|
2006-01-05 23:45:34 +00:00
|
|
|
{ "check-mx-cname", MASTERZONE },
|
|
|
|
{ "check-srv-cname", MASTERZONE },
|
2005-06-20 01:05:33 +00:00
|
|
|
{ "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
|
2006-03-06 01:27:52 +00:00
|
|
|
{ "update-check-ksk", MASTERZONE },
|
2006-06-04 23:17:07 +00:00
|
|
|
{ "try-tcp-refresh", SLAVEZONE },
|
2001-03-01 23:46:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static optionstable dialups[] = {
|
|
|
|
{ "notify", MASTERZONE | SLAVEZONE },
|
|
|
|
{ "notify-passive", SLAVEZONE },
|
|
|
|
{ "refresh", SLAVEZONE | STUBZONE },
|
|
|
|
{ "passive", SLAVEZONE | STUBZONE },
|
|
|
|
};
|
|
|
|
|
2001-03-02 01:30:32 +00:00
|
|
|
zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
|
|
|
|
|
|
|
|
zoptions = cfg_tuple_get(zconfig, "options");
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
obj = NULL;
|
2001-03-02 01:30:32 +00:00
|
|
|
(void)cfg_map_get(zoptions, "type", &obj);
|
2001-03-01 23:46:49 +00:00
|
|
|
if (obj == NULL) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': type not present", zname);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
typestr = cfg_obj_asstring(obj);
|
|
|
|
if (strcasecmp(typestr, "master") == 0)
|
|
|
|
ztype = MASTERZONE;
|
|
|
|
else if (strcasecmp(typestr, "slave") == 0)
|
|
|
|
ztype = SLAVEZONE;
|
|
|
|
else if (strcasecmp(typestr, "stub") == 0)
|
|
|
|
ztype = STUBZONE;
|
|
|
|
else if (strcasecmp(typestr, "forward") == 0)
|
|
|
|
ztype = FORWARDZONE;
|
|
|
|
else if (strcasecmp(typestr, "hint") == 0)
|
|
|
|
ztype = HINTZONE;
|
2003-09-17 05:24:43 +00:00
|
|
|
else if (strcasecmp(typestr, "delegation-only") == 0)
|
|
|
|
ztype = DELEGATIONZONE;
|
2001-03-01 23:46:49 +00:00
|
|
|
else {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': invalid type %s",
|
|
|
|
zname, typestr);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2001-09-20 15:17:07 +00:00
|
|
|
obj = cfg_tuple_get(zconfig, "class");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
isc_textregion_t r;
|
|
|
|
|
|
|
|
DE_CONST(cfg_obj_asstring(obj), r.base);
|
|
|
|
r.length = strlen(r.base);
|
|
|
|
result = dns_rdataclass_fromtext(&zclass, &r);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': invalid class %s",
|
|
|
|
zname, r.base);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
if (zclass != defclass) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': class '%s' does not "
|
|
|
|
"match view/default class",
|
|
|
|
zname, r.base);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Look for an already existing zone.
|
2002-02-06 05:58:06 +00:00
|
|
|
* We need to make this cannonical as isc_symtab_define()
|
|
|
|
* deals with strings.
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_fixedname_init(&fixedname);
|
|
|
|
isc_buffer_init(&b, zname, strlen(zname));
|
|
|
|
isc_buffer_add(&b, strlen(zname));
|
2004-06-04 02:31:43 +00:00
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_rootname, ISC_TRUE, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2001-03-08 00:55:50 +00:00
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
2002-02-06 05:58:06 +00:00
|
|
|
"zone '%s': is not a valid name", zname);
|
2004-06-04 02:31:43 +00:00
|
|
|
tresult = ISC_R_FAILURE;
|
2002-02-06 05:58:06 +00:00
|
|
|
} else {
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
2002-02-12 13:17:23 +00:00
|
|
|
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_name_format(dns_fixedname_name(&fixedname),
|
|
|
|
namebuf, sizeof(namebuf));
|
2004-06-04 02:31:43 +00:00
|
|
|
tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2,
|
|
|
|
symtab, "zone '%s': already exists "
|
|
|
|
"previous definition: %s:%u", logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
2002-02-06 05:58:06 +00:00
|
|
|
}
|
2001-03-08 00:55:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for inappropriate options for the given zone type.
|
2005-01-11 03:46:11 +00:00
|
|
|
* Check that ACLs expand correctly.
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2001-03-01 23:46:49 +00:00
|
|
|
for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
|
|
|
|
obj = NULL;
|
|
|
|
if ((options[i].allowed & ztype) == 0 &&
|
|
|
|
cfg_map_get(zoptions, options[i].name, &obj) ==
|
|
|
|
ISC_R_SUCCESS)
|
|
|
|
{
|
2003-07-18 06:00:41 +00:00
|
|
|
if (strcmp(options[i].name, "allow-update") != 0 ||
|
|
|
|
ztype != SLAVEZONE) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"option '%s' is not allowed "
|
|
|
|
"in '%s' zone '%s'",
|
|
|
|
options[i].name, typestr, zname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"option '%s' is not allowed "
|
|
|
|
"in '%s' zone '%s'",
|
|
|
|
options[i].name, typestr, zname);
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
obj = NULL;
|
|
|
|
if ((options[i].allowed & ztype) != 0 &&
|
|
|
|
(options[i].allowed & CHECKACL) != 0) {
|
|
|
|
|
2005-09-12 02:04:41 +00:00
|
|
|
tresult = checkacl(options[i].name, actx, zconfig,
|
2005-01-11 03:46:11 +00:00
|
|
|
voptions, config, logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Slave & stub zones must have a "masters" field.
|
|
|
|
*/
|
2001-03-01 23:46:49 +00:00
|
|
|
if (ztype == SLAVEZONE || ztype == STUBZONE) {
|
|
|
|
obj = NULL;
|
|
|
|
if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
|
2001-07-19 16:29:14 +00:00
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
2001-03-01 23:46:49 +00:00
|
|
|
"zone '%s': missing 'masters' entry",
|
|
|
|
zname);
|
|
|
|
result = ISC_R_FAILURE;
|
2002-04-17 01:23:15 +00:00
|
|
|
} else {
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_uint32_t count;
|
|
|
|
tresult = validate_masters(obj, config, &count,
|
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
if (tresult == ISC_R_SUCCESS && count == 0) {
|
2002-04-17 01:23:15 +00:00
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': empty 'masters' entry",
|
|
|
|
zname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2001-12-17 22:56:58 +00:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Master zones can't have both "allow-update" and "update-policy".
|
|
|
|
*/
|
2001-03-01 23:46:49 +00:00
|
|
|
if (ztype == MASTERZONE) {
|
|
|
|
isc_result_t res1, res2;
|
|
|
|
obj = NULL;
|
|
|
|
res1 = cfg_map_get(zoptions, "allow-update", &obj);
|
|
|
|
obj = NULL;
|
|
|
|
res2 = cfg_map_get(zoptions, "update-policy", &obj);
|
|
|
|
if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': 'allow-update' is ignored "
|
|
|
|
"when 'update-policy' is present",
|
|
|
|
zname);
|
|
|
|
result = ISC_R_FAILURE;
|
2005-07-28 05:42:20 +00:00
|
|
|
} else if (res2 == ISC_R_SUCCESS &&
|
|
|
|
check_update_policy(obj, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Check the excessively complicated "dialup" option.
|
|
|
|
*/
|
2001-03-01 23:46:49 +00:00
|
|
|
if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *dialup = NULL;
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)cfg_map_get(zoptions, "dialup", &dialup);
|
2001-03-01 23:46:49 +00:00
|
|
|
if (dialup != NULL && cfg_obj_isstring(dialup)) {
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str = cfg_obj_asstring(dialup);
|
2001-03-01 23:46:49 +00:00
|
|
|
for (i = 0;
|
|
|
|
i < sizeof(dialups) / sizeof(dialups[0]);
|
|
|
|
i++)
|
|
|
|
{
|
|
|
|
if (strcasecmp(dialups[i].name, str) != 0)
|
|
|
|
continue;
|
|
|
|
if ((dialups[i].allowed & ztype) == 0) {
|
|
|
|
cfg_obj_log(obj, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"dialup type '%s' is not "
|
|
|
|
"allowed in '%s' "
|
|
|
|
"zone '%s'",
|
|
|
|
str, typestr, zname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == sizeof(dialups) / sizeof(dialups[0])) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"invalid dialup type '%s' in zone "
|
|
|
|
"'%s'", str, zname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
/*
|
|
|
|
* Check that forwarding is reasonable.
|
|
|
|
*/
|
|
|
|
if (check_forward(zoptions, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
/*
|
|
|
|
* Check various options.
|
|
|
|
*/
|
2004-04-15 23:40:27 +00:00
|
|
|
tresult = check_options(zoptions, logctx, mctx);
|
2001-06-04 21:51:27 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
|
2004-11-22 05:03:11 +00:00
|
|
|
/*
|
|
|
|
* If the zone type is rbt/rbt64 then master/hint zones
|
|
|
|
* require file clauses.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
tresult = cfg_map_get(zoptions, "database", &obj);
|
|
|
|
if (tresult == ISC_R_NOTFOUND ||
|
|
|
|
(tresult == ISC_R_SUCCESS &&
|
|
|
|
(strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
|
|
|
|
strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) {
|
|
|
|
obj = NULL;
|
|
|
|
tresult = cfg_map_get(zoptions, "file", &obj);
|
|
|
|
if (tresult != ISC_R_SUCCESS &&
|
|
|
|
(ztype == MASTERZONE || ztype == HINTZONE)) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': missing 'file' entry",
|
|
|
|
zname);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
typedef struct keyalgorithms {
|
|
|
|
const char *name;
|
|
|
|
isc_uint16_t size;
|
|
|
|
} algorithmtable;
|
|
|
|
|
2001-08-03 17:24:11 +00:00
|
|
|
isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
|
|
|
|
const cfg_obj_t *algobj = NULL;
|
|
|
|
const cfg_obj_t *secretobj = NULL;
|
2001-08-03 17:24:11 +00:00
|
|
|
const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
|
2006-01-27 02:35:15 +00:00
|
|
|
const char *algorithm;
|
|
|
|
int i;
|
|
|
|
size_t len = 0;
|
|
|
|
static const algorithmtable algorithms[] = {
|
|
|
|
{ "hmac-md5", 128 },
|
|
|
|
{ "hmac-md5.sig-alg.reg.int", 0 },
|
|
|
|
{ "hmac-md5.sig-alg.reg.int.", 0 },
|
|
|
|
{ "hmac-sha1", 160 },
|
|
|
|
{ "hmac-sha224", 224 },
|
|
|
|
{ "hmac-sha256", 256 },
|
|
|
|
{ "hmac-sha384", 384 },
|
|
|
|
{ "hmac-sha512", 512 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
2001-08-03 17:24:11 +00:00
|
|
|
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)cfg_map_get(key, "algorithm", &algobj);
|
|
|
|
(void)cfg_map_get(key, "secret", &secretobj);
|
2001-08-03 17:24:11 +00:00
|
|
|
if (secretobj == NULL || algobj == NULL) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s' must have both 'secret' and "
|
|
|
|
"'algorithm' defined",
|
|
|
|
keyname);
|
2001-10-25 17:07:21 +00:00
|
|
|
return (ISC_R_FAILURE);
|
2001-08-03 17:24:11 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
algorithm = cfg_obj_asstring(algobj);
|
|
|
|
for (i = 0; algorithms[i].name != NULL; i++) {
|
|
|
|
len = strlen(algorithms[i].name);
|
|
|
|
if (strncasecmp(algorithms[i].name, algorithm, len) == 0 &&
|
|
|
|
(algorithm[len] == '\0' ||
|
|
|
|
(algorithms[i].size != 0 && algorithm[len] == '-')))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (algorithms[i].name == NULL) {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"unknown algorithm '%s'", algorithm);
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
if (algorithm[len] == '-') {
|
|
|
|
isc_uint16_t digestbits;
|
|
|
|
isc_result_t result;
|
|
|
|
result = isc_parse_uint16(&digestbits, algorithm + len + 1, 10);
|
|
|
|
if (result == ISC_R_SUCCESS || result == ISC_R_RANGE) {
|
|
|
|
if (result == ISC_R_RANGE ||
|
|
|
|
digestbits > algorithms[i].size) {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s' digest-bits too large "
|
|
|
|
"[%u..%u]", keyname,
|
|
|
|
algorithms[i].size / 2,
|
|
|
|
algorithms[i].size);
|
|
|
|
return (ISC_R_RANGE);
|
|
|
|
}
|
|
|
|
if ((digestbits % 8) != 0) {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s' digest-bits not multiple"
|
|
|
|
" of 8", keyname);
|
|
|
|
return (ISC_R_RANGE);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Recommended minima for hmac algorithms.
|
|
|
|
*/
|
|
|
|
if ((digestbits < (algorithms[i].size / 2U) ||
|
|
|
|
(digestbits < 80U)))
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_WARNING,
|
|
|
|
"key '%s' digest-bits too small "
|
|
|
|
"[<%u]", keyname,
|
|
|
|
algorithms[i].size/2);
|
|
|
|
} else {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s': unable to parse digest-bits",
|
|
|
|
keyname);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
2001-10-25 17:07:21 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2001-08-03 17:24:11 +00:00
|
|
|
}
|
2001-10-29 06:09:05 +00:00
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab, isc_log_t *logctx) {
|
2001-10-29 06:09:05 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
2001-10-29 06:09:05 +00:00
|
|
|
|
|
|
|
for (element = cfg_list_first(keys);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *key = cfg_listelt_value(element);
|
2001-10-29 06:09:05 +00:00
|
|
|
const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
tresult = bind9_check_key(key, logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
return (tresult);
|
|
|
|
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = key;
|
2001-10-29 06:09:05 +00:00
|
|
|
tresult = isc_symtab_define(symtab, keyname, 1,
|
|
|
|
symvalue, isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
2002-03-04 05:27:31 +00:00
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, keyname,
|
|
|
|
1, &symvalue) == ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2002-03-04 05:27:31 +00:00
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
file = "<unknown file>";
|
2001-10-29 06:09:05 +00:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2002-03-04 05:27:31 +00:00
|
|
|
"key '%s': already exists "
|
|
|
|
"previous definition: %s:%u",
|
|
|
|
keyname, file, line);
|
2001-10-29 06:09:05 +00:00
|
|
|
result = tresult;
|
|
|
|
} else if (tresult != ISC_R_SUCCESS)
|
|
|
|
return (tresult);
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
2002-02-12 13:17:23 +00:00
|
|
|
|
2006-02-17 00:24:21 +00:00
|
|
|
static struct {
|
|
|
|
const char *v4;
|
|
|
|
const char *v6;
|
|
|
|
} sources[] = {
|
|
|
|
{ "transfer-source", "transfer-source-v6" },
|
|
|
|
{ "notify-source", "notify-source-v6" },
|
|
|
|
{ "query-source", "query-source-v6" },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2002-03-04 05:07:06 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_servers(const cfg_obj_t *servers, isc_log_t *logctx) {
|
2002-03-04 05:07:06 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2006-02-17 00:24:21 +00:00
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *e1, *e2;
|
|
|
|
const cfg_obj_t *v1, *v2;
|
2005-01-17 00:46:05 +00:00
|
|
|
isc_netaddr_t n1, n2;
|
|
|
|
unsigned int p1, p2;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2006-02-17 00:24:21 +00:00
|
|
|
char buf[ISC_NETADDR_FORMATSIZE];
|
2003-09-25 18:16:50 +00:00
|
|
|
const char *xfr;
|
2006-02-17 00:24:21 +00:00
|
|
|
int source;
|
2002-03-04 05:07:06 +00:00
|
|
|
|
|
|
|
for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
|
|
|
|
v1 = cfg_listelt_value(e1);
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1);
|
|
|
|
/*
|
|
|
|
* Check that unused bits are zero.
|
|
|
|
*/
|
2006-02-17 00:24:21 +00:00
|
|
|
tresult = isc_netaddr_prefixok(&n1, p1);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
INSIST(tresult == ISC_R_FAILURE);
|
|
|
|
isc_netaddr_format(&n1, buf, sizeof(buf));
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
|
|
|
|
"server '%s/%u': invalid prefix "
|
|
|
|
"(extra bits specified)", buf, p1);
|
2006-02-17 00:24:21 +00:00
|
|
|
result = tresult;
|
2005-01-17 00:46:05 +00:00
|
|
|
}
|
2006-02-17 00:24:21 +00:00
|
|
|
source = 0;
|
|
|
|
do {
|
|
|
|
obj = NULL;
|
|
|
|
if (n1.family == AF_INET)
|
|
|
|
xfr = sources[source].v6;
|
|
|
|
else
|
|
|
|
xfr = sources[source].v4;
|
|
|
|
(void)cfg_map_get(v1, xfr, &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
isc_netaddr_format(&n1, buf, sizeof(buf));
|
|
|
|
cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
|
|
|
|
"server '%s': %s not legal",
|
|
|
|
buf, xfr);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
} while (sources[++source].v4 != NULL);
|
2002-03-04 05:07:06 +00:00
|
|
|
e2 = e1;
|
|
|
|
while ((e2 = cfg_list_next(e2)) != NULL) {
|
|
|
|
v2 = cfg_listelt_value(e2);
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2);
|
|
|
|
if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) {
|
2002-03-04 05:07:06 +00:00
|
|
|
const char *file = cfg_obj_file(v1);
|
|
|
|
unsigned int line = cfg_obj_line(v1);
|
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
file = "<unknown file>";
|
|
|
|
|
2006-02-17 00:24:21 +00:00
|
|
|
isc_netaddr_format(&n2, buf, sizeof(buf));
|
2002-03-04 05:07:06 +00:00
|
|
|
cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
|
2005-01-17 00:46:05 +00:00
|
|
|
"server '%s/%u': already exists "
|
2002-03-04 05:07:06 +00:00
|
|
|
"previous definition: %s:%u",
|
2005-01-17 00:46:05 +00:00
|
|
|
buf, p2, file, line);
|
2002-03-04 05:07:06 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
2001-08-03 17:24:11 +00:00
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
2007-03-29 06:36:31 +00:00
|
|
|
const char *viewname, dns_rdataclass_t vclass,
|
|
|
|
isc_log_t *logctx, isc_mem_t *mctx)
|
2001-03-08 00:55:50 +00:00
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *servers = NULL;
|
|
|
|
const cfg_obj_t *zones = NULL;
|
|
|
|
const cfg_obj_t *keys = NULL;
|
|
|
|
const cfg_listelt_t *element;
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2001-03-03 23:09:23 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-09 19:07:30 +00:00
|
|
|
isc_result_t tresult = ISC_R_SUCCESS;
|
2005-09-12 02:04:41 +00:00
|
|
|
cfg_aclconfctx_t actx;
|
2006-03-10 05:00:23 +00:00
|
|
|
const cfg_obj_t *obj;
|
2006-03-09 23:21:54 +00:00
|
|
|
isc_boolean_t enablednssec, enablevalidation;
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Check that all zone statements are syntactically correct and
|
|
|
|
* there are no duplicate zones.
|
|
|
|
*/
|
2002-02-12 13:17:23 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
|
2004-04-15 23:40:27 +00:00
|
|
|
ISC_FALSE, &symtab);
|
2001-03-09 19:07:30 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2001-03-08 00:55:50 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
2005-09-12 02:04:41 +00:00
|
|
|
cfg_aclconfctx_init(&actx);
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL)
|
|
|
|
(void)cfg_map_get(voptions, "zone", &zones);
|
2001-10-29 06:09:05 +00:00
|
|
|
else
|
|
|
|
(void)cfg_map_get(config, "zone", &zones);
|
2001-09-20 15:17:07 +00:00
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
for (element = cfg_list_first(zones);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2001-09-20 15:17:07 +00:00
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zone = cfg_listelt_value(element);
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
tresult = check_zoneconf(zone, voptions, config, symtab,
|
2005-09-12 02:04:41 +00:00
|
|
|
vclass, &actx, logctx, mctx);
|
2001-09-20 15:17:07 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that all key statements are syntactically correct and
|
|
|
|
* there are no duplicate keys.
|
|
|
|
*/
|
2001-03-09 19:07:30 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2001-03-08 00:55:50 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)cfg_map_get(config, "key", &keys);
|
2001-10-29 06:09:05 +00:00
|
|
|
tresult = check_keylist(keys, symtab, logctx);
|
|
|
|
if (tresult == ISC_R_EXISTS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
else if (tresult != ISC_R_SUCCESS) {
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (tresult);
|
|
|
|
}
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL) {
|
2001-10-29 06:09:05 +00:00
|
|
|
keys = NULL;
|
2005-01-11 03:46:11 +00:00
|
|
|
(void)cfg_map_get(voptions, "key", &keys);
|
2001-10-29 06:09:05 +00:00
|
|
|
tresult = check_keylist(keys, symtab, logctx);
|
|
|
|
if (tresult == ISC_R_EXISTS)
|
2001-03-08 00:55:50 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2001-10-29 06:09:05 +00:00
|
|
|
else if (tresult != ISC_R_SUCCESS) {
|
2001-08-03 17:24:11 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (tresult);
|
2001-03-03 23:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
/*
|
|
|
|
* Check that forwarding is reasonable.
|
|
|
|
*/
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions == NULL) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *options = NULL;
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)cfg_map_get(config, "options", &options);
|
2001-03-09 19:07:30 +00:00
|
|
|
if (options != NULL)
|
|
|
|
if (check_forward(options, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else {
|
2005-01-11 03:46:11 +00:00
|
|
|
if (check_forward(voptions, logctx) != ISC_R_SUCCESS)
|
2001-03-09 19:07:30 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
/*
|
|
|
|
* Check that dual-stack-servers is reasonable.
|
|
|
|
*/
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions == NULL) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *options = NULL;
|
2003-01-16 03:59:28 +00:00
|
|
|
(void)cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL)
|
|
|
|
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else {
|
2005-01-11 03:46:11 +00:00
|
|
|
if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS)
|
2003-01-16 03:59:28 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2001-03-09 19:07:30 +00:00
|
|
|
|
2002-03-08 00:54:48 +00:00
|
|
|
/*
|
|
|
|
* Check that rrset-order is reasonable.
|
|
|
|
*/
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL) {
|
|
|
|
if (check_order(voptions, logctx) != ISC_R_SUCCESS)
|
2002-03-08 00:54:48 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "server", &servers);
|
2002-03-04 05:07:06 +00:00
|
|
|
if (servers != NULL &&
|
|
|
|
check_servers(servers, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2006-03-09 23:21:54 +00:00
|
|
|
/*
|
|
|
|
* Check that dnssec-enable/dnssec-validation are sensible.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
if (voptions != NULL)
|
|
|
|
(void)cfg_map_get(voptions, "dnssec-enable", &obj);
|
|
|
|
if (obj == NULL)
|
|
|
|
(void)cfg_map_get(config, "dnssec-enable", &obj);
|
|
|
|
if (obj == NULL)
|
|
|
|
enablednssec = ISC_TRUE;
|
|
|
|
else
|
|
|
|
enablednssec = cfg_obj_asboolean(obj);
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
if (voptions != NULL)
|
|
|
|
(void)cfg_map_get(voptions, "dnssec-validation", &obj);
|
|
|
|
if (obj == NULL)
|
|
|
|
(void)cfg_map_get(config, "dnssec-validation", &obj);
|
|
|
|
if (obj == NULL)
|
|
|
|
enablevalidation = ISC_FALSE; /* XXXMPA Change for 9.5. */
|
|
|
|
else
|
|
|
|
enablevalidation = cfg_obj_asboolean(obj);
|
|
|
|
|
|
|
|
if (enablevalidation && !enablednssec)
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"'dnssec-validation yes;' and 'dnssec-enable no;'");
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL)
|
|
|
|
tresult = check_options(voptions, logctx, mctx);
|
2001-10-29 06:09:05 +00:00
|
|
|
else
|
2004-04-15 23:40:27 +00:00
|
|
|
tresult = check_options(config, logctx, mctx);
|
2001-06-04 21:51:27 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
|
2005-09-12 02:04:41 +00:00
|
|
|
tresult = check_viewacls(&actx, voptions, config, logctx, mctx);
|
2005-01-11 03:46:11 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
tresult = check_recursionacls(&actx, voptions, viewname,
|
|
|
|
config, logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
|
2005-09-12 02:04:41 +00:00
|
|
|
cfg_aclconfctx_destroy(&actx);
|
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-11-09 21:24:20 +00:00
|
|
|
static const char *
|
|
|
|
default_channels[] = {
|
|
|
|
"default_syslog",
|
|
|
|
"default_stderr",
|
|
|
|
"default_debug",
|
|
|
|
"null",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
const cfg_obj_t *categories = NULL;
|
|
|
|
const cfg_obj_t *category;
|
|
|
|
const cfg_obj_t *channels = NULL;
|
|
|
|
const cfg_obj_t *channel;
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_listelt_t *delement;
|
2004-11-09 21:24:20 +00:00
|
|
|
const char *channelname;
|
|
|
|
const char *catname;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *fileobj = NULL;
|
|
|
|
const cfg_obj_t *syslogobj = NULL;
|
|
|
|
const cfg_obj_t *nullobj = NULL;
|
|
|
|
const cfg_obj_t *stderrobj = NULL;
|
|
|
|
const cfg_obj_t *logobj = NULL;
|
2004-11-09 21:24:20 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
(void)cfg_map_get(config, "logging", &logobj);
|
|
|
|
if (logobj == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = NULL;
|
2004-11-09 21:24:20 +00:00
|
|
|
for (i = 0; default_channels[i] != NULL; i++) {
|
|
|
|
tresult = isc_symtab_define(symtab, default_channels[i], 1,
|
|
|
|
symvalue, isc_symexists_replace);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_map_get(logobj, "channel", &channels);
|
|
|
|
|
|
|
|
for (element = cfg_list_first(channels);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
channel = cfg_listelt_value(element);
|
|
|
|
channelname = cfg_obj_asstring(cfg_map_getname(channel));
|
|
|
|
fileobj = syslogobj = nullobj = stderrobj = NULL;
|
|
|
|
(void)cfg_map_get(channel, "file", &fileobj);
|
|
|
|
(void)cfg_map_get(channel, "syslog", &syslogobj);
|
|
|
|
(void)cfg_map_get(channel, "null", &nullobj);
|
|
|
|
(void)cfg_map_get(channel, "stderr", &stderrobj);
|
|
|
|
i = 0;
|
|
|
|
if (fileobj != NULL)
|
|
|
|
i++;
|
|
|
|
if (syslogobj != NULL)
|
|
|
|
i++;
|
|
|
|
if (nullobj != NULL)
|
|
|
|
i++;
|
|
|
|
if (stderrobj != NULL)
|
|
|
|
i++;
|
|
|
|
if (i != 1) {
|
|
|
|
cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
|
|
|
|
"channel '%s': exactly one of file, syslog, "
|
|
|
|
"null, and stderr must be present",
|
|
|
|
channelname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
tresult = isc_symtab_define(symtab, channelname, 1,
|
|
|
|
symvalue, isc_symexists_replace);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_map_get(logobj, "category", &categories);
|
|
|
|
|
|
|
|
for (element = cfg_list_first(categories);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
category = cfg_listelt_value(element);
|
|
|
|
catname = cfg_obj_asstring(cfg_tuple_get(category, "name"));
|
|
|
|
if (isc_log_categorybyname(logctx, catname) == NULL) {
|
|
|
|
cfg_obj_log(category, logctx, ISC_LOG_ERROR,
|
|
|
|
"undefined category: '%s'", catname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
channels = cfg_tuple_get(category, "destinations");
|
|
|
|
for (delement = cfg_list_first(channels);
|
|
|
|
delement != NULL;
|
|
|
|
delement = cfg_list_next(delement))
|
|
|
|
{
|
|
|
|
channel = cfg_listelt_value(delement);
|
|
|
|
channelname = cfg_obj_asstring(channel);
|
|
|
|
tresult = isc_symtab_lookup(symtab, channelname, 1,
|
|
|
|
&symvalue);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
|
|
|
|
"undefined channel: '%s'",
|
|
|
|
channelname);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (result);
|
|
|
|
}
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
key_exists(const cfg_obj_t *keylist, const char *keyname) {
|
|
|
|
const cfg_listelt_t *element;
|
2005-02-23 01:09:23 +00:00
|
|
|
const char *str;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
if (keylist == NULL)
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
for (element = cfg_list_first(keylist);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(cfg_map_getname(obj));
|
|
|
|
if (strcasecmp(str, keyname) == 0)
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
bind9_check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist,
|
2005-02-23 01:09:23 +00:00
|
|
|
isc_log_t *logctx)
|
|
|
|
{
|
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *control_keylist;
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *key;
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
control_keylist = cfg_tuple_get(control, "keys");
|
|
|
|
if (cfg_obj_isvoid(control_keylist))
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
for (element = cfg_list_first(control_keylist);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
key = cfg_listelt_value(element);
|
|
|
|
tresult = key_exists(keylist, cfg_obj_asstring(key));
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"unknown key '%s'", cfg_obj_asstring(key));
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
2005-02-23 01:09:23 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
|
|
|
cfg_aclconfctx_t actx;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element, *element2;
|
|
|
|
const cfg_obj_t *allow;
|
|
|
|
const cfg_obj_t *control;
|
|
|
|
const cfg_obj_t *controls;
|
|
|
|
const cfg_obj_t *controlslist = NULL;
|
|
|
|
const cfg_obj_t *inetcontrols;
|
|
|
|
const cfg_obj_t *unixcontrols;
|
|
|
|
const cfg_obj_t *keylist = NULL;
|
2005-02-23 01:09:23 +00:00
|
|
|
const char *path;
|
|
|
|
isc_uint32_t perm, mask;
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
isc_sockaddr_t addr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
(void)cfg_map_get(config, "controls", &controlslist);
|
|
|
|
if (controlslist == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
(void)cfg_map_get(config, "key", &keylist);
|
|
|
|
|
2005-09-12 02:04:41 +00:00
|
|
|
cfg_aclconfctx_init(&actx);
|
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
/*
|
|
|
|
* INET: Check allow clause.
|
|
|
|
* UNIX: Check "perm" for sanity, check path length.
|
|
|
|
*/
|
|
|
|
for (element = cfg_list_first(controlslist);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element)) {
|
|
|
|
controls = cfg_listelt_value(element);
|
|
|
|
unixcontrols = NULL;
|
|
|
|
inetcontrols = NULL;
|
|
|
|
(void)cfg_map_get(controls, "unix", &unixcontrols);
|
|
|
|
(void)cfg_map_get(controls, "inet", &inetcontrols);
|
|
|
|
for (element2 = cfg_list_first(inetcontrols);
|
|
|
|
element2 != NULL;
|
|
|
|
element2 = cfg_list_next(element2)) {
|
|
|
|
control = cfg_listelt_value(element2);
|
|
|
|
allow = cfg_tuple_get(control, "allow");
|
|
|
|
tresult = cfg_acl_fromconfig(allow, config, logctx,
|
2005-09-12 02:04:41 +00:00
|
|
|
&actx, mctx, &acl);
|
2005-02-23 01:09:23 +00:00
|
|
|
if (acl != NULL)
|
|
|
|
dns_acl_detach(&acl);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
tresult = bind9_check_controlskeys(control, keylist,
|
|
|
|
logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
for (element2 = cfg_list_first(unixcontrols);
|
|
|
|
element2 != NULL;
|
|
|
|
element2 = cfg_list_next(element2)) {
|
|
|
|
control = cfg_listelt_value(element2);
|
|
|
|
path = cfg_obj_asstring(cfg_tuple_get(control, "path"));
|
|
|
|
tresult = isc_sockaddr_frompath(&addr, path);
|
|
|
|
if (tresult == ISC_R_NOSPACE) {
|
|
|
|
cfg_obj_log(control, logctx, ISC_LOG_ERROR,
|
|
|
|
"unix control '%s': path too long",
|
|
|
|
path);
|
|
|
|
result = ISC_R_NOSPACE;
|
|
|
|
}
|
|
|
|
perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
#ifdef NEED_SECURE_DIRECTORY
|
|
|
|
mask = (0x1 << (i*3)); /* SEARCH */
|
|
|
|
#else
|
|
|
|
mask = (0x6 << (i*3)); /* READ + WRITE */
|
|
|
|
#endif
|
|
|
|
if ((perm & mask) == mask)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == 0) {
|
|
|
|
cfg_obj_log(control, logctx, ISC_LOG_WARNING,
|
|
|
|
"unix control '%s' allows access "
|
|
|
|
"to everyone", path);
|
|
|
|
} else if (i == 3) {
|
|
|
|
cfg_obj_log(control, logctx, ISC_LOG_WARNING,
|
|
|
|
"unix control '%s' allows access "
|
|
|
|
"to nobody", path);
|
|
|
|
}
|
|
|
|
tresult = bind9_check_controlskeys(control, keylist,
|
|
|
|
logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
2005-09-12 02:04:41 +00:00
|
|
|
cfg_aclconfctx_destroy(&actx);
|
2005-02-23 01:09:23 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx)
|
|
|
|
{
|
|
|
|
const cfg_obj_t *options = NULL;
|
|
|
|
const cfg_obj_t *servers = NULL;
|
|
|
|
const cfg_obj_t *views = NULL;
|
|
|
|
const cfg_obj_t *acls = NULL;
|
|
|
|
const cfg_obj_t *kals = NULL;
|
|
|
|
const cfg_obj_t *obj;
|
|
|
|
const cfg_listelt_t *velement;
|
2001-03-02 03:09:27 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-09 19:07:30 +00:00
|
|
|
isc_result_t tresult;
|
2004-05-17 05:37:41 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2002-02-06 06:45:40 +00:00
|
|
|
static const char *builtin[] = { "localhost", "localnets",
|
2002-02-06 06:54:31 +00:00
|
|
|
"any", "none"};
|
2002-02-06 06:45:40 +00:00
|
|
|
|
2001-03-03 23:05:23 +00:00
|
|
|
(void)cfg_map_get(config, "options", &options);
|
|
|
|
|
2001-11-13 06:34:59 +00:00
|
|
|
if (options != NULL &&
|
2004-04-15 23:40:27 +00:00
|
|
|
check_options(options, logctx, mctx) != ISC_R_SUCCESS)
|
2002-03-04 05:07:06 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
|
|
|
(void)cfg_map_get(config, "server", &servers);
|
|
|
|
if (servers != NULL &&
|
|
|
|
check_servers(servers, logctx) != ISC_R_SUCCESS)
|
2002-03-08 00:54:48 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2004-11-09 21:24:20 +00:00
|
|
|
if (bind9_check_logging(config, logctx, mctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2002-03-08 00:54:48 +00:00
|
|
|
if (options != NULL &&
|
|
|
|
check_order(options, logctx) != ISC_R_SUCCESS)
|
2001-11-13 06:34:59 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2001-06-04 21:51:27 +00:00
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
(void)cfg_map_get(config, "view", &views);
|
|
|
|
|
2003-01-16 03:59:28 +00:00
|
|
|
if (views != NULL && options != NULL)
|
|
|
|
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
if (views == NULL) {
|
2007-03-29 06:36:31 +00:00
|
|
|
if (check_viewconf(config, NULL, NULL, dns_rdataclass_in,
|
2001-09-20 15:17:07 +00:00
|
|
|
logctx, mctx) != ISC_R_SUCCESS)
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2001-03-01 23:46:49 +00:00
|
|
|
} else {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zones = NULL;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(config, "zone", &zones);
|
|
|
|
if (zones != NULL) {
|
|
|
|
cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
|
|
|
|
"when using 'view' statements, "
|
|
|
|
"all zones must be in views");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-17 05:37:41 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
|
|
|
result = tresult;
|
2001-03-01 23:46:49 +00:00
|
|
|
for (velement = cfg_list_first(views);
|
|
|
|
velement != NULL;
|
|
|
|
velement = cfg_list_next(velement))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *view = cfg_listelt_value(velement);
|
|
|
|
const cfg_obj_t *vname = cfg_tuple_get(view, "name");
|
|
|
|
const cfg_obj_t *voptions = cfg_tuple_get(view, "options");
|
|
|
|
const cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
|
2001-09-20 15:17:07 +00:00
|
|
|
dns_rdataclass_t vclass = dns_rdataclass_in;
|
|
|
|
isc_result_t tresult = ISC_R_SUCCESS;
|
2004-05-17 05:37:41 +00:00
|
|
|
const char *key = cfg_obj_asstring(vname);
|
|
|
|
isc_symvalue_t symvalue;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2001-09-20 15:17:07 +00:00
|
|
|
if (cfg_obj_isstring(vclassobj)) {
|
|
|
|
isc_textregion_t r;
|
|
|
|
|
|
|
|
DE_CONST(cfg_obj_asstring(vclassobj), r.base);
|
|
|
|
r.length = strlen(r.base);
|
|
|
|
tresult = dns_rdataclass_fromtext(&vclass, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2001-11-16 04:43:04 +00:00
|
|
|
cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
|
2001-09-20 15:17:07 +00:00
|
|
|
"view '%s': invalid class %s",
|
|
|
|
cfg_obj_asstring(vname), r.base);
|
|
|
|
}
|
2004-05-17 05:37:41 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS && symtab != NULL) {
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = view;
|
2004-05-17 05:37:41 +00:00
|
|
|
tresult = isc_symtab_define(symtab, key, vclass,
|
|
|
|
symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, key,
|
|
|
|
vclass, &symvalue) == ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2004-05-17 05:37:41 +00:00
|
|
|
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
|
|
|
|
"view '%s': already exists "
|
|
|
|
"previous definition: %s:%u",
|
|
|
|
key, file, line);
|
|
|
|
result = tresult;
|
2004-07-29 00:08:10 +00:00
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
2004-05-17 05:37:41 +00:00
|
|
|
result = tresult;
|
2004-07-29 00:08:10 +00:00
|
|
|
} else if ((strcasecmp(key, "_bind") == 0 &&
|
|
|
|
vclass == dns_rdataclass_ch) ||
|
|
|
|
(strcasecmp(key, "_default") == 0 &&
|
|
|
|
vclass == dns_rdataclass_in)) {
|
|
|
|
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine builtin view "
|
|
|
|
"'%s'", key);
|
|
|
|
result = ISC_R_EXISTS;
|
|
|
|
}
|
2004-05-17 05:37:41 +00:00
|
|
|
}
|
2001-09-20 15:17:07 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS)
|
2007-03-29 06:36:31 +00:00
|
|
|
tresult = check_viewconf(config, voptions, key,
|
2001-09-20 15:17:07 +00:00
|
|
|
vclass, logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS)
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
2004-05-17 05:37:41 +00:00
|
|
|
if (symtab != NULL)
|
|
|
|
isc_symtab_destroy(&symtab);
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2001-03-03 23:05:23 +00:00
|
|
|
if (views != NULL && options != NULL) {
|
|
|
|
obj = NULL;
|
2001-03-09 19:07:30 +00:00
|
|
|
tresult = cfg_map_get(options, "cache-file", &obj);
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2001-03-03 23:05:23 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'cache-file' cannot be a global "
|
|
|
|
"option if views are present");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2002-02-06 06:45:40 +00:00
|
|
|
tresult = cfg_map_get(config, "acl", &acls);
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *elt;
|
|
|
|
const cfg_listelt_t *elt2;
|
2002-02-06 06:45:40 +00:00
|
|
|
const char *aclname;
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(acls);
|
|
|
|
elt != NULL;
|
|
|
|
elt = cfg_list_next(elt)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
2002-02-06 06:54:31 +00:00
|
|
|
unsigned int i;
|
2002-02-06 06:45:40 +00:00
|
|
|
|
|
|
|
aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
2002-02-06 06:54:31 +00:00
|
|
|
for (i = 0;
|
|
|
|
i < sizeof(builtin) / sizeof(builtin[0]);
|
|
|
|
i++)
|
2002-02-06 06:45:40 +00:00
|
|
|
if (strcasecmp(aclname, builtin[i]) == 0) {
|
|
|
|
cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine "
|
|
|
|
"builtin acl '%s'",
|
|
|
|
aclname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
2002-02-11 00:46:26 +00:00
|
|
|
|
|
|
|
for (elt2 = cfg_list_next(elt);
|
|
|
|
elt2 != NULL;
|
|
|
|
elt2 = cfg_list_next(elt2)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
|
2002-02-11 00:46:26 +00:00
|
|
|
const char *name;
|
|
|
|
name = cfg_obj_asstring(cfg_tuple_get(acl2,
|
|
|
|
"name"));
|
|
|
|
if (strcasecmp(aclname, name) == 0) {
|
2002-02-13 03:43:09 +00:00
|
|
|
const char *file = cfg_obj_file(acl);
|
|
|
|
unsigned int line = cfg_obj_line(acl);
|
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
file = "<unknown file>";
|
|
|
|
|
2002-02-11 00:46:26 +00:00
|
|
|
cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine "
|
2002-02-13 03:43:09 +00:00
|
|
|
"acl '%s' previous "
|
|
|
|
"definition: %s:%u",
|
|
|
|
name, file, line);
|
2002-02-11 00:46:26 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2002-02-06 06:45:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-20 00:43:08 +00:00
|
|
|
tresult = cfg_map_get(config, "kal", &kals);
|
2003-02-26 06:04:03 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *elt;
|
|
|
|
const cfg_listelt_t *elt2;
|
2003-02-26 06:04:03 +00:00
|
|
|
const char *aclname;
|
|
|
|
|
2003-03-20 00:43:08 +00:00
|
|
|
for (elt = cfg_list_first(kals);
|
2003-02-26 06:04:03 +00:00
|
|
|
elt != NULL;
|
|
|
|
elt = cfg_list_next(elt)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
|
|
|
|
|
|
|
for (elt2 = cfg_list_next(elt);
|
|
|
|
elt2 != NULL;
|
|
|
|
elt2 = cfg_list_next(elt2)) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
|
2003-02-26 06:04:03 +00:00
|
|
|
const char *name;
|
|
|
|
name = cfg_obj_asstring(cfg_tuple_get(acl2,
|
|
|
|
"name"));
|
|
|
|
if (strcasecmp(aclname, name) == 0) {
|
|
|
|
const char *file = cfg_obj_file(acl);
|
|
|
|
unsigned int line = cfg_obj_line(acl);
|
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
file = "<unknown file>";
|
|
|
|
|
|
|
|
cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine "
|
|
|
|
"kal '%s' previous "
|
|
|
|
"definition: %s:%u",
|
|
|
|
name, file, line);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|