diff options
Diffstat (limited to 'contrib/bind9/lib/bind9/check.c')
-rw-r--r-- | contrib/bind9/lib/bind9/check.c | 2935 |
1 files changed, 0 insertions, 2935 deletions
diff --git a/contrib/bind9/lib/bind9/check.c b/contrib/bind9/lib/bind9/check.c deleted file mode 100644 index 91f8bff..0000000 --- a/contrib/bind9/lib/bind9/check.c +++ /dev/null @@ -1,2935 +0,0 @@ -/* - * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -/*! \file */ - -#include <config.h> - -#include <stdlib.h> - -#include <isc/base64.h> -#include <isc/buffer.h> -#include <isc/log.h> -#include <isc/mem.h> -#include <isc/netaddr.h> -#include <isc/parseint.h> -#include <isc/region.h> -#include <isc/result.h> -#include <isc/sockaddr.h> -#include <isc/string.h> -#include <isc/symtab.h> -#include <isc/util.h> - -#include <dns/acl.h> -#include <dns/fixedname.h> -#include <dns/rdataclass.h> -#include <dns/rdatatype.h> -#include <dns/secalg.h> - -#include <dst/dst.h> - -#include <isccfg/aclconf.h> -#include <isccfg/cfg.h> - -#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(const cfg_obj_t *ent, isc_log_t *logctx) { - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - isc_textregion_t r; - dns_fixedname_t fixed; - const cfg_obj_t *obj; - 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_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, 0, 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; - } 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' was disabled at " - "compilation time"); -#endif - } else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 && - 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 -check_order(const cfg_obj_t *options, isc_log_t *logctx) { - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - const cfg_listelt_t *element; - const cfg_obj_t *obj = NULL; - - 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); -} - -static isc_result_t -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; - const char *str; - 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_constinit(&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, - 0, 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); -} - -static isc_result_t -check_forward(const cfg_obj_t *options, const cfg_obj_t *global, - isc_log_t *logctx) -{ - const cfg_obj_t *forward = NULL; - const cfg_obj_t *forwarders = NULL; - - (void)cfg_map_get(options, "forward", &forward); - (void)cfg_map_get(options, "forwarders", &forwarders); - - if (forwarders != NULL && global != NULL) { - const char *file = cfg_obj_file(global); - unsigned int line = cfg_obj_line(global); - cfg_obj_log(forwarders, logctx, ISC_LOG_ERROR, - "forwarders declared in root zone and " - "in general configuration: %s:%u", - file, line); - return (ISC_R_FAILURE); - } - 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); -} - -static isc_result_t -disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) { - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - const cfg_listelt_t *element; - const char *str; - isc_buffer_t b; - dns_fixedname_t fixed; - dns_name_t *name; - const cfg_obj_t *obj; - - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - obj = cfg_tuple_get(disabled, "name"); - str = cfg_obj_asstring(obj); - isc_buffer_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(name, &b, dns_rootname, 0, 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; - - DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); - r.length = strlen(r.base); - - tresult = dns_secalg_fromtext(&alg, &r); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(cfg_listelt_value(element), logctx, - ISC_LOG_ERROR, "invalid algorithm '%s'", - r.base); - result = tresult; - } - } - return (result); -} - -static isc_result_t -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) -{ - 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); - symvalue.as_cpointer = obj; - 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); - file = cfg_obj_file(symvalue.as_cpointer); - line = cfg_obj_line(symvalue.as_cpointer); - - 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); -} - -static isc_result_t -mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx, - isc_mem_t *mctx) -{ - const 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; - - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - obj = cfg_tuple_get(secure, "name"); - str = cfg_obj_asstring(obj); - isc_buffer_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad domain name '%s'", str); - } else { - dns_name_format(name, namebuf, sizeof(namebuf)); - result = nameexist(secure, namebuf, 1, symtab, - "dnssec-must-be-secure '%s': already " - "exists previous definition: %s:%u", - logctx, mctx); - } - return (result); -} - -static isc_result_t -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) -{ - isc_result_t result; - const cfg_obj_t *aclobj = NULL; - const cfg_obj_t *options; - 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); - result = cfg_acl_fromconfig(aclobj, config, logctx, - actx, mctx, 0, &acl); - if (acl != NULL) - dns_acl_detach(&acl); - return (result); -} - -static isc_result_t -check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, - const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) -{ - isc_result_t result = ISC_R_SUCCESS, tresult; - int i = 0; - - static const char *acls[] = { "allow-query", "allow-query-on", - "allow-query-cache", "allow-query-cache-on", - "blackhole", "match-clients", "match-destinations", - "sortlist", "filter-aaaa", NULL }; - - while (acls[i] != NULL) { - tresult = checkacl(acls[i++], actx, NULL, voptions, config, - logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - } - return (result); -} - -static const unsigned char zeros[16]; - -static isc_result_t -check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, - const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) -{ - isc_result_t result = ISC_R_SUCCESS; - const cfg_obj_t *dns64 = NULL; - const cfg_obj_t *options; - const cfg_listelt_t *element; - const cfg_obj_t *map, *obj; - isc_netaddr_t na, sa; - unsigned int prefixlen; - int nbytes; - int i; - - static const char *acls[] = { "clients", "exclude", "mapped", NULL}; - - if (voptions != NULL) - cfg_map_get(voptions, "dns64", &dns64); - if (config != NULL && dns64 == NULL) { - options = NULL; - cfg_map_get(config, "options", &options); - if (options != NULL) - cfg_map_get(options, "dns64", &dns64); - } - if (dns64 == NULL) - return (ISC_R_SUCCESS); - - for (element = cfg_list_first(dns64); - element != NULL; - element = cfg_list_next(element)) - { - map = cfg_listelt_value(element); - obj = cfg_map_getname(map); - - cfg_obj_asnetprefix(obj, &na, &prefixlen); - if (na.family != AF_INET6) { - cfg_obj_log(map, logctx, ISC_LOG_ERROR, - "dns64 requires a IPv6 prefix"); - result = ISC_R_FAILURE; - continue; - } - - if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 && - prefixlen != 56 && prefixlen != 64 && prefixlen != 96) { - cfg_obj_log(map, logctx, ISC_LOG_ERROR, - "bad prefix length %u [32/40/48/56/64/96]", - prefixlen); - result = ISC_R_FAILURE; - continue; - } - - for (i = 0; acls[i] != NULL; i++) { - obj = NULL; - (void)cfg_map_get(map, acls[i], &obj); - if (obj != NULL) { - dns_acl_t *acl = NULL; - isc_result_t tresult; - - tresult = cfg_acl_fromconfig(obj, config, - logctx, actx, - mctx, 0, &acl); - if (acl != NULL) - dns_acl_detach(&acl); - if (tresult != ISC_R_SUCCESS) - result = tresult; - } - } - - obj = NULL; - (void)cfg_map_get(map, "suffix", &obj); - if (obj != NULL) { - isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj)); - if (sa.family != AF_INET6) { - cfg_obj_log(map, logctx, ISC_LOG_ERROR, - "dns64 requires a IPv6 suffix"); - result = ISC_R_FAILURE; - continue; - } - nbytes = prefixlen / 8 + 4; - if (prefixlen >= 32 && prefixlen <= 64) - nbytes++; - if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) { - char netaddrbuf[ISC_NETADDR_FORMATSIZE]; - isc_netaddr_format(&sa, netaddrbuf, - sizeof(netaddrbuf)); - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad suffix '%s' leading " - "%u octets not zeros", - netaddrbuf, nbytes); - result = ISC_R_FAILURE; - } - } - } - - return (result); -} - - -/* - * 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, 0, &acl); - - if (tresult != ISC_R_SUCCESS) - result = tresult; - - if (acl == NULL) - continue; - - if (recursion == ISC_FALSE && !dns_acl_isnone(acl)) { - 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); -} - -static isc_result_t -check_filteraaaa(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; - dns_v4_aaaa_t filter; - const char *forview = " for view "; - - if (voptions != NULL) - cfg_map_get(voptions, "filter-aaaa-on-v4", &obj); - if (obj == NULL && config != NULL) { - options = NULL; - cfg_map_get(config, "options", &options); - if (options != NULL) - cfg_map_get(options, "filter-aaaa-on-v4", &obj); - } - - if (obj == NULL) - filter = dns_v4_aaaa_ok; /* default */ - else if (cfg_obj_isboolean(obj)) - filter = cfg_obj_asboolean(obj) ? dns_v4_aaaa_filter : - dns_v4_aaaa_ok; - else - filter = dns_v4_aaaa_break_dnssec; /* break-dnssec */ - - if (viewname == NULL) { - viewname = ""; - forview = ""; - } - - aclobj = options = NULL; - acl = NULL; - - if (voptions != NULL) - cfg_map_get(voptions, "filter-aaaa", &aclobj); - if (config != NULL && aclobj == NULL) { - options = NULL; - cfg_map_get(config, "options", &options); - if (options != NULL) - cfg_map_get(options, "filter-aaaa", &aclobj); - } - if (aclobj == NULL) - return (result); - - tresult = cfg_acl_fromconfig(aclobj, config, logctx, - actx, mctx, 0, &acl); - - if (tresult != ISC_R_SUCCESS) { - result = tresult; - } else if (filter != dns_v4_aaaa_ok && dns_acl_isnone(acl)) { - cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, - "both \"filter-aaaa-on-v4 %s;\" and " - "\"filter-aaaa\" is 'none;'%s%s", - filter == dns_v4_aaaa_break_dnssec ? - "break-dnssec" : "yes", forview, viewname); - result = ISC_R_FAILURE; - } else if (filter == dns_v4_aaaa_ok && !dns_acl_isnone(acl)) { - cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, - "both \"filter-aaaa-on-v4 no;\" and " - "\"filter-aaaa\" is set%s%s", forview, viewname); - result = ISC_R_FAILURE; - } - - if (acl != NULL) - dns_acl_detach(&acl); - - return (result); -} - -typedef struct { - const char *name; - unsigned int scale; - unsigned int max; -} intervaltable; - -typedef enum { - optlevel_config, - optlevel_options, - optlevel_view, - optlevel_zone -} optlevel_t; - -static isc_result_t -check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, - optlevel_t optlevel) -{ - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - unsigned int i; - const cfg_obj_t *obj = NULL; - const cfg_obj_t *resignobj = NULL; - const cfg_listelt_t *element; - isc_symtab_t *symtab = NULL; - dns_fixedname_t fixed; - const char *str; - dns_name_t *name; - isc_buffer_t b; - - static intervaltable intervals[] = { - { "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 */ - { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */ - }; - - static const char *server_contact[] = { - "empty-server", "empty-contact", - "dns64-server", "dns64-contact", - NULL - }; - - /* - * 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; - obj = NULL; - (void)cfg_map_get(options, intervals[i].name, &obj); - if (obj == NULL) - continue; - val = cfg_obj_asuint32(obj); - 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)) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "%s '%d' is out of range", - intervals[i].name, val); - result = ISC_R_RANGE; - } - } - - obj = NULL; - cfg_map_get(options, "max-rsa-exponent-size", &obj); - if (obj != NULL) { - isc_uint32_t val; - - val = cfg_obj_asuint32(obj); - if (val != 0 && (val < 35 || val > 4096)) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "max-rsa-exponent-size '%u' is out of " - "range (35..4096)", val); - result = ISC_R_RANGE; - } - } - - obj = NULL; - cfg_map_get(options, "sig-validity-interval", &obj); - if (obj != NULL) { - isc_uint32_t validity, resign = 0; - - validity = cfg_obj_asuint32(cfg_tuple_get(obj, "validity")); - resignobj = cfg_tuple_get(obj, "re-sign"); - if (!cfg_obj_isvoid(resignobj)) - resign = cfg_obj_asuint32(resignobj); - - if (validity > 3660 || validity == 0) { /* 10 years */ - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "%s '%u' is out of range (1..3660)", - "sig-validity-interval", validity); - result = ISC_R_RANGE; - } - - if (!cfg_obj_isvoid(resignobj)) { - if (resign > 3660 || resign == 0) { /* 10 years */ - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "%s '%u' is out of range (1..3660)", - "sig-validity-interval (re-sign)", - validity); - result = ISC_R_RANGE; - } else if ((validity > 7 && validity < resign) || - (validity <= 7 && validity * 24 < resign)) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "validity interval (%u days) " - "less than re-signing interval " - "(%u %s)", validity, resign, - (validity > 7) ? "days" : "hours"); - result = ISC_R_RANGE; - } - } - } - - 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); - } - - obj = NULL; - (void)cfg_map_get(options, "root-delegation-only", &obj); - if (obj != NULL) { - if (!cfg_obj_isvoid(obj)) { - const cfg_listelt_t *element; - const cfg_obj_t *exclude; - const char *str; - 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_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(name, &b, - dns_rootname, - 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad domain name '%s'", - str); - result = tresult; - } - } - } - } - - /* - * 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; - } - } - - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - - /* - * Check the DLV zone name. - */ - obj = NULL; - (void)cfg_map_get(options, "dnssec-lookaside", &obj); - if (obj != 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)) - { - const char *dlv; - const cfg_obj_t *dlvobj, *anchor; - - obj = cfg_listelt_value(element); - - anchor = cfg_tuple_get(obj, "trust-anchor"); - dlvobj = cfg_tuple_get(obj, "domain"); - dlv = cfg_obj_asstring(dlvobj); - - /* - * If domain is "auto" or "no" and trust anchor - * is missing, skip remaining tests - */ - if (cfg_obj_isvoid(anchor)) { - if (!strcasecmp(dlv, "no") || - !strcasecmp(dlv, "auto")) - continue; - } - - isc_buffer_constinit(&b, dlv, strlen(dlv)); - isc_buffer_add(&b, strlen(dlv)); - tresult = dns_name_fromtext(name, &b, dns_rootname, - 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad domain name '%s'", dlv); - result = tresult; - continue; - } - 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; - } - - if (!cfg_obj_isvoid(anchor)) { - dlv = cfg_obj_asstring(anchor); - isc_buffer_constinit(&b, dlv, strlen(dlv)); - isc_buffer_add(&b, strlen(dlv)); - tresult = dns_name_fromtext(name, &b, - dns_rootname, - DNS_NAME_DOWNCASE, - 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; - } - } else { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "dnssec-lookaside requires " - "either 'auto' or 'no', or a " - "domain and trust anchor"); - if (result == ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - } - - if (symtab != NULL) - isc_symtab_destroy(&symtab); - } - - /* - * Check auto-dnssec at the view/options level - */ - obj = NULL; - (void)cfg_map_get(options, "auto-dnssec", &obj); - if (obj != NULL) { - const char *arg = cfg_obj_asstring(obj); - if (optlevel != optlevel_zone && strcasecmp(arg, "off") != 0) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "auto-dnssec may only be activated at the " - "zone level"); - result = ISC_R_FAILURE; - } - } - - /* - * 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); - } - - /* - * Check server/contacts for syntactic validity. - */ - for (i= 0; server_contact[i] != NULL; i++) { - obj = NULL; - (void)cfg_map_get(options, server_contact[i], &obj); - if (obj != NULL) { - str = cfg_obj_asstring(obj); - isc_buffer_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), - &b, dns_rootname, 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "%s: invalid name '%s'", - server_contact[i], str); - result = ISC_R_FAILURE; - } - } - } - - /* - * Check empty zone configuration. - */ - 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_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, 0, 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; - } - } - - /* - * Check that server-id is not too long. - * 1024 bytes should be big enough. - */ - obj = NULL; - (void)cfg_map_get(options, "server-id", &obj); - if (obj != NULL && cfg_obj_isstring(obj) && - strlen(cfg_obj_asstring(obj)) > 1024U) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'server-id' too big (>1024 bytes)"); - result = ISC_R_FAILURE; - } - - return (result); -} - -static isc_result_t -get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) { - isc_result_t result; - const cfg_obj_t *masters = NULL; - const cfg_listelt_t *elt; - - 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)) { - const cfg_obj_t *list; - 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 -validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config, - isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx) -{ - 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; - const cfg_listelt_t *element; - const cfg_listelt_t **stack = NULL; - isc_uint32_t stackcount = 0, pushed = 0; - const cfg_obj_t *list; - - REQUIRE(countp != NULL); - result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab); - if (result != ISC_R_SUCCESS) { - *countp = count; - return (result); - } - - newlist: - list = cfg_tuple_get(obj, "addresses"); - element = cfg_list_first(list); - resume: - for ( ; - element != NULL; - element = cfg_list_next(element)) - { - const char *listname; - const cfg_obj_t *addr; - const cfg_obj_t *key; - - 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); - symvalue.as_cpointer = addr; - 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) { - void *ptr; - - DE_CONST(stack, ptr); - memcpy(new, stack, oldsize); - isc_mem_put(mctx, ptr, 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) { - void *ptr; - - DE_CONST(stack, ptr); - isc_mem_put(mctx, ptr, stackcount * sizeof(*stack)); - } - isc_symtab_destroy(&symtab); - *countp = count; - return (result); -} - -static isc_result_t -check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - const cfg_listelt_t *element; - const cfg_listelt_t *element2; - dns_fixedname_t fixed; - const char *str; - isc_buffer_t b; - - /* Check for "update-policy local;" */ - if (cfg_obj_isstring(policy) && - strcmp("local", cfg_obj_asstring(policy)) == 0) - return (ISC_R_SUCCESS); - - /* Now check the grant policy */ - for (element = cfg_list_first(policy); - element != NULL; - element = cfg_list_next(element)) - { - 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"); - - dns_fixedname_init(&fixed); - str = cfg_obj_asstring(identity); - isc_buffer_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(identity, logctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - result = tresult; - } - - if (tresult == ISC_R_SUCCESS && - strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) { - dns_fixedname_init(&fixed); - str = cfg_obj_asstring(dname); - isc_buffer_constinit(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), - &b, dns_rootname, 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(dname, logctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - result = tresult; - } - } - - 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; - } - - for (element2 = cfg_list_first(typelist); - element2 != NULL; - element2 = cfg_list_next(element2)) - { - const cfg_obj_t *typeobj; - isc_textregion_t r; - dns_rdatatype_t type; - - typeobj = cfg_listelt_value(element2); - DE_CONST(cfg_obj_asstring(typeobj), r.base); - r.length = strlen(r.base); - - tresult = dns_rdatatype_fromtext(&type, &r); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR, - "'%s' is not a valid type", r.base); - result = tresult; - } - } - } - return (result); -} - -#define MASTERZONE 1 -#define SLAVEZONE 2 -#define STUBZONE 4 -#define HINTZONE 8 -#define FORWARDZONE 16 -#define DELEGATIONZONE 32 -#define STATICSTUBZONE 64 -#define REDIRECTZONE 128 -#define STREDIRECTZONE 0 /* Set to REDIRECTZONE to allow xfr-in. */ -#define CHECKACL 512 - -typedef struct { - const char *name; - int allowed; -} optionstable; - -static isc_result_t -check_nonzero(const cfg_obj_t *options, isc_log_t *logctx) { - isc_result_t result = ISC_R_SUCCESS; - const cfg_obj_t *obj = NULL; - unsigned int i; - - static const char *nonzero[] = { "max-retry-time", "min-retry-time", - "max-refresh-time", "min-refresh-time" }; - /* - * Check if value is zero. - */ - for (i = 0; i < sizeof(nonzero) / sizeof(nonzero[0]); i++) { - obj = NULL; - if (cfg_map_get(options, nonzero[i], &obj) == ISC_R_SUCCESS && - cfg_obj_asuint32(obj) == 0) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'%s' must not be zero", nonzero[i]); - result = ISC_R_FAILURE; - } - } - return (result); -} - -static isc_result_t -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) -{ - const char *znamestr; - const char *typestr; - unsigned int ztype; - const cfg_obj_t *zoptions, *goptions = NULL; - const cfg_obj_t *obj = NULL; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - unsigned int i; - dns_rdataclass_t zclass; - dns_fixedname_t fixedname; - dns_name_t *zname = NULL; - isc_buffer_t b; - isc_boolean_t root = ISC_FALSE; - const cfg_listelt_t *element; - - static optionstable options[] = { - { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE | - CHECKACL | STATICSTUBZONE }, - { "allow-notify", SLAVEZONE | CHECKACL }, - { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL }, - { "notify", MASTERZONE | SLAVEZONE }, - { "also-notify", MASTERZONE | SLAVEZONE }, - { "dialup", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "delegation-only", HINTZONE | STUBZONE | DELEGATIONZONE }, - { "forward", MASTERZONE | SLAVEZONE | STUBZONE | - STATICSTUBZONE | FORWARDZONE }, - { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | - STATICSTUBZONE | FORWARDZONE }, - { "maintain-ixfr-base", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, - { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, - { "notify-source", MASTERZONE | SLAVEZONE }, - { "notify-source-v6", MASTERZONE | SLAVEZONE }, - { "transfer-source", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "transfer-source-v6", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "max-transfer-time-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "max-transfer-time-out", MASTERZONE | SLAVEZONE }, - { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "max-transfer-idle-out", MASTERZONE | SLAVEZONE }, - { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "min-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "min-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "dnssec-secure-to-insecure", MASTERZONE }, - { "sig-re-signing-interval", MASTERZONE | SLAVEZONE }, - { "sig-signing-nodes", MASTERZONE | SLAVEZONE }, - { "sig-signing-signatures", MASTERZONE | SLAVEZONE }, - { "sig-signing-type", MASTERZONE | SLAVEZONE }, - { "sig-validity-interval", MASTERZONE | SLAVEZONE }, - { "signing", MASTERZONE | SLAVEZONE }, - { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE | - STATICSTUBZONE | REDIRECTZONE }, - { "allow-update", MASTERZONE | CHECKACL }, - { "allow-update-forwarding", SLAVEZONE | CHECKACL }, - { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | REDIRECTZONE }, - { "journal", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, - { "ixfr-base", MASTERZONE | SLAVEZONE }, - { "ixfr-tmp-file", MASTERZONE | SLAVEZONE }, - { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE }, - { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE }, - { "update-policy", MASTERZONE }, - { "database", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE }, - { "key-directory", MASTERZONE | SLAVEZONE }, - { "check-wildcard", MASTERZONE }, - { "check-mx", MASTERZONE }, - { "check-dup-records", MASTERZONE }, - { "integrity-check", MASTERZONE }, - { "check-mx-cname", MASTERZONE }, - { "check-srv-cname", MASTERZONE }, - { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | - REDIRECTZONE }, - { "update-check-ksk", MASTERZONE | SLAVEZONE }, - { "dnssec-dnskey-kskonly", MASTERZONE | SLAVEZONE }, - { "dnssec-loadkeys-interval", MASTERZONE | SLAVEZONE }, - { "auto-dnssec", MASTERZONE | SLAVEZONE }, - { "try-tcp-refresh", SLAVEZONE | STREDIRECTZONE }, - { "server-addresses", STATICSTUBZONE }, - { "server-names", STATICSTUBZONE }, - }; - - static optionstable dialups[] = { - { "notify", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, - { "notify-passive", SLAVEZONE | STREDIRECTZONE }, - { "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - { "passive", SLAVEZONE | STUBZONE | STREDIRECTZONE }, - }; - - znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); - - zoptions = cfg_tuple_get(zconfig, "options"); - - if (config != NULL) - cfg_map_get(config, "options", &goptions); - - obj = NULL; - (void)cfg_map_get(zoptions, "type", &obj); - if (obj == NULL) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': type not present", znamestr); - 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, "static-stub") == 0) - ztype = STATICSTUBZONE; - else if (strcasecmp(typestr, "forward") == 0) - ztype = FORWARDZONE; - else if (strcasecmp(typestr, "hint") == 0) - ztype = HINTZONE; - else if (strcasecmp(typestr, "delegation-only") == 0) - ztype = DELEGATIONZONE; - else if (strcasecmp(typestr, "redirect") == 0) - ztype = REDIRECTZONE; - else { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "zone '%s': invalid type %s", - znamestr, typestr); - return (ISC_R_FAILURE); - } - - if (ztype == REDIRECTZONE && strcmp(znamestr, ".") != 0) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "redirect zones must be called \".\""); - return (ISC_R_FAILURE); - } - 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", - znamestr, 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", - znamestr, r.base); - return (ISC_R_FAILURE); - } - } - - /* - * Look for an already existing zone. - * We need to make this canonical as isc_symtab_define() - * deals with strings. - */ - dns_fixedname_init(&fixedname); - isc_buffer_constinit(&b, znamestr, strlen(znamestr)); - isc_buffer_add(&b, strlen(znamestr)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b, - dns_rootname, DNS_NAME_DOWNCASE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': is not a valid name", znamestr); - result = ISC_R_FAILURE; - } else { - char namebuf[DNS_NAME_FORMATSIZE]; - - zname = dns_fixedname_name(&fixedname); - dns_name_format(zname, namebuf, sizeof(namebuf)); - tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : - ztype == REDIRECTZONE ? 2 : 3, - symtab, "zone '%s': already exists " - "previous definition: %s:%u", logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - if (dns_name_equal(zname, dns_rootname)) - root = ISC_TRUE; - } - - /* - * Check if value is zero. - */ - if (check_nonzero(zoptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - /* - * Look for inappropriate options for the given zone type. - * Check that ACLs expand correctly. - */ - 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) - { - 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, - znamestr); - 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, - znamestr); - } - obj = NULL; - if ((options[i].allowed & ztype) != 0 && - (options[i].allowed & CHECKACL) != 0) { - - tresult = checkacl(options[i].name, actx, zconfig, - voptions, config, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - } - - } - - /* - * Master & slave zones must have a "also-notify" field. - */ - if (ztype == MASTERZONE || ztype == SLAVEZONE ) { - obj = NULL; - tresult = cfg_map_get(zoptions, "also-notify", &obj); - if (tresult == ISC_R_SUCCESS) { - isc_uint32_t count; - tresult = validate_masters(obj, config, &count, - logctx, mctx); - if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) - result = tresult; - } - } - - /* - * Slave & stub zones must have a "masters" field. - */ - if (ztype == SLAVEZONE || ztype == STUBZONE) { - obj = NULL; - if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) { - cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, - "zone '%s': missing 'masters' entry", - znamestr); - result = ISC_R_FAILURE; - } else { - 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) { - cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, - "zone '%s': empty 'masters' entry", - znamestr); - result = ISC_R_FAILURE; - } - } - } - - /* - * Master zones can't have both "allow-update" and "update-policy". - */ - if (ztype == MASTERZONE || ztype == SLAVEZONE) { - isc_result_t res1, res2, res3; - const char *arg; - isc_boolean_t ddns = ISC_FALSE, signing = ISC_FALSE; - - 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", - znamestr); - result = ISC_R_FAILURE; - } else if (res2 == ISC_R_SUCCESS && - check_update_policy(obj, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS); - - obj = NULL; - res1 = cfg_map_get(zoptions, "inline-signing", &obj); - if (res1 == ISC_R_SUCCESS) - signing = cfg_obj_asboolean(obj); - - obj = NULL; - arg = "off"; - res3 = cfg_map_get(zoptions, "auto-dnssec", &obj); - if (res3 == ISC_R_SUCCESS) - arg = cfg_obj_asstring(obj); - if (strcasecmp(arg, "off") != 0 && !ddns && !signing) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'auto-dnssec %s;' requires%s " - "inline-signing to be configured for " - "the zone", arg, - (ztype == MASTERZONE) ? - " dynamic DNS or" : ""); - result = ISC_R_FAILURE; - } - if (strcasecmp(arg, "create") == 0) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'auto-dnssec create;' is not " - "yet implemented"); - result = ISC_R_FAILURE; - } - - obj = NULL; - res1 = cfg_map_get(zoptions, "sig-signing-type", &obj); - if (res1 == ISC_R_SUCCESS) { - isc_uint32_t type = cfg_obj_asuint32(obj); - if (type < 0xff00U || type > 0xffffU) - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "sig-signing-type: %u out of " - "range [%u..%u]", type, - 0xff00U, 0xffffU); - result = ISC_R_FAILURE; - } - - obj = NULL; - res1 = cfg_map_get(zoptions, "dnssec-dnskey-kskonly", &obj); - if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "dnssec-dnskey-kskonly: requires " - "inline-signing when used in slave zone"); - result = ISC_R_FAILURE; - } - - obj = NULL; - res1 = cfg_map_get(zoptions, "dnssec-loadkeys-interval", &obj); - if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "dnssec-loadkeys-interval: requires " - "inline-signing when used in slave zone"); - result = ISC_R_FAILURE; - } - - obj = NULL; - res1 = cfg_map_get(zoptions, "update-check-ksk", &obj); - if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "update-check-ksk: requires " - "inline-signing when used in slave zone"); - result = ISC_R_FAILURE; - } - } - - /* - * Check the excessively complicated "dialup" option. - */ - if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) { - const cfg_obj_t *dialup = NULL; - (void)cfg_map_get(zoptions, "dialup", &dialup); - if (dialup != NULL && cfg_obj_isstring(dialup)) { - const char *str = cfg_obj_asstring(dialup); - 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, znamestr); - 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, znamestr); - result = ISC_R_FAILURE; - } - } - } - - /* - * Check that forwarding is reasonable. - */ - obj = NULL; - if (root) { - if (voptions != NULL) - (void)cfg_map_get(voptions, "forwarders", &obj); - if (obj == NULL) { - const cfg_obj_t *options = NULL; - (void)cfg_map_get(config, "options", &options); - if (options != NULL) - (void)cfg_map_get(options, "forwarders", &obj); - } - } - if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - /* - * Check validity of static stub server addresses. - */ - obj = NULL; - (void)cfg_map_get(zoptions, "server-addresses", &obj); - if (ztype == STATICSTUBZONE && obj != NULL) { - for (element = cfg_list_first(obj); - element != NULL; - element = cfg_list_next(element)) - { - isc_sockaddr_t sa; - isc_netaddr_t na; - obj = cfg_listelt_value(element); - sa = *cfg_obj_assockaddr(obj); - - if (isc_sockaddr_getport(&sa) != 0) { - result = ISC_R_FAILURE; - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "port is not configurable for " - "static stub server-addresses"); - } - - isc_netaddr_fromsockaddr(&na, &sa); - if (isc_netaddr_getzone(&na) != 0) { - result = ISC_R_FAILURE; - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "scoped address is not allowed " - "for static stub " - "server-addresses"); - } - } - } - - /* - * Check validity of static stub server names. - */ - obj = NULL; - (void)cfg_map_get(zoptions, "server-names", &obj); - if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) { - for (element = cfg_list_first(obj); - element != NULL; - element = cfg_list_next(element)) - { - const char *snamestr; - dns_fixedname_t fixed_sname; - isc_buffer_t b2; - dns_name_t *sname; - - obj = cfg_listelt_value(element); - snamestr = cfg_obj_asstring(obj); - - dns_fixedname_init(&fixed_sname); - isc_buffer_constinit(&b2, snamestr, strlen(snamestr)); - isc_buffer_add(&b2, strlen(snamestr)); - sname = dns_fixedname_name(&fixed_sname); - tresult = dns_name_fromtext(sname, &b2, dns_rootname, - 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "server-name '%s' is not a valid " - "name", snamestr); - result = ISC_R_FAILURE; - } else if (dns_name_issubdomain(sname, zname)) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "server-name '%s' must not be a " - "subdomain of zone name '%s'", - snamestr, znamestr); - result = ISC_R_FAILURE; - } - } - } - - /* - * Check various options. - */ - tresult = check_options(zoptions, logctx, mctx, optlevel_zone); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - /* - * If the zone type is rbt/rbt64 then master/hint zones - * require file clauses. - * If inline signing is used, then slave zones require a - * file clause as well - */ - 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))) - { - isc_result_t res1; - obj = NULL; - tresult = cfg_map_get(zoptions, "file", &obj); - obj = NULL; - res1 = cfg_map_get(zoptions, "inline-signing", &obj); - if ((tresult != ISC_R_SUCCESS && - (ztype == MASTERZONE || ztype == HINTZONE)) || - (ztype == SLAVEZONE && res1 == ISC_R_SUCCESS)) { - cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': missing 'file' entry", - znamestr); - result = tresult; - } - } - - return (result); -} - - -typedef struct keyalgorithms { - const char *name; - isc_uint16_t size; -} algorithmtable; - -isc_result_t -bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { - const cfg_obj_t *algobj = NULL; - const cfg_obj_t *secretobj = NULL; - const char *keyname = cfg_obj_asstring(cfg_map_getname(key)); - const char *algorithm; - int i; - size_t len = 0; - isc_result_t result; - isc_buffer_t buf; - unsigned char secretbuf[1024]; - 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 } - }; - - (void)cfg_map_get(key, "algorithm", &algobj); - (void)cfg_map_get(key, "secret", &secretobj); - if (secretobj == NULL || algobj == NULL) { - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "key '%s' must have both 'secret' and " - "'algorithm' defined", - keyname); - return (ISC_R_FAILURE); - } - - isc_buffer_init(&buf, secretbuf, sizeof(secretbuf)); - result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR, - "bad secret '%s'", isc_result_totext(result)); - return (result); - } - - 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); - } - } - return (ISC_R_SUCCESS); -} - -/* - * Check key list for duplicates key names and that the key names - * are valid domain names as these keys are used for TSIG. - * - * Check the key contents for validity. - */ -static isc_result_t -check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab, - isc_mem_t *mctx, isc_log_t *logctx) -{ - char namebuf[DNS_NAME_FORMATSIZE]; - dns_fixedname_t fname; - dns_name_t *name; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - const cfg_listelt_t *element; - - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - for (element = cfg_list_first(keys); - element != NULL; - element = cfg_list_next(element)) - { - const cfg_obj_t *key = cfg_listelt_value(element); - const char *keyid = cfg_obj_asstring(cfg_map_getname(key)); - isc_symvalue_t symvalue; - isc_buffer_t b; - char *keyname; - - isc_buffer_constinit(&b, keyid, strlen(keyid)); - isc_buffer_add(&b, strlen(keyid)); - tresult = dns_name_fromtext(name, &b, dns_rootname, - 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "key '%s': bad key name", keyid); - result = tresult; - continue; - } - tresult = bind9_check_key(key, logctx); - if (tresult != ISC_R_SUCCESS) - return (tresult); - - dns_name_format(name, namebuf, sizeof(namebuf)); - keyname = isc_mem_strdup(mctx, namebuf); - if (keyname == NULL) - return (ISC_R_NOMEMORY); - symvalue.as_cpointer = key; - tresult = isc_symtab_define(symtab, keyname, 1, symvalue, - isc_symexists_reject); - if (tresult == ISC_R_EXISTS) { - const char *file; - unsigned int line; - - RUNTIME_CHECK(isc_symtab_lookup(symtab, keyname, - 1, &symvalue) == ISC_R_SUCCESS); - file = cfg_obj_file(symvalue.as_cpointer); - line = cfg_obj_line(symvalue.as_cpointer); - - if (file == NULL) - file = "<unknown file>"; - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "key '%s': already exists " - "previous definition: %s:%u", - keyid, file, line); - isc_mem_free(mctx, keyname); - result = tresult; - } else if (tresult != ISC_R_SUCCESS) { - isc_mem_free(mctx, keyname); - return (tresult); - } - } - return (result); -} - -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 } -}; - -/* - * RNDC keys are not normalised unlike TSIG keys. - * - * "foo." is different to "foo". - */ -static isc_boolean_t -rndckey_exists(const cfg_obj_t *keylist, const char *keyname) { - const cfg_listelt_t *element; - const cfg_obj_t *obj; - const char *str; - - if (keylist == NULL) - return (ISC_FALSE); - - 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)) - return (ISC_TRUE); - } - return (ISC_FALSE); -} - -static isc_result_t -check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, - isc_symtab_t *symtab, isc_log_t *logctx) -{ - dns_fixedname_t fname; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - const cfg_listelt_t *e1, *e2; - const cfg_obj_t *v1, *v2, *keys; - const cfg_obj_t *servers; - isc_netaddr_t n1, n2; - unsigned int p1, p2; - const cfg_obj_t *obj; - char buf[ISC_NETADDR_FORMATSIZE]; - char namebuf[DNS_NAME_FORMATSIZE]; - const char *xfr; - const char *keyval; - isc_buffer_t b; - int source; - dns_name_t *keyname; - - servers = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "server", &servers); - if (servers == NULL) - (void)cfg_map_get(config, "server", &servers); - if (servers == NULL) - return (ISC_R_SUCCESS); - - for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) { - v1 = cfg_listelt_value(e1); - cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1); - /* - * Check that unused bits are zero. - */ - tresult = isc_netaddr_prefixok(&n1, p1); - if (tresult != ISC_R_SUCCESS) { - INSIST(tresult == ISC_R_FAILURE); - isc_netaddr_format(&n1, buf, sizeof(buf)); - cfg_obj_log(v1, logctx, ISC_LOG_ERROR, - "server '%s/%u': invalid prefix " - "(extra bits specified)", buf, p1); - result = tresult; - } - 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/%u': %s not legal", - buf, p1, xfr); - result = ISC_R_FAILURE; - } - } while (sources[++source].v4 != NULL); - e2 = e1; - while ((e2 = cfg_list_next(e2)) != NULL) { - v2 = cfg_listelt_value(e2); - cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2); - if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) { - const char *file = cfg_obj_file(v1); - unsigned int line = cfg_obj_line(v1); - - if (file == NULL) - file = "<unknown file>"; - - isc_netaddr_format(&n2, buf, sizeof(buf)); - cfg_obj_log(v2, logctx, ISC_LOG_ERROR, - "server '%s/%u': already exists " - "previous definition: %s:%u", - buf, p2, file, line); - result = ISC_R_FAILURE; - } - } - keys = NULL; - cfg_map_get(v1, "keys", &keys); - if (keys != NULL) { - /* - * Normalize key name. - */ - keyval = cfg_obj_asstring(keys); - dns_fixedname_init(&fname); - isc_buffer_constinit(&b, keyval, strlen(keyval)); - isc_buffer_add(&b, strlen(keyval)); - keyname = dns_fixedname_name(&fname); - tresult = dns_name_fromtext(keyname, &b, dns_rootname, - 0, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(keys, logctx, ISC_LOG_ERROR, - "bad key name '%s'", keyval); - result = ISC_R_FAILURE; - continue; - } - dns_name_format(keyname, namebuf, sizeof(namebuf)); - tresult = isc_symtab_lookup(symtab, namebuf, 1, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(keys, logctx, ISC_LOG_ERROR, - "unknown key '%s'", keyval); - result = ISC_R_FAILURE; - } - } - } - return (result); -} - -static isc_result_t -check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed, - isc_log_t *logctx) -{ - const char *keystr, *keynamestr; - dns_fixedname_t fkeyname; - dns_name_t *keyname; - isc_buffer_t b; - isc_region_t r; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - isc_uint32_t flags, proto, alg; - unsigned char keydata[4096]; - - flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); - proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); - alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); - - dns_fixedname_init(&fkeyname); - keyname = dns_fixedname_name(&fkeyname); - keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); - - isc_buffer_constinit(&b, keynamestr, strlen(keynamestr)); - isc_buffer_add(&b, strlen(keynamestr)); - result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(key, logctx, ISC_LOG_WARNING, "bad key name: %s\n", - isc_result_totext(result)); - result = ISC_R_FAILURE; - } - - if (flags > 0xffff) { - cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "flags too big: %u\n", flags); - result = ISC_R_FAILURE; - } - if (proto > 0xff) { - cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "protocol too big: %u\n", proto); - result = ISC_R_FAILURE; - } - if (alg > 0xff) { - cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "algorithm too big: %u\n", alg); - result = ISC_R_FAILURE; - } - - if (managed) { - const char *initmethod; - initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); - - if (strcasecmp(initmethod, "initial-key") != 0) { - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "managed key '%s': " - "invalid initialization method '%s'", - keynamestr, initmethod); - result = ISC_R_FAILURE; - } - } - - isc_buffer_init(&b, keydata, sizeof(keydata)); - - keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); - tresult = isc_base64_decodestring(keystr, &b); - - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "%s", isc_result_totext(tresult)); - result = ISC_R_FAILURE; - } else { - isc_buffer_usedregion(&b, &r); - - if ((alg == DST_ALG_RSASHA1 || alg == DST_ALG_RSAMD5) && - r.length > 1 && r.base[0] == 1 && r.base[1] == 3) - cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "%s key '%s' has a weak exponent", - managed ? "managed" : "trusted", - keynamestr); - } - - return (result); -} - -static isc_result_t -check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, - const char *viewname, dns_rdataclass_t vclass, - isc_log_t *logctx, isc_mem_t *mctx) -{ - const cfg_obj_t *zones = NULL; - const cfg_obj_t *keys = NULL; - const cfg_listelt_t *element, *element2; - isc_symtab_t *symtab = NULL; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult = ISC_R_SUCCESS; - cfg_aclconfctx_t *actx = NULL; - const cfg_obj_t *obj; - const cfg_obj_t *options = NULL; - isc_boolean_t enablednssec, enablevalidation; - const char *valstr = "no"; - - /* - * Get global options block - */ - (void)cfg_map_get(config, "options", &options); - - /* - * Check that all zone statements are syntactically correct and - * there are no duplicate zones. - */ - tresult = isc_symtab_create(mctx, 1000, freekey, mctx, - ISC_FALSE, &symtab); - if (tresult != ISC_R_SUCCESS) - return (ISC_R_NOMEMORY); - - cfg_aclconfctx_create(mctx, &actx); - - if (voptions != NULL) - (void)cfg_map_get(voptions, "zone", &zones); - else - (void)cfg_map_get(config, "zone", &zones); - - for (element = cfg_list_first(zones); - element != NULL; - element = cfg_list_next(element)) - { - isc_result_t tresult; - const cfg_obj_t *zone = cfg_listelt_value(element); - - tresult = check_zoneconf(zone, voptions, config, symtab, - vclass, actx, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - - isc_symtab_destroy(&symtab); - - /* - * Check that forwarding is reasonable. - */ - if (voptions == NULL) { - if (options != NULL) - if (check_forward(options, NULL, - logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } else { - if (check_forward(voptions, NULL, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - - /* - * Check non-zero options at the global and view levels. - */ - if (options != NULL && check_nonzero(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - if (voptions != NULL &&check_nonzero(voptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - /* - * Check that dual-stack-servers is reasonable. - */ - if (voptions == NULL) { - if (options != NULL) - if (check_dual_stack(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } else { - if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - - /* - * Check that rrset-order is reasonable. - */ - if (voptions != NULL) { - if (check_order(voptions, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - - /* - * Check that all key statements are syntactically correct and - * there are no duplicate keys. - */ - tresult = isc_symtab_create(mctx, 1000, freekey, mctx, - ISC_FALSE, &symtab); - if (tresult != ISC_R_SUCCESS) - goto cleanup; - - (void)cfg_map_get(config, "key", &keys); - tresult = check_keylist(keys, symtab, mctx, logctx); - if (tresult == ISC_R_EXISTS) - result = ISC_R_FAILURE; - else if (tresult != ISC_R_SUCCESS) { - result = tresult; - goto cleanup; - } - - if (voptions != NULL) { - keys = NULL; - (void)cfg_map_get(voptions, "key", &keys); - tresult = check_keylist(keys, symtab, mctx, logctx); - if (tresult == ISC_R_EXISTS) - result = ISC_R_FAILURE; - else if (tresult != ISC_R_SUCCESS) { - result = tresult; - goto cleanup; - } - } - - /* - * Global servers can refer to keys in views. - */ - if (check_servers(config, voptions, symtab, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - isc_symtab_destroy(&symtab); - - /* - * Check that dnssec-enable/dnssec-validation are sensible. - */ - obj = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "dnssec-enable", &obj); - if (obj == NULL && options != NULL) - (void)cfg_map_get(options, "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 && options != NULL) - (void)cfg_map_get(options, "dnssec-validation", &obj); - if (obj == NULL) { - enablevalidation = enablednssec; - valstr = "yes"; - } else if (cfg_obj_isboolean(obj)) { - enablevalidation = cfg_obj_asboolean(obj); - valstr = enablevalidation ? "yes" : "no"; - } else { - enablevalidation = ISC_TRUE; - valstr = "auto"; - } - - if (enablevalidation && !enablednssec) - cfg_obj_log(obj, logctx, ISC_LOG_WARNING, - "'dnssec-validation %s;' and 'dnssec-enable no;'", - valstr); - - /* - * Check trusted-keys and managed-keys. - */ - keys = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "trusted-keys", &keys); - if (keys == NULL) - (void)cfg_map_get(config, "trusted-keys", &keys); - - for (element = cfg_list_first(keys); - element != NULL; - element = cfg_list_next(element)) - { - const cfg_obj_t *keylist = cfg_listelt_value(element); - for (element2 = cfg_list_first(keylist); - element2 != NULL; - element2 = cfg_list_next(element2)) { - obj = cfg_listelt_value(element2); - tresult = check_trusted_key(obj, ISC_FALSE, logctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - } - } - - keys = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "managed-keys", &keys); - if (keys == NULL) - (void)cfg_map_get(config, "managed-keys", &keys); - - for (element = cfg_list_first(keys); - element != NULL; - element = cfg_list_next(element)) - { - const cfg_obj_t *keylist = cfg_listelt_value(element); - for (element2 = cfg_list_first(keylist); - element2 != NULL; - element2 = cfg_list_next(element2)) { - obj = cfg_listelt_value(element2); - tresult = check_trusted_key(obj, ISC_TRUE, logctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - } - } - - /* - * Check options. - */ - if (voptions != NULL) - tresult = check_options(voptions, logctx, mctx, - optlevel_view); - else - tresult = check_options(config, logctx, mctx, - optlevel_config); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - tresult = check_viewacls(actx, voptions, config, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - tresult = check_recursionacls(actx, voptions, viewname, - config, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - tresult = check_filteraaaa(actx, voptions, viewname, config, - logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - tresult = check_dns64(actx, voptions, config, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = tresult; - - cleanup: - if (symtab != NULL) - isc_symtab_destroy(&symtab); - if (actx != NULL) - cfg_aclconfctx_detach(&actx); - - return (result); -} - -static const char * -default_channels[] = { - "default_syslog", - "default_stderr", - "default_debug", - "null", - NULL -}; - -static isc_result_t -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; - const char *channelname; - const char *catname; - 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; - 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); - - symvalue.as_cpointer = NULL; - 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); -} - -static isc_result_t -bind9_check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist, - isc_log_t *logctx) -{ - isc_result_t result = ISC_R_SUCCESS; - const cfg_obj_t *control_keylist; - const cfg_listelt_t *element; - const cfg_obj_t *key; - const char *keyval; - - 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); - keyval = cfg_obj_asstring(key); - - if (!rndckey_exists(keylist, keyval)) { - cfg_obj_log(key, logctx, ISC_LOG_ERROR, - "unknown key '%s'", keyval); - result = ISC_R_NOTFOUND; - } - } - return (result); -} - -static isc_result_t -bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx, - isc_mem_t *mctx) -{ - isc_result_t result = ISC_R_SUCCESS, tresult; - cfg_aclconfctx_t *actx = NULL; - 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; - 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); - - cfg_aclconfctx_create(mctx, &actx); - - /* - * 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, - actx, mctx, 0, &acl); - 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; - } - } - cfg_aclconfctx_detach(&actx); - return (result); -} - -isc_result_t -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 *views = NULL; - const cfg_obj_t *acls = NULL; - const cfg_obj_t *kals = NULL; - const cfg_obj_t *obj; - const cfg_listelt_t *velement; - isc_result_t result = ISC_R_SUCCESS; - isc_result_t tresult; - isc_symtab_t *symtab = NULL; - - static const char *builtin[] = { "localhost", "localnets", - "any", "none"}; - - (void)cfg_map_get(config, "options", &options); - - if (options != NULL && - check_options(options, logctx, mctx, - optlevel_options) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - if (bind9_check_logging(config, logctx, mctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - if (options != NULL && - check_order(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - (void)cfg_map_get(config, "view", &views); - - if (views != NULL && options != NULL) - if (check_dual_stack(options, logctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - - if (views == NULL) { - if (check_viewconf(config, NULL, NULL, dns_rdataclass_in, - logctx, mctx) != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } else { - const cfg_obj_t *zones = NULL; - - (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; - } - } - - tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab); - if (tresult != ISC_R_SUCCESS) - result = tresult; - for (velement = cfg_list_first(views); - velement != NULL; - velement = cfg_list_next(velement)) - { - 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"); - dns_rdataclass_t vclass = dns_rdataclass_in; - isc_result_t tresult = ISC_R_SUCCESS; - const char *key = cfg_obj_asstring(vname); - isc_symvalue_t symvalue; - - 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) - cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR, - "view '%s': invalid class %s", - cfg_obj_asstring(vname), r.base); - } - if (tresult == ISC_R_SUCCESS && symtab != NULL) { - symvalue.as_cpointer = view; - 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); - file = cfg_obj_file(symvalue.as_cpointer); - line = cfg_obj_line(symvalue.as_cpointer); - cfg_obj_log(view, logctx, ISC_LOG_ERROR, - "view '%s': already exists " - "previous definition: %s:%u", - key, file, line); - result = tresult; - } else if (tresult != ISC_R_SUCCESS) { - result = tresult; - } 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; - } - } - if (tresult == ISC_R_SUCCESS) - tresult = check_viewconf(config, voptions, key, - vclass, logctx, mctx); - if (tresult != ISC_R_SUCCESS) - result = ISC_R_FAILURE; - } - if (symtab != NULL) - isc_symtab_destroy(&symtab); - - if (views != NULL && options != NULL) { - obj = NULL; - tresult = cfg_map_get(options, "cache-file", &obj); - if (tresult == ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'cache-file' cannot be a global " - "option if views are present"); - result = ISC_R_FAILURE; - } - } - - cfg_map_get(config, "acl", &acls); - - if (acls != NULL) { - const cfg_listelt_t *elt; - const cfg_listelt_t *elt2; - const char *aclname; - - for (elt = cfg_list_first(acls); - elt != NULL; - elt = cfg_list_next(elt)) { - const cfg_obj_t *acl = cfg_listelt_value(elt); - unsigned int line = cfg_obj_line(acl); - unsigned int i; - - aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name")); - for (i = 0; - i < sizeof(builtin) / sizeof(builtin[0]); - i++) - 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; - } - - for (elt2 = cfg_list_next(elt); - elt2 != NULL; - elt2 = cfg_list_next(elt2)) { - const cfg_obj_t *acl2 = cfg_listelt_value(elt2); - const char *name; - name = cfg_obj_asstring(cfg_tuple_get(acl2, - "name")); - if (strcasecmp(aclname, name) == 0) { - const char *file = cfg_obj_file(acl); - - if (file == NULL) - file = "<unknown file>"; - - cfg_obj_log(acl2, logctx, ISC_LOG_ERROR, - "attempt to redefine " - "acl '%s' previous " - "definition: %s:%u", - name, file, line); - result = ISC_R_FAILURE; - } - } - } - } - - tresult = cfg_map_get(config, "kal", &kals); - if (tresult == ISC_R_SUCCESS) { - const cfg_listelt_t *elt; - const cfg_listelt_t *elt2; - const char *aclname; - - for (elt = cfg_list_first(kals); - elt != NULL; - elt = cfg_list_next(elt)) { - const cfg_obj_t *acl = cfg_listelt_value(elt); - - aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name")); - - for (elt2 = cfg_list_next(elt); - elt2 != NULL; - elt2 = cfg_list_next(elt2)) { - const cfg_obj_t *acl2 = cfg_listelt_value(elt2); - 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; - } - } - } - } - - return (result); -} |