check.c revision 508f61f8d699c46f962b682f388e54b446a7194d
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein/*
11e9368a226272085c337e9e74b79808c16fbdbaTinderbox User * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
75c0816e8295e180f4bc7f10db3d0d880383bc1cMark Andrews * Copyright (C) 2001-2003 Internet Software Consortium.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein *
4a14ce5ba00ab7bc55c99ffdcf59c7a4ab902721Automatic Updater * Permission to use, copy, modify, and distribute this software for any
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * purpose with or without fee is hereby granted, provided that the above
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * copyright notice and this permission notice appear in all copies.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein *
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein * PERFORMANCE OF THIS SOFTWARE.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein/* $Id: check.c,v 1.52 2005/01/09 23:40:00 marka Exp $ */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <config.h>
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt#include <stdlib.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <string.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/buffer.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/log.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/mem.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/netaddr.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/parseint.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/region.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/result.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/sockaddr.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/symtab.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isc/util.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/fixedname.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/rdataclass.h>
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User#include <dns/rdatatype.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/secalg.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <isccfg/cfg.h>
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User#include <bind9/check.h>
11e9368a226272085c337e9e74b79808c16fbdbaTinderbox User
75c0816e8295e180f4bc7f10db3d0d880383bc1cMark Andrewsstatic void
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinfreekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein UNUSED(type);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein UNUSED(value);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_mem_free(userarg, key);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein}
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinstatic isc_result_t
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeincheck_orderent(cfg_obj_t *ent, isc_log_t *logctx) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_result_t result = ISC_R_SUCCESS;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_result_t tresult;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_textregion_t r;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_fixedname_t fixed;
010a51c427bfb6ab658fc0056955a1a5b69810beTinderbox User cfg_obj_t *obj;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_rdataclass_t rdclass;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_rdatatype_t rdtype;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_t b;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User const char *str;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_fixedname_init(&fixed);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein obj = cfg_tuple_get(ent, "class");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (cfg_obj_isstring(obj)) {
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein DE_CONST(cfg_obj_asstring(obj), r.base);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User r.length = strlen(r.base);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User tresult = dns_rdataclass_fromtext(&rdclass, &r);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (tresult != ISC_R_SUCCESS) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User "rrset-order: invalid class '%s'",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein r.base);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein result = ISC_R_FAILURE;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User obj = cfg_tuple_get(ent, "type");
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (cfg_obj_isstring(obj)) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User DE_CONST(cfg_obj_asstring(obj), r.base);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User r.length = strlen(r.base);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein tresult = dns_rdatatype_fromtext(&rdtype, &r);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (tresult != ISC_R_SUCCESS) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "rrset-order: invalid type '%s'",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein r.base);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein result = ISC_R_FAILURE;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt obj = cfg_tuple_get(ent, "name");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt if (cfg_obj_isstring(obj)) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User str = cfg_obj_asstring(obj);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_init(&b, str, strlen(str));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_buffer_add(&b, strlen(str));
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
2b4d1b54f6ca406b8233d9e6fea9593df6dad035Tinderbox User dns_rootname, ISC_FALSE, NULL);
2b4d1b54f6ca406b8233d9e6fea9593df6dad035Tinderbox User if (tresult != ISC_R_SUCCESS) {
2b4d1b54f6ca406b8233d9e6fea9593df6dad035Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
2b4d1b54f6ca406b8233d9e6fea9593df6dad035Tinderbox User "rrset-order: invalid name '%s'", str);
2b4d1b54f6ca406b8233d9e6fea9593df6dad035Tinderbox User result = ISC_R_FAILURE;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User }
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt obj = cfg_tuple_get(ent, "order");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (!cfg_obj_isstring(obj) ||
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User strcasecmp("order", cfg_obj_asstring(obj)) != 0) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User "rrset-order: keyword 'order' missing");
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater result = ISC_R_FAILURE;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
6f64d4ab8e68f9b2333bcbfc755396d29a4a9d7cAutomatic Updater
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User obj = cfg_tuple_get(ent, "ordering");
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User if (!cfg_obj_isstring(obj)) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User "rrset-order: missing ordering");
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User result = ISC_R_FAILURE;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User } else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User "rrset-order: order 'fixed' not implemented");
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User } else if (/* strcasecmp(cfg_obj_asstring(obj), "fixed") != 0 && */
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User "rrset-order: invalid order '%s'",
6f64d4ab8e68f9b2333bcbfc755396d29a4a9d7cAutomatic Updater cfg_obj_asstring(obj));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = ISC_R_FAILURE;
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater }
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User return (result);
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User}
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntstatic isc_result_t
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox Usercheck_order(cfg_obj_t *options, isc_log_t *logctx) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User isc_result_t result = ISC_R_SUCCESS;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User isc_result_t tresult;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_listelt_t *element;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_obj_t *obj = NULL;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS)
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User return (result);
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt for (element = cfg_list_first(obj);
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater element != NULL;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User element = cfg_list_next(element))
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User {
bcf15a19ae0efa72a22cdfb50666a3c6ce39eb9fTinderbox User tresult = check_orderent(cfg_listelt_value(element), logctx);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt if (tresult != ISC_R_SUCCESS)
bcf15a19ae0efa72a22cdfb50666a3c6ce39eb9fTinderbox User result = tresult;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User }
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User return (result);
983df82baf1d7d0b668c98cf45928a19f175c6e7Tinderbox User}
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox Userstatic isc_result_t
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox Usercheck_dual_stack(cfg_obj_t *options, isc_log_t *logctx) {
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User cfg_listelt_t *element;
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User cfg_obj_t *alternates = NULL;
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User cfg_obj_t *value;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_t *obj;
983df82baf1d7d0b668c98cf45928a19f175c6e7Tinderbox User char *str;
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User dns_fixedname_t fixed;
260e8e04b0dc24cb884c789b5d9eb046457f264eTinderbox User dns_name_t *name;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_buffer_t buffer;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_result_t result = ISC_R_SUCCESS;
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews isc_result_t tresult;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User (void)cfg_map_get(options, "dual-stack-servers", &alternates);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (alternates == NULL)
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews return (ISC_R_SUCCESS);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt obj = cfg_tuple_get(alternates, "port");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (cfg_obj_isuint32(obj)) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_uint32_t val = cfg_obj_asuint32(obj);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (val > ISC_UINT16_MAX) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "port '%u' out of range", val);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein result = ISC_R_FAILURE;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein obj = cfg_tuple_get(alternates, "addresses");
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User for (element = cfg_list_first(obj);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt element != NULL;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein element = cfg_list_next(element)) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User value = cfg_listelt_value(element);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (cfg_obj_issockaddr(value))
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User continue;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User obj = cfg_tuple_get(value, "name");
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User str = cfg_obj_asstring(obj);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_init(&buffer, str, strlen(str));
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_add(&buffer, strlen(str));
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_fixedname_init(&fixed);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User name = dns_fixedname_name(&fixed);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User tresult = dns_name_fromtext(name, &buffer, dns_rootname,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ISC_FALSE, NULL);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (tresult != ISC_R_SUCCESS) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "bad name '%s'", str);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = ISC_R_FAILURE;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein obj = cfg_tuple_get(value, "port");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt if (cfg_obj_isuint32(obj)) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_uint32_t val = cfg_obj_asuint32(obj);
a1ad6695ed6f988406cf155aa26376f84f73bcb9Automatic Updater if (val > ISC_UINT16_MAX) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User "port '%u' out of range", val);
2895f101b5585a19015ac2c2c1e1812ac467fa12Automatic Updater result = ISC_R_FAILURE;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt return (result);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User}
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinstatic isc_result_t
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox Usercheck_forward(cfg_obj_t *options, isc_log_t *logctx) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_obj_t *forward = NULL;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_t *forwarders = NULL;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt (void)cfg_map_get(options, "forward", &forward);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User (void)cfg_map_get(options, "forwarders", &forwarders);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (forward != NULL && forwarders == NULL) {
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User "no matching 'forwarders' statement");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt return (ISC_R_FAILURE);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt return (ISC_R_SUCCESS);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt}
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Huntstatic isc_result_t
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindisabled_algorithms(cfg_obj_t *disabled, isc_log_t *logctx) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_result_t result = ISC_R_SUCCESS;
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews isc_result_t tresult;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_listelt_t *element;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt const char *str;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_t b;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_fixedname_t fixed;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User dns_name_t *name;
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User cfg_obj_t *obj;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt dns_fixedname_init(&fixed);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein name = dns_fixedname_name(&fixed);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein obj = cfg_tuple_get(disabled, "name");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein str = cfg_obj_asstring(obj);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User isc_buffer_init(&b, str, strlen(str));
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User isc_buffer_add(&b, strlen(str));
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User if (tresult != ISC_R_SUCCESS) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User "bad domain name '%s'", str);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = tresult;
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt obj = cfg_tuple_get(disabled, "algorithms");
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User for (element = cfg_list_first(obj);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt element != NULL;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt element = cfg_list_next(element))
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_textregion_t r;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt dns_secalg_t alg;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_result_t tresult;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt r.base = cfg_obj_asstring(cfg_listelt_value(element));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt r.length = strlen(r.base);
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User tresult = dns_secalg_fromtext(&alg, &r);
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User if (tresult != ISC_R_SUCCESS) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt isc_uint8_t ui;
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = isc_parse_uint8(&ui, r.base, 10);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt if (tresult != ISC_R_SUCCESS) {
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt cfg_obj_log(cfg_listelt_value(element), logctx,
af40ebed6257e4ac1996144530b3de317cf4da11Tinderbox User ISC_LOG_ERROR, "invalid algorithm");
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater result = tresult;
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User }
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User }
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User return (result);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt}
44d0f0256fbdce130a18655023c3b06bacacbd61Automatic Updater
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox Userstatic isc_result_t
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox Usernameexist(cfg_obj_t *obj, const char *name, int value, isc_symtab_t *symtab,
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User const char *fmt, isc_log_t *logctx, isc_mem_t *mctx)
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User{
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User char *key;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User const char *file;
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User unsigned int line;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_result_t result;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_symvalue_t symvalue;
cd32f419a8a5432fbb139f56ee73cbf68b9350ccTinderbox User
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews key = isc_mem_strdup(mctx, name);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if (key == NULL)
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews return (ISC_R_NOMEMORY);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews symvalue.as_pointer = obj;
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews result = isc_symtab_define(symtab, key, value, symvalue,
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews isc_symexists_reject);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if (result == ISC_R_EXISTS) {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
e108f2ec640e1acb54999c0ade58af606149956dTinderbox User &symvalue) == ISC_R_SUCCESS);
6d382c9fcec316a84a237779fb64bb471b6f9d43Tinderbox User file = cfg_obj_file(symvalue.as_pointer);
6d382c9fcec316a84a237779fb64bb471b6f9d43Tinderbox User line = cfg_obj_line(symvalue.as_pointer);
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User
f9aef05653eeb454c489d5bd2bde6daab774ad4aTinderbox User if (file == NULL)
f9aef05653eeb454c489d5bd2bde6daab774ad4aTinderbox User file = "<unknown file>";
f9aef05653eeb454c489d5bd2bde6daab774ad4aTinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
f9aef05653eeb454c489d5bd2bde6daab774ad4aTinderbox User isc_mem_free(mctx, key);
f9aef05653eeb454c489d5bd2bde6daab774ad4aTinderbox User result = ISC_R_EXISTS;
922312472e2e05ebc64993d465999c5351b83036Automatic Updater } else if (result != ISC_R_SUCCESS) {
922312472e2e05ebc64993d465999c5351b83036Automatic Updater isc_mem_free(mctx, key);
922312472e2e05ebc64993d465999c5351b83036Automatic Updater }
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User return (result);
50066670817cdf9e86c832066d73715232b29680Tinderbox User}
50066670817cdf9e86c832066d73715232b29680Tinderbox User
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updaterstatic isc_result_t
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updatermustbesecure(cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
28b3569d6248168e6c00caab951521cc8141a49dAutomatic Updater isc_mem_t *mctx)
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews{
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cfg_obj_t *obj;
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews char namebuf[DNS_NAME_FORMATSIZE];
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User const char *str;
2cbb4ab75757fbb656997a82c14ca07db37d481aAutomatic Updater dns_fixedname_t fixed;
2cbb4ab75757fbb656997a82c14ca07db37d481aAutomatic Updater dns_name_t *name;
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User isc_buffer_t b;
0a7ed88633a680bb881868b75ded4d09a7bbbc50Automatic Updater isc_result_t result = ISC_R_SUCCESS;
0a7ed88633a680bb881868b75ded4d09a7bbbc50Automatic Updater
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews dns_fixedname_init(&fixed);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews name = dns_fixedname_name(&fixed);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews obj = cfg_tuple_get(secure, "name");
c3dc968140ab7f04795acc7835e4e89ccb0c0a27Tinderbox User str = cfg_obj_asstring(obj);
c3dc968140ab7f04795acc7835e4e89ccb0c0a27Tinderbox User isc_buffer_init(&b, str, strlen(str));
c3dc968140ab7f04795acc7835e4e89ccb0c0a27Tinderbox User isc_buffer_add(&b, strlen(str));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if (result != ISC_R_SUCCESS) {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt "bad domain name '%s'", str);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews } else {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews dns_name_format(name, namebuf, sizeof(namebuf));
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt result = nameexist(secure, namebuf, 1, symtab,
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "dnssec-must-be-secure '%s': already "
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews "exists previous definition: %s:%u",
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt logctx, mctx);
ad8f23aed6c75f94f238c1f23f4e17515d28eb55Tinderbox User }
ad8f23aed6c75f94f238c1f23f4e17515d28eb55Tinderbox User return (result);
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt}
ad8f23aed6c75f94f238c1f23f4e17515d28eb55Tinderbox User
ad8f23aed6c75f94f238c1f23f4e17515d28eb55Tinderbox Usertypedef struct {
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater const char *name;
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater unsigned int scale;
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater unsigned int max;
dec590a3deb8e87380a8bd3a77d535dba3729bf6Tinderbox User} intervaltable;
b6b8f8a0362da8c749021c4b6376cfb96047912bTinderbox User
b6b8f8a0362da8c749021c4b6376cfb96047912bTinderbox Userstatic isc_result_t
0c6ada0a814f3c5417daa1654129bc2af56ed504Automatic Updatercheck_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
0c6ada0a814f3c5417daa1654129bc2af56ed504Automatic Updater isc_result_t result = ISC_R_SUCCESS;
0c6ada0a814f3c5417daa1654129bc2af56ed504Automatic Updater isc_result_t tresult;
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews unsigned int i;
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cfg_obj_t *obj = NULL;
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews cfg_listelt_t *element;
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews isc_symtab_t *symtab = NULL;
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater static intervaltable intervals[] = {
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater { "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater { "heartbeat-interval", 60, 28 * 24 * 60 }, /* 28 days */
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater { "interface-interval", 60, 28 * 24 * 60 }, /* 28 days */
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater { "max-transfer-idle-in", 60, 28 * 24 * 60 }, /* 28 days */
9b469e3c59015b1a4899c9d8395168126fe094fdAutomatic Updater { "max-transfer-idle-out", 60, 28 * 24 * 60 }, /* 28 days */
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater { "max-transfer-time-in", 60, 28 * 24 * 60 }, /* 28 days */
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater { "max-transfer-time-out", 60, 28 * 24 * 60 }, /* 28 days */
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater { "sig-validity-interval", 86400, 10 * 366 }, /* 10 years */
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */
10b865e9187fc77cae02f106ddcc9e03eecdfe06Tinderbox User };
10b865e9187fc77cae02f106ddcc9e03eecdfe06Tinderbox User
10b865e9187fc77cae02f106ddcc9e03eecdfe06Tinderbox User /*
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater * Check that fields specified in units of time other than seconds
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater * have reasonable values.
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater */
fdd80e9a55c70b36a3bf3e409b86897301c44ff8Automatic Updater for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
fdd80e9a55c70b36a3bf3e409b86897301c44ff8Automatic Updater isc_uint32_t val;
fdd80e9a55c70b36a3bf3e409b86897301c44ff8Automatic Updater obj = NULL;
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater (void)cfg_map_get(options, intervals[i].name, &obj);
e2e4d321999340802f77adaacd19c797d04b4b95Automatic Updater if (obj == NULL)
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews continue;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein val = cfg_obj_asuint32(obj);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (val > intervals[i].max) {
fd2597f75693a2279fdf588bd40dfe2407c42028Tinderbox User cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "%s '%u' is out of range (0..%u)",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein intervals[i].name, val,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein intervals[i].max);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein result = ISC_R_RANGE;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein } else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "%s '%d' is out of range",
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein intervals[i].name, val);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein result = ISC_R_RANGE;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein obj = NULL;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (void)cfg_map_get(options, "preferred-glue", &obj);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (obj != NULL) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein const char *str;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein str = cfg_obj_asstring(obj);
a1ff871f78b7d907d6fc3a382beea2a640fe8423Tinderbox User if (strcasecmp(str, "a") != 0 &&
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein strcasecmp(str, "aaaa") != 0 &&
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein 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)) {
cfg_listelt_t *element;
cfg_obj_t *exclude;
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_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(name, &b,
dns_rootname,
ISC_FALSE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'",
str);
result = tresult;
}
}
}
}
/*
* 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;
}
}
/*
* 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_TRUE, &symtab);
if (tresult != ISC_R_SUCCESS)
result = tresult;
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
dns_fixedname_t fixedname;
dns_name_t *name;
const char *dlv;
isc_buffer_t b;
obj = cfg_listelt_value(element);
dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain"));
dns_fixedname_init(&fixedname);
name = dns_fixedname_name(&fixedname);
isc_buffer_init(&b, dlv, strlen(dlv));
isc_buffer_add(&b, strlen(dlv));
tresult = dns_name_fromtext(name, &b, dns_rootname,
ISC_TRUE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", dlv);
result = tresult;
}
if (symtab != NULL) {
tresult = nameexist(obj, dlv, 1, symtab,
"dnssec-lookaside '%s': "
"already exists previous "
"definition: %s:%u",
logctx, mctx);
if (tresult != ISC_R_SUCCESS &&
result == ISC_R_SUCCESS)
result = tresult;
}
/*
* XXXMPA to be removed when multiple lookaside
* namespaces are supported.
*/
if (!dns_name_equal(dns_rootname, name)) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"dnssec-lookaside '%s': "
"non-root not yet supported", dlv);
if (result == ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
dlv = cfg_obj_asstring(cfg_tuple_get(obj,
"trust-anchor"));
dns_fixedname_init(&fixedname);
isc_buffer_init(&b, dlv, strlen(dlv));
isc_buffer_add(&b, strlen(dlv));
tresult = dns_name_fromtext(name, &b, dns_rootname,
ISC_TRUE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", dlv);
if (result == ISC_R_SUCCESS)
result = tresult;
}
}
if (symtab != NULL)
isc_symtab_destroy(&symtab);
}
/*
* Check dnssec-must-be-secure.
*/
obj = NULL;
(void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
if (obj != NULL) {
isc_symtab_t *symtab = NULL;
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
ISC_FALSE, &symtab);
if (tresult != ISC_R_SUCCESS)
result = tresult;
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
tresult = mustbesecure(obj, symtab, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
if (symtab != NULL)
isc_symtab_destroy(&symtab);
}
return (result);
}
static isc_result_t
get_masters_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *masters = NULL;
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)) {
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(cfg_obj_t *obj, 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;
cfg_listelt_t *element;
cfg_listelt_t **stack = NULL;
isc_uint32_t stackcount = 0, pushed = 0;
cfg_obj_t *list;
REQUIRE(countp != NULL);
result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
if (result != ISC_R_SUCCESS)
return (result);
newlist:
list = cfg_tuple_get(obj, "addresses");
element = cfg_list_first(list);
resume:
for ( ;
element != NULL;
element = cfg_list_next(element))
{
char *listname;
cfg_obj_t *addr;
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_pointer = 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) {
memcpy(new, stack, oldsize);
isc_mem_put(mctx, stack, oldsize);
}
stack = new;
stackcount = newlen;
}
stack[pushed++] = cfg_list_next(element);
goto newlist;
}
if (pushed != 0) {
element = stack[--pushed];
goto resume;
}
cleanup:
if (stack != NULL)
isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
isc_symtab_destroy(&symtab);
*countp = count;
return (result);
}
#define MASTERZONE 1
#define SLAVEZONE 2
#define STUBZONE 4
#define HINTZONE 8
#define FORWARDZONE 16
#define DELEGATIONZONE 32
typedef struct {
const char *name;
int allowed;
} optionstable;
static isc_result_t
check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
dns_rdataclass_t defclass, isc_log_t *logctx, isc_mem_t *mctx)
{
const char *zname;
const char *typestr;
unsigned int ztype;
cfg_obj_t *zoptions;
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;
isc_buffer_t b;
static optionstable options[] = {
{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE },
{ "allow-notify", SLAVEZONE },
{ "allow-transfer", MASTERZONE | SLAVEZONE },
{ "notify", MASTERZONE | SLAVEZONE },
{ "also-notify", MASTERZONE | SLAVEZONE },
{ "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
{ "delegation-only", HINTZONE | STUBZONE },
{ "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
{ "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
{ "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
{ "max-ixfr-log-size", MASTERZONE | SLAVEZONE },
{ "notify-source", MASTERZONE | SLAVEZONE },
{ "notify-source-v6", MASTERZONE | SLAVEZONE },
{ "transfer-source", SLAVEZONE | STUBZONE },
{ "transfer-source-v6", SLAVEZONE | STUBZONE },
{ "max-transfer-time-in", SLAVEZONE | STUBZONE },
{ "max-transfer-time-out", MASTERZONE | SLAVEZONE },
{ "max-transfer-idle-in", SLAVEZONE | STUBZONE },
{ "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
{ "max-retry-time", SLAVEZONE | STUBZONE },
{ "min-retry-time", SLAVEZONE | STUBZONE },
{ "max-refresh-time", SLAVEZONE | STUBZONE },
{ "min-refresh-time", SLAVEZONE | STUBZONE },
{ "sig-validity-interval", MASTERZONE },
{ "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
{ "allow-update", MASTERZONE },
{ "allow-update-forwarding", SLAVEZONE },
{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
{ "journal", MASTERZONE | SLAVEZONE },
{ "ixfr-base", MASTERZONE | SLAVEZONE },
{ "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
{ "masters", SLAVEZONE | STUBZONE },
{ "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
{ "update-policy", MASTERZONE },
{ "database", MASTERZONE | SLAVEZONE | STUBZONE },
{ "key-directory", MASTERZONE },
{ "check-wildcard", MASTERZONE },
};
static optionstable dialups[] = {
{ "notify", MASTERZONE | SLAVEZONE },
{ "notify-passive", SLAVEZONE },
{ "refresh", SLAVEZONE | STUBZONE },
{ "passive", SLAVEZONE | STUBZONE },
};
zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
zoptions = cfg_tuple_get(zconfig, "options");
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", zname);
return (ISC_R_FAILURE);
}
typestr = cfg_obj_asstring(obj);
if (strcasecmp(typestr, "master") == 0)
ztype = MASTERZONE;
else if (strcasecmp(typestr, "slave") == 0)
ztype = SLAVEZONE;
else if (strcasecmp(typestr, "stub") == 0)
ztype = STUBZONE;
else if (strcasecmp(typestr, "forward") == 0)
ztype = FORWARDZONE;
else if (strcasecmp(typestr, "hint") == 0)
ztype = HINTZONE;
else if (strcasecmp(typestr, "delegation-only") == 0)
ztype = DELEGATIONZONE;
else {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': invalid type %s",
zname, typestr);
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",
zname, r.base);
return (ISC_R_FAILURE);
}
if (zclass != defclass) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': class '%s' does not "
"match view/default class",
zname, r.base);
return (ISC_R_FAILURE);
}
}
/*
* Look for an already existing zone.
* We need to make this cannonical as isc_symtab_define()
* deals with strings.
*/
dns_fixedname_init(&fixedname);
isc_buffer_init(&b, zname, strlen(zname));
isc_buffer_add(&b, strlen(zname));
tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
dns_rootname, ISC_TRUE, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
"zone '%s': is not a valid name", zname);
tresult = ISC_R_FAILURE;
} else {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(dns_fixedname_name(&fixedname),
namebuf, sizeof(namebuf));
tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2,
symtab, "zone '%s': already exists "
"previous definition: %s:%u", logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
/*
* Look for inappropriate options for the given zone type.
*/
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, zname);
result = ISC_R_FAILURE;
} else
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
"option '%s' is not allowed "
"in '%s' zone '%s'",
options[i].name, typestr, zname);
}
}
/*
* 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",
zname);
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",
zname);
result = ISC_R_FAILURE;
}
}
}
/*
* Master zones can't have both "allow-update" and "update-policy".
*/
if (ztype == MASTERZONE) {
isc_result_t res1, res2;
obj = NULL;
res1 = cfg_map_get(zoptions, "allow-update", &obj);
obj = NULL;
res2 = cfg_map_get(zoptions, "update-policy", &obj);
if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': 'allow-update' is ignored "
"when 'update-policy' is present",
zname);
result = ISC_R_FAILURE;
}
}
/*
* Check the excessively complicated "dialup" option.
*/
if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
cfg_obj_t *dialup = NULL;
(void)cfg_map_get(zoptions, "dialup", &dialup);
if (dialup != NULL && cfg_obj_isstring(dialup)) {
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, zname);
result = ISC_R_FAILURE;
}
break;
}
if (i == sizeof(dialups) / sizeof(dialups[0])) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"invalid dialup type '%s' in zone "
"'%s'", str, zname);
result = ISC_R_FAILURE;
}
}
}
/*
* Check that forwarding is reasonable.
*/
if (check_forward(zoptions, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
/*
* Check various options.
*/
tresult = check_options(zoptions, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
/*
* If the zone type is rbt/rbt64 then master/hint zones
* require file clauses.
*/
obj = NULL;
tresult = cfg_map_get(zoptions, "database", &obj);
if (tresult == ISC_R_NOTFOUND ||
(tresult == ISC_R_SUCCESS &&
(strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) {
obj = NULL;
tresult = cfg_map_get(zoptions, "file", &obj);
if (tresult != ISC_R_SUCCESS &&
(ztype == MASTERZONE || ztype == HINTZONE)) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
"zone '%s': missing 'file' entry",
zname);
result = tresult;
}
}
return (result);
}
isc_result_t
bind9_check_key(cfg_obj_t *key, isc_log_t *logctx) {
cfg_obj_t *algobj = NULL;
cfg_obj_t *secretobj = NULL;
const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
(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);
}
return (ISC_R_SUCCESS);
}
static isc_result_t
check_keylist(cfg_obj_t *keys, isc_symtab_t *symtab, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
cfg_listelt_t *element;
for (element = cfg_list_first(keys);
element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *key = cfg_listelt_value(element);
const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
isc_symvalue_t symvalue;
symvalue.as_pointer = 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_pointer);
line = cfg_obj_line(symvalue.as_pointer);
if (file == NULL)
file = "<unknown file>";
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"key '%s': already exists "
"previous definition: %s:%u",
keyname, file, line);
result = tresult;
} else if (tresult != ISC_R_SUCCESS)
return (tresult);
tresult = bind9_check_key(key, logctx);
if (tresult != ISC_R_SUCCESS)
return (tresult);
}
return (result);
}
static isc_result_t
check_servers(cfg_obj_t *servers, isc_log_t *logctx) {
isc_result_t result = ISC_R_SUCCESS;
cfg_listelt_t *e1, *e2;
cfg_obj_t *v1, *v2;
isc_sockaddr_t *s1, *s2;
isc_netaddr_t na;
cfg_obj_t *ts;
char buf[128];
const char *xfr;
isc_buffer_t target;
for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
v1 = cfg_listelt_value(e1);
s1 = cfg_obj_assockaddr(cfg_map_getname(v1));
ts = NULL;
if (isc_sockaddr_pf(s1) == AF_INET)
xfr = "transfer-source-v6";
else
xfr = "transfer-source";
(void)cfg_map_get(v1, xfr, &ts);
if (ts != NULL) {
isc_netaddr_fromsockaddr(&na, s1);
isc_buffer_init(&target, buf, sizeof(buf) - 1);
RUNTIME_CHECK(isc_netaddr_totext(&na, &target)
== ISC_R_SUCCESS);
buf[isc_buffer_usedlength(&target)] = '\0';
cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
"server '%s': %s not valid", buf, xfr);
result = ISC_R_FAILURE;
}
e2 = e1;
while ((e2 = cfg_list_next(e2)) != NULL) {
v2 = cfg_listelt_value(e2);
s2 = cfg_obj_assockaddr(cfg_map_getname(v2));
if (isc_sockaddr_eqaddr(s1, s2)) {
const char *file = cfg_obj_file(v1);
unsigned int line = cfg_obj_line(v1);
if (file == NULL)
file = "<unknown file>";
isc_netaddr_fromsockaddr(&na, s2);
isc_buffer_init(&target, buf, sizeof(buf) - 1);
RUNTIME_CHECK(isc_netaddr_totext(&na, &target)
== ISC_R_SUCCESS);
buf[isc_buffer_usedlength(&target)] = '\0';
cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
"server '%s': already exists "
"previous definition: %s:%u",
buf, file, line);
result = ISC_R_FAILURE;
}
}
}
return (result);
}
static isc_result_t
check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
isc_log_t *logctx, isc_mem_t *mctx)
{
cfg_obj_t *servers = NULL;
cfg_obj_t *zones = NULL;
cfg_obj_t *keys = NULL;
cfg_listelt_t *element;
isc_symtab_t *symtab = NULL;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult = ISC_R_SUCCESS;
/*
* Check that all zone statements are syntactically correct and
* there are no duplicate zones.
*/
tresult = isc_symtab_create(mctx, 100, freekey, mctx,
ISC_FALSE, &symtab);
if (tresult != ISC_R_SUCCESS)
return (ISC_R_NOMEMORY);
if (vconfig != NULL)
(void)cfg_map_get(vconfig, "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;
cfg_obj_t *zone = cfg_listelt_value(element);
tresult = check_zoneconf(zone, config, symtab, vclass,
logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
isc_symtab_destroy(&symtab);
/*
* Check that all key statements are syntactically correct and
* there are no duplicate keys.
*/
tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
if (tresult != ISC_R_SUCCESS)
return (ISC_R_NOMEMORY);
(void)cfg_map_get(config, "key", &keys);
tresult = check_keylist(keys, symtab, logctx);
if (tresult == ISC_R_EXISTS)
result = ISC_R_FAILURE;
else if (tresult != ISC_R_SUCCESS) {
isc_symtab_destroy(&symtab);
return (tresult);
}
if (vconfig != NULL) {
keys = NULL;
(void)cfg_map_get(vconfig, "key", &keys);
tresult = check_keylist(keys, symtab, logctx);
if (tresult == ISC_R_EXISTS)
result = ISC_R_FAILURE;
else if (tresult != ISC_R_SUCCESS) {
isc_symtab_destroy(&symtab);
return (tresult);
}
}
isc_symtab_destroy(&symtab);
/*
* Check that forwarding is reasonable.
*/
if (vconfig == NULL) {
cfg_obj_t *options = NULL;
(void)cfg_map_get(config, "options", &options);
if (options != NULL)
if (check_forward(options, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
} else {
if (check_forward(vconfig, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
/*
* Check that dual-stack-servers is reasonable.
*/
if (vconfig == NULL) {
cfg_obj_t *options = NULL;
(void)cfg_map_get(config, "options", &options);
if (options != NULL)
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
} else {
if (check_dual_stack(vconfig, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
/*
* Check that rrset-order is reasonable.
*/
if (vconfig != NULL) {
if (check_order(vconfig, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
if (vconfig != NULL) {
(void)cfg_map_get(vconfig, "server", &servers);
if (servers != NULL &&
check_servers(servers, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
if (vconfig != NULL)
tresult = check_options(vconfig, logctx, mctx);
else
tresult = check_options(config, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
return (result);
}
static const char *
default_channels[] = {
"default_syslog",
"default_stderr",
"default_debug",
"null",
NULL
};
static isc_result_t
bind9_check_logging(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
cfg_obj_t *categories = NULL;
cfg_obj_t *category;
cfg_obj_t *channels = NULL;
cfg_obj_t *channel;
cfg_listelt_t *element;
cfg_listelt_t *delement;
const char *channelname;
const char *catname;
cfg_obj_t *fileobj = NULL;
cfg_obj_t *syslogobj = NULL;
cfg_obj_t *nullobj = NULL;
cfg_obj_t *stderrobj = NULL;
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_pointer = 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);
}
isc_result_t
bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
cfg_obj_t *options = NULL;
cfg_obj_t *servers = NULL;
cfg_obj_t *views = NULL;
cfg_obj_t *acls = NULL;
cfg_obj_t *kals = NULL;
cfg_obj_t *obj;
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) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
(void)cfg_map_get(config, "server", &servers);
if (servers != NULL &&
check_servers(servers, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
if (bind9_check_logging(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, dns_rdataclass_in,
logctx, mctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
} else {
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))
{
cfg_obj_t *view = cfg_listelt_value(velement);
cfg_obj_t *vname = cfg_tuple_get(view, "name");
cfg_obj_t *voptions = cfg_tuple_get(view, "options");
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_pointer = 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_pointer);
line = cfg_obj_line(symvalue.as_pointer);
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
"view '%s': already exists "
"previous definition: %s:%u",
key, file, line);
result = tresult;
} else if (result != 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,
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;
}
}
tresult = cfg_map_get(config, "acl", &acls);
if (tresult == ISC_R_SUCCESS) {
cfg_listelt_t *elt;
cfg_listelt_t *elt2;
const char *aclname;
for (elt = cfg_list_first(acls);
elt != NULL;
elt = cfg_list_next(elt)) {
cfg_obj_t *acl = cfg_listelt_value(elt);
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)) {
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 "
"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) {
cfg_listelt_t *elt;
cfg_listelt_t *elt2;
const char *aclname;
for (elt = cfg_list_first(kals);
elt != NULL;
elt = cfg_list_next(elt)) {
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)) {
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);
}