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