1/* $NetBSD: zoneconf.c,v 1.15 2024/02/21 22:51:05 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#include <inttypes.h> 17#include <stdbool.h> 18 19#include <isc/buffer.h> 20#include <isc/file.h> 21#include <isc/mem.h> 22#include <isc/print.h> 23#include <isc/result.h> 24#include <isc/stats.h> 25#include <isc/string.h> /* Required for HP/UX (and others?) */ 26#include <isc/util.h> 27 28#include <dns/acl.h> 29#include <dns/db.h> 30#include <dns/fixedname.h> 31#include <dns/ipkeylist.h> 32#include <dns/journal.h> 33#include <dns/kasp.h> 34#include <dns/log.h> 35#include <dns/masterdump.h> 36#include <dns/name.h> 37#include <dns/nsec3.h> 38#include <dns/rdata.h> 39#include <dns/rdatalist.h> 40#include <dns/rdataset.h> 41#include <dns/rdatatype.h> 42#include <dns/sdlz.h> 43#include <dns/ssu.h> 44#include <dns/stats.h> 45#include <dns/tsig.h> 46#include <dns/view.h> 47#include <dns/zone.h> 48 49#include <ns/client.h> 50 51#include <named/config.h> 52#include <named/globals.h> 53#include <named/log.h> 54#include <named/server.h> 55#include <named/zoneconf.h> 56 57/* ACLs associated with zone */ 58typedef enum { 59 allow_notify, 60 allow_query, 61 allow_query_on, 62 allow_transfer, 63 allow_update, 64 allow_update_forwarding 65} acl_type_t; 66 67#define RETERR(x) \ 68 do { \ 69 isc_result_t _r = (x); \ 70 if (_r != ISC_R_SUCCESS) \ 71 return ((_r)); \ 72 } while (0) 73 74#define CHECK(x) \ 75 do { \ 76 result = (x); \ 77 if (result != ISC_R_SUCCESS) \ 78 goto cleanup; \ 79 } while (0) 80 81/*% 82 * Convenience function for configuring a single zone ACL. 83 */ 84static isc_result_t 85configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, 86 const cfg_obj_t *config, acl_type_t acltype, 87 cfg_aclconfctx_t *actx, dns_zone_t *zone, 88 void (*setzacl)(dns_zone_t *, dns_acl_t *), 89 void (*clearzacl)(dns_zone_t *)) { 90 isc_result_t result; 91 const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL }; 92 const cfg_obj_t *aclobj = NULL; 93 int i = 0; 94 dns_acl_t **aclp = NULL, *acl = NULL; 95 const char *aclname; 96 dns_view_t *view; 97 98 view = dns_zone_getview(zone); 99 100 switch (acltype) { 101 case allow_notify: 102 if (view != NULL) { 103 aclp = &view->notifyacl; 104 } 105 aclname = "allow-notify"; 106 break; 107 case allow_query: 108 if (view != NULL) { 109 aclp = &view->queryacl; 110 } 111 aclname = "allow-query"; 112 break; 113 case allow_query_on: 114 if (view != NULL) { 115 aclp = &view->queryonacl; 116 } 117 aclname = "allow-query-on"; 118 break; 119 case allow_transfer: 120 if (view != NULL) { 121 aclp = &view->transferacl; 122 } 123 aclname = "allow-transfer"; 124 break; 125 case allow_update: 126 if (view != NULL) { 127 aclp = &view->updateacl; 128 } 129 aclname = "allow-update"; 130 break; 131 case allow_update_forwarding: 132 if (view != NULL) { 133 aclp = &view->upfwdacl; 134 } 135 aclname = "allow-update-forwarding"; 136 break; 137 default: 138 UNREACHABLE(); 139 } 140 141 /* First check to see if ACL is defined within the zone */ 142 if (zconfig != NULL) { 143 maps[0] = cfg_tuple_get(zconfig, "options"); 144 (void)named_config_get(maps, aclname, &aclobj); 145 if (aclobj != NULL) { 146 aclp = NULL; 147 goto parse_acl; 148 } 149 } 150 151 /* Failing that, see if there's a default ACL already in the view */ 152 if (aclp != NULL && *aclp != NULL) { 153 (*setzacl)(zone, *aclp); 154 return (ISC_R_SUCCESS); 155 } 156 157 /* Check for default ACLs that haven't been parsed yet */ 158 if (vconfig != NULL) { 159 const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); 160 if (options != NULL) { 161 maps[i++] = options; 162 } 163 } 164 if (config != NULL) { 165 const cfg_obj_t *options = NULL; 166 (void)cfg_map_get(config, "options", &options); 167 if (options != NULL) { 168 maps[i++] = options; 169 } 170 } 171 maps[i++] = named_g_defaults; 172 maps[i] = NULL; 173 174 (void)named_config_get(maps, aclname, &aclobj); 175 if (aclobj == NULL) { 176 (*clearzacl)(zone); 177 return (ISC_R_SUCCESS); 178 } 179 180parse_acl: 181 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, 182 named_g_mctx, 0, &acl); 183 if (result != ISC_R_SUCCESS) { 184 return (result); 185 } 186 (*setzacl)(zone, acl); 187 188 /* Set the view default now */ 189 if (aclp != NULL) { 190 dns_acl_attach(acl, aclp); 191 } 192 193 dns_acl_detach(&acl); 194 return (ISC_R_SUCCESS); 195} 196 197/*% 198 * Parse the zone update-policy statement. 199 */ 200static isc_result_t 201configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, 202 const char *zname) { 203 const cfg_obj_t *updatepolicy = NULL; 204 const cfg_listelt_t *element, *element2; 205 dns_ssutable_t *table = NULL; 206 isc_mem_t *mctx = dns_zone_getmctx(zone); 207 bool autoddns = false; 208 isc_result_t result = ISC_R_SUCCESS; 209 210 (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); 211 212 if (updatepolicy == NULL) { 213 dns_zone_setssutable(zone, NULL); 214 return (ISC_R_SUCCESS); 215 } 216 217 if (cfg_obj_isstring(updatepolicy) && 218 strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) 219 { 220 autoddns = true; 221 updatepolicy = NULL; 222 } 223 224 dns_ssutable_create(mctx, &table); 225 226 for (element = cfg_list_first(updatepolicy); element != NULL; 227 element = cfg_list_next(element)) 228 { 229 const cfg_obj_t *stmt = cfg_listelt_value(element); 230 const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); 231 const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); 232 const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); 233 const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); 234 const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); 235 const char *str; 236 bool grant = false; 237 bool usezone = false; 238 dns_ssumatchtype_t mtype = dns_ssumatchtype_name; 239 dns_fixedname_t fname, fident; 240 isc_buffer_t b; 241 dns_ssuruletype_t *types; 242 unsigned int i, n; 243 244 str = cfg_obj_asstring(mode); 245 if (strcasecmp(str, "grant") == 0) { 246 grant = true; 247 } else if (strcasecmp(str, "deny") == 0) { 248 grant = false; 249 } else { 250 UNREACHABLE(); 251 } 252 253 str = cfg_obj_asstring(matchtype); 254 CHECK(dns_ssu_mtypefromstring(str, &mtype)); 255 if (mtype == dns_ssumatchtype_subdomain && 256 strcasecmp(str, "zonesub") == 0) 257 { 258 usezone = true; 259 } 260 261 dns_fixedname_init(&fident); 262 str = cfg_obj_asstring(identity); 263 isc_buffer_constinit(&b, str, strlen(str)); 264 isc_buffer_add(&b, strlen(str)); 265 result = dns_name_fromtext(dns_fixedname_name(&fident), &b, 266 dns_rootname, 0, NULL); 267 if (result != ISC_R_SUCCESS) { 268 cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR, 269 "'%s' is not a valid name", str); 270 goto cleanup; 271 } 272 273 dns_fixedname_init(&fname); 274 if (usezone) { 275 dns_name_copy(dns_zone_getorigin(zone), 276 dns_fixedname_name(&fname)); 277 } else { 278 str = cfg_obj_asstring(dname); 279 isc_buffer_constinit(&b, str, strlen(str)); 280 isc_buffer_add(&b, strlen(str)); 281 result = dns_name_fromtext(dns_fixedname_name(&fname), 282 &b, dns_rootname, 0, NULL); 283 if (result != ISC_R_SUCCESS) { 284 cfg_obj_log(identity, named_g_lctx, 285 ISC_LOG_ERROR, 286 "'%s' is not a valid name", str); 287 goto cleanup; 288 } 289 } 290 291 n = named_config_listcount(typelist); 292 if (n == 0) { 293 types = NULL; 294 } else { 295 types = isc_mem_get(mctx, n * sizeof(*types)); 296 } 297 298 i = 0; 299 for (element2 = cfg_list_first(typelist); element2 != NULL; 300 element2 = cfg_list_next(element2)) 301 { 302 const cfg_obj_t *typeobj; 303 const char *bracket; 304 isc_textregion_t r; 305 unsigned long max = 0; 306 307 INSIST(i < n); 308 309 typeobj = cfg_listelt_value(element2); 310 str = cfg_obj_asstring(typeobj); 311 DE_CONST(str, r.base); 312 313 bracket = strchr(str, '(' /*)*/); 314 if (bracket != NULL) { 315 char *end = NULL; 316 r.length = bracket - str; 317 max = strtoul(bracket + 1, &end, 10); 318 if (max > 0xffff || end[0] != /*(*/ ')' || 319 end[1] != 0) 320 { 321 cfg_obj_log(identity, named_g_lctx, 322 ISC_LOG_ERROR, 323 "'%s' is not a valid count", 324 bracket); 325 isc_mem_put(mctx, types, 326 n * sizeof(*types)); 327 goto cleanup; 328 } 329 } else { 330 r.length = strlen(str); 331 } 332 types[i].max = max; 333 334 result = dns_rdatatype_fromtext(&types[i++].type, &r); 335 if (result != ISC_R_SUCCESS) { 336 cfg_obj_log(identity, named_g_lctx, 337 ISC_LOG_ERROR, 338 "'%.*s' is not a valid type", 339 (int)r.length, str); 340 isc_mem_put(mctx, types, n * sizeof(*types)); 341 goto cleanup; 342 } 343 } 344 INSIST(i == n); 345 346 dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident), 347 mtype, dns_fixedname_name(&fname), n, 348 types); 349 if (types != NULL) { 350 isc_mem_put(mctx, types, n * sizeof(*types)); 351 } 352 } 353 354 /* 355 * If "update-policy local;" and a session key exists, 356 * then use the default policy, which is equivalent to: 357 * update-policy { grant <session-keyname> zonesub any; }; 358 */ 359 if (autoddns) { 360 dns_ssuruletype_t any = { dns_rdatatype_any, 0 }; 361 362 if (named_g_server->session_keyname == NULL) { 363 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 364 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 365 "failed to enable auto DDNS policy " 366 "for zone %s: session key not found", 367 zname); 368 result = ISC_R_NOTFOUND; 369 goto cleanup; 370 } 371 372 dns_ssutable_addrule(table, true, 373 named_g_server->session_keyname, 374 dns_ssumatchtype_local, 375 dns_zone_getorigin(zone), 1, &any); 376 } 377 378 dns_zone_setssutable(zone, table); 379 380cleanup: 381 dns_ssutable_detach(&table); 382 return (result); 383} 384 385/* 386 * This is the TTL used for internally generated RRsets for static-stub zones. 387 * The value doesn't matter because the mapping is static, but needs to be 388 * defined for the sake of implementation. 389 */ 390#define STATICSTUB_SERVER_TTL 86400 391 392/*% 393 * Configure an apex NS with glues for a static-stub zone. 394 * For example, for the zone named "example.com", the following RRs will be 395 * added to the zone DB: 396 * example.com. NS example.com. 397 * example.com. A 192.0.2.1 398 * example.com. AAAA 2001:db8::1 399 */ 400static isc_result_t 401configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, 402 dns_rdatalist_t *rdatalist_ns, 403 dns_rdatalist_t *rdatalist_a, 404 dns_rdatalist_t *rdatalist_aaaa) { 405 const cfg_listelt_t *element; 406 isc_mem_t *mctx = dns_zone_getmctx(zone); 407 isc_region_t region, sregion; 408 dns_rdata_t *rdata; 409 isc_result_t result = ISC_R_SUCCESS; 410 411 for (element = cfg_list_first(zconfig); element != NULL; 412 element = cfg_list_next(element)) 413 { 414 const isc_sockaddr_t *sa; 415 isc_netaddr_t na; 416 const cfg_obj_t *address = cfg_listelt_value(element); 417 dns_rdatalist_t *rdatalist; 418 419 sa = cfg_obj_assockaddr(address); 420 if (isc_sockaddr_getport(sa) != 0) { 421 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 422 "port is not configurable for " 423 "static stub server-addresses"); 424 return (ISC_R_FAILURE); 425 } 426 isc_netaddr_fromsockaddr(&na, sa); 427 if (isc_netaddr_getzone(&na) != 0) { 428 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 429 "scoped address is not allowed " 430 "for static stub " 431 "server-addresses"); 432 return (ISC_R_FAILURE); 433 } 434 435 switch (na.family) { 436 case AF_INET: 437 region.length = sizeof(na.type.in); 438 rdatalist = rdatalist_a; 439 break; 440 default: 441 INSIST(na.family == AF_INET6); 442 region.length = sizeof(na.type.in6); 443 rdatalist = rdatalist_aaaa; 444 break; 445 } 446 447 rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); 448 region.base = (unsigned char *)(rdata + 1); 449 memmove(region.base, &na.type, region.length); 450 dns_rdata_init(rdata); 451 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), 452 rdatalist->type, ®ion); 453 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 454 } 455 456 /* 457 * If no address is specified (unlikely in this context, but possible), 458 * there's nothing to do anymore. 459 */ 460 if (ISC_LIST_EMPTY(rdatalist_a->rdata) && 461 ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) 462 { 463 return (ISC_R_SUCCESS); 464 } 465 466 /* Add to the list an apex NS with the ns name being the origin name */ 467 dns_name_toregion(dns_zone_getorigin(zone), &sregion); 468 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); 469 region.length = sregion.length; 470 region.base = (unsigned char *)(rdata + 1); 471 memmove(region.base, sregion.base, region.length); 472 dns_rdata_init(rdata); 473 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, 474 ®ion); 475 ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); 476 477 return (result); 478} 479 480/*% 481 * Configure an apex NS with an out-of-zone NS names for a static-stub zone. 482 * For example, for the zone named "example.com", something like the following 483 * RRs will be added to the zone DB: 484 * example.com. NS ns.example.net. 485 */ 486static isc_result_t 487configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, 488 dns_rdatalist_t *rdatalist, 489 const char *zname) { 490 const cfg_listelt_t *element; 491 isc_mem_t *mctx = dns_zone_getmctx(zone); 492 dns_rdata_t *rdata; 493 isc_region_t sregion, region; 494 isc_result_t result = ISC_R_SUCCESS; 495 496 for (element = cfg_list_first(zconfig); element != NULL; 497 element = cfg_list_next(element)) 498 { 499 const cfg_obj_t *obj; 500 const char *str; 501 dns_fixedname_t fixed_name; 502 dns_name_t *nsname; 503 isc_buffer_t b; 504 505 obj = cfg_listelt_value(element); 506 str = cfg_obj_asstring(obj); 507 508 nsname = dns_fixedname_initname(&fixed_name); 509 510 isc_buffer_constinit(&b, str, strlen(str)); 511 isc_buffer_add(&b, strlen(str)); 512 result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); 513 if (result != ISC_R_SUCCESS) { 514 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 515 "server-name '%s' is not a valid " 516 "name", 517 str); 518 return (result); 519 } 520 if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { 521 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 522 "server-name '%s' must not be a " 523 "subdomain of zone name '%s'", 524 str, zname); 525 return (ISC_R_FAILURE); 526 } 527 528 dns_name_toregion(nsname, &sregion); 529 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); 530 region.length = sregion.length; 531 region.base = (unsigned char *)(rdata + 1); 532 memmove(region.base, sregion.base, region.length); 533 dns_rdata_init(rdata); 534 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), 535 dns_rdatatype_ns, ®ion); 536 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 537 } 538 539 return (result); 540} 541 542/*% 543 * Configure static-stub zone. 544 */ 545static isc_result_t 546configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, 547 const char *zname, const char *dbtype) { 548 int i = 0; 549 const cfg_obj_t *obj; 550 isc_mem_t *mctx = dns_zone_getmctx(zone); 551 dns_db_t *db = NULL; 552 dns_dbversion_t *dbversion = NULL; 553 dns_dbnode_t *apexnode = NULL; 554 dns_name_t apexname; 555 isc_result_t result; 556 dns_rdataset_t rdataset; 557 dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; 558 dns_rdatalist_t *rdatalists[] = { &rdatalist_ns, &rdatalist_a, 559 &rdatalist_aaaa, NULL }; 560 dns_rdata_t *rdata; 561 isc_region_t region; 562 563 /* Create the DB beforehand */ 564 RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), 565 dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL, 566 &db)); 567 568 dns_rdataset_init(&rdataset); 569 570 dns_rdatalist_init(&rdatalist_ns); 571 rdatalist_ns.rdclass = dns_zone_getclass(zone); 572 rdatalist_ns.type = dns_rdatatype_ns; 573 rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; 574 575 dns_rdatalist_init(&rdatalist_a); 576 rdatalist_a.rdclass = dns_zone_getclass(zone); 577 rdatalist_a.type = dns_rdatatype_a; 578 rdatalist_a.ttl = STATICSTUB_SERVER_TTL; 579 580 dns_rdatalist_init(&rdatalist_aaaa); 581 rdatalist_aaaa.rdclass = dns_zone_getclass(zone); 582 rdatalist_aaaa.type = dns_rdatatype_aaaa; 583 rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; 584 585 /* Prepare zone RRs from the configuration */ 586 obj = NULL; 587 result = cfg_map_get(zconfig, "server-addresses", &obj); 588 if (result == ISC_R_SUCCESS) { 589 INSIST(obj != NULL); 590 CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns, 591 &rdatalist_a, 592 &rdatalist_aaaa)); 593 } 594 595 obj = NULL; 596 result = cfg_map_get(zconfig, "server-names", &obj); 597 if (result == ISC_R_SUCCESS) { 598 INSIST(obj != NULL); 599 CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns, 600 zname)); 601 } 602 603 /* 604 * Sanity check: there should be at least one NS RR at the zone apex 605 * to trigger delegation. 606 */ 607 if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { 608 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 609 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 610 "No NS record is configured for a " 611 "static-stub zone '%s'", 612 zname); 613 result = ISC_R_FAILURE; 614 goto cleanup; 615 } 616 617 /* 618 * Now add NS and glue A/AAAA RRsets to the zone DB. 619 * First open a new version for the add operation and get a pointer 620 * to the apex node (all RRs are of the apex name). 621 */ 622 CHECK(dns_db_newversion(db, &dbversion)); 623 624 dns_name_init(&apexname, NULL); 625 dns_name_clone(dns_zone_getorigin(zone), &apexname); 626 CHECK(dns_db_findnode(db, &apexname, false, &apexnode)); 627 628 /* Add NS RRset */ 629 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) == 630 ISC_R_SUCCESS); 631 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, 632 NULL)); 633 dns_rdataset_disassociate(&rdataset); 634 635 /* Add glue A RRset, if any */ 636 if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { 637 RUNTIME_CHECK( 638 dns_rdatalist_tordataset(&rdatalist_a, &rdataset) == 639 ISC_R_SUCCESS); 640 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 641 0, NULL)); 642 dns_rdataset_disassociate(&rdataset); 643 } 644 645 /* Add glue AAAA RRset, if any */ 646 if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { 647 RUNTIME_CHECK( 648 dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) == 649 ISC_R_SUCCESS); 650 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 651 0, NULL)); 652 dns_rdataset_disassociate(&rdataset); 653 } 654 655 dns_db_closeversion(db, &dbversion, true); 656 dns_zone_setdb(zone, db); 657 658 result = ISC_R_SUCCESS; 659 660cleanup: 661 if (dns_rdataset_isassociated(&rdataset)) { 662 dns_rdataset_disassociate(&rdataset); 663 } 664 if (apexnode != NULL) { 665 dns_db_detachnode(db, &apexnode); 666 } 667 if (dbversion != NULL) { 668 dns_db_closeversion(db, &dbversion, false); 669 } 670 if (db != NULL) { 671 dns_db_detach(&db); 672 } 673 for (i = 0; rdatalists[i] != NULL; i++) { 674 while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { 675 ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); 676 dns_rdata_toregion(rdata, ®ion); 677 isc_mem_put(mctx, rdata, 678 sizeof(*rdata) + region.length); 679 } 680 } 681 682 INSIST(dbversion == NULL); 683 684 return (result); 685} 686 687/*% 688 * Convert a config file zone type into a server zone type. 689 */ 690static dns_zonetype_t 691zonetype_fromconfig(const cfg_obj_t *map) { 692 const cfg_obj_t *obj = NULL; 693 isc_result_t result; 694 695 result = cfg_map_get(map, "type", &obj); 696 INSIST(result == ISC_R_SUCCESS && obj != NULL); 697 return (named_config_getzonetype(obj)); 698} 699 700/*% 701 * Helper function for strtoargv(). Pardon the gratuitous recursion. 702 */ 703static isc_result_t 704strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp, 705 unsigned int n) { 706 isc_result_t result; 707 708 /* Discard leading whitespace. */ 709 while (*s == ' ' || *s == '\t') { 710 s++; 711 } 712 713 if (*s == '\0') { 714 /* We have reached the end of the string. */ 715 *argcp = n; 716 *argvp = isc_mem_get(mctx, n * sizeof(char *)); 717 } else { 718 char *p = s; 719 while (*p != ' ' && *p != '\t' && *p != '\0') { 720 p++; 721 } 722 if (*p != '\0') { 723 *p++ = '\0'; 724 } 725 726 result = strtoargvsub(mctx, p, argcp, argvp, n + 1); 727 if (result != ISC_R_SUCCESS) { 728 return (result); 729 } 730 (*argvp)[n] = s; 731 } 732 return (ISC_R_SUCCESS); 733} 734 735/*% 736 * Tokenize the string "s" into whitespace-separated words, 737 * return the number of words in '*argcp' and an array 738 * of pointers to the words in '*argvp'. The caller 739 * must free the array using isc_mem_put(). The string 740 * is modified in-place. 741 */ 742static isc_result_t 743strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { 744 return (strtoargvsub(mctx, s, argcp, argvp, 0)); 745} 746 747static const char *const primary_synonyms[] = { "primary", "master", NULL }; 748 749static const char *const secondary_synonyms[] = { "secondary", "slave", NULL }; 750 751static void 752checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, 753 const cfg_obj_t **objp) { 754 isc_result_t result; 755 756 switch (ztype) { 757 case dns_zone_secondary: 758 case dns_zone_mirror: 759 result = named_checknames_get(maps, secondary_synonyms, objp); 760 break; 761 case dns_zone_primary: 762 result = named_checknames_get(maps, primary_synonyms, objp); 763 break; 764 default: 765 UNREACHABLE(); 766 } 767 768 INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL); 769} 770 771/* 772 * Callback to see if a non-recursive query coming from 'srcaddr' to 773 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be 774 * delivered to 'myview'. 775 * 776 * We run this unlocked as both the view list and the interface list 777 * are updated when the appropriate task has exclusivity. 778 */ 779static bool 780isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr, 781 const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) { 782 dns_aclenv_t *env = NULL; 783 dns_view_t *view = NULL; 784 dns_tsigkey_t *key = NULL; 785 isc_netaddr_t netsrc; 786 isc_netaddr_t netdst; 787 788 UNUSED(arg); 789 790 /* interfacemgr can be destroyed only in exclusive mode. */ 791 if (named_g_server->interfacemgr == NULL) { 792 return (true); 793 } 794 795 if (!ns_interfacemgr_listeningon(named_g_server->interfacemgr, dstaddr)) 796 { 797 return (false); 798 } 799 800 isc_netaddr_fromsockaddr(&netsrc, srcaddr); 801 isc_netaddr_fromsockaddr(&netdst, dstaddr); 802 env = ns_interfacemgr_getaclenv(named_g_server->interfacemgr); 803 804 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; 805 view = ISC_LIST_NEXT(view, link)) 806 { 807 const dns_name_t *tsig = NULL; 808 809 if (view->matchrecursiveonly) { 810 continue; 811 } 812 813 if (rdclass != view->rdclass) { 814 continue; 815 } 816 817 if (mykey != NULL) { 818 bool match; 819 isc_result_t result; 820 821 result = dns_view_gettsig(view, &mykey->name, &key); 822 if (result != ISC_R_SUCCESS) { 823 continue; 824 } 825 match = dst_key_compare(mykey->key, key->key); 826 dns_tsigkey_detach(&key); 827 if (!match) { 828 continue; 829 } 830 tsig = dns_tsigkey_identity(mykey); 831 } 832 833 if (dns_acl_allowed(&netsrc, tsig, view->matchclients, env) && 834 dns_acl_allowed(&netdst, tsig, view->matchdestinations, 835 env)) 836 { 837 break; 838 } 839 } 840 return (view == myview); 841} 842 843/*% 844 * For mirror zones, change "notify yes;" to "notify explicit;", informing the 845 * user only if "notify" was explicitly configured rather than inherited from 846 * default configuration. 847 */ 848static dns_notifytype_t 849process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype, 850 const char *zname, const cfg_obj_t **maps) { 851 const cfg_obj_t *obj = NULL; 852 853 /* 854 * Return the original setting if this is not a mirror zone or if the 855 * zone is configured with something else than "notify yes;". 856 */ 857 if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) { 858 return (ntype); 859 } 860 861 /* 862 * Only log a message if "notify" was set in the configuration 863 * hierarchy supplied in 'maps'. 864 */ 865 if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) { 866 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 867 "'notify explicit;' will be used for mirror zone " 868 "'%s'", 869 zname); 870 } 871 872 return (dns_notifytype_explicit); 873} 874 875isc_result_t 876named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, 877 const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, 878 dns_kasplist_t *kasplist, dns_zone_t *zone, 879 dns_zone_t *raw) { 880 isc_result_t result; 881 const char *zname; 882 dns_rdataclass_t zclass; 883 dns_rdataclass_t vclass; 884 const cfg_obj_t *maps[5]; 885 const cfg_obj_t *nodefault[4]; 886 const cfg_obj_t *zoptions = NULL; 887 const cfg_obj_t *options = NULL; 888 const cfg_obj_t *obj; 889 const char *filename = NULL; 890 const char *kaspname = NULL; 891 const char *dupcheck; 892 dns_notifytype_t notifytype = dns_notifytype_yes; 893 uint32_t count; 894 unsigned int dbargc; 895 char **dbargv; 896 static char default_dbtype[] = "rbt"; 897 static char dlz_dbtype[] = "dlz"; 898 char *cpval = default_dbtype; 899 isc_mem_t *mctx = dns_zone_getmctx(zone); 900 dns_dialuptype_t dialup = dns_dialuptype_no; 901 dns_zonetype_t ztype; 902 int i; 903 int32_t journal_size; 904 bool multi; 905 bool alt; 906 dns_view_t *view = NULL; 907 dns_kasp_t *kasp = NULL; 908 bool check = false, fail = false; 909 bool warn = false, ignore = false; 910 bool ixfrdiff; 911 bool use_kasp = false; 912 dns_masterformat_t masterformat; 913 const dns_master_style_t *masterstyle = &dns_master_style_default; 914 isc_stats_t *zoneqrystats; 915 dns_stats_t *rcvquerystats; 916 dns_stats_t *dnssecsignstats; 917 dns_zonestat_level_t statlevel = dns_zonestat_none; 918 int seconds; 919 dns_ttl_t maxttl = 0; /* unlimited */ 920 dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; 921 bool transferinsecs = ns_server_getoption(named_g_server->sctx, 922 NS_SERVER_TRANSFERINSECS); 923 924 i = 0; 925 if (zconfig != NULL) { 926 zoptions = cfg_tuple_get(zconfig, "options"); 927 nodefault[i] = maps[i] = zoptions; 928 i++; 929 } 930 if (vconfig != NULL) { 931 nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options"); 932 i++; 933 } 934 if (config != NULL) { 935 (void)cfg_map_get(config, "options", &options); 936 if (options != NULL) { 937 nodefault[i] = maps[i] = options; 938 i++; 939 } 940 } 941 nodefault[i] = NULL; 942 maps[i++] = named_g_defaults; 943 maps[i] = NULL; 944 945 if (vconfig != NULL) { 946 CHECK(named_config_getclass(cfg_tuple_get(vconfig, "class"), 947 dns_rdataclass_in, &vclass)); 948 } else { 949 vclass = dns_rdataclass_in; 950 } 951 952 /* 953 * Configure values common to all zone types. 954 */ 955 956 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 957 958 CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), vclass, 959 &zclass)); 960 dns_zone_setclass(zone, zclass); 961 if (raw != NULL) { 962 dns_zone_setclass(raw, zclass); 963 } 964 965 ztype = zonetype_fromconfig(zoptions); 966 if (raw != NULL) { 967 dns_zone_settype(raw, ztype); 968 dns_zone_settype(zone, dns_zone_primary); 969 } else { 970 dns_zone_settype(zone, ztype); 971 } 972 973 obj = NULL; 974 result = cfg_map_get(zoptions, "database", &obj); 975 if (result == ISC_R_SUCCESS) { 976 cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 977 } 978 if (cpval == NULL) { 979 CHECK(ISC_R_NOMEMORY); 980 } 981 982 obj = NULL; 983 result = cfg_map_get(zoptions, "dlz", &obj); 984 if (result == ISC_R_SUCCESS) { 985 const char *dlzname = cfg_obj_asstring(obj); 986 size_t len; 987 988 if (cpval != default_dbtype) { 989 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 990 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 991 "zone '%s': both 'database' and 'dlz' " 992 "specified", 993 zname); 994 CHECK(ISC_R_FAILURE); 995 } 996 997 len = strlen(dlzname) + 5; 998 cpval = isc_mem_allocate(mctx, len); 999 snprintf(cpval, len, "dlz %s", dlzname); 1000 } 1001 1002 result = strtoargv(mctx, cpval, &dbargc, &dbargv); 1003 if (result != ISC_R_SUCCESS && cpval != default_dbtype) { 1004 isc_mem_free(mctx, cpval); 1005 CHECK(result); 1006 } 1007 1008 /* 1009 * ANSI C is strange here. There is no logical reason why (char **) 1010 * cannot be promoted automatically to (const char * const *) by the 1011 * compiler w/o generating a warning. 1012 */ 1013 dns_zone_setdbtype(zone, dbargc, (const char *const *)dbargv); 1014 isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv)); 1015 if (cpval != default_dbtype && cpval != dlz_dbtype) { 1016 isc_mem_free(mctx, cpval); 1017 } 1018 1019 obj = NULL; 1020 result = cfg_map_get(zoptions, "file", &obj); 1021 if (result == ISC_R_SUCCESS) { 1022 filename = cfg_obj_asstring(obj); 1023 } 1024 1025 /* 1026 * Unless we're using some alternative database, a primary zone 1027 * will be needing a master file. 1028 */ 1029 if (ztype == dns_zone_primary && cpval == default_dbtype && 1030 filename == NULL) 1031 { 1032 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1033 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1034 "zone '%s': 'file' not specified", zname); 1035 CHECK(ISC_R_FAILURE); 1036 } 1037 1038 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { 1039 masterformat = dns_masterformat_raw; 1040 } else { 1041 masterformat = dns_masterformat_text; 1042 } 1043 obj = NULL; 1044 result = named_config_get(maps, "masterfile-format", &obj); 1045 if (result == ISC_R_SUCCESS) { 1046 const char *masterformatstr = cfg_obj_asstring(obj); 1047 1048 if (strcasecmp(masterformatstr, "text") == 0) { 1049 masterformat = dns_masterformat_text; 1050 } else if (strcasecmp(masterformatstr, "raw") == 0) { 1051 masterformat = dns_masterformat_raw; 1052 } else { 1053 UNREACHABLE(); 1054 } 1055 } 1056 1057 obj = NULL; 1058 result = named_config_get(maps, "masterfile-style", &obj); 1059 if (result == ISC_R_SUCCESS) { 1060 const char *masterstylestr = cfg_obj_asstring(obj); 1061 1062 if (masterformat != dns_masterformat_text) { 1063 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 1064 "zone '%s': 'masterfile-style' " 1065 "can only be used with " 1066 "'masterfile-format text'", 1067 zname); 1068 CHECK(ISC_R_FAILURE); 1069 } 1070 1071 if (strcasecmp(masterstylestr, "full") == 0) { 1072 masterstyle = &dns_master_style_full; 1073 } else if (strcasecmp(masterstylestr, "relative") == 0) { 1074 masterstyle = &dns_master_style_default; 1075 } else { 1076 UNREACHABLE(); 1077 } 1078 } 1079 1080 obj = NULL; 1081 result = named_config_get(maps, "max-records", &obj); 1082 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1083 dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj)); 1084 if (zone != mayberaw) { 1085 dns_zone_setmaxrecords(zone, 0); 1086 } 1087 1088 if (raw != NULL && filename != NULL) { 1089#define SIGNED ".signed" 1090 size_t signedlen = strlen(filename) + sizeof(SIGNED); 1091 char *signedname; 1092 1093 CHECK(dns_zone_setfile(raw, filename, masterformat, 1094 masterstyle)); 1095 signedname = isc_mem_get(mctx, signedlen); 1096 1097 (void)snprintf(signedname, signedlen, "%s" SIGNED, filename); 1098 result = dns_zone_setfile(zone, signedname, 1099 dns_masterformat_raw, NULL); 1100 isc_mem_put(mctx, signedname, signedlen); 1101 CHECK(result); 1102 } else { 1103 CHECK(dns_zone_setfile(zone, filename, masterformat, 1104 masterstyle)); 1105 } 1106 1107 obj = NULL; 1108 result = cfg_map_get(zoptions, "journal", &obj); 1109 if (result == ISC_R_SUCCESS) { 1110 CHECK(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); 1111 } 1112 1113 /* 1114 * Notify messages are processed by the raw zone if it exists. 1115 */ 1116 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { 1117 CHECK(configure_zone_acl(zconfig, vconfig, config, allow_notify, 1118 ac, mayberaw, dns_zone_setnotifyacl, 1119 dns_zone_clearnotifyacl)); 1120 } 1121 1122 /* 1123 * XXXAG This probably does not make sense for stubs. 1124 */ 1125 CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query, ac, 1126 zone, dns_zone_setqueryacl, 1127 dns_zone_clearqueryacl)); 1128 1129 CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac, 1130 zone, dns_zone_setqueryonacl, 1131 dns_zone_clearqueryonacl)); 1132 1133 obj = NULL; 1134 result = named_config_get(maps, "dialup", &obj); 1135 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1136 if (cfg_obj_isboolean(obj)) { 1137 if (cfg_obj_asboolean(obj)) { 1138 dialup = dns_dialuptype_yes; 1139 } else { 1140 dialup = dns_dialuptype_no; 1141 } 1142 } else { 1143 const char *dialupstr = cfg_obj_asstring(obj); 1144 if (strcasecmp(dialupstr, "notify") == 0) { 1145 dialup = dns_dialuptype_notify; 1146 } else if (strcasecmp(dialupstr, "notify-passive") == 0) { 1147 dialup = dns_dialuptype_notifypassive; 1148 } else if (strcasecmp(dialupstr, "refresh") == 0) { 1149 dialup = dns_dialuptype_refresh; 1150 } else if (strcasecmp(dialupstr, "passive") == 0) { 1151 dialup = dns_dialuptype_passive; 1152 } else { 1153 UNREACHABLE(); 1154 } 1155 } 1156 if (raw != NULL) { 1157 dns_zone_setdialup(raw, dialup); 1158 } 1159 dns_zone_setdialup(zone, dialup); 1160 1161 obj = NULL; 1162 result = named_config_get(maps, "zone-statistics", &obj); 1163 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1164 if (cfg_obj_isboolean(obj)) { 1165 if (cfg_obj_asboolean(obj)) { 1166 statlevel = dns_zonestat_full; 1167 } else { 1168 statlevel = dns_zonestat_none; 1169 } 1170 } else { 1171 const char *levelstr = cfg_obj_asstring(obj); 1172 if (strcasecmp(levelstr, "full") == 0) { 1173 statlevel = dns_zonestat_full; 1174 } else if (strcasecmp(levelstr, "terse") == 0) { 1175 statlevel = dns_zonestat_terse; 1176 } else if (strcasecmp(levelstr, "none") == 0) { 1177 statlevel = dns_zonestat_none; 1178 } else { 1179 UNREACHABLE(); 1180 } 1181 } 1182 dns_zone_setstatlevel(zone, statlevel); 1183 1184 zoneqrystats = NULL; 1185 rcvquerystats = NULL; 1186 dnssecsignstats = NULL; 1187 if (statlevel == dns_zonestat_full) { 1188 CHECK(isc_stats_create(mctx, &zoneqrystats, 1189 ns_statscounter_max)); 1190 CHECK(dns_rdatatypestats_create(mctx, &rcvquerystats)); 1191 CHECK(dns_dnssecsignstats_create(mctx, &dnssecsignstats)); 1192 } 1193 dns_zone_setrequeststats(zone, zoneqrystats); 1194 dns_zone_setrcvquerystats(zone, rcvquerystats); 1195 dns_zone_setdnssecsignstats(zone, dnssecsignstats); 1196 1197 if (zoneqrystats != NULL) { 1198 isc_stats_detach(&zoneqrystats); 1199 } 1200 1201 if (rcvquerystats != NULL) { 1202 dns_stats_detach(&rcvquerystats); 1203 } 1204 1205 if (dnssecsignstats != NULL) { 1206 dns_stats_detach(&dnssecsignstats); 1207 } 1208 1209 /* 1210 * Configure authoritative zone functionality. This applies 1211 * to primary servers (type "primary") and secondaries 1212 * acting as primaries (type "secondary"), but not to stubs. 1213 */ 1214 if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && 1215 ztype != dns_zone_redirect) 1216 { 1217 obj = NULL; 1218 result = named_config_get(maps, "dnssec-policy", &obj); 1219 if (result == ISC_R_SUCCESS) { 1220 kaspname = cfg_obj_asstring(obj); 1221 if (strcmp(kaspname, "none") != 0) { 1222 result = dns_kasplist_find(kasplist, kaspname, 1223 &kasp); 1224 if (result != ISC_R_SUCCESS) { 1225 cfg_obj_log( 1226 obj, named_g_lctx, 1227 ISC_LOG_ERROR, 1228 "dnssec-policy '%s' not found ", 1229 kaspname); 1230 CHECK(result); 1231 } 1232 dns_zone_setkasp(zone, kasp); 1233 use_kasp = true; 1234 } 1235 } 1236 if (!use_kasp) { 1237 dns_zone_setkasp(zone, NULL); 1238 } 1239 1240 obj = NULL; 1241 result = named_config_get(maps, "notify", &obj); 1242 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1243 if (cfg_obj_isboolean(obj)) { 1244 if (cfg_obj_asboolean(obj)) { 1245 notifytype = dns_notifytype_yes; 1246 } else { 1247 notifytype = dns_notifytype_no; 1248 } 1249 } else { 1250 const char *str = cfg_obj_asstring(obj); 1251 if (strcasecmp(str, "explicit") == 0) { 1252 notifytype = dns_notifytype_explicit; 1253 } else if (strcasecmp(str, "master-only") == 0 || 1254 strcasecmp(str, "primary-only") == 0) 1255 { 1256 notifytype = dns_notifytype_masteronly; 1257 } else { 1258 UNREACHABLE(); 1259 } 1260 } 1261 notifytype = process_notifytype(notifytype, ztype, zname, 1262 nodefault); 1263 if (raw != NULL) { 1264 dns_zone_setnotifytype(raw, dns_notifytype_no); 1265 } 1266 dns_zone_setnotifytype(zone, notifytype); 1267 1268 obj = NULL; 1269 result = named_config_get(maps, "also-notify", &obj); 1270 if (result == ISC_R_SUCCESS && 1271 (notifytype == dns_notifytype_yes || 1272 notifytype == dns_notifytype_explicit || 1273 (notifytype == dns_notifytype_masteronly && 1274 ztype == dns_zone_primary))) 1275 { 1276 dns_ipkeylist_t ipkl; 1277 dns_ipkeylist_init(&ipkl); 1278 1279 CHECK(named_config_getipandkeylist(config, "primaries", 1280 obj, mctx, &ipkl)); 1281 dns_zone_setalsonotify(zone, ipkl.addrs, ipkl.keys, 1282 ipkl.tlss, ipkl.count); 1283 dns_ipkeylist_clear(mctx, &ipkl); 1284 } else { 1285 dns_zone_setalsonotify(zone, NULL, NULL, NULL, 0); 1286 } 1287 1288 obj = NULL; 1289 result = named_config_get(maps, "parental-source", &obj); 1290 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1291 1292 CHECK(dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj))); 1293 named_add_reserved_dispatch(named_g_server, 1294 cfg_obj_assockaddr(obj)); 1295 1296 obj = NULL; 1297 result = named_config_get(maps, "parental-source-v6", &obj); 1298 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1299 1300 CHECK(dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj))); 1301 named_add_reserved_dispatch(named_g_server, 1302 cfg_obj_assockaddr(obj)); 1303 1304 obj = NULL; 1305 result = named_config_get(maps, "notify-source", &obj); 1306 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1307 CHECK(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj))); 1308 named_add_reserved_dispatch(named_g_server, 1309 cfg_obj_assockaddr(obj)); 1310 1311 obj = NULL; 1312 result = named_config_get(maps, "notify-source-v6", &obj); 1313 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1314 CHECK(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); 1315 named_add_reserved_dispatch(named_g_server, 1316 cfg_obj_assockaddr(obj)); 1317 1318 obj = NULL; 1319 result = named_config_get(maps, "notify-to-soa", &obj); 1320 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1321 dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, 1322 cfg_obj_asboolean(obj)); 1323 1324 dns_zone_setisself(zone, isself, NULL); 1325 1326 CHECK(configure_zone_acl( 1327 zconfig, vconfig, config, allow_transfer, ac, zone, 1328 dns_zone_setxfracl, dns_zone_clearxfracl)); 1329 1330 obj = NULL; 1331 result = named_config_get(maps, "max-transfer-time-out", &obj); 1332 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1333 dns_zone_setmaxxfrout( 1334 zone, transferinsecs ? cfg_obj_asuint32(obj) 1335 : cfg_obj_asuint32(obj) * 60); 1336 1337 obj = NULL; 1338 result = named_config_get(maps, "max-transfer-idle-out", &obj); 1339 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1340 dns_zone_setidleout(zone, transferinsecs 1341 ? cfg_obj_asuint32(obj) 1342 : cfg_obj_asuint32(obj) * 60); 1343 1344 obj = NULL; 1345 result = named_config_get(maps, "max-journal-size", &obj); 1346 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1347 if (raw != NULL) { 1348 dns_zone_setjournalsize(raw, -1); 1349 } 1350 dns_zone_setjournalsize(zone, -1); 1351 if (cfg_obj_isstring(obj)) { 1352 const char *str = cfg_obj_asstring(obj); 1353 if (strcasecmp(str, "unlimited") == 0) { 1354 journal_size = DNS_JOURNAL_SIZE_MAX; 1355 } else { 1356 INSIST(strcasecmp(str, "default") == 0); 1357 journal_size = -1; 1358 } 1359 } else { 1360 isc_resourcevalue_t value; 1361 value = cfg_obj_asuint64(obj); 1362 if (value > DNS_JOURNAL_SIZE_MAX) { 1363 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 1364 "'max-journal-size " 1365 "%" PRId64 "' " 1366 "is too large", 1367 value); 1368 CHECK(ISC_R_RANGE); 1369 } 1370 journal_size = (uint32_t)value; 1371 } 1372 if (raw != NULL) { 1373 dns_zone_setjournalsize(raw, journal_size); 1374 } 1375 dns_zone_setjournalsize(zone, journal_size); 1376 1377 obj = NULL; 1378 result = named_config_get(maps, "ixfr-from-differences", &obj); 1379 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1380 if (cfg_obj_isboolean(obj)) { 1381 ixfrdiff = cfg_obj_asboolean(obj); 1382 } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 || 1383 strcasecmp(cfg_obj_asstring(obj), "master") == 0) && 1384 ztype == dns_zone_primary) 1385 { 1386 ixfrdiff = true; 1387 } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") == 1388 0 || 1389 strcasecmp(cfg_obj_asstring(obj), "slave") == 0) && 1390 ztype == dns_zone_secondary) 1391 { 1392 ixfrdiff = true; 1393 } else { 1394 ixfrdiff = false; 1395 } 1396 if (raw != NULL) { 1397 dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, 1398 true); 1399 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1400 false); 1401 } else { 1402 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1403 ixfrdiff); 1404 } 1405 1406 obj = NULL; 1407 result = named_config_get(maps, "max-ixfr-ratio", &obj); 1408 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1409 if (cfg_obj_isstring(obj)) { 1410 dns_zone_setixfrratio(zone, 0); 1411 } else { 1412 dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj)); 1413 } 1414 1415 obj = NULL; 1416 result = named_config_get(maps, "request-expire", &obj); 1417 INSIST(result == ISC_R_SUCCESS); 1418 dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj)); 1419 1420 obj = NULL; 1421 result = named_config_get(maps, "request-ixfr", &obj); 1422 INSIST(result == ISC_R_SUCCESS); 1423 dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); 1424 1425 obj = NULL; 1426 checknames(ztype, maps, &obj); 1427 INSIST(obj != NULL); 1428 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1429 fail = false; 1430 check = true; 1431 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1432 fail = check = true; 1433 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1434 fail = check = false; 1435 } else { 1436 UNREACHABLE(); 1437 } 1438 if (raw != NULL) { 1439 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check); 1440 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, 1441 fail); 1442 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false); 1443 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1444 false); 1445 } else { 1446 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); 1447 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1448 fail); 1449 } 1450 1451 obj = NULL; 1452 result = named_config_get(maps, "notify-delay", &obj); 1453 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1454 dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); 1455 1456 obj = NULL; 1457 result = named_config_get(maps, "check-sibling", &obj); 1458 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1459 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, 1460 cfg_obj_asboolean(obj)); 1461 1462 obj = NULL; 1463 result = named_config_get(maps, "check-spf", &obj); 1464 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1465 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1466 check = true; 1467 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1468 check = false; 1469 } else { 1470 UNREACHABLE(); 1471 } 1472 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check); 1473 1474 obj = NULL; 1475 result = named_config_get(maps, "zero-no-soa-ttl", &obj); 1476 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1477 dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); 1478 1479 obj = NULL; 1480 result = named_config_get(maps, "nsec3-test-zone", &obj); 1481 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1482 dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, 1483 cfg_obj_asboolean(obj)); 1484 } else if (ztype == dns_zone_redirect) { 1485 dns_zone_setnotifytype(zone, dns_notifytype_no); 1486 1487 obj = NULL; 1488 result = named_config_get(maps, "max-journal-size", &obj); 1489 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1490 dns_zone_setjournalsize(zone, -1); 1491 if (cfg_obj_isstring(obj)) { 1492 const char *str = cfg_obj_asstring(obj); 1493 if (strcasecmp(str, "unlimited") == 0) { 1494 journal_size = DNS_JOURNAL_SIZE_MAX; 1495 } else { 1496 INSIST(strcasecmp(str, "default") == 0); 1497 journal_size = -1; 1498 } 1499 } else { 1500 isc_resourcevalue_t value; 1501 value = cfg_obj_asuint64(obj); 1502 if (value > DNS_JOURNAL_SIZE_MAX) { 1503 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 1504 "'max-journal-size " 1505 "%" PRId64 "' " 1506 "is too large", 1507 value); 1508 CHECK(ISC_R_RANGE); 1509 } 1510 journal_size = (uint32_t)value; 1511 } 1512 dns_zone_setjournalsize(zone, journal_size); 1513 } 1514 1515 if (use_kasp) { 1516 maxttl = dns_kasp_zonemaxttl(dns_zone_getkasp(zone), false); 1517 } else { 1518 obj = NULL; 1519 result = named_config_get(maps, "max-zone-ttl", &obj); 1520 if (result == ISC_R_SUCCESS) { 1521 if (cfg_obj_isduration(obj)) { 1522 maxttl = cfg_obj_asduration(obj); 1523 } 1524 } 1525 } 1526 dns_zone_setmaxttl(zone, maxttl); 1527 if (raw != NULL) { 1528 dns_zone_setmaxttl(raw, maxttl); 1529 } 1530 1531 /* 1532 * Configure update-related options. These apply to 1533 * primary servers only. 1534 */ 1535 if (ztype == dns_zone_primary) { 1536 dns_acl_t *updateacl; 1537 1538 CHECK(configure_zone_acl(zconfig, vconfig, config, allow_update, 1539 ac, mayberaw, dns_zone_setupdateacl, 1540 dns_zone_clearupdateacl)); 1541 1542 updateacl = dns_zone_getupdateacl(mayberaw); 1543 if (updateacl != NULL && dns_acl_isinsecure(updateacl)) { 1544 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1545 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 1546 "zone '%s' allows unsigned updates " 1547 "from remote hosts, which is insecure", 1548 zname); 1549 } 1550 1551 CHECK(configure_zone_ssutable(zoptions, mayberaw, zname)); 1552 } 1553 1554 /* 1555 * Configure DNSSEC signing. These apply to primary zones or zones that 1556 * use inline-signing (raw != NULL). 1557 */ 1558 if (ztype == dns_zone_primary || raw != NULL) { 1559 const cfg_obj_t *validity, *resign; 1560 bool allow = false, maint = false; 1561 bool sigvalinsecs; 1562 1563 if (use_kasp) { 1564 if (dns_kasp_nsec3(kasp)) { 1565 result = dns_zone_setnsec3param( 1566 zone, 1, dns_kasp_nsec3flags(kasp), 1567 dns_kasp_nsec3iter(kasp), 1568 dns_kasp_nsec3saltlen(kasp), NULL, true, 1569 false); 1570 } else { 1571 result = dns_zone_setnsec3param( 1572 zone, 0, 0, 0, 0, NULL, true, false); 1573 } 1574 INSIST(result == ISC_R_SUCCESS); 1575 } 1576 1577 if (use_kasp) { 1578 seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp); 1579 } else { 1580 obj = NULL; 1581 result = named_config_get(maps, "dnskey-sig-validity", 1582 &obj); 1583 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1584 seconds = cfg_obj_asuint32(obj) * 86400; 1585 } 1586 dns_zone_setkeyvalidityinterval(zone, seconds); 1587 1588 if (use_kasp) { 1589 seconds = (uint32_t)dns_kasp_sigvalidity(kasp); 1590 dns_zone_setsigvalidityinterval(zone, seconds); 1591 seconds = (uint32_t)dns_kasp_sigrefresh(kasp); 1592 dns_zone_setsigresigninginterval(zone, seconds); 1593 } else { 1594 obj = NULL; 1595 result = named_config_get(maps, "sig-validity-interval", 1596 &obj); 1597 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1598 1599 sigvalinsecs = ns_server_getoption( 1600 named_g_server->sctx, NS_SERVER_SIGVALINSECS); 1601 validity = cfg_tuple_get(obj, "validity"); 1602 seconds = cfg_obj_asuint32(validity); 1603 if (!sigvalinsecs) { 1604 seconds *= 86400; 1605 } 1606 dns_zone_setsigvalidityinterval(zone, seconds); 1607 1608 resign = cfg_tuple_get(obj, "re-sign"); 1609 if (cfg_obj_isvoid(resign)) { 1610 seconds /= 4; 1611 } else if (!sigvalinsecs) { 1612 uint32_t r = cfg_obj_asuint32(resign); 1613 if (seconds > 7 * 86400) { 1614 seconds = r * 86400; 1615 } else { 1616 seconds = r * 3600; 1617 } 1618 } else { 1619 seconds = cfg_obj_asuint32(resign); 1620 } 1621 dns_zone_setsigresigninginterval(zone, seconds); 1622 } 1623 1624 obj = NULL; 1625 result = named_config_get(maps, "key-directory", &obj); 1626 if (result == ISC_R_SUCCESS) { 1627 filename = cfg_obj_asstring(obj); 1628 CHECK(dns_zone_setkeydirectory(zone, filename)); 1629 } 1630 1631 obj = NULL; 1632 result = named_config_get(maps, "sig-signing-signatures", &obj); 1633 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1634 dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); 1635 1636 obj = NULL; 1637 result = named_config_get(maps, "sig-signing-nodes", &obj); 1638 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1639 dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); 1640 1641 obj = NULL; 1642 result = named_config_get(maps, "sig-signing-type", &obj); 1643 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1644 dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); 1645 1646 obj = NULL; 1647 result = named_config_get(maps, "update-check-ksk", &obj); 1648 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1649 dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, 1650 cfg_obj_asboolean(obj)); 1651 /* 1652 * This setting will be ignored if dnssec-policy is used. 1653 * named-checkconf will error if both are configured. 1654 */ 1655 1656 obj = NULL; 1657 result = named_config_get(maps, "dnssec-dnskey-kskonly", &obj); 1658 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1659 dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, 1660 cfg_obj_asboolean(obj)); 1661 /* 1662 * This setting will be ignored if dnssec-policy is used. 1663 * named-checkconf will error if both are configured. 1664 */ 1665 1666 obj = NULL; 1667 result = named_config_get(maps, "dnssec-loadkeys-interval", 1668 &obj); 1669 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1670 CHECK(dns_zone_setrefreshkeyinterval(zone, 1671 cfg_obj_asuint32(obj))); 1672 1673 obj = NULL; 1674 result = cfg_map_get(zoptions, "auto-dnssec", &obj); 1675 if (kasp != NULL) { 1676 bool s2i = (strcmp(dns_kasp_getname(kasp), 1677 "insecure") != 0); 1678 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true); 1679 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, !s2i); 1680 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true); 1681 } else if (result == ISC_R_SUCCESS) { 1682 const char *arg = cfg_obj_asstring(obj); 1683 if (strcasecmp(arg, "allow") == 0) { 1684 allow = true; 1685 } else if (strcasecmp(arg, "maintain") == 0) { 1686 allow = maint = true; 1687 } else if (strcasecmp(arg, "off") == 0) { 1688 /* Default */ 1689 } else { 1690 UNREACHABLE(); 1691 } 1692 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); 1693 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false); 1694 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); 1695 } 1696 } 1697 1698 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { 1699 CHECK(configure_zone_acl(zconfig, vconfig, config, 1700 allow_update_forwarding, ac, mayberaw, 1701 dns_zone_setforwardacl, 1702 dns_zone_clearforwardacl)); 1703 } 1704 1705 /*% 1706 * Configure parental agents, applies to primary and secondary zones. 1707 */ 1708 if (ztype == dns_zone_primary || ztype == dns_zone_secondary) { 1709 obj = NULL; 1710 (void)cfg_map_get(zoptions, "parental-agents", &obj); 1711 if (obj != NULL) { 1712 dns_ipkeylist_t ipkl; 1713 dns_ipkeylist_init(&ipkl); 1714 CHECK(named_config_getipandkeylist( 1715 config, "parental-agents", obj, mctx, &ipkl)); 1716 dns_zone_setparentals(zone, ipkl.addrs, ipkl.keys, 1717 ipkl.tlss, ipkl.count); 1718 dns_ipkeylist_clear(mctx, &ipkl); 1719 } else { 1720 dns_zone_setparentals(zone, NULL, NULL, NULL, 0); 1721 } 1722 } 1723 1724 /*% 1725 * Configure primary zone functionality. 1726 */ 1727 if (ztype == dns_zone_primary) { 1728 obj = NULL; 1729 result = named_config_get(maps, "check-wildcard", &obj); 1730 if (result == ISC_R_SUCCESS) { 1731 check = cfg_obj_asboolean(obj); 1732 } else { 1733 check = false; 1734 } 1735 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); 1736 1737 obj = NULL; 1738 result = named_config_get(maps, "check-dup-records", &obj); 1739 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1740 dupcheck = cfg_obj_asstring(obj); 1741 if (strcasecmp(dupcheck, "warn") == 0) { 1742 fail = false; 1743 check = true; 1744 } else if (strcasecmp(dupcheck, "fail") == 0) { 1745 fail = check = true; 1746 } else if (strcasecmp(dupcheck, "ignore") == 0) { 1747 fail = check = false; 1748 } else { 1749 UNREACHABLE(); 1750 } 1751 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); 1752 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); 1753 1754 obj = NULL; 1755 result = named_config_get(maps, "check-mx", &obj); 1756 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1757 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1758 fail = false; 1759 check = true; 1760 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1761 fail = check = true; 1762 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1763 fail = check = false; 1764 } else { 1765 UNREACHABLE(); 1766 } 1767 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); 1768 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); 1769 1770 obj = NULL; 1771 result = named_config_get(maps, "check-integrity", &obj); 1772 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1773 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, 1774 cfg_obj_asboolean(obj)); 1775 1776 obj = NULL; 1777 result = named_config_get(maps, "check-mx-cname", &obj); 1778 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1779 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1780 warn = true; 1781 ignore = false; 1782 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1783 warn = ignore = false; 1784 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1785 warn = ignore = true; 1786 } else { 1787 UNREACHABLE(); 1788 } 1789 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); 1790 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); 1791 1792 obj = NULL; 1793 result = named_config_get(maps, "check-srv-cname", &obj); 1794 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1795 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1796 warn = true; 1797 ignore = false; 1798 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1799 warn = ignore = false; 1800 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1801 warn = ignore = true; 1802 } else { 1803 UNREACHABLE(); 1804 } 1805 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); 1806 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, 1807 ignore); 1808 1809 obj = NULL; 1810 result = named_config_get(maps, "dnssec-secure-to-insecure", 1811 &obj); 1812 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1813 dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE, 1814 cfg_obj_asboolean(obj)); 1815 1816 obj = NULL; 1817 result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); 1818 if (result == ISC_R_SUCCESS) { 1819 const char *arg = cfg_obj_asstring(obj); 1820 if (strcasecmp(arg, "no-resign") == 0) { 1821 dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, 1822 true); 1823 } else if (strcasecmp(arg, "maintain") == 0) { 1824 /* Default */ 1825 } else { 1826 UNREACHABLE(); 1827 } 1828 } 1829 1830 obj = NULL; 1831 result = named_config_get(maps, "serial-update-method", &obj); 1832 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1833 if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) { 1834 dns_zone_setserialupdatemethod( 1835 zone, dns_updatemethod_unixtime); 1836 } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) { 1837 dns_zone_setserialupdatemethod(zone, 1838 dns_updatemethod_date); 1839 } else { 1840 dns_zone_setserialupdatemethod( 1841 zone, dns_updatemethod_increment); 1842 } 1843 } 1844 1845 /* 1846 * Configure secondary zone functionality. 1847 */ 1848 switch (ztype) { 1849 case dns_zone_mirror: 1850 /* 1851 * Disable outgoing zone transfers for mirror zones unless they 1852 * are explicitly enabled by zone configuration. 1853 */ 1854 obj = NULL; 1855 (void)cfg_map_get(zoptions, "allow-transfer", &obj); 1856 if (obj == NULL) { 1857 dns_acl_t *none; 1858 CHECK(dns_acl_none(mctx, &none)); 1859 dns_zone_setxfracl(zone, none); 1860 dns_acl_detach(&none); 1861 } 1862 FALLTHROUGH; 1863 case dns_zone_secondary: 1864 case dns_zone_stub: 1865 case dns_zone_redirect: 1866 count = 0; 1867 obj = NULL; 1868 (void)cfg_map_get(zoptions, "primaries", &obj); 1869 if (obj == NULL) { 1870 (void)cfg_map_get(zoptions, "masters", &obj); 1871 } 1872 1873 /* 1874 * Use the built-in primary server list if one was not 1875 * explicitly specified and this is a root zone mirror. 1876 */ 1877 if (obj == NULL && ztype == dns_zone_mirror && 1878 dns_name_equal(dns_zone_getorigin(zone), dns_rootname)) 1879 { 1880 result = named_config_getremotesdef( 1881 named_g_config, "primaries", 1882 DEFAULT_IANA_ROOT_ZONE_PRIMARIES, &obj); 1883 CHECK(result); 1884 } 1885 if (obj != NULL) { 1886 dns_ipkeylist_t ipkl; 1887 dns_ipkeylist_init(&ipkl); 1888 1889 CHECK(named_config_getipandkeylist(config, "primaries", 1890 obj, mctx, &ipkl)); 1891 dns_zone_setprimaries(mayberaw, ipkl.addrs, ipkl.keys, 1892 ipkl.tlss, ipkl.count); 1893 count = ipkl.count; 1894 dns_ipkeylist_clear(mctx, &ipkl); 1895 } else { 1896 dns_zone_setprimaries(mayberaw, NULL, NULL, NULL, 0); 1897 } 1898 1899 multi = false; 1900 if (count > 1) { 1901 obj = NULL; 1902 result = named_config_get(maps, "multi-master", &obj); 1903 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1904 multi = cfg_obj_asboolean(obj); 1905 } 1906 dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); 1907 1908 obj = NULL; 1909 result = named_config_get(maps, "max-transfer-time-in", &obj); 1910 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1911 dns_zone_setmaxxfrin( 1912 mayberaw, transferinsecs ? cfg_obj_asuint32(obj) 1913 : cfg_obj_asuint32(obj) * 60); 1914 1915 obj = NULL; 1916 result = named_config_get(maps, "max-transfer-idle-in", &obj); 1917 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1918 dns_zone_setidlein(mayberaw, 1919 transferinsecs ? cfg_obj_asuint32(obj) 1920 : cfg_obj_asuint32(obj) * 60); 1921 1922 obj = NULL; 1923 result = named_config_get(maps, "max-refresh-time", &obj); 1924 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1925 dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1926 1927 obj = NULL; 1928 result = named_config_get(maps, "min-refresh-time", &obj); 1929 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1930 dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1931 1932 obj = NULL; 1933 result = named_config_get(maps, "max-retry-time", &obj); 1934 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1935 dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); 1936 1937 obj = NULL; 1938 result = named_config_get(maps, "min-retry-time", &obj); 1939 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1940 dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); 1941 1942 obj = NULL; 1943 result = named_config_get(maps, "transfer-source", &obj); 1944 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1945 CHECK(dns_zone_setxfrsource4(mayberaw, 1946 cfg_obj_assockaddr(obj))); 1947 named_add_reserved_dispatch(named_g_server, 1948 cfg_obj_assockaddr(obj)); 1949 1950 obj = NULL; 1951 result = named_config_get(maps, "transfer-source-v6", &obj); 1952 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1953 CHECK(dns_zone_setxfrsource6(mayberaw, 1954 cfg_obj_assockaddr(obj))); 1955 named_add_reserved_dispatch(named_g_server, 1956 cfg_obj_assockaddr(obj)); 1957 1958 obj = NULL; 1959 result = named_config_get(maps, "alt-transfer-source", &obj); 1960 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1961 CHECK(dns_zone_setaltxfrsource4(mayberaw, 1962 cfg_obj_assockaddr(obj))); 1963 obj = NULL; 1964 result = named_config_get(maps, "alt-transfer-source-v6", &obj); 1965 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1966 CHECK(dns_zone_setaltxfrsource6(mayberaw, 1967 cfg_obj_assockaddr(obj))); 1968 obj = NULL; 1969 (void)named_config_get(maps, "use-alt-transfer-source", &obj); 1970 if (obj == NULL) { 1971 /* 1972 * Default off when views are in use otherwise 1973 * on for BIND 8 compatibility. 1974 */ 1975 view = dns_zone_getview(zone); 1976 if (view != NULL && strcmp(view->name, "_default") == 0) 1977 { 1978 alt = true; 1979 } else { 1980 alt = false; 1981 } 1982 } else { 1983 alt = cfg_obj_asboolean(obj); 1984 } 1985 dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt); 1986 1987 obj = NULL; 1988 (void)named_config_get(maps, "try-tcp-refresh", &obj); 1989 dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, 1990 cfg_obj_asboolean(obj)); 1991 break; 1992 1993 case dns_zone_staticstub: 1994 CHECK(configure_staticstub(zoptions, zone, zname, 1995 default_dbtype)); 1996 break; 1997 1998 default: 1999 break; 2000 } 2001 2002 result = ISC_R_SUCCESS; 2003 2004cleanup: 2005 if (kasp != NULL) { 2006 dns_kasp_detach(&kasp); 2007 } 2008 return (result); 2009} 2010 2011/* 2012 * Set up a DLZ zone as writeable 2013 */ 2014isc_result_t 2015named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, 2016 dns_rdataclass_t rdclass, dns_name_t *name) { 2017 dns_db_t *db = NULL; 2018 isc_time_t now; 2019 isc_result_t result; 2020 2021 TIME_NOW(&now); 2022 2023 dns_zone_settype(zone, dns_zone_dlz); 2024 result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); 2025 if (result != ISC_R_SUCCESS) { 2026 return (result); 2027 } 2028 result = dns_zone_dlzpostload(zone, db); 2029 dns_db_detach(&db); 2030 return (result); 2031} 2032 2033bool 2034named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { 2035 const cfg_obj_t *zoptions = NULL; 2036 const cfg_obj_t *obj = NULL; 2037 const char *cfilename; 2038 const char *zfilename; 2039 dns_zone_t *raw = NULL; 2040 bool has_raw, inline_signing; 2041 dns_zonetype_t ztype; 2042 2043 zoptions = cfg_tuple_get(zconfig, "options"); 2044 2045 /* 2046 * We always reconfigure a static-stub zone for simplicity, assuming 2047 * the amount of data to be loaded is small. 2048 */ 2049 if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) { 2050 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2051 "not reusable: staticstub"); 2052 return (false); 2053 } 2054 2055 /* If there's a raw zone, use that for filename and type comparison */ 2056 dns_zone_getraw(zone, &raw); 2057 if (raw != NULL) { 2058 zfilename = dns_zone_getfile(raw); 2059 ztype = dns_zone_gettype(raw); 2060 dns_zone_detach(&raw); 2061 has_raw = true; 2062 } else { 2063 zfilename = dns_zone_getfile(zone); 2064 ztype = dns_zone_gettype(zone); 2065 has_raw = false; 2066 } 2067 2068 inline_signing = named_zone_inlinesigning(zconfig); 2069 if (!inline_signing && has_raw) { 2070 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2071 "not reusable: old zone was inline-signing"); 2072 return (false); 2073 } else if (inline_signing && !has_raw) { 2074 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2075 "not reusable: old zone was not inline-signing"); 2076 return (false); 2077 } 2078 2079 if (zonetype_fromconfig(zoptions) != ztype) { 2080 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2081 "not reusable: type mismatch"); 2082 return (false); 2083 } 2084 2085 obj = NULL; 2086 (void)cfg_map_get(zoptions, "file", &obj); 2087 if (obj != NULL) { 2088 cfilename = cfg_obj_asstring(obj); 2089 } else { 2090 cfilename = NULL; 2091 } 2092 if (!((cfilename == NULL && zfilename == NULL) || 2093 (cfilename != NULL && zfilename != NULL && 2094 strcmp(cfilename, zfilename) == 0))) 2095 { 2096 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2097 "not reusable: filename mismatch"); 2098 return (false); 2099 } 2100 2101 return (true); 2102} 2103 2104bool 2105named_zone_inlinesigning(const cfg_obj_t *zconfig) { 2106 const cfg_obj_t *zoptions = NULL; 2107 const cfg_obj_t *signing = NULL; 2108 bool inline_signing = false; 2109 2110 zoptions = cfg_tuple_get(zconfig, "options"); 2111 inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) == 2112 ISC_R_SUCCESS && 2113 cfg_obj_asboolean(signing)); 2114 2115 return (inline_signing); 2116} 2117