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