1 /* $NetBSD: zoneconf.c,v 1.13 2023/01/25 21:43:23 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #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 RETERR(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 RETERR(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 return (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 return (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 return (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 return (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 return (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 RETERR(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 if (result != ISC_R_SUCCESS) { 1091 return (result); 1092 } 1093 } else { 1094 RETERR(dns_zone_setfile(zone, filename, masterformat, 1095 masterstyle)); 1096 } 1097 1098 obj = NULL; 1099 result = cfg_map_get(zoptions, "journal", &obj); 1100 if (result == ISC_R_SUCCESS) { 1101 RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); 1102 } 1103 1104 /* 1105 * Notify messages are processed by the raw zone if it exists. 1106 */ 1107 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { 1108 RETERR(configure_zone_acl( 1109 zconfig, vconfig, config, allow_notify, ac, mayberaw, 1110 dns_zone_setnotifyacl, dns_zone_clearnotifyacl)); 1111 } 1112 1113 /* 1114 * XXXAG This probably does not make sense for stubs. 1115 */ 1116 RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query, ac, 1117 zone, dns_zone_setqueryacl, 1118 dns_zone_clearqueryacl)); 1119 1120 RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac, 1121 zone, dns_zone_setqueryonacl, 1122 dns_zone_clearqueryonacl)); 1123 1124 obj = NULL; 1125 result = named_config_get(maps, "dialup", &obj); 1126 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1127 if (cfg_obj_isboolean(obj)) { 1128 if (cfg_obj_asboolean(obj)) { 1129 dialup = dns_dialuptype_yes; 1130 } else { 1131 dialup = dns_dialuptype_no; 1132 } 1133 } else { 1134 const char *dialupstr = cfg_obj_asstring(obj); 1135 if (strcasecmp(dialupstr, "notify") == 0) { 1136 dialup = dns_dialuptype_notify; 1137 } else if (strcasecmp(dialupstr, "notify-passive") == 0) { 1138 dialup = dns_dialuptype_notifypassive; 1139 } else if (strcasecmp(dialupstr, "refresh") == 0) { 1140 dialup = dns_dialuptype_refresh; 1141 } else if (strcasecmp(dialupstr, "passive") == 0) { 1142 dialup = dns_dialuptype_passive; 1143 } else { 1144 UNREACHABLE(); 1145 } 1146 } 1147 if (raw != NULL) { 1148 dns_zone_setdialup(raw, dialup); 1149 } 1150 dns_zone_setdialup(zone, dialup); 1151 1152 obj = NULL; 1153 result = named_config_get(maps, "zone-statistics", &obj); 1154 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1155 if (cfg_obj_isboolean(obj)) { 1156 if (cfg_obj_asboolean(obj)) { 1157 statlevel = dns_zonestat_full; 1158 } else { 1159 statlevel = dns_zonestat_none; 1160 } 1161 } else { 1162 const char *levelstr = cfg_obj_asstring(obj); 1163 if (strcasecmp(levelstr, "full") == 0) { 1164 statlevel = dns_zonestat_full; 1165 } else if (strcasecmp(levelstr, "terse") == 0) { 1166 statlevel = dns_zonestat_terse; 1167 } else if (strcasecmp(levelstr, "none") == 0) { 1168 statlevel = dns_zonestat_none; 1169 } else { 1170 UNREACHABLE(); 1171 } 1172 } 1173 dns_zone_setstatlevel(zone, statlevel); 1174 1175 zoneqrystats = NULL; 1176 rcvquerystats = NULL; 1177 dnssecsignstats = NULL; 1178 if (statlevel == dns_zonestat_full) { 1179 RETERR(isc_stats_create(mctx, &zoneqrystats, 1180 ns_statscounter_max)); 1181 RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats)); 1182 RETERR(dns_dnssecsignstats_create(mctx, &dnssecsignstats)); 1183 } 1184 dns_zone_setrequeststats(zone, zoneqrystats); 1185 dns_zone_setrcvquerystats(zone, rcvquerystats); 1186 dns_zone_setdnssecsignstats(zone, dnssecsignstats); 1187 1188 if (zoneqrystats != NULL) { 1189 isc_stats_detach(&zoneqrystats); 1190 } 1191 1192 if (rcvquerystats != NULL) { 1193 dns_stats_detach(&rcvquerystats); 1194 } 1195 1196 if (dnssecsignstats != NULL) { 1197 dns_stats_detach(&dnssecsignstats); 1198 } 1199 1200 /* 1201 * Configure master functionality. This applies 1202 * to primary servers (type "primary") and secondaries 1203 * acting as primaries (type "secondary"), but not to stubs. 1204 */ 1205 if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && 1206 ztype != dns_zone_redirect) 1207 { 1208 obj = NULL; 1209 result = named_config_get(maps, "dnssec-policy", &obj); 1210 if (result == ISC_R_SUCCESS) { 1211 kaspname = cfg_obj_asstring(obj); 1212 if (strcmp(kaspname, "none") != 0) { 1213 result = dns_kasplist_find(kasplist, kaspname, 1214 &kasp); 1215 if (result != ISC_R_SUCCESS) { 1216 cfg_obj_log( 1217 obj, named_g_lctx, 1218 ISC_LOG_ERROR, 1219 "dnssec-policy '%s' not found ", 1220 kaspname); 1221 RETERR(result); 1222 } 1223 dns_zone_setkasp(zone, kasp); 1224 use_kasp = true; 1225 } 1226 } 1227 if (!use_kasp) { 1228 dns_zone_setkasp(zone, NULL); 1229 } 1230 1231 obj = NULL; 1232 result = named_config_get(maps, "notify", &obj); 1233 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1234 if (cfg_obj_isboolean(obj)) { 1235 if (cfg_obj_asboolean(obj)) { 1236 notifytype = dns_notifytype_yes; 1237 } else { 1238 notifytype = dns_notifytype_no; 1239 } 1240 } else { 1241 const char *str = cfg_obj_asstring(obj); 1242 if (strcasecmp(str, "explicit") == 0) { 1243 notifytype = dns_notifytype_explicit; 1244 } else if (strcasecmp(str, "master-only") == 0 || 1245 strcasecmp(str, "primary-only") == 0) 1246 { 1247 notifytype = dns_notifytype_masteronly; 1248 } else { 1249 UNREACHABLE(); 1250 } 1251 } 1252 notifytype = process_notifytype(notifytype, ztype, zname, 1253 nodefault); 1254 if (raw != NULL) { 1255 dns_zone_setnotifytype(raw, dns_notifytype_no); 1256 } 1257 dns_zone_setnotifytype(zone, notifytype); 1258 1259 obj = NULL; 1260 result = named_config_get(maps, "also-notify", &obj); 1261 if (result == ISC_R_SUCCESS && 1262 (notifytype == dns_notifytype_yes || 1263 notifytype == dns_notifytype_explicit || 1264 (notifytype == dns_notifytype_masteronly && 1265 ztype == dns_zone_primary))) 1266 { 1267 dns_ipkeylist_t ipkl; 1268 dns_ipkeylist_init(&ipkl); 1269 1270 RETERR(named_config_getipandkeylist(config, "primaries", 1271 obj, mctx, &ipkl)); 1272 result = dns_zone_setalsonotifydscpkeys( 1273 zone, ipkl.addrs, ipkl.dscps, ipkl.keys, 1274 ipkl.count); 1275 dns_ipkeylist_clear(mctx, &ipkl); 1276 RETERR(result); 1277 } else { 1278 RETERR(dns_zone_setalsonotify(zone, NULL, 0)); 1279 } 1280 1281 obj = NULL; 1282 result = named_config_get(maps, "parental-source", &obj); 1283 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1284 RETERR(dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj))); 1285 dscp = cfg_obj_getdscp(obj); 1286 if (dscp == -1) { 1287 dscp = named_g_dscp; 1288 } 1289 RETERR(dns_zone_setparentalsrc4dscp(zone, dscp)); 1290 named_add_reserved_dispatch(named_g_server, 1291 cfg_obj_assockaddr(obj)); 1292 1293 obj = NULL; 1294 result = named_config_get(maps, "parental-source-v6", &obj); 1295 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1296 RETERR(dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj))); 1297 dscp = cfg_obj_getdscp(obj); 1298 if (dscp == -1) { 1299 dscp = named_g_dscp; 1300 } 1301 RETERR(dns_zone_setparentalsrc6dscp(zone, dscp)); 1302 named_add_reserved_dispatch(named_g_server, 1303 cfg_obj_assockaddr(obj)); 1304 1305 obj = NULL; 1306 result = named_config_get(maps, "notify-source", &obj); 1307 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1308 RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj))); 1309 dscp = cfg_obj_getdscp(obj); 1310 if (dscp == -1) { 1311 dscp = named_g_dscp; 1312 } 1313 RETERR(dns_zone_setnotifysrc4dscp(zone, dscp)); 1314 named_add_reserved_dispatch(named_g_server, 1315 cfg_obj_assockaddr(obj)); 1316 1317 obj = NULL; 1318 result = named_config_get(maps, "notify-source-v6", &obj); 1319 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1320 RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); 1321 dscp = cfg_obj_getdscp(obj); 1322 if (dscp == -1) { 1323 dscp = named_g_dscp; 1324 } 1325 RETERR(dns_zone_setnotifysrc6dscp(zone, dscp)); 1326 named_add_reserved_dispatch(named_g_server, 1327 cfg_obj_assockaddr(obj)); 1328 1329 obj = NULL; 1330 result = named_config_get(maps, "notify-to-soa", &obj); 1331 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1332 dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, 1333 cfg_obj_asboolean(obj)); 1334 1335 dns_zone_setisself(zone, isself, named_g_server->interfacemgr); 1336 1337 RETERR(configure_zone_acl( 1338 zconfig, vconfig, config, allow_transfer, ac, zone, 1339 dns_zone_setxfracl, dns_zone_clearxfracl)); 1340 1341 obj = NULL; 1342 result = named_config_get(maps, "max-transfer-time-out", &obj); 1343 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1344 dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60); 1345 1346 obj = NULL; 1347 result = named_config_get(maps, "max-transfer-idle-out", &obj); 1348 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1349 dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60); 1350 1351 obj = NULL; 1352 result = named_config_get(maps, "max-journal-size", &obj); 1353 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1354 if (raw != NULL) { 1355 dns_zone_setjournalsize(raw, -1); 1356 } 1357 dns_zone_setjournalsize(zone, -1); 1358 if (cfg_obj_isstring(obj)) { 1359 const char *str = cfg_obj_asstring(obj); 1360 if (strcasecmp(str, "unlimited") == 0) { 1361 journal_size = DNS_JOURNAL_SIZE_MAX; 1362 } else { 1363 INSIST(strcasecmp(str, "default") == 0); 1364 journal_size = -1; 1365 } 1366 } else { 1367 isc_resourcevalue_t value; 1368 value = cfg_obj_asuint64(obj); 1369 if (value > DNS_JOURNAL_SIZE_MAX) { 1370 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 1371 "'max-journal-size " 1372 "%" PRId64 "' " 1373 "is too large", 1374 value); 1375 RETERR(ISC_R_RANGE); 1376 } 1377 journal_size = (uint32_t)value; 1378 } 1379 if (raw != NULL) { 1380 dns_zone_setjournalsize(raw, journal_size); 1381 } 1382 dns_zone_setjournalsize(zone, journal_size); 1383 1384 obj = NULL; 1385 result = named_config_get(maps, "ixfr-from-differences", &obj); 1386 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1387 if (cfg_obj_isboolean(obj)) { 1388 ixfrdiff = cfg_obj_asboolean(obj); 1389 } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 || 1390 strcasecmp(cfg_obj_asstring(obj), "master") == 0) && 1391 ztype == dns_zone_primary) 1392 { 1393 ixfrdiff = true; 1394 } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") == 1395 0 || 1396 strcasecmp(cfg_obj_asstring(obj), "slave") == 0) && 1397 ztype == dns_zone_secondary) 1398 { 1399 ixfrdiff = true; 1400 } else { 1401 ixfrdiff = false; 1402 } 1403 if (raw != NULL) { 1404 dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, 1405 true); 1406 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1407 false); 1408 } else { 1409 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1410 ixfrdiff); 1411 } 1412 1413 obj = NULL; 1414 result = named_config_get(maps, "max-ixfr-ratio", &obj); 1415 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1416 if (cfg_obj_isstring(obj)) { 1417 dns_zone_setixfrratio(zone, 0); 1418 } else { 1419 dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj)); 1420 } 1421 1422 obj = NULL; 1423 result = named_config_get(maps, "request-expire", &obj); 1424 INSIST(result == ISC_R_SUCCESS); 1425 dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj)); 1426 1427 obj = NULL; 1428 result = named_config_get(maps, "request-ixfr", &obj); 1429 INSIST(result == ISC_R_SUCCESS); 1430 dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); 1431 1432 obj = NULL; 1433 checknames(ztype, maps, &obj); 1434 INSIST(obj != NULL); 1435 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1436 fail = false; 1437 check = true; 1438 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1439 fail = check = true; 1440 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1441 fail = check = false; 1442 } else { 1443 UNREACHABLE(); 1444 } 1445 if (raw != NULL) { 1446 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check); 1447 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, 1448 fail); 1449 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false); 1450 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1451 false); 1452 } else { 1453 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); 1454 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1455 fail); 1456 } 1457 1458 obj = NULL; 1459 result = named_config_get(maps, "notify-delay", &obj); 1460 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1461 dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); 1462 1463 obj = NULL; 1464 result = named_config_get(maps, "check-sibling", &obj); 1465 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1466 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, 1467 cfg_obj_asboolean(obj)); 1468 1469 obj = NULL; 1470 result = named_config_get(maps, "check-spf", &obj); 1471 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1472 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1473 check = true; 1474 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1475 check = false; 1476 } else { 1477 UNREACHABLE(); 1478 } 1479 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check); 1480 1481 obj = NULL; 1482 result = named_config_get(maps, "zero-no-soa-ttl", &obj); 1483 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1484 dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); 1485 1486 obj = NULL; 1487 result = named_config_get(maps, "nsec3-test-zone", &obj); 1488 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1489 dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, 1490 cfg_obj_asboolean(obj)); 1491 } else if (ztype == dns_zone_redirect) { 1492 dns_zone_setnotifytype(zone, dns_notifytype_no); 1493 1494 obj = NULL; 1495 result = named_config_get(maps, "max-journal-size", &obj); 1496 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1497 dns_zone_setjournalsize(zone, -1); 1498 if (cfg_obj_isstring(obj)) { 1499 const char *str = cfg_obj_asstring(obj); 1500 if (strcasecmp(str, "unlimited") == 0) { 1501 journal_size = DNS_JOURNAL_SIZE_MAX; 1502 } else { 1503 INSIST(strcasecmp(str, "default") == 0); 1504 journal_size = -1; 1505 } 1506 } else { 1507 isc_resourcevalue_t value; 1508 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 RETERR(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)); 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 RETERR(configure_zone_acl( 1546 zconfig, vconfig, config, allow_update, ac, mayberaw, 1547 dns_zone_setupdateacl, 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 RETERR(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 const cfg_obj_t *validity, *resign; 1567 bool allow = false, maint = false; 1568 bool sigvalinsecs; 1569 1570 if (use_kasp) { 1571 if (dns_kasp_nsec3(kasp)) { 1572 result = dns_zone_setnsec3param( 1573 zone, 1, dns_kasp_nsec3flags(kasp), 1574 dns_kasp_nsec3iter(kasp), 1575 dns_kasp_nsec3saltlen(kasp), NULL, true, 1576 false); 1577 } else { 1578 result = dns_zone_setnsec3param( 1579 zone, 0, 0, 0, 0, NULL, true, false); 1580 } 1581 INSIST(result == ISC_R_SUCCESS); 1582 } 1583 1584 if (use_kasp) { 1585 seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp); 1586 } else { 1587 obj = NULL; 1588 result = named_config_get(maps, "dnskey-sig-validity", 1589 &obj); 1590 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1591 seconds = cfg_obj_asuint32(obj) * 86400; 1592 } 1593 dns_zone_setkeyvalidityinterval(zone, seconds); 1594 1595 if (use_kasp) { 1596 seconds = (uint32_t)dns_kasp_sigvalidity(kasp); 1597 dns_zone_setsigvalidityinterval(zone, seconds); 1598 seconds = (uint32_t)dns_kasp_sigrefresh(kasp); 1599 dns_zone_setsigresigninginterval(zone, seconds); 1600 } else { 1601 obj = NULL; 1602 result = named_config_get(maps, "sig-validity-interval", 1603 &obj); 1604 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1605 1606 sigvalinsecs = ns_server_getoption( 1607 named_g_server->sctx, NS_SERVER_SIGVALINSECS); 1608 validity = cfg_tuple_get(obj, "validity"); 1609 seconds = cfg_obj_asuint32(validity); 1610 if (!sigvalinsecs) { 1611 seconds *= 86400; 1612 } 1613 dns_zone_setsigvalidityinterval(zone, seconds); 1614 1615 resign = cfg_tuple_get(obj, "re-sign"); 1616 if (cfg_obj_isvoid(resign)) { 1617 seconds /= 4; 1618 } else if (!sigvalinsecs) { 1619 uint32_t r = cfg_obj_asuint32(resign); 1620 if (seconds > 7 * 86400) { 1621 seconds = r * 86400; 1622 } else { 1623 seconds = r * 3600; 1624 } 1625 } else { 1626 seconds = cfg_obj_asuint32(resign); 1627 } 1628 dns_zone_setsigresigninginterval(zone, seconds); 1629 } 1630 1631 obj = NULL; 1632 result = named_config_get(maps, "key-directory", &obj); 1633 if (result == ISC_R_SUCCESS) { 1634 filename = cfg_obj_asstring(obj); 1635 RETERR(dns_zone_setkeydirectory(zone, filename)); 1636 } 1637 1638 obj = NULL; 1639 result = named_config_get(maps, "sig-signing-signatures", &obj); 1640 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1641 dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); 1642 1643 obj = NULL; 1644 result = named_config_get(maps, "sig-signing-nodes", &obj); 1645 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1646 dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); 1647 1648 obj = NULL; 1649 result = named_config_get(maps, "sig-signing-type", &obj); 1650 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1651 dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); 1652 1653 obj = NULL; 1654 result = named_config_get(maps, "update-check-ksk", &obj); 1655 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1656 dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, 1657 cfg_obj_asboolean(obj)); 1658 /* 1659 * This setting will be ignored if dnssec-policy is used. 1660 * named-checkconf will error if both are configured. 1661 */ 1662 1663 obj = NULL; 1664 result = named_config_get(maps, "dnssec-dnskey-kskonly", &obj); 1665 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1666 dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, 1667 cfg_obj_asboolean(obj)); 1668 /* 1669 * This setting will be ignored if dnssec-policy is used. 1670 * named-checkconf will error if both are configured. 1671 */ 1672 1673 obj = NULL; 1674 result = named_config_get(maps, "dnssec-loadkeys-interval", 1675 &obj); 1676 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1677 RETERR(dns_zone_setrefreshkeyinterval(zone, 1678 cfg_obj_asuint32(obj))); 1679 1680 obj = NULL; 1681 result = cfg_map_get(zoptions, "auto-dnssec", &obj); 1682 if (kasp != NULL) { 1683 bool s2i = (strcmp(dns_kasp_getname(kasp), 1684 "insecure") != 0); 1685 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true); 1686 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, !s2i); 1687 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true); 1688 } else if (result == ISC_R_SUCCESS) { 1689 const char *arg = cfg_obj_asstring(obj); 1690 if (strcasecmp(arg, "allow") == 0) { 1691 allow = true; 1692 } else if (strcasecmp(arg, "maintain") == 0) { 1693 allow = maint = true; 1694 } else if (strcasecmp(arg, "off") == 0) { 1695 /* Default */ 1696 } else { 1697 UNREACHABLE(); 1698 } 1699 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); 1700 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false); 1701 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); 1702 } 1703 } 1704 1705 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { 1706 RETERR(configure_zone_acl(zconfig, vconfig, config, 1707 allow_update_forwarding, ac, mayberaw, 1708 dns_zone_setforwardacl, 1709 dns_zone_clearforwardacl)); 1710 } 1711 1712 /*% 1713 * Configure parental agents, applies to primary and secondary zones. 1714 */ 1715 if (ztype == dns_zone_primary || ztype == dns_zone_secondary) { 1716 obj = NULL; 1717 (void)cfg_map_get(zoptions, "parental-agents", &obj); 1718 if (obj != NULL) { 1719 dns_ipkeylist_t ipkl; 1720 dns_ipkeylist_init(&ipkl); 1721 RETERR(named_config_getipandkeylist( 1722 config, "parental-agents", obj, mctx, &ipkl)); 1723 result = dns_zone_setparentals(zone, ipkl.addrs, 1724 ipkl.keys, ipkl.count); 1725 dns_ipkeylist_clear(mctx, &ipkl); 1726 RETERR(result); 1727 } else { 1728 RETERR(dns_zone_setparentals(zone, NULL, NULL, 0)); 1729 } 1730 } 1731 1732 /*% 1733 * Primary master functionality. 1734 */ 1735 if (ztype == dns_zone_primary) { 1736 obj = NULL; 1737 result = named_config_get(maps, "check-wildcard", &obj); 1738 if (result == ISC_R_SUCCESS) { 1739 check = cfg_obj_asboolean(obj); 1740 } else { 1741 check = false; 1742 } 1743 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); 1744 1745 /* 1746 * With map files, the default is ignore duplicate 1747 * records. With other master formats, the default is 1748 * taken from the global configuration. 1749 */ 1750 obj = NULL; 1751 if (masterformat != dns_masterformat_map) { 1752 result = named_config_get(maps, "check-dup-records", 1753 &obj); 1754 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1755 dupcheck = cfg_obj_asstring(obj); 1756 } else { 1757 result = named_config_get(nodefault, 1758 "check-dup-records", &obj); 1759 if (result == ISC_R_SUCCESS) { 1760 dupcheck = cfg_obj_asstring(obj); 1761 } else { 1762 dupcheck = "ignore"; 1763 } 1764 } 1765 if (strcasecmp(dupcheck, "warn") == 0) { 1766 fail = false; 1767 check = true; 1768 } else if (strcasecmp(dupcheck, "fail") == 0) { 1769 fail = check = true; 1770 } else if (strcasecmp(dupcheck, "ignore") == 0) { 1771 fail = check = false; 1772 } else { 1773 UNREACHABLE(); 1774 } 1775 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); 1776 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); 1777 1778 obj = NULL; 1779 result = named_config_get(maps, "check-mx", &obj); 1780 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1781 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1782 fail = false; 1783 check = true; 1784 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1785 fail = check = true; 1786 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1787 fail = check = false; 1788 } else { 1789 UNREACHABLE(); 1790 } 1791 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); 1792 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); 1793 1794 /* 1795 * With map files, the default is *not* to check 1796 * integrity. With other master formats, the default is 1797 * taken from the global configuration. 1798 */ 1799 obj = NULL; 1800 if (masterformat != dns_masterformat_map) { 1801 result = named_config_get(maps, "check-integrity", 1802 &obj); 1803 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1804 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, 1805 cfg_obj_asboolean(obj)); 1806 } else { 1807 check = false; 1808 result = named_config_get(nodefault, "check-integrity", 1809 &obj); 1810 if (result == ISC_R_SUCCESS) { 1811 check = cfg_obj_asboolean(obj); 1812 } 1813 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, 1814 check); 1815 } 1816 1817 obj = NULL; 1818 result = named_config_get(maps, "check-mx-cname", &obj); 1819 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1820 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1821 warn = true; 1822 ignore = false; 1823 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1824 warn = ignore = false; 1825 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1826 warn = ignore = true; 1827 } else { 1828 UNREACHABLE(); 1829 } 1830 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); 1831 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); 1832 1833 obj = NULL; 1834 result = named_config_get(maps, "check-srv-cname", &obj); 1835 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1836 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1837 warn = true; 1838 ignore = false; 1839 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1840 warn = ignore = false; 1841 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1842 warn = ignore = true; 1843 } else { 1844 UNREACHABLE(); 1845 } 1846 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); 1847 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, 1848 ignore); 1849 1850 obj = NULL; 1851 result = named_config_get(maps, "dnssec-secure-to-insecure", 1852 &obj); 1853 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1854 dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE, 1855 cfg_obj_asboolean(obj)); 1856 1857 obj = NULL; 1858 result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); 1859 if (result == ISC_R_SUCCESS) { 1860 const char *arg = cfg_obj_asstring(obj); 1861 if (strcasecmp(arg, "no-resign") == 0) { 1862 dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, 1863 true); 1864 } else if (strcasecmp(arg, "maintain") == 0) { 1865 /* Default */ 1866 } else { 1867 UNREACHABLE(); 1868 } 1869 } 1870 1871 obj = NULL; 1872 result = named_config_get(maps, "serial-update-method", &obj); 1873 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1874 if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) { 1875 dns_zone_setserialupdatemethod( 1876 zone, dns_updatemethod_unixtime); 1877 } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) { 1878 dns_zone_setserialupdatemethod(zone, 1879 dns_updatemethod_date); 1880 } else { 1881 dns_zone_setserialupdatemethod( 1882 zone, dns_updatemethod_increment); 1883 } 1884 } 1885 1886 /* 1887 * Configure slave functionality. 1888 */ 1889 switch (ztype) { 1890 case dns_zone_mirror: 1891 /* 1892 * Disable outgoing zone transfers for mirror zones unless they 1893 * are explicitly enabled by zone configuration. 1894 */ 1895 obj = NULL; 1896 (void)cfg_map_get(zoptions, "allow-transfer", &obj); 1897 if (obj == NULL) { 1898 dns_acl_t *none; 1899 RETERR(dns_acl_none(mctx, &none)); 1900 dns_zone_setxfracl(zone, none); 1901 dns_acl_detach(&none); 1902 } 1903 FALLTHROUGH; 1904 case dns_zone_secondary: 1905 case dns_zone_stub: 1906 case dns_zone_redirect: 1907 count = 0; 1908 obj = NULL; 1909 (void)cfg_map_get(zoptions, "primaries", &obj); 1910 if (obj == NULL) { 1911 (void)cfg_map_get(zoptions, "masters", &obj); 1912 } 1913 1914 /* 1915 * Use the built-in primary server list if one was not 1916 * explicitly specified and this is a root zone mirror. 1917 */ 1918 if (obj == NULL && ztype == dns_zone_mirror && 1919 dns_name_equal(dns_zone_getorigin(zone), dns_rootname)) 1920 { 1921 result = named_config_getremotesdef( 1922 named_g_config, "primaries", 1923 DEFAULT_IANA_ROOT_ZONE_PRIMARIES, &obj); 1924 RETERR(result); 1925 } 1926 if (obj != NULL) { 1927 dns_ipkeylist_t ipkl; 1928 dns_ipkeylist_init(&ipkl); 1929 1930 RETERR(named_config_getipandkeylist(config, "primaries", 1931 obj, mctx, &ipkl)); 1932 result = dns_zone_setprimarieswithkeys( 1933 mayberaw, ipkl.addrs, ipkl.keys, ipkl.count); 1934 count = ipkl.count; 1935 dns_ipkeylist_clear(mctx, &ipkl); 1936 RETERR(result); 1937 } else { 1938 result = dns_zone_setprimaries(mayberaw, NULL, 0); 1939 } 1940 RETERR(result); 1941 1942 multi = false; 1943 if (count > 1) { 1944 obj = NULL; 1945 result = named_config_get(maps, "multi-master", &obj); 1946 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1947 multi = cfg_obj_asboolean(obj); 1948 } 1949 dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); 1950 1951 obj = NULL; 1952 result = named_config_get(maps, "max-transfer-time-in", &obj); 1953 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1954 dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60); 1955 1956 obj = NULL; 1957 result = named_config_get(maps, "max-transfer-idle-in", &obj); 1958 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1959 dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60); 1960 1961 obj = NULL; 1962 result = named_config_get(maps, "max-refresh-time", &obj); 1963 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1964 dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1965 1966 obj = NULL; 1967 result = named_config_get(maps, "min-refresh-time", &obj); 1968 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1969 dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1970 1971 obj = NULL; 1972 result = named_config_get(maps, "max-retry-time", &obj); 1973 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1974 dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); 1975 1976 obj = NULL; 1977 result = named_config_get(maps, "min-retry-time", &obj); 1978 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1979 dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); 1980 1981 obj = NULL; 1982 result = named_config_get(maps, "transfer-source", &obj); 1983 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1984 RETERR(dns_zone_setxfrsource4(mayberaw, 1985 cfg_obj_assockaddr(obj))); 1986 dscp = cfg_obj_getdscp(obj); 1987 if (dscp == -1) { 1988 dscp = named_g_dscp; 1989 } 1990 RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp)); 1991 named_add_reserved_dispatch(named_g_server, 1992 cfg_obj_assockaddr(obj)); 1993 1994 obj = NULL; 1995 result = named_config_get(maps, "transfer-source-v6", &obj); 1996 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1997 RETERR(dns_zone_setxfrsource6(mayberaw, 1998 cfg_obj_assockaddr(obj))); 1999 dscp = cfg_obj_getdscp(obj); 2000 if (dscp == -1) { 2001 dscp = named_g_dscp; 2002 } 2003 RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp)); 2004 named_add_reserved_dispatch(named_g_server, 2005 cfg_obj_assockaddr(obj)); 2006 2007 obj = NULL; 2008 result = named_config_get(maps, "alt-transfer-source", &obj); 2009 INSIST(result == ISC_R_SUCCESS && obj != NULL); 2010 RETERR(dns_zone_setaltxfrsource4(mayberaw, 2011 cfg_obj_assockaddr(obj))); 2012 dscp = cfg_obj_getdscp(obj); 2013 if (dscp == -1) { 2014 dscp = named_g_dscp; 2015 } 2016 RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp)); 2017 2018 obj = NULL; 2019 result = named_config_get(maps, "alt-transfer-source-v6", &obj); 2020 INSIST(result == ISC_R_SUCCESS && obj != NULL); 2021 RETERR(dns_zone_setaltxfrsource6(mayberaw, 2022 cfg_obj_assockaddr(obj))); 2023 dscp = cfg_obj_getdscp(obj); 2024 if (dscp == -1) { 2025 dscp = named_g_dscp; 2026 } 2027 RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp)); 2028 2029 obj = NULL; 2030 (void)named_config_get(maps, "use-alt-transfer-source", &obj); 2031 if (obj == NULL) { 2032 /* 2033 * Default off when views are in use otherwise 2034 * on for BIND 8 compatibility. 2035 */ 2036 view = dns_zone_getview(zone); 2037 if (view != NULL && strcmp(view->name, "_default") == 0) 2038 { 2039 alt = true; 2040 } else { 2041 alt = false; 2042 } 2043 } else { 2044 alt = cfg_obj_asboolean(obj); 2045 } 2046 dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt); 2047 2048 obj = NULL; 2049 (void)named_config_get(maps, "try-tcp-refresh", &obj); 2050 dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, 2051 cfg_obj_asboolean(obj)); 2052 break; 2053 2054 case dns_zone_staticstub: 2055 RETERR(configure_staticstub(zoptions, zone, zname, 2056 default_dbtype)); 2057 break; 2058 2059 default: 2060 break; 2061 } 2062 2063 return (ISC_R_SUCCESS); 2064 } 2065 2066 /* 2067 * Set up a DLZ zone as writeable 2068 */ 2069 isc_result_t 2070 named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, 2071 dns_rdataclass_t rdclass, dns_name_t *name) { 2072 dns_db_t *db = NULL; 2073 isc_time_t now; 2074 isc_result_t result; 2075 2076 TIME_NOW(&now); 2077 2078 dns_zone_settype(zone, dns_zone_dlz); 2079 result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); 2080 if (result != ISC_R_SUCCESS) { 2081 return (result); 2082 } 2083 result = dns_zone_dlzpostload(zone, db); 2084 dns_db_detach(&db); 2085 return (result); 2086 } 2087 2088 bool 2089 named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { 2090 const cfg_obj_t *zoptions = NULL; 2091 const cfg_obj_t *obj = NULL; 2092 const char *cfilename; 2093 const char *zfilename; 2094 dns_zone_t *raw = NULL; 2095 bool has_raw, inline_signing; 2096 dns_zonetype_t ztype; 2097 2098 zoptions = cfg_tuple_get(zconfig, "options"); 2099 2100 /* 2101 * We always reconfigure a static-stub zone for simplicity, assuming 2102 * the amount of data to be loaded is small. 2103 */ 2104 if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) { 2105 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2106 "not reusable: staticstub"); 2107 return (false); 2108 } 2109 2110 /* If there's a raw zone, use that for filename and type comparison */ 2111 dns_zone_getraw(zone, &raw); 2112 if (raw != NULL) { 2113 zfilename = dns_zone_getfile(raw); 2114 ztype = dns_zone_gettype(raw); 2115 dns_zone_detach(&raw); 2116 has_raw = true; 2117 } else { 2118 zfilename = dns_zone_getfile(zone); 2119 ztype = dns_zone_gettype(zone); 2120 has_raw = false; 2121 } 2122 2123 inline_signing = named_zone_inlinesigning(zconfig); 2124 if (!inline_signing && has_raw) { 2125 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2126 "not reusable: old zone was inline-signing"); 2127 return (false); 2128 } else if (inline_signing && !has_raw) { 2129 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2130 "not reusable: old zone was not inline-signing"); 2131 return (false); 2132 } 2133 2134 if (zonetype_fromconfig(zoptions) != ztype) { 2135 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2136 "not reusable: type mismatch"); 2137 return (false); 2138 } 2139 2140 obj = NULL; 2141 (void)cfg_map_get(zoptions, "file", &obj); 2142 if (obj != NULL) { 2143 cfilename = cfg_obj_asstring(obj); 2144 } else { 2145 cfilename = NULL; 2146 } 2147 if (!((cfilename == NULL && zfilename == NULL) || 2148 (cfilename != NULL && zfilename != NULL && 2149 strcmp(cfilename, zfilename) == 0))) 2150 { 2151 dns_zone_log(zone, ISC_LOG_DEBUG(1), 2152 "not reusable: filename mismatch"); 2153 return (false); 2154 } 2155 2156 return (true); 2157 } 2158 2159 bool 2160 named_zone_inlinesigning(const cfg_obj_t *zconfig) { 2161 const cfg_obj_t *zoptions = NULL; 2162 const cfg_obj_t *signing = NULL; 2163 bool inline_signing = false; 2164 2165 zoptions = cfg_tuple_get(zconfig, "options"); 2166 inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) == 2167 ISC_R_SUCCESS && 2168 cfg_obj_asboolean(signing)); 2169 2170 return (inline_signing); 2171 } 2172