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