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