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