xref: /minix3/external/bsd/bind/dist/lib/bind9/check.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: check.c,v 1.12 2015/07/08 17:28:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2001-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /*! \file */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <stdlib.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <isc/base64.h>
27*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
28*00b67f09SDavid van Moolenbroek #include <isc/file.h>
29*00b67f09SDavid van Moolenbroek #include <isc/hex.h>
30*00b67f09SDavid van Moolenbroek #include <isc/log.h>
31*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
32*00b67f09SDavid van Moolenbroek #include <isc/netaddr.h>
33*00b67f09SDavid van Moolenbroek #include <isc/parseint.h>
34*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
35*00b67f09SDavid van Moolenbroek #include <isc/region.h>
36*00b67f09SDavid van Moolenbroek #include <isc/result.h>
37*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
38*00b67f09SDavid van Moolenbroek #include <isc/string.h>
39*00b67f09SDavid van Moolenbroek #include <isc/symtab.h>
40*00b67f09SDavid van Moolenbroek #include <isc/util.h>
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
43*00b67f09SDavid van Moolenbroek #ifdef AES_SIT
44*00b67f09SDavid van Moolenbroek #include <isc/aes.h>
45*00b67f09SDavid van Moolenbroek #endif
46*00b67f09SDavid van Moolenbroek #ifdef HMAC_SHA1_SIT
47*00b67f09SDavid van Moolenbroek #include <isc/sha1.h>
48*00b67f09SDavid van Moolenbroek #endif
49*00b67f09SDavid van Moolenbroek #ifdef HMAC_SHA256_SIT
50*00b67f09SDavid van Moolenbroek #include <isc/sha2.h>
51*00b67f09SDavid van Moolenbroek #endif
52*00b67f09SDavid van Moolenbroek #endif
53*00b67f09SDavid van Moolenbroek 
54*00b67f09SDavid van Moolenbroek #include <dns/acl.h>
55*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
56*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
57*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
58*00b67f09SDavid van Moolenbroek #include <dns/secalg.h>
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek #include <isccfg/aclconf.h>
63*00b67f09SDavid van Moolenbroek #include <isccfg/cfg.h>
64*00b67f09SDavid van Moolenbroek 
65*00b67f09SDavid van Moolenbroek #include <bind9/check.h>
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek static isc_result_t
68*00b67f09SDavid van Moolenbroek fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, isc_boolean_t writeable,
69*00b67f09SDavid van Moolenbroek 	  isc_log_t *logctxlogc);
70*00b67f09SDavid van Moolenbroek 
71*00b67f09SDavid van Moolenbroek static void
freekey(char * key,unsigned int type,isc_symvalue_t value,void * userarg)72*00b67f09SDavid van Moolenbroek freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
73*00b67f09SDavid van Moolenbroek 	UNUSED(type);
74*00b67f09SDavid van Moolenbroek 	UNUSED(value);
75*00b67f09SDavid van Moolenbroek 	isc_mem_free(userarg, key);
76*00b67f09SDavid van Moolenbroek }
77*00b67f09SDavid van Moolenbroek 
78*00b67f09SDavid van Moolenbroek static isc_result_t
check_orderent(const cfg_obj_t * ent,isc_log_t * logctx)79*00b67f09SDavid van Moolenbroek check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
80*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
81*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
82*00b67f09SDavid van Moolenbroek 	isc_textregion_t r;
83*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
84*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
85*00b67f09SDavid van Moolenbroek 	dns_rdataclass_t rdclass;
86*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t rdtype;
87*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
88*00b67f09SDavid van Moolenbroek 	const char *str;
89*00b67f09SDavid van Moolenbroek 
90*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
91*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(ent, "class");
92*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isstring(obj)) {
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 		DE_CONST(cfg_obj_asstring(obj), r.base);
95*00b67f09SDavid van Moolenbroek 		r.length = strlen(r.base);
96*00b67f09SDavid van Moolenbroek 		tresult = dns_rdataclass_fromtext(&rdclass, &r);
97*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
98*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
99*00b67f09SDavid van Moolenbroek 				    "rrset-order: invalid class '%s'",
100*00b67f09SDavid van Moolenbroek 				    r.base);
101*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
102*00b67f09SDavid van Moolenbroek 		}
103*00b67f09SDavid van Moolenbroek 	}
104*00b67f09SDavid van Moolenbroek 
105*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(ent, "type");
106*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isstring(obj)) {
107*00b67f09SDavid van Moolenbroek 		DE_CONST(cfg_obj_asstring(obj), r.base);
108*00b67f09SDavid van Moolenbroek 		r.length = strlen(r.base);
109*00b67f09SDavid van Moolenbroek 		tresult = dns_rdatatype_fromtext(&rdtype, &r);
110*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
111*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
112*00b67f09SDavid van Moolenbroek 				    "rrset-order: invalid type '%s'",
113*00b67f09SDavid van Moolenbroek 				    r.base);
114*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
115*00b67f09SDavid van Moolenbroek 		}
116*00b67f09SDavid van Moolenbroek 	}
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(ent, "name");
119*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isstring(obj)) {
120*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(obj);
121*00b67f09SDavid van Moolenbroek 		isc_buffer_constinit(&b, str, strlen(str));
122*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, strlen(str));
123*00b67f09SDavid van Moolenbroek 		tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
124*00b67f09SDavid van Moolenbroek 					    dns_rootname, 0, NULL);
125*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
126*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
127*00b67f09SDavid van Moolenbroek 				    "rrset-order: invalid name '%s'", str);
128*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
129*00b67f09SDavid van Moolenbroek 		}
130*00b67f09SDavid van Moolenbroek 	}
131*00b67f09SDavid van Moolenbroek 
132*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(ent, "order");
133*00b67f09SDavid van Moolenbroek 	if (!cfg_obj_isstring(obj) ||
134*00b67f09SDavid van Moolenbroek 	    strcasecmp("order", cfg_obj_asstring(obj)) != 0) {
135*00b67f09SDavid van Moolenbroek 		cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
136*00b67f09SDavid van Moolenbroek 			    "rrset-order: keyword 'order' missing");
137*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
138*00b67f09SDavid van Moolenbroek 	}
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(ent, "ordering");
141*00b67f09SDavid van Moolenbroek 	if (!cfg_obj_isstring(obj)) {
142*00b67f09SDavid van Moolenbroek 	    cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
143*00b67f09SDavid van Moolenbroek 			"rrset-order: missing ordering");
144*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
145*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
146*00b67f09SDavid van Moolenbroek #if !DNS_RDATASET_FIXED
147*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
148*00b67f09SDavid van Moolenbroek 			    "rrset-order: order 'fixed' was disabled at "
149*00b67f09SDavid van Moolenbroek 			    "compilation time");
150*00b67f09SDavid van Moolenbroek #endif
151*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
152*00b67f09SDavid van Moolenbroek 		   strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) {
153*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
154*00b67f09SDavid van Moolenbroek 			    "rrset-order: invalid order '%s'",
155*00b67f09SDavid van Moolenbroek 			    cfg_obj_asstring(obj));
156*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
157*00b67f09SDavid van Moolenbroek 	}
158*00b67f09SDavid van Moolenbroek 	return (result);
159*00b67f09SDavid van Moolenbroek }
160*00b67f09SDavid van Moolenbroek 
161*00b67f09SDavid van Moolenbroek static isc_result_t
check_order(const cfg_obj_t * options,isc_log_t * logctx)162*00b67f09SDavid van Moolenbroek check_order(const cfg_obj_t *options, isc_log_t *logctx) {
163*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
164*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
165*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
166*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj = NULL;
167*00b67f09SDavid van Moolenbroek 
168*00b67f09SDavid van Moolenbroek 	if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS)
169*00b67f09SDavid van Moolenbroek 		return (result);
170*00b67f09SDavid van Moolenbroek 
171*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(obj);
172*00b67f09SDavid van Moolenbroek 	     element != NULL;
173*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
174*00b67f09SDavid van Moolenbroek 	{
175*00b67f09SDavid van Moolenbroek 		tresult = check_orderent(cfg_listelt_value(element), logctx);
176*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
177*00b67f09SDavid van Moolenbroek 			result = tresult;
178*00b67f09SDavid van Moolenbroek 	}
179*00b67f09SDavid van Moolenbroek 	return (result);
180*00b67f09SDavid van Moolenbroek }
181*00b67f09SDavid van Moolenbroek 
182*00b67f09SDavid van Moolenbroek static isc_result_t
check_dual_stack(const cfg_obj_t * options,isc_log_t * logctx)183*00b67f09SDavid van Moolenbroek check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
184*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
185*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *alternates = NULL;
186*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *value;
187*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
188*00b67f09SDavid van Moolenbroek 	const char *str;
189*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
190*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
191*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
192*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
193*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
194*00b67f09SDavid van Moolenbroek 
195*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "dual-stack-servers", &alternates);
196*00b67f09SDavid van Moolenbroek 
197*00b67f09SDavid van Moolenbroek 	if (alternates == NULL)
198*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(alternates, "port");
201*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isuint32(obj)) {
202*00b67f09SDavid van Moolenbroek 		isc_uint32_t val = cfg_obj_asuint32(obj);
203*00b67f09SDavid van Moolenbroek 		if (val > ISC_UINT16_MAX) {
204*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
205*00b67f09SDavid van Moolenbroek 				    "port '%u' out of range", val);
206*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
207*00b67f09SDavid van Moolenbroek 		}
208*00b67f09SDavid van Moolenbroek 	}
209*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(alternates, "addresses");
210*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(obj);
211*00b67f09SDavid van Moolenbroek 	     element != NULL;
212*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element)) {
213*00b67f09SDavid van Moolenbroek 		value = cfg_listelt_value(element);
214*00b67f09SDavid van Moolenbroek 		if (cfg_obj_issockaddr(value))
215*00b67f09SDavid van Moolenbroek 			continue;
216*00b67f09SDavid van Moolenbroek 		obj = cfg_tuple_get(value, "name");
217*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(obj);
218*00b67f09SDavid van Moolenbroek 		isc_buffer_constinit(&buffer, str, strlen(str));
219*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&buffer, strlen(str));
220*00b67f09SDavid van Moolenbroek 		dns_fixedname_init(&fixed);
221*00b67f09SDavid van Moolenbroek 		name = dns_fixedname_name(&fixed);
222*00b67f09SDavid van Moolenbroek 		tresult = dns_name_fromtext(name, &buffer, dns_rootname,
223*00b67f09SDavid van Moolenbroek 					    0, NULL);
224*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
225*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
226*00b67f09SDavid van Moolenbroek 				    "bad name '%s'", str);
227*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
228*00b67f09SDavid van Moolenbroek 		}
229*00b67f09SDavid van Moolenbroek 		obj = cfg_tuple_get(value, "port");
230*00b67f09SDavid van Moolenbroek 		if (cfg_obj_isuint32(obj)) {
231*00b67f09SDavid van Moolenbroek 			isc_uint32_t val = cfg_obj_asuint32(obj);
232*00b67f09SDavid van Moolenbroek 			if (val > ISC_UINT16_MAX) {
233*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
234*00b67f09SDavid van Moolenbroek 					    "port '%u' out of range", val);
235*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
236*00b67f09SDavid van Moolenbroek 			}
237*00b67f09SDavid van Moolenbroek 		}
238*00b67f09SDavid van Moolenbroek 	}
239*00b67f09SDavid van Moolenbroek 	return (result);
240*00b67f09SDavid van Moolenbroek }
241*00b67f09SDavid van Moolenbroek 
242*00b67f09SDavid van Moolenbroek static isc_result_t
check_forward(const cfg_obj_t * options,const cfg_obj_t * global,isc_log_t * logctx)243*00b67f09SDavid van Moolenbroek check_forward(const cfg_obj_t *options,  const cfg_obj_t *global,
244*00b67f09SDavid van Moolenbroek 	      isc_log_t *logctx)
245*00b67f09SDavid van Moolenbroek {
246*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *forward = NULL;
247*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *forwarders = NULL;
248*00b67f09SDavid van Moolenbroek 
249*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "forward", &forward);
250*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "forwarders", &forwarders);
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek 	if (forwarders != NULL && global != NULL) {
253*00b67f09SDavid van Moolenbroek 		const char *file = cfg_obj_file(global);
254*00b67f09SDavid van Moolenbroek 		unsigned int line = cfg_obj_line(global);
255*00b67f09SDavid van Moolenbroek 		cfg_obj_log(forwarders, logctx, ISC_LOG_ERROR,
256*00b67f09SDavid van Moolenbroek 			    "forwarders declared in root zone and "
257*00b67f09SDavid van Moolenbroek 			    "in general configuration: %s:%u",
258*00b67f09SDavid van Moolenbroek 			    file, line);
259*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
260*00b67f09SDavid van Moolenbroek 	}
261*00b67f09SDavid van Moolenbroek 	if (forward != NULL && forwarders == NULL) {
262*00b67f09SDavid van Moolenbroek 		cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
263*00b67f09SDavid van Moolenbroek 			    "no matching 'forwarders' statement");
264*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
265*00b67f09SDavid van Moolenbroek 	}
266*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek 
269*00b67f09SDavid van Moolenbroek static isc_result_t
disabled_algorithms(const cfg_obj_t * disabled,isc_log_t * logctx)270*00b67f09SDavid van Moolenbroek disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
271*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
272*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
273*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
274*00b67f09SDavid van Moolenbroek 	const char *str;
275*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
276*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
277*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
278*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
279*00b67f09SDavid van Moolenbroek 
280*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
281*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
282*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(disabled, "name");
283*00b67f09SDavid van Moolenbroek 	str = cfg_obj_asstring(obj);
284*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&b, str, strlen(str));
285*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&b, strlen(str));
286*00b67f09SDavid van Moolenbroek 	tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
287*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS) {
288*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
289*00b67f09SDavid van Moolenbroek 			    "bad domain name '%s'", str);
290*00b67f09SDavid van Moolenbroek 		result = tresult;
291*00b67f09SDavid van Moolenbroek 	}
292*00b67f09SDavid van Moolenbroek 
293*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(disabled, "algorithms");
294*00b67f09SDavid van Moolenbroek 
295*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(obj);
296*00b67f09SDavid van Moolenbroek 	     element != NULL;
297*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
298*00b67f09SDavid van Moolenbroek 	{
299*00b67f09SDavid van Moolenbroek 		isc_textregion_t r;
300*00b67f09SDavid van Moolenbroek 		dns_secalg_t alg;
301*00b67f09SDavid van Moolenbroek 
302*00b67f09SDavid van Moolenbroek 		DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
303*00b67f09SDavid van Moolenbroek 		r.length = strlen(r.base);
304*00b67f09SDavid van Moolenbroek 
305*00b67f09SDavid van Moolenbroek 		tresult = dns_secalg_fromtext(&alg, &r);
306*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
307*00b67f09SDavid van Moolenbroek 			cfg_obj_log(cfg_listelt_value(element), logctx,
308*00b67f09SDavid van Moolenbroek 				    ISC_LOG_ERROR, "invalid algorithm '%s'",
309*00b67f09SDavid van Moolenbroek 				    r.base);
310*00b67f09SDavid van Moolenbroek 			result = tresult;
311*00b67f09SDavid van Moolenbroek 		}
312*00b67f09SDavid van Moolenbroek 	}
313*00b67f09SDavid van Moolenbroek 	return (result);
314*00b67f09SDavid van Moolenbroek }
315*00b67f09SDavid van Moolenbroek 
316*00b67f09SDavid van Moolenbroek static isc_result_t
disabled_ds_digests(const cfg_obj_t * disabled,isc_log_t * logctx)317*00b67f09SDavid van Moolenbroek disabled_ds_digests(const cfg_obj_t *disabled, isc_log_t *logctx) {
318*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
319*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
320*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
321*00b67f09SDavid van Moolenbroek 	const char *str;
322*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
323*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
324*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
325*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
326*00b67f09SDavid van Moolenbroek 
327*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
328*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
329*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(disabled, "name");
330*00b67f09SDavid van Moolenbroek 	str = cfg_obj_asstring(obj);
331*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&b, str, strlen(str));
332*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&b, strlen(str));
333*00b67f09SDavid van Moolenbroek 	tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
334*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS) {
335*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
336*00b67f09SDavid van Moolenbroek 			    "bad domain name '%s'", str);
337*00b67f09SDavid van Moolenbroek 		result = tresult;
338*00b67f09SDavid van Moolenbroek 	}
339*00b67f09SDavid van Moolenbroek 
340*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(disabled, "digests");
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(obj);
343*00b67f09SDavid van Moolenbroek 	     element != NULL;
344*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
345*00b67f09SDavid van Moolenbroek 	{
346*00b67f09SDavid van Moolenbroek 		isc_textregion_t r;
347*00b67f09SDavid van Moolenbroek 		dns_dsdigest_t digest;
348*00b67f09SDavid van Moolenbroek 
349*00b67f09SDavid van Moolenbroek 		DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
350*00b67f09SDavid van Moolenbroek 		r.length = strlen(r.base);
351*00b67f09SDavid van Moolenbroek 
352*00b67f09SDavid van Moolenbroek 		/* works with a numeric argument too */
353*00b67f09SDavid van Moolenbroek 		tresult = dns_dsdigest_fromtext(&digest, &r);
354*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
355*00b67f09SDavid van Moolenbroek 			cfg_obj_log(cfg_listelt_value(element), logctx,
356*00b67f09SDavid van Moolenbroek 				    ISC_LOG_ERROR, "invalid digest type '%s'",
357*00b67f09SDavid van Moolenbroek 				    r.base);
358*00b67f09SDavid van Moolenbroek 			result = tresult;
359*00b67f09SDavid van Moolenbroek 		}
360*00b67f09SDavid van Moolenbroek 	}
361*00b67f09SDavid van Moolenbroek 	return (result);
362*00b67f09SDavid van Moolenbroek }
363*00b67f09SDavid van Moolenbroek 
364*00b67f09SDavid van Moolenbroek static isc_result_t
nameexist(const cfg_obj_t * obj,const char * name,int value,isc_symtab_t * symtab,const char * fmt,isc_log_t * logctx,isc_mem_t * mctx)365*00b67f09SDavid van Moolenbroek nameexist(const cfg_obj_t *obj, const char *name, int value,
366*00b67f09SDavid van Moolenbroek 	  isc_symtab_t *symtab, const char *fmt, isc_log_t *logctx,
367*00b67f09SDavid van Moolenbroek 	  isc_mem_t *mctx)
368*00b67f09SDavid van Moolenbroek {
369*00b67f09SDavid van Moolenbroek 	char *key;
370*00b67f09SDavid van Moolenbroek 	const char *file;
371*00b67f09SDavid van Moolenbroek 	unsigned int line;
372*00b67f09SDavid van Moolenbroek 	isc_result_t result;
373*00b67f09SDavid van Moolenbroek 	isc_symvalue_t symvalue;
374*00b67f09SDavid van Moolenbroek 
375*00b67f09SDavid van Moolenbroek 	key = isc_mem_strdup(mctx, name);
376*00b67f09SDavid van Moolenbroek 	if (key == NULL)
377*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
378*00b67f09SDavid van Moolenbroek 	symvalue.as_cpointer = obj;
379*00b67f09SDavid van Moolenbroek 	result = isc_symtab_define(symtab, key, value, symvalue,
380*00b67f09SDavid van Moolenbroek 				   isc_symexists_reject);
381*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_EXISTS) {
382*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
383*00b67f09SDavid van Moolenbroek 						&symvalue) == ISC_R_SUCCESS);
384*00b67f09SDavid van Moolenbroek 		file = cfg_obj_file(symvalue.as_cpointer);
385*00b67f09SDavid van Moolenbroek 		line = cfg_obj_line(symvalue.as_cpointer);
386*00b67f09SDavid van Moolenbroek 
387*00b67f09SDavid van Moolenbroek 		if (file == NULL)
388*00b67f09SDavid van Moolenbroek 			file = "<unknown file>";
389*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
390*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, key);
391*00b67f09SDavid van Moolenbroek 		result = ISC_R_EXISTS;
392*00b67f09SDavid van Moolenbroek 	} else if (result != ISC_R_SUCCESS) {
393*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, key);
394*00b67f09SDavid van Moolenbroek 	}
395*00b67f09SDavid van Moolenbroek 	return (result);
396*00b67f09SDavid van Moolenbroek }
397*00b67f09SDavid van Moolenbroek 
398*00b67f09SDavid van Moolenbroek static isc_result_t
mustbesecure(const cfg_obj_t * secure,isc_symtab_t * symtab,isc_log_t * logctx,isc_mem_t * mctx)399*00b67f09SDavid van Moolenbroek mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
400*00b67f09SDavid van Moolenbroek 	     isc_mem_t *mctx)
401*00b67f09SDavid van Moolenbroek {
402*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
403*00b67f09SDavid van Moolenbroek 	char namebuf[DNS_NAME_FORMATSIZE];
404*00b67f09SDavid van Moolenbroek 	const char *str;
405*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
406*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
407*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
408*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
411*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
412*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(secure, "name");
413*00b67f09SDavid van Moolenbroek 	str = cfg_obj_asstring(obj);
414*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&b, str, strlen(str));
415*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&b, strlen(str));
416*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
417*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
418*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
419*00b67f09SDavid van Moolenbroek 			    "bad domain name '%s'", str);
420*00b67f09SDavid van Moolenbroek 	} else {
421*00b67f09SDavid van Moolenbroek 		dns_name_format(name, namebuf, sizeof(namebuf));
422*00b67f09SDavid van Moolenbroek 		result = nameexist(secure, namebuf, 1, symtab,
423*00b67f09SDavid van Moolenbroek 				   "dnssec-must-be-secure '%s': already "
424*00b67f09SDavid van Moolenbroek 				   "exists previous definition: %s:%u",
425*00b67f09SDavid van Moolenbroek 				   logctx, mctx);
426*00b67f09SDavid van Moolenbroek 	}
427*00b67f09SDavid van Moolenbroek 	return (result);
428*00b67f09SDavid van Moolenbroek }
429*00b67f09SDavid van Moolenbroek 
430*00b67f09SDavid van Moolenbroek static isc_result_t
checkacl(const char * aclname,cfg_aclconfctx_t * actx,const cfg_obj_t * zconfig,const cfg_obj_t * voptions,const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)431*00b67f09SDavid van Moolenbroek checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
432*00b67f09SDavid van Moolenbroek 	 const cfg_obj_t *voptions, const cfg_obj_t *config,
433*00b67f09SDavid van Moolenbroek 	 isc_log_t *logctx, isc_mem_t *mctx)
434*00b67f09SDavid van Moolenbroek {
435*00b67f09SDavid van Moolenbroek 	isc_result_t result;
436*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *aclobj = NULL;
437*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options;
438*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = NULL;
439*00b67f09SDavid van Moolenbroek 
440*00b67f09SDavid van Moolenbroek 	if (zconfig != NULL) {
441*00b67f09SDavid van Moolenbroek 		options = cfg_tuple_get(zconfig, "options");
442*00b67f09SDavid van Moolenbroek 		cfg_map_get(options, aclname, &aclobj);
443*00b67f09SDavid van Moolenbroek 	}
444*00b67f09SDavid van Moolenbroek 	if (voptions != NULL && aclobj == NULL)
445*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, aclname, &aclobj);
446*00b67f09SDavid van Moolenbroek 	if (config != NULL && aclobj == NULL) {
447*00b67f09SDavid van Moolenbroek 		options = NULL;
448*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
449*00b67f09SDavid van Moolenbroek 		if (options != NULL)
450*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, aclname, &aclobj);
451*00b67f09SDavid van Moolenbroek 	}
452*00b67f09SDavid van Moolenbroek 	if (aclobj == NULL)
453*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
454*00b67f09SDavid van Moolenbroek 	result = cfg_acl_fromconfig(aclobj, config, logctx,
455*00b67f09SDavid van Moolenbroek 				    actx, mctx, 0, &acl);
456*00b67f09SDavid van Moolenbroek 	if (acl != NULL)
457*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&acl);
458*00b67f09SDavid van Moolenbroek 	return (result);
459*00b67f09SDavid van Moolenbroek }
460*00b67f09SDavid van Moolenbroek 
461*00b67f09SDavid van Moolenbroek static isc_result_t
check_viewacls(cfg_aclconfctx_t * actx,const cfg_obj_t * voptions,const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)462*00b67f09SDavid van Moolenbroek check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
463*00b67f09SDavid van Moolenbroek 	       const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
464*00b67f09SDavid van Moolenbroek {
465*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS, tresult;
466*00b67f09SDavid van Moolenbroek 	int i = 0;
467*00b67f09SDavid van Moolenbroek 
468*00b67f09SDavid van Moolenbroek 	static const char *acls[] = { "allow-query", "allow-query-on",
469*00b67f09SDavid van Moolenbroek 		"allow-query-cache", "allow-query-cache-on",
470*00b67f09SDavid van Moolenbroek 		"blackhole", "match-clients", "match-destinations",
471*00b67f09SDavid van Moolenbroek 		"sortlist", "filter-aaaa", NULL };
472*00b67f09SDavid van Moolenbroek 
473*00b67f09SDavid van Moolenbroek 	while (acls[i] != NULL) {
474*00b67f09SDavid van Moolenbroek 		tresult = checkacl(acls[i++], actx, NULL, voptions, config,
475*00b67f09SDavid van Moolenbroek 				   logctx, mctx);
476*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
477*00b67f09SDavid van Moolenbroek 			result = tresult;
478*00b67f09SDavid van Moolenbroek 	}
479*00b67f09SDavid van Moolenbroek 	return (result);
480*00b67f09SDavid van Moolenbroek }
481*00b67f09SDavid van Moolenbroek 
482*00b67f09SDavid van Moolenbroek static const unsigned char zeros[16];
483*00b67f09SDavid van Moolenbroek 
484*00b67f09SDavid van Moolenbroek 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)485*00b67f09SDavid van Moolenbroek check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
486*00b67f09SDavid van Moolenbroek 	    const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
487*00b67f09SDavid van Moolenbroek {
488*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
489*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *dns64 = NULL;
490*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options;
491*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
492*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *map, *obj;
493*00b67f09SDavid van Moolenbroek 	isc_netaddr_t na, sa;
494*00b67f09SDavid van Moolenbroek 	unsigned int prefixlen;
495*00b67f09SDavid van Moolenbroek 	int nbytes;
496*00b67f09SDavid van Moolenbroek 	int i;
497*00b67f09SDavid van Moolenbroek 
498*00b67f09SDavid van Moolenbroek 	static const char *acls[] = { "clients", "exclude", "mapped", NULL};
499*00b67f09SDavid van Moolenbroek 
500*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
501*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, "dns64", &dns64);
502*00b67f09SDavid van Moolenbroek 	if (config != NULL && dns64 == NULL) {
503*00b67f09SDavid van Moolenbroek 		options = NULL;
504*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
505*00b67f09SDavid van Moolenbroek 		if (options != NULL)
506*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, "dns64", &dns64);
507*00b67f09SDavid van Moolenbroek 	}
508*00b67f09SDavid van Moolenbroek 	if (dns64 == NULL)
509*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
510*00b67f09SDavid van Moolenbroek 
511*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(dns64);
512*00b67f09SDavid van Moolenbroek 	     element != NULL;
513*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
514*00b67f09SDavid van Moolenbroek 	{
515*00b67f09SDavid van Moolenbroek 		map = cfg_listelt_value(element);
516*00b67f09SDavid van Moolenbroek 		obj = cfg_map_getname(map);
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek 		cfg_obj_asnetprefix(obj, &na, &prefixlen);
519*00b67f09SDavid van Moolenbroek 		if (na.family != AF_INET6) {
520*00b67f09SDavid van Moolenbroek 			cfg_obj_log(map, logctx, ISC_LOG_ERROR,
521*00b67f09SDavid van Moolenbroek 				    "dns64 requires a IPv6 prefix");
522*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
523*00b67f09SDavid van Moolenbroek 			continue;
524*00b67f09SDavid van Moolenbroek 		}
525*00b67f09SDavid van Moolenbroek 
526*00b67f09SDavid van Moolenbroek 		if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 &&
527*00b67f09SDavid van Moolenbroek 		    prefixlen != 56 && prefixlen != 64 && prefixlen != 96) {
528*00b67f09SDavid van Moolenbroek 			cfg_obj_log(map, logctx, ISC_LOG_ERROR,
529*00b67f09SDavid van Moolenbroek 				    "bad prefix length %u [32/40/48/56/64/96]",
530*00b67f09SDavid van Moolenbroek 				    prefixlen);
531*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
532*00b67f09SDavid van Moolenbroek 			continue;
533*00b67f09SDavid van Moolenbroek 		}
534*00b67f09SDavid van Moolenbroek 
535*00b67f09SDavid van Moolenbroek 		for (i = 0; acls[i] != NULL; i++) {
536*00b67f09SDavid van Moolenbroek 			obj = NULL;
537*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(map, acls[i], &obj);
538*00b67f09SDavid van Moolenbroek 			if (obj != NULL) {
539*00b67f09SDavid van Moolenbroek 				dns_acl_t *acl = NULL;
540*00b67f09SDavid van Moolenbroek 				isc_result_t tresult;
541*00b67f09SDavid van Moolenbroek 
542*00b67f09SDavid van Moolenbroek 				tresult = cfg_acl_fromconfig(obj, config,
543*00b67f09SDavid van Moolenbroek 							     logctx, actx,
544*00b67f09SDavid van Moolenbroek 							     mctx, 0, &acl);
545*00b67f09SDavid van Moolenbroek 				if (acl != NULL)
546*00b67f09SDavid van Moolenbroek 					dns_acl_detach(&acl);
547*00b67f09SDavid van Moolenbroek 				if (tresult != ISC_R_SUCCESS)
548*00b67f09SDavid van Moolenbroek 					result = tresult;
549*00b67f09SDavid van Moolenbroek 			}
550*00b67f09SDavid van Moolenbroek 		}
551*00b67f09SDavid van Moolenbroek 
552*00b67f09SDavid van Moolenbroek 		obj = NULL;
553*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(map, "suffix", &obj);
554*00b67f09SDavid van Moolenbroek 		if (obj != NULL) {
555*00b67f09SDavid van Moolenbroek 			isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj));
556*00b67f09SDavid van Moolenbroek 			if (sa.family != AF_INET6) {
557*00b67f09SDavid van Moolenbroek 				cfg_obj_log(map, logctx, ISC_LOG_ERROR,
558*00b67f09SDavid van Moolenbroek 					    "dns64 requires a IPv6 suffix");
559*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
560*00b67f09SDavid van Moolenbroek 				continue;
561*00b67f09SDavid van Moolenbroek 			}
562*00b67f09SDavid van Moolenbroek 			nbytes = prefixlen / 8 + 4;
563*00b67f09SDavid van Moolenbroek 			if (prefixlen >= 32 && prefixlen <= 64)
564*00b67f09SDavid van Moolenbroek 				nbytes++;
565*00b67f09SDavid van Moolenbroek 			if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) {
566*00b67f09SDavid van Moolenbroek 				char netaddrbuf[ISC_NETADDR_FORMATSIZE];
567*00b67f09SDavid van Moolenbroek 				isc_netaddr_format(&sa, netaddrbuf,
568*00b67f09SDavid van Moolenbroek 						   sizeof(netaddrbuf));
569*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
570*00b67f09SDavid van Moolenbroek 					    "bad suffix '%s' leading "
571*00b67f09SDavid van Moolenbroek 					    "%u octets not zeros",
572*00b67f09SDavid van Moolenbroek 					    netaddrbuf, nbytes);
573*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
574*00b67f09SDavid van Moolenbroek 			}
575*00b67f09SDavid van Moolenbroek 		}
576*00b67f09SDavid van Moolenbroek 	}
577*00b67f09SDavid van Moolenbroek 
578*00b67f09SDavid van Moolenbroek 	return (result);
579*00b67f09SDavid van Moolenbroek }
580*00b67f09SDavid van Moolenbroek 
581*00b67f09SDavid van Moolenbroek 
582*00b67f09SDavid van Moolenbroek /*
583*00b67f09SDavid van Moolenbroek  * Check allow-recursion and allow-recursion-on acls, and also log a
584*00b67f09SDavid van Moolenbroek  * warning if they're inconsistent with the "recursion" option.
585*00b67f09SDavid van Moolenbroek  */
586*00b67f09SDavid van Moolenbroek 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)587*00b67f09SDavid van Moolenbroek check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
588*00b67f09SDavid van Moolenbroek 		    const char *viewname, const cfg_obj_t *config,
589*00b67f09SDavid van Moolenbroek 		    isc_log_t *logctx, isc_mem_t *mctx)
590*00b67f09SDavid van Moolenbroek {
591*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options, *aclobj, *obj = NULL;
592*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = NULL;
593*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS, tresult;
594*00b67f09SDavid van Moolenbroek 	isc_boolean_t recursion;
595*00b67f09SDavid van Moolenbroek 	const char *forview = " for view ";
596*00b67f09SDavid van Moolenbroek 	int i = 0;
597*00b67f09SDavid van Moolenbroek 
598*00b67f09SDavid van Moolenbroek 	static const char *acls[] = { "allow-recursion", "allow-recursion-on",
599*00b67f09SDavid van Moolenbroek 				      NULL };
600*00b67f09SDavid van Moolenbroek 
601*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
602*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, "recursion", &obj);
603*00b67f09SDavid van Moolenbroek 	if (obj == NULL && config != NULL) {
604*00b67f09SDavid van Moolenbroek 		options = NULL;
605*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
606*00b67f09SDavid van Moolenbroek 		if (options != NULL)
607*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, "recursion", &obj);
608*00b67f09SDavid van Moolenbroek 	}
609*00b67f09SDavid van Moolenbroek 	if (obj == NULL)
610*00b67f09SDavid van Moolenbroek 		recursion = ISC_TRUE;
611*00b67f09SDavid van Moolenbroek 	else
612*00b67f09SDavid van Moolenbroek 		recursion = cfg_obj_asboolean(obj);
613*00b67f09SDavid van Moolenbroek 
614*00b67f09SDavid van Moolenbroek 	if (viewname == NULL) {
615*00b67f09SDavid van Moolenbroek 		viewname = "";
616*00b67f09SDavid van Moolenbroek 		forview = "";
617*00b67f09SDavid van Moolenbroek 	}
618*00b67f09SDavid van Moolenbroek 
619*00b67f09SDavid van Moolenbroek 	for (i = 0; acls[i] != NULL; i++) {
620*00b67f09SDavid van Moolenbroek 		aclobj = options = NULL;
621*00b67f09SDavid van Moolenbroek 		acl = NULL;
622*00b67f09SDavid van Moolenbroek 
623*00b67f09SDavid van Moolenbroek 		if (voptions != NULL)
624*00b67f09SDavid van Moolenbroek 			cfg_map_get(voptions, acls[i], &aclobj);
625*00b67f09SDavid van Moolenbroek 		if (config != NULL && aclobj == NULL) {
626*00b67f09SDavid van Moolenbroek 			options = NULL;
627*00b67f09SDavid van Moolenbroek 			cfg_map_get(config, "options", &options);
628*00b67f09SDavid van Moolenbroek 			if (options != NULL)
629*00b67f09SDavid van Moolenbroek 				cfg_map_get(options, acls[i], &aclobj);
630*00b67f09SDavid van Moolenbroek 		}
631*00b67f09SDavid van Moolenbroek 		if (aclobj == NULL)
632*00b67f09SDavid van Moolenbroek 			continue;
633*00b67f09SDavid van Moolenbroek 
634*00b67f09SDavid van Moolenbroek 		tresult = cfg_acl_fromconfig(aclobj, config, logctx,
635*00b67f09SDavid van Moolenbroek 					    actx, mctx, 0, &acl);
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
638*00b67f09SDavid van Moolenbroek 			result = tresult;
639*00b67f09SDavid van Moolenbroek 
640*00b67f09SDavid van Moolenbroek 		if (acl == NULL)
641*00b67f09SDavid van Moolenbroek 			continue;
642*00b67f09SDavid van Moolenbroek 
643*00b67f09SDavid van Moolenbroek 		if (recursion == ISC_FALSE && !dns_acl_isnone(acl)) {
644*00b67f09SDavid van Moolenbroek 			cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
645*00b67f09SDavid van Moolenbroek 				    "both \"recursion no;\" and "
646*00b67f09SDavid van Moolenbroek 				    "\"%s\" active%s%s",
647*00b67f09SDavid van Moolenbroek 				    acls[i], forview, viewname);
648*00b67f09SDavid van Moolenbroek 		}
649*00b67f09SDavid van Moolenbroek 
650*00b67f09SDavid van Moolenbroek 		if (acl != NULL)
651*00b67f09SDavid van Moolenbroek 			dns_acl_detach(&acl);
652*00b67f09SDavid van Moolenbroek 	}
653*00b67f09SDavid van Moolenbroek 
654*00b67f09SDavid van Moolenbroek 	return (result);
655*00b67f09SDavid van Moolenbroek }
656*00b67f09SDavid van Moolenbroek 
657*00b67f09SDavid van Moolenbroek static isc_result_t
check_filteraaaa(cfg_aclconfctx_t * actx,const cfg_obj_t * voptions,const char * viewname,const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)658*00b67f09SDavid van Moolenbroek check_filteraaaa(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
659*00b67f09SDavid van Moolenbroek 		 const char *viewname, const cfg_obj_t *config,
660*00b67f09SDavid van Moolenbroek 		 isc_log_t *logctx, isc_mem_t *mctx)
661*00b67f09SDavid van Moolenbroek {
662*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options, *aclobj, *obj;
663*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = NULL;
664*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
665*00b67f09SDavid van Moolenbroek 	dns_aaaa_t filter4, filter6;
666*00b67f09SDavid van Moolenbroek 	const char *forview = " for view ";
667*00b67f09SDavid van Moolenbroek 
668*00b67f09SDavid van Moolenbroek 	if (viewname == NULL) {
669*00b67f09SDavid van Moolenbroek 		viewname = "";
670*00b67f09SDavid van Moolenbroek 		forview = "";
671*00b67f09SDavid van Moolenbroek 	}
672*00b67f09SDavid van Moolenbroek 
673*00b67f09SDavid van Moolenbroek 	aclobj = options = NULL;
674*00b67f09SDavid van Moolenbroek 	acl = NULL;
675*00b67f09SDavid van Moolenbroek 
676*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
677*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, "filter-aaaa", &aclobj);
678*00b67f09SDavid van Moolenbroek 	if (config != NULL && aclobj == NULL) {
679*00b67f09SDavid van Moolenbroek 		options = NULL;
680*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
681*00b67f09SDavid van Moolenbroek 		if (options != NULL)
682*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, "filter-aaaa", &aclobj);
683*00b67f09SDavid van Moolenbroek 	}
684*00b67f09SDavid van Moolenbroek 	if (aclobj == NULL)
685*00b67f09SDavid van Moolenbroek 		return (result);
686*00b67f09SDavid van Moolenbroek 
687*00b67f09SDavid van Moolenbroek 	result = cfg_acl_fromconfig(aclobj, config, logctx,
688*00b67f09SDavid van Moolenbroek 				    actx, mctx, 0, &acl);
689*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
690*00b67f09SDavid van Moolenbroek 		goto failure;
691*00b67f09SDavid van Moolenbroek 
692*00b67f09SDavid van Moolenbroek 	obj = NULL;
693*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
694*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, "filter-aaaa-on-v4", &obj);
695*00b67f09SDavid van Moolenbroek 	if (obj == NULL && config != NULL) {
696*00b67f09SDavid van Moolenbroek 		options = NULL;
697*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
698*00b67f09SDavid van Moolenbroek 		if (options != NULL)
699*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, "filter-aaaa-on-v4", &obj);
700*00b67f09SDavid van Moolenbroek 	}
701*00b67f09SDavid van Moolenbroek 
702*00b67f09SDavid van Moolenbroek 	if (obj == NULL)
703*00b67f09SDavid van Moolenbroek 		filter4 = dns_aaaa_ok;		/* default */
704*00b67f09SDavid van Moolenbroek 	else if (cfg_obj_isboolean(obj))
705*00b67f09SDavid van Moolenbroek 		filter4 = cfg_obj_asboolean(obj) ? dns_aaaa_filter :
706*00b67f09SDavid van Moolenbroek 						  dns_aaaa_ok;
707*00b67f09SDavid van Moolenbroek 	else
708*00b67f09SDavid van Moolenbroek 		filter4 = dns_aaaa_break_dnssec; 	/* break-dnssec */
709*00b67f09SDavid van Moolenbroek 
710*00b67f09SDavid van Moolenbroek 	obj = NULL;
711*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
712*00b67f09SDavid van Moolenbroek 		cfg_map_get(voptions, "filter-aaaa-on-v6", &obj);
713*00b67f09SDavid van Moolenbroek 	if (obj == NULL && config != NULL) {
714*00b67f09SDavid van Moolenbroek 		options = NULL;
715*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &options);
716*00b67f09SDavid van Moolenbroek 		if (options != NULL)
717*00b67f09SDavid van Moolenbroek 			cfg_map_get(options, "filter-aaaa-on-v6", &obj);
718*00b67f09SDavid van Moolenbroek 	}
719*00b67f09SDavid van Moolenbroek 
720*00b67f09SDavid van Moolenbroek 	if (obj == NULL)
721*00b67f09SDavid van Moolenbroek 		filter6 = dns_aaaa_ok;		/* default */
722*00b67f09SDavid van Moolenbroek 	else if (cfg_obj_isboolean(obj))
723*00b67f09SDavid van Moolenbroek 		filter6 = cfg_obj_asboolean(obj) ? dns_aaaa_filter :
724*00b67f09SDavid van Moolenbroek 						  dns_aaaa_ok;
725*00b67f09SDavid van Moolenbroek 	else
726*00b67f09SDavid van Moolenbroek 		filter6 = dns_aaaa_break_dnssec; 	/* break-dnssec */
727*00b67f09SDavid van Moolenbroek 
728*00b67f09SDavid van Moolenbroek 	if ((filter4 != dns_aaaa_ok || filter6 != dns_aaaa_ok) &&
729*00b67f09SDavid van Moolenbroek 	    dns_acl_isnone(acl))
730*00b67f09SDavid van Moolenbroek 	{
731*00b67f09SDavid van Moolenbroek 		cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
732*00b67f09SDavid van Moolenbroek 			    "\"filter-aaaa\" is 'none;' but "
733*00b67f09SDavid van Moolenbroek 			    "either filter-aaaa-on-v4 or filter-aaaa-on-v6 "
734*00b67f09SDavid van Moolenbroek 			    "is enabled%s%s", forview, viewname);
735*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
736*00b67f09SDavid van Moolenbroek 	} else if (filter4 == dns_aaaa_ok && filter6 == dns_aaaa_ok &&
737*00b67f09SDavid van Moolenbroek 		   !dns_acl_isnone(acl))
738*00b67f09SDavid van Moolenbroek 	{
739*00b67f09SDavid van Moolenbroek 		cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
740*00b67f09SDavid van Moolenbroek 			    "\"filter-aaaa\" is set but "
741*00b67f09SDavid van Moolenbroek 			    "neither filter-aaaa-on-v4 or filter-aaaa-on-v6 "
742*00b67f09SDavid van Moolenbroek 			    "is enabled%s%s", forview, viewname);
743*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
744*00b67f09SDavid van Moolenbroek 	}
745*00b67f09SDavid van Moolenbroek 
746*00b67f09SDavid van Moolenbroek  failure:
747*00b67f09SDavid van Moolenbroek 	if (acl != NULL)
748*00b67f09SDavid van Moolenbroek 		dns_acl_detach(&acl);
749*00b67f09SDavid van Moolenbroek 
750*00b67f09SDavid van Moolenbroek 	return (result);
751*00b67f09SDavid van Moolenbroek }
752*00b67f09SDavid van Moolenbroek 
753*00b67f09SDavid van Moolenbroek typedef struct {
754*00b67f09SDavid van Moolenbroek 	const char *name;
755*00b67f09SDavid van Moolenbroek 	unsigned int scale;
756*00b67f09SDavid van Moolenbroek 	unsigned int max;
757*00b67f09SDavid van Moolenbroek } intervaltable;
758*00b67f09SDavid van Moolenbroek 
759*00b67f09SDavid van Moolenbroek typedef enum {
760*00b67f09SDavid van Moolenbroek 	optlevel_config,
761*00b67f09SDavid van Moolenbroek 	optlevel_options,
762*00b67f09SDavid van Moolenbroek 	optlevel_view,
763*00b67f09SDavid van Moolenbroek 	optlevel_zone
764*00b67f09SDavid van Moolenbroek } optlevel_t;
765*00b67f09SDavid van Moolenbroek 
766*00b67f09SDavid van Moolenbroek static isc_result_t
check_dscp(const cfg_obj_t * options,isc_log_t * logctx)767*00b67f09SDavid van Moolenbroek check_dscp(const cfg_obj_t *options, isc_log_t *logctx) {
768*00b67f09SDavid van Moolenbroek        isc_result_t result = ISC_R_SUCCESS;
769*00b67f09SDavid van Moolenbroek        const cfg_obj_t *obj = NULL;
770*00b67f09SDavid van Moolenbroek 
771*00b67f09SDavid van Moolenbroek        /*
772*00b67f09SDavid van Moolenbroek 	* Check that DSCP setting is within range
773*00b67f09SDavid van Moolenbroek 	*/
774*00b67f09SDavid van Moolenbroek        obj = NULL;
775*00b67f09SDavid van Moolenbroek        (void)cfg_map_get(options, "dscp", &obj);
776*00b67f09SDavid van Moolenbroek        if (obj != NULL) {
777*00b67f09SDavid van Moolenbroek 	       isc_uint32_t dscp = cfg_obj_asuint32(obj);
778*00b67f09SDavid van Moolenbroek 	       if (dscp >= 64) {
779*00b67f09SDavid van Moolenbroek 		       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
780*00b67f09SDavid van Moolenbroek 				   "'dscp' out of range (0-63)");
781*00b67f09SDavid van Moolenbroek 		       result = ISC_R_FAILURE;
782*00b67f09SDavid van Moolenbroek 	       }
783*00b67f09SDavid van Moolenbroek        }
784*00b67f09SDavid van Moolenbroek 
785*00b67f09SDavid van Moolenbroek        return (result);
786*00b67f09SDavid van Moolenbroek }
787*00b67f09SDavid van Moolenbroek 
788*00b67f09SDavid van Moolenbroek static isc_result_t
check_name(const char * str)789*00b67f09SDavid van Moolenbroek check_name(const char *str) {
790*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
791*00b67f09SDavid van Moolenbroek 
792*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
793*00b67f09SDavid van Moolenbroek 	return (dns_name_fromstring(dns_fixedname_name(&fixed), str, 0, NULL));
794*00b67f09SDavid van Moolenbroek }
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek static isc_result_t
check_options(const cfg_obj_t * options,isc_log_t * logctx,isc_mem_t * mctx,optlevel_t optlevel)797*00b67f09SDavid van Moolenbroek check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
798*00b67f09SDavid van Moolenbroek 	      optlevel_t optlevel)
799*00b67f09SDavid van Moolenbroek {
800*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
801*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
802*00b67f09SDavid van Moolenbroek 	unsigned int i;
803*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj = NULL;
804*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *resignobj = NULL;
805*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
806*00b67f09SDavid van Moolenbroek 	isc_symtab_t *symtab = NULL;
807*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
808*00b67f09SDavid van Moolenbroek 	const char *str;
809*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
810*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
811*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
812*00b67f09SDavid van Moolenbroek #endif
813*00b67f09SDavid van Moolenbroek 
814*00b67f09SDavid van Moolenbroek 	static intervaltable intervals[] = {
815*00b67f09SDavid van Moolenbroek 	{ "cleaning-interval", 60, 28 * 24 * 60 },	/* 28 days */
816*00b67f09SDavid van Moolenbroek 	{ "heartbeat-interval", 60, 28 * 24 * 60 },	/* 28 days */
817*00b67f09SDavid van Moolenbroek 	{ "interface-interval", 60, 28 * 24 * 60 },	/* 28 days */
818*00b67f09SDavid van Moolenbroek 	{ "max-transfer-idle-in", 60, 28 * 24 * 60 },	/* 28 days */
819*00b67f09SDavid van Moolenbroek 	{ "max-transfer-idle-out", 60, 28 * 24 * 60 },	/* 28 days */
820*00b67f09SDavid van Moolenbroek 	{ "max-transfer-time-in", 60, 28 * 24 * 60 },	/* 28 days */
821*00b67f09SDavid van Moolenbroek 	{ "max-transfer-time-out", 60, 28 * 24 * 60 },	/* 28 days */
822*00b67f09SDavid van Moolenbroek 	{ "statistics-interval", 60, 28 * 24 * 60 },	/* 28 days */
823*00b67f09SDavid van Moolenbroek 	};
824*00b67f09SDavid van Moolenbroek 
825*00b67f09SDavid van Moolenbroek 	static const char *server_contact[] = {
826*00b67f09SDavid van Moolenbroek 		"empty-server", "empty-contact",
827*00b67f09SDavid van Moolenbroek 		"dns64-server", "dns64-contact",
828*00b67f09SDavid van Moolenbroek 		NULL
829*00b67f09SDavid van Moolenbroek 	};
830*00b67f09SDavid van Moolenbroek 
831*00b67f09SDavid van Moolenbroek 	/*
832*00b67f09SDavid van Moolenbroek 	 * Check that fields specified in units of time other than seconds
833*00b67f09SDavid van Moolenbroek 	 * have reasonable values.
834*00b67f09SDavid van Moolenbroek 	 */
835*00b67f09SDavid van Moolenbroek 	for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
836*00b67f09SDavid van Moolenbroek 		isc_uint32_t val;
837*00b67f09SDavid van Moolenbroek 		obj = NULL;
838*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(options, intervals[i].name, &obj);
839*00b67f09SDavid van Moolenbroek 		if (obj == NULL)
840*00b67f09SDavid van Moolenbroek 			continue;
841*00b67f09SDavid van Moolenbroek 		val = cfg_obj_asuint32(obj);
842*00b67f09SDavid van Moolenbroek 		if (val > intervals[i].max) {
843*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
844*00b67f09SDavid van Moolenbroek 				    "%s '%u' is out of range (0..%u)",
845*00b67f09SDavid van Moolenbroek 				    intervals[i].name, val,
846*00b67f09SDavid van Moolenbroek 				    intervals[i].max);
847*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
848*00b67f09SDavid van Moolenbroek 		} else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
849*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
850*00b67f09SDavid van Moolenbroek 				    "%s '%d' is out of range",
851*00b67f09SDavid van Moolenbroek 				    intervals[i].name, val);
852*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
853*00b67f09SDavid van Moolenbroek 		}
854*00b67f09SDavid van Moolenbroek 	}
855*00b67f09SDavid van Moolenbroek 
856*00b67f09SDavid van Moolenbroek 	obj = NULL;
857*00b67f09SDavid van Moolenbroek 	cfg_map_get(options, "max-rsa-exponent-size", &obj);
858*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
859*00b67f09SDavid van Moolenbroek 		isc_uint32_t val;
860*00b67f09SDavid van Moolenbroek 
861*00b67f09SDavid van Moolenbroek 		val = cfg_obj_asuint32(obj);
862*00b67f09SDavid van Moolenbroek 		if (val != 0 && (val < 35 || val > 4096)) {
863*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
864*00b67f09SDavid van Moolenbroek 				    "max-rsa-exponent-size '%u' is out of "
865*00b67f09SDavid van Moolenbroek 				    "range (35..4096)", val);
866*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
867*00b67f09SDavid van Moolenbroek 		}
868*00b67f09SDavid van Moolenbroek 	}
869*00b67f09SDavid van Moolenbroek 
870*00b67f09SDavid van Moolenbroek 	obj = NULL;
871*00b67f09SDavid van Moolenbroek 	cfg_map_get(options, "sig-validity-interval", &obj);
872*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
873*00b67f09SDavid van Moolenbroek 		isc_uint32_t validity, resign = 0;
874*00b67f09SDavid van Moolenbroek 
875*00b67f09SDavid van Moolenbroek 		validity = cfg_obj_asuint32(cfg_tuple_get(obj, "validity"));
876*00b67f09SDavid van Moolenbroek 		resignobj = cfg_tuple_get(obj, "re-sign");
877*00b67f09SDavid van Moolenbroek 		if (!cfg_obj_isvoid(resignobj))
878*00b67f09SDavid van Moolenbroek 			resign = cfg_obj_asuint32(resignobj);
879*00b67f09SDavid van Moolenbroek 
880*00b67f09SDavid van Moolenbroek 		if (validity > 3660 || validity == 0) { /* 10 years */
881*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
882*00b67f09SDavid van Moolenbroek 				    "%s '%u' is out of range (1..3660)",
883*00b67f09SDavid van Moolenbroek 				    "sig-validity-interval", validity);
884*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
885*00b67f09SDavid van Moolenbroek 		}
886*00b67f09SDavid van Moolenbroek 
887*00b67f09SDavid van Moolenbroek 		if (!cfg_obj_isvoid(resignobj)) {
888*00b67f09SDavid van Moolenbroek 			if (resign > 3660 || resign == 0) { /* 10 years */
889*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
890*00b67f09SDavid van Moolenbroek 					    "%s '%u' is out of range (1..3660)",
891*00b67f09SDavid van Moolenbroek 					    "sig-validity-interval (re-sign)",
892*00b67f09SDavid van Moolenbroek 					    validity);
893*00b67f09SDavid van Moolenbroek 				result = ISC_R_RANGE;
894*00b67f09SDavid van Moolenbroek 			} else if ((validity > 7 && validity < resign) ||
895*00b67f09SDavid van Moolenbroek 				   (validity <= 7 && validity * 24 < resign)) {
896*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
897*00b67f09SDavid van Moolenbroek 					    "validity interval (%u days) "
898*00b67f09SDavid van Moolenbroek 					    "less than re-signing interval "
899*00b67f09SDavid van Moolenbroek 					    "(%u %s)", validity, resign,
900*00b67f09SDavid van Moolenbroek 					    (validity > 7) ? "days" : "hours");
901*00b67f09SDavid van Moolenbroek 				result = ISC_R_RANGE;
902*00b67f09SDavid van Moolenbroek 			}
903*00b67f09SDavid van Moolenbroek 		}
904*00b67f09SDavid van Moolenbroek 	}
905*00b67f09SDavid van Moolenbroek 
906*00b67f09SDavid van Moolenbroek 	obj = NULL;
907*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "preferred-glue", &obj);
908*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
909*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(obj);
910*00b67f09SDavid van Moolenbroek 		if (strcasecmp(str, "a") != 0 &&
911*00b67f09SDavid van Moolenbroek 		    strcasecmp(str, "aaaa") != 0 &&
912*00b67f09SDavid van Moolenbroek 		    strcasecmp(str, "none") != 0)
913*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
914*00b67f09SDavid van Moolenbroek 				    "preferred-glue unexpected value '%s'",
915*00b67f09SDavid van Moolenbroek 				    str);
916*00b67f09SDavid van Moolenbroek 	}
917*00b67f09SDavid van Moolenbroek 
918*00b67f09SDavid van Moolenbroek 	obj = NULL;
919*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "root-delegation-only", &obj);
920*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
921*00b67f09SDavid van Moolenbroek 		if (!cfg_obj_isvoid(obj)) {
922*00b67f09SDavid van Moolenbroek 			for (element = cfg_list_first(obj);
923*00b67f09SDavid van Moolenbroek 			     element != NULL;
924*00b67f09SDavid van Moolenbroek 			     element = cfg_list_next(element)) {
925*00b67f09SDavid van Moolenbroek 				const cfg_obj_t *exclude;
926*00b67f09SDavid van Moolenbroek 
927*00b67f09SDavid van Moolenbroek 				exclude = cfg_listelt_value(element);
928*00b67f09SDavid van Moolenbroek 				str = cfg_obj_asstring(exclude);
929*00b67f09SDavid van Moolenbroek 				tresult = check_name(str);
930*00b67f09SDavid van Moolenbroek 				if (tresult != ISC_R_SUCCESS) {
931*00b67f09SDavid van Moolenbroek 					cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
932*00b67f09SDavid van Moolenbroek 						    "bad domain name '%s'",
933*00b67f09SDavid van Moolenbroek 						    str);
934*00b67f09SDavid van Moolenbroek 					result = tresult;
935*00b67f09SDavid van Moolenbroek 				}
936*00b67f09SDavid van Moolenbroek 			}
937*00b67f09SDavid van Moolenbroek 		}
938*00b67f09SDavid van Moolenbroek 	}
939*00b67f09SDavid van Moolenbroek 
940*00b67f09SDavid van Moolenbroek 	/*
941*00b67f09SDavid van Moolenbroek 	 * Set supported DNSSEC algorithms.
942*00b67f09SDavid van Moolenbroek 	 */
943*00b67f09SDavid van Moolenbroek 	obj = NULL;
944*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "disable-algorithms", &obj);
945*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
946*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
947*00b67f09SDavid van Moolenbroek 		     element != NULL;
948*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
949*00b67f09SDavid van Moolenbroek 		{
950*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
951*00b67f09SDavid van Moolenbroek 			tresult = disabled_algorithms(obj, logctx);
952*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
953*00b67f09SDavid van Moolenbroek 				result = tresult;
954*00b67f09SDavid van Moolenbroek 		}
955*00b67f09SDavid van Moolenbroek 	}
956*00b67f09SDavid van Moolenbroek 
957*00b67f09SDavid van Moolenbroek 	/*
958*00b67f09SDavid van Moolenbroek 	 * Set supported DS/DLV digest types.
959*00b67f09SDavid van Moolenbroek 	 */
960*00b67f09SDavid van Moolenbroek 	obj = NULL;
961*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "disable-ds-digests", &obj);
962*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
963*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
964*00b67f09SDavid van Moolenbroek 		     element != NULL;
965*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
966*00b67f09SDavid van Moolenbroek 		{
967*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
968*00b67f09SDavid van Moolenbroek 			tresult = disabled_ds_digests(obj, logctx);
969*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
970*00b67f09SDavid van Moolenbroek 				result = tresult;
971*00b67f09SDavid van Moolenbroek 		}
972*00b67f09SDavid van Moolenbroek 	}
973*00b67f09SDavid van Moolenbroek 
974*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
975*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
976*00b67f09SDavid van Moolenbroek 
977*00b67f09SDavid van Moolenbroek 	/*
978*00b67f09SDavid van Moolenbroek 	 * Check the DLV zone name.
979*00b67f09SDavid van Moolenbroek 	 */
980*00b67f09SDavid van Moolenbroek 	obj = NULL;
981*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "dnssec-lookaside", &obj);
982*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
983*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_create(mctx, 100, freekey, mctx,
984*00b67f09SDavid van Moolenbroek 					    ISC_FALSE, &symtab);
985*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
986*00b67f09SDavid van Moolenbroek 			result = tresult;
987*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
988*00b67f09SDavid van Moolenbroek 		     element != NULL;
989*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
990*00b67f09SDavid van Moolenbroek 		{
991*00b67f09SDavid van Moolenbroek 			const char *dlv;
992*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *dlvobj, *anchor;
993*00b67f09SDavid van Moolenbroek 
994*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
995*00b67f09SDavid van Moolenbroek 
996*00b67f09SDavid van Moolenbroek 			anchor = cfg_tuple_get(obj, "trust-anchor");
997*00b67f09SDavid van Moolenbroek 			dlvobj = cfg_tuple_get(obj, "domain");
998*00b67f09SDavid van Moolenbroek 			dlv = cfg_obj_asstring(dlvobj);
999*00b67f09SDavid van Moolenbroek 
1000*00b67f09SDavid van Moolenbroek 			/*
1001*00b67f09SDavid van Moolenbroek 			 * If domain is "auto" or "no" and trust anchor
1002*00b67f09SDavid van Moolenbroek 			 * is missing, skip remaining tests
1003*00b67f09SDavid van Moolenbroek 			 */
1004*00b67f09SDavid van Moolenbroek 			if (cfg_obj_isvoid(anchor)) {
1005*00b67f09SDavid van Moolenbroek 				if (!strcasecmp(dlv, "no") ||
1006*00b67f09SDavid van Moolenbroek 				    !strcasecmp(dlv, "auto"))
1007*00b67f09SDavid van Moolenbroek 					continue;
1008*00b67f09SDavid van Moolenbroek 			}
1009*00b67f09SDavid van Moolenbroek 
1010*00b67f09SDavid van Moolenbroek 			tresult = dns_name_fromstring(name, dlv, 0, NULL);
1011*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
1012*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1013*00b67f09SDavid van Moolenbroek 					    "bad domain name '%s'", dlv);
1014*00b67f09SDavid van Moolenbroek 				result = tresult;
1015*00b67f09SDavid van Moolenbroek 				continue;
1016*00b67f09SDavid van Moolenbroek 			}
1017*00b67f09SDavid van Moolenbroek 			if (symtab != NULL) {
1018*00b67f09SDavid van Moolenbroek 				tresult = nameexist(obj, dlv, 1, symtab,
1019*00b67f09SDavid van Moolenbroek 						    "dnssec-lookaside '%s': "
1020*00b67f09SDavid van Moolenbroek 						    "already exists previous "
1021*00b67f09SDavid van Moolenbroek 						    "definition: %s:%u",
1022*00b67f09SDavid van Moolenbroek 						    logctx, mctx);
1023*00b67f09SDavid van Moolenbroek 				if (tresult != ISC_R_SUCCESS &&
1024*00b67f09SDavid van Moolenbroek 				    result == ISC_R_SUCCESS)
1025*00b67f09SDavid van Moolenbroek 					result = tresult;
1026*00b67f09SDavid van Moolenbroek 			}
1027*00b67f09SDavid van Moolenbroek 
1028*00b67f09SDavid van Moolenbroek 			/*
1029*00b67f09SDavid van Moolenbroek 			 * XXXMPA to be removed when multiple lookaside
1030*00b67f09SDavid van Moolenbroek 			 * namespaces are supported.
1031*00b67f09SDavid van Moolenbroek 			 */
1032*00b67f09SDavid van Moolenbroek 			if (!dns_name_equal(dns_rootname, name)) {
1033*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1034*00b67f09SDavid van Moolenbroek 					    "dnssec-lookaside '%s': "
1035*00b67f09SDavid van Moolenbroek 					    "non-root not yet supported", dlv);
1036*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS)
1037*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
1038*00b67f09SDavid van Moolenbroek 			}
1039*00b67f09SDavid van Moolenbroek 
1040*00b67f09SDavid van Moolenbroek 			if (!cfg_obj_isvoid(anchor)) {
1041*00b67f09SDavid van Moolenbroek 				dlv = cfg_obj_asstring(anchor);
1042*00b67f09SDavid van Moolenbroek 				tresult = check_name(dlv);
1043*00b67f09SDavid van Moolenbroek 				if (tresult != ISC_R_SUCCESS) {
1044*00b67f09SDavid van Moolenbroek 					cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1045*00b67f09SDavid van Moolenbroek 						    "bad domain name '%s'",
1046*00b67f09SDavid van Moolenbroek 						    dlv);
1047*00b67f09SDavid van Moolenbroek 					if (result == ISC_R_SUCCESS)
1048*00b67f09SDavid van Moolenbroek 						result = tresult;
1049*00b67f09SDavid van Moolenbroek 				}
1050*00b67f09SDavid van Moolenbroek 			} else {
1051*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1052*00b67f09SDavid van Moolenbroek 					"dnssec-lookaside requires "
1053*00b67f09SDavid van Moolenbroek 					"either 'auto' or 'no', or a "
1054*00b67f09SDavid van Moolenbroek 					"domain and trust anchor");
1055*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS)
1056*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
1057*00b67f09SDavid van Moolenbroek 			}
1058*00b67f09SDavid van Moolenbroek 		}
1059*00b67f09SDavid van Moolenbroek 
1060*00b67f09SDavid van Moolenbroek 		if (symtab != NULL)
1061*00b67f09SDavid van Moolenbroek 			isc_symtab_destroy(&symtab);
1062*00b67f09SDavid van Moolenbroek 	}
1063*00b67f09SDavid van Moolenbroek 
1064*00b67f09SDavid van Moolenbroek 	/*
1065*00b67f09SDavid van Moolenbroek 	 * Check auto-dnssec at the view/options level
1066*00b67f09SDavid van Moolenbroek 	 */
1067*00b67f09SDavid van Moolenbroek 	obj = NULL;
1068*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "auto-dnssec", &obj);
1069*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
1070*00b67f09SDavid van Moolenbroek 		const char *arg = cfg_obj_asstring(obj);
1071*00b67f09SDavid van Moolenbroek 		if (optlevel != optlevel_zone && strcasecmp(arg, "off") != 0) {
1072*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1073*00b67f09SDavid van Moolenbroek 				    "auto-dnssec may only be activated at the "
1074*00b67f09SDavid van Moolenbroek 				    "zone level");
1075*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1076*00b67f09SDavid van Moolenbroek 		}
1077*00b67f09SDavid van Moolenbroek 	}
1078*00b67f09SDavid van Moolenbroek 
1079*00b67f09SDavid van Moolenbroek 	/*
1080*00b67f09SDavid van Moolenbroek 	 * Check dnssec-must-be-secure.
1081*00b67f09SDavid van Moolenbroek 	 */
1082*00b67f09SDavid van Moolenbroek 	obj = NULL;
1083*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
1084*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
1085*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_create(mctx, 100, freekey, mctx,
1086*00b67f09SDavid van Moolenbroek 					    ISC_FALSE, &symtab);
1087*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
1088*00b67f09SDavid van Moolenbroek 			result = tresult;
1089*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
1090*00b67f09SDavid van Moolenbroek 		     element != NULL;
1091*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
1092*00b67f09SDavid van Moolenbroek 		{
1093*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
1094*00b67f09SDavid van Moolenbroek 			tresult = mustbesecure(obj, symtab, logctx, mctx);
1095*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
1096*00b67f09SDavid van Moolenbroek 				result = tresult;
1097*00b67f09SDavid van Moolenbroek 		}
1098*00b67f09SDavid van Moolenbroek 		if (symtab != NULL)
1099*00b67f09SDavid van Moolenbroek 			isc_symtab_destroy(&symtab);
1100*00b67f09SDavid van Moolenbroek 	}
1101*00b67f09SDavid van Moolenbroek 
1102*00b67f09SDavid van Moolenbroek 	/*
1103*00b67f09SDavid van Moolenbroek 	 * Check server/contacts for syntactic validity.
1104*00b67f09SDavid van Moolenbroek 	 */
1105*00b67f09SDavid van Moolenbroek 	for (i= 0; server_contact[i] != NULL; i++) {
1106*00b67f09SDavid van Moolenbroek 		obj = NULL;
1107*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(options, server_contact[i], &obj);
1108*00b67f09SDavid van Moolenbroek 		if (obj != NULL) {
1109*00b67f09SDavid van Moolenbroek 			str = cfg_obj_asstring(obj);
1110*00b67f09SDavid van Moolenbroek 			if (check_name(str) != ISC_R_SUCCESS) {
1111*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1112*00b67f09SDavid van Moolenbroek 					    "%s: invalid name '%s'",
1113*00b67f09SDavid van Moolenbroek 					    server_contact[i], str);
1114*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1115*00b67f09SDavid van Moolenbroek 			}
1116*00b67f09SDavid van Moolenbroek 		}
1117*00b67f09SDavid van Moolenbroek 	}
1118*00b67f09SDavid van Moolenbroek 
1119*00b67f09SDavid van Moolenbroek 	/*
1120*00b67f09SDavid van Moolenbroek 	 * Check empty zone configuration.
1121*00b67f09SDavid van Moolenbroek 	 */
1122*00b67f09SDavid van Moolenbroek 	obj = NULL;
1123*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "disable-empty-zone", &obj);
1124*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(obj);
1125*00b67f09SDavid van Moolenbroek 	     element != NULL;
1126*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
1127*00b67f09SDavid van Moolenbroek 	{
1128*00b67f09SDavid van Moolenbroek 		obj = cfg_listelt_value(element);
1129*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(obj);
1130*00b67f09SDavid van Moolenbroek 		if (check_name(str) != ISC_R_SUCCESS) {
1131*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1132*00b67f09SDavid van Moolenbroek 				    "disable-empty-zone: invalid name '%s'",
1133*00b67f09SDavid van Moolenbroek 				    str);
1134*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1135*00b67f09SDavid van Moolenbroek 		}
1136*00b67f09SDavid van Moolenbroek 	}
1137*00b67f09SDavid van Moolenbroek 
1138*00b67f09SDavid van Moolenbroek 	/*
1139*00b67f09SDavid van Moolenbroek 	 * Check that server-id is not too long.
1140*00b67f09SDavid van Moolenbroek 	 * 1024 bytes should be big enough.
1141*00b67f09SDavid van Moolenbroek 	 */
1142*00b67f09SDavid van Moolenbroek 	obj = NULL;
1143*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(options, "server-id", &obj);
1144*00b67f09SDavid van Moolenbroek 	if (obj != NULL && cfg_obj_isstring(obj) &&
1145*00b67f09SDavid van Moolenbroek 	    strlen(cfg_obj_asstring(obj)) > 1024U) {
1146*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1147*00b67f09SDavid van Moolenbroek 			    "'server-id' too big (>1024 bytes)");
1148*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
1149*00b67f09SDavid van Moolenbroek 	}
1150*00b67f09SDavid van Moolenbroek 
1151*00b67f09SDavid van Moolenbroek 	tresult = check_dscp(options, logctx);
1152*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
1153*00b67f09SDavid van Moolenbroek 		result = tresult;
1154*00b67f09SDavid van Moolenbroek 
1155*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
1156*00b67f09SDavid van Moolenbroek 	obj = NULL;
1157*00b67f09SDavid van Moolenbroek 	(void) cfg_map_get(options, "sit-secret", &obj);
1158*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
1159*00b67f09SDavid van Moolenbroek 		unsigned char secret[32];
1160*00b67f09SDavid van Moolenbroek 
1161*00b67f09SDavid van Moolenbroek 		memset(secret, 0, sizeof(secret));
1162*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&b, secret, sizeof(secret));
1163*00b67f09SDavid van Moolenbroek 		tresult = isc_hex_decodestring(cfg_obj_asstring(obj), &b);
1164*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_NOSPACE) {
1165*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1166*00b67f09SDavid van Moolenbroek 				    "sit-secret: too long");
1167*00b67f09SDavid van Moolenbroek 		} else if (tresult != ISC_R_SUCCESS) {
1168*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1169*00b67f09SDavid van Moolenbroek 				    "sit-secret: invalid hex string");
1170*00b67f09SDavid van Moolenbroek 		}
1171*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
1172*00b67f09SDavid van Moolenbroek 			result = tresult;
1173*00b67f09SDavid van Moolenbroek #ifdef AES_SIT
1174*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS &&
1175*00b67f09SDavid van Moolenbroek 		    isc_buffer_usedlength(&b) != ISC_AES128_KEYLENGTH) {
1176*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1177*00b67f09SDavid van Moolenbroek 				    "AES sit-secret must be on 128 bits");
1178*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
1179*00b67f09SDavid van Moolenbroek 		}
1180*00b67f09SDavid van Moolenbroek #endif
1181*00b67f09SDavid van Moolenbroek #ifdef HMAC_SHA1_SIT
1182*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS &&
1183*00b67f09SDavid van Moolenbroek 		    isc_buffer_usedlength(&b) != ISC_SHA1_DIGESTLENGTH) {
1184*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1185*00b67f09SDavid van Moolenbroek 				    "SHA1 sit-secret must be on 160 bits");
1186*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
1187*00b67f09SDavid van Moolenbroek 		}
1188*00b67f09SDavid van Moolenbroek #endif
1189*00b67f09SDavid van Moolenbroek #ifdef HMAC_SHA256_SIT
1190*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS &&
1191*00b67f09SDavid van Moolenbroek 		    isc_buffer_usedlength(&b) != ISC_SHA256_DIGESTLENGTH) {
1192*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1193*00b67f09SDavid van Moolenbroek 				    "SHA256 sit-secret must be on 256 bits");
1194*00b67f09SDavid van Moolenbroek 			result = ISC_R_RANGE;
1195*00b67f09SDavid van Moolenbroek 		}
1196*00b67f09SDavid van Moolenbroek #endif
1197*00b67f09SDavid van Moolenbroek 	}
1198*00b67f09SDavid van Moolenbroek #endif
1199*00b67f09SDavid van Moolenbroek 
1200*00b67f09SDavid van Moolenbroek 	return (result);
1201*00b67f09SDavid van Moolenbroek }
1202*00b67f09SDavid van Moolenbroek 
1203*00b67f09SDavid van Moolenbroek static isc_result_t
get_masters_def(const cfg_obj_t * cctx,const char * name,const cfg_obj_t ** ret)1204*00b67f09SDavid van Moolenbroek get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
1205*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1206*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *masters = NULL;
1207*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *elt;
1208*00b67f09SDavid van Moolenbroek 
1209*00b67f09SDavid van Moolenbroek 	result = cfg_map_get(cctx, "masters", &masters);
1210*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1211*00b67f09SDavid van Moolenbroek 		return (result);
1212*00b67f09SDavid van Moolenbroek 	for (elt = cfg_list_first(masters);
1213*00b67f09SDavid van Moolenbroek 	     elt != NULL;
1214*00b67f09SDavid van Moolenbroek 	     elt = cfg_list_next(elt)) {
1215*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *list;
1216*00b67f09SDavid van Moolenbroek 		const char *listname;
1217*00b67f09SDavid van Moolenbroek 
1218*00b67f09SDavid van Moolenbroek 		list = cfg_listelt_value(elt);
1219*00b67f09SDavid van Moolenbroek 		listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
1220*00b67f09SDavid van Moolenbroek 
1221*00b67f09SDavid van Moolenbroek 		if (strcasecmp(listname, name) == 0) {
1222*00b67f09SDavid van Moolenbroek 			*ret = list;
1223*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
1224*00b67f09SDavid van Moolenbroek 		}
1225*00b67f09SDavid van Moolenbroek 	}
1226*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
1227*00b67f09SDavid van Moolenbroek }
1228*00b67f09SDavid van Moolenbroek 
1229*00b67f09SDavid van Moolenbroek static isc_result_t
validate_masters(const cfg_obj_t * obj,const cfg_obj_t * config,isc_uint32_t * countp,isc_log_t * logctx,isc_mem_t * mctx)1230*00b67f09SDavid van Moolenbroek validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
1231*00b67f09SDavid van Moolenbroek 		 isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
1232*00b67f09SDavid van Moolenbroek {
1233*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1234*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
1235*00b67f09SDavid van Moolenbroek 	isc_uint32_t count = 0;
1236*00b67f09SDavid van Moolenbroek 	isc_symtab_t *symtab = NULL;
1237*00b67f09SDavid van Moolenbroek 	isc_symvalue_t symvalue;
1238*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
1239*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t **stack = NULL;
1240*00b67f09SDavid van Moolenbroek 	isc_uint32_t stackcount = 0, pushed = 0;
1241*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *list;
1242*00b67f09SDavid van Moolenbroek 
1243*00b67f09SDavid van Moolenbroek 	REQUIRE(countp != NULL);
1244*00b67f09SDavid van Moolenbroek 	result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
1245*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1246*00b67f09SDavid van Moolenbroek 		*countp = count;
1247*00b67f09SDavid van Moolenbroek 		return (result);
1248*00b67f09SDavid van Moolenbroek 	}
1249*00b67f09SDavid van Moolenbroek 
1250*00b67f09SDavid van Moolenbroek  newlist:
1251*00b67f09SDavid van Moolenbroek 	list = cfg_tuple_get(obj, "addresses");
1252*00b67f09SDavid van Moolenbroek 	element = cfg_list_first(list);
1253*00b67f09SDavid van Moolenbroek  resume:
1254*00b67f09SDavid van Moolenbroek 	for ( ;
1255*00b67f09SDavid van Moolenbroek 	     element != NULL;
1256*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
1257*00b67f09SDavid van Moolenbroek 	{
1258*00b67f09SDavid van Moolenbroek 		const char *listname;
1259*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *addr;
1260*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *key;
1261*00b67f09SDavid van Moolenbroek 
1262*00b67f09SDavid van Moolenbroek 		addr = cfg_tuple_get(cfg_listelt_value(element),
1263*00b67f09SDavid van Moolenbroek 				     "masterselement");
1264*00b67f09SDavid van Moolenbroek 		key = cfg_tuple_get(cfg_listelt_value(element), "key");
1265*00b67f09SDavid van Moolenbroek 
1266*00b67f09SDavid van Moolenbroek 		if (cfg_obj_issockaddr(addr)) {
1267*00b67f09SDavid van Moolenbroek 			count++;
1268*00b67f09SDavid van Moolenbroek 			continue;
1269*00b67f09SDavid van Moolenbroek 		}
1270*00b67f09SDavid van Moolenbroek 		if (!cfg_obj_isvoid(key)) {
1271*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
1272*00b67f09SDavid van Moolenbroek 				    "unexpected token '%s'",
1273*00b67f09SDavid van Moolenbroek 				    cfg_obj_asstring(key));
1274*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS)
1275*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1276*00b67f09SDavid van Moolenbroek 		}
1277*00b67f09SDavid van Moolenbroek 		listname = cfg_obj_asstring(addr);
1278*00b67f09SDavid van Moolenbroek 		symvalue.as_cpointer = addr;
1279*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_define(symtab, listname, 1, symvalue,
1280*00b67f09SDavid van Moolenbroek 					    isc_symexists_reject);
1281*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_EXISTS)
1282*00b67f09SDavid van Moolenbroek 			continue;
1283*00b67f09SDavid van Moolenbroek 		tresult = get_masters_def(config, listname, &obj);
1284*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
1285*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS)
1286*00b67f09SDavid van Moolenbroek 				result = tresult;
1287*00b67f09SDavid van Moolenbroek 			cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
1288*00b67f09SDavid van Moolenbroek 				    "unable to find masters list '%s'",
1289*00b67f09SDavid van Moolenbroek 				    listname);
1290*00b67f09SDavid van Moolenbroek 			continue;
1291*00b67f09SDavid van Moolenbroek 		}
1292*00b67f09SDavid van Moolenbroek 		/* Grow stack? */
1293*00b67f09SDavid van Moolenbroek 		if (stackcount == pushed) {
1294*00b67f09SDavid van Moolenbroek 			void * new;
1295*00b67f09SDavid van Moolenbroek 			isc_uint32_t newlen = stackcount + 16;
1296*00b67f09SDavid van Moolenbroek 			size_t newsize, oldsize;
1297*00b67f09SDavid van Moolenbroek 
1298*00b67f09SDavid van Moolenbroek 			newsize = newlen * sizeof(*stack);
1299*00b67f09SDavid van Moolenbroek 			oldsize = stackcount * sizeof(*stack);
1300*00b67f09SDavid van Moolenbroek 			new = isc_mem_get(mctx, newsize);
1301*00b67f09SDavid van Moolenbroek 			if (new == NULL)
1302*00b67f09SDavid van Moolenbroek 				goto cleanup;
1303*00b67f09SDavid van Moolenbroek 			if (stackcount != 0) {
1304*00b67f09SDavid van Moolenbroek 				void *ptr;
1305*00b67f09SDavid van Moolenbroek 
1306*00b67f09SDavid van Moolenbroek 				DE_CONST(stack, ptr);
1307*00b67f09SDavid van Moolenbroek 				memmove(new, stack, oldsize);
1308*00b67f09SDavid van Moolenbroek 				isc_mem_put(mctx, ptr, oldsize);
1309*00b67f09SDavid van Moolenbroek 			}
1310*00b67f09SDavid van Moolenbroek 			stack = new;
1311*00b67f09SDavid van Moolenbroek 			stackcount = newlen;
1312*00b67f09SDavid van Moolenbroek 		}
1313*00b67f09SDavid van Moolenbroek 		stack[pushed++] = cfg_list_next(element);
1314*00b67f09SDavid van Moolenbroek 		goto newlist;
1315*00b67f09SDavid van Moolenbroek 	}
1316*00b67f09SDavid van Moolenbroek 	if (pushed != 0) {
1317*00b67f09SDavid van Moolenbroek 		element = stack[--pushed];
1318*00b67f09SDavid van Moolenbroek 		goto resume;
1319*00b67f09SDavid van Moolenbroek 	}
1320*00b67f09SDavid van Moolenbroek  cleanup:
1321*00b67f09SDavid van Moolenbroek 	if (stack != NULL) {
1322*00b67f09SDavid van Moolenbroek 		void *ptr;
1323*00b67f09SDavid van Moolenbroek 
1324*00b67f09SDavid van Moolenbroek 		DE_CONST(stack, ptr);
1325*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, ptr, stackcount * sizeof(*stack));
1326*00b67f09SDavid van Moolenbroek 	}
1327*00b67f09SDavid van Moolenbroek 	isc_symtab_destroy(&symtab);
1328*00b67f09SDavid van Moolenbroek 	*countp = count;
1329*00b67f09SDavid van Moolenbroek 	return (result);
1330*00b67f09SDavid van Moolenbroek }
1331*00b67f09SDavid van Moolenbroek 
1332*00b67f09SDavid van Moolenbroek static isc_result_t
check_update_policy(const cfg_obj_t * policy,isc_log_t * logctx)1333*00b67f09SDavid van Moolenbroek check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
1334*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1335*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
1336*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
1337*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element2;
1338*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
1339*00b67f09SDavid van Moolenbroek 	const char *str;
1340*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
1341*00b67f09SDavid van Moolenbroek 
1342*00b67f09SDavid van Moolenbroek 	/* Check for "update-policy local;" */
1343*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isstring(policy) &&
1344*00b67f09SDavid van Moolenbroek 	    strcmp("local", cfg_obj_asstring(policy)) == 0)
1345*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1346*00b67f09SDavid van Moolenbroek 
1347*00b67f09SDavid van Moolenbroek 	/* Now check the grant policy */
1348*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(policy);
1349*00b67f09SDavid van Moolenbroek 	     element != NULL;
1350*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
1351*00b67f09SDavid van Moolenbroek 	{
1352*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *stmt = cfg_listelt_value(element);
1353*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
1354*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
1355*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
1356*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
1357*00b67f09SDavid van Moolenbroek 
1358*00b67f09SDavid van Moolenbroek 		dns_fixedname_init(&fixed);
1359*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(identity);
1360*00b67f09SDavid van Moolenbroek 		isc_buffer_constinit(&b, str, strlen(str));
1361*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, strlen(str));
1362*00b67f09SDavid van Moolenbroek 		tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
1363*00b67f09SDavid van Moolenbroek 					    dns_rootname, 0, NULL);
1364*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
1365*00b67f09SDavid van Moolenbroek 			cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
1366*00b67f09SDavid van Moolenbroek 				    "'%s' is not a valid name", str);
1367*00b67f09SDavid van Moolenbroek 			result = tresult;
1368*00b67f09SDavid van Moolenbroek 		}
1369*00b67f09SDavid van Moolenbroek 
1370*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS &&
1371*00b67f09SDavid van Moolenbroek 		    strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) {
1372*00b67f09SDavid van Moolenbroek 			dns_fixedname_init(&fixed);
1373*00b67f09SDavid van Moolenbroek 			str = cfg_obj_asstring(dname);
1374*00b67f09SDavid van Moolenbroek 			isc_buffer_constinit(&b, str, strlen(str));
1375*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b, strlen(str));
1376*00b67f09SDavid van Moolenbroek 			tresult = dns_name_fromtext(dns_fixedname_name(&fixed),
1377*00b67f09SDavid van Moolenbroek 						    &b, dns_rootname, 0, NULL);
1378*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
1379*00b67f09SDavid van Moolenbroek 				cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
1380*00b67f09SDavid van Moolenbroek 					    "'%s' is not a valid name", str);
1381*00b67f09SDavid van Moolenbroek 				result = tresult;
1382*00b67f09SDavid van Moolenbroek 			}
1383*00b67f09SDavid van Moolenbroek 		}
1384*00b67f09SDavid van Moolenbroek 
1385*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS &&
1386*00b67f09SDavid van Moolenbroek 		    strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 &&
1387*00b67f09SDavid van Moolenbroek 		    !dns_name_iswildcard(dns_fixedname_name(&fixed))) {
1388*00b67f09SDavid van Moolenbroek 			cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
1389*00b67f09SDavid van Moolenbroek 				    "'%s' is not a wildcard", str);
1390*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1391*00b67f09SDavid van Moolenbroek 		}
1392*00b67f09SDavid van Moolenbroek 
1393*00b67f09SDavid van Moolenbroek 		for (element2 = cfg_list_first(typelist);
1394*00b67f09SDavid van Moolenbroek 		     element2 != NULL;
1395*00b67f09SDavid van Moolenbroek 		     element2 = cfg_list_next(element2))
1396*00b67f09SDavid van Moolenbroek 		{
1397*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *typeobj;
1398*00b67f09SDavid van Moolenbroek 			isc_textregion_t r;
1399*00b67f09SDavid van Moolenbroek 			dns_rdatatype_t type;
1400*00b67f09SDavid van Moolenbroek 
1401*00b67f09SDavid van Moolenbroek 			typeobj = cfg_listelt_value(element2);
1402*00b67f09SDavid van Moolenbroek 			DE_CONST(cfg_obj_asstring(typeobj), r.base);
1403*00b67f09SDavid van Moolenbroek 			r.length = strlen(r.base);
1404*00b67f09SDavid van Moolenbroek 
1405*00b67f09SDavid van Moolenbroek 			tresult = dns_rdatatype_fromtext(&type, &r);
1406*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
1407*00b67f09SDavid van Moolenbroek 				cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
1408*00b67f09SDavid van Moolenbroek 					    "'%s' is not a valid type", r.base);
1409*00b67f09SDavid van Moolenbroek 				result = tresult;
1410*00b67f09SDavid van Moolenbroek 			}
1411*00b67f09SDavid van Moolenbroek 		}
1412*00b67f09SDavid van Moolenbroek 	}
1413*00b67f09SDavid van Moolenbroek 	return (result);
1414*00b67f09SDavid van Moolenbroek }
1415*00b67f09SDavid van Moolenbroek 
1416*00b67f09SDavid van Moolenbroek #define MASTERZONE	1
1417*00b67f09SDavid van Moolenbroek #define SLAVEZONE	2
1418*00b67f09SDavid van Moolenbroek #define STUBZONE	4
1419*00b67f09SDavid van Moolenbroek #define HINTZONE	8
1420*00b67f09SDavid van Moolenbroek #define FORWARDZONE	16
1421*00b67f09SDavid van Moolenbroek #define DELEGATIONZONE	32
1422*00b67f09SDavid van Moolenbroek #define STATICSTUBZONE	64
1423*00b67f09SDavid van Moolenbroek #define REDIRECTZONE	128
1424*00b67f09SDavid van Moolenbroek #define STREDIRECTZONE	0	/* Set to REDIRECTZONE to allow xfr-in. */
1425*00b67f09SDavid van Moolenbroek #define CHECKACL	512
1426*00b67f09SDavid van Moolenbroek 
1427*00b67f09SDavid van Moolenbroek typedef struct {
1428*00b67f09SDavid van Moolenbroek 	const char *name;
1429*00b67f09SDavid van Moolenbroek 	int allowed;
1430*00b67f09SDavid van Moolenbroek } optionstable;
1431*00b67f09SDavid van Moolenbroek 
1432*00b67f09SDavid van Moolenbroek static isc_result_t
check_nonzero(const cfg_obj_t * options,isc_log_t * logctx)1433*00b67f09SDavid van Moolenbroek check_nonzero(const cfg_obj_t *options, isc_log_t *logctx) {
1434*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1435*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj = NULL;
1436*00b67f09SDavid van Moolenbroek 	unsigned int i;
1437*00b67f09SDavid van Moolenbroek 
1438*00b67f09SDavid van Moolenbroek 	static const char *nonzero[] = { "max-retry-time", "min-retry-time",
1439*00b67f09SDavid van Moolenbroek 				 "max-refresh-time", "min-refresh-time" };
1440*00b67f09SDavid van Moolenbroek 	/*
1441*00b67f09SDavid van Moolenbroek 	 * Check if value is zero.
1442*00b67f09SDavid van Moolenbroek 	 */
1443*00b67f09SDavid van Moolenbroek 	for (i = 0; i < sizeof(nonzero) / sizeof(nonzero[0]); i++) {
1444*00b67f09SDavid van Moolenbroek 		obj = NULL;
1445*00b67f09SDavid van Moolenbroek 		if (cfg_map_get(options, nonzero[i], &obj) == ISC_R_SUCCESS &&
1446*00b67f09SDavid van Moolenbroek 		    cfg_obj_asuint32(obj) == 0) {
1447*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1448*00b67f09SDavid van Moolenbroek 				    "'%s' must not be zero", nonzero[i]);
1449*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1450*00b67f09SDavid van Moolenbroek 		}
1451*00b67f09SDavid van Moolenbroek 	}
1452*00b67f09SDavid van Moolenbroek 	return (result);
1453*00b67f09SDavid van Moolenbroek }
1454*00b67f09SDavid van Moolenbroek 
1455*00b67f09SDavid van Moolenbroek static isc_result_t
check_zoneconf(const cfg_obj_t * zconfig,const cfg_obj_t * voptions,const cfg_obj_t * config,isc_symtab_t * symtab,isc_symtab_t * files,dns_rdataclass_t defclass,cfg_aclconfctx_t * actx,isc_log_t * logctx,isc_mem_t * mctx)1456*00b67f09SDavid van Moolenbroek check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
1457*00b67f09SDavid van Moolenbroek 	       const cfg_obj_t *config, isc_symtab_t *symtab,
1458*00b67f09SDavid van Moolenbroek 	       isc_symtab_t *files, dns_rdataclass_t defclass,
1459*00b67f09SDavid van Moolenbroek 	       cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx)
1460*00b67f09SDavid van Moolenbroek {
1461*00b67f09SDavid van Moolenbroek 	const char *znamestr;
1462*00b67f09SDavid van Moolenbroek 	const char *typestr;
1463*00b67f09SDavid van Moolenbroek 	unsigned int ztype;
1464*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *zoptions, *goptions = NULL;
1465*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj = NULL;
1466*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1467*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
1468*00b67f09SDavid van Moolenbroek 	unsigned int i;
1469*00b67f09SDavid van Moolenbroek 	dns_rdataclass_t zclass;
1470*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixedname;
1471*00b67f09SDavid van Moolenbroek 	dns_name_t *zname = NULL;
1472*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
1473*00b67f09SDavid van Moolenbroek 	isc_boolean_t root = ISC_FALSE;
1474*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
1475*00b67f09SDavid van Moolenbroek 	isc_boolean_t dlz;
1476*00b67f09SDavid van Moolenbroek 	dns_masterformat_t masterformat;
1477*00b67f09SDavid van Moolenbroek 	isc_boolean_t ddns = ISC_FALSE;
1478*00b67f09SDavid van Moolenbroek 
1479*00b67f09SDavid van Moolenbroek 	static optionstable options[] = {
1480*00b67f09SDavid van Moolenbroek 	{ "allow-notify", SLAVEZONE | CHECKACL },
1481*00b67f09SDavid van Moolenbroek 	{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE |
1482*00b67f09SDavid van Moolenbroek 	  CHECKACL | STATICSTUBZONE },
1483*00b67f09SDavid van Moolenbroek 	{ "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
1484*00b67f09SDavid van Moolenbroek 	{ "allow-update", MASTERZONE | CHECKACL },
1485*00b67f09SDavid van Moolenbroek 	{ "allow-update-forwarding", SLAVEZONE | CHECKACL },
1486*00b67f09SDavid van Moolenbroek 	{ "also-notify", MASTERZONE | SLAVEZONE },
1487*00b67f09SDavid van Moolenbroek 	{ "auto-dnssec", MASTERZONE | SLAVEZONE },
1488*00b67f09SDavid van Moolenbroek 	{ "check-dup-records", MASTERZONE },
1489*00b67f09SDavid van Moolenbroek 	{ "check-mx", MASTERZONE },
1490*00b67f09SDavid van Moolenbroek 	{ "check-mx-cname", MASTERZONE },
1491*00b67f09SDavid van Moolenbroek 	{ "check-srv-cname", MASTERZONE },
1492*00b67f09SDavid van Moolenbroek 	{ "check-wildcard", MASTERZONE },
1493*00b67f09SDavid van Moolenbroek 	{ "database", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE },
1494*00b67f09SDavid van Moolenbroek 	{ "delegation-only", HINTZONE | STUBZONE | FORWARDZONE |
1495*00b67f09SDavid van Moolenbroek 	  DELEGATIONZONE },
1496*00b67f09SDavid van Moolenbroek 	{ "dialup", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE },
1497*00b67f09SDavid van Moolenbroek 	{ "dnssec-dnskey-kskonly", MASTERZONE | SLAVEZONE },
1498*00b67f09SDavid van Moolenbroek 	{ "dnssec-loadkeys-interval", MASTERZONE | SLAVEZONE },
1499*00b67f09SDavid van Moolenbroek 	{ "dnssec-secure-to-insecure", MASTERZONE },
1500*00b67f09SDavid van Moolenbroek 	{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | REDIRECTZONE },
1501*00b67f09SDavid van Moolenbroek 	{ "forward", MASTERZONE | SLAVEZONE | STUBZONE | STATICSTUBZONE |
1502*00b67f09SDavid van Moolenbroek 	  FORWARDZONE },
1503*00b67f09SDavid van Moolenbroek 	{ "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | STATICSTUBZONE |
1504*00b67f09SDavid van Moolenbroek 	  FORWARDZONE },
1505*00b67f09SDavid van Moolenbroek 	{ "integrity-check", MASTERZONE },
1506*00b67f09SDavid van Moolenbroek 	{ "ixfr-base", MASTERZONE | SLAVEZONE },
1507*00b67f09SDavid van Moolenbroek 	{ "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
1508*00b67f09SDavid van Moolenbroek 	{ "journal", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
1509*00b67f09SDavid van Moolenbroek 	{ "key-directory", MASTERZONE | SLAVEZONE },
1510*00b67f09SDavid van Moolenbroek 	{ "maintain-ixfr-base", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
1511*00b67f09SDavid van Moolenbroek 	{ "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE |
1512*00b67f09SDavid van Moolenbroek 	  REDIRECTZONE },
1513*00b67f09SDavid van Moolenbroek 	{ "masters", SLAVEZONE | STUBZONE | REDIRECTZONE },
1514*00b67f09SDavid van Moolenbroek 	{ "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
1515*00b67f09SDavid van Moolenbroek 	{ "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1516*00b67f09SDavid van Moolenbroek 	{ "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1517*00b67f09SDavid van Moolenbroek 	{ "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1518*00b67f09SDavid van Moolenbroek 	{ "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
1519*00b67f09SDavid van Moolenbroek 	{ "max-transfer-time-in", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1520*00b67f09SDavid van Moolenbroek 	{ "max-transfer-time-out", MASTERZONE | SLAVEZONE },
1521*00b67f09SDavid van Moolenbroek 	{ "max-zone-ttl", MASTERZONE | REDIRECTZONE },
1522*00b67f09SDavid van Moolenbroek 	{ "min-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1523*00b67f09SDavid van Moolenbroek 	{ "min-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1524*00b67f09SDavid van Moolenbroek 	{ "notify", MASTERZONE | SLAVEZONE },
1525*00b67f09SDavid van Moolenbroek 	{ "notify-source", MASTERZONE | SLAVEZONE },
1526*00b67f09SDavid van Moolenbroek 	{ "notify-source-v6", MASTERZONE | SLAVEZONE },
1527*00b67f09SDavid van Moolenbroek 	{ "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
1528*00b67f09SDavid van Moolenbroek 	{ "request-ixfr", SLAVEZONE | REDIRECTZONE },
1529*00b67f09SDavid van Moolenbroek 	{ "server-addresses", STATICSTUBZONE },
1530*00b67f09SDavid van Moolenbroek 	{ "server-names", STATICSTUBZONE },
1531*00b67f09SDavid van Moolenbroek 	{ "sig-re-signing-interval", MASTERZONE | SLAVEZONE },
1532*00b67f09SDavid van Moolenbroek 	{ "sig-signing-nodes", MASTERZONE | SLAVEZONE },
1533*00b67f09SDavid van Moolenbroek 	{ "sig-signing-signatures", MASTERZONE | SLAVEZONE },
1534*00b67f09SDavid van Moolenbroek 	{ "sig-signing-type", MASTERZONE | SLAVEZONE },
1535*00b67f09SDavid van Moolenbroek 	{ "sig-validity-interval", MASTERZONE | SLAVEZONE },
1536*00b67f09SDavid van Moolenbroek 	{ "signing", MASTERZONE | SLAVEZONE },
1537*00b67f09SDavid van Moolenbroek 	{ "transfer-source", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1538*00b67f09SDavid van Moolenbroek 	{ "transfer-source-v6", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1539*00b67f09SDavid van Moolenbroek 	{ "try-tcp-refresh", SLAVEZONE | STREDIRECTZONE },
1540*00b67f09SDavid van Moolenbroek 	{ "update-check-ksk", MASTERZONE | SLAVEZONE },
1541*00b67f09SDavid van Moolenbroek 	{ "update-policy", MASTERZONE },
1542*00b67f09SDavid van Moolenbroek 	{ "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE |
1543*00b67f09SDavid van Moolenbroek 	  STATICSTUBZONE | REDIRECTZONE },
1544*00b67f09SDavid van Moolenbroek 	};
1545*00b67f09SDavid van Moolenbroek 
1546*00b67f09SDavid van Moolenbroek 	static optionstable dialups[] = {
1547*00b67f09SDavid van Moolenbroek 	{ "notify", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
1548*00b67f09SDavid van Moolenbroek 	{ "notify-passive", SLAVEZONE | STREDIRECTZONE },
1549*00b67f09SDavid van Moolenbroek 	{ "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1550*00b67f09SDavid van Moolenbroek 	{ "passive", SLAVEZONE | STUBZONE | STREDIRECTZONE },
1551*00b67f09SDavid van Moolenbroek 	};
1552*00b67f09SDavid van Moolenbroek 
1553*00b67f09SDavid van Moolenbroek 	znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
1554*00b67f09SDavid van Moolenbroek 
1555*00b67f09SDavid van Moolenbroek 	zoptions = cfg_tuple_get(zconfig, "options");
1556*00b67f09SDavid van Moolenbroek 
1557*00b67f09SDavid van Moolenbroek 	if (config != NULL)
1558*00b67f09SDavid van Moolenbroek 		cfg_map_get(config, "options", &goptions);
1559*00b67f09SDavid van Moolenbroek 
1560*00b67f09SDavid van Moolenbroek 	obj = NULL;
1561*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(zoptions, "in-view", &obj);
1562*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
1563*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *fwd = NULL;
1564*00b67f09SDavid van Moolenbroek 		unsigned int maxopts = 1;
1565*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(zoptions, "forward", &fwd);
1566*00b67f09SDavid van Moolenbroek 		if (fwd != NULL)
1567*00b67f09SDavid van Moolenbroek 			maxopts++;
1568*00b67f09SDavid van Moolenbroek 		fwd = NULL;
1569*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(zoptions, "forwarders", &fwd);
1570*00b67f09SDavid van Moolenbroek 		if (fwd != NULL)
1571*00b67f09SDavid van Moolenbroek 			maxopts++;
1572*00b67f09SDavid van Moolenbroek 		if (cfg_map_count(zoptions) > maxopts) {
1573*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
1574*00b67f09SDavid van Moolenbroek 				    "zone '%s': 'in-view' used "
1575*00b67f09SDavid van Moolenbroek 				    "with incompatible zone options",
1576*00b67f09SDavid van Moolenbroek 				    znamestr);
1577*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
1578*00b67f09SDavid van Moolenbroek 		}
1579*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
1580*00b67f09SDavid van Moolenbroek 	}
1581*00b67f09SDavid van Moolenbroek 
1582*00b67f09SDavid van Moolenbroek 	obj = NULL;
1583*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(zoptions, "type", &obj);
1584*00b67f09SDavid van Moolenbroek 	if (obj == NULL) {
1585*00b67f09SDavid van Moolenbroek 		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
1586*00b67f09SDavid van Moolenbroek 			    "zone '%s': type not present", znamestr);
1587*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1588*00b67f09SDavid van Moolenbroek 	}
1589*00b67f09SDavid van Moolenbroek 
1590*00b67f09SDavid van Moolenbroek 	typestr = cfg_obj_asstring(obj);
1591*00b67f09SDavid van Moolenbroek 	if (strcasecmp(typestr, "master") == 0)
1592*00b67f09SDavid van Moolenbroek 		ztype = MASTERZONE;
1593*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "slave") == 0)
1594*00b67f09SDavid van Moolenbroek 		ztype = SLAVEZONE;
1595*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "stub") == 0)
1596*00b67f09SDavid van Moolenbroek 		ztype = STUBZONE;
1597*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "static-stub") == 0)
1598*00b67f09SDavid van Moolenbroek 		ztype = STATICSTUBZONE;
1599*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "forward") == 0)
1600*00b67f09SDavid van Moolenbroek 		ztype = FORWARDZONE;
1601*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "hint") == 0)
1602*00b67f09SDavid van Moolenbroek 		ztype = HINTZONE;
1603*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "delegation-only") == 0)
1604*00b67f09SDavid van Moolenbroek 		ztype = DELEGATIONZONE;
1605*00b67f09SDavid van Moolenbroek 	else if (strcasecmp(typestr, "redirect") == 0)
1606*00b67f09SDavid van Moolenbroek 		ztype = REDIRECTZONE;
1607*00b67f09SDavid van Moolenbroek 	else {
1608*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1609*00b67f09SDavid van Moolenbroek 			    "zone '%s': invalid type %s",
1610*00b67f09SDavid van Moolenbroek 			    znamestr, typestr);
1611*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1612*00b67f09SDavid van Moolenbroek 	}
1613*00b67f09SDavid van Moolenbroek 
1614*00b67f09SDavid van Moolenbroek 	if (ztype == REDIRECTZONE && strcmp(znamestr, ".") != 0) {
1615*00b67f09SDavid van Moolenbroek 		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
1616*00b67f09SDavid van Moolenbroek 			    "redirect zones must be called \".\"");
1617*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1618*00b67f09SDavid van Moolenbroek 	}
1619*00b67f09SDavid van Moolenbroek 	obj = cfg_tuple_get(zconfig, "class");
1620*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isstring(obj)) {
1621*00b67f09SDavid van Moolenbroek 		isc_textregion_t r;
1622*00b67f09SDavid van Moolenbroek 
1623*00b67f09SDavid van Moolenbroek 		DE_CONST(cfg_obj_asstring(obj), r.base);
1624*00b67f09SDavid van Moolenbroek 		r.length = strlen(r.base);
1625*00b67f09SDavid van Moolenbroek 		result = dns_rdataclass_fromtext(&zclass, &r);
1626*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
1627*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1628*00b67f09SDavid van Moolenbroek 				    "zone '%s': invalid class %s",
1629*00b67f09SDavid van Moolenbroek 				    znamestr, r.base);
1630*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
1631*00b67f09SDavid van Moolenbroek 		}
1632*00b67f09SDavid van Moolenbroek 		if (zclass != defclass) {
1633*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1634*00b67f09SDavid van Moolenbroek 				    "zone '%s': class '%s' does not "
1635*00b67f09SDavid van Moolenbroek 				    "match view/default class",
1636*00b67f09SDavid van Moolenbroek 				    znamestr, r.base);
1637*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
1638*00b67f09SDavid van Moolenbroek 		}
1639*00b67f09SDavid van Moolenbroek 	}
1640*00b67f09SDavid van Moolenbroek 
1641*00b67f09SDavid van Moolenbroek 	/*
1642*00b67f09SDavid van Moolenbroek 	 * Look for an already existing zone.
1643*00b67f09SDavid van Moolenbroek 	 * We need to make this canonical as isc_symtab_define()
1644*00b67f09SDavid van Moolenbroek 	 * deals with strings.
1645*00b67f09SDavid van Moolenbroek 	 */
1646*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixedname);
1647*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&b, znamestr, strlen(znamestr));
1648*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&b, strlen(znamestr));
1649*00b67f09SDavid van Moolenbroek 	tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
1650*00b67f09SDavid van Moolenbroek 				    dns_rootname, DNS_NAME_DOWNCASE, NULL);
1651*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS) {
1652*00b67f09SDavid van Moolenbroek 		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
1653*00b67f09SDavid van Moolenbroek 			    "zone '%s': is not a valid name", znamestr);
1654*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
1655*00b67f09SDavid van Moolenbroek 	} else {
1656*00b67f09SDavid van Moolenbroek 		char namebuf[DNS_NAME_FORMATSIZE];
1657*00b67f09SDavid van Moolenbroek 
1658*00b67f09SDavid van Moolenbroek 		zname = dns_fixedname_name(&fixedname);
1659*00b67f09SDavid van Moolenbroek 		dns_name_format(zname, namebuf, sizeof(namebuf));
1660*00b67f09SDavid van Moolenbroek 		tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 :
1661*00b67f09SDavid van Moolenbroek 				    ztype == REDIRECTZONE ? 2 : 3,
1662*00b67f09SDavid van Moolenbroek 				    symtab, "zone '%s': already exists "
1663*00b67f09SDavid van Moolenbroek 				    "previous definition: %s:%u", logctx, mctx);
1664*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
1665*00b67f09SDavid van Moolenbroek 			result = tresult;
1666*00b67f09SDavid van Moolenbroek 		if (dns_name_equal(zname, dns_rootname))
1667*00b67f09SDavid van Moolenbroek 			root = ISC_TRUE;
1668*00b67f09SDavid van Moolenbroek 	}
1669*00b67f09SDavid van Moolenbroek 
1670*00b67f09SDavid van Moolenbroek 	/*
1671*00b67f09SDavid van Moolenbroek 	 * Check if value is zero.
1672*00b67f09SDavid van Moolenbroek 	 */
1673*00b67f09SDavid van Moolenbroek 	if (check_nonzero(zoptions, logctx) != ISC_R_SUCCESS)
1674*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
1675*00b67f09SDavid van Moolenbroek 
1676*00b67f09SDavid van Moolenbroek 	/*
1677*00b67f09SDavid van Moolenbroek 	 * Look for inappropriate options for the given zone type.
1678*00b67f09SDavid van Moolenbroek 	 * Check that ACLs expand correctly.
1679*00b67f09SDavid van Moolenbroek 	 */
1680*00b67f09SDavid van Moolenbroek 	for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
1681*00b67f09SDavid van Moolenbroek 		obj = NULL;
1682*00b67f09SDavid van Moolenbroek 		if ((options[i].allowed & ztype) == 0 &&
1683*00b67f09SDavid van Moolenbroek 		    cfg_map_get(zoptions, options[i].name, &obj) ==
1684*00b67f09SDavid van Moolenbroek 		    ISC_R_SUCCESS)
1685*00b67f09SDavid van Moolenbroek 		{
1686*00b67f09SDavid van Moolenbroek 			if (strcmp(options[i].name, "allow-update") != 0 ||
1687*00b67f09SDavid van Moolenbroek 			    ztype != SLAVEZONE) {
1688*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1689*00b67f09SDavid van Moolenbroek 					    "option '%s' is not allowed "
1690*00b67f09SDavid van Moolenbroek 					    "in '%s' zone '%s'",
1691*00b67f09SDavid van Moolenbroek 					    options[i].name, typestr,
1692*00b67f09SDavid van Moolenbroek 					    znamestr);
1693*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
1694*00b67f09SDavid van Moolenbroek 			} else
1695*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
1696*00b67f09SDavid van Moolenbroek 					    "option '%s' is not allowed "
1697*00b67f09SDavid van Moolenbroek 					    "in '%s' zone '%s'",
1698*00b67f09SDavid van Moolenbroek 					    options[i].name, typestr,
1699*00b67f09SDavid van Moolenbroek 					    znamestr);
1700*00b67f09SDavid van Moolenbroek 		}
1701*00b67f09SDavid van Moolenbroek 		obj = NULL;
1702*00b67f09SDavid van Moolenbroek 		if ((options[i].allowed & ztype) != 0 &&
1703*00b67f09SDavid van Moolenbroek 		    (options[i].allowed & CHECKACL) != 0) {
1704*00b67f09SDavid van Moolenbroek 
1705*00b67f09SDavid van Moolenbroek 			tresult = checkacl(options[i].name, actx, zconfig,
1706*00b67f09SDavid van Moolenbroek 					   voptions, config, logctx, mctx);
1707*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
1708*00b67f09SDavid van Moolenbroek 				result = tresult;
1709*00b67f09SDavid van Moolenbroek 		}
1710*00b67f09SDavid van Moolenbroek 
1711*00b67f09SDavid van Moolenbroek 	}
1712*00b67f09SDavid van Moolenbroek 
1713*00b67f09SDavid van Moolenbroek 	/*
1714*00b67f09SDavid van Moolenbroek 	 * Master & slave zones may have an "also-notify" field, but
1715*00b67f09SDavid van Moolenbroek 	 * shouldn't if notify is disabled.
1716*00b67f09SDavid van Moolenbroek 	 */
1717*00b67f09SDavid van Moolenbroek 	if (ztype == MASTERZONE || ztype == SLAVEZONE ) {
1718*00b67f09SDavid van Moolenbroek 		isc_boolean_t donotify = ISC_TRUE;
1719*00b67f09SDavid van Moolenbroek 
1720*00b67f09SDavid van Moolenbroek 		obj = NULL;
1721*00b67f09SDavid van Moolenbroek 		tresult = cfg_map_get(zoptions, "notify", &obj);
1722*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS && voptions != NULL)
1723*00b67f09SDavid van Moolenbroek 			tresult = cfg_map_get(voptions, "notify", &obj);
1724*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS && goptions != NULL)
1725*00b67f09SDavid van Moolenbroek 			tresult = cfg_map_get(goptions, "notify", &obj);
1726*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS) {
1727*00b67f09SDavid van Moolenbroek 			if (cfg_obj_isboolean(obj))
1728*00b67f09SDavid van Moolenbroek 				donotify = cfg_obj_asboolean(obj);
1729*00b67f09SDavid van Moolenbroek 			else {
1730*00b67f09SDavid van Moolenbroek 				const char *notifystr = cfg_obj_asstring(obj);
1731*00b67f09SDavid van Moolenbroek 				if (ztype != MASTERZONE &&
1732*00b67f09SDavid van Moolenbroek 				    strcasecmp(notifystr, "master-only") == 0)
1733*00b67f09SDavid van Moolenbroek 					donotify = ISC_FALSE;
1734*00b67f09SDavid van Moolenbroek 			}
1735*00b67f09SDavid van Moolenbroek 		}
1736*00b67f09SDavid van Moolenbroek 
1737*00b67f09SDavid van Moolenbroek 		obj = NULL;
1738*00b67f09SDavid van Moolenbroek 		tresult = cfg_map_get(zoptions, "also-notify", &obj);
1739*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS && !donotify) {
1740*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zoptions, logctx, ISC_LOG_WARNING,
1741*00b67f09SDavid van Moolenbroek 				    "zone '%s': 'also-notify' set but "
1742*00b67f09SDavid van Moolenbroek 				    "'notify' is disabled", znamestr);
1743*00b67f09SDavid van Moolenbroek 		} else if (tresult == ISC_R_SUCCESS) {
1744*00b67f09SDavid van Moolenbroek 			isc_uint32_t count;
1745*00b67f09SDavid van Moolenbroek 			tresult = validate_masters(obj, config, &count,
1746*00b67f09SDavid van Moolenbroek 						   logctx, mctx);
1747*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
1748*00b67f09SDavid van Moolenbroek 				result = tresult;
1749*00b67f09SDavid van Moolenbroek 		}
1750*00b67f09SDavid van Moolenbroek 	}
1751*00b67f09SDavid van Moolenbroek 
1752*00b67f09SDavid van Moolenbroek 	/*
1753*00b67f09SDavid van Moolenbroek 	 * Slave & stub zones must have a "masters" field.
1754*00b67f09SDavid van Moolenbroek 	 */
1755*00b67f09SDavid van Moolenbroek 	if (ztype == SLAVEZONE || ztype == STUBZONE) {
1756*00b67f09SDavid van Moolenbroek 		obj = NULL;
1757*00b67f09SDavid van Moolenbroek 		if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
1758*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
1759*00b67f09SDavid van Moolenbroek 				    "zone '%s': missing 'masters' entry",
1760*00b67f09SDavid van Moolenbroek 				    znamestr);
1761*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1762*00b67f09SDavid van Moolenbroek 		} else {
1763*00b67f09SDavid van Moolenbroek 			isc_uint32_t count;
1764*00b67f09SDavid van Moolenbroek 			tresult = validate_masters(obj, config, &count,
1765*00b67f09SDavid van Moolenbroek 						   logctx, mctx);
1766*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
1767*00b67f09SDavid van Moolenbroek 				result = tresult;
1768*00b67f09SDavid van Moolenbroek 			if (tresult == ISC_R_SUCCESS && count == 0) {
1769*00b67f09SDavid van Moolenbroek 				cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
1770*00b67f09SDavid van Moolenbroek 					    "zone '%s': empty 'masters' entry",
1771*00b67f09SDavid van Moolenbroek 					    znamestr);
1772*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1773*00b67f09SDavid van Moolenbroek 			}
1774*00b67f09SDavid van Moolenbroek 		}
1775*00b67f09SDavid van Moolenbroek 	}
1776*00b67f09SDavid van Moolenbroek 
1777*00b67f09SDavid van Moolenbroek 	/*
1778*00b67f09SDavid van Moolenbroek 	 * Master zones can't have both "allow-update" and "update-policy".
1779*00b67f09SDavid van Moolenbroek 	 */
1780*00b67f09SDavid van Moolenbroek 	if (ztype == MASTERZONE || ztype == SLAVEZONE) {
1781*00b67f09SDavid van Moolenbroek 		isc_boolean_t signing = ISC_FALSE;
1782*00b67f09SDavid van Moolenbroek 		isc_result_t res1, res2, res3;
1783*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *au = NULL;
1784*00b67f09SDavid van Moolenbroek 		const char *arg;
1785*00b67f09SDavid van Moolenbroek 
1786*00b67f09SDavid van Moolenbroek 		obj = NULL;
1787*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "allow-update", &au);
1788*00b67f09SDavid van Moolenbroek 		obj = NULL;
1789*00b67f09SDavid van Moolenbroek 		res2 = cfg_map_get(zoptions, "update-policy", &obj);
1790*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
1791*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1792*00b67f09SDavid van Moolenbroek 				    "zone '%s': 'allow-update' is ignored "
1793*00b67f09SDavid van Moolenbroek 				    "when 'update-policy' is present",
1794*00b67f09SDavid van Moolenbroek 				    znamestr);
1795*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1796*00b67f09SDavid van Moolenbroek 		} else if (res2 == ISC_R_SUCCESS) {
1797*00b67f09SDavid van Moolenbroek 			res3 = check_update_policy(obj, logctx);
1798*00b67f09SDavid van Moolenbroek 			if (res3 != ISC_R_SUCCESS)
1799*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1800*00b67f09SDavid van Moolenbroek 		}
1801*00b67f09SDavid van Moolenbroek 
1802*00b67f09SDavid van Moolenbroek 		/*
1803*00b67f09SDavid van Moolenbroek 		 * To determine whether auto-dnssec is allowed,
1804*00b67f09SDavid van Moolenbroek 		 * we should also check for allow-update at the
1805*00b67f09SDavid van Moolenbroek 		 * view and options levels.
1806*00b67f09SDavid van Moolenbroek 		 */
1807*00b67f09SDavid van Moolenbroek 		if (res1 != ISC_R_SUCCESS && voptions != NULL)
1808*00b67f09SDavid van Moolenbroek 			res1 = cfg_map_get(voptions, "allow-update", &au);
1809*00b67f09SDavid van Moolenbroek 		if (res1 != ISC_R_SUCCESS && goptions != NULL)
1810*00b67f09SDavid van Moolenbroek 			res1 = cfg_map_get(goptions, "allow-update", &au);
1811*00b67f09SDavid van Moolenbroek 
1812*00b67f09SDavid van Moolenbroek 		if (res2 == ISC_R_SUCCESS)
1813*00b67f09SDavid van Moolenbroek 			ddns = ISC_TRUE;
1814*00b67f09SDavid van Moolenbroek 		else if (res1 == ISC_R_SUCCESS) {
1815*00b67f09SDavid van Moolenbroek 			dns_acl_t *acl = NULL;
1816*00b67f09SDavid van Moolenbroek 			res1 = cfg_acl_fromconfig(au, config, logctx,
1817*00b67f09SDavid van Moolenbroek 						  actx, mctx, 0, &acl);
1818*00b67f09SDavid van Moolenbroek 			if (res1 != ISC_R_SUCCESS) {
1819*00b67f09SDavid van Moolenbroek 				cfg_obj_log(au, logctx, ISC_LOG_ERROR,
1820*00b67f09SDavid van Moolenbroek 					    "acl expansion failed: %s",
1821*00b67f09SDavid van Moolenbroek 					    isc_result_totext(result));
1822*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1823*00b67f09SDavid van Moolenbroek 			} else if (acl != NULL) {
1824*00b67f09SDavid van Moolenbroek 				if (!dns_acl_isnone(acl))
1825*00b67f09SDavid van Moolenbroek 					ddns = ISC_TRUE;
1826*00b67f09SDavid van Moolenbroek 				dns_acl_detach(&acl);
1827*00b67f09SDavid van Moolenbroek 			}
1828*00b67f09SDavid van Moolenbroek 		}
1829*00b67f09SDavid van Moolenbroek 
1830*00b67f09SDavid van Moolenbroek 		obj = NULL;
1831*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "inline-signing", &obj);
1832*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS)
1833*00b67f09SDavid van Moolenbroek 			signing = cfg_obj_asboolean(obj);
1834*00b67f09SDavid van Moolenbroek 
1835*00b67f09SDavid van Moolenbroek 		obj = NULL;
1836*00b67f09SDavid van Moolenbroek 		arg = "off";
1837*00b67f09SDavid van Moolenbroek 		res3 = cfg_map_get(zoptions, "auto-dnssec", &obj);
1838*00b67f09SDavid van Moolenbroek 		if (res3 == ISC_R_SUCCESS)
1839*00b67f09SDavid van Moolenbroek 			arg = cfg_obj_asstring(obj);
1840*00b67f09SDavid van Moolenbroek 		if (strcasecmp(arg, "off") != 0 && !ddns && !signing) {
1841*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1842*00b67f09SDavid van Moolenbroek 				    "'auto-dnssec %s;' requires%s "
1843*00b67f09SDavid van Moolenbroek 				    "inline-signing to be configured for "
1844*00b67f09SDavid van Moolenbroek 				    "the zone", arg,
1845*00b67f09SDavid van Moolenbroek 				    (ztype == MASTERZONE) ?
1846*00b67f09SDavid van Moolenbroek 					 " dynamic DNS or" : "");
1847*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1848*00b67f09SDavid van Moolenbroek 		}
1849*00b67f09SDavid van Moolenbroek 
1850*00b67f09SDavid van Moolenbroek 		obj = NULL;
1851*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
1852*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS) {
1853*00b67f09SDavid van Moolenbroek 			isc_uint32_t type = cfg_obj_asuint32(obj);
1854*00b67f09SDavid van Moolenbroek 			if (type < 0xff00U || type > 0xffffU)
1855*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1856*00b67f09SDavid van Moolenbroek 					    "sig-signing-type: %u out of "
1857*00b67f09SDavid van Moolenbroek 					    "range [%u..%u]", type,
1858*00b67f09SDavid van Moolenbroek 					    0xff00U, 0xffffU);
1859*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1860*00b67f09SDavid van Moolenbroek 		}
1861*00b67f09SDavid van Moolenbroek 
1862*00b67f09SDavid van Moolenbroek 		obj = NULL;
1863*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "dnssec-dnskey-kskonly", &obj);
1864*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) {
1865*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1866*00b67f09SDavid van Moolenbroek 				    "dnssec-dnskey-kskonly: requires "
1867*00b67f09SDavid van Moolenbroek 				    "inline-signing when used in slave zone");
1868*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1869*00b67f09SDavid van Moolenbroek 		}
1870*00b67f09SDavid van Moolenbroek 
1871*00b67f09SDavid van Moolenbroek 		obj = NULL;
1872*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "dnssec-loadkeys-interval", &obj);
1873*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) {
1874*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1875*00b67f09SDavid van Moolenbroek 				    "dnssec-loadkeys-interval: requires "
1876*00b67f09SDavid van Moolenbroek 				    "inline-signing when used in slave zone");
1877*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1878*00b67f09SDavid van Moolenbroek 		}
1879*00b67f09SDavid van Moolenbroek 
1880*00b67f09SDavid van Moolenbroek 		obj = NULL;
1881*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "update-check-ksk", &obj);
1882*00b67f09SDavid van Moolenbroek 		if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) {
1883*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1884*00b67f09SDavid van Moolenbroek 				    "update-check-ksk: requires "
1885*00b67f09SDavid van Moolenbroek 				    "inline-signing when used in slave zone");
1886*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1887*00b67f09SDavid van Moolenbroek 		}
1888*00b67f09SDavid van Moolenbroek 	}
1889*00b67f09SDavid van Moolenbroek 
1890*00b67f09SDavid van Moolenbroek 	/*
1891*00b67f09SDavid van Moolenbroek 	 * Check the excessively complicated "dialup" option.
1892*00b67f09SDavid van Moolenbroek 	 */
1893*00b67f09SDavid van Moolenbroek 	if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
1894*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *dialup = NULL;
1895*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(zoptions, "dialup", &dialup);
1896*00b67f09SDavid van Moolenbroek 		if (dialup != NULL && cfg_obj_isstring(dialup)) {
1897*00b67f09SDavid van Moolenbroek 			const char *str = cfg_obj_asstring(dialup);
1898*00b67f09SDavid van Moolenbroek 			for (i = 0;
1899*00b67f09SDavid van Moolenbroek 			     i < sizeof(dialups) / sizeof(dialups[0]);
1900*00b67f09SDavid van Moolenbroek 			     i++)
1901*00b67f09SDavid van Moolenbroek 			{
1902*00b67f09SDavid van Moolenbroek 				if (strcasecmp(dialups[i].name, str) != 0)
1903*00b67f09SDavid van Moolenbroek 					continue;
1904*00b67f09SDavid van Moolenbroek 				if ((dialups[i].allowed & ztype) == 0) {
1905*00b67f09SDavid van Moolenbroek 					cfg_obj_log(obj, logctx,
1906*00b67f09SDavid van Moolenbroek 						    ISC_LOG_ERROR,
1907*00b67f09SDavid van Moolenbroek 						    "dialup type '%s' is not "
1908*00b67f09SDavid van Moolenbroek 						    "allowed in '%s' "
1909*00b67f09SDavid van Moolenbroek 						    "zone '%s'",
1910*00b67f09SDavid van Moolenbroek 						    str, typestr, znamestr);
1911*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
1912*00b67f09SDavid van Moolenbroek 				}
1913*00b67f09SDavid van Moolenbroek 				break;
1914*00b67f09SDavid van Moolenbroek 			}
1915*00b67f09SDavid van Moolenbroek 			if (i == sizeof(dialups) / sizeof(dialups[0])) {
1916*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1917*00b67f09SDavid van Moolenbroek 					    "invalid dialup type '%s' in zone "
1918*00b67f09SDavid van Moolenbroek 					    "'%s'", str, znamestr);
1919*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1920*00b67f09SDavid van Moolenbroek 			}
1921*00b67f09SDavid van Moolenbroek 		}
1922*00b67f09SDavid van Moolenbroek 	}
1923*00b67f09SDavid van Moolenbroek 
1924*00b67f09SDavid van Moolenbroek 	/*
1925*00b67f09SDavid van Moolenbroek 	 * Check that forwarding is reasonable.
1926*00b67f09SDavid van Moolenbroek 	 */
1927*00b67f09SDavid van Moolenbroek 	obj = NULL;
1928*00b67f09SDavid van Moolenbroek 	if (root) {
1929*00b67f09SDavid van Moolenbroek 		if (voptions != NULL)
1930*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(voptions, "forwarders", &obj);
1931*00b67f09SDavid van Moolenbroek 		if (obj == NULL && goptions != NULL)
1932*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(goptions, "forwarders", &obj);
1933*00b67f09SDavid van Moolenbroek 	}
1934*00b67f09SDavid van Moolenbroek 	if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS)
1935*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
1936*00b67f09SDavid van Moolenbroek 
1937*00b67f09SDavid van Moolenbroek 	/*
1938*00b67f09SDavid van Moolenbroek 	 * Check validity of static stub server addresses.
1939*00b67f09SDavid van Moolenbroek 	 */
1940*00b67f09SDavid van Moolenbroek 	obj = NULL;
1941*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(zoptions, "server-addresses", &obj);
1942*00b67f09SDavid van Moolenbroek 	if (ztype == STATICSTUBZONE && obj != NULL) {
1943*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
1944*00b67f09SDavid van Moolenbroek 		     element != NULL;
1945*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
1946*00b67f09SDavid van Moolenbroek 		{
1947*00b67f09SDavid van Moolenbroek 			isc_sockaddr_t sa;
1948*00b67f09SDavid van Moolenbroek 			isc_netaddr_t na;
1949*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
1950*00b67f09SDavid van Moolenbroek 			sa = *cfg_obj_assockaddr(obj);
1951*00b67f09SDavid van Moolenbroek 
1952*00b67f09SDavid van Moolenbroek 			if (isc_sockaddr_getport(&sa) != 0) {
1953*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1954*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1955*00b67f09SDavid van Moolenbroek 					    "port is not configurable for "
1956*00b67f09SDavid van Moolenbroek 					    "static stub server-addresses");
1957*00b67f09SDavid van Moolenbroek 			}
1958*00b67f09SDavid van Moolenbroek 
1959*00b67f09SDavid van Moolenbroek 			isc_netaddr_fromsockaddr(&na, &sa);
1960*00b67f09SDavid van Moolenbroek 			if (isc_netaddr_getzone(&na) != 0) {
1961*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1962*00b67f09SDavid van Moolenbroek 				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
1963*00b67f09SDavid van Moolenbroek 					    "scoped address is not allowed "
1964*00b67f09SDavid van Moolenbroek 					    "for static stub "
1965*00b67f09SDavid van Moolenbroek 					    "server-addresses");
1966*00b67f09SDavid van Moolenbroek 			}
1967*00b67f09SDavid van Moolenbroek 		}
1968*00b67f09SDavid van Moolenbroek 	}
1969*00b67f09SDavid van Moolenbroek 
1970*00b67f09SDavid van Moolenbroek 	/*
1971*00b67f09SDavid van Moolenbroek 	 * Check validity of static stub server names.
1972*00b67f09SDavid van Moolenbroek 	 */
1973*00b67f09SDavid van Moolenbroek 	obj = NULL;
1974*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(zoptions, "server-names", &obj);
1975*00b67f09SDavid van Moolenbroek 	if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) {
1976*00b67f09SDavid van Moolenbroek 		for (element = cfg_list_first(obj);
1977*00b67f09SDavid van Moolenbroek 		     element != NULL;
1978*00b67f09SDavid van Moolenbroek 		     element = cfg_list_next(element))
1979*00b67f09SDavid van Moolenbroek 		{
1980*00b67f09SDavid van Moolenbroek 			const char *snamestr;
1981*00b67f09SDavid van Moolenbroek 			dns_fixedname_t fixed_sname;
1982*00b67f09SDavid van Moolenbroek 			isc_buffer_t b2;
1983*00b67f09SDavid van Moolenbroek 			dns_name_t *sname;
1984*00b67f09SDavid van Moolenbroek 
1985*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element);
1986*00b67f09SDavid van Moolenbroek 			snamestr = cfg_obj_asstring(obj);
1987*00b67f09SDavid van Moolenbroek 
1988*00b67f09SDavid van Moolenbroek 			dns_fixedname_init(&fixed_sname);
1989*00b67f09SDavid van Moolenbroek 			isc_buffer_constinit(&b2, snamestr, strlen(snamestr));
1990*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b2, strlen(snamestr));
1991*00b67f09SDavid van Moolenbroek 			sname = dns_fixedname_name(&fixed_sname);
1992*00b67f09SDavid van Moolenbroek 			tresult = dns_name_fromtext(sname, &b2, dns_rootname,
1993*00b67f09SDavid van Moolenbroek 						    0, NULL);
1994*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
1995*00b67f09SDavid van Moolenbroek 				cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
1996*00b67f09SDavid van Moolenbroek 					    "server-name '%s' is not a valid "
1997*00b67f09SDavid van Moolenbroek 					    "name", snamestr);
1998*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
1999*00b67f09SDavid van Moolenbroek 			} else if (dns_name_issubdomain(sname, zname)) {
2000*00b67f09SDavid van Moolenbroek 				cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
2001*00b67f09SDavid van Moolenbroek 					    "server-name '%s' must not be a "
2002*00b67f09SDavid van Moolenbroek 					    "subdomain of zone name '%s'",
2003*00b67f09SDavid van Moolenbroek 					    snamestr, znamestr);
2004*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2005*00b67f09SDavid van Moolenbroek 			}
2006*00b67f09SDavid van Moolenbroek 		}
2007*00b67f09SDavid van Moolenbroek 	}
2008*00b67f09SDavid van Moolenbroek 
2009*00b67f09SDavid van Moolenbroek 
2010*00b67f09SDavid van Moolenbroek 	/*
2011*00b67f09SDavid van Moolenbroek 	 * Check that max-zone-ttl isn't used with masterfile-format map
2012*00b67f09SDavid van Moolenbroek 	 */
2013*00b67f09SDavid van Moolenbroek 	masterformat = dns_masterformat_text;
2014*00b67f09SDavid van Moolenbroek 	obj = NULL;
2015*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(zoptions, "masterfile-format", &obj);
2016*00b67f09SDavid van Moolenbroek 	if (obj != NULL) {
2017*00b67f09SDavid van Moolenbroek 		const char *masterformatstr = cfg_obj_asstring(obj);
2018*00b67f09SDavid van Moolenbroek 		if (strcasecmp(masterformatstr, "text") == 0)
2019*00b67f09SDavid van Moolenbroek 			masterformat = dns_masterformat_text;
2020*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(masterformatstr, "raw") == 0)
2021*00b67f09SDavid van Moolenbroek 			masterformat = dns_masterformat_raw;
2022*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(masterformatstr, "map") == 0)
2023*00b67f09SDavid van Moolenbroek 			masterformat = dns_masterformat_map;
2024*00b67f09SDavid van Moolenbroek 		else
2025*00b67f09SDavid van Moolenbroek 			INSIST(0);
2026*00b67f09SDavid van Moolenbroek 	}
2027*00b67f09SDavid van Moolenbroek 
2028*00b67f09SDavid van Moolenbroek 	if (masterformat == dns_masterformat_map) {
2029*00b67f09SDavid van Moolenbroek 		obj = NULL;
2030*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(zoptions, "max-zone-ttl", &obj);
2031*00b67f09SDavid van Moolenbroek 		if (obj == NULL && voptions != NULL)
2032*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(voptions, "max-zone-ttl", &obj);
2033*00b67f09SDavid van Moolenbroek 		if (obj == NULL && goptions !=NULL)
2034*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(goptions, "max-zone-ttl", &obj);
2035*00b67f09SDavid van Moolenbroek 		if (obj != NULL) {
2036*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
2037*00b67f09SDavid van Moolenbroek 				    "zone '%s': 'max-zone-ttl' is not "
2038*00b67f09SDavid van Moolenbroek 				    "compatible with 'masterfile-format map'",
2039*00b67f09SDavid van Moolenbroek 				    znamestr);
2040*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2041*00b67f09SDavid van Moolenbroek 		}
2042*00b67f09SDavid van Moolenbroek 	}
2043*00b67f09SDavid van Moolenbroek 
2044*00b67f09SDavid van Moolenbroek 	/*
2045*00b67f09SDavid van Moolenbroek 	 * Warn if key-directory doesn't exist
2046*00b67f09SDavid van Moolenbroek 	 */
2047*00b67f09SDavid van Moolenbroek 	obj = NULL;
2048*00b67f09SDavid van Moolenbroek 	tresult = cfg_map_get(zoptions, "key-directory", &obj);
2049*00b67f09SDavid van Moolenbroek 	if (tresult == ISC_R_SUCCESS) {
2050*00b67f09SDavid van Moolenbroek 		const char *dir = cfg_obj_asstring(obj);
2051*00b67f09SDavid van Moolenbroek 		tresult = isc_file_isdirectory(dir);
2052*00b67f09SDavid van Moolenbroek 		switch (tresult) {
2053*00b67f09SDavid van Moolenbroek 		case ISC_R_SUCCESS:
2054*00b67f09SDavid van Moolenbroek 			break;
2055*00b67f09SDavid van Moolenbroek 		case ISC_R_FILENOTFOUND:
2056*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
2057*00b67f09SDavid van Moolenbroek 				    "key-directory: '%s' does not exist",
2058*00b67f09SDavid van Moolenbroek 				    dir);
2059*00b67f09SDavid van Moolenbroek 			break;
2060*00b67f09SDavid van Moolenbroek 		case ISC_R_INVALIDFILE:
2061*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
2062*00b67f09SDavid van Moolenbroek 				    "key-directory: '%s' is not a directory",
2063*00b67f09SDavid van Moolenbroek 				    dir);
2064*00b67f09SDavid van Moolenbroek 			break;
2065*00b67f09SDavid van Moolenbroek 		default:
2066*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
2067*00b67f09SDavid van Moolenbroek 				    "key-directory: '%s' %s",
2068*00b67f09SDavid van Moolenbroek 				    dir, isc_result_totext(tresult));
2069*00b67f09SDavid van Moolenbroek 			result = tresult;
2070*00b67f09SDavid van Moolenbroek 		}
2071*00b67f09SDavid van Moolenbroek 	}
2072*00b67f09SDavid van Moolenbroek 
2073*00b67f09SDavid van Moolenbroek 	/*
2074*00b67f09SDavid van Moolenbroek 	 * Check various options.
2075*00b67f09SDavid van Moolenbroek 	 */
2076*00b67f09SDavid van Moolenbroek 	tresult = check_options(zoptions, logctx, mctx, optlevel_zone);
2077*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2078*00b67f09SDavid van Moolenbroek 		result = tresult;
2079*00b67f09SDavid van Moolenbroek 
2080*00b67f09SDavid van Moolenbroek 	/*
2081*00b67f09SDavid van Moolenbroek 	 * If the zone type is rbt/rbt64 then master/hint zones
2082*00b67f09SDavid van Moolenbroek 	 * require file clauses.
2083*00b67f09SDavid van Moolenbroek 	 * If inline signing is used, then slave zones require a
2084*00b67f09SDavid van Moolenbroek 	 * file clause as well
2085*00b67f09SDavid van Moolenbroek 	 */
2086*00b67f09SDavid van Moolenbroek 	obj = NULL;
2087*00b67f09SDavid van Moolenbroek 	dlz = ISC_FALSE;
2088*00b67f09SDavid van Moolenbroek 	tresult = cfg_map_get(zoptions, "dlz", &obj);
2089*00b67f09SDavid van Moolenbroek 	if (tresult == ISC_R_SUCCESS)
2090*00b67f09SDavid van Moolenbroek 		dlz = ISC_TRUE;
2091*00b67f09SDavid van Moolenbroek 
2092*00b67f09SDavid van Moolenbroek 	obj = NULL;
2093*00b67f09SDavid van Moolenbroek 	tresult = cfg_map_get(zoptions, "database", &obj);
2094*00b67f09SDavid van Moolenbroek 	if (dlz && tresult == ISC_R_SUCCESS) {
2095*00b67f09SDavid van Moolenbroek 		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
2096*00b67f09SDavid van Moolenbroek 				    "zone '%s': cannot specify both 'dlz' "
2097*00b67f09SDavid van Moolenbroek 				    "and 'database'", znamestr);
2098*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2099*00b67f09SDavid van Moolenbroek 	} else if (!dlz &&
2100*00b67f09SDavid van Moolenbroek 	    (tresult == ISC_R_NOTFOUND ||
2101*00b67f09SDavid van Moolenbroek 	    (tresult == ISC_R_SUCCESS &&
2102*00b67f09SDavid van Moolenbroek 	     (strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
2103*00b67f09SDavid van Moolenbroek 	      strcmp("rbt64", cfg_obj_asstring(obj)) == 0))))
2104*00b67f09SDavid van Moolenbroek 	{
2105*00b67f09SDavid van Moolenbroek 		isc_result_t res1;
2106*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *fileobj = NULL;
2107*00b67f09SDavid van Moolenbroek 		tresult = cfg_map_get(zoptions, "file", &fileobj);
2108*00b67f09SDavid van Moolenbroek 		obj = NULL;
2109*00b67f09SDavid van Moolenbroek 		res1 = cfg_map_get(zoptions, "inline-signing", &obj);
2110*00b67f09SDavid van Moolenbroek 		if ((tresult != ISC_R_SUCCESS &&
2111*00b67f09SDavid van Moolenbroek 		    (ztype == MASTERZONE || ztype == HINTZONE ||
2112*00b67f09SDavid van Moolenbroek 		     (ztype == SLAVEZONE && res1 == ISC_R_SUCCESS &&
2113*00b67f09SDavid van Moolenbroek 		      cfg_obj_asboolean(obj))))) {
2114*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
2115*00b67f09SDavid van Moolenbroek 			    "zone '%s': missing 'file' entry",
2116*00b67f09SDavid van Moolenbroek 			    znamestr);
2117*00b67f09SDavid van Moolenbroek 			result = tresult;
2118*00b67f09SDavid van Moolenbroek 		} else if (tresult == ISC_R_SUCCESS &&
2119*00b67f09SDavid van Moolenbroek 			   (ztype == SLAVEZONE || ddns)) {
2120*00b67f09SDavid van Moolenbroek 			tresult = fileexist(fileobj, files, ISC_TRUE, logctx);
2121*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
2122*00b67f09SDavid van Moolenbroek 				result = tresult;
2123*00b67f09SDavid van Moolenbroek 		} else if (tresult == ISC_R_SUCCESS &&
2124*00b67f09SDavid van Moolenbroek 			   (ztype == MASTERZONE || ztype == HINTZONE)) {
2125*00b67f09SDavid van Moolenbroek 			tresult = fileexist(fileobj, files, ISC_FALSE, logctx);
2126*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
2127*00b67f09SDavid van Moolenbroek 				result = tresult;
2128*00b67f09SDavid van Moolenbroek 		}
2129*00b67f09SDavid van Moolenbroek 	}
2130*00b67f09SDavid van Moolenbroek 
2131*00b67f09SDavid van Moolenbroek 	return (result);
2132*00b67f09SDavid van Moolenbroek }
2133*00b67f09SDavid van Moolenbroek 
2134*00b67f09SDavid van Moolenbroek 
2135*00b67f09SDavid van Moolenbroek typedef struct keyalgorithms {
2136*00b67f09SDavid van Moolenbroek 	const char *name;
2137*00b67f09SDavid van Moolenbroek 	isc_uint16_t size;
2138*00b67f09SDavid van Moolenbroek } algorithmtable;
2139*00b67f09SDavid van Moolenbroek 
2140*00b67f09SDavid van Moolenbroek isc_result_t
bind9_check_key(const cfg_obj_t * key,isc_log_t * logctx)2141*00b67f09SDavid van Moolenbroek bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
2142*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *algobj = NULL;
2143*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *secretobj = NULL;
2144*00b67f09SDavid van Moolenbroek 	const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
2145*00b67f09SDavid van Moolenbroek 	const char *algorithm;
2146*00b67f09SDavid van Moolenbroek 	int i;
2147*00b67f09SDavid van Moolenbroek 	size_t len = 0;
2148*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2149*00b67f09SDavid van Moolenbroek 	isc_buffer_t buf;
2150*00b67f09SDavid van Moolenbroek 	unsigned char secretbuf[1024];
2151*00b67f09SDavid van Moolenbroek 	static const algorithmtable algorithms[] = {
2152*00b67f09SDavid van Moolenbroek 		{ "hmac-md5", 128 },
2153*00b67f09SDavid van Moolenbroek 		{ "hmac-md5.sig-alg.reg.int", 0 },
2154*00b67f09SDavid van Moolenbroek 		{ "hmac-md5.sig-alg.reg.int.", 0 },
2155*00b67f09SDavid van Moolenbroek 		{ "hmac-sha1", 160 },
2156*00b67f09SDavid van Moolenbroek 		{ "hmac-sha224", 224 },
2157*00b67f09SDavid van Moolenbroek 		{ "hmac-sha256", 256 },
2158*00b67f09SDavid van Moolenbroek 		{ "hmac-sha384", 384 },
2159*00b67f09SDavid van Moolenbroek 		{ "hmac-sha512", 512 },
2160*00b67f09SDavid van Moolenbroek 		{  NULL, 0 }
2161*00b67f09SDavid van Moolenbroek 	};
2162*00b67f09SDavid van Moolenbroek 
2163*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(key, "algorithm", &algobj);
2164*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(key, "secret", &secretobj);
2165*00b67f09SDavid van Moolenbroek 	if (secretobj == NULL || algobj == NULL) {
2166*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2167*00b67f09SDavid van Moolenbroek 			    "key '%s' must have both 'secret' and "
2168*00b67f09SDavid van Moolenbroek 			    "'algorithm' defined",
2169*00b67f09SDavid van Moolenbroek 			    keyname);
2170*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
2171*00b67f09SDavid van Moolenbroek 	}
2172*00b67f09SDavid van Moolenbroek 
2173*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buf, secretbuf, sizeof(secretbuf));
2174*00b67f09SDavid van Moolenbroek 	result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf);
2175*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
2176*00b67f09SDavid van Moolenbroek 		cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR,
2177*00b67f09SDavid van Moolenbroek 			    "bad secret '%s'", isc_result_totext(result));
2178*00b67f09SDavid van Moolenbroek 		return (result);
2179*00b67f09SDavid van Moolenbroek 	}
2180*00b67f09SDavid van Moolenbroek 
2181*00b67f09SDavid van Moolenbroek 	algorithm = cfg_obj_asstring(algobj);
2182*00b67f09SDavid van Moolenbroek 	for (i = 0; algorithms[i].name != NULL; i++) {
2183*00b67f09SDavid van Moolenbroek 		len = strlen(algorithms[i].name);
2184*00b67f09SDavid van Moolenbroek 		if (strncasecmp(algorithms[i].name, algorithm, len) == 0 &&
2185*00b67f09SDavid van Moolenbroek 		    (algorithm[len] == '\0' ||
2186*00b67f09SDavid van Moolenbroek 		     (algorithms[i].size != 0 && algorithm[len] == '-')))
2187*00b67f09SDavid van Moolenbroek 			break;
2188*00b67f09SDavid van Moolenbroek 	}
2189*00b67f09SDavid van Moolenbroek 	if (algorithms[i].name == NULL) {
2190*00b67f09SDavid van Moolenbroek 		cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
2191*00b67f09SDavid van Moolenbroek 			    "unknown algorithm '%s'", algorithm);
2192*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
2193*00b67f09SDavid van Moolenbroek 	}
2194*00b67f09SDavid van Moolenbroek 	if (algorithm[len] == '-') {
2195*00b67f09SDavid van Moolenbroek 		isc_uint16_t digestbits;
2196*00b67f09SDavid van Moolenbroek 		result = isc_parse_uint16(&digestbits, algorithm + len + 1, 10);
2197*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS || result == ISC_R_RANGE) {
2198*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_RANGE ||
2199*00b67f09SDavid van Moolenbroek 			    digestbits > algorithms[i].size) {
2200*00b67f09SDavid van Moolenbroek 				cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
2201*00b67f09SDavid van Moolenbroek 					    "key '%s' digest-bits too large "
2202*00b67f09SDavid van Moolenbroek 					    "[%u..%u]", keyname,
2203*00b67f09SDavid van Moolenbroek 					    algorithms[i].size / 2,
2204*00b67f09SDavid van Moolenbroek 					    algorithms[i].size);
2205*00b67f09SDavid van Moolenbroek 				return (ISC_R_RANGE);
2206*00b67f09SDavid van Moolenbroek 			}
2207*00b67f09SDavid van Moolenbroek 			if ((digestbits % 8) != 0) {
2208*00b67f09SDavid van Moolenbroek 				cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
2209*00b67f09SDavid van Moolenbroek 					    "key '%s' digest-bits not multiple"
2210*00b67f09SDavid van Moolenbroek 					    " of 8", keyname);
2211*00b67f09SDavid van Moolenbroek 				return (ISC_R_RANGE);
2212*00b67f09SDavid van Moolenbroek 			}
2213*00b67f09SDavid van Moolenbroek 			/*
2214*00b67f09SDavid van Moolenbroek 			 * Recommended minima for hmac algorithms.
2215*00b67f09SDavid van Moolenbroek 			 */
2216*00b67f09SDavid van Moolenbroek 			if ((digestbits < (algorithms[i].size / 2U) ||
2217*00b67f09SDavid van Moolenbroek 			     (digestbits < 80U)))
2218*00b67f09SDavid van Moolenbroek 				cfg_obj_log(algobj, logctx, ISC_LOG_WARNING,
2219*00b67f09SDavid van Moolenbroek 					    "key '%s' digest-bits too small "
2220*00b67f09SDavid van Moolenbroek 					    "[<%u]", keyname,
2221*00b67f09SDavid van Moolenbroek 					    algorithms[i].size/2);
2222*00b67f09SDavid van Moolenbroek 		} else {
2223*00b67f09SDavid van Moolenbroek 			cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
2224*00b67f09SDavid van Moolenbroek 				    "key '%s': unable to parse digest-bits",
2225*00b67f09SDavid van Moolenbroek 				    keyname);
2226*00b67f09SDavid van Moolenbroek 			return (result);
2227*00b67f09SDavid van Moolenbroek 		}
2228*00b67f09SDavid van Moolenbroek 	}
2229*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
2230*00b67f09SDavid van Moolenbroek }
2231*00b67f09SDavid van Moolenbroek 
2232*00b67f09SDavid van Moolenbroek static isc_result_t
fileexist(const cfg_obj_t * obj,isc_symtab_t * symtab,isc_boolean_t writeable,isc_log_t * logctx)2233*00b67f09SDavid van Moolenbroek fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, isc_boolean_t writeable,
2234*00b67f09SDavid van Moolenbroek 	  isc_log_t *logctx)
2235*00b67f09SDavid van Moolenbroek {
2236*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2237*00b67f09SDavid van Moolenbroek 	isc_symvalue_t symvalue;
2238*00b67f09SDavid van Moolenbroek 	unsigned int line;
2239*00b67f09SDavid van Moolenbroek 	const char *file;
2240*00b67f09SDavid van Moolenbroek 
2241*00b67f09SDavid van Moolenbroek 	result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 0, &symvalue);
2242*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
2243*00b67f09SDavid van Moolenbroek 		if (writeable) {
2244*00b67f09SDavid van Moolenbroek 			file = cfg_obj_file(symvalue.as_cpointer);
2245*00b67f09SDavid van Moolenbroek 			line = cfg_obj_line(symvalue.as_cpointer);
2246*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
2247*00b67f09SDavid van Moolenbroek 				    "writeable file '%s': already in use: "
2248*00b67f09SDavid van Moolenbroek 				    "%s:%u", cfg_obj_asstring(obj),
2249*00b67f09SDavid van Moolenbroek 				    file, line);
2250*00b67f09SDavid van Moolenbroek 			return (ISC_R_EXISTS);
2251*00b67f09SDavid van Moolenbroek 		}
2252*00b67f09SDavid van Moolenbroek 		result = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), 2,
2253*00b67f09SDavid van Moolenbroek 					   &symvalue);
2254*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
2255*00b67f09SDavid van Moolenbroek 			file = cfg_obj_file(symvalue.as_cpointer);
2256*00b67f09SDavid van Moolenbroek 			line = cfg_obj_line(symvalue.as_cpointer);
2257*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
2258*00b67f09SDavid van Moolenbroek 				    "writeable file '%s': already in use: "
2259*00b67f09SDavid van Moolenbroek 				    "%s:%u", cfg_obj_asstring(obj),
2260*00b67f09SDavid van Moolenbroek 				    file, line);
2261*00b67f09SDavid van Moolenbroek 			return (ISC_R_EXISTS);
2262*00b67f09SDavid van Moolenbroek 		}
2263*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
2264*00b67f09SDavid van Moolenbroek 	}
2265*00b67f09SDavid van Moolenbroek 
2266*00b67f09SDavid van Moolenbroek 	symvalue.as_cpointer = obj;
2267*00b67f09SDavid van Moolenbroek 	result = isc_symtab_define(symtab, cfg_obj_asstring(obj),
2268*00b67f09SDavid van Moolenbroek 				   writeable ? 2 : 1, symvalue,
2269*00b67f09SDavid van Moolenbroek 				   isc_symexists_reject);
2270*00b67f09SDavid van Moolenbroek 	return (result);
2271*00b67f09SDavid van Moolenbroek }
2272*00b67f09SDavid van Moolenbroek 
2273*00b67f09SDavid van Moolenbroek /*
2274*00b67f09SDavid van Moolenbroek  * Check key list for duplicates key names and that the key names
2275*00b67f09SDavid van Moolenbroek  * are valid domain names as these keys are used for TSIG.
2276*00b67f09SDavid van Moolenbroek  *
2277*00b67f09SDavid van Moolenbroek  * Check the key contents for validity.
2278*00b67f09SDavid van Moolenbroek  */
2279*00b67f09SDavid van Moolenbroek static isc_result_t
check_keylist(const cfg_obj_t * keys,isc_symtab_t * symtab,isc_mem_t * mctx,isc_log_t * logctx)2280*00b67f09SDavid van Moolenbroek check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab,
2281*00b67f09SDavid van Moolenbroek 	      isc_mem_t *mctx, isc_log_t *logctx)
2282*00b67f09SDavid van Moolenbroek {
2283*00b67f09SDavid van Moolenbroek 	char namebuf[DNS_NAME_FORMATSIZE];
2284*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fname;
2285*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
2286*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2287*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
2288*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
2289*00b67f09SDavid van Moolenbroek 
2290*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fname);
2291*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fname);
2292*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(keys);
2293*00b67f09SDavid van Moolenbroek 	     element != NULL;
2294*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2295*00b67f09SDavid van Moolenbroek 	{
2296*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *key = cfg_listelt_value(element);
2297*00b67f09SDavid van Moolenbroek 		const char *keyid = cfg_obj_asstring(cfg_map_getname(key));
2298*00b67f09SDavid van Moolenbroek 		isc_symvalue_t symvalue;
2299*00b67f09SDavid van Moolenbroek 		isc_buffer_t b;
2300*00b67f09SDavid van Moolenbroek 		char *keyname;
2301*00b67f09SDavid van Moolenbroek 
2302*00b67f09SDavid van Moolenbroek 		isc_buffer_constinit(&b, keyid, strlen(keyid));
2303*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, strlen(keyid));
2304*00b67f09SDavid van Moolenbroek 		tresult = dns_name_fromtext(name, &b, dns_rootname,
2305*00b67f09SDavid van Moolenbroek 					    0, NULL);
2306*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
2307*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2308*00b67f09SDavid van Moolenbroek 				    "key '%s': bad key name", keyid);
2309*00b67f09SDavid van Moolenbroek 			result = tresult;
2310*00b67f09SDavid van Moolenbroek 			continue;
2311*00b67f09SDavid van Moolenbroek 		}
2312*00b67f09SDavid van Moolenbroek 		tresult = bind9_check_key(key, logctx);
2313*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
2314*00b67f09SDavid van Moolenbroek 			return (tresult);
2315*00b67f09SDavid van Moolenbroek 
2316*00b67f09SDavid van Moolenbroek 		dns_name_format(name, namebuf, sizeof(namebuf));
2317*00b67f09SDavid van Moolenbroek 		keyname = isc_mem_strdup(mctx, namebuf);
2318*00b67f09SDavid van Moolenbroek 		if (keyname == NULL)
2319*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
2320*00b67f09SDavid van Moolenbroek 		symvalue.as_cpointer = key;
2321*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_define(symtab, keyname, 1, symvalue,
2322*00b67f09SDavid van Moolenbroek 					    isc_symexists_reject);
2323*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_EXISTS) {
2324*00b67f09SDavid van Moolenbroek 			const char *file;
2325*00b67f09SDavid van Moolenbroek 			unsigned int line;
2326*00b67f09SDavid van Moolenbroek 
2327*00b67f09SDavid van Moolenbroek 			RUNTIME_CHECK(isc_symtab_lookup(symtab, keyname,
2328*00b67f09SDavid van Moolenbroek 					    1, &symvalue) == ISC_R_SUCCESS);
2329*00b67f09SDavid van Moolenbroek 			file = cfg_obj_file(symvalue.as_cpointer);
2330*00b67f09SDavid van Moolenbroek 			line = cfg_obj_line(symvalue.as_cpointer);
2331*00b67f09SDavid van Moolenbroek 
2332*00b67f09SDavid van Moolenbroek 			if (file == NULL)
2333*00b67f09SDavid van Moolenbroek 				file = "<unknown file>";
2334*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2335*00b67f09SDavid van Moolenbroek 				    "key '%s': already exists "
2336*00b67f09SDavid van Moolenbroek 				    "previous definition: %s:%u",
2337*00b67f09SDavid van Moolenbroek 				    keyid, file, line);
2338*00b67f09SDavid van Moolenbroek 			isc_mem_free(mctx, keyname);
2339*00b67f09SDavid van Moolenbroek 			result = tresult;
2340*00b67f09SDavid van Moolenbroek 		} else if (tresult != ISC_R_SUCCESS) {
2341*00b67f09SDavid van Moolenbroek 			isc_mem_free(mctx, keyname);
2342*00b67f09SDavid van Moolenbroek 			return (tresult);
2343*00b67f09SDavid van Moolenbroek 		}
2344*00b67f09SDavid van Moolenbroek 	}
2345*00b67f09SDavid van Moolenbroek 	return (result);
2346*00b67f09SDavid van Moolenbroek }
2347*00b67f09SDavid van Moolenbroek 
2348*00b67f09SDavid van Moolenbroek static struct {
2349*00b67f09SDavid van Moolenbroek 	const char *v4;
2350*00b67f09SDavid van Moolenbroek 	const char *v6;
2351*00b67f09SDavid van Moolenbroek } sources[] = {
2352*00b67f09SDavid van Moolenbroek 	{ "transfer-source", "transfer-source-v6" },
2353*00b67f09SDavid van Moolenbroek 	{ "notify-source", "notify-source-v6" },
2354*00b67f09SDavid van Moolenbroek 	{ "query-source", "query-source-v6" },
2355*00b67f09SDavid van Moolenbroek 	{ NULL, NULL }
2356*00b67f09SDavid van Moolenbroek };
2357*00b67f09SDavid van Moolenbroek 
2358*00b67f09SDavid van Moolenbroek /*
2359*00b67f09SDavid van Moolenbroek  * RNDC keys are not normalised unlike TSIG keys.
2360*00b67f09SDavid van Moolenbroek  *
2361*00b67f09SDavid van Moolenbroek  * 	"foo." is different to "foo".
2362*00b67f09SDavid van Moolenbroek  */
2363*00b67f09SDavid van Moolenbroek static isc_boolean_t
rndckey_exists(const cfg_obj_t * keylist,const char * keyname)2364*00b67f09SDavid van Moolenbroek rndckey_exists(const cfg_obj_t *keylist, const char *keyname) {
2365*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
2366*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
2367*00b67f09SDavid van Moolenbroek 	const char *str;
2368*00b67f09SDavid van Moolenbroek 
2369*00b67f09SDavid van Moolenbroek 	if (keylist == NULL)
2370*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
2371*00b67f09SDavid van Moolenbroek 
2372*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(keylist);
2373*00b67f09SDavid van Moolenbroek 	     element != NULL;
2374*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2375*00b67f09SDavid van Moolenbroek 	{
2376*00b67f09SDavid van Moolenbroek 		obj = cfg_listelt_value(element);
2377*00b67f09SDavid van Moolenbroek 		str = cfg_obj_asstring(cfg_map_getname(obj));
2378*00b67f09SDavid van Moolenbroek 		if (!strcasecmp(str, keyname))
2379*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
2380*00b67f09SDavid van Moolenbroek 	}
2381*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
2382*00b67f09SDavid van Moolenbroek }
2383*00b67f09SDavid van Moolenbroek 
2384*00b67f09SDavid van Moolenbroek static isc_result_t
check_servers(const cfg_obj_t * config,const cfg_obj_t * voptions,isc_symtab_t * symtab,isc_log_t * logctx)2385*00b67f09SDavid van Moolenbroek check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
2386*00b67f09SDavid van Moolenbroek 	      isc_symtab_t *symtab, isc_log_t *logctx)
2387*00b67f09SDavid van Moolenbroek {
2388*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fname;
2389*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2390*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
2391*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *e1, *e2;
2392*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *v1, *v2, *keys;
2393*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *servers;
2394*00b67f09SDavid van Moolenbroek 	isc_netaddr_t n1, n2;
2395*00b67f09SDavid van Moolenbroek 	unsigned int p1, p2;
2396*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
2397*00b67f09SDavid van Moolenbroek 	char buf[ISC_NETADDR_FORMATSIZE];
2398*00b67f09SDavid van Moolenbroek 	char namebuf[DNS_NAME_FORMATSIZE];
2399*00b67f09SDavid van Moolenbroek 	const char *xfr;
2400*00b67f09SDavid van Moolenbroek 	const char *keyval;
2401*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
2402*00b67f09SDavid van Moolenbroek 	int source;
2403*00b67f09SDavid van Moolenbroek 	dns_name_t *keyname;
2404*00b67f09SDavid van Moolenbroek 
2405*00b67f09SDavid van Moolenbroek 	servers = NULL;
2406*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2407*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "server", &servers);
2408*00b67f09SDavid van Moolenbroek 	if (servers == NULL)
2409*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(config, "server", &servers);
2410*00b67f09SDavid van Moolenbroek 	if (servers == NULL)
2411*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
2412*00b67f09SDavid van Moolenbroek 
2413*00b67f09SDavid van Moolenbroek 	for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
2414*00b67f09SDavid van Moolenbroek 		v1 = cfg_listelt_value(e1);
2415*00b67f09SDavid van Moolenbroek 		cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1);
2416*00b67f09SDavid van Moolenbroek 		/*
2417*00b67f09SDavid van Moolenbroek 		 * Check that unused bits are zero.
2418*00b67f09SDavid van Moolenbroek 		 */
2419*00b67f09SDavid van Moolenbroek 		tresult = isc_netaddr_prefixok(&n1, p1);
2420*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS) {
2421*00b67f09SDavid van Moolenbroek 			INSIST(tresult == ISC_R_FAILURE);
2422*00b67f09SDavid van Moolenbroek 			isc_netaddr_format(&n1, buf, sizeof(buf));
2423*00b67f09SDavid van Moolenbroek 			cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
2424*00b67f09SDavid van Moolenbroek 				    "server '%s/%u': invalid prefix "
2425*00b67f09SDavid van Moolenbroek 				    "(extra bits specified)", buf, p1);
2426*00b67f09SDavid van Moolenbroek 			result = tresult;
2427*00b67f09SDavid van Moolenbroek 		}
2428*00b67f09SDavid van Moolenbroek 		source = 0;
2429*00b67f09SDavid van Moolenbroek 		do {
2430*00b67f09SDavid van Moolenbroek 			obj = NULL;
2431*00b67f09SDavid van Moolenbroek 			if (n1.family == AF_INET)
2432*00b67f09SDavid van Moolenbroek 				xfr = sources[source].v6;
2433*00b67f09SDavid van Moolenbroek 			else
2434*00b67f09SDavid van Moolenbroek 				xfr = sources[source].v4;
2435*00b67f09SDavid van Moolenbroek 			(void)cfg_map_get(v1, xfr, &obj);
2436*00b67f09SDavid van Moolenbroek 			if (obj != NULL) {
2437*00b67f09SDavid van Moolenbroek 				isc_netaddr_format(&n1, buf, sizeof(buf));
2438*00b67f09SDavid van Moolenbroek 				cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
2439*00b67f09SDavid van Moolenbroek 					    "server '%s/%u': %s not legal",
2440*00b67f09SDavid van Moolenbroek 					    buf, p1, xfr);
2441*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2442*00b67f09SDavid van Moolenbroek 			}
2443*00b67f09SDavid van Moolenbroek 		} while (sources[++source].v4 != NULL);
2444*00b67f09SDavid van Moolenbroek 		e2 = e1;
2445*00b67f09SDavid van Moolenbroek 		while ((e2 = cfg_list_next(e2)) != NULL) {
2446*00b67f09SDavid van Moolenbroek 			v2 = cfg_listelt_value(e2);
2447*00b67f09SDavid van Moolenbroek 			cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2);
2448*00b67f09SDavid van Moolenbroek 			if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) {
2449*00b67f09SDavid van Moolenbroek 				const char *file = cfg_obj_file(v1);
2450*00b67f09SDavid van Moolenbroek 				unsigned int line = cfg_obj_line(v1);
2451*00b67f09SDavid van Moolenbroek 
2452*00b67f09SDavid van Moolenbroek 				if (file == NULL)
2453*00b67f09SDavid van Moolenbroek 					file = "<unknown file>";
2454*00b67f09SDavid van Moolenbroek 
2455*00b67f09SDavid van Moolenbroek 				isc_netaddr_format(&n2, buf, sizeof(buf));
2456*00b67f09SDavid van Moolenbroek 				cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
2457*00b67f09SDavid van Moolenbroek 					    "server '%s/%u': already exists "
2458*00b67f09SDavid van Moolenbroek 					    "previous definition: %s:%u",
2459*00b67f09SDavid van Moolenbroek 					    buf, p2, file, line);
2460*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2461*00b67f09SDavid van Moolenbroek 			}
2462*00b67f09SDavid van Moolenbroek 		}
2463*00b67f09SDavid van Moolenbroek 		keys = NULL;
2464*00b67f09SDavid van Moolenbroek 		cfg_map_get(v1, "keys", &keys);
2465*00b67f09SDavid van Moolenbroek 		if (keys != NULL) {
2466*00b67f09SDavid van Moolenbroek 			/*
2467*00b67f09SDavid van Moolenbroek 			 * Normalize key name.
2468*00b67f09SDavid van Moolenbroek 			 */
2469*00b67f09SDavid van Moolenbroek 			keyval = cfg_obj_asstring(keys);
2470*00b67f09SDavid van Moolenbroek 			dns_fixedname_init(&fname);
2471*00b67f09SDavid van Moolenbroek 			isc_buffer_constinit(&b, keyval, strlen(keyval));
2472*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b, strlen(keyval));
2473*00b67f09SDavid van Moolenbroek 			keyname = dns_fixedname_name(&fname);
2474*00b67f09SDavid van Moolenbroek 			tresult = dns_name_fromtext(keyname, &b, dns_rootname,
2475*00b67f09SDavid van Moolenbroek 						    0, NULL);
2476*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
2477*00b67f09SDavid van Moolenbroek 				cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
2478*00b67f09SDavid van Moolenbroek 					    "bad key name '%s'", keyval);
2479*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2480*00b67f09SDavid van Moolenbroek 				continue;
2481*00b67f09SDavid van Moolenbroek 			}
2482*00b67f09SDavid van Moolenbroek 			dns_name_format(keyname, namebuf, sizeof(namebuf));
2483*00b67f09SDavid van Moolenbroek 			tresult = isc_symtab_lookup(symtab, namebuf, 1, NULL);
2484*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
2485*00b67f09SDavid van Moolenbroek 				cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
2486*00b67f09SDavid van Moolenbroek 					    "unknown key '%s'", keyval);
2487*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2488*00b67f09SDavid van Moolenbroek 			}
2489*00b67f09SDavid van Moolenbroek 		}
2490*00b67f09SDavid van Moolenbroek 	}
2491*00b67f09SDavid van Moolenbroek 	return (result);
2492*00b67f09SDavid van Moolenbroek }
2493*00b67f09SDavid van Moolenbroek 
2494*00b67f09SDavid van Moolenbroek static isc_result_t
check_trusted_key(const cfg_obj_t * key,isc_boolean_t managed,isc_log_t * logctx)2495*00b67f09SDavid van Moolenbroek check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed,
2496*00b67f09SDavid van Moolenbroek 		  isc_log_t *logctx)
2497*00b67f09SDavid van Moolenbroek {
2498*00b67f09SDavid van Moolenbroek 	const char *keystr, *keynamestr;
2499*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fkeyname;
2500*00b67f09SDavid van Moolenbroek 	dns_name_t *keyname;
2501*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
2502*00b67f09SDavid van Moolenbroek 	isc_region_t r;
2503*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2504*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
2505*00b67f09SDavid van Moolenbroek 	isc_uint32_t flags, proto, alg;
2506*00b67f09SDavid van Moolenbroek 	unsigned char keydata[4096];
2507*00b67f09SDavid van Moolenbroek 
2508*00b67f09SDavid van Moolenbroek 	flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
2509*00b67f09SDavid van Moolenbroek 	proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
2510*00b67f09SDavid van Moolenbroek 	alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
2511*00b67f09SDavid van Moolenbroek 
2512*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fkeyname);
2513*00b67f09SDavid van Moolenbroek 	keyname = dns_fixedname_name(&fkeyname);
2514*00b67f09SDavid van Moolenbroek 	keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
2515*00b67f09SDavid van Moolenbroek 
2516*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&b, keynamestr, strlen(keynamestr));
2517*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&b, strlen(keynamestr));
2518*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
2519*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
2520*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_WARNING, "bad key name: %s\n",
2521*00b67f09SDavid van Moolenbroek 			    isc_result_totext(result));
2522*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2523*00b67f09SDavid van Moolenbroek 	}
2524*00b67f09SDavid van Moolenbroek 
2525*00b67f09SDavid van Moolenbroek 	if (flags > 0xffff) {
2526*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_WARNING,
2527*00b67f09SDavid van Moolenbroek 			    "flags too big: %u\n", flags);
2528*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2529*00b67f09SDavid van Moolenbroek 	}
2530*00b67f09SDavid van Moolenbroek 	if (proto > 0xff) {
2531*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_WARNING,
2532*00b67f09SDavid van Moolenbroek 			    "protocol too big: %u\n", proto);
2533*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2534*00b67f09SDavid van Moolenbroek 	}
2535*00b67f09SDavid van Moolenbroek 	if (alg > 0xff) {
2536*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_WARNING,
2537*00b67f09SDavid van Moolenbroek 			    "algorithm too big: %u\n", alg);
2538*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2539*00b67f09SDavid van Moolenbroek 	}
2540*00b67f09SDavid van Moolenbroek 
2541*00b67f09SDavid van Moolenbroek 	if (managed) {
2542*00b67f09SDavid van Moolenbroek 		const char *initmethod;
2543*00b67f09SDavid van Moolenbroek 		initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
2544*00b67f09SDavid van Moolenbroek 
2545*00b67f09SDavid van Moolenbroek 		if (strcasecmp(initmethod, "initial-key") != 0) {
2546*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2547*00b67f09SDavid van Moolenbroek 				    "managed key '%s': "
2548*00b67f09SDavid van Moolenbroek 				    "invalid initialization method '%s'",
2549*00b67f09SDavid van Moolenbroek 				    keynamestr, initmethod);
2550*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2551*00b67f09SDavid van Moolenbroek 		}
2552*00b67f09SDavid van Moolenbroek 	}
2553*00b67f09SDavid van Moolenbroek 
2554*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&b, keydata, sizeof(keydata));
2555*00b67f09SDavid van Moolenbroek 
2556*00b67f09SDavid van Moolenbroek 	keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
2557*00b67f09SDavid van Moolenbroek 	tresult = isc_base64_decodestring(keystr, &b);
2558*00b67f09SDavid van Moolenbroek 
2559*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS) {
2560*00b67f09SDavid van Moolenbroek 		cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2561*00b67f09SDavid van Moolenbroek 			    "%s", isc_result_totext(tresult));
2562*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2563*00b67f09SDavid van Moolenbroek 	} else {
2564*00b67f09SDavid van Moolenbroek 		isc_buffer_usedregion(&b, &r);
2565*00b67f09SDavid van Moolenbroek 
2566*00b67f09SDavid van Moolenbroek 		if ((alg == DST_ALG_RSASHA1 || alg == DST_ALG_RSAMD5) &&
2567*00b67f09SDavid van Moolenbroek 		    r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
2568*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_WARNING,
2569*00b67f09SDavid van Moolenbroek 				    "%s key '%s' has a weak exponent",
2570*00b67f09SDavid van Moolenbroek 				    managed ? "managed" : "trusted",
2571*00b67f09SDavid van Moolenbroek 				    keynamestr);
2572*00b67f09SDavid van Moolenbroek 	}
2573*00b67f09SDavid van Moolenbroek 
2574*00b67f09SDavid van Moolenbroek 	return (result);
2575*00b67f09SDavid van Moolenbroek }
2576*00b67f09SDavid van Moolenbroek 
2577*00b67f09SDavid van Moolenbroek static isc_result_t
check_viewconf(const cfg_obj_t * config,const cfg_obj_t * voptions,const char * viewname,dns_rdataclass_t vclass,isc_symtab_t * files,isc_log_t * logctx,isc_mem_t * mctx)2578*00b67f09SDavid van Moolenbroek check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
2579*00b67f09SDavid van Moolenbroek 	       const char *viewname, dns_rdataclass_t vclass,
2580*00b67f09SDavid van Moolenbroek 	       isc_symtab_t *files, isc_log_t *logctx, isc_mem_t *mctx)
2581*00b67f09SDavid van Moolenbroek {
2582*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *zones = NULL;
2583*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *keys = NULL;
2584*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element, *element2;
2585*00b67f09SDavid van Moolenbroek 	isc_symtab_t *symtab = NULL;
2586*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2587*00b67f09SDavid van Moolenbroek 	isc_result_t tresult = ISC_R_SUCCESS;
2588*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_t *actx = NULL;
2589*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
2590*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options = NULL;
2591*00b67f09SDavid van Moolenbroek 	isc_boolean_t enablednssec, enablevalidation;
2592*00b67f09SDavid van Moolenbroek 	const char *valstr = "no";
2593*00b67f09SDavid van Moolenbroek 
2594*00b67f09SDavid van Moolenbroek 	/*
2595*00b67f09SDavid van Moolenbroek 	 * Get global options block
2596*00b67f09SDavid van Moolenbroek 	 */
2597*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "options", &options);
2598*00b67f09SDavid van Moolenbroek 
2599*00b67f09SDavid van Moolenbroek 	/*
2600*00b67f09SDavid van Moolenbroek 	 * Check that all zone statements are syntactically correct and
2601*00b67f09SDavid van Moolenbroek 	 * there are no duplicate zones.
2602*00b67f09SDavid van Moolenbroek 	 */
2603*00b67f09SDavid van Moolenbroek 	tresult = isc_symtab_create(mctx, 1000, freekey, mctx,
2604*00b67f09SDavid van Moolenbroek 				    ISC_FALSE, &symtab);
2605*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2606*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
2607*00b67f09SDavid van Moolenbroek 
2608*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_create(mctx, &actx);
2609*00b67f09SDavid van Moolenbroek 
2610*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2611*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "zone", &zones);
2612*00b67f09SDavid van Moolenbroek 	else
2613*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(config, "zone", &zones);
2614*00b67f09SDavid van Moolenbroek 
2615*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(zones);
2616*00b67f09SDavid van Moolenbroek 	     element != NULL;
2617*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2618*00b67f09SDavid van Moolenbroek 	{
2619*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *zone = cfg_listelt_value(element);
2620*00b67f09SDavid van Moolenbroek 
2621*00b67f09SDavid van Moolenbroek 		tresult = check_zoneconf(zone, voptions, config, symtab,
2622*00b67f09SDavid van Moolenbroek 					 files, vclass, actx, logctx,
2623*00b67f09SDavid van Moolenbroek 					 mctx);
2624*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
2625*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2626*00b67f09SDavid van Moolenbroek 	}
2627*00b67f09SDavid van Moolenbroek 
2628*00b67f09SDavid van Moolenbroek 	isc_symtab_destroy(&symtab);
2629*00b67f09SDavid van Moolenbroek 
2630*00b67f09SDavid van Moolenbroek 	/*
2631*00b67f09SDavid van Moolenbroek 	 * Check that forwarding is reasonable.
2632*00b67f09SDavid van Moolenbroek 	 */
2633*00b67f09SDavid van Moolenbroek 	if (voptions == NULL) {
2634*00b67f09SDavid van Moolenbroek 		if (options != NULL)
2635*00b67f09SDavid van Moolenbroek 			if (check_forward(options, NULL,
2636*00b67f09SDavid van Moolenbroek 					  logctx) != ISC_R_SUCCESS)
2637*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2638*00b67f09SDavid van Moolenbroek 	} else {
2639*00b67f09SDavid van Moolenbroek 		if (check_forward(voptions, NULL, logctx) != ISC_R_SUCCESS)
2640*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2641*00b67f09SDavid van Moolenbroek 	}
2642*00b67f09SDavid van Moolenbroek 
2643*00b67f09SDavid van Moolenbroek 	/*
2644*00b67f09SDavid van Moolenbroek 	 * Check non-zero options at the global and view levels.
2645*00b67f09SDavid van Moolenbroek 	 */
2646*00b67f09SDavid van Moolenbroek 	if (options != NULL && check_nonzero(options, logctx) != ISC_R_SUCCESS)
2647*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2648*00b67f09SDavid van Moolenbroek 	if (voptions != NULL &&check_nonzero(voptions, logctx) != ISC_R_SUCCESS)
2649*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2650*00b67f09SDavid van Moolenbroek 
2651*00b67f09SDavid van Moolenbroek 	/*
2652*00b67f09SDavid van Moolenbroek 	 * Check that dual-stack-servers is reasonable.
2653*00b67f09SDavid van Moolenbroek 	 */
2654*00b67f09SDavid van Moolenbroek 	if (voptions == NULL) {
2655*00b67f09SDavid van Moolenbroek 		if (options != NULL)
2656*00b67f09SDavid van Moolenbroek 			if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
2657*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
2658*00b67f09SDavid van Moolenbroek 	} else {
2659*00b67f09SDavid van Moolenbroek 		if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS)
2660*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2661*00b67f09SDavid van Moolenbroek 	}
2662*00b67f09SDavid van Moolenbroek 
2663*00b67f09SDavid van Moolenbroek 	/*
2664*00b67f09SDavid van Moolenbroek 	 * Check that rrset-order is reasonable.
2665*00b67f09SDavid van Moolenbroek 	 */
2666*00b67f09SDavid van Moolenbroek 	if (voptions != NULL) {
2667*00b67f09SDavid van Moolenbroek 		if (check_order(voptions, logctx) != ISC_R_SUCCESS)
2668*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2669*00b67f09SDavid van Moolenbroek 	}
2670*00b67f09SDavid van Moolenbroek 
2671*00b67f09SDavid van Moolenbroek 	/*
2672*00b67f09SDavid van Moolenbroek 	 * Check that all key statements are syntactically correct and
2673*00b67f09SDavid van Moolenbroek 	 * there are no duplicate keys.
2674*00b67f09SDavid van Moolenbroek 	 */
2675*00b67f09SDavid van Moolenbroek 	tresult = isc_symtab_create(mctx, 1000, freekey, mctx,
2676*00b67f09SDavid van Moolenbroek 				    ISC_FALSE, &symtab);
2677*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2678*00b67f09SDavid van Moolenbroek 		goto cleanup;
2679*00b67f09SDavid van Moolenbroek 
2680*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "key", &keys);
2681*00b67f09SDavid van Moolenbroek 	tresult = check_keylist(keys, symtab, mctx, logctx);
2682*00b67f09SDavid van Moolenbroek 	if (tresult == ISC_R_EXISTS)
2683*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2684*00b67f09SDavid van Moolenbroek 	else if (tresult != ISC_R_SUCCESS) {
2685*00b67f09SDavid van Moolenbroek 		result = tresult;
2686*00b67f09SDavid van Moolenbroek 		goto cleanup;
2687*00b67f09SDavid van Moolenbroek 	}
2688*00b67f09SDavid van Moolenbroek 
2689*00b67f09SDavid van Moolenbroek 	if (voptions != NULL) {
2690*00b67f09SDavid van Moolenbroek 		keys = NULL;
2691*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "key", &keys);
2692*00b67f09SDavid van Moolenbroek 		tresult = check_keylist(keys, symtab, mctx, logctx);
2693*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_EXISTS)
2694*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2695*00b67f09SDavid van Moolenbroek 		else if (tresult != ISC_R_SUCCESS) {
2696*00b67f09SDavid van Moolenbroek 			result = tresult;
2697*00b67f09SDavid van Moolenbroek 			goto cleanup;
2698*00b67f09SDavid van Moolenbroek 		}
2699*00b67f09SDavid van Moolenbroek 	}
2700*00b67f09SDavid van Moolenbroek 
2701*00b67f09SDavid van Moolenbroek 	/*
2702*00b67f09SDavid van Moolenbroek 	 * Global servers can refer to keys in views.
2703*00b67f09SDavid van Moolenbroek 	 */
2704*00b67f09SDavid van Moolenbroek 	if (check_servers(config, voptions, symtab, logctx) != ISC_R_SUCCESS)
2705*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
2706*00b67f09SDavid van Moolenbroek 
2707*00b67f09SDavid van Moolenbroek 	isc_symtab_destroy(&symtab);
2708*00b67f09SDavid van Moolenbroek 
2709*00b67f09SDavid van Moolenbroek 	/*
2710*00b67f09SDavid van Moolenbroek 	 * Check that dnssec-enable/dnssec-validation are sensible.
2711*00b67f09SDavid van Moolenbroek 	 */
2712*00b67f09SDavid van Moolenbroek 	obj = NULL;
2713*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2714*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "dnssec-enable", &obj);
2715*00b67f09SDavid van Moolenbroek 	if (obj == NULL && options != NULL)
2716*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(options, "dnssec-enable", &obj);
2717*00b67f09SDavid van Moolenbroek 	if (obj == NULL)
2718*00b67f09SDavid van Moolenbroek 		enablednssec = ISC_TRUE;
2719*00b67f09SDavid van Moolenbroek 	else
2720*00b67f09SDavid van Moolenbroek 		enablednssec = cfg_obj_asboolean(obj);
2721*00b67f09SDavid van Moolenbroek 
2722*00b67f09SDavid van Moolenbroek 	obj = NULL;
2723*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2724*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "dnssec-validation", &obj);
2725*00b67f09SDavid van Moolenbroek 	if (obj == NULL && options != NULL)
2726*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(options, "dnssec-validation", &obj);
2727*00b67f09SDavid van Moolenbroek 	if (obj == NULL) {
2728*00b67f09SDavid van Moolenbroek 		enablevalidation = enablednssec;
2729*00b67f09SDavid van Moolenbroek 		valstr = "yes";
2730*00b67f09SDavid van Moolenbroek 	} else if (cfg_obj_isboolean(obj)) {
2731*00b67f09SDavid van Moolenbroek 		enablevalidation = cfg_obj_asboolean(obj);
2732*00b67f09SDavid van Moolenbroek 		valstr = enablevalidation ? "yes" : "no";
2733*00b67f09SDavid van Moolenbroek 	} else {
2734*00b67f09SDavid van Moolenbroek 		enablevalidation = ISC_TRUE;
2735*00b67f09SDavid van Moolenbroek 		valstr = "auto";
2736*00b67f09SDavid van Moolenbroek 	}
2737*00b67f09SDavid van Moolenbroek 
2738*00b67f09SDavid van Moolenbroek 	if (enablevalidation && !enablednssec)
2739*00b67f09SDavid van Moolenbroek 		cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
2740*00b67f09SDavid van Moolenbroek 			    "'dnssec-validation %s;' and 'dnssec-enable no;'",
2741*00b67f09SDavid van Moolenbroek 			    valstr);
2742*00b67f09SDavid van Moolenbroek 
2743*00b67f09SDavid van Moolenbroek 	/*
2744*00b67f09SDavid van Moolenbroek 	 * Check trusted-keys and managed-keys.
2745*00b67f09SDavid van Moolenbroek 	 */
2746*00b67f09SDavid van Moolenbroek 	keys = NULL;
2747*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2748*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "trusted-keys", &keys);
2749*00b67f09SDavid van Moolenbroek 	if (keys == NULL)
2750*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(config, "trusted-keys", &keys);
2751*00b67f09SDavid van Moolenbroek 
2752*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(keys);
2753*00b67f09SDavid van Moolenbroek 	     element != NULL;
2754*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2755*00b67f09SDavid van Moolenbroek 	{
2756*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *keylist = cfg_listelt_value(element);
2757*00b67f09SDavid van Moolenbroek 		for (element2 = cfg_list_first(keylist);
2758*00b67f09SDavid van Moolenbroek 		     element2 != NULL;
2759*00b67f09SDavid van Moolenbroek 		     element2 = cfg_list_next(element2)) {
2760*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element2);
2761*00b67f09SDavid van Moolenbroek 			tresult = check_trusted_key(obj, ISC_FALSE, logctx);
2762*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
2763*00b67f09SDavid van Moolenbroek 				result = tresult;
2764*00b67f09SDavid van Moolenbroek 		}
2765*00b67f09SDavid van Moolenbroek 	}
2766*00b67f09SDavid van Moolenbroek 
2767*00b67f09SDavid van Moolenbroek 	keys = NULL;
2768*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2769*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(voptions, "managed-keys", &keys);
2770*00b67f09SDavid van Moolenbroek 	if (keys == NULL)
2771*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(config, "managed-keys", &keys);
2772*00b67f09SDavid van Moolenbroek 
2773*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(keys);
2774*00b67f09SDavid van Moolenbroek 	     element != NULL;
2775*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2776*00b67f09SDavid van Moolenbroek 	{
2777*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *keylist = cfg_listelt_value(element);
2778*00b67f09SDavid van Moolenbroek 		for (element2 = cfg_list_first(keylist);
2779*00b67f09SDavid van Moolenbroek 		     element2 != NULL;
2780*00b67f09SDavid van Moolenbroek 		     element2 = cfg_list_next(element2)) {
2781*00b67f09SDavid van Moolenbroek 			obj = cfg_listelt_value(element2);
2782*00b67f09SDavid van Moolenbroek 			tresult = check_trusted_key(obj, ISC_TRUE, logctx);
2783*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
2784*00b67f09SDavid van Moolenbroek 				result = tresult;
2785*00b67f09SDavid van Moolenbroek 		}
2786*00b67f09SDavid van Moolenbroek 	}
2787*00b67f09SDavid van Moolenbroek 
2788*00b67f09SDavid van Moolenbroek 	/*
2789*00b67f09SDavid van Moolenbroek 	 * Check options.
2790*00b67f09SDavid van Moolenbroek 	 */
2791*00b67f09SDavid van Moolenbroek 	if (voptions != NULL)
2792*00b67f09SDavid van Moolenbroek 		tresult = check_options(voptions, logctx, mctx,
2793*00b67f09SDavid van Moolenbroek 					optlevel_view);
2794*00b67f09SDavid van Moolenbroek 	else
2795*00b67f09SDavid van Moolenbroek 		tresult = check_options(config, logctx, mctx,
2796*00b67f09SDavid van Moolenbroek 					optlevel_config);
2797*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2798*00b67f09SDavid van Moolenbroek 		result = tresult;
2799*00b67f09SDavid van Moolenbroek 
2800*00b67f09SDavid van Moolenbroek 	tresult = check_viewacls(actx, voptions, config, logctx, mctx);
2801*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2802*00b67f09SDavid van Moolenbroek 		result = tresult;
2803*00b67f09SDavid van Moolenbroek 
2804*00b67f09SDavid van Moolenbroek 	tresult = check_recursionacls(actx, voptions, viewname,
2805*00b67f09SDavid van Moolenbroek 				      config, logctx, mctx);
2806*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2807*00b67f09SDavid van Moolenbroek 		result = tresult;
2808*00b67f09SDavid van Moolenbroek 
2809*00b67f09SDavid van Moolenbroek 	tresult = check_filteraaaa(actx, voptions, viewname, config,
2810*00b67f09SDavid van Moolenbroek 				   logctx, mctx);
2811*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2812*00b67f09SDavid van Moolenbroek 		result = tresult;
2813*00b67f09SDavid van Moolenbroek 
2814*00b67f09SDavid van Moolenbroek 	tresult = check_dns64(actx, voptions, config, logctx, mctx);
2815*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
2816*00b67f09SDavid van Moolenbroek 		result = tresult;
2817*00b67f09SDavid van Moolenbroek 
2818*00b67f09SDavid van Moolenbroek  cleanup:
2819*00b67f09SDavid van Moolenbroek 	if (symtab != NULL)
2820*00b67f09SDavid van Moolenbroek 		isc_symtab_destroy(&symtab);
2821*00b67f09SDavid van Moolenbroek 	if (actx != NULL)
2822*00b67f09SDavid van Moolenbroek 		cfg_aclconfctx_detach(&actx);
2823*00b67f09SDavid van Moolenbroek 
2824*00b67f09SDavid van Moolenbroek 	return (result);
2825*00b67f09SDavid van Moolenbroek }
2826*00b67f09SDavid van Moolenbroek 
2827*00b67f09SDavid van Moolenbroek static const char *
2828*00b67f09SDavid van Moolenbroek default_channels[] = {
2829*00b67f09SDavid van Moolenbroek 	"default_syslog",
2830*00b67f09SDavid van Moolenbroek 	"default_stderr",
2831*00b67f09SDavid van Moolenbroek 	"default_debug",
2832*00b67f09SDavid van Moolenbroek 	"null",
2833*00b67f09SDavid van Moolenbroek 	NULL
2834*00b67f09SDavid van Moolenbroek };
2835*00b67f09SDavid van Moolenbroek 
2836*00b67f09SDavid van Moolenbroek static isc_result_t
bind9_check_logging(const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)2837*00b67f09SDavid van Moolenbroek bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
2838*00b67f09SDavid van Moolenbroek 		    isc_mem_t *mctx)
2839*00b67f09SDavid van Moolenbroek {
2840*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *categories = NULL;
2841*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *category;
2842*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *channels = NULL;
2843*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *channel;
2844*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
2845*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *delement;
2846*00b67f09SDavid van Moolenbroek 	const char *channelname;
2847*00b67f09SDavid van Moolenbroek 	const char *catname;
2848*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *fileobj = NULL;
2849*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *syslogobj = NULL;
2850*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *nullobj = NULL;
2851*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *stderrobj = NULL;
2852*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *logobj = NULL;
2853*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2854*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
2855*00b67f09SDavid van Moolenbroek 	isc_symtab_t *symtab = NULL;
2856*00b67f09SDavid van Moolenbroek 	isc_symvalue_t symvalue;
2857*00b67f09SDavid van Moolenbroek 	int i;
2858*00b67f09SDavid van Moolenbroek 
2859*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "logging", &logobj);
2860*00b67f09SDavid van Moolenbroek 	if (logobj == NULL)
2861*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
2862*00b67f09SDavid van Moolenbroek 
2863*00b67f09SDavid van Moolenbroek 	result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
2864*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
2865*00b67f09SDavid van Moolenbroek 		return (result);
2866*00b67f09SDavid van Moolenbroek 
2867*00b67f09SDavid van Moolenbroek 	symvalue.as_cpointer = NULL;
2868*00b67f09SDavid van Moolenbroek 	for (i = 0; default_channels[i] != NULL; i++) {
2869*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_define(symtab, default_channels[i], 1,
2870*00b67f09SDavid van Moolenbroek 					    symvalue, isc_symexists_replace);
2871*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
2872*00b67f09SDavid van Moolenbroek 			result = tresult;
2873*00b67f09SDavid van Moolenbroek 	}
2874*00b67f09SDavid van Moolenbroek 
2875*00b67f09SDavid van Moolenbroek 	cfg_map_get(logobj, "channel", &channels);
2876*00b67f09SDavid van Moolenbroek 
2877*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(channels);
2878*00b67f09SDavid van Moolenbroek 	     element != NULL;
2879*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2880*00b67f09SDavid van Moolenbroek 	{
2881*00b67f09SDavid van Moolenbroek 		channel = cfg_listelt_value(element);
2882*00b67f09SDavid van Moolenbroek 		channelname = cfg_obj_asstring(cfg_map_getname(channel));
2883*00b67f09SDavid van Moolenbroek 		fileobj = syslogobj = nullobj = stderrobj = NULL;
2884*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(channel, "file", &fileobj);
2885*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(channel, "syslog", &syslogobj);
2886*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(channel, "null", &nullobj);
2887*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(channel, "stderr", &stderrobj);
2888*00b67f09SDavid van Moolenbroek 		i = 0;
2889*00b67f09SDavid van Moolenbroek 		if (fileobj != NULL)
2890*00b67f09SDavid van Moolenbroek 			i++;
2891*00b67f09SDavid van Moolenbroek 		if (syslogobj != NULL)
2892*00b67f09SDavid van Moolenbroek 			i++;
2893*00b67f09SDavid van Moolenbroek 		if (nullobj != NULL)
2894*00b67f09SDavid van Moolenbroek 			i++;
2895*00b67f09SDavid van Moolenbroek 		if (stderrobj != NULL)
2896*00b67f09SDavid van Moolenbroek 			i++;
2897*00b67f09SDavid van Moolenbroek 		if (i != 1) {
2898*00b67f09SDavid van Moolenbroek 			cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
2899*00b67f09SDavid van Moolenbroek 				    "channel '%s': exactly one of file, syslog, "
2900*00b67f09SDavid van Moolenbroek 				    "null, and stderr must be present",
2901*00b67f09SDavid van Moolenbroek 				     channelname);
2902*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2903*00b67f09SDavid van Moolenbroek 		}
2904*00b67f09SDavid van Moolenbroek 		tresult = isc_symtab_define(symtab, channelname, 1,
2905*00b67f09SDavid van Moolenbroek 					    symvalue, isc_symexists_replace);
2906*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
2907*00b67f09SDavid van Moolenbroek 			result = tresult;
2908*00b67f09SDavid van Moolenbroek 	}
2909*00b67f09SDavid van Moolenbroek 
2910*00b67f09SDavid van Moolenbroek 	cfg_map_get(logobj, "category", &categories);
2911*00b67f09SDavid van Moolenbroek 
2912*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(categories);
2913*00b67f09SDavid van Moolenbroek 	     element != NULL;
2914*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2915*00b67f09SDavid van Moolenbroek 	{
2916*00b67f09SDavid van Moolenbroek 		category = cfg_listelt_value(element);
2917*00b67f09SDavid van Moolenbroek 		catname = cfg_obj_asstring(cfg_tuple_get(category, "name"));
2918*00b67f09SDavid van Moolenbroek 		if (isc_log_categorybyname(logctx, catname) == NULL) {
2919*00b67f09SDavid van Moolenbroek 			cfg_obj_log(category, logctx, ISC_LOG_ERROR,
2920*00b67f09SDavid van Moolenbroek 				    "undefined category: '%s'", catname);
2921*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
2922*00b67f09SDavid van Moolenbroek 		}
2923*00b67f09SDavid van Moolenbroek 		channels = cfg_tuple_get(category, "destinations");
2924*00b67f09SDavid van Moolenbroek 		for (delement = cfg_list_first(channels);
2925*00b67f09SDavid van Moolenbroek 		     delement != NULL;
2926*00b67f09SDavid van Moolenbroek 		     delement = cfg_list_next(delement))
2927*00b67f09SDavid van Moolenbroek 		{
2928*00b67f09SDavid van Moolenbroek 			channel = cfg_listelt_value(delement);
2929*00b67f09SDavid van Moolenbroek 			channelname = cfg_obj_asstring(channel);
2930*00b67f09SDavid van Moolenbroek 			tresult = isc_symtab_lookup(symtab, channelname, 1,
2931*00b67f09SDavid van Moolenbroek 						    &symvalue);
2932*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS) {
2933*00b67f09SDavid van Moolenbroek 				cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
2934*00b67f09SDavid van Moolenbroek 					    "undefined channel: '%s'",
2935*00b67f09SDavid van Moolenbroek 					    channelname);
2936*00b67f09SDavid van Moolenbroek 				result = tresult;
2937*00b67f09SDavid van Moolenbroek 			}
2938*00b67f09SDavid van Moolenbroek 		}
2939*00b67f09SDavid van Moolenbroek 	}
2940*00b67f09SDavid van Moolenbroek 	isc_symtab_destroy(&symtab);
2941*00b67f09SDavid van Moolenbroek 	return (result);
2942*00b67f09SDavid van Moolenbroek }
2943*00b67f09SDavid van Moolenbroek 
2944*00b67f09SDavid van Moolenbroek static isc_result_t
bind9_check_controlskeys(const cfg_obj_t * control,const cfg_obj_t * keylist,isc_log_t * logctx)2945*00b67f09SDavid van Moolenbroek bind9_check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist,
2946*00b67f09SDavid van Moolenbroek 			 isc_log_t *logctx)
2947*00b67f09SDavid van Moolenbroek {
2948*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
2949*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *control_keylist;
2950*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element;
2951*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *key;
2952*00b67f09SDavid van Moolenbroek 	const char *keyval;
2953*00b67f09SDavid van Moolenbroek 
2954*00b67f09SDavid van Moolenbroek 	control_keylist = cfg_tuple_get(control, "keys");
2955*00b67f09SDavid van Moolenbroek 	if (cfg_obj_isvoid(control_keylist))
2956*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
2957*00b67f09SDavid van Moolenbroek 
2958*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(control_keylist);
2959*00b67f09SDavid van Moolenbroek 	     element != NULL;
2960*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element))
2961*00b67f09SDavid van Moolenbroek 	{
2962*00b67f09SDavid van Moolenbroek 		key = cfg_listelt_value(element);
2963*00b67f09SDavid van Moolenbroek 		keyval = cfg_obj_asstring(key);
2964*00b67f09SDavid van Moolenbroek 
2965*00b67f09SDavid van Moolenbroek 		if (!rndckey_exists(keylist, keyval)) {
2966*00b67f09SDavid van Moolenbroek 			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
2967*00b67f09SDavid van Moolenbroek 				    "unknown key '%s'", keyval);
2968*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
2969*00b67f09SDavid van Moolenbroek 		}
2970*00b67f09SDavid van Moolenbroek 	}
2971*00b67f09SDavid van Moolenbroek 	return (result);
2972*00b67f09SDavid van Moolenbroek }
2973*00b67f09SDavid van Moolenbroek 
2974*00b67f09SDavid van Moolenbroek static isc_result_t
bind9_check_controls(const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)2975*00b67f09SDavid van Moolenbroek bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
2976*00b67f09SDavid van Moolenbroek 		     isc_mem_t *mctx)
2977*00b67f09SDavid van Moolenbroek {
2978*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS, tresult;
2979*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_t *actx = NULL;
2980*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *element, *element2;
2981*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *allow;
2982*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *control;
2983*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *controls;
2984*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *controlslist = NULL;
2985*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *inetcontrols;
2986*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *unixcontrols;
2987*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *keylist = NULL;
2988*00b67f09SDavid van Moolenbroek 	const char *path;
2989*00b67f09SDavid van Moolenbroek 	isc_uint32_t perm, mask;
2990*00b67f09SDavid van Moolenbroek 	dns_acl_t *acl = NULL;
2991*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t addr;
2992*00b67f09SDavid van Moolenbroek 	int i;
2993*00b67f09SDavid van Moolenbroek 
2994*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "controls", &controlslist);
2995*00b67f09SDavid van Moolenbroek 	if (controlslist == NULL)
2996*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
2997*00b67f09SDavid van Moolenbroek 
2998*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "key", &keylist);
2999*00b67f09SDavid van Moolenbroek 
3000*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_create(mctx, &actx);
3001*00b67f09SDavid van Moolenbroek 
3002*00b67f09SDavid van Moolenbroek 	/*
3003*00b67f09SDavid van Moolenbroek 	 * INET: Check allow clause.
3004*00b67f09SDavid van Moolenbroek 	 * UNIX: Check "perm" for sanity, check path length.
3005*00b67f09SDavid van Moolenbroek 	 */
3006*00b67f09SDavid van Moolenbroek 	for (element = cfg_list_first(controlslist);
3007*00b67f09SDavid van Moolenbroek 	     element != NULL;
3008*00b67f09SDavid van Moolenbroek 	     element = cfg_list_next(element)) {
3009*00b67f09SDavid van Moolenbroek 		controls = cfg_listelt_value(element);
3010*00b67f09SDavid van Moolenbroek 		unixcontrols = NULL;
3011*00b67f09SDavid van Moolenbroek 		inetcontrols = NULL;
3012*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(controls, "unix", &unixcontrols);
3013*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(controls, "inet", &inetcontrols);
3014*00b67f09SDavid van Moolenbroek 		for (element2 = cfg_list_first(inetcontrols);
3015*00b67f09SDavid van Moolenbroek 		     element2 != NULL;
3016*00b67f09SDavid van Moolenbroek 		     element2 = cfg_list_next(element2)) {
3017*00b67f09SDavid van Moolenbroek 			control = cfg_listelt_value(element2);
3018*00b67f09SDavid van Moolenbroek 			allow = cfg_tuple_get(control, "allow");
3019*00b67f09SDavid van Moolenbroek 			tresult = cfg_acl_fromconfig(allow, config, logctx,
3020*00b67f09SDavid van Moolenbroek 						     actx, mctx, 0, &acl);
3021*00b67f09SDavid van Moolenbroek 			if (acl != NULL)
3022*00b67f09SDavid van Moolenbroek 				dns_acl_detach(&acl);
3023*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
3024*00b67f09SDavid van Moolenbroek 				result = tresult;
3025*00b67f09SDavid van Moolenbroek 			tresult = bind9_check_controlskeys(control, keylist,
3026*00b67f09SDavid van Moolenbroek 							   logctx);
3027*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
3028*00b67f09SDavid van Moolenbroek 				result = tresult;
3029*00b67f09SDavid van Moolenbroek 		}
3030*00b67f09SDavid van Moolenbroek 		for (element2 = cfg_list_first(unixcontrols);
3031*00b67f09SDavid van Moolenbroek 		     element2 != NULL;
3032*00b67f09SDavid van Moolenbroek 		     element2 = cfg_list_next(element2)) {
3033*00b67f09SDavid van Moolenbroek 			control = cfg_listelt_value(element2);
3034*00b67f09SDavid van Moolenbroek 			path = cfg_obj_asstring(cfg_tuple_get(control, "path"));
3035*00b67f09SDavid van Moolenbroek 			tresult = isc_sockaddr_frompath(&addr, path);
3036*00b67f09SDavid van Moolenbroek 			if (tresult == ISC_R_NOSPACE) {
3037*00b67f09SDavid van Moolenbroek 				cfg_obj_log(control, logctx, ISC_LOG_ERROR,
3038*00b67f09SDavid van Moolenbroek 					    "unix control '%s': path too long",
3039*00b67f09SDavid van Moolenbroek 					    path);
3040*00b67f09SDavid van Moolenbroek 				result = ISC_R_NOSPACE;
3041*00b67f09SDavid van Moolenbroek 			}
3042*00b67f09SDavid van Moolenbroek 			perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
3043*00b67f09SDavid van Moolenbroek 			for (i = 0; i < 3; i++) {
3044*00b67f09SDavid van Moolenbroek #ifdef NEED_SECURE_DIRECTORY
3045*00b67f09SDavid van Moolenbroek 				mask = (0x1 << (i*3));	/* SEARCH */
3046*00b67f09SDavid van Moolenbroek #else
3047*00b67f09SDavid van Moolenbroek 				mask = (0x6 << (i*3)); 	/* READ + WRITE */
3048*00b67f09SDavid van Moolenbroek #endif
3049*00b67f09SDavid van Moolenbroek 				if ((perm & mask) == mask)
3050*00b67f09SDavid van Moolenbroek 					break;
3051*00b67f09SDavid van Moolenbroek 			}
3052*00b67f09SDavid van Moolenbroek 			if (i == 0) {
3053*00b67f09SDavid van Moolenbroek 				cfg_obj_log(control, logctx, ISC_LOG_WARNING,
3054*00b67f09SDavid van Moolenbroek 					    "unix control '%s' allows access "
3055*00b67f09SDavid van Moolenbroek 					    "to everyone", path);
3056*00b67f09SDavid van Moolenbroek 			} else if (i == 3) {
3057*00b67f09SDavid van Moolenbroek 				cfg_obj_log(control, logctx, ISC_LOG_WARNING,
3058*00b67f09SDavid van Moolenbroek 					    "unix control '%s' allows access "
3059*00b67f09SDavid van Moolenbroek 					    "to nobody", path);
3060*00b67f09SDavid van Moolenbroek 			}
3061*00b67f09SDavid van Moolenbroek 			tresult = bind9_check_controlskeys(control, keylist,
3062*00b67f09SDavid van Moolenbroek 							   logctx);
3063*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
3064*00b67f09SDavid van Moolenbroek 				result = tresult;
3065*00b67f09SDavid van Moolenbroek 		}
3066*00b67f09SDavid van Moolenbroek 	}
3067*00b67f09SDavid van Moolenbroek 	cfg_aclconfctx_detach(&actx);
3068*00b67f09SDavid van Moolenbroek 	return (result);
3069*00b67f09SDavid van Moolenbroek }
3070*00b67f09SDavid van Moolenbroek 
3071*00b67f09SDavid van Moolenbroek isc_result_t
bind9_check_namedconf(const cfg_obj_t * config,isc_log_t * logctx,isc_mem_t * mctx)3072*00b67f09SDavid van Moolenbroek bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
3073*00b67f09SDavid van Moolenbroek 		      isc_mem_t *mctx)
3074*00b67f09SDavid van Moolenbroek {
3075*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *options = NULL;
3076*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *views = NULL;
3077*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *acls = NULL;
3078*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *kals = NULL;
3079*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *obj;
3080*00b67f09SDavid van Moolenbroek 	const cfg_listelt_t *velement;
3081*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
3082*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
3083*00b67f09SDavid van Moolenbroek 	isc_symtab_t *symtab = NULL;
3084*00b67f09SDavid van Moolenbroek 	isc_symtab_t *files = NULL;
3085*00b67f09SDavid van Moolenbroek 
3086*00b67f09SDavid van Moolenbroek 	static const char *builtin[] = { "localhost", "localnets",
3087*00b67f09SDavid van Moolenbroek 					 "any", "none"};
3088*00b67f09SDavid van Moolenbroek 
3089*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "options", &options);
3090*00b67f09SDavid van Moolenbroek 
3091*00b67f09SDavid van Moolenbroek 	if (options != NULL &&
3092*00b67f09SDavid van Moolenbroek 	    check_options(options, logctx, mctx,
3093*00b67f09SDavid van Moolenbroek 			  optlevel_options) != ISC_R_SUCCESS)
3094*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
3095*00b67f09SDavid van Moolenbroek 
3096*00b67f09SDavid van Moolenbroek 	if (bind9_check_logging(config, logctx, mctx) != ISC_R_SUCCESS)
3097*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
3098*00b67f09SDavid van Moolenbroek 
3099*00b67f09SDavid van Moolenbroek 	if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS)
3100*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
3101*00b67f09SDavid van Moolenbroek 
3102*00b67f09SDavid van Moolenbroek 	if (options != NULL &&
3103*00b67f09SDavid van Moolenbroek 	    check_order(options, logctx) != ISC_R_SUCCESS)
3104*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
3105*00b67f09SDavid van Moolenbroek 
3106*00b67f09SDavid van Moolenbroek 	(void)cfg_map_get(config, "view", &views);
3107*00b67f09SDavid van Moolenbroek 
3108*00b67f09SDavid van Moolenbroek 	if (views != NULL && options != NULL)
3109*00b67f09SDavid van Moolenbroek 		if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
3110*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
3111*00b67f09SDavid van Moolenbroek 
3112*00b67f09SDavid van Moolenbroek 	/*
3113*00b67f09SDavid van Moolenbroek 	 * Use case insensitve comparision as not all file systems are
3114*00b67f09SDavid van Moolenbroek 	 * case sensitive. This will prevent people using FOO.DB and foo.db
3115*00b67f09SDavid van Moolenbroek 	 * on case sensitive file systems but that shouldn't be a major issue.
3116*00b67f09SDavid van Moolenbroek 	 */
3117*00b67f09SDavid van Moolenbroek 	tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE,
3118*00b67f09SDavid van Moolenbroek 				    &files);
3119*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
3120*00b67f09SDavid van Moolenbroek 		result = tresult;
3121*00b67f09SDavid van Moolenbroek 
3122*00b67f09SDavid van Moolenbroek 	if (views == NULL) {
3123*00b67f09SDavid van Moolenbroek 		if (check_viewconf(config, NULL, NULL, dns_rdataclass_in,
3124*00b67f09SDavid van Moolenbroek 				   files, logctx, mctx) != ISC_R_SUCCESS)
3125*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
3126*00b67f09SDavid van Moolenbroek 	} else {
3127*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *zones = NULL;
3128*00b67f09SDavid van Moolenbroek 
3129*00b67f09SDavid van Moolenbroek 		(void)cfg_map_get(config, "zone", &zones);
3130*00b67f09SDavid van Moolenbroek 		if (zones != NULL) {
3131*00b67f09SDavid van Moolenbroek 			cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
3132*00b67f09SDavid van Moolenbroek 				    "when using 'view' statements, "
3133*00b67f09SDavid van Moolenbroek 				    "all zones must be in views");
3134*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
3135*00b67f09SDavid van Moolenbroek 		}
3136*00b67f09SDavid van Moolenbroek 	}
3137*00b67f09SDavid van Moolenbroek 
3138*00b67f09SDavid van Moolenbroek 	tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
3139*00b67f09SDavid van Moolenbroek 	if (tresult != ISC_R_SUCCESS)
3140*00b67f09SDavid van Moolenbroek 		result = tresult;
3141*00b67f09SDavid van Moolenbroek 	for (velement = cfg_list_first(views);
3142*00b67f09SDavid van Moolenbroek 	     velement != NULL;
3143*00b67f09SDavid van Moolenbroek 	     velement = cfg_list_next(velement))
3144*00b67f09SDavid van Moolenbroek 	{
3145*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *view = cfg_listelt_value(velement);
3146*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *vname = cfg_tuple_get(view, "name");
3147*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *voptions = cfg_tuple_get(view, "options");
3148*00b67f09SDavid van Moolenbroek 		const cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
3149*00b67f09SDavid van Moolenbroek 		dns_rdataclass_t vclass = dns_rdataclass_in;
3150*00b67f09SDavid van Moolenbroek 		const char *key = cfg_obj_asstring(vname);
3151*00b67f09SDavid van Moolenbroek 		isc_symvalue_t symvalue;
3152*00b67f09SDavid van Moolenbroek 
3153*00b67f09SDavid van Moolenbroek 		tresult = ISC_R_SUCCESS;
3154*00b67f09SDavid van Moolenbroek 		if (cfg_obj_isstring(vclassobj)) {
3155*00b67f09SDavid van Moolenbroek 			isc_textregion_t r;
3156*00b67f09SDavid van Moolenbroek 
3157*00b67f09SDavid van Moolenbroek 			DE_CONST(cfg_obj_asstring(vclassobj), r.base);
3158*00b67f09SDavid van Moolenbroek 			r.length = strlen(r.base);
3159*00b67f09SDavid van Moolenbroek 			tresult = dns_rdataclass_fromtext(&vclass, &r);
3160*00b67f09SDavid van Moolenbroek 			if (tresult != ISC_R_SUCCESS)
3161*00b67f09SDavid van Moolenbroek 				cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
3162*00b67f09SDavid van Moolenbroek 					    "view '%s': invalid class %s",
3163*00b67f09SDavid van Moolenbroek 					    cfg_obj_asstring(vname), r.base);
3164*00b67f09SDavid van Moolenbroek 		}
3165*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS && symtab != NULL) {
3166*00b67f09SDavid van Moolenbroek 			symvalue.as_cpointer = view;
3167*00b67f09SDavid van Moolenbroek 			tresult = isc_symtab_define(symtab, key, vclass,
3168*00b67f09SDavid van Moolenbroek 						    symvalue,
3169*00b67f09SDavid van Moolenbroek 						    isc_symexists_reject);
3170*00b67f09SDavid van Moolenbroek 			if (tresult == ISC_R_EXISTS) {
3171*00b67f09SDavid van Moolenbroek 				const char *file;
3172*00b67f09SDavid van Moolenbroek 				unsigned int line;
3173*00b67f09SDavid van Moolenbroek 				RUNTIME_CHECK(isc_symtab_lookup(symtab, key,
3174*00b67f09SDavid van Moolenbroek 					   vclass, &symvalue) == ISC_R_SUCCESS);
3175*00b67f09SDavid van Moolenbroek 				file = cfg_obj_file(symvalue.as_cpointer);
3176*00b67f09SDavid van Moolenbroek 				line = cfg_obj_line(symvalue.as_cpointer);
3177*00b67f09SDavid van Moolenbroek 				cfg_obj_log(view, logctx, ISC_LOG_ERROR,
3178*00b67f09SDavid van Moolenbroek 					    "view '%s': already exists "
3179*00b67f09SDavid van Moolenbroek 					    "previous definition: %s:%u",
3180*00b67f09SDavid van Moolenbroek 					    key, file, line);
3181*00b67f09SDavid van Moolenbroek 				result = tresult;
3182*00b67f09SDavid van Moolenbroek 			} else if (tresult != ISC_R_SUCCESS) {
3183*00b67f09SDavid van Moolenbroek 				result = tresult;
3184*00b67f09SDavid van Moolenbroek 			} else if ((strcasecmp(key, "_bind") == 0 &&
3185*00b67f09SDavid van Moolenbroek 				    vclass == dns_rdataclass_ch) ||
3186*00b67f09SDavid van Moolenbroek 				   (strcasecmp(key, "_default") == 0 &&
3187*00b67f09SDavid van Moolenbroek 				    vclass == dns_rdataclass_in)) {
3188*00b67f09SDavid van Moolenbroek 				cfg_obj_log(view, logctx, ISC_LOG_ERROR,
3189*00b67f09SDavid van Moolenbroek 					    "attempt to redefine builtin view "
3190*00b67f09SDavid van Moolenbroek 					    "'%s'", key);
3191*00b67f09SDavid van Moolenbroek 				result = ISC_R_EXISTS;
3192*00b67f09SDavid van Moolenbroek 			}
3193*00b67f09SDavid van Moolenbroek 		}
3194*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS)
3195*00b67f09SDavid van Moolenbroek 			tresult = check_viewconf(config, voptions, key, vclass,
3196*00b67f09SDavid van Moolenbroek 						 files, logctx, mctx);
3197*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS)
3198*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
3199*00b67f09SDavid van Moolenbroek 	}
3200*00b67f09SDavid van Moolenbroek 	if (symtab != NULL)
3201*00b67f09SDavid van Moolenbroek 		isc_symtab_destroy(&symtab);
3202*00b67f09SDavid van Moolenbroek 	if (files != NULL)
3203*00b67f09SDavid van Moolenbroek 		isc_symtab_destroy(&files);
3204*00b67f09SDavid van Moolenbroek 
3205*00b67f09SDavid van Moolenbroek 	if (views != NULL && options != NULL) {
3206*00b67f09SDavid van Moolenbroek 		obj = NULL;
3207*00b67f09SDavid van Moolenbroek 		tresult = cfg_map_get(options, "cache-file", &obj);
3208*00b67f09SDavid van Moolenbroek 		if (tresult == ISC_R_SUCCESS) {
3209*00b67f09SDavid van Moolenbroek 			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
3210*00b67f09SDavid van Moolenbroek 				    "'cache-file' cannot be a global "
3211*00b67f09SDavid van Moolenbroek 				    "option if views are present");
3212*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
3213*00b67f09SDavid van Moolenbroek 		}
3214*00b67f09SDavid van Moolenbroek 	}
3215*00b67f09SDavid van Moolenbroek 
3216*00b67f09SDavid van Moolenbroek 	cfg_map_get(config, "acl", &acls);
3217*00b67f09SDavid van Moolenbroek 
3218*00b67f09SDavid van Moolenbroek 	if (acls != NULL) {
3219*00b67f09SDavid van Moolenbroek 		const cfg_listelt_t *elt;
3220*00b67f09SDavid van Moolenbroek 		const cfg_listelt_t *elt2;
3221*00b67f09SDavid van Moolenbroek 		const char *aclname;
3222*00b67f09SDavid van Moolenbroek 
3223*00b67f09SDavid van Moolenbroek 		for (elt = cfg_list_first(acls);
3224*00b67f09SDavid van Moolenbroek 		     elt != NULL;
3225*00b67f09SDavid van Moolenbroek 		     elt = cfg_list_next(elt)) {
3226*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *acl = cfg_listelt_value(elt);
3227*00b67f09SDavid van Moolenbroek 			unsigned int line = cfg_obj_line(acl);
3228*00b67f09SDavid van Moolenbroek 			unsigned int i;
3229*00b67f09SDavid van Moolenbroek 
3230*00b67f09SDavid van Moolenbroek 			aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
3231*00b67f09SDavid van Moolenbroek 			for (i = 0;
3232*00b67f09SDavid van Moolenbroek 			     i < sizeof(builtin) / sizeof(builtin[0]);
3233*00b67f09SDavid van Moolenbroek 			     i++)
3234*00b67f09SDavid van Moolenbroek 				if (strcasecmp(aclname, builtin[i]) == 0) {
3235*00b67f09SDavid van Moolenbroek 					cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
3236*00b67f09SDavid van Moolenbroek 						    "attempt to redefine "
3237*00b67f09SDavid van Moolenbroek 						    "builtin acl '%s'",
3238*00b67f09SDavid van Moolenbroek 						    aclname);
3239*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
3240*00b67f09SDavid van Moolenbroek 					break;
3241*00b67f09SDavid van Moolenbroek 				}
3242*00b67f09SDavid van Moolenbroek 
3243*00b67f09SDavid van Moolenbroek 			for (elt2 = cfg_list_next(elt);
3244*00b67f09SDavid van Moolenbroek 			     elt2 != NULL;
3245*00b67f09SDavid van Moolenbroek 			     elt2 = cfg_list_next(elt2)) {
3246*00b67f09SDavid van Moolenbroek 				const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
3247*00b67f09SDavid van Moolenbroek 				const char *name;
3248*00b67f09SDavid van Moolenbroek 				name = cfg_obj_asstring(cfg_tuple_get(acl2,
3249*00b67f09SDavid van Moolenbroek 								      "name"));
3250*00b67f09SDavid van Moolenbroek 				if (strcasecmp(aclname, name) == 0) {
3251*00b67f09SDavid van Moolenbroek 					const char *file = cfg_obj_file(acl);
3252*00b67f09SDavid van Moolenbroek 
3253*00b67f09SDavid van Moolenbroek 					if (file == NULL)
3254*00b67f09SDavid van Moolenbroek 						file = "<unknown file>";
3255*00b67f09SDavid van Moolenbroek 
3256*00b67f09SDavid van Moolenbroek 					cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
3257*00b67f09SDavid van Moolenbroek 						    "attempt to redefine "
3258*00b67f09SDavid van Moolenbroek 						    "acl '%s' previous "
3259*00b67f09SDavid van Moolenbroek 						    "definition: %s:%u",
3260*00b67f09SDavid van Moolenbroek 						     name, file, line);
3261*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
3262*00b67f09SDavid van Moolenbroek 				}
3263*00b67f09SDavid van Moolenbroek 			}
3264*00b67f09SDavid van Moolenbroek 		}
3265*00b67f09SDavid van Moolenbroek 	}
3266*00b67f09SDavid van Moolenbroek 
3267*00b67f09SDavid van Moolenbroek 	tresult = cfg_map_get(config, "kal", &kals);
3268*00b67f09SDavid van Moolenbroek 	if (tresult == ISC_R_SUCCESS) {
3269*00b67f09SDavid van Moolenbroek 		const cfg_listelt_t *elt;
3270*00b67f09SDavid van Moolenbroek 		const cfg_listelt_t *elt2;
3271*00b67f09SDavid van Moolenbroek 		const char *aclname;
3272*00b67f09SDavid van Moolenbroek 
3273*00b67f09SDavid van Moolenbroek 		for (elt = cfg_list_first(kals);
3274*00b67f09SDavid van Moolenbroek 		     elt != NULL;
3275*00b67f09SDavid van Moolenbroek 		     elt = cfg_list_next(elt)) {
3276*00b67f09SDavid van Moolenbroek 			const cfg_obj_t *acl = cfg_listelt_value(elt);
3277*00b67f09SDavid van Moolenbroek 
3278*00b67f09SDavid van Moolenbroek 			aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
3279*00b67f09SDavid van Moolenbroek 
3280*00b67f09SDavid van Moolenbroek 			for (elt2 = cfg_list_next(elt);
3281*00b67f09SDavid van Moolenbroek 			     elt2 != NULL;
3282*00b67f09SDavid van Moolenbroek 			     elt2 = cfg_list_next(elt2)) {
3283*00b67f09SDavid van Moolenbroek 				const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
3284*00b67f09SDavid van Moolenbroek 				const char *name;
3285*00b67f09SDavid van Moolenbroek 				name = cfg_obj_asstring(cfg_tuple_get(acl2,
3286*00b67f09SDavid van Moolenbroek 								      "name"));
3287*00b67f09SDavid van Moolenbroek 				if (strcasecmp(aclname, name) == 0) {
3288*00b67f09SDavid van Moolenbroek 					const char *file = cfg_obj_file(acl);
3289*00b67f09SDavid van Moolenbroek 					unsigned int line = cfg_obj_line(acl);
3290*00b67f09SDavid van Moolenbroek 
3291*00b67f09SDavid van Moolenbroek 					if (file == NULL)
3292*00b67f09SDavid van Moolenbroek 						file = "<unknown file>";
3293*00b67f09SDavid van Moolenbroek 
3294*00b67f09SDavid van Moolenbroek 					cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
3295*00b67f09SDavid van Moolenbroek 						    "attempt to redefine "
3296*00b67f09SDavid van Moolenbroek 						    "kal '%s' previous "
3297*00b67f09SDavid van Moolenbroek 						    "definition: %s:%u",
3298*00b67f09SDavid van Moolenbroek 						     name, file, line);
3299*00b67f09SDavid van Moolenbroek 					result = ISC_R_FAILURE;
3300*00b67f09SDavid van Moolenbroek 				}
3301*00b67f09SDavid van Moolenbroek 			}
3302*00b67f09SDavid van Moolenbroek 		}
3303*00b67f09SDavid van Moolenbroek 	}
3304*00b67f09SDavid van Moolenbroek 
3305*00b67f09SDavid van Moolenbroek 	return (result);
3306*00b67f09SDavid van Moolenbroek }
3307