2001-03-01 23:46:49 +00:00
|
|
|
/*
|
2016-03-08 16:21:19 +11:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2001-03-01 23:46:49 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
2001-03-01 23:46:49 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
2001-03-01 23:46:49 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2007-03-29 06:36:31 +00:00
|
|
|
* information regarding copyright ownership.
|
2001-03-01 23:46:49 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2021-04-14 09:19:20 +02:00
|
|
|
#include <ctype.h>
|
2018-03-28 14:56:40 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2022-08-26 14:11:47 +00:00
|
|
|
#include <stdint.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <stdlib.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2021-09-13 15:39:36 +03:00
|
|
|
#include <openssl/opensslv.h>
|
|
|
|
|
2021-02-11 14:25:58 +01:00
|
|
|
#ifdef HAVE_DNSTAP
|
|
|
|
#include <fstrm.h>
|
|
|
|
#endif
|
|
|
|
|
2015-07-06 09:44:24 +10:00
|
|
|
#include <isc/aes.h>
|
2009-10-08 23:13:07 +00:00
|
|
|
#include <isc/base64.h>
|
2002-02-06 05:58:06 +00:00
|
|
|
#include <isc/buffer.h>
|
2021-06-10 08:14:57 +02:00
|
|
|
#include <isc/dir.h>
|
2013-12-20 14:57:03 -08:00
|
|
|
#include <isc/file.h>
|
2014-08-29 14:35:21 +10:00
|
|
|
#include <isc/hex.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isc/log.h>
|
2018-06-01 09:31:59 +02:00
|
|
|
#include <isc/md.h>
|
2002-02-12 13:17:23 +00:00
|
|
|
#include <isc/mem.h>
|
2002-03-04 05:07:06 +00:00
|
|
|
#include <isc/netaddr.h>
|
2004-01-14 02:06:51 +00:00
|
|
|
#include <isc/parseint.h>
|
2002-02-12 13:17:23 +00:00
|
|
|
#include <isc/region.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isc/result.h>
|
2019-07-21 14:26:49 -04:00
|
|
|
#include <isc/siphash.h>
|
2002-03-04 05:07:06 +00:00
|
|
|
#include <isc/sockaddr.h>
|
2007-09-13 04:45:18 +00:00
|
|
|
#include <isc/string.h>
|
2001-03-08 00:55:50 +00:00
|
|
|
#include <isc/symtab.h>
|
2001-03-03 23:09:23 +00:00
|
|
|
#include <isc/util.h>
|
2001-09-20 15:17:07 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
#include <dns/acl.h>
|
2016-08-18 11:16:06 +10:00
|
|
|
#include <dns/dnstap.h>
|
2002-02-06 05:58:06 +00:00
|
|
|
#include <dns/fixedname.h>
|
2020-02-06 17:43:54 +01:00
|
|
|
#include <dns/kasp.h>
|
2019-09-15 22:15:29 -07:00
|
|
|
#include <dns/keyvalues.h>
|
2021-12-01 14:52:31 +11:00
|
|
|
#include <dns/peer.h>
|
2019-02-07 15:10:41 -08:00
|
|
|
#include <dns/rbt.h>
|
2002-03-08 00:54:48 +00:00
|
|
|
#include <dns/rdataclass.h>
|
|
|
|
#include <dns/rdatatype.h>
|
2022-08-26 14:11:47 +00:00
|
|
|
#include <dns/rpz.h>
|
2016-08-08 23:52:40 +10:00
|
|
|
#include <dns/rrl.h>
|
2004-01-14 02:06:51 +00:00
|
|
|
#include <dns/secalg.h>
|
2018-02-07 13:34:02 +11:00
|
|
|
#include <dns/ssu.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2020-03-09 16:17:26 +01:00
|
|
|
#include <dst/dst.h>
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
#include <isccfg/aclconf.h>
|
2001-03-01 23:46:49 +00:00
|
|
|
#include <isccfg/cfg.h>
|
2022-12-16 10:39:15 +00:00
|
|
|
#include <isccfg/check.h>
|
2018-01-22 11:00:45 -08:00
|
|
|
#include <isccfg/grammar.h>
|
2020-02-06 17:43:54 +01:00
|
|
|
#include <isccfg/kaspconf.h>
|
2018-01-22 11:00:45 -08:00
|
|
|
#include <isccfg/namedconf.h>
|
2001-09-20 15:17:07 +00:00
|
|
|
|
2018-11-02 23:28:25 -07:00
|
|
|
#include <ns/hooks.h>
|
|
|
|
|
2023-09-20 12:53:35 +10:00
|
|
|
#define NAMED_CONTROL_PORT 953
|
|
|
|
|
2021-09-13 17:55:34 -07:00
|
|
|
static in_port_t dnsport = 53;
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static isc_result_t
|
|
|
|
fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable,
|
2014-09-29 12:10:10 +10:00
|
|
|
isc_log_t *logctxlogc);
|
|
|
|
|
2021-05-04 15:35:39 +02:00
|
|
|
static isc_result_t
|
|
|
|
keydirexist(const cfg_obj_t *zcgf, const char *dir, const char *kaspnamestr,
|
|
|
|
isc_symtab_t *symtab, isc_log_t *logctx, isc_mem_t *mctx);
|
2022-12-08 10:57:37 +00:00
|
|
|
|
|
|
|
static const cfg_obj_t *
|
|
|
|
find_maplist(const cfg_obj_t *config, const char *listname, const char *name);
|
|
|
|
|
2004-04-15 23:40:27 +00:00
|
|
|
static void
|
|
|
|
freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
|
|
|
|
UNUSED(type);
|
|
|
|
UNUSED(value);
|
|
|
|
isc_mem_free(userarg, key);
|
|
|
|
}
|
|
|
|
|
2002-03-08 00:54:48 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
|
2002-03-08 00:54:48 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
isc_textregion_t r;
|
|
|
|
dns_fixedname_t fixed;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2002-03-08 00:54:48 +00:00
|
|
|
dns_rdataclass_t rdclass;
|
|
|
|
dns_rdatatype_t rdtype;
|
|
|
|
isc_buffer_t b;
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
|
|
|
obj = cfg_tuple_get(ent, "class");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(obj));
|
2002-03-08 00:54:48 +00:00
|
|
|
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);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "type");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(obj));
|
2002-03-08 00:54:48 +00:00
|
|
|
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);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "name");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
str = cfg_obj_asstring(obj);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, str, strlen(str));
|
2002-03-08 00:54:48 +00:00
|
|
|
isc_buffer_add(&b, strlen(str));
|
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rootname, 0, NULL);
|
2002-03-08 00:54:48 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid name '%s'", str);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "order");
|
|
|
|
if (!cfg_obj_isstring(obj) ||
|
2022-11-02 19:33:14 +01:00
|
|
|
strcasecmp("order", cfg_obj_asstring(obj)) != 0)
|
|
|
|
{
|
2002-03-08 00:54:48 +00:00
|
|
|
cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: keyword 'order' missing");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(ent, "ordering");
|
|
|
|
if (!cfg_obj_isstring(obj)) {
|
|
|
|
cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: missing ordering");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-14 05:57:10 +00:00
|
|
|
} else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
|
|
|
|
#if !DNS_RDATASET_FIXED
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
2008-04-23 21:32:57 +00:00
|
|
|
"rrset-order: order 'fixed' was disabled at "
|
|
|
|
"compilation time");
|
2007-03-14 05:57:10 +00:00
|
|
|
#endif /* if !DNS_RDATASET_FIXED */
|
|
|
|
} else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
|
2017-04-22 08:25:10 +05:30
|
|
|
strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0 &&
|
|
|
|
strcasecmp(cfg_obj_asstring(obj), "none") != 0)
|
|
|
|
{
|
2002-03-08 00:54:48 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"rrset-order: invalid order '%s'",
|
|
|
|
cfg_obj_asstring(obj));
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_order(const cfg_obj_t *options, isc_log_t *logctx) {
|
2002-03-08 00:54:48 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2002-03-08 00:54:48 +00:00
|
|
|
|
|
|
|
if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
tresult = check_orderent(cfg_listelt_value(element), logctx);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) {
|
2002-03-08 00:54:48 +00:00
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-08 00:54:48 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2003-01-16 03:59:28 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *alternates = NULL;
|
|
|
|
const cfg_obj_t *value;
|
|
|
|
const cfg_obj_t *obj;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str;
|
2003-01-16 03:59:28 +00:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
|
|
|
|
(void)cfg_map_get(options, "dual-stack-servers", &alternates);
|
|
|
|
|
|
|
|
if (alternates == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
|
|
|
|
obj = cfg_tuple_get(alternates, "port");
|
|
|
|
if (cfg_obj_isuint32(obj)) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t val = cfg_obj_asuint32(obj);
|
|
|
|
if (val > UINT16_MAX) {
|
2003-01-16 03:59:28 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port '%u' out of range", val);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
obj = cfg_tuple_get(value, "name");
|
|
|
|
str = cfg_obj_asstring(obj);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&buffer, str, strlen(str));
|
2003-01-16 03:59:28 +00:00
|
|
|
isc_buffer_add(&buffer, strlen(str));
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2003-01-16 03:59:28 +00:00
|
|
|
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);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
obj = cfg_tuple_get(value, "port");
|
|
|
|
if (cfg_obj_isuint32(obj)) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t val = cfg_obj_asuint32(obj);
|
|
|
|
if (val > UINT16_MAX) {
|
2003-01-16 03:59:28 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port '%u' out of range", val);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
static isc_result_t
|
2022-12-08 10:57:37 +00:00
|
|
|
validate_tls(const cfg_obj_t *config, const cfg_obj_t *obj, isc_log_t *logctx,
|
|
|
|
const char *str) {
|
|
|
|
dns_fixedname_t fname;
|
|
|
|
dns_name_t *nm = dns_fixedname_initname(&fname);
|
2023-08-15 17:41:01 -07:00
|
|
|
isc_result_t result = dns_name_fromstring(nm, str, dns_rootname, 0,
|
|
|
|
NULL);
|
2022-12-08 10:57:37 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name", str);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcasecmp(str, "ephemeral") != 0) {
|
|
|
|
const cfg_obj_t *tlsmap = find_maplist(config, "tls", str);
|
|
|
|
|
|
|
|
if (tlsmap == NULL) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"tls '%s' is not defined", str);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
check_forward(const cfg_obj_t *config, const cfg_obj_t *options,
|
|
|
|
const cfg_obj_t *global, isc_log_t *logctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *forward = NULL;
|
|
|
|
const cfg_obj_t *forwarders = NULL;
|
2022-12-08 10:57:37 +00:00
|
|
|
const cfg_obj_t *faddresses = NULL;
|
|
|
|
const cfg_listelt_t *element;
|
2001-03-09 19:07:30 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(options, "forward", &forward);
|
|
|
|
(void)cfg_map_get(options, "forwarders", &forwarders);
|
|
|
|
|
2008-03-28 03:26:39 +00:00
|
|
|
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);
|
|
|
|
}
|
2001-03-09 19:07:30 +00:00
|
|
|
if (forward != NULL && forwarders == NULL) {
|
|
|
|
cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
|
|
|
|
"no matching 'forwarders' statement");
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2022-12-08 10:57:37 +00:00
|
|
|
if (forwarders != NULL) {
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
const cfg_obj_t *tlspobj = cfg_tuple_get(forwarders, "tls");
|
|
|
|
|
|
|
|
if (tlspobj != NULL && cfg_obj_isstring(tlspobj)) {
|
|
|
|
const char *tls = cfg_obj_asstring(tlspobj);
|
|
|
|
if (tls != NULL) {
|
|
|
|
result = validate_tls(config, tlspobj, logctx,
|
|
|
|
tls);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
faddresses = cfg_tuple_get(forwarders, "addresses");
|
|
|
|
for (element = cfg_list_first(faddresses); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
const cfg_obj_t *forwarder = cfg_listelt_value(element);
|
|
|
|
const char *tls = cfg_obj_getsockaddrtls(forwarder);
|
|
|
|
if (tls != NULL) {
|
|
|
|
result = validate_tls(config, faddresses,
|
|
|
|
logctx, tls);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2004-01-14 02:06:51 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
|
2004-01-14 02:06:51 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
2004-01-14 02:06:51 +00:00
|
|
|
const char *str;
|
|
|
|
isc_buffer_t b;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2004-01-14 02:06:51 +00:00
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2004-01-14 02:06:51 +00:00
|
|
|
obj = cfg_tuple_get(disabled, "name");
|
|
|
|
str = cfg_obj_asstring(obj);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, str, strlen(str));
|
2004-01-14 02:06:51 +00:00
|
|
|
isc_buffer_add(&b, strlen(str));
|
2009-09-01 00:22:28 +00:00
|
|
|
tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
|
2004-01-14 02:06:51 +00:00
|
|
|
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;
|
|
|
|
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element)));
|
2004-01-14 02:06:51 +00:00
|
|
|
r.length = strlen(r.base);
|
|
|
|
|
|
|
|
tresult = dns_secalg_fromtext(&alg, &r);
|
2012-10-03 12:38:43 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2004-01-14 02:06:51 +00:00
|
|
|
cfg_obj_log(cfg_listelt_value(element), logctx,
|
2005-08-23 02:36:11 +00:00
|
|
|
ISC_LOG_ERROR, "invalid algorithm '%s'",
|
|
|
|
r.base);
|
2004-01-14 02:06:51 +00:00
|
|
|
result = tresult;
|
2012-10-03 12:38:43 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
disabled_ds_digests(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;
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2012-10-03 12:38:43 +10:00
|
|
|
obj = cfg_tuple_get(disabled, "name");
|
|
|
|
str = cfg_obj_asstring(obj);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, str, strlen(str));
|
2012-10-03 12:38:43 +10:00
|
|
|
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, "digests");
|
|
|
|
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
isc_textregion_t r;
|
|
|
|
dns_dsdigest_t digest;
|
|
|
|
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element)));
|
2012-10-03 12:38:43 +10:00
|
|
|
r.length = strlen(r.base);
|
|
|
|
|
|
|
|
/* works with a numeric argument too */
|
|
|
|
tresult = dns_dsdigest_fromtext(&digest, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(cfg_listelt_value(element), logctx,
|
|
|
|
ISC_LOG_ERROR, "invalid digest type '%s'",
|
|
|
|
r.base);
|
|
|
|
result = tresult;
|
|
|
|
}
|
2004-01-14 02:06:51 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-06-04 02:31:43 +00:00
|
|
|
static isc_result_t
|
2023-09-20 12:53:35 +10:00
|
|
|
exists(const cfg_obj_t *obj, const char *name, int value, isc_symtab_t *symtab,
|
|
|
|
const char *fmt, isc_log_t *logctx, isc_mem_t *mctx) {
|
2004-06-04 02:31:43 +00:00
|
|
|
char *key;
|
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
|
|
|
key = isc_mem_strdup(mctx, name);
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = obj;
|
2004-06-04 02:31:43 +00:00
|
|
|
result = isc_symtab_define(symtab, key, value, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
|
|
|
|
&symvalue) == ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2004-06-04 02:31:43 +00:00
|
|
|
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-06-04 02:31:43 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
|
|
|
|
isc_mem_free(mctx, key);
|
|
|
|
result = ISC_R_EXISTS;
|
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, key);
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-04-15 23:40:27 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
|
2004-04-15 23:40:27 +00:00
|
|
|
isc_mem_t *mctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2004-04-15 23:40:27 +00:00
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
const char *str;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
isc_buffer_t b;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2004-04-15 23:40:27 +00:00
|
|
|
obj = cfg_tuple_get(secure, "name");
|
|
|
|
str = cfg_obj_asstring(obj);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, str, strlen(str));
|
2004-04-15 23:40:27 +00:00
|
|
|
isc_buffer_add(&b, strlen(str));
|
2009-09-01 00:22:28 +00:00
|
|
|
result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
|
2004-06-04 02:31:43 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2004-04-15 23:40:27 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'",
|
|
|
|
str);
|
|
|
|
} else {
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
2023-09-20 12:53:35 +10:00
|
|
|
result = exists(secure, namebuf, 1, symtab,
|
|
|
|
"dnssec-must-be-secure '%s': already exists "
|
|
|
|
"previous definition: %s:%u",
|
|
|
|
logctx, mctx);
|
2004-04-15 23:40:27 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
|
|
|
|
const cfg_obj_t *voptions, const cfg_obj_t *config, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx) {
|
2005-01-11 03:46:11 +00:00
|
|
|
isc_result_t result;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *aclobj = NULL;
|
|
|
|
const cfg_obj_t *options;
|
2005-01-11 03:46:11 +00:00
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
|
|
|
|
if (zconfig != NULL) {
|
|
|
|
options = cfg_tuple_get(zconfig, "options");
|
|
|
|
cfg_map_get(options, aclname, &aclobj);
|
|
|
|
}
|
|
|
|
if (voptions != NULL && aclobj == NULL) {
|
|
|
|
cfg_map_get(voptions, aclname, &aclobj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
if (config != NULL && aclobj == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL) {
|
|
|
|
cfg_map_get(options, aclname, &aclobj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
}
|
|
|
|
if (aclobj == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-09-12 01:09:08 +00:00
|
|
|
result = cfg_acl_fromconfig(aclobj, config, logctx, actx, mctx, 0,
|
|
|
|
&acl);
|
2005-01-11 03:46:11 +00:00
|
|
|
if (acl != NULL) {
|
|
|
|
dns_acl_detach(&acl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-11-04 16:52:49 +02:00
|
|
|
|
|
|
|
if (strcasecmp(aclname, "allow-transfer") == 0 &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_obj_istuple(aclobj))
|
|
|
|
{
|
2021-11-04 16:52:49 +02:00
|
|
|
const cfg_obj_t *obj_port = cfg_tuple_get(
|
|
|
|
cfg_tuple_get(aclobj, "port-transport"), "port");
|
|
|
|
const cfg_obj_t *obj_proto = cfg_tuple_get(
|
|
|
|
cfg_tuple_get(aclobj, "port-transport"), "transport");
|
|
|
|
|
|
|
|
if (cfg_obj_isuint32(obj_port) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_obj_asuint32(obj_port) >= UINT16_MAX)
|
|
|
|
{
|
2021-11-04 16:52:49 +02:00
|
|
|
cfg_obj_log(obj_port, logctx, ISC_LOG_ERROR,
|
|
|
|
"port value '%u' is out of range",
|
|
|
|
|
|
|
|
cfg_obj_asuint32(obj_port));
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg_obj_isstring(obj_proto)) {
|
|
|
|
const char *allowed[] = { "tcp", "tls" };
|
|
|
|
const char *transport = cfg_obj_asstring(obj_proto);
|
|
|
|
bool found = false;
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(allowed); i++) {
|
|
|
|
if (strcasecmp(transport, allowed[i]) == 0) {
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
cfg_obj_log(obj_proto, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid transport "
|
|
|
|
"protocol for "
|
|
|
|
"zone "
|
|
|
|
"transfers. Please specify either "
|
|
|
|
"'tcp' or 'tls'",
|
|
|
|
transport);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
|
|
|
const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
|
2005-01-11 03:46:11 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
|
|
|
int i = 0;
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
static const char *acls[] = {
|
2022-01-27 10:09:07 +01:00
|
|
|
"allow-query", "allow-query-on", "allow-query-cache",
|
|
|
|
"allow-query-cache-on", "blackhole", "match-clients",
|
|
|
|
"match-destinations", "sortlist", NULL
|
2018-08-12 23:06:00 -07:00
|
|
|
};
|
2005-01-11 03:46:11 +00:00
|
|
|
|
|
|
|
while (acls[i] != NULL) {
|
2005-09-12 02:04:41 +00:00
|
|
|
tresult = checkacl(acls[i++], actx, NULL, voptions, config,
|
2005-01-11 03:46:11 +00:00
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2008-03-28 23:47:02 +00:00
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2022-03-16 17:33:10 +00:00
|
|
|
static void
|
|
|
|
dns64_error(const cfg_obj_t *obj, isc_log_t *logctx, isc_netaddr_t *netaddr,
|
|
|
|
unsigned int prefixlen, const char *message) {
|
|
|
|
char buf[ISC_NETADDR_FORMATSIZE + 1];
|
|
|
|
isc_netaddr_format(netaddr, buf, sizeof(buf));
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "dns64 prefix %s/%u %s", buf,
|
|
|
|
prefixlen, message);
|
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2012-04-26 11:42:39 +10:00
|
|
|
static const char *acls[] = { "clients", "exclude", "mapped", NULL };
|
2010-12-08 02:46:17 +00:00
|
|
|
|
|
|
|
if (voptions != NULL) {
|
|
|
|
cfg_map_get(voptions, "dns64", &dns64);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
if (config != NULL && dns64 == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL) {
|
|
|
|
cfg_map_get(options, "dns64", &dns64);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
}
|
|
|
|
if (dns64 == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
|
|
|
|
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) {
|
2022-03-16 17:33:10 +00:00
|
|
|
dns64_error(map, logctx, &na, prefixlen,
|
|
|
|
"must be IPv6");
|
2010-12-08 02:46:17 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
continue;
|
|
|
|
}
|
2010-12-08 23:51:56 +00:00
|
|
|
|
2019-07-24 04:53:13 +10:00
|
|
|
if (na.type.in6.s6_addr[8] != 0) {
|
2022-03-16 17:33:10 +00:00
|
|
|
dns64_error(map, logctx, &na, prefixlen,
|
|
|
|
"bits [64..71] must be zero");
|
2019-07-24 04:53:13 +10:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-12-08 02:46:17 +00:00
|
|
|
if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 &&
|
|
|
|
prefixlen != 56 && prefixlen != 64 && prefixlen != 96)
|
|
|
|
{
|
2022-03-16 17:33:10 +00:00
|
|
|
dns64_error(map, logctx, &na, prefixlen,
|
|
|
|
"length is not 32/40/48/56/64/96");
|
2010-12-08 02:46:17 +00:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(map, "suffix", &obj);
|
|
|
|
if (obj != NULL) {
|
2022-03-16 17:33:10 +00:00
|
|
|
static const unsigned char zeros[16];
|
2010-12-08 02:46:17 +00:00
|
|
|
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;
|
2018-12-03 16:26:54 +11:00
|
|
|
if (prefixlen <= 64) {
|
2010-12-08 02:46:17 +00:00
|
|
|
nbytes++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-08-08 23:52:40 +10:00
|
|
|
#define CHECK_RRL(cond, pat, val1, val2) \
|
|
|
|
do { \
|
|
|
|
if (!(cond)) { \
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR, pat, val1, \
|
|
|
|
val2); \
|
|
|
|
if (result == ISC_R_SUCCESS) \
|
|
|
|
result = ISC_R_RANGE; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define CHECK_RRL_RATE(rate, def, max_rate, name) \
|
|
|
|
do { \
|
|
|
|
obj = NULL; \
|
|
|
|
mresult = cfg_map_get(map, name, &obj); \
|
|
|
|
if (mresult == ISC_R_SUCCESS) { \
|
|
|
|
rate = cfg_obj_asuint32(obj); \
|
|
|
|
CHECK_RRL(rate <= max_rate, name " %d > %d", rate, \
|
|
|
|
max_rate); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
check_ratelimit(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;
|
|
|
|
isc_result_t mresult;
|
|
|
|
const cfg_obj_t *map = NULL;
|
|
|
|
const cfg_obj_t *options;
|
|
|
|
const cfg_obj_t *obj;
|
|
|
|
int min_entries, i;
|
|
|
|
int all_per_second;
|
|
|
|
int errors_per_second;
|
|
|
|
int nodata_per_second;
|
|
|
|
int nxdomains_per_second;
|
|
|
|
int referrals_per_second;
|
|
|
|
int responses_per_second;
|
|
|
|
int slip;
|
|
|
|
|
|
|
|
if (voptions != NULL) {
|
|
|
|
cfg_map_get(voptions, "rate-limit", &map);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
if (config != NULL && map == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL) {
|
|
|
|
cfg_map_get(options, "rate-limit", &map);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
}
|
|
|
|
if (map == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
|
|
|
|
min_entries = 500;
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "min-table-size", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
min_entries = cfg_obj_asuint32(obj);
|
|
|
|
if (min_entries < 1) {
|
|
|
|
min_entries = 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "max-table-size", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
i = cfg_obj_asuint32(obj);
|
|
|
|
CHECK_RRL(i >= min_entries,
|
|
|
|
"max-table-size %d < min-table-size %d", i,
|
|
|
|
min_entries);
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE,
|
|
|
|
"responses-per-second");
|
|
|
|
|
|
|
|
CHECK_RRL_RATE(referrals_per_second, responses_per_second,
|
|
|
|
DNS_RRL_MAX_RATE, "referrals-per-second");
|
|
|
|
CHECK_RRL_RATE(nodata_per_second, responses_per_second,
|
|
|
|
DNS_RRL_MAX_RATE, "nodata-per-second");
|
|
|
|
CHECK_RRL_RATE(nxdomains_per_second, responses_per_second,
|
|
|
|
DNS_RRL_MAX_RATE, "nxdomains-per-second");
|
|
|
|
CHECK_RRL_RATE(errors_per_second, responses_per_second,
|
|
|
|
DNS_RRL_MAX_RATE, "errors-per-second");
|
|
|
|
|
|
|
|
CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second");
|
|
|
|
|
|
|
|
CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip");
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "window", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
i = cfg_obj_asuint32(obj);
|
|
|
|
CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW,
|
|
|
|
"window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "qps-scale", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
i = cfg_obj_asuint32(obj);
|
|
|
|
CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "ipv4-prefix-length", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
i = cfg_obj_asuint32(obj);
|
|
|
|
CHECK_RRL(i >= 8 && i <= 32,
|
|
|
|
"invalid 'ipv4-prefix-length %d'%s", i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
mresult = cfg_map_get(map, "ipv6-prefix-length", &obj);
|
|
|
|
if (mresult == ISC_R_SUCCESS) {
|
|
|
|
i = cfg_obj_asuint32(obj);
|
|
|
|
CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX,
|
|
|
|
"ipv6-prefix-length %d < 16 or > %d", i,
|
|
|
|
DNS_RRL_MAX_PREFIX);
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(map, "exempt-clients", &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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
/*
|
|
|
|
* Check allow-recursion and allow-recursion-on acls, and also log a
|
|
|
|
* warning if they're inconsistent with the "recursion" option.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
|
|
|
|
const char *viewname, const cfg_obj_t *config,
|
|
|
|
isc_log_t *logctx, isc_mem_t *mctx) {
|
|
|
|
const cfg_obj_t *options, *aclobj, *obj = NULL;
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool recursion;
|
2007-03-29 06:36:31 +00:00
|
|
|
const char *forview = " for view ";
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
static const char *acls[] = { "allow-recursion", "allow-recursion-on",
|
2008-03-28 23:47:02 +00:00
|
|
|
NULL };
|
|
|
|
|
2007-03-29 06:36:31 +00:00
|
|
|
if (voptions != NULL) {
|
|
|
|
cfg_map_get(voptions, "recursion", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
if (obj == NULL && config != NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL) {
|
|
|
|
cfg_map_get(options, "recursion", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
}
|
|
|
|
if (obj == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
recursion = true;
|
2007-03-29 06:36:31 +00:00
|
|
|
} else {
|
|
|
|
recursion = cfg_obj_asboolean(obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
if (config != NULL && aclobj == NULL) {
|
|
|
|
options = NULL;
|
|
|
|
cfg_map_get(config, "options", &options);
|
|
|
|
if (options != NULL) {
|
|
|
|
cfg_map_get(options, acls[i], &aclobj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
}
|
2008-03-28 23:47:02 +00:00
|
|
|
if (aclobj == NULL) {
|
2007-03-29 06:36:31 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
|
|
|
tresult = cfg_acl_fromconfig(aclobj, config, logctx, actx, mctx,
|
2007-09-12 01:09:08 +00:00
|
|
|
0, &acl);
|
2007-03-29 06:36:31 +00:00
|
|
|
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2008-03-28 23:47:02 +00:00
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
|
|
|
if (acl == NULL) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!recursion && !dns_acl_isnone(acl)) {
|
2007-03-29 06:36:31 +00:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-03-28 23:47:02 +00:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
unsigned int scale;
|
2001-11-09 03:34:55 +00:00
|
|
|
unsigned int max;
|
2001-06-04 21:51:27 +00:00
|
|
|
} intervaltable;
|
|
|
|
|
2018-02-24 17:55:24 -08:00
|
|
|
#ifdef HAVE_DNSTAP
|
2016-08-18 11:16:06 +10:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
unsigned int min;
|
|
|
|
unsigned int max;
|
|
|
|
} fstrmtable;
|
2018-02-20 12:48:29 +11:00
|
|
|
#endif /* ifdef HAVE_DNSTAP */
|
2016-08-18 11:16:06 +10:00
|
|
|
|
2011-11-07 00:14:11 +00:00
|
|
|
typedef enum {
|
|
|
|
optlevel_config,
|
|
|
|
optlevel_options,
|
|
|
|
optlevel_view,
|
|
|
|
optlevel_zone
|
|
|
|
} optlevel_t;
|
|
|
|
|
2015-01-20 13:29:18 -08:00
|
|
|
static isc_result_t
|
|
|
|
check_name(const char *str) {
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixed);
|
2023-08-15 17:41:01 -07:00
|
|
|
return (dns_name_fromstring(dns_fixedname_name(&fixed), str,
|
|
|
|
dns_rootname, 0, NULL));
|
2015-01-20 13:29:18 -08:00
|
|
|
}
|
|
|
|
|
2019-11-05 17:22:35 +01:00
|
|
|
static bool
|
|
|
|
kasp_name_allowed(const cfg_listelt_t *element) {
|
|
|
|
const char *name = cfg_obj_asstring(
|
|
|
|
cfg_tuple_get(cfg_listelt_value(element), "name"));
|
|
|
|
|
|
|
|
if (strcmp("none", name) == 0) {
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
if (strcmp("default", name) == 0) {
|
|
|
|
return (false);
|
|
|
|
}
|
2021-05-05 11:23:02 +10:00
|
|
|
if (strcmp("insecure", name) == 0) {
|
|
|
|
return (false);
|
|
|
|
}
|
2019-11-05 17:22:35 +01:00
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2021-02-03 13:13:41 -08:00
|
|
|
static const cfg_obj_t *
|
|
|
|
find_maplist(const cfg_obj_t *config, const char *listname, const char *name) {
|
|
|
|
isc_result_t result;
|
|
|
|
const cfg_obj_t *maplist = NULL;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
|
|
|
|
REQUIRE(config != NULL);
|
|
|
|
REQUIRE(name != NULL);
|
|
|
|
|
|
|
|
result = cfg_map_get(config, listname, &maplist);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(maplist); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2021-02-03 13:13:41 -08:00
|
|
|
const cfg_obj_t *map = cfg_listelt_value(elt);
|
|
|
|
if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) ==
|
2022-11-02 19:33:14 +01:00
|
|
|
0)
|
|
|
|
{
|
2021-02-03 13:13:41 -08:00
|
|
|
return (map);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
check_listener(const cfg_obj_t *listener, const cfg_obj_t *config,
|
|
|
|
cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx) {
|
|
|
|
isc_result_t tresult, result = ISC_R_SUCCESS;
|
|
|
|
const cfg_obj_t *ltup = NULL;
|
|
|
|
const cfg_obj_t *tlsobj = NULL, *httpobj = NULL;
|
2023-01-05 22:18:55 -08:00
|
|
|
const cfg_obj_t *portobj = NULL;
|
2021-02-03 13:13:41 -08:00
|
|
|
const cfg_obj_t *http_server = NULL;
|
|
|
|
bool do_tls = false, no_tls = false;
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
|
|
|
|
ltup = cfg_tuple_get(listener, "tuple");
|
|
|
|
RUNTIME_CHECK(ltup != NULL);
|
|
|
|
|
|
|
|
tlsobj = cfg_tuple_get(ltup, "tls");
|
|
|
|
if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) {
|
|
|
|
const char *tlsname = cfg_obj_asstring(tlsobj);
|
|
|
|
|
|
|
|
if (strcasecmp(tlsname, "none") == 0) {
|
|
|
|
no_tls = true;
|
|
|
|
} else if (strcasecmp(tlsname, "ephemeral") == 0) {
|
|
|
|
do_tls = true;
|
|
|
|
} else {
|
|
|
|
const cfg_obj_t *tlsmap = NULL;
|
|
|
|
|
|
|
|
do_tls = true;
|
|
|
|
|
|
|
|
tlsmap = find_maplist(config, "tls", tlsname);
|
|
|
|
if (tlsmap == NULL) {
|
|
|
|
cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"tls '%s' is not defined",
|
|
|
|
cfg_obj_asstring(tlsobj));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
httpobj = cfg_tuple_get(ltup, "http");
|
|
|
|
if (httpobj != NULL && cfg_obj_isstring(httpobj)) {
|
|
|
|
const char *httpname = cfg_obj_asstring(httpobj);
|
|
|
|
|
|
|
|
if (!do_tls && !no_tls) {
|
|
|
|
cfg_obj_log(httpobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"http must specify a 'tls' "
|
|
|
|
"statement, 'tls ephemeral', or "
|
|
|
|
"'tls none'");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
http_server = find_maplist(config, "http", httpname);
|
2021-02-12 18:17:09 -08:00
|
|
|
if (http_server == NULL && strcasecmp(httpname, "default") != 0)
|
|
|
|
{
|
2021-02-03 13:13:41 -08:00
|
|
|
cfg_obj_log(httpobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"http '%s' is not defined",
|
|
|
|
cfg_obj_asstring(httpobj));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
portobj = cfg_tuple_get(ltup, "port");
|
|
|
|
if (cfg_obj_isuint32(portobj) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_obj_asuint32(portobj) >= UINT16_MAX)
|
|
|
|
{
|
2021-02-03 13:13:41 -08:00
|
|
|
cfg_obj_log(portobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port value '%u' is out of range",
|
|
|
|
|
|
|
|
cfg_obj_asuint32(portobj));
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tresult = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), config,
|
|
|
|
logctx, actx, mctx, 0, &acl);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acl != NULL) {
|
|
|
|
dns_acl_detach(&acl);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
static isc_result_t
|
2021-02-03 13:13:41 -08:00
|
|
|
check_listeners(const cfg_obj_t *list, const cfg_obj_t *config,
|
|
|
|
cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx) {
|
|
|
|
isc_result_t tresult, result = ISC_R_SUCCESS;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(list); elt != NULL; elt = cfg_list_next(elt))
|
|
|
|
{
|
|
|
|
const cfg_obj_t *obj = cfg_listelt_value(elt);
|
|
|
|
tresult = check_listener(obj, config, actx, logctx, mctx);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2021-09-13 17:55:34 -07:00
|
|
|
static isc_result_t
|
|
|
|
check_port(const cfg_obj_t *options, isc_log_t *logctx, const char *type,
|
|
|
|
in_port_t *portp) {
|
|
|
|
const cfg_obj_t *portobj = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
result = cfg_map_get(options, type, &portobj);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
|
|
|
|
cfg_obj_log(portobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"port '%u' out of range",
|
|
|
|
cfg_obj_asuint32(portobj));
|
|
|
|
return (ISC_R_RANGE);
|
|
|
|
}
|
|
|
|
|
2023-04-06 16:32:16 +01:00
|
|
|
SET_IF_NOT_NULL(portp, (in_port_t)cfg_obj_asuint32(portobj));
|
2021-09-13 17:55:34 -07:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2021-02-03 13:13:41 -08:00
|
|
|
static isc_result_t
|
|
|
|
check_options(const cfg_obj_t *options, const cfg_obj_t *config,
|
2022-08-25 16:47:34 +10:00
|
|
|
bool check_algorithms, isc_log_t *logctx, isc_mem_t *mctx,
|
|
|
|
optlevel_t optlevel) {
|
2001-06-04 21:51:27 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2004-01-14 02:06:51 +00:00
|
|
|
isc_result_t tresult;
|
2001-06-04 21:51:27 +00:00
|
|
|
unsigned int i;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
const cfg_listelt_t *element;
|
2004-06-04 02:31:43 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2005-08-18 00:57:31 +00:00
|
|
|
const char *str;
|
|
|
|
isc_buffer_t b;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t lifetime = 3600;
|
2019-07-21 14:26:49 -04:00
|
|
|
const char *ccalg = "siphash24";
|
2021-02-03 13:13:41 -08:00
|
|
|
cfg_aclconfctx_t *actx = NULL;
|
2021-09-13 17:55:34 -07:00
|
|
|
static const char *sources[] = {
|
|
|
|
"query-source",
|
|
|
|
"query-source-v6",
|
|
|
|
};
|
2001-06-04 21:51:27 +00:00
|
|
|
|
2018-10-24 15:17:18 +02:00
|
|
|
/*
|
|
|
|
* { "name", scale, value }
|
|
|
|
* (scale * value) <= UINT32_MAX
|
|
|
|
*/
|
2001-06-04 21:51:27 +00:00
|
|
|
static intervaltable intervals[] = {
|
2018-10-24 15:17:18 +02:00
|
|
|
{ "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 */
|
|
|
|
|
|
|
|
/* minimum and maximum cache and negative cache TTLs */
|
|
|
|
{ "min-cache-ttl", 1, MAX_MIN_CACHE_TTL }, /* 90 secs */
|
|
|
|
{ "max-cache-ttl", 1, UINT32_MAX }, /* no limit */
|
|
|
|
{ "min-ncache-ttl", 1, MAX_MIN_NCACHE_TTL }, /* 90 secs */
|
|
|
|
{ "max-ncache-ttl", 1, MAX_MAX_NCACHE_TTL }, /* 7 days */
|
2001-06-04 21:51:27 +00:00
|
|
|
};
|
|
|
|
|
2011-01-07 04:31:39 +00:00
|
|
|
static const char *server_contact[] = { "empty-server", "empty-contact",
|
|
|
|
"dns64-server", "dns64-contact",
|
|
|
|
NULL };
|
|
|
|
|
2018-02-24 17:55:24 -08:00
|
|
|
#ifdef HAVE_DNSTAP
|
2016-08-18 11:16:06 +10:00
|
|
|
static fstrmtable fstrm[] = {
|
|
|
|
{ "fstrm-set-buffer-hint", FSTRM_IOTHR_BUFFER_HINT_MIN,
|
|
|
|
FSTRM_IOTHR_BUFFER_HINT_MAX },
|
|
|
|
{ "fstrm-set-flush-timeout", FSTRM_IOTHR_FLUSH_TIMEOUT_MIN,
|
|
|
|
FSTRM_IOTHR_FLUSH_TIMEOUT_MAX },
|
|
|
|
{ "fstrm-set-input-queue-size",
|
|
|
|
FSTRM_IOTHR_INPUT_QUEUE_SIZE_MIN,
|
|
|
|
FSTRM_IOTHR_INPUT_QUEUE_SIZE_MAX },
|
|
|
|
{ "fstrm-set-output-notify-threshold",
|
|
|
|
FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_MIN, 0 },
|
|
|
|
{ "fstrm-set-output-queue-size",
|
|
|
|
FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MIN,
|
|
|
|
FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MAX },
|
|
|
|
{ "fstrm-set-reopen-interval", FSTRM_IOTHR_REOPEN_INTERVAL_MIN,
|
|
|
|
FSTRM_IOTHR_REOPEN_INTERVAL_MAX }
|
|
|
|
};
|
|
|
|
#endif /* ifdef HAVE_DNSTAP */
|
|
|
|
|
2021-09-13 17:55:34 -07:00
|
|
|
if (optlevel == optlevel_options) {
|
|
|
|
/*
|
|
|
|
* Check port values, and record "port" for later use.
|
|
|
|
*/
|
|
|
|
tresult = check_port(options, logctx, "port", &dnsport);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
tresult = check_port(options, logctx, "tls-port", NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
tresult = check_port(options, logctx, "http-port", NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
tresult = check_port(options, logctx, "https-port", NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optlevel == optlevel_options || optlevel == optlevel_view) {
|
|
|
|
/*
|
|
|
|
* Warn if query-source or query-source-v6 options specify
|
|
|
|
* a port, and fail if they specify the DNS port.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(sources); i++) {
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, sources[i], &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
const isc_sockaddr_t *sa =
|
|
|
|
cfg_obj_assockaddr(obj);
|
|
|
|
in_port_t port = isc_sockaddr_getport(sa);
|
|
|
|
if (port == dnsport) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' cannot specify the "
|
|
|
|
"DNS listener port (%d)",
|
|
|
|
sources[i], port);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else if (port != 0) {
|
|
|
|
cfg_obj_log(obj, logctx,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"'%s': specifying a port "
|
|
|
|
"is not recommended",
|
|
|
|
sources[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
/*
|
|
|
|
* Check that fields specified in units of time other than seconds
|
|
|
|
* have reasonable values.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t val;
|
2001-12-29 04:49:51 +00:00
|
|
|
obj = NULL;
|
2001-06-04 21:51:27 +00:00
|
|
|
(void)cfg_map_get(options, intervals[i].name, &obj);
|
|
|
|
if (obj == NULL) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-09-02 15:46:28 +02:00
|
|
|
if (cfg_obj_isduration(obj)) {
|
|
|
|
val = cfg_obj_asduration(obj);
|
|
|
|
} else {
|
|
|
|
val = cfg_obj_asuint32(obj);
|
|
|
|
}
|
2001-11-09 03:34:55 +00:00
|
|
|
if (val > intervals[i].max) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%u' is out of range (0..%u)",
|
|
|
|
intervals[i].name, val, intervals[i].max);
|
|
|
|
result = ISC_R_RANGE;
|
2018-03-28 14:19:37 +02:00
|
|
|
} else if (val > (UINT32_MAX / intervals[i].scale)) {
|
2001-06-04 21:51:27 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%d' is out of range",
|
|
|
|
intervals[i].name, val);
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
}
|
2008-04-02 02:37:42 +00:00
|
|
|
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
/*
|
2019-11-05 17:22:35 +01:00
|
|
|
* Check dnssec-policy.
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "dnssec-policy", &obj);
|
|
|
|
if (obj != NULL) {
|
2019-11-05 17:22:35 +01:00
|
|
|
bool bad_kasp = false;
|
|
|
|
bool bad_name = false;
|
2020-02-06 12:13:20 -08:00
|
|
|
|
2019-11-05 17:22:35 +01:00
|
|
|
if (optlevel != optlevel_config && !cfg_obj_isstring(obj)) {
|
|
|
|
bad_kasp = true;
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
} else if (optlevel == optlevel_config) {
|
2020-02-06 17:43:54 +01:00
|
|
|
dns_kasplist_t list;
|
2020-02-06 12:13:20 -08:00
|
|
|
dns_kasp_t *kasp = NULL, *kasp_next = NULL;
|
2020-02-06 17:43:54 +01:00
|
|
|
|
|
|
|
ISC_LIST_INIT(list);
|
|
|
|
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
if (cfg_obj_islist(obj)) {
|
|
|
|
for (element = cfg_list_first(obj);
|
|
|
|
element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2020-02-06 12:13:20 -08:00
|
|
|
isc_result_t ret;
|
2020-02-06 17:43:54 +01:00
|
|
|
cfg_obj_t *kconfig =
|
|
|
|
cfg_listelt_value(element);
|
|
|
|
|
2020-02-06 12:13:20 -08:00
|
|
|
if (!cfg_obj_istuple(kconfig)) {
|
2019-11-05 17:22:35 +01:00
|
|
|
bad_kasp = true;
|
2020-02-06 17:43:54 +01:00
|
|
|
continue;
|
2019-11-05 17:22:35 +01:00
|
|
|
}
|
|
|
|
if (!kasp_name_allowed(element)) {
|
|
|
|
bad_name = true;
|
2020-02-06 17:43:54 +01:00
|
|
|
continue;
|
|
|
|
}
|
2020-02-06 12:13:20 -08:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
ret = cfg_kasp_fromconfig(
|
|
|
|
kconfig, NULL, check_algorithms,
|
|
|
|
mctx, logctx, &list, &kasp);
|
2020-02-06 12:13:20 -08:00
|
|
|
if (ret != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 17:43:54 +01:00
|
|
|
if (kasp != NULL) {
|
|
|
|
dns_kasp_detach(&kasp);
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-06 17:43:54 +01:00
|
|
|
|
2020-02-06 12:13:20 -08:00
|
|
|
for (kasp = ISC_LIST_HEAD(list); kasp != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
kasp = kasp_next)
|
|
|
|
{
|
2020-02-06 17:43:54 +01:00
|
|
|
kasp_next = ISC_LIST_NEXT(kasp, link);
|
|
|
|
ISC_LIST_UNLINK(list, kasp, link);
|
|
|
|
dns_kasp_detach(&kasp);
|
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bad_kasp) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2019-11-05 17:22:35 +01:00
|
|
|
"dnssec-policy may only be configured at "
|
|
|
|
"the top level, please use name reference "
|
|
|
|
"at the zone level");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2021-04-13 16:45:16 +02:00
|
|
|
} else if (bad_name) {
|
2019-11-05 17:22:35 +01:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2021-05-05 11:23:02 +10:00
|
|
|
"dnssec-policy name may not be 'insecure', "
|
|
|
|
"'none', or 'default' (which are built-in "
|
|
|
|
"policies)");
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-14 15:44:20 +10:00
|
|
|
obj = NULL;
|
|
|
|
cfg_map_get(options, "max-rsa-exponent-size", &obj);
|
|
|
|
if (obj != NULL) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t val;
|
2012-06-14 15:44:20 +10:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-02 02:37:42 +00:00
|
|
|
obj = NULL;
|
2002-04-26 00:40:37 +00:00
|
|
|
(void)cfg_map_get(options, "preferred-glue", &obj);
|
|
|
|
if (obj != NULL) {
|
2008-03-28 23:47:02 +00:00
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
if (strcasecmp(str, "a") != 0 && strcasecmp(str, "aaaa") != 0 &&
|
2002-04-26 00:40:37 +00:00
|
|
|
strcasecmp(str, "none") != 0)
|
|
|
|
{
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"preferred-glue unexpected value '%s'",
|
|
|
|
str);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-04-26 00:40:37 +00:00
|
|
|
}
|
2008-04-02 02:37:42 +00:00
|
|
|
|
2004-01-14 02:06:51 +00:00
|
|
|
/*
|
|
|
|
* Set supported DNSSEC algorithms.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "disable-algorithms", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
tresult = disabled_algorithms(obj, logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-01-14 02:06:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 12:38:43 +10:00
|
|
|
/*
|
2019-08-07 11:53:13 -07:00
|
|
|
* Set supported DS digest types.
|
2012-10-03 12:38:43 +10:00
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "disable-ds-digests", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
tresult = disabled_ds_digests(obj, logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-10-03 12:38:43 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-15 23:40:27 +00:00
|
|
|
/*
|
|
|
|
* Check dnssec-must-be-secure.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
tresult = isc_symtab_create(mctx, 100, freekey, mctx, false,
|
2018-04-17 08:29:14 -07:00
|
|
|
&symtab);
|
2004-04-15 23:40:27 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2021-09-22 15:21:45 +10:00
|
|
|
} else {
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
2017-09-06 09:58:29 +10:00
|
|
|
{
|
2021-09-22 15:21:45 +10:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
tresult = mustbesecure(obj, symtab, logctx,
|
|
|
|
mctx);
|
|
|
|
if (result == ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
tresult != ISC_R_SUCCESS)
|
|
|
|
{
|
2021-09-22 15:21:45 +10:00
|
|
|
result = tresult;
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-04-15 23:40:27 +00:00
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
if (symtab != NULL) {
|
2004-04-15 23:40:27 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
2004-04-15 23:40:27 +00:00
|
|
|
}
|
|
|
|
|
2005-08-18 00:57:31 +00:00
|
|
|
/*
|
2011-01-07 04:31:39 +00:00
|
|
|
* Check server/contacts for syntactic validity.
|
2005-08-18 00:57:31 +00:00
|
|
|
*/
|
2011-01-07 04:31:39 +00:00
|
|
|
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);
|
2015-01-20 13:29:18 -08:00
|
|
|
if (check_name(str) != ISC_R_SUCCESS) {
|
2011-01-07 04:31:39 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s: invalid name '%s'",
|
|
|
|
server_contact[i], str);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-01-07 04:31:39 +00:00
|
|
|
}
|
2005-08-18 00:57:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-07 04:31:39 +00:00
|
|
|
/*
|
|
|
|
* Check empty zone configuration.
|
|
|
|
*/
|
2005-08-18 00:57:31 +00:00
|
|
|
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);
|
2015-01-20 13:29:18 -08:00
|
|
|
if (check_name(str) != ISC_R_SUCCESS) {
|
2005-08-18 00:57:31 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"disable-empty-zone: invalid name '%s'",
|
|
|
|
str);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-08-18 00:57:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-16 20:57:55 +00:00
|
|
|
/*
|
|
|
|
* 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) &&
|
2008-11-19 05:38:49 +00:00
|
|
|
strlen(cfg_obj_asstring(obj)) > 1024U)
|
|
|
|
{
|
2008-11-16 20:57:55 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'server-id' too big (>1024 bytes)");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-11-16 20:57:55 +00:00
|
|
|
}
|
|
|
|
|
2014-06-18 16:47:22 -07:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "nta-lifetime", &obj);
|
|
|
|
if (obj != NULL) {
|
2019-09-02 15:46:28 +02:00
|
|
|
lifetime = cfg_obj_asduration(obj);
|
2014-10-20 13:40:17 -07:00
|
|
|
if (lifetime > 604800) { /* 7 days */
|
2014-06-18 16:47:22 -07:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2014-10-20 13:40:17 -07:00
|
|
|
"'nta-lifetime' cannot exceed one week");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-18 16:47:22 -07:00
|
|
|
} else if (lifetime == 0) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'nta-lifetime' may not be zero");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-18 16:47:22 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "nta-recheck", &obj);
|
|
|
|
if (obj != NULL) {
|
2019-09-02 15:46:28 +02:00
|
|
|
uint32_t recheck = cfg_obj_asduration(obj);
|
2014-10-20 13:40:17 -07:00
|
|
|
if (recheck > 604800) { /* 7 days */
|
2014-06-18 16:47:22 -07:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2014-10-20 13:40:17 -07:00
|
|
|
"'nta-recheck' cannot exceed one week");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-18 16:47:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (recheck > lifetime) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"'nta-recheck' (%d seconds) is "
|
|
|
|
"greater than 'nta-lifetime' "
|
|
|
|
"(%d seconds)",
|
|
|
|
recheck, lifetime);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-06-18 16:47:22 -07:00
|
|
|
}
|
|
|
|
|
2014-08-29 14:35:21 +10:00
|
|
|
obj = NULL;
|
2015-07-08 12:20:46 +10:00
|
|
|
(void)cfg_map_get(options, "cookie-algorithm", &obj);
|
2018-06-12 11:26:04 +02:00
|
|
|
if (obj != NULL) {
|
2015-07-06 09:44:24 +10:00
|
|
|
ccalg = cfg_obj_asstring(obj);
|
2015-07-08 12:20:46 +10:00
|
|
|
}
|
2015-07-06 09:44:24 +10:00
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "cookie-secret", &obj);
|
2014-08-29 14:35:21 +10:00
|
|
|
if (obj != NULL) {
|
|
|
|
unsigned char secret[32];
|
|
|
|
|
2017-09-05 09:19:45 +10:00
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
unsigned int usedlength;
|
2015-07-05 23:45:22 +00:00
|
|
|
|
2017-09-05 09:19:45 +10:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(obj);
|
|
|
|
|
|
|
|
memset(secret, 0, sizeof(secret));
|
|
|
|
isc_buffer_init(&b, secret, sizeof(secret));
|
|
|
|
tresult = isc_hex_decodestring(str, &b);
|
|
|
|
if (tresult == ISC_R_NOSPACE) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"cookie-secret: too long");
|
|
|
|
} else if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"cookie-secret: invalid hex "
|
|
|
|
"string");
|
|
|
|
}
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-05 09:19:45 +10:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
usedlength = isc_buffer_usedlength(&b);
|
|
|
|
if (strcasecmp(ccalg, "aes") == 0 &&
|
2022-11-02 19:33:14 +01:00
|
|
|
usedlength != ISC_AES128_KEYLENGTH)
|
|
|
|
{
|
2017-09-05 09:19:45 +10:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2019-07-21 14:26:49 -04:00
|
|
|
"AES cookie-secret must be 128 "
|
|
|
|
"bits");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-07-21 14:26:49 -04:00
|
|
|
}
|
|
|
|
if (strcasecmp(ccalg, "siphash24") == 0 &&
|
|
|
|
usedlength != ISC_SIPHASH24_KEY_LENGTH)
|
|
|
|
{
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"SipHash-2-4 cookie-secret must be "
|
|
|
|
"128 bits");
|
2017-09-05 09:19:45 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-05 09:19:45 +10:00
|
|
|
}
|
2014-08-29 14:35:21 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-24 17:55:24 -08:00
|
|
|
#ifdef HAVE_DNSTAP
|
2016-08-18 11:16:06 +10:00
|
|
|
for (i = 0; i < sizeof(fstrm) / sizeof(fstrm[0]); i++) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t value;
|
2016-08-18 11:16:06 +10:00
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, fstrm[i].name, &obj);
|
|
|
|
if (obj == NULL) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-18 11:16:06 +10:00
|
|
|
|
2019-09-02 15:46:28 +02:00
|
|
|
if (cfg_obj_isduration(obj)) {
|
|
|
|
value = cfg_obj_asduration(obj);
|
|
|
|
} else {
|
|
|
|
value = cfg_obj_asuint32(obj);
|
|
|
|
}
|
2016-08-18 11:16:06 +10:00
|
|
|
if (value < fstrm[i].min ||
|
2022-11-02 19:33:14 +01:00
|
|
|
(fstrm[i].max != 0U && value > fstrm[i].max))
|
|
|
|
{
|
2016-08-18 11:16:06 +10:00
|
|
|
if (fstrm[i].max != 0U) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%u' out of range (%u..%u)",
|
|
|
|
fstrm[i].name, value, fstrm[i].min,
|
|
|
|
fstrm[i].max);
|
|
|
|
} else {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s out of range (%u < %u)",
|
|
|
|
fstrm[i].name, value, fstrm[i].min);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-18 11:16:06 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(fstrm[i].name, "fstrm-set-input-queue-size") == 0) {
|
|
|
|
int bits = 0;
|
|
|
|
do {
|
|
|
|
bits += value & 0x1;
|
|
|
|
value >>= 1;
|
|
|
|
} while (value != 0U);
|
|
|
|
if (bits != 1) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"%s '%u' not a power-of-2",
|
|
|
|
fstrm[i].name,
|
|
|
|
cfg_obj_asuint32(obj));
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-08-18 11:16:06 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-06 16:03:37 -08:00
|
|
|
|
|
|
|
/* Check that dnstap-ouput values are consistent */
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "dnstap-output", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
const cfg_obj_t *obj2;
|
|
|
|
dns_dtmode_t dmode;
|
|
|
|
|
|
|
|
obj2 = cfg_tuple_get(obj, "mode");
|
|
|
|
if (obj2 == NULL) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnstap-output mode not found");
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
} else {
|
|
|
|
if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) {
|
|
|
|
dmode = dns_dtmode_file;
|
|
|
|
} else {
|
|
|
|
dmode = dns_dtmode_unix;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-02-06 16:03:37 -08:00
|
|
|
|
2017-09-06 09:58:29 +10:00
|
|
|
obj2 = cfg_tuple_get(obj, "size");
|
|
|
|
if (obj2 != NULL && !cfg_obj_isvoid(obj2) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
dmode == dns_dtmode_unix)
|
|
|
|
{
|
2017-09-06 09:58:29 +10:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnstap-output size "
|
|
|
|
"cannot be set with mode unix");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
}
|
2017-02-06 16:03:37 -08:00
|
|
|
|
2017-09-06 09:58:29 +10:00
|
|
|
obj2 = cfg_tuple_get(obj, "versions");
|
|
|
|
if (obj2 != NULL && !cfg_obj_isvoid(obj2) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
dmode == dns_dtmode_unix)
|
|
|
|
{
|
2017-09-06 09:58:29 +10:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnstap-output versions "
|
|
|
|
"cannot be set with mode unix");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
}
|
2017-03-08 23:20:40 -08:00
|
|
|
|
2017-09-06 09:58:29 +10:00
|
|
|
obj2 = cfg_tuple_get(obj, "suffix");
|
|
|
|
if (obj2 != NULL && !cfg_obj_isvoid(obj2) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
dmode == dns_dtmode_unix)
|
|
|
|
{
|
2017-09-06 09:58:29 +10:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnstap-output suffix "
|
|
|
|
"cannot be set with mode unix");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
}
|
2017-03-08 23:20:40 -08:00
|
|
|
}
|
2017-02-06 16:03:37 -08:00
|
|
|
}
|
2016-08-18 11:16:06 +10:00
|
|
|
#endif /* ifdef HAVE_DNSTAP */
|
|
|
|
|
2017-04-26 23:43:35 +05:30
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "lmdb-mapsize", &obj);
|
|
|
|
if (obj != NULL) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint64_t mapsize = cfg_obj_asuint64(obj);
|
2017-04-26 23:43:35 +05:30
|
|
|
|
|
|
|
if (mapsize < (1ULL << 20)) { /* 1 megabyte */
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'lmdb-mapsize "
|
2018-03-28 14:56:40 +02:00
|
|
|
"%" PRId64 "' "
|
2017-04-26 23:43:35 +05:30
|
|
|
"is too small",
|
|
|
|
mapsize);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-04-26 23:43:35 +05:30
|
|
|
} else if (mapsize > (1ULL << 40)) { /* 1 terabyte */
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'lmdb-mapsize "
|
2018-03-28 14:56:40 +02:00
|
|
|
"%" PRId64 "' "
|
2017-04-26 23:43:35 +05:30
|
|
|
"is too large",
|
|
|
|
mapsize);
|
2017-09-06 09:58:29 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-04-26 23:43:35 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-06 09:58:29 +10:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "resolver-nonbackoff-tries", &obj);
|
|
|
|
if (obj != NULL && cfg_obj_asuint32(obj) == 0U) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'resolver-nonbackoff-tries' must be >= 1");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-06 09:58:29 +10:00
|
|
|
}
|
|
|
|
|
2020-02-21 10:53:08 -08:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "max-ixfr-ratio", &obj);
|
|
|
|
if (obj != NULL && cfg_obj_ispercentage(obj)) {
|
|
|
|
uint32_t percent = cfg_obj_aspercentage(obj);
|
|
|
|
if (percent == 0) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'ixfr-max-ratio' must be a nonzero "
|
|
|
|
"percentage or 'unlimited')");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
} else if (percent > 100) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"'ixfr-max-ratio %d%%' exceeds 100%%",
|
|
|
|
percent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-16 17:48:42 -07:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "check-names", &obj);
|
|
|
|
if (obj != NULL && !cfg_obj_islist(obj)) {
|
|
|
|
obj = NULL;
|
|
|
|
}
|
|
|
|
if (obj != NULL) {
|
2020-07-09 14:49:47 +10:00
|
|
|
/* Note: SEC is defined in <sys/time.h> on some platforms. */
|
|
|
|
enum { MAS = 1, PRI = 2, SLA = 4, SCN = 8 } values = 0;
|
2020-06-16 17:48:42 -07:00
|
|
|
for (const cfg_listelt_t *el = cfg_list_first(obj); el != NULL;
|
|
|
|
el = cfg_list_next(el))
|
|
|
|
{
|
|
|
|
const cfg_obj_t *tuple = cfg_listelt_value(el);
|
|
|
|
const cfg_obj_t *type = cfg_tuple_get(tuple, "type");
|
|
|
|
const char *keyword = cfg_obj_asstring(type);
|
|
|
|
if (strcasecmp(keyword, "primary") == 0) {
|
|
|
|
if ((values & PRI) == PRI) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names primary' "
|
|
|
|
"duplicated");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
values |= PRI;
|
|
|
|
} else if (strcasecmp(keyword, "master") == 0) {
|
|
|
|
if ((values & MAS) == MAS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names master' "
|
|
|
|
"duplicated");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
values |= MAS;
|
|
|
|
} else if (strcasecmp(keyword, "secondary") == 0) {
|
2020-07-09 14:49:47 +10:00
|
|
|
if ((values & SCN) == SCN) {
|
2020-06-16 17:48:42 -07:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names secondary' "
|
|
|
|
"duplicated");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2020-07-09 14:49:47 +10:00
|
|
|
values |= SCN;
|
2020-06-16 17:48:42 -07:00
|
|
|
} else if (strcasecmp(keyword, "slave") == 0) {
|
|
|
|
if ((values & SLA) == SLA) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names slave' "
|
|
|
|
"duplicated");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
values |= SLA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((values & (PRI | MAS)) == (PRI | MAS)) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names' cannot take both "
|
|
|
|
"'primary' and 'master'");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-09 14:49:47 +10:00
|
|
|
if ((values & (SCN | SLA)) == (SCN | SLA)) {
|
2020-06-16 17:48:42 -07:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'check-names' cannot take both "
|
|
|
|
"'secondary' and 'slave'");
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-05 13:07:47 -03:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "stale-refresh-time", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
uint32_t refresh_time = cfg_obj_asduration(obj);
|
|
|
|
if (refresh_time > 0 && refresh_time < 30) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"'stale-refresh-time' should either be 0 "
|
|
|
|
"or otherwise 30 seconds or higher");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-03 13:13:41 -08:00
|
|
|
cfg_aclconfctx_create(mctx, &actx);
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "listen-on", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
INSIST(config != NULL);
|
|
|
|
tresult = check_listeners(obj, config, actx, logctx, mctx);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(options, "listen-on-v6", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
INSIST(config != NULL);
|
|
|
|
tresult = check_listeners(obj, config, actx, logctx, mctx);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actx != NULL) {
|
|
|
|
cfg_aclconfctx_detach(&actx);
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-06-25 21:59:56 -07:00
|
|
|
/*
|
2021-05-07 14:27:25 +02:00
|
|
|
* Check "remote-servers" style list.
|
2020-06-25 21:59:56 -07:00
|
|
|
*/
|
2003-02-26 06:04:03 +00:00
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_remoteserverlist(const cfg_obj_t *cctx, const char *list,
|
|
|
|
isc_log_t *logctx, isc_symtab_t *symtab,
|
|
|
|
isc_mem_t *mctx) {
|
2020-06-25 21:59:56 -07:00
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
isc_result_t result, tresult;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *elt;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
2020-06-25 21:59:56 -07:00
|
|
|
result = cfg_map_get(cctx, list, &obj);
|
2020-06-17 02:02:27 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-06-25 21:59:56 -07:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
elt = cfg_list_first(obj);
|
|
|
|
while (elt != NULL) {
|
|
|
|
char *tmp;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
obj = cfg_listelt_value(elt);
|
|
|
|
name = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
|
|
|
|
|
|
|
|
tmp = isc_mem_strdup(mctx, name);
|
|
|
|
symvalue.as_cpointer = obj;
|
|
|
|
tresult = isc_symtab_define(symtab, tmp, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
|
|
|
const char *file = NULL;
|
|
|
|
unsigned int line;
|
|
|
|
|
|
|
|
RUNTIME_CHECK(
|
|
|
|
isc_symtab_lookup(symtab, tmp, 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(obj, logctx, ISC_LOG_ERROR,
|
2021-05-07 14:27:25 +02:00
|
|
|
"%s list '%s' is duplicated: "
|
2020-06-25 21:59:56 -07:00
|
|
|
"also defined at %s:%u",
|
2021-05-07 14:27:25 +02:00
|
|
|
list, name, file, line);
|
2020-06-25 21:59:56 -07:00
|
|
|
isc_mem_free(mctx, tmp);
|
|
|
|
result = tresult;
|
|
|
|
break;
|
|
|
|
} else if (tresult != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, tmp);
|
|
|
|
result = tresult;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
elt = cfg_list_next(elt);
|
2020-06-17 02:02:27 -07:00
|
|
|
}
|
2020-06-25 21:59:56 -07:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check primaries lists for duplicates.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_primarylists(const cfg_obj_t *cctx, isc_log_t *logctx, isc_mem_t *mctx) {
|
2020-06-25 21:59:56 -07:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
|
2003-02-26 06:04:03 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_remoteserverlist(cctx, "primaries", logctx, symtab,
|
|
|
|
mctx);
|
2020-06-25 21:59:56 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_remoteserverlist(cctx, "masters", logctx, symtab, mctx);
|
2021-05-07 14:27:25 +02:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check parental-agents lists for duplicates.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_parentalagentlists(const cfg_obj_t *cctx, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx) {
|
2021-05-07 14:27:25 +02:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_remoteserverlist(cctx, "parental-agents", logctx,
|
|
|
|
symtab, mctx);
|
2020-06-25 21:59:56 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (result);
|
|
|
|
}
|
2020-06-17 02:02:27 -07:00
|
|
|
|
2021-05-19 18:03:11 +03:00
|
|
|
#if HAVE_LIBNGHTTP2
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_httpserver(const cfg_obj_t *http, isc_log_t *logctx,
|
|
|
|
isc_symtab_t *symtab) {
|
2021-05-19 18:03:11 +03:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
const char *name = cfg_obj_asstring(cfg_map_getname(http));
|
|
|
|
const cfg_obj_t *eps = NULL;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
2021-09-30 12:40:03 +03:00
|
|
|
if (strcasecmp(name, "default") == 0) {
|
|
|
|
cfg_obj_log(http, logctx, ISC_LOG_ERROR,
|
|
|
|
"'http' name cannot be '%s' (which is a "
|
|
|
|
"built-in configuration)",
|
|
|
|
name);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else {
|
|
|
|
/* Check for duplicates */
|
|
|
|
symvalue.as_cpointer = http;
|
|
|
|
result = isc_symtab_define(symtab, name, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
const char *file = NULL;
|
|
|
|
unsigned int line;
|
2021-05-19 18:03:11 +03:00
|
|
|
|
2021-09-30 12:40:03 +03:00
|
|
|
tresult = isc_symtab_lookup(symtab, name, 1, &symvalue);
|
|
|
|
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
|
2021-05-19 18:03:11 +03:00
|
|
|
|
2021-09-30 12:40:03 +03:00
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
|
|
|
}
|
2021-05-19 18:03:11 +03:00
|
|
|
|
2021-09-30 12:40:03 +03:00
|
|
|
cfg_obj_log(http, logctx, ISC_LOG_ERROR,
|
|
|
|
"http '%s' is duplicated: "
|
|
|
|
"also defined at %s:%u",
|
|
|
|
name, file, line);
|
|
|
|
}
|
2021-05-19 18:03:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check endpoints are valid */
|
|
|
|
tresult = cfg_map_get(http, "endpoints", &eps);
|
Add (http-)listener-clients option (DoH quota mechanism)
This commit adds support for http-listener-clients global options as
well as ability to override the default in an HTTP server description,
like:
http local-http-server {
...
listener-clients 100;
...
};
This way we have ability to specify per-listener active connections
quota globally and then override it when required. This is exactly
what AT&T requested us: they wanted a functionality to specify quota
globally and then override it for specific IPs. This change
functionality makes such a configuration possible.
It makes sense: for example, one could have different quotas for
internal and external clients. Or, for example, one could use BIND's
internal ability to serve encrypted DoH with some sane quota value for
internal clients, while having un-encrypted DoH listener without quota
to put BIND behind a load balancer doing TLS offloading for external
clients.
Moreover, the code no more shares the quota with TCP, which makes
little sense anyway (see tcp-clients option), because of the nature of
interaction of DoH clients: they tend to keep idle opened connections
for longer periods of time, preventing the TCP and TLS client from
being served. Thus, the need to have a separate, generally larger,
quota for them.
Also, the change makes any option within "http <name> { ... };"
statement optional, making it easier to override only required default
options.
By default, the DoH connections are limited to 300 per listener. I
hope that it is a good initial guesstimate.
2021-05-14 14:18:57 +03:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
|
|
|
for (elt = cfg_list_first(eps); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
Add (http-)listener-clients option (DoH quota mechanism)
This commit adds support for http-listener-clients global options as
well as ability to override the default in an HTTP server description,
like:
http local-http-server {
...
listener-clients 100;
...
};
This way we have ability to specify per-listener active connections
quota globally and then override it when required. This is exactly
what AT&T requested us: they wanted a functionality to specify quota
globally and then override it for specific IPs. This change
functionality makes such a configuration possible.
It makes sense: for example, one could have different quotas for
internal and external clients. Or, for example, one could use BIND's
internal ability to serve encrypted DoH with some sane quota value for
internal clients, while having un-encrypted DoH listener without quota
to put BIND behind a load balancer doing TLS offloading for external
clients.
Moreover, the code no more shares the quota with TCP, which makes
little sense anyway (see tcp-clients option), because of the nature of
interaction of DoH clients: they tend to keep idle opened connections
for longer periods of time, preventing the TCP and TLS client from
being served. Thus, the need to have a separate, generally larger,
quota for them.
Also, the change makes any option within "http <name> { ... };"
statement optional, making it easier to override only required default
options.
By default, the DoH connections are limited to 300 per listener. I
hope that it is a good initial guesstimate.
2021-05-14 14:18:57 +03:00
|
|
|
const cfg_obj_t *ep = cfg_listelt_value(elt);
|
|
|
|
const char *path = cfg_obj_asstring(ep);
|
|
|
|
if (!isc_nm_http_path_isvalid(path)) {
|
|
|
|
cfg_obj_log(eps, logctx, ISC_LOG_ERROR,
|
|
|
|
"endpoint '%s' is not a "
|
|
|
|
"valid absolute HTTP path",
|
|
|
|
path);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2021-05-19 18:03:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_httpservers(const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
|
2021-05-19 18:03:11 +03:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = cfg_map_get(config, "http", &obj);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(obj); elt != NULL; elt = cfg_list_next(elt)) {
|
|
|
|
obj = cfg_listelt_value(elt);
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_httpserver(obj, logctx, symtab);
|
2021-05-19 18:03:11 +03:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LIBNGHTTP2 */
|
|
|
|
|
2021-09-13 15:39:36 +03:00
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_tls_defintion(const cfg_obj_t *tlsobj, const char *name,
|
|
|
|
isc_log_t *logctx, isc_symtab_t *symtab) {
|
2021-09-13 15:39:36 +03:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
const cfg_obj_t *tls_proto_list = NULL, *tls_key = NULL,
|
2021-09-20 14:25:59 +03:00
|
|
|
*tls_cert = NULL, *tls_ciphers = NULL;
|
2021-09-13 15:39:36 +03:00
|
|
|
uint32_t tls_protos = 0;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
|
|
|
if (strcasecmp(name, "ephemeral") == 0 || strcasecmp(name, "none") == 0)
|
|
|
|
{
|
|
|
|
cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"tls clause name '%s' is reserved for internal use",
|
|
|
|
name);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else {
|
|
|
|
/* Check for duplicates */
|
|
|
|
symvalue.as_cpointer = tlsobj;
|
|
|
|
result = isc_symtab_define(symtab, name, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
const char *file = NULL;
|
|
|
|
unsigned int line;
|
|
|
|
|
|
|
|
tresult = isc_symtab_lookup(symtab, name, 1, &symvalue);
|
|
|
|
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"tls clause '%s' is duplicated: "
|
|
|
|
"also defined at %s:%u",
|
|
|
|
name, file, line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:43:40 +03:00
|
|
|
(void)cfg_map_get(tlsobj, "key-file", &tls_key);
|
|
|
|
(void)cfg_map_get(tlsobj, "cert-file", &tls_cert);
|
|
|
|
if ((tls_key == NULL && tls_cert != NULL) ||
|
|
|
|
(tls_cert == NULL && tls_key != NULL))
|
|
|
|
{
|
2021-09-13 15:39:36 +03:00
|
|
|
cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR,
|
2021-10-29 18:43:40 +03:00
|
|
|
"tls '%s': 'cert-file' and 'key-file' must "
|
|
|
|
"both be specified, or both omitted",
|
|
|
|
name);
|
2021-09-13 15:39:36 +03:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check protocols are valid */
|
|
|
|
tresult = cfg_map_get(tlsobj, "protocols", &tls_proto_list);
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
|
|
|
const cfg_listelt_t *proto = NULL;
|
|
|
|
INSIST(tls_proto_list != NULL);
|
|
|
|
for (proto = cfg_list_first(tls_proto_list); proto != 0;
|
|
|
|
proto = cfg_list_next(proto))
|
|
|
|
{
|
|
|
|
const cfg_obj_t *tls_proto_obj =
|
|
|
|
cfg_listelt_value(proto);
|
|
|
|
const char *tls_sver = cfg_obj_asstring(tls_proto_obj);
|
|
|
|
const isc_tls_protocol_version_t ver =
|
|
|
|
isc_tls_protocol_name_to_version(tls_sver);
|
|
|
|
|
|
|
|
if (ver == ISC_TLS_PROTO_VER_UNDEFINED) {
|
|
|
|
cfg_obj_log(tls_proto_obj, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid "
|
|
|
|
"TLS protocol version",
|
|
|
|
tls_sver);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
continue;
|
|
|
|
} else if (!isc_tls_protocol_supported(ver)) {
|
|
|
|
cfg_obj_log(tls_proto_obj, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"'%s' is not "
|
|
|
|
"supported by the "
|
|
|
|
"cryptographic library version in "
|
|
|
|
"use (%s)",
|
|
|
|
tls_sver, OPENSSL_VERSION_TEXT);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tls_protos & ver) != 0) {
|
|
|
|
cfg_obj_log(tls_proto_obj, logctx,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"'%s' is specified more than once "
|
|
|
|
"in '%s'",
|
|
|
|
tls_sver, name);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
tls_protos |= ver;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tls_protos == 0) {
|
|
|
|
cfg_obj_log(tlsobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"tls '%s' does not contain any valid "
|
|
|
|
"TLS protocol versions definitions",
|
|
|
|
name);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-20 14:25:59 +03:00
|
|
|
/* Check cipher list string is valid */
|
|
|
|
tresult = cfg_map_get(tlsobj, "ciphers", &tls_ciphers);
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
|
|
|
const char *ciphers = cfg_obj_asstring(tls_ciphers);
|
|
|
|
if (!isc_tls_cipherlist_valid(ciphers)) {
|
|
|
|
cfg_obj_log(tls_ciphers, logctx, ISC_LOG_ERROR,
|
|
|
|
"'ciphers' in the 'tls' clause '%s' is "
|
|
|
|
"not a "
|
|
|
|
"valid cipher list string",
|
|
|
|
name);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 15:39:36 +03:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_tls_definitions(const cfg_obj_t *config, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx) {
|
2021-09-13 15:39:36 +03:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
|
|
|
|
result = cfg_map_get(config, "tls", &obj);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(obj); elt != NULL; elt = cfg_list_next(elt)) {
|
|
|
|
const char *name;
|
|
|
|
obj = cfg_listelt_value(elt);
|
|
|
|
name = cfg_obj_asstring(cfg_map_getname(obj));
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_tls_defintion(obj, name, logctx, symtab);
|
2021-09-13 15:39:36 +03:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-06-25 21:59:56 -07:00
|
|
|
static isc_result_t
|
2021-05-07 14:27:25 +02:00
|
|
|
get_remotes(const cfg_obj_t *cctx, const char *list, const char *name,
|
|
|
|
const cfg_obj_t **ret) {
|
2020-06-25 21:59:56 -07:00
|
|
|
isc_result_t result;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
|
|
|
|
result = cfg_map_get(cctx, list, &obj);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
elt = cfg_list_first(obj);
|
|
|
|
while (elt != NULL) {
|
2003-02-26 06:04:03 +00:00
|
|
|
const char *listname;
|
|
|
|
|
2020-06-25 21:59:56 -07:00
|
|
|
obj = cfg_listelt_value(elt);
|
|
|
|
listname = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
if (strcasecmp(listname, name) == 0) {
|
2020-06-25 21:59:56 -07:00
|
|
|
*ret = obj;
|
2003-02-26 06:04:03 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2020-06-25 21:59:56 -07:00
|
|
|
|
|
|
|
elt = cfg_list_next(elt);
|
2003-02-26 06:04:03 +00:00
|
|
|
}
|
2020-06-25 21:59:56 -07:00
|
|
|
|
2003-02-26 06:04:03 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
2020-06-25 21:59:56 -07:00
|
|
|
static isc_result_t
|
2021-05-07 14:27:25 +02:00
|
|
|
get_remoteservers_def(const char *list, const char *name, const cfg_obj_t *cctx,
|
|
|
|
const cfg_obj_t **ret) {
|
|
|
|
isc_result_t result = ISC_R_NOTFOUND;
|
2020-06-25 21:59:56 -07:00
|
|
|
|
2021-05-07 14:27:25 +02:00
|
|
|
if (strcmp(list, "primaries") == 0) {
|
|
|
|
result = get_remotes(cctx, "primaries", name, ret);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = get_remotes(cctx, "masters", name, ret);
|
|
|
|
}
|
|
|
|
} else if (strcmp(list, "parental-agents") == 0) {
|
|
|
|
result = get_remotes(cctx, "parental-agents", name, ret);
|
2020-06-25 21:59:56 -07:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2003-02-26 06:04:03 +00:00
|
|
|
static isc_result_t
|
2021-05-07 14:27:25 +02:00
|
|
|
validate_remotes(const char *list, const cfg_obj_t *obj,
|
|
|
|
const cfg_obj_t *config, uint32_t *countp, isc_log_t *logctx,
|
|
|
|
isc_mem_t *mctx) {
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t count = 0;
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
isc_symvalue_t symvalue;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
2023-03-30 22:34:12 +02:00
|
|
|
cfg_listelt_t **stack = NULL;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t stackcount = 0, pushed = 0;
|
2021-05-07 14:27:25 +02:00
|
|
|
const cfg_obj_t *listobj;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
REQUIRE(countp != NULL);
|
2018-04-17 08:29:14 -07:00
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
2005-11-03 22:59:53 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
*countp = count;
|
2003-02-26 06:04:03 +00:00
|
|
|
return (result);
|
2005-11-03 22:59:53 +00:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
newlist:
|
2021-05-07 14:27:25 +02:00
|
|
|
listobj = cfg_tuple_get(obj, "addresses");
|
|
|
|
element = cfg_list_first(listobj);
|
2008-03-28 23:47:02 +00:00
|
|
|
resume:
|
2003-02-26 06:04:03 +00:00
|
|
|
for (; element != NULL; element = cfg_list_next(element)) {
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *listname;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *addr;
|
|
|
|
const cfg_obj_t *key;
|
2021-08-04 17:33:00 +10:00
|
|
|
const cfg_obj_t *tls;
|
2003-02-26 06:04:03 +00:00
|
|
|
|
2020-06-17 02:02:27 -07:00
|
|
|
addr = cfg_tuple_get(cfg_listelt_value(element),
|
2021-05-07 11:31:15 +02:00
|
|
|
"remoteselement");
|
2003-02-26 06:04:03 +00:00
|
|
|
key = cfg_tuple_get(cfg_listelt_value(element), "key");
|
2021-08-04 17:33:00 +10:00
|
|
|
tls = cfg_tuple_get(cfg_listelt_value(element), "tls");
|
2003-02-26 06:04:03 +00:00
|
|
|
|
|
|
|
if (cfg_obj_issockaddr(addr)) {
|
|
|
|
count++;
|
2021-08-04 17:23:07 +10:00
|
|
|
if (cfg_obj_isstring(key)) {
|
|
|
|
const char *str = cfg_obj_asstring(key);
|
|
|
|
dns_fixedname_t fname;
|
|
|
|
dns_name_t *nm = dns_fixedname_initname(&fname);
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(
|
|
|
|
nm, str, dns_rootname, 0, NULL);
|
2021-08-04 17:23:07 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name",
|
|
|
|
str);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-04 17:33:00 +10:00
|
|
|
if (cfg_obj_isstring(tls)) {
|
|
|
|
const char *str = cfg_obj_asstring(tls);
|
|
|
|
dns_fixedname_t fname;
|
|
|
|
dns_name_t *nm = dns_fixedname_initname(&fname);
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(
|
|
|
|
nm, str, dns_rootname, 0, NULL);
|
2021-08-04 17:33:00 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(tls, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name",
|
|
|
|
str);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
2021-11-30 00:31:36 +02:00
|
|
|
|
|
|
|
if (strcasecmp(str, "ephemeral") != 0) {
|
|
|
|
const cfg_obj_t *tlsmap = NULL;
|
|
|
|
|
|
|
|
tlsmap = find_maplist(config, "tls",
|
|
|
|
str);
|
|
|
|
if (tlsmap == NULL) {
|
|
|
|
cfg_obj_log(
|
|
|
|
tls, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"tls '%s' is not "
|
|
|
|
"defined",
|
|
|
|
cfg_obj_asstring(tls));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2021-08-04 17:33:00 +10:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
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;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
}
|
2021-08-04 17:33:00 +10:00
|
|
|
if (!cfg_obj_isvoid(tls)) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"unexpected token '%s'",
|
|
|
|
cfg_obj_asstring(tls));
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
listname = cfg_obj_asstring(addr);
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = addr;
|
2003-02-26 06:04:03 +00:00
|
|
|
tresult = isc_symtab_define(symtab, listname, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-05-07 14:27:25 +02:00
|
|
|
tresult = get_remoteservers_def(list, listname, config, &obj);
|
2003-02-26 06:04:03 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
|
2021-05-07 14:27:25 +02:00
|
|
|
"unable to find %s list '%s'", list,
|
2003-02-26 06:04:03 +00:00
|
|
|
listname);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* Grow stack? */
|
|
|
|
if (stackcount == pushed) {
|
2023-08-23 10:00:12 +02:00
|
|
|
stack = isc_mem_creget(mctx, stack, stackcount,
|
|
|
|
stackcount + 16,
|
|
|
|
sizeof(stack[0]));
|
|
|
|
stackcount += 16;
|
2003-02-26 06:04:03 +00:00
|
|
|
}
|
2023-03-30 22:34:12 +02:00
|
|
|
stack[pushed++] = UNCONST(cfg_list_next(element));
|
2003-02-26 06:04:03 +00:00
|
|
|
goto newlist;
|
|
|
|
}
|
|
|
|
if (pushed != 0) {
|
|
|
|
element = stack[--pushed];
|
|
|
|
goto resume;
|
|
|
|
}
|
2009-02-17 03:40:28 +00:00
|
|
|
if (stack != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(mctx, stack, stackcount, sizeof(*stack));
|
2009-02-17 03:40:28 +00:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
*countp = count;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2005-07-28 05:42:20 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
|
2005-07-28 05:42:20 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_listelt_t *element2;
|
2018-02-07 13:34:02 +11:00
|
|
|
dns_fixedname_t fixed_id, fixed_name;
|
|
|
|
dns_name_t *id, *name;
|
2005-08-23 02:36:11 +00:00
|
|
|
const char *str;
|
2018-09-06 19:36:17 +10:00
|
|
|
isc_textregion_t r;
|
|
|
|
dns_rdatatype_t type;
|
2005-07-28 05:42:20 +00:00
|
|
|
|
2009-07-14 22:54:57 +00:00
|
|
|
/* Check for "update-policy local;" */
|
|
|
|
if (cfg_obj_isstring(policy) &&
|
2022-11-02 19:33:14 +01:00
|
|
|
strcmp("local", cfg_obj_asstring(policy)) == 0)
|
|
|
|
{
|
2009-07-14 23:47:54 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-07-14 22:54:57 +00:00
|
|
|
|
|
|
|
/* Now check the grant policy */
|
2005-07-28 05:42:20 +00:00
|
|
|
for (element = cfg_list_first(policy); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *stmt = cfg_listelt_value(element);
|
|
|
|
const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
|
|
|
|
const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
|
|
|
|
const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
|
|
|
|
const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
|
2018-02-07 13:34:02 +11:00
|
|
|
dns_ssumatchtype_t mtype;
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
id = dns_fixedname_initname(&fixed_id);
|
|
|
|
name = dns_fixedname_initname(&fixed_name);
|
2018-02-07 13:34:02 +11:00
|
|
|
|
|
|
|
tresult = dns_ssu_mtypefromstring(cfg_obj_asstring(matchtype),
|
|
|
|
&mtype);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"has a bad match-type");
|
|
|
|
}
|
2005-07-28 05:42:20 +00:00
|
|
|
|
|
|
|
str = cfg_obj_asstring(identity);
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(id, str, dns_rootname, 1, NULL);
|
2005-07-28 05:42:20 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name", str);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
2018-02-07 13:34:02 +11:00
|
|
|
/*
|
2018-09-06 19:36:17 +10:00
|
|
|
* There is no name field for subzone and dname is void
|
2018-02-07 13:34:02 +11:00
|
|
|
*/
|
2018-09-06 19:36:17 +10:00
|
|
|
if (mtype == dns_ssumatchtype_subdomain &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_obj_isvoid(dname))
|
|
|
|
{
|
2018-09-06 19:36:17 +10:00
|
|
|
str = "."; /* Use "." as a replacement. */
|
|
|
|
} else {
|
2009-06-10 00:27:22 +00:00
|
|
|
str = cfg_obj_asstring(dname);
|
2018-09-06 19:36:17 +10:00
|
|
|
}
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(name, str, dns_rootname,
|
|
|
|
0, NULL);
|
2009-06-10 00:27:22 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid name", str);
|
|
|
|
result = tresult;
|
|
|
|
}
|
2005-07-28 05:42:20 +00:00
|
|
|
}
|
2009-06-10 00:27:22 +00:00
|
|
|
|
2006-08-21 00:11:43 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS &&
|
2018-02-07 13:34:02 +11:00
|
|
|
mtype == dns_ssumatchtype_wildcard &&
|
|
|
|
!dns_name_iswildcard(name))
|
|
|
|
{
|
2006-08-21 00:11:43 +00:00
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a wildcard", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2005-07-28 05:42:20 +00:00
|
|
|
|
2018-02-07 13:34:02 +11:00
|
|
|
/*
|
|
|
|
* For some match types, the name should be a placeholder
|
|
|
|
* value, either "." or the same as identity.
|
|
|
|
*/
|
|
|
|
switch (mtype) {
|
|
|
|
case dns_ssumatchtype_self:
|
|
|
|
case dns_ssumatchtype_selfsub:
|
|
|
|
case dns_ssumatchtype_selfwild:
|
|
|
|
if (tresult == ISC_R_SUCCESS &&
|
|
|
|
(!dns_name_equal(id, name) &&
|
|
|
|
!dns_name_equal(dns_rootname, name)))
|
|
|
|
{
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"identity and name fields are not "
|
|
|
|
"the same");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case dns_ssumatchtype_selfkrb5:
|
|
|
|
case dns_ssumatchtype_selfms:
|
2018-08-30 18:31:17 +10:00
|
|
|
case dns_ssumatchtype_selfsubkrb5:
|
|
|
|
case dns_ssumatchtype_selfsubms:
|
2018-02-07 13:34:02 +11:00
|
|
|
case dns_ssumatchtype_tcpself:
|
|
|
|
case dns_ssumatchtype_6to4self:
|
|
|
|
if (tresult == ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
!dns_name_equal(dns_rootname, name))
|
|
|
|
{
|
2018-02-07 13:34:02 +11:00
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"name field not set to "
|
|
|
|
"placeholder value '.'");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case dns_ssumatchtype_name:
|
2018-09-06 19:36:17 +10:00
|
|
|
case dns_ssumatchtype_subdomain: /* also zonesub */
|
2018-09-06 13:51:24 +10:00
|
|
|
case dns_ssumatchtype_subdomainms:
|
2018-08-24 09:19:38 +10:00
|
|
|
case dns_ssumatchtype_subdomainselfmsrhs:
|
2018-09-06 13:51:24 +10:00
|
|
|
case dns_ssumatchtype_subdomainkrb5:
|
2018-08-24 09:19:38 +10:00
|
|
|
case dns_ssumatchtype_subdomainselfkrb5rhs:
|
2018-02-07 13:34:02 +11:00
|
|
|
case dns_ssumatchtype_wildcard:
|
|
|
|
case dns_ssumatchtype_external:
|
|
|
|
case dns_ssumatchtype_local:
|
2018-09-06 19:36:17 +10:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(str);
|
2018-09-06 19:36:17 +10:00
|
|
|
r.length = strlen(str);
|
|
|
|
tresult = dns_rdatatype_fromtext(&type, &r);
|
|
|
|
}
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
|
|
|
|
"missing name field type '%s' "
|
|
|
|
"found",
|
|
|
|
str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
2018-02-07 13:34:02 +11:00
|
|
|
break;
|
|
|
|
default:
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2018-02-07 13:34:02 +11:00
|
|
|
}
|
|
|
|
|
2005-07-28 05:42:20 +00:00
|
|
|
for (element2 = cfg_list_first(typelist); element2 != NULL;
|
|
|
|
element2 = cfg_list_next(element2))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *typeobj;
|
2019-07-03 16:42:15 +10:00
|
|
|
const char *bracket;
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2005-07-28 05:42:20 +00:00
|
|
|
typeobj = cfg_listelt_value(element2);
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(typeobj));
|
2019-07-03 16:42:15 +10:00
|
|
|
|
|
|
|
bracket = strchr(r.base, '(' /*)*/);
|
|
|
|
if (bracket != NULL) {
|
|
|
|
char *end = NULL;
|
|
|
|
unsigned long max;
|
|
|
|
|
|
|
|
r.length = bracket - r.base;
|
|
|
|
max = strtoul(bracket + 1, &end, 10);
|
|
|
|
if (max > 0xffff || end[0] != /*(*/ ')' ||
|
2022-11-02 19:33:14 +01:00
|
|
|
end[1] != 0)
|
|
|
|
{
|
2019-07-03 16:42:15 +10:00
|
|
|
cfg_obj_log(typeobj, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"'%s' is not a valid count",
|
|
|
|
bracket);
|
|
|
|
result = DNS_R_SYNTAX;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r.length = strlen(r.base);
|
|
|
|
}
|
2005-07-28 05:42:20 +00:00
|
|
|
|
|
|
|
tresult = dns_rdatatype_fromtext(&type, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
|
2019-07-03 16:42:15 +10:00
|
|
|
"'%.*s' is not a valid type",
|
|
|
|
(int)r.length, r.base);
|
2005-07-28 05:42:20 +00:00
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
2018-08-30 13:16:15 +02:00
|
|
|
unsigned int allowed;
|
2001-03-01 23:46:49 +00:00
|
|
|
} optionstable;
|
|
|
|
|
2012-08-13 22:39:42 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
Clean up handling of NOTIFY settings for mirror zones
Previous way of handling NOTIFY settings for mirror zones was a bit
tricky: any value of the "notify" option was accepted, but it was
subsequently overridden with dns_notifytype_explicit. Given the way
zone configuration is performed, this resulted in the following
behavior:
- if "notify yes;" was set explicitly at any configuration level or
inherited from default configuration, it was silently changed and so
only hosts specified in "also-notify", if any, were notified,
- if "notify no;" was set at any configuration level, it was
effectively honored since even though zone->notifytype was silently
set to dns_notifytype_explicit, the "also-notify" option was never
processed due to "notify no;" being set.
Effectively, this only allowed the hosts specified in "also-notify" to
be notified, when either "notify yes;" or "notify explicit;" was
explicitly set or inherited from default configuration.
Clean up handling of NOTIFY settings for mirror zones by:
- reporting a configuration error when anything else than "notify no;"
or "notify explicit;" is set for a mirror zone at the zone level,
- overriding inherited "notify yes;" setting with "notify explicit;"
for mirror zones,
- informing the user when the "notify" setting is overridden, unless
the setting in question was inherited from default configuration.
2018-10-09 10:54:51 +02:00
|
|
|
/*%
|
|
|
|
* Check whether NOTIFY configuration at the zone level is acceptable for a
|
|
|
|
* mirror zone. Return true if it is; return false otherwise.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr,
|
|
|
|
isc_log_t *logctx) {
|
|
|
|
bool notify_configuration_ok = true;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
|
|
|
|
(void)cfg_map_get(zoptions, "notify", &obj);
|
|
|
|
if (obj == NULL) {
|
|
|
|
/*
|
|
|
|
* "notify" not set at zone level. This is fine.
|
|
|
|
*/
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg_obj_isboolean(obj)) {
|
|
|
|
if (cfg_obj_asboolean(obj)) {
|
|
|
|
/*
|
|
|
|
* "notify yes;" set at zone level. This is an error.
|
|
|
|
*/
|
|
|
|
notify_configuration_ok = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *notifystr = cfg_obj_asstring(obj);
|
|
|
|
if (strcasecmp(notifystr, "explicit") != 0) {
|
|
|
|
/*
|
|
|
|
* Something else than "notify explicit;" set at zone
|
|
|
|
* level. This is an error.
|
|
|
|
*/
|
|
|
|
notify_configuration_ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!notify_configuration_ok) {
|
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': mirror zones can only be used with "
|
|
|
|
"'notify no;' or 'notify explicit;'",
|
|
|
|
znamestr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (notify_configuration_ok);
|
|
|
|
}
|
|
|
|
|
2018-10-09 10:54:51 +02:00
|
|
|
/*%
|
|
|
|
* Try to determine whether recursion is available in a view without resorting
|
|
|
|
* to extraordinary measures: just check the "recursion" and "allow-recursion"
|
|
|
|
* settings. The point is to prevent accidental mirror zone misuse rather than
|
|
|
|
* to enforce some sort of policy. Recursion is assumed to be allowed by
|
|
|
|
* default if it is not explicitly disabled.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|
|
|
const cfg_obj_t *goptions, isc_log_t *logctx,
|
|
|
|
cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
const cfg_obj_t *obj;
|
|
|
|
isc_result_t result;
|
|
|
|
bool retval = true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the "recursion" option first.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
if (voptions != NULL) {
|
|
|
|
result = cfg_map_get(voptions, "recursion", &obj);
|
|
|
|
}
|
|
|
|
if (result != ISC_R_SUCCESS && goptions != NULL) {
|
|
|
|
result = cfg_map_get(goptions, "recursion", &obj);
|
|
|
|
}
|
|
|
|
if (result == ISC_R_SUCCESS && !cfg_obj_asboolean(obj)) {
|
|
|
|
retval = false;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If recursion is not disabled by the "recursion" option, check
|
|
|
|
* whether it is disabled by the "allow-recursion" ACL.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
if (voptions != NULL) {
|
|
|
|
result = cfg_map_get(voptions, "allow-recursion", &obj);
|
|
|
|
}
|
|
|
|
if (result != ISC_R_SUCCESS && goptions != NULL) {
|
|
|
|
result = cfg_map_get(goptions, "allow-recursion", &obj);
|
|
|
|
}
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = cfg_acl_fromconfig(obj, config, logctx, actx, mctx, 0,
|
|
|
|
&acl);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
retval = !dns_acl_isnone(acl);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (acl != NULL) {
|
|
|
|
dns_acl_detach(&acl);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|
|
|
const cfg_obj_t *config, isc_symtab_t *symtab,
|
2021-05-04 15:35:39 +02:00
|
|
|
isc_symtab_t *files, isc_symtab_t *keydirs, isc_symtab_t *inview,
|
|
|
|
const char *viewname, dns_rdataclass_t defclass,
|
2023-03-22 16:57:54 -07:00
|
|
|
cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx) {
|
2010-12-16 09:51:30 +00:00
|
|
|
const char *znamestr;
|
2018-03-05 11:53:18 +11:00
|
|
|
const char *typestr = NULL;
|
2018-05-25 13:15:00 +10:00
|
|
|
const char *target = NULL;
|
2001-03-01 23:46:49 +00:00
|
|
|
unsigned int ztype;
|
2012-08-13 22:39:42 -07:00
|
|
|
const cfg_obj_t *zoptions, *goptions = NULL;
|
2022-06-07 14:46:05 +02:00
|
|
|
const cfg_obj_t *obj = NULL, *kasp = NULL;
|
2018-05-25 13:15:00 +10:00
|
|
|
const cfg_obj_t *inviewobj = NULL;
|
2001-03-04 21:18:30 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_result_t tresult;
|
2001-03-01 23:46:49 +00:00
|
|
|
unsigned int i;
|
2001-09-20 15:17:07 +00:00
|
|
|
dns_rdataclass_t zclass;
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_fixedname_t fixedname;
|
2018-12-14 16:50:46 +11:00
|
|
|
dns_name_t *zname = NULL; /* NULL if parsing of zone name fails. */
|
2002-02-06 05:58:06 +00:00
|
|
|
isc_buffer_t b;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool root = false;
|
|
|
|
bool rfc1918 = false;
|
|
|
|
bool ula = false;
|
2010-12-16 09:51:30 +00:00
|
|
|
const cfg_listelt_t *element;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool dlz;
|
|
|
|
bool ddns = false;
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
bool has_dnssecpolicy = false;
|
2022-12-09 12:22:49 +01:00
|
|
|
bool kasp_inlinesigning = false;
|
2018-01-22 11:00:45 -08:00
|
|
|
const void *clauses = NULL;
|
|
|
|
const char *option = NULL;
|
2021-05-04 15:35:39 +02:00
|
|
|
const char *kaspname = NULL;
|
|
|
|
const char *dir = NULL;
|
2018-01-22 11:00:45 -08:00
|
|
|
static const char *acls[] = {
|
|
|
|
"allow-notify",
|
|
|
|
"allow-transfer",
|
|
|
|
"allow-update",
|
|
|
|
"allow-update-forwarding",
|
2001-03-01 23:46:49 +00:00
|
|
|
};
|
|
|
|
static optionstable dialups[] = {
|
2021-08-25 22:31:18 -07:00
|
|
|
{ "notify", CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
|
|
|
|
{ "notify-passive", CFG_ZONE_SECONDARY },
|
|
|
|
{ "passive", CFG_ZONE_SECONDARY | CFG_ZONE_STUB },
|
|
|
|
{ "refresh", CFG_ZONE_SECONDARY | CFG_ZONE_STUB },
|
2001-03-01 23:46:49 +00:00
|
|
|
};
|
2021-09-13 17:55:34 -07:00
|
|
|
static const char *sources[] = {
|
|
|
|
"transfer-source", "transfer-source-v6", "notify-source",
|
|
|
|
"notify-source-v6", "parental-source", "parental-source-v6",
|
|
|
|
};
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2010-12-16 09:51:30 +00:00
|
|
|
znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
|
2001-03-02 01:30:32 +00:00
|
|
|
|
|
|
|
zoptions = cfg_tuple_get(zconfig, "options");
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2012-08-13 22:39:42 -07:00
|
|
|
if (config != NULL) {
|
|
|
|
cfg_map_get(config, "options", &goptions);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-08-13 22:39:42 -07:00
|
|
|
|
2018-05-25 13:15:00 +10:00
|
|
|
inviewobj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "in-view", &inviewobj);
|
|
|
|
if (inviewobj != NULL) {
|
|
|
|
target = cfg_obj_asstring(inviewobj);
|
2018-03-05 11:53:18 +11:00
|
|
|
ztype = CFG_ZONE_INVIEW;
|
|
|
|
} else {
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "type", &obj);
|
|
|
|
if (obj == NULL) {
|
2013-11-13 20:35:40 -08:00
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
2018-03-05 11:53:18 +11:00
|
|
|
"zone '%s': type not present", znamestr);
|
2013-11-13 20:35:40 -08:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2018-03-05 11:53:18 +11:00
|
|
|
typestr = cfg_obj_asstring(obj);
|
|
|
|
if (strcasecmp(typestr, "master") == 0 ||
|
2022-11-02 19:33:14 +01:00
|
|
|
strcasecmp(typestr, "primary") == 0)
|
|
|
|
{
|
2021-08-25 22:31:18 -07:00
|
|
|
ztype = CFG_ZONE_PRIMARY;
|
2018-03-05 11:53:18 +11:00
|
|
|
} else if (strcasecmp(typestr, "slave") == 0 ||
|
|
|
|
strcasecmp(typestr, "secondary") == 0)
|
|
|
|
{
|
2021-08-25 22:31:18 -07:00
|
|
|
ztype = CFG_ZONE_SECONDARY;
|
2018-10-09 10:54:51 +02:00
|
|
|
} else if (strcasecmp(typestr, "mirror") == 0) {
|
|
|
|
ztype = CFG_ZONE_MIRROR;
|
2018-03-05 11:53:18 +11:00
|
|
|
} else if (strcasecmp(typestr, "stub") == 0) {
|
|
|
|
ztype = CFG_ZONE_STUB;
|
|
|
|
} else if (strcasecmp(typestr, "static-stub") == 0) {
|
|
|
|
ztype = CFG_ZONE_STATICSTUB;
|
|
|
|
} else if (strcasecmp(typestr, "forward") == 0) {
|
|
|
|
ztype = CFG_ZONE_FORWARD;
|
|
|
|
} else if (strcasecmp(typestr, "hint") == 0) {
|
|
|
|
ztype = CFG_ZONE_HINT;
|
|
|
|
} else if (strcasecmp(typestr, "redirect") == 0) {
|
|
|
|
ztype = CFG_ZONE_REDIRECT;
|
|
|
|
} else {
|
2001-09-20 15:17:07 +00:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2018-03-05 11:53:18 +11:00
|
|
|
"zone '%s': invalid type %s", znamestr,
|
|
|
|
typestr);
|
2001-09-20 15:17:07 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2018-03-05 11:53:18 +11:00
|
|
|
|
|
|
|
if (ztype == CFG_ZONE_REDIRECT && strcmp(znamestr, ".") != 0) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"redirect zones must be called \".\"");
|
2001-09-20 15:17:07 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
}
|
2018-03-05 11:53:18 +11:00
|
|
|
|
2018-05-25 13:15:00 +10:00
|
|
|
obj = cfg_tuple_get(zconfig, "class");
|
|
|
|
if (cfg_obj_isstring(obj)) {
|
|
|
|
isc_textregion_t r;
|
|
|
|
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(obj));
|
2018-05-25 13:15:00 +10:00
|
|
|
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);
|
2018-03-05 11:53:18 +11:00
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
} else {
|
|
|
|
zclass = defclass;
|
2001-09-20 15:17:07 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Look for an already existing zone.
|
2009-01-17 11:57:25 +00:00
|
|
|
* We need to make this canonical as isc_symtab_define()
|
2002-02-06 05:58:06 +00:00
|
|
|
* deals with strings.
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2002-02-06 05:58:06 +00:00
|
|
|
dns_fixedname_init(&fixedname);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, znamestr, strlen(znamestr));
|
2010-12-16 09:51:30 +00:00
|
|
|
isc_buffer_add(&b, strlen(znamestr));
|
2004-06-04 02:31:43 +00:00
|
|
|
tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
|
2009-09-01 00:22:28 +00:00
|
|
|
dns_rootname, DNS_NAME_DOWNCASE, NULL);
|
2007-12-14 01:27:12 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-03-08 00:55:50 +00:00
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
2010-12-16 09:51:30 +00:00
|
|
|
"zone '%s': is not a valid name", znamestr);
|
2007-12-14 01:27:12 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2002-02-06 05:58:06 +00:00
|
|
|
} else {
|
2018-05-25 13:15:00 +10:00
|
|
|
char namebuf[DNS_NAME_FORMATSIZE + 128];
|
|
|
|
char *tmp = namebuf;
|
|
|
|
size_t len = sizeof(namebuf);
|
2002-02-12 13:17:23 +00:00
|
|
|
|
2010-12-16 09:51:30 +00:00
|
|
|
zname = dns_fixedname_name(&fixedname);
|
|
|
|
dns_name_format(zname, namebuf, sizeof(namebuf));
|
2023-09-20 12:53:35 +10:00
|
|
|
tresult = exists(
|
|
|
|
zconfig, namebuf,
|
|
|
|
ztype == CFG_ZONE_HINT ? 1
|
|
|
|
: ztype == CFG_ZONE_REDIRECT ? 2
|
|
|
|
: 3,
|
|
|
|
symtab,
|
|
|
|
"zone '%s': already exists previous definition: %s:%u",
|
|
|
|
logctx, mctx);
|
2004-06-04 02:31:43 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2010-12-16 09:51:30 +00:00
|
|
|
if (dns_name_equal(zname, dns_rootname)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
root = true;
|
2016-03-08 10:11:23 +11:00
|
|
|
} else if (dns_name_isrfc1918(zname)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
rfc1918 = true;
|
2016-03-08 10:11:23 +11:00
|
|
|
} else if (dns_name_isula(zname)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ula = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
len -= strlen(tmp);
|
2022-05-13 19:59:58 -07:00
|
|
|
tmp += strlen(tmp);
|
2018-05-25 13:15:00 +10:00
|
|
|
(void)snprintf(tmp, len, "%u/%s", zclass,
|
|
|
|
(ztype == CFG_ZONE_INVIEW) ? target
|
|
|
|
: (viewname != NULL) ? viewname
|
|
|
|
: "_default");
|
|
|
|
switch (ztype) {
|
|
|
|
case CFG_ZONE_INVIEW:
|
|
|
|
tresult = isc_symtab_lookup(inview, namebuf, 0, NULL);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(inviewobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'in-view' zone '%s' "
|
|
|
|
"does not exist in view '%s', "
|
|
|
|
"or view '%s' is not yet defined",
|
|
|
|
znamestr, target, target);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CFG_ZONE_FORWARD:
|
|
|
|
case CFG_ZONE_REDIRECT:
|
|
|
|
case CFG_ZONE_DELEGATION:
|
|
|
|
break;
|
|
|
|
|
2021-08-25 22:31:18 -07:00
|
|
|
case CFG_ZONE_PRIMARY:
|
|
|
|
case CFG_ZONE_SECONDARY:
|
2018-10-09 10:54:51 +02:00
|
|
|
case CFG_ZONE_MIRROR:
|
2018-05-25 13:15:00 +10:00
|
|
|
case CFG_ZONE_HINT:
|
|
|
|
case CFG_ZONE_STUB:
|
|
|
|
case CFG_ZONE_STATICSTUB:
|
|
|
|
tmp = isc_mem_strdup(mctx, namebuf);
|
2019-07-23 11:12:11 -04:00
|
|
|
{
|
2018-05-25 13:15:00 +10:00
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
symvalue.as_cpointer = NULL;
|
|
|
|
tresult = isc_symtab_define(
|
|
|
|
inview, tmp, 1, symvalue,
|
2019-07-23 11:12:11 -04:00
|
|
|
isc_symexists_replace);
|
2018-05-25 13:15:00 +10:00
|
|
|
if (tresult == ISC_R_NOMEMORY) {
|
|
|
|
isc_mem_free(mctx, tmp);
|
|
|
|
}
|
2019-07-23 11:12:11 -04:00
|
|
|
if (result == ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
tresult != ISC_R_SUCCESS)
|
|
|
|
{
|
2018-05-25 13:15:00 +10:00
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2018-05-25 13:15:00 +10:00
|
|
|
}
|
2002-02-06 05:58:06 +00:00
|
|
|
}
|
2001-03-08 00:55:50 +00:00
|
|
|
|
2018-03-05 11:53:18 +11:00
|
|
|
if (ztype == CFG_ZONE_INVIEW) {
|
|
|
|
const cfg_obj_t *fwd = NULL;
|
|
|
|
unsigned int maxopts = 1;
|
|
|
|
|
|
|
|
(void)cfg_map_get(zoptions, "forward", &fwd);
|
|
|
|
if (fwd != NULL) {
|
|
|
|
maxopts++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-03-05 11:53:18 +11:00
|
|
|
fwd = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "forwarders", &fwd);
|
|
|
|
if (fwd != NULL) {
|
|
|
|
maxopts++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-03-05 11:53:18 +11:00
|
|
|
if (cfg_map_count(zoptions) > maxopts) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': 'in-view' used "
|
|
|
|
"with incompatible zone options",
|
|
|
|
znamestr);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-03-05 11:53:18 +11:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2012-08-13 22:39:42 -07:00
|
|
|
/*
|
|
|
|
* Check if value is zero.
|
|
|
|
*/
|
|
|
|
if (check_nonzero(zoptions, logctx) != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-08-13 22:39:42 -07:00
|
|
|
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
/*
|
|
|
|
* Check if a dnssec-policy is set.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "dnssec-policy", &obj);
|
2021-06-18 11:00:23 +02:00
|
|
|
if (obj == NULL && voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "dnssec-policy", &obj);
|
|
|
|
}
|
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
(void)cfg_map_get(goptions, "dnssec-policy", &obj);
|
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
if (obj != NULL) {
|
|
|
|
const cfg_obj_t *kasps = NULL;
|
|
|
|
|
2021-05-04 15:35:39 +02:00
|
|
|
kaspname = cfg_obj_asstring(obj);
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
if (strcmp(kaspname, "default") == 0) {
|
|
|
|
has_dnssecpolicy = true;
|
2022-12-09 12:22:49 +01:00
|
|
|
kasp_inlinesigning = true;
|
2021-04-21 16:09:06 +02:00
|
|
|
} else if (strcmp(kaspname, "insecure") == 0) {
|
|
|
|
has_dnssecpolicy = true;
|
2022-12-09 12:22:49 +01:00
|
|
|
kasp_inlinesigning = true;
|
2019-11-05 17:22:35 +01:00
|
|
|
} else if (strcmp(kaspname, "none") == 0) {
|
|
|
|
has_dnssecpolicy = false;
|
2022-12-09 12:22:49 +01:00
|
|
|
kasp_inlinesigning = false;
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
} else {
|
|
|
|
(void)cfg_map_get(config, "dnssec-policy", &kasps);
|
|
|
|
for (element = cfg_list_first(kasps); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2020-04-08 13:08:20 +02:00
|
|
|
const cfg_obj_t *kobj = cfg_tuple_get(
|
|
|
|
cfg_listelt_value(element), "name");
|
|
|
|
if (strcmp(kaspname, cfg_obj_asstring(kobj)) ==
|
2022-11-02 19:33:14 +01:00
|
|
|
0)
|
|
|
|
{
|
2022-12-09 12:22:49 +01:00
|
|
|
const cfg_obj_t *inlinesigning = NULL;
|
|
|
|
const cfg_obj_t *kopt = cfg_tuple_get(
|
|
|
|
cfg_listelt_value(element),
|
|
|
|
"options");
|
|
|
|
if (cfg_map_get(kopt, "inline-signing",
|
|
|
|
&inlinesigning) ==
|
|
|
|
ISC_R_SUCCESS)
|
|
|
|
{
|
|
|
|
kasp_inlinesigning =
|
|
|
|
cfg_obj_asboolean(
|
|
|
|
inlinesigning);
|
|
|
|
} else {
|
|
|
|
/* By default true */
|
|
|
|
kasp_inlinesigning = true;
|
|
|
|
}
|
|
|
|
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
has_dnssecpolicy = true;
|
2022-12-09 12:22:49 +01:00
|
|
|
break;
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-05 17:22:35 +01:00
|
|
|
if (!has_dnssecpolicy) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': option "
|
|
|
|
"'dnssec-policy %s' has no "
|
|
|
|
"matching dnssec-policy config",
|
|
|
|
znamestr, kaspname);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
}
|
2022-06-07 14:46:05 +02:00
|
|
|
if (has_dnssecpolicy) {
|
|
|
|
kasp = obj;
|
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
|
2022-07-19 12:13:42 -07:00
|
|
|
/*
|
|
|
|
* Reject zones with both dnssec-policy and max-zone-ttl
|
|
|
|
* */
|
|
|
|
if (has_dnssecpolicy) {
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "max-zone-ttl", &obj);
|
|
|
|
if (obj == NULL && voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "max-zone-ttl", &obj);
|
|
|
|
}
|
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
(void)cfg_map_get(goptions, "max-zone-ttl", &obj);
|
|
|
|
}
|
|
|
|
if (obj != NULL) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': option 'max-zone-ttl' "
|
|
|
|
"cannot be used together with "
|
|
|
|
"'dnssec-policy'",
|
|
|
|
znamestr);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
2018-01-22 11:00:45 -08:00
|
|
|
* Check validity of the zone options.
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2018-01-22 11:00:45 -08:00
|
|
|
option = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &i);
|
|
|
|
while (option != NULL) {
|
2001-03-01 23:46:49 +00:00
|
|
|
obj = NULL;
|
2018-01-22 11:00:45 -08:00
|
|
|
if (cfg_map_get(zoptions, option, &obj) == ISC_R_SUCCESS &&
|
|
|
|
obj != NULL && !cfg_clause_validforzone(option, ztype))
|
|
|
|
{
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"option '%s' is not allowed "
|
|
|
|
"in '%s' zone '%s'",
|
|
|
|
option, typestr, znamestr);
|
|
|
|
result = ISC_R_FAILURE;
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
2018-01-22 11:00:45 -08:00
|
|
|
option = cfg_map_nextclause(&cfg_type_zoneopts, &clauses, &i);
|
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
|
2018-01-22 11:00:45 -08:00
|
|
|
/*
|
|
|
|
* Check that ACLs expand correctly.
|
|
|
|
*/
|
2021-09-13 17:55:34 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(acls); i++) {
|
2018-01-22 11:00:45 -08:00
|
|
|
tresult = checkacl(acls[i], actx, zconfig, voptions, config,
|
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2005-01-11 03:46:11 +00:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
Clean up handling of NOTIFY settings for mirror zones
Previous way of handling NOTIFY settings for mirror zones was a bit
tricky: any value of the "notify" option was accepted, but it was
subsequently overridden with dns_notifytype_explicit. Given the way
zone configuration is performed, this resulted in the following
behavior:
- if "notify yes;" was set explicitly at any configuration level or
inherited from default configuration, it was silently changed and so
only hosts specified in "also-notify", if any, were notified,
- if "notify no;" was set at any configuration level, it was
effectively honored since even though zone->notifytype was silently
set to dns_notifytype_explicit, the "also-notify" option was never
processed due to "notify no;" being set.
Effectively, this only allowed the hosts specified in "also-notify" to
be notified, when either "notify yes;" or "notify explicit;" was
explicitly set or inherited from default configuration.
Clean up handling of NOTIFY settings for mirror zones by:
- reporting a configuration error when anything else than "notify no;"
or "notify explicit;" is set for a mirror zone at the zone level,
- overriding inherited "notify yes;" setting with "notify explicit;"
for mirror zones,
- informing the user when the "notify" setting is overridden, unless
the setting in question was inherited from default configuration.
2018-10-09 10:54:51 +02:00
|
|
|
/*
|
|
|
|
* Only a limited subset of all possible "notify" settings can be used
|
|
|
|
* at the zone level for mirror zones.
|
|
|
|
*/
|
|
|
|
if (ztype == CFG_ZONE_MIRROR &&
|
|
|
|
!check_mirror_zone_notify(zoptions, znamestr, logctx))
|
|
|
|
{
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-10-02 13:06:02 +10:00
|
|
|
/*
|
2021-09-13 17:55:34 -07:00
|
|
|
* Primary, secondary, and mirror zones may have an "also-notify"
|
|
|
|
* field, but shouldn't if notify is disabled.
|
2012-10-02 13:06:02 +10:00
|
|
|
*/
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY ||
|
2018-10-09 10:54:51 +02:00
|
|
|
ztype == CFG_ZONE_MIRROR)
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
bool donotify = true;
|
2014-01-20 15:53:51 -08:00
|
|
|
|
2012-10-02 13:06:02 +10:00
|
|
|
obj = NULL;
|
2014-01-20 15:53:51 -08:00
|
|
|
tresult = cfg_map_get(zoptions, "notify", &obj);
|
|
|
|
if (tresult != ISC_R_SUCCESS && voptions != NULL) {
|
|
|
|
tresult = cfg_map_get(voptions, "notify", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-01-20 15:53:51 -08:00
|
|
|
if (tresult != ISC_R_SUCCESS && goptions != NULL) {
|
|
|
|
tresult = cfg_map_get(goptions, "notify", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-10-02 13:06:02 +10:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2014-01-20 15:53:51 -08:00
|
|
|
if (cfg_obj_isboolean(obj)) {
|
|
|
|
donotify = cfg_obj_asboolean(obj);
|
|
|
|
} else {
|
2020-06-17 02:45:07 -07:00
|
|
|
const char *str = cfg_obj_asstring(obj);
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype != CFG_ZONE_PRIMARY &&
|
2020-06-17 02:45:07 -07:00
|
|
|
(strcasecmp(str, "master-only") == 0 ||
|
|
|
|
strcasecmp(str, "primary-only") == 0))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
donotify = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-01-20 15:53:51 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
tresult = cfg_map_get(zoptions, "also-notify", &obj);
|
|
|
|
if (tresult == ISC_R_SUCCESS && !donotify) {
|
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_WARNING,
|
|
|
|
"zone '%s': 'also-notify' set but "
|
|
|
|
"'notify' is disabled",
|
|
|
|
znamestr);
|
2016-05-05 21:59:09 +10:00
|
|
|
}
|
|
|
|
if (tresult != ISC_R_SUCCESS && voptions != NULL) {
|
|
|
|
tresult = cfg_map_get(voptions, "also-notify", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-05 21:59:09 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS && goptions != NULL) {
|
|
|
|
tresult = cfg_map_get(goptions, "also-notify", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-05 21:59:09 +10:00
|
|
|
if (tresult == ISC_R_SUCCESS && donotify) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t count;
|
2021-05-07 14:27:25 +02:00
|
|
|
tresult = validate_remotes("primaries", obj, config,
|
|
|
|
&count, logctx, mctx);
|
2012-10-02 13:06:02 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
|
|
|
{
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-10-02 13:06:02 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
2021-09-13 17:55:34 -07:00
|
|
|
* Secondary, mirror, and stub zones must have a "primaries" field,
|
|
|
|
* with one exception: when mirroring the root zone, a default,
|
|
|
|
* built-in primary server list is used in the absence of one
|
|
|
|
* explicitly specified.
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype == CFG_ZONE_SECONDARY || ztype == CFG_ZONE_STUB ||
|
2018-12-14 16:50:46 +11:00
|
|
|
(ztype == CFG_ZONE_MIRROR && zname != NULL &&
|
|
|
|
!dns_name_equal(zname, dns_rootname)))
|
|
|
|
{
|
2001-03-01 23:46:49 +00:00
|
|
|
obj = NULL;
|
2020-06-17 02:02:27 -07:00
|
|
|
(void)cfg_map_get(zoptions, "primaries", &obj);
|
|
|
|
if (obj == NULL) {
|
|
|
|
/* If "primaries" was unset, check for "masters" */
|
|
|
|
(void)cfg_map_get(zoptions, "masters", &obj);
|
|
|
|
} else {
|
|
|
|
const cfg_obj_t *obj2 = NULL;
|
|
|
|
|
|
|
|
/* ...bug if it was set, "masters" must not be. */
|
|
|
|
(void)cfg_map_get(zoptions, "masters", &obj2);
|
|
|
|
if (obj2 != NULL) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'primaries' and 'masters' cannot "
|
|
|
|
"both be used in the same zone");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj == NULL) {
|
2001-07-19 16:29:14 +00:00
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
2020-06-17 02:02:27 -07:00
|
|
|
"zone '%s': missing 'primaries' entry",
|
2010-12-16 09:51:30 +00:00
|
|
|
znamestr);
|
2001-03-01 23:46:49 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2002-04-17 01:23:15 +00:00
|
|
|
} else {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t count;
|
2021-05-07 14:27:25 +02:00
|
|
|
tresult = validate_remotes("primaries", obj, config,
|
|
|
|
&count, logctx, mctx);
|
2003-02-26 06:04:03 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
|
|
|
{
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-02-26 06:04:03 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS && count == 0) {
|
2002-04-17 01:23:15 +00:00
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
2020-06-17 02:02:27 -07:00
|
|
|
"zone '%s': "
|
|
|
|
"empty 'primaries' entry",
|
2010-12-16 09:51:30 +00:00
|
|
|
znamestr);
|
2002-04-17 01:23:15 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2001-12-17 22:56:58 +00:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2021-09-13 17:55:34 -07:00
|
|
|
/*
|
|
|
|
* Warn if *-source and *-source-v6 options specify a port,
|
|
|
|
* and fail if they specify the default listener port.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(sources); i++) {
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, sources[i], &obj);
|
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
(void)cfg_map_get(goptions, sources[i], &obj);
|
|
|
|
}
|
|
|
|
if (obj != NULL) {
|
|
|
|
in_port_t port =
|
|
|
|
isc_sockaddr_getport(cfg_obj_assockaddr(obj));
|
|
|
|
if (port == dnsport) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' cannot specify the "
|
|
|
|
"DNS listener port (%d)",
|
|
|
|
sources[i], port);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else if (port != 0) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"'%s': specifying a port is "
|
|
|
|
"not recommended",
|
|
|
|
sources[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-07 14:27:25 +02:00
|
|
|
/*
|
|
|
|
* Primary and secondary zones that have a "parental-agents" field,
|
|
|
|
* must have a corresponding "parental-agents" clause.
|
|
|
|
*/
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY) {
|
2021-05-07 14:27:25 +02:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "parental-agents", &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
uint32_t count;
|
|
|
|
tresult = validate_remotes("parental-agents", 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 'parental-agents' entry",
|
|
|
|
znamestr);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-09 10:54:51 +02:00
|
|
|
/*
|
|
|
|
* Configuring a mirror zone and disabling recursion at the same time
|
|
|
|
* contradicts the purpose of the former.
|
|
|
|
*/
|
|
|
|
if (ztype == CFG_ZONE_MIRROR &&
|
|
|
|
!check_recursion(config, voptions, goptions, logctx, actx, mctx))
|
|
|
|
{
|
|
|
|
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': mirror zones cannot be used if "
|
|
|
|
"recursion is disabled",
|
|
|
|
znamestr);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
2021-09-13 17:55:34 -07:00
|
|
|
* Primary zones can't have both "allow-update" and "update-policy".
|
2001-03-08 00:55:50 +00:00
|
|
|
*/
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY) {
|
2018-04-17 08:29:14 -07:00
|
|
|
bool signing = false;
|
2009-10-12 20:48:12 +00:00
|
|
|
isc_result_t res1, res2, res3;
|
2014-03-12 21:35:08 -07:00
|
|
|
const cfg_obj_t *au = NULL;
|
2009-10-12 20:48:12 +00:00
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
obj = NULL;
|
2014-03-12 21:35:08 -07:00
|
|
|
res1 = cfg_map_get(zoptions, "allow-update", &au);
|
2001-03-01 23:46:49 +00:00
|
|
|
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",
|
2010-12-16 09:51:30 +00:00
|
|
|
znamestr);
|
2001-03-01 23:46:49 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2014-03-12 21:35:08 -07:00
|
|
|
} else if (res2 == ISC_R_SUCCESS) {
|
|
|
|
res3 = check_update_policy(obj, logctx);
|
|
|
|
if (res3 != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-03-12 21:35:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-07-05 09:42:24 +02:00
|
|
|
* To determine whether dnssec-policy is allowed,
|
2014-03-12 21:35:08 -07:00
|
|
|
* we should also check for allow-update at the
|
|
|
|
* view and options levels.
|
|
|
|
*/
|
|
|
|
if (res1 != ISC_R_SUCCESS && voptions != NULL) {
|
|
|
|
res1 = cfg_map_get(voptions, "allow-update", &au);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-03-12 21:35:08 -07:00
|
|
|
if (res1 != ISC_R_SUCCESS && goptions != NULL) {
|
|
|
|
res1 = cfg_map_get(goptions, "allow-update", &au);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-03-12 21:35:08 -07:00
|
|
|
|
|
|
|
if (res2 == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ddns = true;
|
2014-03-12 21:35:08 -07:00
|
|
|
} else if (res1 == ISC_R_SUCCESS) {
|
|
|
|
dns_acl_t *acl = NULL;
|
|
|
|
res1 = cfg_acl_fromconfig(au, config, logctx, actx,
|
|
|
|
mctx, 0, &acl);
|
|
|
|
if (res1 != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(au, logctx, ISC_LOG_ERROR,
|
|
|
|
"acl expansion failed: %s",
|
|
|
|
isc_result_totext(result));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else if (acl != NULL) {
|
|
|
|
if (!dns_acl_isnone(acl)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ddns = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-03-12 21:35:08 -07:00
|
|
|
dns_acl_detach(&acl);
|
|
|
|
}
|
|
|
|
}
|
2011-10-26 23:46:15 +00:00
|
|
|
|
2011-10-26 20:56:45 +00:00
|
|
|
obj = NULL;
|
|
|
|
res1 = cfg_map_get(zoptions, "inline-signing", &obj);
|
|
|
|
if (res1 == ISC_R_SUCCESS) {
|
|
|
|
signing = cfg_obj_asboolean(obj);
|
2022-12-09 12:22:49 +01:00
|
|
|
} else if (has_dnssecpolicy) {
|
|
|
|
signing = kasp_inlinesigning;
|
2022-06-07 14:46:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (has_dnssecpolicy) {
|
|
|
|
if (!ddns && !signing) {
|
|
|
|
cfg_obj_log(kasp, logctx, ISC_LOG_ERROR,
|
2022-10-05 14:44:09 +02:00
|
|
|
"'inline-signing yes;' must also "
|
|
|
|
"be configured explicitly for "
|
|
|
|
"zones using dnssec-policy%s. See "
|
|
|
|
"https://kb.isc.org/docs/"
|
|
|
|
"dnssec-policy-requires-dynamic-"
|
|
|
|
"dns-or-inline-signing",
|
2022-06-07 14:46:05 +02:00
|
|
|
(ztype == CFG_ZONE_PRIMARY)
|
2022-10-05 14:44:09 +02:00
|
|
|
? " without a configured "
|
|
|
|
"'allow-update' or "
|
|
|
|
"'update-policy'"
|
2022-06-07 14:46:05 +02:00
|
|
|
: "");
|
2020-04-08 13:08:20 +02:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
Introduce dnssec-policy configuration
This commit introduces the initial `dnssec-policy` configuration
statement. It has an initial set of options to deal with signature
and key maintenance.
Add some checks to ensure that dnssec-policy is configured at the
right locations, and that policies referenced to in zone statements
actually exist.
Add some checks that when a user adds the new `dnssec-policy`
configuration, it will no longer contain existing DNSSEC
configuration options. Specifically: `inline-signing`,
`auto-dnssec`, `dnssec-dnskey-kskonly`, `dnssec-secure-to-insecure`,
`update-check-ksk`, `dnssec-update-mode`, `dnskey-sig-validity`,
and `sig-validity-interval`.
Test a good kasp configuration, and some bad configurations.
2019-09-02 16:24:48 +02:00
|
|
|
}
|
|
|
|
|
2008-04-02 02:37:42 +00:00
|
|
|
obj = NULL;
|
|
|
|
res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
|
|
|
|
if (res1 == ISC_R_SUCCESS) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t type = cfg_obj_asuint32(obj);
|
2008-04-02 02:37:42 +00:00
|
|
|
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);
|
2021-09-16 10:30:37 +10:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-04-02 02:37:42 +00:00
|
|
|
}
|
2012-10-26 16:14:59 -07:00
|
|
|
|
|
|
|
obj = NULL;
|
|
|
|
res1 = cfg_map_get(zoptions, "dnssec-loadkeys-interval", &obj);
|
2021-08-25 22:31:18 -07:00
|
|
|
if (res1 == ISC_R_SUCCESS && ztype == CFG_ZONE_SECONDARY &&
|
2022-11-02 19:33:14 +01:00
|
|
|
!signing)
|
|
|
|
{
|
2012-10-26 16:14:59 -07:00
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dnssec-loadkeys-interval: requires "
|
2021-10-05 11:28:24 +02:00
|
|
|
"inline-signing when used in secondary "
|
|
|
|
"zone");
|
2012-10-26 16:14:59 -07:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Check the excessively complicated "dialup" option.
|
|
|
|
*/
|
2021-08-25 22:31:18 -07:00
|
|
|
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY ||
|
2018-01-22 11:00:45 -08:00
|
|
|
ztype == CFG_ZONE_STUB)
|
|
|
|
{
|
2018-12-14 16:29:02 +11:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "dialup", &obj);
|
|
|
|
if (obj != NULL && cfg_obj_isstring(obj)) {
|
|
|
|
const char *str = cfg_obj_asstring(obj);
|
2001-03-01 23:46:49 +00:00
|
|
|
for (i = 0; i < sizeof(dialups) / sizeof(dialups[0]);
|
2022-11-02 19:33:14 +01:00
|
|
|
i++)
|
|
|
|
{
|
2001-03-01 23:46:49 +00:00
|
|
|
if (strcasecmp(dialups[i].name, str) != 0) {
|
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
if ((dialups[i].allowed & ztype) == 0) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"dialup type '%s' is not "
|
|
|
|
"allowed in '%s' "
|
|
|
|
"zone '%s'",
|
2010-12-16 09:51:30 +00:00
|
|
|
str, typestr, znamestr);
|
2001-03-01 23:46:49 +00:00
|
|
|
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 "
|
2010-12-16 09:51:30 +00:00
|
|
|
"'%s'",
|
|
|
|
str, znamestr);
|
2001-03-01 23:46:49 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
/*
|
|
|
|
* Check that forwarding is reasonable.
|
|
|
|
*/
|
2008-03-28 23:47:02 +00:00
|
|
|
obj = NULL;
|
2008-03-28 03:26:39 +00:00
|
|
|
if (root) {
|
|
|
|
if (voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "forwarders", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-18 23:26:50 -08:00
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
(void)cfg_map_get(goptions, "forwarders", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-03-28 03:26:39 +00:00
|
|
|
}
|
2022-12-08 10:57:37 +00:00
|
|
|
if (check_forward(config, zoptions, obj, logctx) != ISC_R_SUCCESS) {
|
2001-03-09 19:07:30 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-09 19:07:30 +00:00
|
|
|
|
2016-03-08 10:11:23 +11:00
|
|
|
/*
|
|
|
|
* Check that a RFC 1918 / ULA reverse zone is not forward first
|
|
|
|
* unless explicitly configured to be so.
|
|
|
|
*/
|
2018-01-22 11:00:45 -08:00
|
|
|
if (ztype == CFG_ZONE_FORWARD && (rfc1918 || ula)) {
|
2016-03-08 10:11:23 +11:00
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "forward", &obj);
|
|
|
|
if (obj == NULL) {
|
|
|
|
/*
|
|
|
|
* Forward mode not explicitly configured.
|
|
|
|
*/
|
|
|
|
if (voptions != NULL) {
|
|
|
|
cfg_map_get(voptions, "forward", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-03-08 10:11:23 +11:00
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
cfg_map_get(goptions, "forward", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-03-08 10:11:23 +11:00
|
|
|
if (obj == NULL ||
|
2022-11-02 19:33:14 +01:00
|
|
|
strcasecmp(cfg_obj_asstring(obj), "first") == 0)
|
|
|
|
{
|
2016-03-08 10:11:23 +11:00
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_WARNING,
|
|
|
|
"inherited 'forward first;' for "
|
|
|
|
"%s zone '%s' - did you want "
|
|
|
|
"'forward only;'?",
|
|
|
|
rfc1918 ? "rfc1918" : "ula",
|
|
|
|
znamestr);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-03-08 10:11:23 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-16 09:51:30 +00:00
|
|
|
/*
|
|
|
|
* Check validity of static stub server addresses.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
(void)cfg_map_get(zoptions, "server-addresses", &obj);
|
2018-01-22 11:00:45 -08:00
|
|
|
if (ztype == CFG_ZONE_STATICSTUB && obj != NULL) {
|
2010-12-16 09:51:30 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
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);
|
2018-01-22 11:00:45 -08:00
|
|
|
if (zname != NULL && ztype == CFG_ZONE_STATICSTUB && obj != NULL) {
|
2010-12-16 09:51:30 +00:00
|
|
|
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);
|
|
|
|
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b2, snamestr, strlen(snamestr));
|
2010-12-16 09:51:30 +00:00
|
|
|
isc_buffer_add(&b2, strlen(snamestr));
|
2018-03-28 14:38:09 +02:00
|
|
|
sname = dns_fixedname_initname(&fixed_sname);
|
2010-12-16 09:51:30 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-20 14:57:03 -08:00
|
|
|
/*
|
|
|
|
* Warn if key-directory doesn't exist
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
2021-06-18 15:35:01 +10:00
|
|
|
(void)cfg_map_get(zoptions, "key-directory", &obj);
|
|
|
|
if (obj == NULL && voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "key-directory", &obj);
|
|
|
|
}
|
|
|
|
if (obj == NULL && goptions != NULL) {
|
|
|
|
(void)cfg_map_get(goptions, "key-directory", &obj);
|
|
|
|
}
|
|
|
|
if (obj != NULL) {
|
2021-05-04 15:35:39 +02:00
|
|
|
dir = cfg_obj_asstring(obj);
|
|
|
|
|
2013-12-20 14:57:03 -08:00
|
|
|
tresult = isc_file_isdirectory(dir);
|
|
|
|
switch (tresult) {
|
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
break;
|
|
|
|
case ISC_R_FILENOTFOUND:
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"key-directory: '%s' does not exist", dir);
|
|
|
|
break;
|
|
|
|
case ISC_R_INVALIDFILE:
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"key-directory: '%s' is not a directory",
|
|
|
|
dir);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
|
|
|
"key-directory: '%s' %s", dir,
|
|
|
|
isc_result_totext(tresult));
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 15:35:39 +02:00
|
|
|
/*
|
|
|
|
* Make sure there is no other zone with the same
|
|
|
|
* key-directory and a different dnssec-policy.
|
|
|
|
*/
|
|
|
|
if (zname != NULL) {
|
|
|
|
char keydirbuf[DNS_NAME_FORMATSIZE + 128];
|
|
|
|
char *tmp = keydirbuf;
|
|
|
|
size_t len = sizeof(keydirbuf);
|
|
|
|
dns_name_format(zname, keydirbuf, sizeof(keydirbuf));
|
|
|
|
len -= strlen(tmp);
|
2022-05-13 19:59:58 -07:00
|
|
|
tmp += strlen(tmp);
|
2021-05-04 15:35:39 +02:00
|
|
|
(void)snprintf(tmp, len, "/%s", (dir == NULL) ? "(null)" : dir);
|
|
|
|
tresult = keydirexist(zconfig, (const char *)keydirbuf,
|
|
|
|
kaspname, keydirs, logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-04 21:51:27 +00:00
|
|
|
/*
|
|
|
|
* Check various options.
|
|
|
|
*/
|
2022-08-25 16:47:34 +10:00
|
|
|
tresult = check_options(zoptions, config, false, logctx, mctx,
|
|
|
|
optlevel_zone);
|
2001-06-04 21:51:27 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-06-04 21:51:27 +00:00
|
|
|
|
2004-11-22 05:03:11 +00:00
|
|
|
/*
|
2022-04-06 11:39:27 +01:00
|
|
|
* If the zone type is rbt then primary/hint zones require file
|
2021-09-13 17:55:34 -07:00
|
|
|
* clauses. If inline-signing is used, then secondary zones require a
|
2021-04-13 16:45:16 +02:00
|
|
|
* file clause as well.
|
2004-11-22 05:03:11 +00:00
|
|
|
*/
|
|
|
|
obj = NULL;
|
2018-04-17 08:29:14 -07:00
|
|
|
dlz = false;
|
2012-12-06 12:39:52 -08:00
|
|
|
tresult = cfg_map_get(zoptions, "dlz", &obj);
|
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
dlz = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-12-06 12:39:52 -08:00
|
|
|
|
|
|
|
obj = NULL;
|
2004-11-22 05:03:11 +00:00
|
|
|
tresult = cfg_map_get(zoptions, "database", &obj);
|
2012-12-06 12:39:52 -08:00
|
|
|
if (dlz && tresult == ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
|
|
|
"zone '%s': cannot specify both 'dlz' "
|
|
|
|
"and 'database'",
|
|
|
|
znamestr);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
} else if (!dlz && (tresult == ISC_R_NOTFOUND ||
|
2004-11-22 05:03:11 +00:00
|
|
|
(tresult == ISC_R_SUCCESS &&
|
2022-04-06 11:39:27 +01:00
|
|
|
strcmp("rbt", cfg_obj_asstring(obj)) == 0)))
|
2012-12-06 12:39:52 -08:00
|
|
|
{
|
2013-02-20 14:01:31 -08:00
|
|
|
isc_result_t res1;
|
2014-09-29 12:10:10 +10:00
|
|
|
const cfg_obj_t *fileobj = NULL;
|
|
|
|
tresult = cfg_map_get(zoptions, "file", &fileobj);
|
2013-02-20 14:01:31 -08:00
|
|
|
obj = NULL;
|
|
|
|
res1 = cfg_map_get(zoptions, "inline-signing", &obj);
|
|
|
|
if ((tresult != ISC_R_SUCCESS &&
|
2021-08-25 22:31:18 -07:00
|
|
|
(ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_HINT ||
|
|
|
|
(ztype == CFG_ZONE_SECONDARY && res1 == ISC_R_SUCCESS &&
|
2018-01-22 11:00:45 -08:00
|
|
|
cfg_obj_asboolean(obj)))))
|
|
|
|
{
|
2004-11-22 05:03:11 +00:00
|
|
|
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
|
2013-02-20 14:01:31 -08:00
|
|
|
"zone '%s': missing 'file' entry",
|
|
|
|
znamestr);
|
2004-11-22 05:03:11 +00:00
|
|
|
result = tresult;
|
2014-09-29 12:10:10 +10:00
|
|
|
} else if (tresult == ISC_R_SUCCESS &&
|
2021-08-25 22:31:18 -07:00
|
|
|
(ztype == CFG_ZONE_SECONDARY ||
|
2021-04-13 16:45:16 +02:00
|
|
|
ztype == CFG_ZONE_MIRROR || ddns ||
|
|
|
|
has_dnssecpolicy))
|
2018-10-09 10:54:51 +02:00
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
tresult = fileexist(fileobj, files, true, logctx);
|
2014-09-29 12:10:10 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-09-29 12:10:10 +10:00
|
|
|
} else if (tresult == ISC_R_SUCCESS &&
|
2021-08-25 22:31:18 -07:00
|
|
|
(ztype == CFG_ZONE_PRIMARY ||
|
|
|
|
ztype == CFG_ZONE_HINT))
|
2018-01-22 11:00:45 -08:00
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
tresult = fileexist(fileobj, files, false, logctx);
|
2014-09-29 12:10:10 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-22 05:03:11 +00:00
|
|
|
}
|
|
|
|
}
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
typedef struct keyalgorithms {
|
|
|
|
const char *name;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint16_t size;
|
2006-01-27 02:35:15 +00:00
|
|
|
} algorithmtable;
|
|
|
|
|
2001-08-03 17:24:11 +00:00
|
|
|
isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
isccfg_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *algobj = NULL;
|
|
|
|
const cfg_obj_t *secretobj = NULL;
|
2001-08-03 17:24:11 +00:00
|
|
|
const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
|
2006-01-27 02:35:15 +00:00
|
|
|
const char *algorithm;
|
|
|
|
int i;
|
|
|
|
size_t len = 0;
|
2009-10-08 23:13:07 +00:00
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t buf;
|
|
|
|
unsigned char secretbuf[1024];
|
2006-01-27 02:35:15 +00:00
|
|
|
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 }
|
|
|
|
};
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)cfg_map_get(key, "algorithm", &algobj);
|
|
|
|
(void)cfg_map_get(key, "secret", &secretobj);
|
2001-08-03 17:24:11 +00:00
|
|
|
if (secretobj == NULL || algobj == NULL) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s' must have both 'secret' and "
|
|
|
|
"'algorithm' defined",
|
|
|
|
keyname);
|
2001-10-25 17:07:21 +00:00
|
|
|
return (ISC_R_FAILURE);
|
2001-08-03 17:24:11 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2009-10-08 23:13:07 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
algorithm = cfg_obj_asstring(algobj);
|
|
|
|
for (i = 0; algorithms[i].name != NULL; i++) {
|
|
|
|
len = strlen(algorithms[i].name);
|
|
|
|
if (strncasecmp(algorithms[i].name, algorithm, len) == 0 &&
|
|
|
|
(algorithm[len] == '\0' ||
|
|
|
|
(algorithms[i].size != 0 && algorithm[len] == '-')))
|
|
|
|
{
|
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
if (algorithms[i].name == NULL) {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"unknown algorithm '%s'", algorithm);
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
if (algorithm[len] == '-') {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint16_t digestbits;
|
2006-01-27 02:35:15 +00:00
|
|
|
result = isc_parse_uint16(&digestbits, algorithm + len + 1, 10);
|
|
|
|
if (result == ISC_R_SUCCESS || result == ISC_R_RANGE) {
|
|
|
|
if (result == ISC_R_RANGE ||
|
2022-11-02 19:33:14 +01:00
|
|
|
digestbits > algorithms[i].size)
|
|
|
|
{
|
2006-01-27 02:35:15 +00:00
|
|
|
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) ||
|
2022-11-02 19:33:14 +01:00
|
|
|
(digestbits < 80U)))
|
|
|
|
{
|
2006-01-27 02:35:15 +00:00
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_WARNING,
|
|
|
|
"key '%s' digest-bits too small "
|
2008-03-28 23:47:02 +00:00
|
|
|
"[<%u]",
|
2006-01-27 02:35:15 +00:00
|
|
|
keyname, algorithms[i].size / 2);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
} else {
|
|
|
|
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"key '%s': unable to parse digest-bits",
|
|
|
|
keyname);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
2001-10-25 17:07:21 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2001-08-03 17:24:11 +00:00
|
|
|
}
|
2001-10-29 06:09:05 +00:00
|
|
|
|
2014-09-29 12:10:10 +10:00
|
|
|
static isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable,
|
2014-09-29 12:10:10 +10:00
|
|
|
isc_log_t *logctx) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
unsigned int line;
|
|
|
|
const char *file;
|
|
|
|
|
|
|
|
result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 0, &symvalue);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
if (writeable) {
|
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"writeable file '%s': already in use: "
|
|
|
|
"%s:%u",
|
|
|
|
cfg_obj_asstring(obj), file, line);
|
|
|
|
return (ISC_R_EXISTS);
|
|
|
|
}
|
|
|
|
result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 2,
|
|
|
|
&symvalue);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"writeable file '%s': already in use: "
|
|
|
|
"%s:%u",
|
|
|
|
cfg_obj_asstring(obj), file, line);
|
|
|
|
return (ISC_R_EXISTS);
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
symvalue.as_cpointer = obj;
|
|
|
|
result = isc_symtab_define(symtab, cfg_obj_asstring(obj),
|
|
|
|
writeable ? 2 : 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2021-05-04 15:35:39 +02:00
|
|
|
static isc_result_t
|
|
|
|
keydirexist(const cfg_obj_t *zcfg, const char *keydir, const char *kaspnamestr,
|
|
|
|
isc_symtab_t *symtab, isc_log_t *logctx, isc_mem_t *mctx) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
char *symkey;
|
|
|
|
|
|
|
|
if (kaspnamestr == NULL || strcmp(kaspnamestr, "none") == 0) {
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = isc_symtab_lookup(symtab, keydir, 0, &symvalue);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
const cfg_obj_t *kasp = NULL;
|
|
|
|
const cfg_obj_t *exist = symvalue.as_cpointer;
|
|
|
|
const char *file = cfg_obj_file(exist);
|
|
|
|
unsigned int line = cfg_obj_line(exist);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Having the same key-directory for the same zone is fine
|
|
|
|
* iff the zone is using the same policy, or has no policy.
|
|
|
|
*/
|
|
|
|
(void)cfg_map_get(cfg_tuple_get(exist, "options"),
|
|
|
|
"dnssec-policy", &kasp);
|
|
|
|
if (kasp == NULL ||
|
|
|
|
strcmp(cfg_obj_asstring(kasp), "none") == 0 ||
|
|
|
|
strcmp(cfg_obj_asstring(kasp), kaspnamestr) == 0)
|
|
|
|
{
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_obj_log(zcfg, logctx, ISC_LOG_ERROR,
|
|
|
|
"key-directory '%s' already in use by zone %s with "
|
|
|
|
"policy %s: %s:%u",
|
|
|
|
keydir,
|
|
|
|
cfg_obj_asstring(cfg_tuple_get(exist, "name")),
|
|
|
|
cfg_obj_asstring(kasp), file, line);
|
|
|
|
return (ISC_R_EXISTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add the new zone plus key-directory.
|
|
|
|
*/
|
|
|
|
symkey = isc_mem_strdup(mctx, keydir);
|
|
|
|
symvalue.as_cpointer = zcfg;
|
|
|
|
result = isc_symtab_define(symtab, symkey, 2, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2001-10-29 06:09:05 +00:00
|
|
|
static isc_result_t
|
2007-08-29 03:23:46 +00:00
|
|
|
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;
|
2001-10-29 06:09:05 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element;
|
2001-10-29 06:09:05 +00:00
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fname);
|
2001-10-29 06:09:05 +00:00
|
|
|
for (element = cfg_list_first(keys); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *key = cfg_listelt_value(element);
|
2007-08-29 03:23:46 +00:00
|
|
|
const char *keyid = cfg_obj_asstring(cfg_map_getname(key));
|
2001-10-29 06:09:05 +00:00
|
|
|
isc_symvalue_t symvalue;
|
2007-08-29 03:23:46 +00:00
|
|
|
isc_buffer_t b;
|
|
|
|
char *keyname;
|
2001-10-29 06:09:05 +00:00
|
|
|
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, keyid, strlen(keyid));
|
2007-08-29 03:23:46 +00:00
|
|
|
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;
|
|
|
|
}
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = isccfg_check_key(key, logctx);
|
2006-01-27 02:35:15 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
return (tresult);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
keyname = isc_mem_strdup(mctx, namebuf);
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = key;
|
2007-08-29 03:23:46 +00:00
|
|
|
tresult = isc_symtab_define(symtab, keyname, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
2001-10-29 06:09:05 +00:00
|
|
|
if (tresult == ISC_R_EXISTS) {
|
2002-03-04 05:27:31 +00:00
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, keyname, 1,
|
|
|
|
&symvalue) ==
|
|
|
|
ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2002-03-04 05:27:31 +00:00
|
|
|
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-10-29 06:09:05 +00:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2002-03-04 05:27:31 +00:00
|
|
|
"key '%s': already exists "
|
|
|
|
"previous definition: %s:%u",
|
2007-08-29 03:23:46 +00:00
|
|
|
keyid, file, line);
|
|
|
|
isc_mem_free(mctx, keyname);
|
2001-10-29 06:09:05 +00:00
|
|
|
result = tresult;
|
2007-08-29 03:23:46 +00:00
|
|
|
} else if (tresult != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, keyname);
|
2001-10-29 06:09:05 +00:00
|
|
|
return (tresult);
|
2007-08-29 03:23:46 +00:00
|
|
|
}
|
2001-10-29 06:09:05 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
2002-02-12 13:17:23 +00:00
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
/*
|
|
|
|
* RNDC keys are not normalised unlike TSIG keys.
|
|
|
|
*
|
|
|
|
* "foo." is different to "foo".
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2007-08-29 03:23:46 +00:00
|
|
|
rndckey_exists(const cfg_obj_t *keylist, const char *keyname) {
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj;
|
|
|
|
const char *str;
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
if (keylist == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
|
|
|
|
for (element = cfg_list_first(keylist); element != NULL;
|
2008-03-28 23:47:02 +00:00
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2007-08-29 03:23:46 +00:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
str = cfg_obj_asstring(cfg_map_getname(obj));
|
|
|
|
if (!strcasecmp(str, keyname)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2007-08-29 03:23:46 +00:00
|
|
|
}
|
|
|
|
|
2021-09-13 17:55:34 -07:00
|
|
|
static struct {
|
|
|
|
const char *v4;
|
|
|
|
const char *v6;
|
|
|
|
} sources[] = { { "transfer-source", "transfer-source-v6" },
|
|
|
|
{ "notify-source", "notify-source-v6" },
|
|
|
|
{ "parental-source", "parental-source-v6" },
|
|
|
|
{ "query-source", "query-source-v6" },
|
|
|
|
{ NULL, NULL } };
|
|
|
|
|
2021-12-01 14:52:31 +11:00
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
isc_result_t (*set)(dns_peer_t *peer, bool newval);
|
|
|
|
} bools[] = {
|
|
|
|
{ "bogus", dns_peer_setbogus },
|
|
|
|
{ "edns", dns_peer_setsupportedns },
|
|
|
|
{ "provide-ixfr", dns_peer_setprovideixfr },
|
|
|
|
{ "request-expire", dns_peer_setrequestexpire },
|
|
|
|
{ "request-ixfr", dns_peer_setrequestixfr },
|
|
|
|
{ "request-nsid", dns_peer_setrequestnsid },
|
|
|
|
{ "send-cookie", dns_peer_setsendcookie },
|
|
|
|
{ "tcp-keepalive", dns_peer_settcpkeepalive },
|
|
|
|
{ "tcp-only", dns_peer_setforcetcp },
|
|
|
|
};
|
|
|
|
|
2002-03-04 05:07:06 +00:00
|
|
|
static isc_result_t
|
2007-08-29 03:23:46 +00:00
|
|
|
check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
2021-12-01 14:52:31 +11:00
|
|
|
isc_symtab_t *symtab, isc_mem_t *mctx, isc_log_t *logctx) {
|
2007-08-29 03:23:46 +00:00
|
|
|
dns_fixedname_t fname;
|
2002-03-04 05:07:06 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2006-02-17 00:24:21 +00:00
|
|
|
isc_result_t tresult;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *e1, *e2;
|
2007-08-29 03:23:46 +00:00
|
|
|
const cfg_obj_t *v1, *v2, *keys;
|
|
|
|
const cfg_obj_t *servers;
|
2005-01-17 00:46:05 +00:00
|
|
|
isc_netaddr_t n1, n2;
|
|
|
|
unsigned int p1, p2;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *obj;
|
2006-02-17 00:24:21 +00:00
|
|
|
char buf[ISC_NETADDR_FORMATSIZE];
|
2007-08-29 03:23:46 +00:00
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
2003-09-25 18:16:50 +00:00
|
|
|
const char *xfr;
|
2007-08-29 03:23:46 +00:00
|
|
|
const char *keyval;
|
|
|
|
isc_buffer_t b;
|
2006-02-17 00:24:21 +00:00
|
|
|
int source;
|
2007-08-29 03:23:46 +00:00
|
|
|
dns_name_t *keyname;
|
|
|
|
|
|
|
|
servers = NULL;
|
|
|
|
if (voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "server", &servers);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
if (servers == NULL) {
|
|
|
|
(void)cfg_map_get(config, "server", &servers);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
if (servers == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
|
|
|
|
for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
|
2021-12-01 14:52:31 +11:00
|
|
|
dns_peer_t *peer = NULL;
|
|
|
|
size_t i;
|
2002-03-04 05:07:06 +00:00
|
|
|
v1 = cfg_listelt_value(e1);
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1);
|
|
|
|
/*
|
|
|
|
* Check that unused bits are zero.
|
|
|
|
*/
|
2006-02-17 00:24:21 +00:00
|
|
|
tresult = isc_netaddr_prefixok(&n1, p1);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
INSIST(tresult == ISC_R_FAILURE);
|
|
|
|
isc_netaddr_format(&n1, buf, sizeof(buf));
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
|
|
|
|
"server '%s/%u': invalid prefix "
|
|
|
|
"(extra bits specified)",
|
|
|
|
buf, p1);
|
2006-02-17 00:24:21 +00:00
|
|
|
result = tresult;
|
2005-01-17 00:46:05 +00:00
|
|
|
}
|
2006-02-17 00:24:21 +00:00
|
|
|
source = 0;
|
|
|
|
do {
|
2021-09-13 17:55:34 -07:00
|
|
|
/*
|
|
|
|
* For a v6 server we can't specify a v4 source,
|
|
|
|
* and vice versa.
|
|
|
|
*/
|
2006-02-17 00:24:21 +00:00
|
|
|
obj = NULL;
|
|
|
|
if (n1.family == AF_INET) {
|
|
|
|
xfr = sources[source].v6;
|
|
|
|
} else {
|
|
|
|
xfr = sources[source].v4;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2006-02-17 00:24:21 +00:00
|
|
|
(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,
|
2007-08-29 03:23:46 +00:00
|
|
|
"server '%s/%u': %s not legal", buf,
|
|
|
|
p1, xfr);
|
2006-02-17 00:24:21 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2021-09-13 17:55:34 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that we aren't using the DNS
|
|
|
|
* listener port (i.e. 53, or whatever was set
|
|
|
|
* as "port" in options) as a source port.
|
|
|
|
*/
|
|
|
|
obj = NULL;
|
|
|
|
if (n1.family == AF_INET) {
|
|
|
|
xfr = sources[source].v4;
|
|
|
|
} else {
|
|
|
|
xfr = sources[source].v6;
|
|
|
|
}
|
|
|
|
(void)cfg_map_get(v1, xfr, &obj);
|
|
|
|
if (obj != NULL) {
|
|
|
|
const isc_sockaddr_t *sa =
|
|
|
|
cfg_obj_assockaddr(obj);
|
|
|
|
in_port_t port = isc_sockaddr_getport(sa);
|
|
|
|
if (port == dnsport) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'%s' cannot specify the "
|
|
|
|
"DNS listener port (%d)",
|
|
|
|
xfr, port);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2006-02-17 00:24:21 +00:00
|
|
|
} while (sources[++source].v4 != NULL);
|
2002-03-04 05:07:06 +00:00
|
|
|
e2 = e1;
|
|
|
|
while ((e2 = cfg_list_next(e2)) != NULL) {
|
|
|
|
v2 = cfg_listelt_value(e2);
|
2005-01-17 00:46:05 +00:00
|
|
|
cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2);
|
|
|
|
if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) {
|
2002-03-04 05:07:06 +00:00
|
|
|
const char *file = cfg_obj_file(v1);
|
|
|
|
unsigned int line = cfg_obj_line(v1);
|
|
|
|
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
|
2006-02-17 00:24:21 +00:00
|
|
|
isc_netaddr_format(&n2, buf, sizeof(buf));
|
2002-03-04 05:07:06 +00:00
|
|
|
cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
|
2005-01-17 00:46:05 +00:00
|
|
|
"server '%s/%u': already exists "
|
2002-03-04 05:07:06 +00:00
|
|
|
"previous definition: %s:%u",
|
2005-01-17 00:46:05 +00:00
|
|
|
buf, p2, file, line);
|
2002-03-04 05:07:06 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
keys = NULL;
|
|
|
|
cfg_map_get(v1, "keys", &keys);
|
|
|
|
if (keys != NULL) {
|
|
|
|
/*
|
|
|
|
* Normalize key name.
|
|
|
|
*/
|
|
|
|
keyval = cfg_obj_asstring(keys);
|
2012-12-08 12:48:57 +11:00
|
|
|
isc_buffer_constinit(&b, keyval, strlen(keyval));
|
2007-08-29 03:23:46 +00:00
|
|
|
isc_buffer_add(&b, strlen(keyval));
|
2018-03-28 14:38:09 +02:00
|
|
|
keyname = dns_fixedname_initname(&fname);
|
2007-08-29 03:23:46 +00:00
|
|
|
tresult = dns_name_fromtext(keyname, &b, dns_rootname,
|
2009-09-01 00:22:28 +00:00
|
|
|
0, NULL);
|
2007-08-29 03:23:46 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2021-12-01 14:52:31 +11:00
|
|
|
(void)dns_peer_newprefix(mctx, &n1, p1, &peer);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(bools); i++) {
|
|
|
|
const cfg_obj_t *opt = NULL;
|
|
|
|
cfg_map_get(v1, bools[i].name, &opt);
|
|
|
|
if (opt != NULL) {
|
|
|
|
tresult = (bools[i].set)(
|
|
|
|
peer, cfg_obj_asboolean(opt));
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(opt, logctx, ISC_LOG_ERROR,
|
|
|
|
"setting server option "
|
|
|
|
"'%s' failed: %s",
|
|
|
|
bools[i].name,
|
|
|
|
isc_result_totext(tresult));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dns_peer_detach(&peer);
|
2002-03-04 05:07:06 +00:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2018-10-03 11:46:06 -07:00
|
|
|
#define ROOT_KSK_STATIC 0x01
|
|
|
|
#define ROOT_KSK_MANAGED 0x02
|
|
|
|
#define ROOT_KSK_ANY 0x03
|
|
|
|
#define ROOT_KSK_2010 0x04
|
|
|
|
#define ROOT_KSK_2017 0x08
|
2018-02-09 12:04:45 +11:00
|
|
|
|
2010-03-04 06:17:01 +00:00
|
|
|
static isc_result_t
|
2019-09-15 23:14:51 -07:00
|
|
|
check_trust_anchor(const cfg_obj_t *key, bool managed, unsigned int *flagsp,
|
|
|
|
isc_log_t *logctx) {
|
|
|
|
const char *str = NULL, *namestr = NULL;
|
2010-03-04 06:17:01 +00:00
|
|
|
dns_fixedname_t fkeyname;
|
2019-09-15 22:15:29 -07:00
|
|
|
dns_name_t *keyname = NULL;
|
2011-03-11 06:11:27 +00:00
|
|
|
isc_buffer_t b;
|
2010-03-04 06:17:01 +00:00
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
2019-12-02 09:29:02 +01:00
|
|
|
uint32_t rdata1, rdata2, rdata3;
|
2019-09-15 23:14:51 -07:00
|
|
|
unsigned char data[4096];
|
2019-09-15 22:15:29 -07:00
|
|
|
const char *atstr = NULL;
|
|
|
|
enum {
|
|
|
|
INIT_DNSKEY,
|
|
|
|
STATIC_DNSKEY,
|
|
|
|
INIT_DS,
|
|
|
|
STATIC_DS,
|
|
|
|
TRUSTED
|
|
|
|
} anchortype;
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
/*
|
|
|
|
* The 2010 and 2017 IANA root keys - these are used below
|
2019-09-15 23:14:51 -07:00
|
|
|
* to check the contents of trusted, initial and
|
|
|
|
* static trust anchor configurations.
|
2019-09-15 22:15:29 -07:00
|
|
|
*/
|
|
|
|
static const unsigned char root_ksk_2010[] = {
|
|
|
|
0x03, 0x01, 0x00, 0x01, 0xa8, 0x00, 0x20, 0xa9, 0x55, 0x66,
|
|
|
|
0xba, 0x42, 0xe8, 0x86, 0xbb, 0x80, 0x4c, 0xda, 0x84, 0xe4,
|
|
|
|
0x7e, 0xf5, 0x6d, 0xbd, 0x7a, 0xec, 0x61, 0x26, 0x15, 0x55,
|
|
|
|
0x2c, 0xec, 0x90, 0x6d, 0x21, 0x16, 0xd0, 0xef, 0x20, 0x70,
|
|
|
|
0x28, 0xc5, 0x15, 0x54, 0x14, 0x4d, 0xfe, 0xaf, 0xe7, 0xc7,
|
|
|
|
0xcb, 0x8f, 0x00, 0x5d, 0xd1, 0x82, 0x34, 0x13, 0x3a, 0xc0,
|
|
|
|
0x71, 0x0a, 0x81, 0x18, 0x2c, 0xe1, 0xfd, 0x14, 0xad, 0x22,
|
|
|
|
0x83, 0xbc, 0x83, 0x43, 0x5f, 0x9d, 0xf2, 0xf6, 0x31, 0x32,
|
|
|
|
0x51, 0x93, 0x1a, 0x17, 0x6d, 0xf0, 0xda, 0x51, 0xe5, 0x4f,
|
|
|
|
0x42, 0xe6, 0x04, 0x86, 0x0d, 0xfb, 0x35, 0x95, 0x80, 0x25,
|
|
|
|
0x0f, 0x55, 0x9c, 0xc5, 0x43, 0xc4, 0xff, 0xd5, 0x1c, 0xbe,
|
|
|
|
0x3d, 0xe8, 0xcf, 0xd0, 0x67, 0x19, 0x23, 0x7f, 0x9f, 0xc4,
|
|
|
|
0x7e, 0xe7, 0x29, 0xda, 0x06, 0x83, 0x5f, 0xa4, 0x52, 0xe8,
|
|
|
|
0x25, 0xe9, 0xa1, 0x8e, 0xbc, 0x2e, 0xcb, 0xcf, 0x56, 0x34,
|
|
|
|
0x74, 0x65, 0x2c, 0x33, 0xcf, 0x56, 0xa9, 0x03, 0x3b, 0xcd,
|
|
|
|
0xf5, 0xd9, 0x73, 0x12, 0x17, 0x97, 0xec, 0x80, 0x89, 0x04,
|
|
|
|
0x1b, 0x6e, 0x03, 0xa1, 0xb7, 0x2d, 0x0a, 0x73, 0x5b, 0x98,
|
|
|
|
0x4e, 0x03, 0x68, 0x73, 0x09, 0x33, 0x23, 0x24, 0xf2, 0x7c,
|
|
|
|
0x2d, 0xba, 0x85, 0xe9, 0xdb, 0x15, 0xe8, 0x3a, 0x01, 0x43,
|
|
|
|
0x38, 0x2e, 0x97, 0x4b, 0x06, 0x21, 0xc1, 0x8e, 0x62, 0x5e,
|
|
|
|
0xce, 0xc9, 0x07, 0x57, 0x7d, 0x9e, 0x7b, 0xad, 0xe9, 0x52,
|
|
|
|
0x41, 0xa8, 0x1e, 0xbb, 0xe8, 0xa9, 0x01, 0xd4, 0xd3, 0x27,
|
|
|
|
0x6e, 0x40, 0xb1, 0x14, 0xc0, 0xa2, 0xe6, 0xfc, 0x38, 0xd1,
|
|
|
|
0x9c, 0x2e, 0x6a, 0xab, 0x02, 0x64, 0x4b, 0x28, 0x13, 0xf5,
|
|
|
|
0x75, 0xfc, 0x21, 0x60, 0x1e, 0x0d, 0xee, 0x49, 0xcd, 0x9e,
|
|
|
|
0xe9, 0x6a, 0x43, 0x10, 0x3e, 0x52, 0x4d, 0x62, 0x87, 0x3d
|
|
|
|
};
|
|
|
|
static const unsigned char root_ksk_2017[] = {
|
|
|
|
0x03, 0x01, 0x00, 0x01, 0xac, 0xff, 0xb4, 0x09, 0xbc, 0xc9,
|
|
|
|
0x39, 0xf8, 0x31, 0xf7, 0xa1, 0xe5, 0xec, 0x88, 0xf7, 0xa5,
|
|
|
|
0x92, 0x55, 0xec, 0x53, 0x04, 0x0b, 0xe4, 0x32, 0x02, 0x73,
|
|
|
|
0x90, 0xa4, 0xce, 0x89, 0x6d, 0x6f, 0x90, 0x86, 0xf3, 0xc5,
|
|
|
|
0xe1, 0x77, 0xfb, 0xfe, 0x11, 0x81, 0x63, 0xaa, 0xec, 0x7a,
|
|
|
|
0xf1, 0x46, 0x2c, 0x47, 0x94, 0x59, 0x44, 0xc4, 0xe2, 0xc0,
|
|
|
|
0x26, 0xbe, 0x5e, 0x98, 0xbb, 0xcd, 0xed, 0x25, 0x97, 0x82,
|
|
|
|
0x72, 0xe1, 0xe3, 0xe0, 0x79, 0xc5, 0x09, 0x4d, 0x57, 0x3f,
|
|
|
|
0x0e, 0x83, 0xc9, 0x2f, 0x02, 0xb3, 0x2d, 0x35, 0x13, 0xb1,
|
|
|
|
0x55, 0x0b, 0x82, 0x69, 0x29, 0xc8, 0x0d, 0xd0, 0xf9, 0x2c,
|
|
|
|
0xac, 0x96, 0x6d, 0x17, 0x76, 0x9f, 0xd5, 0x86, 0x7b, 0x64,
|
|
|
|
0x7c, 0x3f, 0x38, 0x02, 0x9a, 0xbd, 0xc4, 0x81, 0x52, 0xeb,
|
|
|
|
0x8f, 0x20, 0x71, 0x59, 0xec, 0xc5, 0xd2, 0x32, 0xc7, 0xc1,
|
|
|
|
0x53, 0x7c, 0x79, 0xf4, 0xb7, 0xac, 0x28, 0xff, 0x11, 0x68,
|
|
|
|
0x2f, 0x21, 0x68, 0x1b, 0xf6, 0xd6, 0xab, 0xa5, 0x55, 0x03,
|
|
|
|
0x2b, 0xf6, 0xf9, 0xf0, 0x36, 0xbe, 0xb2, 0xaa, 0xa5, 0xb3,
|
|
|
|
0x77, 0x8d, 0x6e, 0xeb, 0xfb, 0xa6, 0xbf, 0x9e, 0xa1, 0x91,
|
|
|
|
0xbe, 0x4a, 0xb0, 0xca, 0xea, 0x75, 0x9e, 0x2f, 0x77, 0x3a,
|
|
|
|
0x1f, 0x90, 0x29, 0xc7, 0x3e, 0xcb, 0x8d, 0x57, 0x35, 0xb9,
|
|
|
|
0x32, 0x1d, 0xb0, 0x85, 0xf1, 0xb8, 0xe2, 0xd8, 0x03, 0x8f,
|
|
|
|
0xe2, 0x94, 0x19, 0x92, 0x54, 0x8c, 0xee, 0x0d, 0x67, 0xdd,
|
|
|
|
0x45, 0x47, 0xe1, 0x1d, 0xd6, 0x3a, 0xf9, 0xc9, 0xfc, 0x1c,
|
|
|
|
0x54, 0x66, 0xfb, 0x68, 0x4c, 0xf0, 0x09, 0xd7, 0x19, 0x7c,
|
|
|
|
0x2c, 0xf7, 0x9e, 0x79, 0x2a, 0xb5, 0x01, 0xe6, 0xa8, 0xa1,
|
|
|
|
0xca, 0x51, 0x9a, 0xf2, 0xcb, 0x9b, 0x5f, 0x63, 0x67, 0xe9,
|
|
|
|
0x4c, 0x0d, 0x47, 0x50, 0x24, 0x51, 0x35, 0x7b, 0xe1, 0xb5
|
|
|
|
};
|
2019-09-15 23:14:51 -07:00
|
|
|
static const unsigned char root_ds_1_2017[] = {
|
|
|
|
0xae, 0x1e, 0xa5, 0xb9, 0x74, 0xd4, 0xc8, 0x58, 0xb7, 0x40,
|
|
|
|
0xbd, 0x03, 0xe3, 0xce, 0xd7, 0xeb, 0xfc, 0xbd, 0x17, 0x24
|
|
|
|
};
|
|
|
|
static const unsigned char root_ds_2_2017[] = {
|
|
|
|
0xe0, 0x6d, 0x44, 0xb8, 0x0b, 0x8f, 0x1d, 0x39,
|
|
|
|
0xa9, 0x5c, 0x0b, 0x0d, 0x7c, 0x65, 0xd0, 0x84,
|
|
|
|
0x58, 0xe8, 0x80, 0x40, 0x9b, 0xbc, 0x68, 0x34,
|
|
|
|
0x57, 0x10, 0x42, 0x37, 0xc7, 0xf8, 0xec, 0x8D
|
|
|
|
};
|
2019-09-15 22:15:29 -07:00
|
|
|
|
|
|
|
/* if DNSKEY, flags; if DS, key tag */
|
2019-12-02 09:29:02 +01:00
|
|
|
rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1"));
|
2019-09-15 22:15:29 -07:00
|
|
|
|
|
|
|
/* if DNSKEY, protocol; if DS, algorithm */
|
2019-12-02 09:29:02 +01:00
|
|
|
rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2"));
|
2019-09-15 22:15:29 -07:00
|
|
|
|
|
|
|
/* if DNSKEY, algorithm; if DS, digest type */
|
2019-12-02 09:29:02 +01:00
|
|
|
rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3"));
|
2011-03-11 17:19:05 +00:00
|
|
|
|
2019-09-15 23:14:51 -07:00
|
|
|
namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
keyname = dns_fixedname_initname(&fkeyname);
|
2019-09-15 23:14:51 -07:00
|
|
|
isc_buffer_constinit(&b, namestr, strlen(namestr));
|
|
|
|
isc_buffer_add(&b, strlen(namestr));
|
2011-03-11 06:11:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-03-04 06:17:01 +00:00
|
|
|
if (managed) {
|
2019-09-15 22:15:29 -07:00
|
|
|
atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
|
2010-03-04 23:50:34 +00:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
if (strcasecmp(atstr, "static-key") == 0) {
|
|
|
|
managed = false;
|
|
|
|
anchortype = STATIC_DNSKEY;
|
|
|
|
} else if (strcasecmp(atstr, "static-ds") == 0) {
|
2018-08-15 16:59:45 -07:00
|
|
|
managed = false;
|
2019-09-15 22:15:29 -07:00
|
|
|
anchortype = STATIC_DS;
|
|
|
|
} else if (strcasecmp(atstr, "initial-key") == 0) {
|
|
|
|
anchortype = INIT_DNSKEY;
|
|
|
|
} else if (strcasecmp(atstr, "initial-ds") == 0) {
|
|
|
|
anchortype = INIT_DS;
|
|
|
|
} else {
|
2010-03-04 23:50:34 +00:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-09-15 22:15:29 -07:00
|
|
|
"key '%s': "
|
2010-03-04 23:50:34 +00:00
|
|
|
"invalid initialization method '%s'",
|
2019-09-15 23:14:51 -07:00
|
|
|
namestr, atstr);
|
2010-03-04 23:50:34 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2019-09-15 22:15:29 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't interpret the trust anchor, so
|
|
|
|
* we skip all other checks.
|
|
|
|
*/
|
|
|
|
goto cleanup;
|
2010-03-04 06:17:01 +00:00
|
|
|
}
|
2019-09-15 22:15:29 -07:00
|
|
|
} else {
|
|
|
|
atstr = "trusted-key";
|
|
|
|
anchortype = TRUSTED;
|
2010-03-04 06:17:01 +00:00
|
|
|
}
|
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
switch (anchortype) {
|
|
|
|
case INIT_DNSKEY:
|
|
|
|
case STATIC_DNSKEY:
|
|
|
|
case TRUSTED:
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 > 0xffff) {
|
2019-09-15 22:15:29 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"flags too big: %u", rdata1);
|
2019-09-15 22:15:29 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 & DNS_KEYFLAG_REVOKE) {
|
2019-09-15 22:15:29 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
|
|
|
|
"key flags revoke bit set");
|
|
|
|
}
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata2 > 0xff) {
|
2019-09-15 22:15:29 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"protocol too big: %u", rdata2);
|
2019-09-15 22:15:29 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata3 > 0xff) {
|
2019-09-15 22:15:29 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"algorithm too big: %u\n", rdata3);
|
2019-09-15 22:15:29 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2019-09-15 23:14:51 -07:00
|
|
|
isc_buffer_init(&b, data, sizeof(data));
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2019-09-15 23:14:51 -07:00
|
|
|
str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
|
|
|
|
tresult = isc_base64_decodestring(str, &b);
|
2018-10-03 11:46:06 -07:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
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);
|
2018-10-03 11:46:06 -07:00
|
|
|
|
2019-12-02 09:29:02 +01:00
|
|
|
if ((rdata3 == DST_ALG_RSASHA1) && r.length > 1 &&
|
2019-09-15 22:15:29 -07:00
|
|
|
r.base[0] == 1 && r.base[1] == 3)
|
|
|
|
{
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
|
|
|
|
"%s '%s' has a weak exponent",
|
2019-09-15 23:14:51 -07:00
|
|
|
atstr, namestr);
|
2019-09-15 22:15:29 -07:00
|
|
|
}
|
2018-02-09 12:04:45 +11:00
|
|
|
}
|
2018-10-03 11:46:06 -07:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
if (result == ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
dns_name_equal(keyname, dns_rootname))
|
|
|
|
{
|
2019-09-15 22:15:29 -07:00
|
|
|
/*
|
|
|
|
* Flag any use of a root key, regardless of content.
|
|
|
|
*/
|
|
|
|
*flagsp |= (managed ? ROOT_KSK_MANAGED
|
|
|
|
: ROOT_KSK_STATIC);
|
|
|
|
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 == 257 && rdata2 == 3 && rdata3 == 8 &&
|
2019-09-15 22:15:29 -07:00
|
|
|
(isc_buffer_usedlength(&b) ==
|
|
|
|
sizeof(root_ksk_2010)) &&
|
2019-09-15 23:14:51 -07:00
|
|
|
memcmp(data, root_ksk_2010,
|
2019-09-15 22:15:29 -07:00
|
|
|
sizeof(root_ksk_2010)) == 0)
|
|
|
|
{
|
2019-09-15 23:14:51 -07:00
|
|
|
*flagsp |= ROOT_KSK_2010;
|
2019-09-15 22:15:29 -07:00
|
|
|
}
|
|
|
|
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 == 257 && rdata2 == 3 && rdata3 == 8 &&
|
2019-09-15 22:15:29 -07:00
|
|
|
(isc_buffer_usedlength(&b) ==
|
|
|
|
sizeof(root_ksk_2017)) &&
|
2019-09-15 23:14:51 -07:00
|
|
|
memcmp(data, root_ksk_2017,
|
2019-09-15 22:15:29 -07:00
|
|
|
sizeof(root_ksk_2017)) == 0)
|
|
|
|
{
|
2019-09-15 23:14:51 -07:00
|
|
|
*flagsp |= ROOT_KSK_2017;
|
2019-09-15 22:15:29 -07:00
|
|
|
}
|
2018-02-09 12:04:45 +11:00
|
|
|
}
|
2019-09-15 22:15:29 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INIT_DS:
|
|
|
|
case STATIC_DS:
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 > 0xffff) {
|
2019-09-15 23:14:51 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"key tag too big: %u", rdata1);
|
2019-09-15 23:14:51 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata2 > 0xff) {
|
2019-09-15 23:14:51 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"algorithm too big: %u\n", rdata2);
|
2019-09-15 23:14:51 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata3 > 0xff) {
|
2019-09-15 23:14:51 -07:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2019-12-02 09:29:02 +01:00
|
|
|
"digest type too big: %u", rdata3);
|
2019-09-15 23:14:51 -07:00
|
|
|
result = ISC_R_RANGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_init(&b, data, sizeof(data));
|
|
|
|
|
|
|
|
str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
|
|
|
|
tresult = isc_hex_decodestring(str, &b);
|
|
|
|
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR, "%s",
|
|
|
|
isc_result_totext(tresult));
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
if (result == ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
dns_name_equal(keyname, dns_rootname))
|
|
|
|
{
|
2019-09-15 23:14:51 -07:00
|
|
|
/*
|
|
|
|
* Flag any use of a root key, regardless of content.
|
|
|
|
*/
|
|
|
|
*flagsp |= (managed ? ROOT_KSK_MANAGED
|
|
|
|
: ROOT_KSK_STATIC);
|
|
|
|
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 == 20326 && rdata2 == 8 && rdata3 == 1 &&
|
2019-09-15 23:14:51 -07:00
|
|
|
(isc_buffer_usedlength(&b) ==
|
|
|
|
sizeof(root_ds_1_2017)) &&
|
|
|
|
memcmp(data, root_ds_1_2017,
|
|
|
|
sizeof(root_ds_1_2017)) == 0)
|
|
|
|
{
|
|
|
|
*flagsp |= ROOT_KSK_2017;
|
|
|
|
}
|
|
|
|
|
2019-12-02 09:29:02 +01:00
|
|
|
if (rdata1 == 20326 && rdata2 == 8 && rdata3 == 2 &&
|
2019-09-15 23:14:51 -07:00
|
|
|
(isc_buffer_usedlength(&b) ==
|
|
|
|
sizeof(root_ds_2_2017)) &&
|
|
|
|
memcmp(data, root_ds_2_2017,
|
|
|
|
sizeof(root_ds_2_2017)) == 0)
|
|
|
|
{
|
|
|
|
*flagsp |= ROOT_KSK_2017;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2018-02-09 12:04:45 +11:00
|
|
|
}
|
2018-10-03 11:46:06 -07:00
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
cleanup:
|
2010-03-04 06:17:01 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2019-02-07 15:10:41 -08:00
|
|
|
static isc_result_t
|
2019-06-10 16:43:56 -07:00
|
|
|
record_static_keys(isc_symtab_t *symtab, isc_mem_t *mctx,
|
|
|
|
const cfg_obj_t *keylist, isc_log_t *logctx,
|
|
|
|
bool autovalidation) {
|
2018-11-02 18:57:23 -07:00
|
|
|
isc_result_t result, ret = ISC_R_SUCCESS;
|
|
|
|
const cfg_listelt_t *elt;
|
2019-02-07 15:10:41 -08:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
2019-06-10 16:43:56 -07:00
|
|
|
char namebuf[DNS_NAME_FORMATSIZE], *p = NULL;
|
2019-02-07 15:10:41 -08:00
|
|
|
|
|
|
|
name = dns_fixedname_initname(&fixed);
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
for (elt = cfg_list_first(keylist); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
const char *initmethod;
|
|
|
|
const cfg_obj_t *init = NULL;
|
|
|
|
const cfg_obj_t *obj = cfg_listelt_value(elt);
|
|
|
|
const char *str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
2023-08-15 17:41:01 -07:00
|
|
|
result = dns_name_fromstring(name, str, dns_rootname, 0, NULL);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
init = cfg_tuple_get(obj, "anchortype");
|
2018-11-02 18:57:23 -07:00
|
|
|
if (!cfg_obj_isvoid(init)) {
|
|
|
|
initmethod = cfg_obj_asstring(init);
|
|
|
|
if (strcasecmp(initmethod, "initial-key") == 0) {
|
|
|
|
/* initializing key, skip it */
|
|
|
|
continue;
|
|
|
|
}
|
2019-09-15 22:15:29 -07:00
|
|
|
if (strcasecmp(initmethod, "initial-ds") == 0) {
|
|
|
|
/* initializing key, skip it */
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
symvalue.as_cpointer = obj;
|
2019-06-10 16:43:56 -07:00
|
|
|
p = isc_mem_strdup(mctx, namebuf);
|
|
|
|
result = isc_symtab_define(symtab, p, 1, symvalue,
|
2018-11-02 18:57:23 -07:00
|
|
|
isc_symexists_reject);
|
2019-06-10 16:43:56 -07:00
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
isc_mem_free(mctx, p);
|
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, p);
|
|
|
|
ret = result;
|
2018-11-02 18:57:23 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (autovalidation && dns_name_equal(name, dns_rootname)) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
2019-09-15 22:15:29 -07:00
|
|
|
"static trust anchor for root zone "
|
2018-11-02 18:57:23 -07:00
|
|
|
"cannot be used with "
|
|
|
|
"'dnssec-validation auto'.");
|
|
|
|
ret = ISC_R_FAILURE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
check_initializing_keys(isc_symtab_t *symtab, const cfg_obj_t *keylist,
|
|
|
|
isc_log_t *logctx) {
|
|
|
|
isc_result_t result, ret = ISC_R_SUCCESS;
|
|
|
|
const cfg_listelt_t *elt;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
|
|
|
|
name = dns_fixedname_initname(&fixed);
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(keylist); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
const cfg_obj_t *obj = cfg_listelt_value(elt);
|
|
|
|
const cfg_obj_t *init = NULL;
|
|
|
|
const char *str;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
2019-09-15 22:15:29 -07:00
|
|
|
init = cfg_tuple_get(obj, "anchortype");
|
2018-11-02 18:57:23 -07:00
|
|
|
if (cfg_obj_isvoid(init) ||
|
2019-09-15 22:15:29 -07:00
|
|
|
strcasecmp(cfg_obj_asstring(init), "static-key") == 0 ||
|
|
|
|
strcasecmp(cfg_obj_asstring(init), "static-ds") == 0)
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
/* static key, skip it */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
|
2023-08-15 17:41:01 -07:00
|
|
|
result = dns_name_fromstring(name, str, dns_rootname, 0, NULL);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
result = isc_symtab_lookup(symtab, namebuf, 1, &symvalue);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
const char *file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
unsigned int line = cfg_obj_line(symvalue.as_cpointer);
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
|
|
|
}
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"static and initializing keys "
|
|
|
|
"cannot be used for the "
|
|
|
|
"same domain. "
|
|
|
|
"static key defined at "
|
|
|
|
"%s:%u",
|
|
|
|
file, line);
|
|
|
|
|
|
|
|
ret = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2019-09-16 13:56:31 -07:00
|
|
|
static isc_result_t
|
|
|
|
record_ds_keys(isc_symtab_t *symtab, isc_mem_t *mctx,
|
|
|
|
const cfg_obj_t *keylist) {
|
|
|
|
isc_result_t result, ret = ISC_R_SUCCESS;
|
|
|
|
const cfg_listelt_t *elt;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE], *p = NULL;
|
|
|
|
|
|
|
|
name = dns_fixedname_initname(&fixed);
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(keylist); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2019-09-16 13:56:31 -07:00
|
|
|
const char *initmethod;
|
|
|
|
const cfg_obj_t *init = NULL;
|
|
|
|
const cfg_obj_t *obj = cfg_listelt_value(elt);
|
|
|
|
const char *str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
|
2023-08-15 17:41:01 -07:00
|
|
|
result = dns_name_fromstring(name, str, dns_rootname, 0, NULL);
|
2019-09-16 13:56:31 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
init = cfg_tuple_get(obj, "anchortype");
|
|
|
|
if (!cfg_obj_isvoid(init)) {
|
|
|
|
initmethod = cfg_obj_asstring(init);
|
|
|
|
if (strcasecmp(initmethod, "initial-key") == 0 ||
|
|
|
|
strcasecmp(initmethod, "static-key") == 0)
|
|
|
|
{
|
|
|
|
/* Key-style key, skip it */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
symvalue.as_cpointer = obj;
|
|
|
|
p = isc_mem_strdup(mctx, namebuf);
|
|
|
|
result = isc_symtab_define(symtab, p, 1, symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
isc_mem_free(mctx, p);
|
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_mem_free(mctx, p);
|
|
|
|
ret = result;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
/*
|
|
|
|
* Check for conflicts between static and initialiizing keys.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2019-12-04 11:06:40 +01:00
|
|
|
check_ta_conflicts(const cfg_obj_t *global_ta, const cfg_obj_t *view_ta,
|
2018-11-02 18:57:23 -07:00
|
|
|
const cfg_obj_t *global_tkeys, const cfg_obj_t *view_tkeys,
|
|
|
|
bool autovalidation, isc_mem_t *mctx, isc_log_t *logctx) {
|
|
|
|
isc_result_t result, tresult;
|
|
|
|
const cfg_listelt_t *elt = NULL;
|
|
|
|
const cfg_obj_t *keylist = NULL;
|
2019-09-16 13:56:31 -07:00
|
|
|
isc_symtab_t *statictab = NULL, *dstab = NULL;
|
|
|
|
|
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &statictab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-11-02 18:57:23 -07:00
|
|
|
|
2019-09-16 13:56:31 -07:00
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &dstab);
|
2019-02-07 15:10:41 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
/*
|
|
|
|
* First we record all the static keys (i.e., old-style
|
2019-12-04 11:06:40 +01:00
|
|
|
* trusted-keys and trust-anchors configured with "static-key"),
|
2019-09-16 13:56:31 -07:00
|
|
|
* and all the DS-style trust anchors.
|
2018-11-02 18:57:23 -07:00
|
|
|
*/
|
2019-12-04 11:06:40 +01:00
|
|
|
for (elt = cfg_list_first(global_ta); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = record_static_keys(statictab, mctx, keylist, logctx,
|
2018-11-02 18:57:23 -07:00
|
|
|
autovalidation);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2019-09-16 13:56:31 -07:00
|
|
|
|
|
|
|
tresult = record_ds_keys(dstab, mctx, keylist);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2019-02-07 15:10:41 -08:00
|
|
|
|
2019-12-04 11:06:40 +01:00
|
|
|
for (elt = cfg_list_first(view_ta); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = record_static_keys(statictab, mctx, keylist, logctx,
|
2018-11-02 18:57:23 -07:00
|
|
|
autovalidation);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2019-02-07 15:10:41 -08:00
|
|
|
}
|
2019-09-16 13:56:31 -07:00
|
|
|
|
|
|
|
tresult = record_ds_keys(dstab, mctx, keylist);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2019-02-07 15:10:41 -08:00
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
for (elt = cfg_list_first(global_tkeys); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = record_static_keys(statictab, mctx, keylist, logctx,
|
2018-11-02 18:57:23 -07:00
|
|
|
autovalidation);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
2019-02-07 15:10:41 -08:00
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
for (elt = cfg_list_first(view_tkeys); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = record_static_keys(statictab, mctx, keylist, logctx,
|
2018-11-02 18:57:23 -07:00
|
|
|
autovalidation);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
2019-02-07 15:10:41 -08:00
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
/*
|
|
|
|
* Next, ensure that there's no conflict between the
|
2020-01-14 11:17:30 -08:00
|
|
|
* static keys and the trust-anchors configured with "initial-key".
|
2018-11-02 18:57:23 -07:00
|
|
|
*/
|
2019-12-04 11:06:40 +01:00
|
|
|
for (elt = cfg_list_first(global_ta); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = check_initializing_keys(statictab, keylist, logctx);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
|
|
|
|
2019-12-04 11:06:40 +01:00
|
|
|
for (elt = cfg_list_first(view_ta); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keylist = cfg_listelt_value(elt);
|
2019-09-16 13:56:31 -07:00
|
|
|
tresult = check_initializing_keys(statictab, keylist, logctx);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2019-02-07 15:10:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2019-09-16 13:56:31 -07:00
|
|
|
if (statictab != NULL) {
|
|
|
|
isc_symtab_destroy(&statictab);
|
|
|
|
}
|
|
|
|
if (dstab != NULL) {
|
|
|
|
isc_symtab_destroy(&dstab);
|
2019-02-07 15:10:41 -08:00
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2018-03-09 15:11:51 +05:30
|
|
|
typedef enum { special_zonetype_rpz, special_zonetype_catz } special_zonetype_t;
|
|
|
|
|
2016-12-27 08:59:07 +11:00
|
|
|
static isc_result_t
|
|
|
|
check_rpz_catz(const char *rpz_catz, const cfg_obj_t *rpz_obj,
|
2018-03-09 15:11:51 +05:30
|
|
|
const char *viewname, isc_symtab_t *symtab, isc_log_t *logctx,
|
|
|
|
special_zonetype_t specialzonetype) {
|
2016-12-27 08:59:07 +11:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj, *nameobj, *zoneobj;
|
|
|
|
const char *zonename, *zonetype;
|
|
|
|
const char *forview = " for view ";
|
|
|
|
isc_symvalue_t value;
|
|
|
|
isc_result_t result, tresult;
|
2017-06-13 13:06:47 +10:00
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name;
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
2018-03-09 14:45:14 +05:30
|
|
|
unsigned int num_zones = 0;
|
2016-12-27 08:59:07 +11:00
|
|
|
|
|
|
|
if (viewname == NULL) {
|
|
|
|
viewname = "";
|
|
|
|
forview = "";
|
|
|
|
}
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2016-12-27 08:59:07 +11:00
|
|
|
obj = cfg_tuple_get(rpz_obj, "zone list");
|
2018-03-09 14:45:14 +05:30
|
|
|
|
2016-12-27 08:59:07 +11:00
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
2018-03-09 14:45:14 +05:30
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2016-12-27 08:59:07 +11:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
nameobj = cfg_tuple_get(obj, "zone name");
|
|
|
|
zonename = cfg_obj_asstring(nameobj);
|
|
|
|
zonetype = "";
|
2017-06-13 13:06:47 +10:00
|
|
|
|
2018-03-09 15:11:51 +05:30
|
|
|
if (specialzonetype == special_zonetype_rpz) {
|
|
|
|
if (++num_zones > 64) {
|
|
|
|
cfg_obj_log(nameobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"more than 64 response policy "
|
|
|
|
"zones in view '%s'",
|
|
|
|
viewname);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(name, zonename, dns_rootname, 0,
|
|
|
|
NULL);
|
2017-06-13 13:06:47 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(nameobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", zonename);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-06-13 13:06:47 +10:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
tresult = isc_symtab_lookup(symtab, namebuf, 3, &value);
|
2016-12-27 08:59:07 +11:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
|
|
|
obj = NULL;
|
|
|
|
zoneobj = value.as_cpointer;
|
|
|
|
if (zoneobj != NULL && cfg_obj_istuple(zoneobj)) {
|
|
|
|
zoneobj = cfg_tuple_get(zoneobj, "options");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
if (zoneobj != NULL && cfg_obj_ismap(zoneobj)) {
|
|
|
|
(void)cfg_map_get(zoneobj, "type", &obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
if (obj != NULL) {
|
|
|
|
zonetype = cfg_obj_asstring(obj);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
}
|
2017-12-15 01:47:05 -08:00
|
|
|
if (strcasecmp(zonetype, "primary") != 0 &&
|
|
|
|
strcasecmp(zonetype, "master") != 0 &&
|
|
|
|
strcasecmp(zonetype, "secondary") != 0 &&
|
|
|
|
strcasecmp(zonetype, "slave") != 0)
|
|
|
|
{
|
2016-12-27 08:59:07 +11:00
|
|
|
cfg_obj_log(nameobj, logctx, ISC_LOG_ERROR,
|
2021-10-05 11:28:24 +02:00
|
|
|
"%s '%s'%s%s is not a primary or secondary "
|
|
|
|
"zone",
|
2016-12-27 08:59:07 +11:00
|
|
|
rpz_catz, zonename, forview, viewname);
|
2017-06-13 13:06:47 +10:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2022-08-26 14:11:47 +00:00
|
|
|
static isc_result_t
|
|
|
|
check_rpz(const cfg_obj_t *rpz_obj, isc_log_t *logctx) {
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj, *nameobj, *edeobj;
|
|
|
|
const char *zonename;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name = dns_fixedname_initname(&fixed);
|
|
|
|
|
|
|
|
obj = cfg_tuple_get(rpz_obj, "zone list");
|
|
|
|
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
nameobj = cfg_tuple_get(obj, "zone name");
|
|
|
|
zonename = cfg_obj_asstring(nameobj);
|
|
|
|
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(name, zonename, dns_rootname, 0,
|
|
|
|
NULL);
|
2022-08-26 14:11:47 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", zonename);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
edeobj = cfg_tuple_get(obj, "ede");
|
|
|
|
if (edeobj != NULL && cfg_obj_isstring(edeobj)) {
|
|
|
|
const char *str = cfg_obj_asstring(edeobj);
|
|
|
|
|
|
|
|
if (dns_rpz_str2ede(str) == UINT16_MAX) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"unsupported EDE type '%s'", str);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2021-09-03 00:56:47 +00:00
|
|
|
static isc_result_t
|
2021-09-22 15:21:45 +10:00
|
|
|
check_catz(const cfg_obj_t *catz_obj, const char *viewname, isc_mem_t *mctx,
|
|
|
|
isc_log_t *logctx) {
|
2021-09-03 00:56:47 +00:00
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *obj, *nameobj, *primariesobj;
|
|
|
|
const char *zonename;
|
|
|
|
const char *forview = " for view ";
|
2021-09-22 15:21:45 +10:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
dns_name_t *name = dns_fixedname_initname(&fixed);
|
2021-09-03 00:56:47 +00:00
|
|
|
|
|
|
|
if (viewname == NULL) {
|
|
|
|
viewname = "";
|
|
|
|
forview = "";
|
|
|
|
}
|
|
|
|
|
2021-09-22 15:21:45 +10:00
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
2021-09-03 00:56:47 +00:00
|
|
|
|
|
|
|
obj = cfg_tuple_get(catz_obj, "zone list");
|
|
|
|
|
|
|
|
for (element = cfg_list_first(obj); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2021-09-22 15:21:45 +10:00
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
|
2021-09-03 00:56:47 +00:00
|
|
|
obj = cfg_listelt_value(element);
|
|
|
|
nameobj = cfg_tuple_get(obj, "zone name");
|
|
|
|
zonename = cfg_obj_asstring(nameobj);
|
|
|
|
|
2023-08-15 17:41:01 -07:00
|
|
|
tresult = dns_name_fromstring(name, zonename, dns_rootname, 0,
|
|
|
|
NULL);
|
2021-09-22 15:21:45 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"bad domain name '%s'", zonename);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
2023-09-20 12:53:35 +10:00
|
|
|
tresult = exists(nameobj, namebuf, 1, symtab,
|
|
|
|
"catalog zone '%s': already added here %s:%u",
|
|
|
|
logctx, mctx);
|
2021-09-22 15:21:45 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-09-03 00:56:47 +00:00
|
|
|
primariesobj = cfg_tuple_get(obj, "default-primaries");
|
|
|
|
if (primariesobj != NULL && cfg_obj_istuple(primariesobj)) {
|
|
|
|
primariesobj = cfg_tuple_get(obj, "default-masters");
|
|
|
|
if (primariesobj != NULL &&
|
2022-11-02 19:33:14 +01:00
|
|
|
cfg_obj_istuple(primariesobj))
|
|
|
|
{
|
2021-09-03 00:56:47 +00:00
|
|
|
cfg_obj_log(nameobj, logctx, ISC_LOG_ERROR,
|
|
|
|
"catalog zone '%s'%s%s: "
|
|
|
|
"'default-primaries' and "
|
|
|
|
"'default-masters' can not be both "
|
|
|
|
"defined",
|
|
|
|
zonename, forview, viewname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-22 15:21:45 +10:00
|
|
|
if (symtab != NULL) {
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
}
|
|
|
|
|
2021-09-03 00:56:47 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2018-12-03 15:30:02 +01:00
|
|
|
/*%
|
|
|
|
* Data structure used for the 'callback_data' argument to check_one_plugin().
|
|
|
|
*/
|
|
|
|
struct check_one_plugin_data {
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_log_t *lctx;
|
|
|
|
cfg_aclconfctx_t *actx;
|
|
|
|
isc_result_t *check_result;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* A callback for the cfg_pluginlist_foreach() call in check_viewconf() below.
|
|
|
|
* Since the point is to check configuration of all plugins even when
|
|
|
|
* processing some of them fails, always return ISC_R_SUCCESS and indicate any
|
|
|
|
* check failures through the 'check_result' variable passed in via the
|
|
|
|
* 'callback_data' structure.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
|
|
|
const char *plugin_path, const char *parameters,
|
|
|
|
void *callback_data) {
|
|
|
|
struct check_one_plugin_data *data = callback_data;
|
2019-02-12 15:59:54 +01:00
|
|
|
char full_path[PATH_MAX];
|
2018-12-03 15:30:02 +01:00
|
|
|
isc_result_t result;
|
|
|
|
|
2019-02-12 15:59:54 +01:00
|
|
|
result = ns_plugin_expandpath(plugin_path, full_path,
|
|
|
|
sizeof(full_path));
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, data->lctx, ISC_LOG_ERROR,
|
|
|
|
"%s: plugin check failed: "
|
|
|
|
"unable to get full plugin path: %s",
|
|
|
|
plugin_path, isc_result_totext(result));
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = ns_plugin_check(full_path, parameters, config,
|
2018-12-03 15:30:02 +01:00
|
|
|
cfg_obj_file(obj), cfg_obj_line(obj),
|
|
|
|
data->mctx, data->lctx, data->actx);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(obj, data->lctx, ISC_LOG_ERROR,
|
|
|
|
"%s: plugin check failed: %s", full_path,
|
2019-02-12 15:59:54 +01:00
|
|
|
isc_result_totext(result));
|
2018-12-03 15:30:02 +01:00
|
|
|
*data->check_result = result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2019-10-21 11:08:06 +11:00
|
|
|
static isc_result_t
|
|
|
|
check_dnstap(const cfg_obj_t *voptions, const cfg_obj_t *config,
|
|
|
|
isc_log_t *logctx) {
|
|
|
|
#ifdef HAVE_DNSTAP
|
|
|
|
const cfg_obj_t *options = NULL;
|
|
|
|
const cfg_obj_t *obj = NULL;
|
|
|
|
|
|
|
|
if (config != NULL) {
|
|
|
|
(void)cfg_map_get(config, "options", &options);
|
|
|
|
}
|
|
|
|
if (options != NULL) {
|
|
|
|
(void)cfg_map_get(options, "dnstap-output", &obj);
|
|
|
|
}
|
|
|
|
if (obj == NULL) {
|
|
|
|
if (voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "dnstap", &obj);
|
|
|
|
}
|
|
|
|
if (options != NULL && obj == NULL) {
|
|
|
|
(void)cfg_map_get(options, "dnstap", &obj);
|
|
|
|
}
|
|
|
|
if (obj != NULL) {
|
|
|
|
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
|
|
|
"'dnstap-output' must be set if 'dnstap' "
|
|
|
|
"is set");
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
#else /* ifdef HAVE_DNSTAP */
|
|
|
|
UNUSED(voptions);
|
|
|
|
UNUSED(config);
|
|
|
|
UNUSED(logctx);
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
#endif /* ifdef HAVE_DNSTAP */
|
|
|
|
}
|
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
static isc_result_t
|
2006-02-28 02:39:52 +00:00
|
|
|
check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
2007-03-29 06:36:31 +00:00
|
|
|
const char *viewname, dns_rdataclass_t vclass,
|
2022-08-25 16:47:34 +10:00
|
|
|
isc_symtab_t *files, isc_symtab_t *keydirs, unsigned int flags,
|
2023-03-22 16:57:54 -07:00
|
|
|
isc_symtab_t *inview, isc_log_t *logctx, isc_mem_t *mctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zones = NULL;
|
2018-11-02 18:57:23 -07:00
|
|
|
const cfg_obj_t *view_tkeys = NULL, *global_tkeys = NULL;
|
|
|
|
const cfg_obj_t *view_mkeys = NULL, *global_mkeys = NULL;
|
2019-12-04 11:06:40 +01:00
|
|
|
const cfg_obj_t *view_ta = NULL, *global_ta = NULL;
|
2018-11-02 18:57:23 -07:00
|
|
|
const cfg_obj_t *check_keys[2] = { NULL, NULL };
|
|
|
|
const cfg_obj_t *keys = NULL;
|
2010-03-04 06:17:01 +00:00
|
|
|
const cfg_listelt_t *element, *element2;
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2001-03-03 23:09:23 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-09 19:07:30 +00:00
|
|
|
isc_result_t tresult = ISC_R_SUCCESS;
|
2011-06-17 07:05:02 +00:00
|
|
|
cfg_aclconfctx_t *actx = NULL;
|
2006-03-10 05:00:23 +00:00
|
|
|
const cfg_obj_t *obj;
|
2011-05-07 05:55:17 +00:00
|
|
|
const cfg_obj_t *options = NULL;
|
2016-12-27 08:59:07 +11:00
|
|
|
const cfg_obj_t *opts = NULL;
|
2018-11-30 15:32:03 -08:00
|
|
|
const cfg_obj_t *plugin_list = NULL;
|
2019-02-07 15:10:41 -08:00
|
|
|
bool autovalidation = false;
|
2018-11-02 18:57:23 -07:00
|
|
|
unsigned int tflags = 0, dflags = 0;
|
|
|
|
int i;
|
2022-08-25 16:47:34 +10:00
|
|
|
bool check_plugins = (flags & BIND_CHECK_PLUGINS) != 0;
|
|
|
|
bool check_algorithms = (flags & BIND_CHECK_ALGORITHMS) != 0;
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2011-05-07 05:55:17 +00:00
|
|
|
/*
|
|
|
|
* Get global options block
|
|
|
|
*/
|
|
|
|
(void)cfg_map_get(config, "options", &options);
|
|
|
|
|
2016-12-27 08:59:07 +11:00
|
|
|
/*
|
|
|
|
* The most relevant options for this view
|
|
|
|
*/
|
|
|
|
if (voptions != NULL) {
|
|
|
|
opts = voptions;
|
|
|
|
} else {
|
|
|
|
opts = options;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
/*
|
|
|
|
* Check that all zone statements are syntactically correct and
|
|
|
|
* there are no duplicate zones.
|
|
|
|
*/
|
2011-11-30 04:27:17 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 1000, freekey, mctx, false, &symtab);
|
2001-03-09 19:07:30 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-03-08 00:55:50 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-08 00:55:50 +00:00
|
|
|
|
2011-06-17 07:05:02 +00:00
|
|
|
cfg_aclconfctx_create(mctx, &actx);
|
2005-09-12 02:04:41 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL) {
|
|
|
|
(void)cfg_map_get(voptions, "zone", &zones);
|
2001-10-29 06:09:05 +00:00
|
|
|
} else {
|
|
|
|
(void)cfg_map_get(config, "zone", &zones);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-09-20 15:17:07 +00:00
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
for (element = cfg_list_first(zones); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zone = cfg_listelt_value(element);
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
tresult = check_zoneconf(zone, voptions, config, symtab, files,
|
2021-05-04 15:35:39 +02:00
|
|
|
keydirs, inview, viewname, vclass,
|
2023-03-22 16:57:54 -07:00
|
|
|
actx, logctx, mctx);
|
2001-09-20 15:17:07 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-03 23:09:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-27 08:59:07 +11:00
|
|
|
/*
|
|
|
|
* Check that the response-policy and catalog-zones options
|
|
|
|
* refer to zones that exist.
|
|
|
|
*/
|
|
|
|
if (opts != NULL) {
|
|
|
|
obj = NULL;
|
2018-03-09 15:11:51 +05:30
|
|
|
if ((cfg_map_get(opts, "response-policy", &obj) ==
|
|
|
|
ISC_R_SUCCESS) &&
|
|
|
|
(check_rpz_catz("response-policy zone", obj, viewname,
|
|
|
|
symtab, logctx,
|
|
|
|
special_zonetype_rpz) != ISC_R_SUCCESS))
|
|
|
|
{
|
2016-12-27 08:59:07 +11:00
|
|
|
result = ISC_R_FAILURE;
|
2018-03-09 15:11:51 +05:30
|
|
|
}
|
|
|
|
|
2016-12-27 08:59:07 +11:00
|
|
|
obj = NULL;
|
2018-03-09 15:11:51 +05:30
|
|
|
if ((cfg_map_get(opts, "catalog-zones", &obj) ==
|
|
|
|
ISC_R_SUCCESS) &&
|
|
|
|
(check_rpz_catz("catalog zone", obj, viewname, symtab,
|
|
|
|
logctx,
|
|
|
|
special_zonetype_catz) != ISC_R_SUCCESS))
|
|
|
|
{
|
2016-12-27 08:59:07 +11:00
|
|
|
result = ISC_R_FAILURE;
|
2018-03-09 15:11:51 +05:30
|
|
|
}
|
2016-12-27 08:59:07 +11:00
|
|
|
}
|
|
|
|
|
2022-08-26 14:11:47 +00:00
|
|
|
/*
|
|
|
|
* Check response-policy configuration.
|
|
|
|
*/
|
|
|
|
if (opts != NULL) {
|
|
|
|
obj = NULL;
|
|
|
|
if ((cfg_map_get(opts, "response-policy", &obj) ==
|
|
|
|
ISC_R_SUCCESS) &&
|
|
|
|
(check_rpz(obj, logctx) != ISC_R_SUCCESS))
|
|
|
|
{
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-03 00:56:47 +00:00
|
|
|
/*
|
|
|
|
* Check catalog-zones configuration.
|
|
|
|
*/
|
|
|
|
if (opts != NULL) {
|
|
|
|
obj = NULL;
|
|
|
|
if ((cfg_map_get(opts, "catalog-zones", &obj) ==
|
|
|
|
ISC_R_SUCCESS) &&
|
2021-09-22 15:21:45 +10:00
|
|
|
(check_catz(obj, viewname, mctx, logctx) != ISC_R_SUCCESS))
|
2021-09-03 00:56:47 +00:00
|
|
|
{
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 00:55:50 +00:00
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
|
2001-03-09 19:07:30 +00:00
|
|
|
/*
|
|
|
|
* Check that forwarding is reasonable.
|
|
|
|
*/
|
2022-12-08 10:57:37 +00:00
|
|
|
if (opts != NULL &&
|
|
|
|
check_forward(config, opts, NULL, logctx) != ISC_R_SUCCESS)
|
2016-12-27 08:59:07 +11:00
|
|
|
{
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
|
2012-08-16 13:53:47 +10:00
|
|
|
/*
|
|
|
|
* Check non-zero options at the global and view levels.
|
|
|
|
*/
|
|
|
|
if (options != NULL && check_nonzero(options, logctx) != ISC_R_SUCCESS)
|
|
|
|
{
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-08-16 13:53:47 +10:00
|
|
|
if (voptions != NULL &&
|
2022-11-02 19:33:14 +01:00
|
|
|
check_nonzero(voptions, logctx) != ISC_R_SUCCESS)
|
|
|
|
{
|
2012-08-16 13:53:47 +10:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-08-16 13:53:47 +10:00
|
|
|
|
2003-01-16 03:59:28 +00:00
|
|
|
/*
|
|
|
|
* Check that dual-stack-servers is reasonable.
|
|
|
|
*/
|
2016-12-27 08:59:07 +11:00
|
|
|
if (opts != NULL && check_dual_stack(opts, logctx) != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-09 19:07:30 +00:00
|
|
|
|
2002-03-08 00:54:48 +00:00
|
|
|
/*
|
|
|
|
* Check that rrset-order is reasonable.
|
|
|
|
*/
|
2016-12-27 08:59:07 +11:00
|
|
|
if (opts != NULL && check_order(opts, logctx) != ISC_R_SUCCESS) {
|
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
/*
|
|
|
|
* Check that all key statements are syntactically correct and
|
|
|
|
* there are no duplicate keys.
|
|
|
|
*/
|
2011-11-30 04:27:17 +00:00
|
|
|
tresult = isc_symtab_create(mctx, 1000, freekey, mctx, false, &symtab);
|
2007-08-29 03:23:46 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2012-08-10 20:15:59 -07:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
|
|
|
|
(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) {
|
2012-08-10 20:15:59 -07:00
|
|
|
result = tresult;
|
|
|
|
goto cleanup;
|
2007-08-29 03:23:46 +00:00
|
|
|
}
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2005-01-11 03:46:11 +00:00
|
|
|
if (voptions != NULL) {
|
2007-08-29 03:23:46 +00:00
|
|
|
keys = NULL;
|
|
|
|
(void)cfg_map_get(voptions, "key", &keys);
|
|
|
|
tresult = check_keylist(keys, symtab, mctx, logctx);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
2002-03-04 05:07:06 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2007-08-29 03:23:46 +00:00
|
|
|
} else if (tresult != ISC_R_SUCCESS) {
|
2012-08-10 20:15:59 -07:00
|
|
|
result = tresult;
|
|
|
|
goto cleanup;
|
2007-08-29 03:23:46 +00:00
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-29 03:23:46 +00:00
|
|
|
/*
|
|
|
|
* Global servers can refer to keys in views.
|
|
|
|
*/
|
2021-12-01 14:52:31 +11:00
|
|
|
if (check_servers(config, voptions, symtab, mctx, logctx) !=
|
2022-11-02 19:33:14 +01:00
|
|
|
ISC_R_SUCCESS)
|
|
|
|
{
|
2007-08-29 03:23:46 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-29 03:23:46 +00:00
|
|
|
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
|
2010-03-04 06:17:01 +00:00
|
|
|
/*
|
2018-11-02 18:57:23 -07:00
|
|
|
* Load all DNSSEC keys.
|
2010-03-04 06:17:01 +00:00
|
|
|
*/
|
2018-10-03 11:46:06 -07:00
|
|
|
if (voptions != NULL) {
|
2018-11-02 18:57:23 -07:00
|
|
|
(void)cfg_map_get(voptions, "trusted-keys", &view_tkeys);
|
2019-12-04 11:06:40 +01:00
|
|
|
(void)cfg_map_get(voptions, "trust-anchors", &view_ta);
|
2018-11-02 18:57:23 -07:00
|
|
|
(void)cfg_map_get(voptions, "managed-keys", &view_mkeys);
|
2018-10-03 11:46:06 -07:00
|
|
|
}
|
2018-11-02 18:57:23 -07:00
|
|
|
(void)cfg_map_get(config, "trusted-keys", &global_tkeys);
|
2019-12-04 11:06:40 +01:00
|
|
|
(void)cfg_map_get(config, "trust-anchors", &global_ta);
|
2018-11-02 18:57:23 -07:00
|
|
|
(void)cfg_map_get(config, "managed-keys", &global_mkeys);
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
/*
|
|
|
|
* Check trusted-keys.
|
|
|
|
*/
|
|
|
|
check_keys[0] = view_tkeys;
|
|
|
|
check_keys[1] = global_tkeys;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (check_keys[i] != NULL) {
|
2022-08-25 16:47:34 +10:00
|
|
|
unsigned int taflags = 0;
|
2018-11-02 18:57:23 -07:00
|
|
|
|
|
|
|
for (element = cfg_list_first(check_keys[i]);
|
|
|
|
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);
|
2019-09-15 23:14:51 -07:00
|
|
|
tresult = check_trust_anchor(
|
2022-08-25 16:47:34 +10:00
|
|
|
obj, false, &taflags, logctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
2018-10-03 11:46:06 -07:00
|
|
|
}
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
if ((taflags & ROOT_KSK_STATIC) != 0) {
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(check_keys[i], logctx,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"trusted-keys entry for the root "
|
|
|
|
"zone WILL FAIL after key "
|
2019-12-04 11:06:40 +01:00
|
|
|
"rollover - use trust-anchors "
|
2019-09-15 23:14:51 -07:00
|
|
|
"with initial-key "
|
|
|
|
"or initial-ds instead.");
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2018-02-09 12:04:45 +11:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
tflags |= taflags;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2018-10-05 12:00:42 -07:00
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
/*
|
|
|
|
* Check dnssec/managed-keys. (Only one or the other can be used.)
|
|
|
|
*/
|
|
|
|
if ((view_mkeys != NULL || global_mkeys != NULL) &&
|
2019-12-04 11:06:40 +01:00
|
|
|
(view_ta != NULL || global_ta != NULL))
|
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
keys = (view_mkeys != NULL) ? view_mkeys : global_mkeys;
|
2018-10-05 12:00:42 -07:00
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
|
|
|
|
"use of managed-keys is not allowed when "
|
2019-12-04 11:06:40 +01:00
|
|
|
"trust-anchors is also in use");
|
2018-11-02 18:57:23 -07:00
|
|
|
result = ISC_R_FAILURE;
|
2018-10-05 12:00:42 -07:00
|
|
|
}
|
|
|
|
|
2019-12-04 11:06:40 +01:00
|
|
|
if (view_ta == NULL && global_ta == NULL) {
|
|
|
|
view_ta = view_mkeys;
|
|
|
|
global_ta = global_mkeys;
|
2018-10-05 12:00:42 -07:00
|
|
|
}
|
|
|
|
|
2019-12-04 11:06:40 +01:00
|
|
|
check_keys[0] = view_ta;
|
|
|
|
check_keys[1] = global_ta;
|
2018-11-02 18:57:23 -07:00
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (check_keys[i] != NULL) {
|
2022-08-25 16:47:34 +10:00
|
|
|
unsigned int taflags = 0;
|
2018-10-05 12:00:42 -07:00
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
for (element = cfg_list_first(check_keys[i]);
|
|
|
|
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);
|
2019-09-15 23:14:51 -07:00
|
|
|
tresult = check_trust_anchor(
|
2022-08-25 16:47:34 +10:00
|
|
|
obj, true, &taflags, logctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-10-05 12:00:42 -07:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
if ((taflags & ROOT_KSK_STATIC) != 0) {
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(check_keys[i], logctx,
|
|
|
|
ISC_LOG_WARNING,
|
2019-09-15 23:14:51 -07:00
|
|
|
"static entry for the root "
|
2018-11-02 18:57:23 -07:00
|
|
|
"zone WILL FAIL after key "
|
2019-12-04 11:06:40 +01:00
|
|
|
"rollover - use trust-anchors "
|
2019-09-15 23:14:51 -07:00
|
|
|
"with initial-key "
|
|
|
|
"or initial-ds instead.");
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2010-03-04 06:17:01 +00:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
if ((taflags & ROOT_KSK_2010) != 0 &&
|
|
|
|
(taflags & ROOT_KSK_2017) == 0)
|
2022-11-02 19:33:14 +01:00
|
|
|
{
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(check_keys[i], logctx,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"initial-key entry for the root "
|
|
|
|
"zone uses the 2010 key without "
|
|
|
|
"the updated 2017 key");
|
2018-10-03 11:46:06 -07:00
|
|
|
}
|
2011-11-07 00:14:11 +00:00
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
dflags |= taflags;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2018-02-09 12:04:45 +11:00
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
if ((tflags & ROOT_KSK_ANY) != 0 && (dflags & ROOT_KSK_ANY) != 0) {
|
2019-12-04 11:06:40 +01:00
|
|
|
keys = (view_ta != NULL) ? view_ta : global_ta;
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(keys, logctx, ISC_LOG_WARNING,
|
2019-12-04 11:06:40 +01:00
|
|
|
"both trusted-keys and trust-anchors "
|
2018-10-05 12:00:42 -07:00
|
|
|
"for the root zone are present");
|
2018-02-09 12:04:45 +11:00
|
|
|
}
|
|
|
|
|
2018-11-02 18:57:23 -07:00
|
|
|
if ((dflags & ROOT_KSK_ANY) == ROOT_KSK_ANY) {
|
2019-12-04 11:06:40 +01:00
|
|
|
keys = (view_ta != NULL) ? view_ta : global_ta;
|
2018-11-02 18:57:23 -07:00
|
|
|
cfg_obj_log(keys, logctx, ISC_LOG_WARNING,
|
2019-09-15 23:14:51 -07:00
|
|
|
"both initial and static entries for the "
|
2018-10-03 11:46:06 -07:00
|
|
|
"root zone are present");
|
|
|
|
}
|
|
|
|
|
2019-02-07 15:10:41 -08:00
|
|
|
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 && !cfg_obj_isboolean(obj)) {
|
|
|
|
autovalidation = true;
|
|
|
|
}
|
|
|
|
|
2019-12-04 11:06:40 +01:00
|
|
|
tresult = check_ta_conflicts(global_ta, view_ta, global_tkeys,
|
2019-02-07 15:10:41 -08:00
|
|
|
view_tkeys, autovalidation, mctx, logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
2010-03-04 06:17:01 +00:00
|
|
|
/*
|
|
|
|
* Check options.
|
|
|
|
*/
|
2018-11-02 18:57:23 -07:00
|
|
|
if (voptions != NULL) {
|
2022-08-25 16:47:34 +10:00
|
|
|
tresult = check_options(voptions, NULL, check_algorithms,
|
|
|
|
logctx, mctx, optlevel_view);
|
2018-11-02 18:57:23 -07:00
|
|
|
} else {
|
2022-08-25 16:47:34 +10:00
|
|
|
tresult = check_options(config, config, check_algorithms,
|
|
|
|
logctx, mctx, optlevel_config);
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-06-04 21:51:27 +00:00
|
|
|
result = tresult;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2001-06-04 21:51:27 +00:00
|
|
|
|
2019-10-21 11:08:06 +11:00
|
|
|
tresult = check_dnstap(voptions, config, logctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
|
2011-06-17 07:05:02 +00:00
|
|
|
tresult = check_viewacls(actx, voptions, config, logctx, mctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2005-01-11 03:46:11 +00:00
|
|
|
result = tresult;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2005-01-11 03:46:11 +00:00
|
|
|
|
2011-06-17 07:05:02 +00:00
|
|
|
tresult = check_recursionacls(actx, voptions, viewname, config, logctx,
|
2007-03-29 06:36:31 +00:00
|
|
|
mctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2010-06-22 04:03:38 +00:00
|
|
|
result = tresult;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2010-12-08 02:46:17 +00:00
|
|
|
|
2011-06-17 07:05:02 +00:00
|
|
|
tresult = check_dns64(actx, voptions, config, logctx, mctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2007-03-29 06:36:31 +00:00
|
|
|
result = tresult;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2007-03-29 06:36:31 +00:00
|
|
|
|
2016-08-08 23:52:40 +10:00
|
|
|
tresult = check_ratelimit(actx, voptions, config, logctx, mctx);
|
2018-11-02 18:57:23 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2016-08-08 23:52:40 +10:00
|
|
|
result = tresult;
|
2018-11-02 18:57:23 -07:00
|
|
|
}
|
2016-08-08 23:52:40 +10:00
|
|
|
|
2018-11-02 23:28:25 -07:00
|
|
|
/*
|
2018-11-30 15:32:03 -08:00
|
|
|
* Load plugins.
|
2018-11-02 23:28:25 -07:00
|
|
|
*/
|
2018-11-30 15:32:03 -08:00
|
|
|
if (check_plugins) {
|
2018-11-02 23:28:25 -07:00
|
|
|
if (voptions != NULL) {
|
2018-11-30 15:32:03 -08:00
|
|
|
(void)cfg_map_get(voptions, "plugin", &plugin_list);
|
2018-11-02 23:28:25 -07:00
|
|
|
} else {
|
2018-11-30 15:32:03 -08:00
|
|
|
(void)cfg_map_get(config, "plugin", &plugin_list);
|
2018-11-02 23:28:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2018-12-03 15:30:02 +01:00
|
|
|
struct check_one_plugin_data check_one_plugin_data = {
|
|
|
|
.mctx = mctx,
|
|
|
|
.lctx = logctx,
|
|
|
|
.actx = actx,
|
|
|
|
.check_result = &tresult,
|
|
|
|
};
|
|
|
|
|
|
|
|
(void)cfg_pluginlist_foreach(config, plugin_list, logctx,
|
|
|
|
check_one_plugin,
|
|
|
|
&check_one_plugin_data);
|
2018-11-02 23:28:25 -07:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-10 20:15:59 -07:00
|
|
|
cleanup:
|
|
|
|
if (symtab != NULL) {
|
|
|
|
isc_symtab_destroy(&symtab);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-08-10 20:15:59 -07:00
|
|
|
if (actx != NULL) {
|
|
|
|
cfg_aclconfctx_detach(&actx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-09-12 02:04:41 +00:00
|
|
|
|
2001-03-03 23:09:23 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2004-11-09 21:24:20 +00:00
|
|
|
static const char *default_channels[] = { "default_syslog", "default_stderr",
|
|
|
|
"default_debug", "null", NULL };
|
|
|
|
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_logging(const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *categories = NULL;
|
|
|
|
const cfg_obj_t *category;
|
|
|
|
const cfg_obj_t *channels = NULL;
|
|
|
|
const cfg_obj_t *channel;
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_listelt_t *delement;
|
2004-11-09 21:24:20 +00:00
|
|
|
const char *channelname;
|
|
|
|
const char *catname;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *fileobj = NULL;
|
2008-03-28 23:47:02 +00:00
|
|
|
const cfg_obj_t *syslogobj = NULL;
|
|
|
|
const cfg_obj_t *nullobj = NULL;
|
|
|
|
const cfg_obj_t *stderrobj = NULL;
|
|
|
|
const cfg_obj_t *logobj = NULL;
|
2004-11-09 21:24:20 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_result_t tresult;
|
|
|
|
isc_symtab_t *symtab = NULL;
|
|
|
|
isc_symvalue_t symvalue;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
(void)cfg_map_get(config, "logging", &logobj);
|
|
|
|
if (logobj == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
result = isc_symtab_create(mctx, 100, NULL, NULL, false, &symtab);
|
2004-11-09 21:24:20 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = NULL;
|
2004-11-09 21:24:20 +00:00
|
|
|
for (i = 0; default_channels[i] != NULL; i++) {
|
|
|
|
tresult = isc_symtab_define(symtab, default_channels[i], 1,
|
|
|
|
symvalue, isc_symexists_replace);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
if (syslogobj != NULL) {
|
|
|
|
i++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
if (nullobj != NULL) {
|
|
|
|
i++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
if (stderrobj != NULL) {
|
|
|
|
i++;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
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;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cfg_map_get(logobj, "category", &categories);
|
|
|
|
|
|
|
|
for (element = cfg_list_first(categories); element != NULL;
|
2008-03-28 23:47:02 +00:00
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
2004-11-09 21:24:20 +00:00
|
|
|
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,
|
2008-03-29 23:47:08 +00:00
|
|
|
&symvalue);
|
2004-11-09 21:24:20 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
|
|
|
|
"undefined channel: '%s'",
|
|
|
|
channelname);
|
|
|
|
result = tresult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
return (result);
|
|
|
|
}
|
2001-03-03 23:09:23 +00:00
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist,
|
|
|
|
isc_log_t *logctx) {
|
2007-08-29 03:23:46 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *control_keylist;
|
|
|
|
const cfg_listelt_t *element;
|
|
|
|
const cfg_obj_t *key;
|
2007-08-29 03:23:46 +00:00
|
|
|
const char *keyval;
|
2008-03-28 23:47:02 +00:00
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
control_keylist = cfg_tuple_get(control, "keys");
|
|
|
|
if (cfg_obj_isvoid(control_keylist)) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
for (element = cfg_list_first(control_keylist); element != NULL;
|
|
|
|
element = cfg_list_next(element))
|
|
|
|
{
|
|
|
|
key = cfg_listelt_value(element);
|
2007-08-29 03:23:46 +00:00
|
|
|
keyval = cfg_obj_asstring(key);
|
|
|
|
|
|
|
|
if (!rndckey_exists(keylist, keyval)) {
|
2005-02-23 01:09:23 +00:00
|
|
|
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
|
2007-08-29 03:23:46 +00:00
|
|
|
"unknown key '%s'", keyval);
|
|
|
|
result = ISC_R_NOTFOUND;
|
2005-02-23 01:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2022-12-16 10:39:15 +00:00
|
|
|
check_controls(const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
|
2005-02-23 01:09:23 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS, tresult;
|
2011-06-17 07:05:02 +00:00
|
|
|
cfg_aclconfctx_t *actx = NULL;
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *element, *element2;
|
|
|
|
const cfg_obj_t *allow;
|
|
|
|
const cfg_obj_t *control;
|
|
|
|
const cfg_obj_t *controls;
|
|
|
|
const cfg_obj_t *controlslist = NULL;
|
|
|
|
const cfg_obj_t *inetcontrols;
|
|
|
|
const cfg_obj_t *unixcontrols;
|
|
|
|
const cfg_obj_t *keylist = NULL;
|
2023-09-20 12:53:35 +10:00
|
|
|
const cfg_obj_t *obj = NULL;
|
2005-02-23 01:09:23 +00:00
|
|
|
const char *path;
|
|
|
|
dns_acl_t *acl = NULL;
|
2023-09-20 12:53:35 +10:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(config, "controls", &controlslist);
|
|
|
|
if (controlslist == NULL) {
|
|
|
|
return (ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(config, "key", &keylist);
|
|
|
|
|
2011-06-17 07:05:02 +00:00
|
|
|
cfg_aclconfctx_create(mctx, &actx);
|
2005-09-12 02:04:41 +00:00
|
|
|
|
2023-09-20 12:53:35 +10:00
|
|
|
result = isc_symtab_create(mctx, 100, freekey, mctx, true, &symtab);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
/*
|
|
|
|
* INET: Check allow clause.
|
2023-09-12 08:39:12 +02:00
|
|
|
* UNIX: Not supported.
|
2005-02-23 01:09:23 +00:00
|
|
|
*/
|
|
|
|
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))
|
|
|
|
{
|
2023-09-20 12:53:35 +10:00
|
|
|
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
isc_sockaddr_t addr;
|
|
|
|
|
2005-02-23 01:09:23 +00:00
|
|
|
control = cfg_listelt_value(element2);
|
|
|
|
allow = cfg_tuple_get(control, "allow");
|
|
|
|
tresult = cfg_acl_fromconfig(allow, config, logctx,
|
2011-06-17 07:05:02 +00:00
|
|
|
actx, mctx, 0, &acl);
|
2005-02-23 01:09:23 +00:00
|
|
|
if (acl != NULL) {
|
|
|
|
dns_acl_detach(&acl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2022-12-16 10:39:15 +00:00
|
|
|
tresult = check_controlskeys(control, keylist, logctx);
|
2005-02-23 01:09:23 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-09-20 12:53:35 +10:00
|
|
|
obj = cfg_tuple_get(control, "address");
|
|
|
|
addr = *cfg_obj_assockaddr(obj);
|
|
|
|
if (isc_sockaddr_getport(&addr) == 0) {
|
|
|
|
isc_sockaddr_setport(&addr, NAMED_CONTROL_PORT);
|
|
|
|
}
|
|
|
|
isc_sockaddr_format(&addr, socktext, sizeof(socktext));
|
|
|
|
tresult = exists(
|
|
|
|
obj, socktext, 1, symtab,
|
|
|
|
"inet control socket '%s': already defined, "
|
|
|
|
"previous definition: %s:%u",
|
|
|
|
logctx, mctx);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
}
|
|
|
|
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"));
|
2023-09-12 08:39:12 +02:00
|
|
|
cfg_obj_log(control, logctx, ISC_LOG_ERROR,
|
|
|
|
"unix control '%s': not supported", path);
|
|
|
|
result = ISC_R_FAMILYNOSUPPORT;
|
2005-02-23 01:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-20 12:53:35 +10:00
|
|
|
cleanup:
|
2011-06-17 07:05:02 +00:00
|
|
|
cfg_aclconfctx_detach(&actx);
|
2023-09-20 12:53:35 +10:00
|
|
|
if (symtab != NULL) {
|
|
|
|
isc_symtab_destroy(&symtab);
|
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
isc_result_t
|
2022-08-25 16:47:34 +10:00
|
|
|
isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
|
2023-03-22 16:57:54 -07:00
|
|
|
isc_log_t *logctx, isc_mem_t *mctx) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *options = NULL;
|
|
|
|
const cfg_obj_t *views = NULL;
|
|
|
|
const cfg_obj_t *acls = NULL;
|
|
|
|
const cfg_listelt_t *velement;
|
2001-03-02 03:09:27 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2001-03-09 19:07:30 +00:00
|
|
|
isc_result_t tresult;
|
2004-05-17 05:37:41 +00:00
|
|
|
isc_symtab_t *symtab = NULL;
|
2014-09-29 12:10:10 +10:00
|
|
|
isc_symtab_t *files = NULL;
|
2021-05-04 15:35:39 +02:00
|
|
|
isc_symtab_t *keydirs = NULL;
|
2018-05-25 13:15:00 +10:00
|
|
|
isc_symtab_t *inview = NULL;
|
2022-08-25 16:47:34 +10:00
|
|
|
bool check_algorithms = (flags & BIND_CHECK_ALGORITHMS) != 0;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2002-02-06 06:45:40 +00:00
|
|
|
static const char *builtin[] = { "localhost", "localnets", "any",
|
2002-02-06 06:54:31 +00:00
|
|
|
"none" };
|
2002-02-06 06:45:40 +00:00
|
|
|
|
2001-03-03 23:05:23 +00:00
|
|
|
(void)cfg_map_get(config, "options", &options);
|
|
|
|
|
2022-08-25 16:47:34 +10:00
|
|
|
if (options != NULL &&
|
|
|
|
check_options(options, config, check_algorithms, logctx, mctx,
|
|
|
|
optlevel_options) != ISC_R_SUCCESS)
|
2011-11-07 00:14:11 +00:00
|
|
|
{
|
2002-03-04 05:07:06 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-03-04 05:07:06 +00:00
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_logging(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2004-11-09 21:24:20 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2004-11-09 21:24:20 +00:00
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_controls(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2005-02-23 01:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-23 01:09:23 +00:00
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_primarylists(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2020-06-25 21:59:56 -07:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_parentalagentlists(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2021-05-07 14:27:25 +02:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2021-05-19 18:03:11 +03:00
|
|
|
#if HAVE_LIBNGHTTP2
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_httpservers(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2021-05-19 18:03:11 +03:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LIBNGHTTP2 */
|
|
|
|
|
2022-12-16 10:39:15 +00:00
|
|
|
if (check_tls_definitions(config, logctx, mctx) != ISC_R_SUCCESS) {
|
2021-09-13 15:39:36 +03:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
(void)cfg_map_get(config, "view", &views);
|
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
if (views != NULL && options != NULL) {
|
|
|
|
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS) {
|
2003-01-16 03:59:28 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
/*
|
|
|
|
* Use case insensitive comparison as not all file
|
|
|
|
* systems are case sensitive. This will prevent people
|
|
|
|
* using FOO.DB and foo.db on case sensitive file
|
|
|
|
* systems but that shouldn't be a major issue.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 12:10:10 +10:00
|
|
|
/*
|
2015-07-06 09:44:24 +10:00
|
|
|
* Use case insensitive comparison as not all file systems are
|
2014-09-29 12:10:10 +10:00
|
|
|
* case sensitive. This will prevent people using FOO.DB and foo.db
|
|
|
|
* on case sensitive file systems but that shouldn't be a major issue.
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
tresult = isc_symtab_create(mctx, 100, NULL, NULL, false, &files);
|
2018-05-25 13:15:00 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2014-09-29 12:10:10 +10:00
|
|
|
result = tresult;
|
2018-05-25 13:15:00 +10:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2021-05-04 15:35:39 +02:00
|
|
|
tresult = isc_symtab_create(mctx, 100, freekey, mctx, false, &keydirs);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-25 13:15:00 +10:00
|
|
|
tresult = isc_symtab_create(mctx, 100, freekey, mctx, true, &inview);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
|
|
|
result = tresult;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-09-29 12:10:10 +10:00
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
if (views == NULL) {
|
2018-11-02 23:28:25 -07:00
|
|
|
tresult = check_viewconf(config, NULL, NULL, dns_rdataclass_in,
|
2022-08-25 16:47:34 +10:00
|
|
|
files, keydirs, flags, inview, logctx,
|
|
|
|
mctx);
|
2018-05-25 13:15:00 +10:00
|
|
|
if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) {
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2018-05-25 13:15:00 +10:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
} else {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *zones = NULL;
|
2018-11-30 15:32:03 -08:00
|
|
|
const cfg_obj_t *plugins = NULL;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
|
|
|
(void)cfg_map_get(config, "zone", &zones);
|
|
|
|
if (zones != NULL) {
|
|
|
|
cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
|
|
|
|
"when using 'view' statements, "
|
|
|
|
"all zones must be in views");
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2018-11-02 23:28:25 -07:00
|
|
|
|
2018-11-30 15:32:03 -08:00
|
|
|
(void)cfg_map_get(config, "plugin", &plugins);
|
|
|
|
if (plugins != NULL) {
|
|
|
|
cfg_obj_log(plugins, logctx, ISC_LOG_ERROR,
|
2018-11-02 23:28:25 -07:00
|
|
|
"when using 'view' statements, "
|
2018-11-30 15:32:03 -08:00
|
|
|
"all plugins must be defined in views");
|
2018-11-02 23:28:25 -07:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
tresult = isc_symtab_create(mctx, 100, NULL, NULL, true, &symtab);
|
2018-05-25 13:15:00 +10:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2004-05-17 05:37:41 +00:00
|
|
|
result = tresult;
|
2018-05-25 13:15:00 +10:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
for (velement = cfg_list_first(views); velement != NULL;
|
|
|
|
velement = cfg_list_next(velement))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *view = cfg_listelt_value(velement);
|
|
|
|
const cfg_obj_t *vname = cfg_tuple_get(view, "name");
|
|
|
|
const cfg_obj_t *voptions = cfg_tuple_get(view, "options");
|
|
|
|
const cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
|
2001-09-20 15:17:07 +00:00
|
|
|
dns_rdataclass_t vclass = dns_rdataclass_in;
|
2004-05-17 05:37:41 +00:00
|
|
|
const char *key = cfg_obj_asstring(vname);
|
|
|
|
isc_symvalue_t symvalue;
|
2015-08-12 19:06:00 +10:00
|
|
|
unsigned int symtype;
|
2001-03-01 23:46:49 +00:00
|
|
|
|
2015-01-20 13:29:18 -08:00
|
|
|
tresult = ISC_R_SUCCESS;
|
2001-09-20 15:17:07 +00:00
|
|
|
if (cfg_obj_isstring(vclassobj)) {
|
|
|
|
isc_textregion_t r;
|
|
|
|
|
2023-03-30 22:34:12 +02:00
|
|
|
r.base = UNCONST(cfg_obj_asstring(vclassobj));
|
2001-09-20 15:17:07 +00:00
|
|
|
r.length = strlen(r.base);
|
|
|
|
tresult = dns_rdataclass_fromtext(&vclass, &r);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-11-16 04:43:04 +00:00
|
|
|
cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
|
2001-09-20 15:17:07 +00:00
|
|
|
"view '%s': invalid class %s",
|
|
|
|
cfg_obj_asstring(vname), r.base);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-09-20 15:17:07 +00:00
|
|
|
}
|
2015-08-12 19:06:00 +10:00
|
|
|
symtype = vclass + 1;
|
2004-05-17 05:37:41 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS && symtab != NULL) {
|
2006-02-28 02:39:52 +00:00
|
|
|
symvalue.as_cpointer = view;
|
2015-08-12 19:06:00 +10:00
|
|
|
tresult = isc_symtab_define(symtab, key, symtype,
|
2004-05-17 05:37:41 +00:00
|
|
|
symvalue,
|
|
|
|
isc_symexists_reject);
|
|
|
|
if (tresult == ISC_R_EXISTS) {
|
|
|
|
const char *file;
|
|
|
|
unsigned int line;
|
|
|
|
RUNTIME_CHECK(isc_symtab_lookup(symtab, key,
|
2015-08-12 19:06:00 +10:00
|
|
|
symtype,
|
|
|
|
&symvalue) ==
|
|
|
|
ISC_R_SUCCESS);
|
2006-02-28 02:39:52 +00:00
|
|
|
file = cfg_obj_file(symvalue.as_cpointer);
|
|
|
|
line = cfg_obj_line(symvalue.as_cpointer);
|
2004-05-17 05:37:41 +00:00
|
|
|
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
|
|
|
|
"view '%s': already exists "
|
|
|
|
"previous definition: %s:%u",
|
|
|
|
key, file, line);
|
|
|
|
result = tresult;
|
2007-11-26 01:51:32 +00:00
|
|
|
} else if (tresult != ISC_R_SUCCESS) {
|
2004-05-17 05:37:41 +00:00
|
|
|
result = tresult;
|
2004-07-29 00:08:10 +00:00
|
|
|
} else if ((strcasecmp(key, "_bind") == 0 &&
|
|
|
|
vclass == dns_rdataclass_ch) ||
|
|
|
|
(strcasecmp(key, "_default") == 0 &&
|
|
|
|
vclass == dns_rdataclass_in))
|
|
|
|
{
|
|
|
|
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine builtin view "
|
|
|
|
"'%s'",
|
|
|
|
key);
|
|
|
|
result = ISC_R_EXISTS;
|
|
|
|
}
|
2004-05-17 05:37:41 +00:00
|
|
|
}
|
2001-09-20 15:17:07 +00:00
|
|
|
if (tresult == ISC_R_SUCCESS) {
|
2018-11-02 23:28:25 -07:00
|
|
|
tresult = check_viewconf(config, voptions, key, vclass,
|
2022-08-25 16:47:34 +10:00
|
|
|
files, keydirs, flags, inview,
|
|
|
|
logctx, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-09-20 15:17:07 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2001-03-03 23:09:23 +00:00
|
|
|
result = ISC_R_FAILURE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-03-01 23:46:49 +00:00
|
|
|
}
|
|
|
|
|
2008-03-28 23:47:02 +00:00
|
|
|
cfg_map_get(config, "acl", &acls);
|
2007-09-12 01:09:08 +00:00
|
|
|
|
2008-03-28 23:47:02 +00:00
|
|
|
if (acls != NULL) {
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_listelt_t *elt;
|
|
|
|
const cfg_listelt_t *elt2;
|
2002-02-06 06:45:40 +00:00
|
|
|
const char *aclname;
|
|
|
|
|
|
|
|
for (elt = cfg_list_first(acls); elt != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt = cfg_list_next(elt))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl = cfg_listelt_value(elt);
|
2007-09-12 01:09:08 +00:00
|
|
|
unsigned int line = cfg_obj_line(acl);
|
2002-02-06 06:54:31 +00:00
|
|
|
unsigned int i;
|
2002-02-06 06:45:40 +00:00
|
|
|
|
|
|
|
aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
|
2002-02-06 06:54:31 +00:00
|
|
|
for (i = 0; i < sizeof(builtin) / sizeof(builtin[0]);
|
2022-11-02 19:33:14 +01:00
|
|
|
i++)
|
|
|
|
{
|
2002-02-06 06:45:40 +00:00
|
|
|
if (strcasecmp(aclname, builtin[i]) == 0) {
|
2020-02-13 18:16:57 +01:00
|
|
|
{
|
|
|
|
cfg_obj_log(acl, logctx,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"attempt to "
|
|
|
|
"redefine "
|
|
|
|
"builtin acl '%s'",
|
|
|
|
aclname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
2002-02-06 06:45:40 +00:00
|
|
|
}
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
2002-02-11 00:46:26 +00:00
|
|
|
|
|
|
|
for (elt2 = cfg_list_next(elt); elt2 != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
elt2 = cfg_list_next(elt2))
|
|
|
|
{
|
2006-02-28 02:39:52 +00:00
|
|
|
const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
|
2002-02-11 00:46:26 +00:00
|
|
|
const char *name;
|
|
|
|
name = cfg_obj_asstring(
|
|
|
|
cfg_tuple_get(acl2, "name"));
|
|
|
|
if (strcasecmp(aclname, name) == 0) {
|
2002-02-13 03:43:09 +00:00
|
|
|
const char *file = cfg_obj_file(acl);
|
|
|
|
|
|
|
|
if (file == NULL) {
|
|
|
|
file = "<unknown file>";
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-02-13 03:43:09 +00:00
|
|
|
|
2002-02-11 00:46:26 +00:00
|
|
|
cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
|
|
|
|
"attempt to redefine "
|
2002-02-13 03:43:09 +00:00
|
|
|
"acl '%s' previous "
|
|
|
|
"definition: %s:%u",
|
|
|
|
name, file, line);
|
2002-02-11 00:46:26 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
2002-02-06 06:45:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-25 13:15:00 +10:00
|
|
|
cleanup:
|
|
|
|
if (symtab != NULL) {
|
|
|
|
isc_symtab_destroy(&symtab);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
if (inview != NULL) {
|
|
|
|
isc_symtab_destroy(&inview);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
if (files != NULL) {
|
|
|
|
isc_symtab_destroy(&files);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-05-04 15:35:39 +02:00
|
|
|
if (keydirs != NULL) {
|
|
|
|
isc_symtab_destroy(&keydirs);
|
|
|
|
}
|
2018-05-25 13:15:00 +10:00
|
|
|
|
2001-03-01 23:46:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|