1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <bind.keys.h>
15 #include <inttypes.h>
16 #include <stdlib.h>
17 
18 #include <isc/buffer.h>
19 #include <isc/log.h>
20 #include <isc/mem.h>
21 #include <isc/parseint.h>
22 #include <isc/region.h>
23 #include <isc/result.h>
24 #include <isc/sockaddr.h>
25 #include <isc/string.h>
26 #include <isc/util.h>
27 
28 #include <dns/fixedname.h>
29 #include <dns/name.h>
30 #include <dns/rdataclass.h>
31 #include <dns/rdatatype.h>
32 #include <dns/tsig.h>
33 #include <dns/zone.h>
34 
35 #include <dst/dst.h>
36 
37 #include <isccfg/grammar.h>
38 #include <isccfg/namedconf.h>
39 
40 #include <named/config.h>
41 #include <named/globals.h>
42 
43 /*% default configuration */
44 static char defaultconf[] = "\
45 options {\n\
46 	answer-cookie true;\n\
47 	automatic-interface-scan yes;\n\
48 	bindkeys-file \"" NAMED_SYSCONFDIR "/bind.keys\";\n\
49 #	blackhole {none;};\n"
50 			    "	cookie-algorithm siphash24;\n"
51 			    "	coresize default;\n\
52 	datasize default;\n"
53 			    "\
54 #	deallocate-on-exit <obsolete>;\n\
55 #	directory <none>\n\
56 	dnssec-policy \"none\";\n\
57 	dump-file \"named_dump.db\";\n\
58 	edns-udp-size 1232;\n\
59 #	fake-iquery <obsolete>;\n\
60 	files unlimited;\n"
61 #if defined(HAVE_GEOIP2)
62 			    "	geoip-directory \"" MAXMINDDB_PREFIX "/share/"
63 			    "GeoIP\";"
64 			    "\n"
65 #elif defined(HAVE_GEOIP2)
66 			    "	geoip-directory \".\";\n"
67 #endif /* if defined(HAVE_GEOIP2) */
68 			    "\
69 #	has-old-clients <obsolete>;\n\
70 	heartbeat-interval 60;\n\
71 #	host-statistics <obsolete>;\n\
72 	interface-interval 60;\n\
73 #	keep-response-order {none;};\n\
74 	listen-on {any;};\n\
75 	listen-on-v6 {any;};\n\
76 #	lock-file \"" NAMED_LOCALSTATEDIR "/run/named/named.lock\";\n\
77 	match-mapped-addresses no;\n\
78 	max-ixfr-ratio 100%;\n\
79 	max-rsa-exponent-size 0; /* no limit */\n\
80 	max-udp-size 1232;\n\
81 	memstatistics-file \"named.memstats\";\n\
82 #	multiple-cnames <obsolete>;\n\
83 #	named-xfer <obsolete>;\n\
84 	nocookie-udp-size 4096;\n\
85 	notify-rate 20;\n\
86 	nta-lifetime 3600;\n\
87 	nta-recheck 300;\n\
88 #	pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\
89 	port 53;\n\
90 	tls-port 853;\n"
91 #if HAVE_LIBNGHTTP2
92 			    "http-port 80;\n"
93 			    "https-port 443;\n"
94 			    "http-listener-clients 300;\n"
95 			    "http-streams-per-connection 100;\n"
96 #endif
97 			    "\
98 	prefetch 2 9;\n\
99 	recursing-file \"named.recursing\";\n\
100 	recursive-clients 1000;\n\
101 	request-nsid false;\n\
102 	reserved-sockets 512;\n\
103 	resolver-query-timeout 10;\n\
104 	rrset-order { order random; };\n\
105 	secroots-file \"named.secroots\";\n\
106 	send-cookie true;\n\
107 #	serial-queries <obsolete>;\n\
108 	serial-query-rate 20;\n\
109 	server-id none;\n\
110 	session-keyalg hmac-sha256;\n\
111 #	session-keyfile \"" NAMED_LOCALSTATEDIR "/run/named/session.key\";\n\
112 	session-keyname local-ddns;\n\
113 	stacksize default;\n\
114 	startup-notify-rate 20;\n\
115 	statistics-file \"named.stats\";\n\
116 #	statistics-interval <obsolete>;\n\
117 	tcp-advertised-timeout 300;\n\
118 	tcp-clients 150;\n\
119 	tcp-idle-timeout 300;\n\
120 	tcp-initial-timeout 300;\n\
121 	tcp-keepalive-timeout 300;\n\
122 	tcp-listen-queue 10;\n\
123 	tcp-receive-buffer 0;\n\
124 	tcp-send-buffer 0;\n\
125 #	tkey-dhkey <none>\n\
126 #	tkey-domain <none>\n\
127 #	tkey-gssapi-credential <none>\n\
128 	transfer-message-size 20480;\n\
129 	transfers-in 10;\n\
130 	transfers-out 10;\n\
131 	transfers-per-ns 2;\n\
132 #	treat-cr-as-space <obsolete>;\n\
133 	trust-anchor-telemetry yes;\n\
134 #	use-id-pool <obsolete>;\n\
135 	udp-receive-buffer 0;\n\
136 	udp-send-buffer 0;\n\
137 \n\
138 	/* view */\n\
139 	allow-new-zones no;\n\
140 	allow-notify {none;};\n\
141 	allow-query-cache { localnets; localhost; };\n\
142 	allow-query-cache-on { any; };\n\
143 	allow-recursion { localnets; localhost; };\n\
144 	allow-recursion-on { any; };\n\
145 	allow-update-forwarding {none;};\n\
146 	auth-nxdomain false;\n\
147 	check-dup-records warn;\n\
148 	check-mx warn;\n\
149 	check-names primary fail;\n\
150 	check-names response ignore;\n\
151 	check-names secondary warn;\n\
152 	check-spf warn;\n\
153 	clients-per-query 10;\n\
154 	dnssec-accept-expired no;\n\
155 	dnssec-validation " VALIDATION_DEFAULT "; \n"
156 #ifdef HAVE_DNSTAP
157 			    "	dnstap-identity hostname;\n"
158 #endif /* ifdef HAVE_DNSTAP */
159 			    "\
160 #	fetch-glue <obsolete>;\n\
161 	fetch-quota-params 100 0.1 0.3 0.7;\n\
162 	fetches-per-server 0;\n\
163 	fetches-per-zone 0;\n\
164 	glue-cache yes;\n\
165 	lame-ttl 600;\n"
166 #ifdef HAVE_LMDB
167 			    "	lmdb-mapsize 32M;\n"
168 #endif /* ifdef HAVE_LMDB */
169 			    "	max-cache-size 90%;\n\
170 	max-cache-ttl 604800; /* 1 week */\n\
171 	max-clients-per-query 100;\n\
172 	max-ncache-ttl 10800; /* 3 hours */\n\
173 	max-recursion-depth 7;\n\
174 	max-recursion-queries 100;\n\
175 	max-stale-ttl 86400; /* 1 day */\n\
176 	message-compression yes;\n\
177 	min-ncache-ttl 0; /* 0 hours */\n\
178 	min-cache-ttl 0; /* 0 seconds */\n\
179 #	min-roots <obsolete>;\n\
180 	minimal-any false;\n\
181 	minimal-responses no-auth-recursive;\n\
182 	notify-source *;\n\
183 	notify-source-v6 *;\n\
184 	nsec3-test-zone no;\n\
185 	parental-source *;\n\
186 	parental-source-v6 *;\n\
187 	provide-ixfr true;\n\
188 	qname-minimization relaxed;\n\
189 	query-source address *;\n\
190 	query-source-v6 address *;\n\
191 	recursion true;\n\
192 	request-expire true;\n\
193 	request-ixfr true;\n\
194 	require-server-cookie no;\n\
195 	resolver-nonbackoff-tries 3;\n\
196 	resolver-retry-interval 800; /* in milliseconds */\n\
197 #	rfc2308-type1 <obsolete>;\n\
198 	root-key-sentinel yes;\n\
199 	servfail-ttl 1;\n\
200 #	sortlist <none>\n\
201 	stale-answer-client-timeout off;\n\
202 	stale-answer-enable false;\n\
203 	stale-answer-ttl 30; /* 30 seconds */\n\
204 	stale-cache-enable false;\n\
205 	stale-refresh-time 30; /* 30 seconds */\n\
206 	synth-from-dnssec no;\n\
207 #	topology <none>\n\
208 	transfer-format many-answers;\n\
209 	v6-bias 50;\n\
210 	zero-no-soa-ttl-cache no;\n\
211 \n\
212 	/* zone */\n\
213 	allow-query {any;};\n\
214 	allow-query-on {any;};\n\
215 	allow-transfer {any;};\n\
216 #	also-notify <none>\n\
217 	alt-transfer-source *;\n\
218 	alt-transfer-source-v6 *;\n\
219 	check-integrity yes;\n\
220 	check-mx-cname warn;\n\
221 	check-sibling yes;\n\
222 	check-srv-cname warn;\n\
223 	check-wildcard yes;\n\
224 	dialup no;\n\
225 	dnssec-dnskey-kskonly no;\n\
226 	dnssec-loadkeys-interval 60;\n\
227 	dnssec-secure-to-insecure no;\n\
228 	dnssec-update-mode maintain;\n\
229 #	forward <none>\n\
230 #	forwarders <none>\n\
231 #	inline-signing no;\n\
232 	ixfr-from-differences false;\n\
233 #	maintain-ixfr-base <obsolete>;\n\
234 #	max-ixfr-log-size <obsolete>\n\
235 	max-journal-size default;\n\
236 	max-records 0;\n\
237 	max-refresh-time 2419200; /* 4 weeks */\n\
238 	max-retry-time 1209600; /* 2 weeks */\n\
239 	max-transfer-idle-in 60;\n\
240 	max-transfer-idle-out 60;\n\
241 	max-transfer-time-in 120;\n\
242 	max-transfer-time-out 120;\n\
243 	min-refresh-time 300;\n\
244 	min-retry-time 500;\n\
245 	multi-master no;\n\
246 	notify yes;\n\
247 	notify-delay 5;\n\
248 	notify-to-soa no;\n\
249 	serial-update-method increment;\n\
250 	sig-signing-nodes 100;\n\
251 	sig-signing-signatures 10;\n\
252 	sig-signing-type 65534;\n\
253 	sig-validity-interval 30; /* days */\n\
254 	dnskey-sig-validity 0; /* default: sig-validity-interval */\n\
255 	transfer-source *;\n\
256 	transfer-source-v6 *;\n\
257 	try-tcp-refresh yes; /* BIND 8 compat */\n\
258 	update-check-ksk yes;\n\
259 	zero-no-soa-ttl yes;\n\
260 	zone-statistics terse;\n\
261 };\n\
262 "
263 
264 			    "#\n\
265 #  Zones in the \"_bind\" view are NOT counted in the count of zones.\n\
266 #\n\
267 view \"_bind\" chaos {\n\
268 	recursion no;\n\
269 	notify no;\n\
270 	allow-new-zones no;\n\
271 	max-cache-size 2M;\n\
272 \n\
273 	# Prevent use of this zone in DNS amplified reflection DoS attacks\n\
274 	rate-limit {\n\
275 		responses-per-second 3;\n\
276 		slip 0;\n\
277 		min-table-size 10;\n\
278 	};\n\
279 \n\
280 	zone \"version.bind\" chaos {\n\
281 		type primary;\n\
282 		database \"_builtin version\";\n\
283 	};\n\
284 \n\
285 	zone \"hostname.bind\" chaos {\n\
286 		type primary;\n\
287 		database \"_builtin hostname\";\n\
288 	};\n\
289 \n\
290 	zone \"authors.bind\" chaos {\n\
291 		type primary;\n\
292 		database \"_builtin authors\";\n\
293 	};\n\
294 \n\
295 	zone \"id.server\" chaos {\n\
296 		type primary;\n\
297 		database \"_builtin id\";\n\
298 	};\n\
299 };\n\
300 "
301 			    "#\n\
302 #  Default trusted key(s), used if \n\
303 # \"dnssec-validation auto;\" is set and\n\
304 #  sysconfdir/bind.keys doesn't exist).\n\
305 #\n\
306 # BEGIN DNSSEC KEYS\n"
307 
308 	/* Imported from bind.keys.h: */
309 	TRUST_ANCHORS
310 
311 			    "# END MANAGED KEYS\n\
312 \n\
313 primaries " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\
314 	2001:500:200::b;	# b.root-servers.net\n\
315 	2001:500:2::c;		# c.root-servers.net\n\
316 	2001:500:2f::f;		# f.root-servers.net\n\
317 	2001:500:12::d0d;	# g.root-servers.net\n\
318 	2001:7fd::1;		# k.root-servers.net\n\
319 	2620:0:2830:202::132;	# xfr.cjr.dns.icann.org\n\
320 	2620:0:2d0:202::132;	# xfr.lax.dns.icann.org\n\
321 	199.9.14.201;		# b.root-servers.net\n\
322 	192.33.4.12;		# c.root-servers.net\n\
323 	192.5.5.241;		# f.root-servers.net\n\
324 	192.112.36.4;		# g.root-servers.net\n\
325 	193.0.14.129;		# k.root-servers.net\n\
326 	192.0.47.132;		# xfr.cjr.dns.icann.org\n\
327 	192.0.32.132;		# xfr.lax.dns.icann.org\n\
328 };\n\
329 ";
330 
331 isc_result_t
named_config_parsedefaults(cfg_parser_t * parser,cfg_obj_t ** conf)332 named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
333 	isc_buffer_t b;
334 
335 	isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
336 	isc_buffer_add(&b, sizeof(defaultconf) - 1);
337 	return (cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf,
338 				 CFG_PCTX_NODEPRECATED, conf));
339 }
340 
341 isc_result_t
named_config_get(cfg_obj_t const * const * maps,const char * name,const cfg_obj_t ** obj)342 named_config_get(cfg_obj_t const *const *maps, const char *name,
343 		 const cfg_obj_t **obj) {
344 	int i;
345 
346 	for (i = 0; maps[i] != NULL; i++) {
347 		if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) {
348 			return (ISC_R_SUCCESS);
349 		}
350 	}
351 	return (ISC_R_NOTFOUND);
352 }
353 
354 isc_result_t
named_checknames_get(const cfg_obj_t ** maps,const char * const names[],const cfg_obj_t ** obj)355 named_checknames_get(const cfg_obj_t **maps, const char *const names[],
356 		     const cfg_obj_t **obj) {
357 	const cfg_listelt_t *element;
358 	const cfg_obj_t *checknames;
359 	const cfg_obj_t *type;
360 	const cfg_obj_t *value;
361 	int i;
362 
363 	REQUIRE(maps != NULL);
364 	REQUIRE(names != NULL);
365 	REQUIRE(obj != NULL && *obj == NULL);
366 
367 	for (i = 0; maps[i] != NULL; i++) {
368 		checknames = NULL;
369 		if (cfg_map_get(maps[i], "check-names", &checknames) ==
370 		    ISC_R_SUCCESS) {
371 			/*
372 			 * Zone map entry is not a list.
373 			 */
374 			if (checknames != NULL && !cfg_obj_islist(checknames)) {
375 				*obj = checknames;
376 				return (ISC_R_SUCCESS);
377 			}
378 			for (element = cfg_list_first(checknames);
379 			     element != NULL; element = cfg_list_next(element))
380 			{
381 				value = cfg_listelt_value(element);
382 				type = cfg_tuple_get(value, "type");
383 
384 				for (size_t j = 0; names[j] != NULL; j++) {
385 					if (strcasecmp(cfg_obj_asstring(type),
386 						       names[j]) == 0) {
387 						*obj = cfg_tuple_get(value,
388 								     "mode");
389 						return (ISC_R_SUCCESS);
390 					}
391 				}
392 			}
393 		}
394 	}
395 	return (ISC_R_NOTFOUND);
396 }
397 
398 int
named_config_listcount(const cfg_obj_t * list)399 named_config_listcount(const cfg_obj_t *list) {
400 	const cfg_listelt_t *e;
401 	int i = 0;
402 
403 	for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) {
404 		i++;
405 	}
406 
407 	return (i);
408 }
409 
410 isc_result_t
named_config_getclass(const cfg_obj_t * classobj,dns_rdataclass_t defclass,dns_rdataclass_t * classp)411 named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
412 		      dns_rdataclass_t *classp) {
413 	isc_textregion_t r;
414 	isc_result_t result;
415 
416 	if (!cfg_obj_isstring(classobj)) {
417 		*classp = defclass;
418 		return (ISC_R_SUCCESS);
419 	}
420 	DE_CONST(cfg_obj_asstring(classobj), r.base);
421 	r.length = strlen(r.base);
422 	result = dns_rdataclass_fromtext(classp, &r);
423 	if (result != ISC_R_SUCCESS) {
424 		cfg_obj_log(classobj, named_g_lctx, ISC_LOG_ERROR,
425 			    "unknown class '%s'", r.base);
426 	}
427 	return (result);
428 }
429 
430 isc_result_t
named_config_gettype(const cfg_obj_t * typeobj,dns_rdatatype_t deftype,dns_rdatatype_t * typep)431 named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
432 		     dns_rdatatype_t *typep) {
433 	isc_textregion_t r;
434 	isc_result_t result;
435 
436 	if (!cfg_obj_isstring(typeobj)) {
437 		*typep = deftype;
438 		return (ISC_R_SUCCESS);
439 	}
440 	DE_CONST(cfg_obj_asstring(typeobj), r.base);
441 	r.length = strlen(r.base);
442 	result = dns_rdatatype_fromtext(typep, &r);
443 	if (result != ISC_R_SUCCESS) {
444 		cfg_obj_log(typeobj, named_g_lctx, ISC_LOG_ERROR,
445 			    "unknown type '%s'", r.base);
446 	}
447 	return (result);
448 }
449 
450 dns_zonetype_t
named_config_getzonetype(const cfg_obj_t * zonetypeobj)451 named_config_getzonetype(const cfg_obj_t *zonetypeobj) {
452 	dns_zonetype_t ztype = dns_zone_none;
453 	const char *str;
454 
455 	str = cfg_obj_asstring(zonetypeobj);
456 	if (strcasecmp(str, "primary") == 0 || strcasecmp(str, "master") == 0) {
457 		ztype = dns_zone_primary;
458 	} else if (strcasecmp(str, "secondary") == 0 ||
459 		   strcasecmp(str, "slave") == 0) {
460 		ztype = dns_zone_secondary;
461 	} else if (strcasecmp(str, "mirror") == 0) {
462 		ztype = dns_zone_mirror;
463 	} else if (strcasecmp(str, "stub") == 0) {
464 		ztype = dns_zone_stub;
465 	} else if (strcasecmp(str, "static-stub") == 0) {
466 		ztype = dns_zone_staticstub;
467 	} else if (strcasecmp(str, "redirect") == 0) {
468 		ztype = dns_zone_redirect;
469 	} else {
470 		INSIST(0);
471 		ISC_UNREACHABLE();
472 	}
473 	return (ztype);
474 }
475 
476 isc_result_t
named_config_getiplist(const cfg_obj_t * config,const cfg_obj_t * list,in_port_t defport,isc_mem_t * mctx,isc_sockaddr_t ** addrsp,isc_dscp_t ** dscpsp,uint32_t * countp)477 named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
478 		       in_port_t defport, isc_mem_t *mctx,
479 		       isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
480 		       uint32_t *countp) {
481 	int count, i = 0;
482 	const cfg_obj_t *addrlist;
483 	const cfg_obj_t *portobj, *dscpobj;
484 	const cfg_listelt_t *element;
485 	isc_sockaddr_t *addrs;
486 	in_port_t port;
487 	isc_dscp_t dscp = -1, *dscps = NULL;
488 	isc_result_t result;
489 
490 	INSIST(addrsp != NULL && *addrsp == NULL);
491 	INSIST(dscpsp == NULL || *dscpsp == NULL);
492 	INSIST(countp != NULL);
493 
494 	addrlist = cfg_tuple_get(list, "addresses");
495 	count = named_config_listcount(addrlist);
496 
497 	portobj = cfg_tuple_get(list, "port");
498 	if (cfg_obj_isuint32(portobj)) {
499 		uint32_t val = cfg_obj_asuint32(portobj);
500 		if (val > UINT16_MAX) {
501 			cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
502 				    "port '%u' out of range", val);
503 			return (ISC_R_RANGE);
504 		}
505 		port = (in_port_t)val;
506 	} else if (defport != 0) {
507 		port = defport;
508 	} else {
509 		result = named_config_getport(config, "port", &port);
510 		if (result != ISC_R_SUCCESS) {
511 			return (result);
512 		}
513 	}
514 
515 	if (dscpsp != NULL) {
516 		dscpobj = cfg_tuple_get(list, "dscp");
517 		if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
518 			if (cfg_obj_asuint32(dscpobj) > 63) {
519 				cfg_obj_log(dscpobj, named_g_lctx,
520 					    ISC_LOG_ERROR,
521 					    "dscp value '%u' is out of range",
522 					    cfg_obj_asuint32(dscpobj));
523 				return (ISC_R_RANGE);
524 			}
525 			dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
526 		}
527 
528 		dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t));
529 	}
530 
531 	addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
532 
533 	for (element = cfg_list_first(addrlist); element != NULL;
534 	     element = cfg_list_next(element), i++)
535 	{
536 		const cfg_obj_t *addr;
537 		INSIST(i < count);
538 		addr = cfg_listelt_value(element);
539 		addrs[i] = *cfg_obj_assockaddr(addr);
540 		if (dscpsp != NULL) {
541 			isc_dscp_t innerdscp;
542 			innerdscp = cfg_obj_getdscp(addr);
543 			if (innerdscp == -1) {
544 				innerdscp = dscp;
545 			}
546 			dscps[i] = innerdscp;
547 		}
548 		if (isc_sockaddr_getport(&addrs[i]) == 0) {
549 			isc_sockaddr_setport(&addrs[i], port);
550 		}
551 	}
552 	INSIST(i == count);
553 
554 	*addrsp = addrs;
555 	*countp = count;
556 
557 	if (dscpsp != NULL) {
558 		*dscpsp = dscps;
559 	}
560 
561 	return (ISC_R_SUCCESS);
562 }
563 
564 void
named_config_putiplist(isc_mem_t * mctx,isc_sockaddr_t ** addrsp,isc_dscp_t ** dscpsp,uint32_t count)565 named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
566 		       isc_dscp_t **dscpsp, uint32_t count) {
567 	INSIST(addrsp != NULL && *addrsp != NULL);
568 	INSIST(dscpsp == NULL || *dscpsp != NULL);
569 
570 	isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
571 	*addrsp = NULL;
572 
573 	if (dscpsp != NULL) {
574 		isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
575 		*dscpsp = NULL;
576 	}
577 }
578 
579 static isc_result_t
getremotesdef(const cfg_obj_t * cctx,const char * list,const char * name,const cfg_obj_t ** ret)580 getremotesdef(const cfg_obj_t *cctx, const char *list, const char *name,
581 	      const cfg_obj_t **ret) {
582 	isc_result_t result;
583 	const cfg_obj_t *obj = NULL;
584 	const cfg_listelt_t *elt;
585 
586 	REQUIRE(cctx != NULL);
587 	REQUIRE(name != NULL);
588 	REQUIRE(ret != NULL && *ret == NULL);
589 
590 	result = cfg_map_get(cctx, list, &obj);
591 	if (result != ISC_R_SUCCESS) {
592 		return (result);
593 	}
594 	elt = cfg_list_first(obj);
595 	while (elt != NULL) {
596 		obj = cfg_listelt_value(elt);
597 		if (strcasecmp(cfg_obj_asstring(cfg_tuple_get(obj, "name")),
598 			       name) == 0) {
599 			*ret = obj;
600 			return (ISC_R_SUCCESS);
601 		}
602 		elt = cfg_list_next(elt);
603 	}
604 	return (ISC_R_NOTFOUND);
605 }
606 
607 isc_result_t
named_config_getremotesdef(const cfg_obj_t * cctx,const char * list,const char * name,const cfg_obj_t ** ret)608 named_config_getremotesdef(const cfg_obj_t *cctx, const char *list,
609 			   const char *name, const cfg_obj_t **ret) {
610 	isc_result_t result;
611 
612 	if (strcmp(list, "parental-agents") == 0) {
613 		return (getremotesdef(cctx, list, name, ret));
614 	} else if (strcmp(list, "primaries") == 0) {
615 		result = getremotesdef(cctx, list, name, ret);
616 		if (result != ISC_R_SUCCESS) {
617 			result = getremotesdef(cctx, "masters", name, ret);
618 		}
619 		return (result);
620 	}
621 	return (ISC_R_NOTFOUND);
622 }
623 
624 static isc_result_t
named_config_getname(isc_mem_t * mctx,const cfg_obj_t * obj,dns_name_t ** namep)625 named_config_getname(isc_mem_t *mctx, const cfg_obj_t *obj,
626 		     dns_name_t **namep) {
627 	REQUIRE(namep != NULL && *namep == NULL);
628 
629 	const char *objstr;
630 	isc_result_t result;
631 	isc_buffer_t b;
632 	dns_fixedname_t fname;
633 
634 	if (!cfg_obj_isstring(obj)) {
635 		*namep = NULL;
636 		return (ISC_R_SUCCESS);
637 	}
638 
639 	*namep = isc_mem_get(mctx, sizeof(**namep));
640 	dns_name_init(*namep, NULL);
641 
642 	objstr = cfg_obj_asstring(obj);
643 	isc_buffer_constinit(&b, objstr, strlen(objstr));
644 	isc_buffer_add(&b, strlen(objstr));
645 	dns_fixedname_init(&fname);
646 	result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname,
647 				   0, NULL);
648 	if (result != ISC_R_SUCCESS) {
649 		isc_mem_put(mctx, *namep, sizeof(**namep));
650 		*namep = NULL;
651 		return (result);
652 	}
653 	dns_name_dup(dns_fixedname_name(&fname), mctx, *namep);
654 
655 	return (ISC_R_SUCCESS);
656 }
657 
658 #define grow_array(mctx, array, newlen, oldlen)                    \
659 	if (newlen >= oldlen) {                                    \
660 		size_t newsize = (newlen + 16) * sizeof(array[0]); \
661 		size_t oldsize = oldlen * sizeof(array[0]);        \
662 		void *tmp = isc_mem_get(mctx, newsize);            \
663 		memset(tmp, 0, newsize);                           \
664 		if (oldlen != 0) {                                 \
665 			memmove(tmp, array, oldsize);              \
666 			isc_mem_put(mctx, array, oldsize);         \
667 		}                                                  \
668 		array = tmp;                                       \
669 		oldlen = newlen + 16;                              \
670 	}
671 
672 #define shrink_array(mctx, array, newlen, oldlen)           \
673 	if (newlen < oldlen) {                              \
674 		void *tmp = NULL;                           \
675 		size_t newsize = newlen * sizeof(array[0]); \
676 		size_t oldsize = oldlen * sizeof(array[0]); \
677 		if (newlen != 0) {                          \
678 			tmp = isc_mem_get(mctx, newsize);   \
679 			memset(tmp, 0, newsize);            \
680 			memmove(tmp, array, newsize);       \
681 		} else {                                    \
682 			tmp = NULL;                         \
683 		}                                           \
684 		isc_mem_put(mctx, array, oldsize);          \
685 		array = tmp;                                \
686 		oldlen = newlen;                            \
687 	}
688 
689 isc_result_t
named_config_getipandkeylist(const cfg_obj_t * config,const char * listtype,const cfg_obj_t * list,isc_mem_t * mctx,dns_ipkeylist_t * ipkl)690 named_config_getipandkeylist(const cfg_obj_t *config, const char *listtype,
691 			     const cfg_obj_t *list, isc_mem_t *mctx,
692 			     dns_ipkeylist_t *ipkl) {
693 	uint32_t addrcount = 0, dscpcount = 0, keycount = 0, tlscount = 0,
694 		 i = 0;
695 	uint32_t listcount = 0, l = 0, j;
696 	uint32_t stackcount = 0, pushed = 0;
697 	isc_result_t result;
698 	const cfg_listelt_t *element;
699 	const cfg_obj_t *addrlist;
700 	const cfg_obj_t *portobj;
701 	const cfg_obj_t *dscpobj;
702 	in_port_t port = (in_port_t)0;
703 	in_port_t def_port;
704 	in_port_t def_tlsport;
705 	isc_dscp_t dscp = -1;
706 	isc_sockaddr_t *addrs = NULL;
707 	isc_dscp_t *dscps = NULL;
708 	dns_name_t **keys = NULL;
709 	dns_name_t **tlss = NULL;
710 	struct {
711 		const char *name;
712 	} *lists = NULL;
713 	struct {
714 		const cfg_listelt_t *element;
715 		in_port_t port;
716 		isc_dscp_t dscp;
717 	} *stack = NULL;
718 
719 	REQUIRE(ipkl != NULL);
720 	REQUIRE(ipkl->count == 0);
721 	REQUIRE(ipkl->addrs == NULL);
722 	REQUIRE(ipkl->keys == NULL);
723 	REQUIRE(ipkl->tlss == NULL);
724 	REQUIRE(ipkl->dscps == NULL);
725 	REQUIRE(ipkl->labels == NULL);
726 	REQUIRE(ipkl->allocated == 0);
727 
728 	/*
729 	 * Get system defaults.
730 	 */
731 	result = named_config_getport(config, "port", &def_port);
732 	if (result != ISC_R_SUCCESS) {
733 		goto cleanup;
734 	}
735 
736 	result = named_config_getport(config, "tls-port", &def_tlsport);
737 	if (result != ISC_R_SUCCESS) {
738 		goto cleanup;
739 	}
740 
741 	result = named_config_getdscp(config, &dscp);
742 	if (result != ISC_R_SUCCESS) {
743 		goto cleanup;
744 	}
745 
746 newlist:
747 	addrlist = cfg_tuple_get(list, "addresses");
748 	portobj = cfg_tuple_get(list, "port");
749 	dscpobj = cfg_tuple_get(list, "dscp");
750 
751 	if (cfg_obj_isuint32(portobj)) {
752 		uint32_t val = cfg_obj_asuint32(portobj);
753 		if (val > UINT16_MAX) {
754 			cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
755 				    "port '%u' out of range", val);
756 			result = ISC_R_RANGE;
757 			goto cleanup;
758 		}
759 		port = (in_port_t)val;
760 	}
761 
762 	if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
763 		if (cfg_obj_asuint32(dscpobj) > 63) {
764 			cfg_obj_log(dscpobj, named_g_lctx, ISC_LOG_ERROR,
765 				    "dscp value '%u' is out of range",
766 				    cfg_obj_asuint32(dscpobj));
767 			result = ISC_R_RANGE;
768 			goto cleanup;
769 		}
770 		dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
771 	}
772 
773 	result = ISC_R_NOMEMORY;
774 
775 	element = cfg_list_first(addrlist);
776 resume:
777 	for (; element != NULL; element = cfg_list_next(element)) {
778 		const cfg_obj_t *addr;
779 		const cfg_obj_t *key;
780 		const cfg_obj_t *tls;
781 
782 		addr = cfg_tuple_get(cfg_listelt_value(element),
783 				     "remoteselement");
784 		key = cfg_tuple_get(cfg_listelt_value(element), "key");
785 		tls = cfg_tuple_get(cfg_listelt_value(element), "tls");
786 
787 		if (!cfg_obj_issockaddr(addr)) {
788 			const char *listname = cfg_obj_asstring(addr);
789 			isc_result_t tresult;
790 
791 			/* Grow lists? */
792 			grow_array(mctx, lists, l, listcount);
793 
794 			/* Seen? */
795 			for (j = 0; j < l; j++) {
796 				if (strcasecmp(lists[j].name, listname) == 0) {
797 					break;
798 				}
799 			}
800 			if (j < l) {
801 				continue;
802 			}
803 			list = NULL;
804 			tresult = named_config_getremotesdef(config, listtype,
805 							     listname, &list);
806 			if (tresult == ISC_R_NOTFOUND) {
807 				cfg_obj_log(addr, named_g_lctx, ISC_LOG_ERROR,
808 					    "%s \"%s\" not found", listtype,
809 					    listname);
810 
811 				result = tresult;
812 				goto cleanup;
813 			}
814 			if (tresult != ISC_R_SUCCESS) {
815 				goto cleanup;
816 			}
817 			lists[l++].name = listname;
818 			/* Grow stack? */
819 			grow_array(mctx, stack, pushed, stackcount);
820 			/*
821 			 * We want to resume processing this list on the
822 			 * next element.
823 			 */
824 			stack[pushed].element = cfg_list_next(element);
825 			stack[pushed].port = port;
826 			stack[pushed].dscp = dscp;
827 			pushed++;
828 			goto newlist;
829 		}
830 
831 		grow_array(mctx, addrs, i, addrcount);
832 		grow_array(mctx, dscps, i, dscpcount);
833 		grow_array(mctx, keys, i, keycount);
834 		grow_array(mctx, tlss, i, tlscount);
835 
836 		addrs[i] = *cfg_obj_assockaddr(addr);
837 		dscps[i] = cfg_obj_getdscp(addr);
838 		if (dscps[i] == -1) {
839 			dscps[i] = dscp;
840 		}
841 
842 		result = named_config_getname(mctx, key, &keys[i]);
843 		if (result != ISC_R_SUCCESS) {
844 			i++; /* Increment here so that cleanup on error works.
845 			      */
846 			goto cleanup;
847 		}
848 
849 		result = named_config_getname(mctx, tls, &tlss[i]);
850 		if (result != ISC_R_SUCCESS) {
851 			i++; /* Increment here so that cleanup on error works.
852 			      */
853 			goto cleanup;
854 		}
855 
856 		/* Set the default port or tls-port */
857 		if (port == 0) {
858 			if (tlss[i] != NULL) {
859 				port = def_tlsport;
860 			} else {
861 				port = def_port;
862 			}
863 		}
864 
865 		if (isc_sockaddr_getport(&addrs[i]) == 0) {
866 			isc_sockaddr_setport(&addrs[i], port);
867 		}
868 		i++;
869 	}
870 	if (pushed != 0) {
871 		pushed--;
872 		element = stack[pushed].element;
873 		port = stack[pushed].port;
874 		dscp = stack[pushed].dscp;
875 		goto resume;
876 	}
877 
878 	shrink_array(mctx, addrs, i, addrcount);
879 	shrink_array(mctx, dscps, i, dscpcount);
880 	shrink_array(mctx, keys, i, keycount);
881 	shrink_array(mctx, tlss, i, tlscount);
882 
883 	if (lists != NULL) {
884 		isc_mem_put(mctx, lists, listcount * sizeof(lists[0]));
885 	}
886 	if (stack != NULL) {
887 		isc_mem_put(mctx, stack, stackcount * sizeof(stack[0]));
888 	}
889 
890 	INSIST(dscpcount == addrcount);
891 	INSIST(keycount == addrcount);
892 	INSIST(tlscount == addrcount);
893 	INSIST(keycount == dscpcount);
894 
895 	ipkl->addrs = addrs;
896 	ipkl->dscps = dscps;
897 	ipkl->keys = keys;
898 	ipkl->tlss = tlss;
899 	ipkl->count = addrcount;
900 	ipkl->allocated = addrcount;
901 
902 	return (ISC_R_SUCCESS);
903 
904 cleanup:
905 	if (addrs != NULL) {
906 		isc_mem_put(mctx, addrs, addrcount * sizeof(addrs[0]));
907 	}
908 	if (dscps != NULL) {
909 		isc_mem_put(mctx, dscps, dscpcount * sizeof(dscps[0]));
910 	}
911 	if (keys != NULL) {
912 		for (j = 0; j < i; j++) {
913 			if (keys[j] == NULL) {
914 				continue;
915 			}
916 			if (dns_name_dynamic(keys[j])) {
917 				dns_name_free(keys[j], mctx);
918 			}
919 			isc_mem_put(mctx, keys[j], sizeof(*keys[j]));
920 		}
921 		isc_mem_put(mctx, keys, keycount * sizeof(keys[0]));
922 	}
923 	if (tlss != NULL) {
924 		for (j = 0; j < i; j++) {
925 			if (tlss[j] == NULL) {
926 				continue;
927 			}
928 			if (dns_name_dynamic(tlss[j])) {
929 				dns_name_free(tlss[j], mctx);
930 			}
931 			isc_mem_put(mctx, tlss[j], sizeof(*tlss[j]));
932 		}
933 		isc_mem_put(mctx, tlss, tlscount * sizeof(tlss[0]));
934 	}
935 	if (lists != NULL) {
936 		isc_mem_put(mctx, lists, listcount * sizeof(lists[0]));
937 	}
938 	if (stack != NULL) {
939 		isc_mem_put(mctx, stack, stackcount * sizeof(stack[0]));
940 	}
941 	return (result);
942 }
943 
944 isc_result_t
named_config_getport(const cfg_obj_t * config,const char * type,in_port_t * portp)945 named_config_getport(const cfg_obj_t *config, const char *type,
946 		     in_port_t *portp) {
947 	const cfg_obj_t *maps[3];
948 	const cfg_obj_t *options = NULL;
949 	const cfg_obj_t *portobj = NULL;
950 	isc_result_t result;
951 	int i;
952 
953 	(void)cfg_map_get(config, "options", &options);
954 	i = 0;
955 	if (options != NULL) {
956 		maps[i++] = options;
957 	}
958 	maps[i++] = named_g_defaults;
959 	maps[i] = NULL;
960 
961 	result = named_config_get(maps, type, &portobj);
962 	INSIST(result == ISC_R_SUCCESS);
963 	if (cfg_obj_asuint32(portobj) >= UINT16_MAX) {
964 		cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR,
965 			    "port '%u' out of range",
966 			    cfg_obj_asuint32(portobj));
967 		return (ISC_R_RANGE);
968 	}
969 	*portp = (in_port_t)cfg_obj_asuint32(portobj);
970 	return (ISC_R_SUCCESS);
971 }
972 
973 isc_result_t
named_config_getdscp(const cfg_obj_t * config,isc_dscp_t * dscpp)974 named_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) {
975 	const cfg_obj_t *options = NULL;
976 	const cfg_obj_t *dscpobj = NULL;
977 	isc_result_t result;
978 
979 	(void)cfg_map_get(config, "options", &options);
980 	if (options == NULL) {
981 		return (ISC_R_SUCCESS);
982 	}
983 
984 	result = cfg_map_get(options, "dscp", &dscpobj);
985 	if (result != ISC_R_SUCCESS || dscpobj == NULL) {
986 		*dscpp = -1;
987 		return (ISC_R_SUCCESS);
988 	}
989 	if (cfg_obj_asuint32(dscpobj) >= 64) {
990 		cfg_obj_log(dscpobj, named_g_lctx, ISC_LOG_ERROR,
991 			    "dscp '%u' out of range",
992 			    cfg_obj_asuint32(dscpobj));
993 		return (ISC_R_RANGE);
994 	}
995 	*dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
996 	return (ISC_R_SUCCESS);
997 }
998 
999 struct keyalgorithms {
1000 	const char *str;
1001 	enum {
1002 		hmacnone,
1003 		hmacmd5,
1004 		hmacsha1,
1005 		hmacsha224,
1006 		hmacsha256,
1007 		hmacsha384,
1008 		hmacsha512
1009 	} hmac;
1010 	unsigned int type;
1011 	uint16_t size;
1012 } algorithms[] = { { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 },
1013 		   { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 },
1014 		   { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 },
1015 		   { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 },
1016 		   { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 },
1017 		   { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 },
1018 		   { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 },
1019 		   { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 },
1020 		   { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } };
1021 
1022 isc_result_t
named_config_getkeyalgorithm(const char * str,const dns_name_t ** name,uint16_t * digestbits)1023 named_config_getkeyalgorithm(const char *str, const dns_name_t **name,
1024 			     uint16_t *digestbits) {
1025 	return (named_config_getkeyalgorithm2(str, name, NULL, digestbits));
1026 }
1027 
1028 isc_result_t
named_config_getkeyalgorithm2(const char * str,const dns_name_t ** name,unsigned int * typep,uint16_t * digestbits)1029 named_config_getkeyalgorithm2(const char *str, const dns_name_t **name,
1030 			      unsigned int *typep, uint16_t *digestbits) {
1031 	int i;
1032 	size_t len = 0;
1033 	uint16_t bits;
1034 	isc_result_t result;
1035 
1036 	for (i = 0; algorithms[i].str != NULL; i++) {
1037 		len = strlen(algorithms[i].str);
1038 		if (strncasecmp(algorithms[i].str, str, len) == 0 &&
1039 		    (str[len] == '\0' ||
1040 		     (algorithms[i].size != 0 && str[len] == '-')))
1041 		{
1042 			break;
1043 		}
1044 	}
1045 	if (algorithms[i].str == NULL) {
1046 		return (ISC_R_NOTFOUND);
1047 	}
1048 	if (str[len] == '-') {
1049 		result = isc_parse_uint16(&bits, str + len + 1, 10);
1050 		if (result != ISC_R_SUCCESS) {
1051 			return (result);
1052 		}
1053 		if (bits > algorithms[i].size) {
1054 			return (ISC_R_RANGE);
1055 		}
1056 	} else if (algorithms[i].size == 0) {
1057 		bits = 128;
1058 	} else {
1059 		bits = algorithms[i].size;
1060 	}
1061 
1062 	if (name != NULL) {
1063 		switch (algorithms[i].hmac) {
1064 		case hmacmd5:
1065 			*name = dns_tsig_hmacmd5_name;
1066 			break;
1067 		case hmacsha1:
1068 			*name = dns_tsig_hmacsha1_name;
1069 			break;
1070 		case hmacsha224:
1071 			*name = dns_tsig_hmacsha224_name;
1072 			break;
1073 		case hmacsha256:
1074 			*name = dns_tsig_hmacsha256_name;
1075 			break;
1076 		case hmacsha384:
1077 			*name = dns_tsig_hmacsha384_name;
1078 			break;
1079 		case hmacsha512:
1080 			*name = dns_tsig_hmacsha512_name;
1081 			break;
1082 		default:
1083 			INSIST(0);
1084 			ISC_UNREACHABLE();
1085 		}
1086 	}
1087 	if (typep != NULL) {
1088 		*typep = algorithms[i].type;
1089 	}
1090 	if (digestbits != NULL) {
1091 		*digestbits = bits;
1092 	}
1093 	return (ISC_R_SUCCESS);
1094 }
1095