summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/bind9/check.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/bind9/check.c')
-rw-r--r--contrib/bind9/lib/bind9/check.c2935
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);
-}
OpenPOWER on IntegriCloud