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