1/* $NetBSD$ */ 2 3/* 4 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id */ 21 22/*% */ 23 24#include <config.h> 25 26#include <isc/buffer.h> 27#include <isc/file.h> 28#include <isc/mem.h> 29#include <isc/print.h> 30#include <isc/stats.h> 31#include <isc/string.h> /* Required for HP/UX (and others?) */ 32#include <isc/util.h> 33 34#include <dns/acl.h> 35#include <dns/db.h> 36#include <dns/fixedname.h> 37#include <dns/log.h> 38#include <dns/name.h> 39#include <dns/rdata.h> 40#include <dns/rdatatype.h> 41#include <dns/rdataset.h> 42#include <dns/rdatalist.h> 43#include <dns/result.h> 44#include <dns/sdlz.h> 45#include <dns/ssu.h> 46#include <dns/stats.h> 47#include <dns/view.h> 48#include <dns/zone.h> 49 50#include <named/client.h> 51#include <named/config.h> 52#include <named/globals.h> 53#include <named/log.h> 54#include <named/server.h> 55#include <named/zoneconf.h> 56 57/* ACLs associated with zone */ 58typedef enum { 59 allow_notify, 60 allow_query, 61 allow_transfer, 62 allow_update, 63 allow_update_forwarding 64} acl_type_t; 65 66#define RETERR(x) do { \ 67 isc_result_t _r = (x); \ 68 if (_r != ISC_R_SUCCESS) \ 69 return (_r); \ 70 } while (/*CONSTCOND*/0) 71 72#define CHECK(x) do { \ 73 result = (x); \ 74 if (result != ISC_R_SUCCESS) \ 75 goto cleanup; \ 76 } while (/*CONSTCOND*/0) 77 78/*% 79 * Convenience function for configuring a single zone ACL. 80 */ 81static isc_result_t 82configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, 83 const cfg_obj_t *config, acl_type_t acltype, 84 cfg_aclconfctx_t *actx, dns_zone_t *zone, 85 void (*setzacl)(dns_zone_t *, dns_acl_t *), 86 void (*clearzacl)(dns_zone_t *)) 87{ 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 aclname = "allow-notify"; 103 break; 104 case allow_query: 105 if (view != NULL) 106 aclp = &view->queryacl; 107 aclname = "allow-query"; 108 break; 109 case allow_transfer: 110 if (view != NULL) 111 aclp = &view->transferacl; 112 aclname = "allow-transfer"; 113 break; 114 case allow_update: 115 if (view != NULL) 116 aclp = &view->updateacl; 117 aclname = "allow-update"; 118 break; 119 case allow_update_forwarding: 120 if (view != NULL) 121 aclp = &view->upfwdacl; 122 aclname = "allow-update-forwarding"; 123 break; 124 default: 125 INSIST(0); 126 return (ISC_R_FAILURE); 127 } 128 129 /* First check to see if ACL is defined within the zone */ 130 if (zconfig != NULL) { 131 maps[0] = cfg_tuple_get(zconfig, "options"); 132 (void)ns_config_get(maps, aclname, &aclobj); 133 if (aclobj != NULL) { 134 aclp = NULL; 135 goto parse_acl; 136 } 137 } 138 139 /* Failing that, see if there's a default ACL already in the view */ 140 if (aclp != NULL && *aclp != NULL) { 141 (*setzacl)(zone, *aclp); 142 return (ISC_R_SUCCESS); 143 } 144 145 /* Check for default ACLs that haven't been parsed yet */ 146 if (vconfig != NULL) { 147 const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); 148 if (options != NULL) 149 maps[i++] = options; 150 } 151 if (config != NULL) { 152 const cfg_obj_t *options = NULL; 153 (void)cfg_map_get(config, "options", &options); 154 if (options != NULL) 155 maps[i++] = options; 156 } 157 maps[i++] = ns_g_defaults; 158 maps[i] = NULL; 159 160 (void)ns_config_get(maps, aclname, &aclobj); 161 if (aclobj == NULL) { 162 (*clearzacl)(zone); 163 return (ISC_R_SUCCESS); 164 } 165 166parse_acl: 167 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, 168 dns_zone_getmctx(zone), 0, &acl); 169 if (result != ISC_R_SUCCESS) 170 return (result); 171 (*setzacl)(zone, acl); 172 173 /* Set the view default now */ 174 if (aclp != NULL) 175 dns_acl_attach(acl, aclp); 176 177 dns_acl_detach(&acl); 178 return (ISC_R_SUCCESS); 179} 180 181/*% 182 * Parse the zone update-policy statement. 183 */ 184static isc_result_t 185configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, 186 const char *zname) 187{ 188 const cfg_obj_t *updatepolicy = NULL; 189 const cfg_listelt_t *element, *element2; 190 dns_ssutable_t *table = NULL; 191 isc_mem_t *mctx = dns_zone_getmctx(zone); 192 isc_boolean_t autoddns = ISC_FALSE; 193 isc_result_t result; 194 195 (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); 196 197 if (updatepolicy == NULL) { 198 dns_zone_setssutable(zone, NULL); 199 return (ISC_R_SUCCESS); 200 } 201 202 if (cfg_obj_isstring(updatepolicy) && 203 strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { 204 autoddns = ISC_TRUE; 205 updatepolicy = NULL; 206 } 207 208 result = dns_ssutable_create(mctx, &table); 209 if (result != ISC_R_SUCCESS) 210 return (result); 211 212 for (element = cfg_list_first(updatepolicy); 213 element != NULL; 214 element = cfg_list_next(element)) 215 { 216 const cfg_obj_t *stmt = cfg_listelt_value(element); 217 const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); 218 const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); 219 const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); 220 const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); 221 const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); 222 const char *str; 223 isc_boolean_t grant = ISC_FALSE; 224 isc_boolean_t usezone = ISC_FALSE; 225 unsigned int mtype = DNS_SSUMATCHTYPE_NAME; 226 dns_fixedname_t fname, fident; 227 isc_buffer_t b; 228 dns_rdatatype_t *types; 229 unsigned int i, n; 230 231 str = cfg_obj_asstring(mode); 232 if (strcasecmp(str, "grant") == 0) 233 grant = ISC_TRUE; 234 else if (strcasecmp(str, "deny") == 0) 235 grant = ISC_FALSE; 236 else 237 INSIST(0); 238 239 str = cfg_obj_asstring(matchtype); 240 if (strcasecmp(str, "name") == 0) 241 mtype = DNS_SSUMATCHTYPE_NAME; 242 else if (strcasecmp(str, "subdomain") == 0) 243 mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; 244 else if (strcasecmp(str, "wildcard") == 0) 245 mtype = DNS_SSUMATCHTYPE_WILDCARD; 246 else if (strcasecmp(str, "self") == 0) 247 mtype = DNS_SSUMATCHTYPE_SELF; 248 else if (strcasecmp(str, "selfsub") == 0) 249 mtype = DNS_SSUMATCHTYPE_SELFSUB; 250 else if (strcasecmp(str, "selfwild") == 0) 251 mtype = DNS_SSUMATCHTYPE_SELFWILD; 252 else if (strcasecmp(str, "ms-self") == 0) 253 mtype = DNS_SSUMATCHTYPE_SELFMS; 254 else if (strcasecmp(str, "krb5-self") == 0) 255 mtype = DNS_SSUMATCHTYPE_SELFKRB5; 256 else if (strcasecmp(str, "ms-subdomain") == 0) 257 mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS; 258 else if (strcasecmp(str, "krb5-subdomain") == 0) 259 mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5; 260 else if (strcasecmp(str, "tcp-self") == 0) 261 mtype = DNS_SSUMATCHTYPE_TCPSELF; 262 else if (strcasecmp(str, "6to4-self") == 0) 263 mtype = DNS_SSUMATCHTYPE_6TO4SELF; 264 else if (strcasecmp(str, "zonesub") == 0) { 265 mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; 266 usezone = ISC_TRUE; 267 } else if (strcasecmp(str, "external") == 0) 268 mtype = DNS_SSUMATCHTYPE_EXTERNAL; 269 else 270 INSIST(0); 271 272 dns_fixedname_init(&fident); 273 str = cfg_obj_asstring(identity); 274 isc_buffer_init(&b, str, strlen(str)); 275 isc_buffer_add(&b, strlen(str)); 276 result = dns_name_fromtext(dns_fixedname_name(&fident), &b, 277 dns_rootname, 0, NULL); 278 if (result != ISC_R_SUCCESS) { 279 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, 280 "'%s' is not a valid name", str); 281 goto cleanup; 282 } 283 284 dns_fixedname_init(&fname); 285 if (usezone) { 286 result = dns_name_copy(dns_zone_getorigin(zone), 287 dns_fixedname_name(&fname), 288 NULL); 289 if (result != ISC_R_SUCCESS) { 290 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, 291 "error copying origin: %s", 292 isc_result_totext(result)); 293 goto cleanup; 294 } 295 } else { 296 str = cfg_obj_asstring(dname); 297 isc_buffer_init(&b, str, strlen(str)); 298 isc_buffer_add(&b, strlen(str)); 299 result = dns_name_fromtext(dns_fixedname_name(&fname), 300 &b, dns_rootname, 0, NULL); 301 if (result != ISC_R_SUCCESS) { 302 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, 303 "'%s' is not a valid name", str); 304 goto cleanup; 305 } 306 } 307 308 n = ns_config_listcount(typelist); 309 if (n == 0) 310 types = NULL; 311 else { 312 types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); 313 if (types == NULL) { 314 result = ISC_R_NOMEMORY; 315 goto cleanup; 316 } 317 } 318 319 i = 0; 320 for (element2 = cfg_list_first(typelist); 321 element2 != NULL; 322 element2 = cfg_list_next(element2)) 323 { 324 const cfg_obj_t *typeobj; 325 isc_textregion_t r; 326 327 INSIST(i < n); 328 329 typeobj = cfg_listelt_value(element2); 330 str = cfg_obj_asstring(typeobj); 331 DE_CONST(str, r.base); 332 r.length = strlen(str); 333 334 result = dns_rdatatype_fromtext(&types[i++], &r); 335 if (result != ISC_R_SUCCESS) { 336 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, 337 "'%s' is not a valid type", str); 338 isc_mem_put(mctx, types, 339 n * sizeof(dns_rdatatype_t)); 340 goto cleanup; 341 } 342 } 343 INSIST(i == n); 344 345 result = dns_ssutable_addrule(table, grant, 346 dns_fixedname_name(&fident), 347 mtype, 348 dns_fixedname_name(&fname), 349 n, types); 350 if (types != NULL) 351 isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); 352 if (result != ISC_R_SUCCESS) { 353 goto cleanup; 354 } 355 } 356 357 /* 358 * If "update-policy local;" and a session key exists, 359 * then use the default policy, which is equivalent to: 360 * update-policy { grant <session-keyname> zonesub any; }; 361 */ 362 if (autoddns) { 363 dns_rdatatype_t any = dns_rdatatype_any; 364 365 if (ns_g_server->session_keyname == NULL) { 366 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 367 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 368 "failed to enable auto DDNS policy " 369 "for zone %s: session key not found", 370 zname); 371 result = ISC_R_NOTFOUND; 372 goto cleanup; 373 } 374 375 result = dns_ssutable_addrule(table, ISC_TRUE, 376 ns_g_server->session_keyname, 377 DNS_SSUMATCHTYPE_SUBDOMAIN, 378 dns_zone_getorigin(zone), 379 1, &any); 380 381 if (result != ISC_R_SUCCESS) 382 goto cleanup; 383 } 384 385 result = ISC_R_SUCCESS; 386 dns_zone_setssutable(zone, table); 387 388 cleanup: 389 dns_ssutable_detach(&table); 390 return (result); 391} 392 393/* 394 * This is the TTL used for internally generated RRsets for static-stub zones. 395 * The value doesn't matter because the mapping is static, but needs to be 396 * defined for the sake of implementation. 397 */ 398#define STATICSTUB_SERVER_TTL 86400 399 400/*% 401 * Configure an apex NS with glues for a static-stub zone. 402 * For example, for the zone named "example.com", the following RRs will be 403 * added to the zone DB: 404 * example.com. NS example.com. 405 * example.com. A 192.0.2.1 406 * example.com. AAAA 2001:db8::1 407 */ 408static isc_result_t 409configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, 410 dns_rdatalist_t *rdatalist_ns, 411 dns_rdatalist_t *rdatalist_a, 412 dns_rdatalist_t *rdatalist_aaaa) 413{ 414 const cfg_listelt_t *element; 415 isc_mem_t *mctx = dns_zone_getmctx(zone); 416 isc_region_t region, sregion; 417 dns_rdata_t *rdata; 418 isc_result_t result = ISC_R_SUCCESS; 419 420 for (element = cfg_list_first(zconfig); 421 element != NULL; 422 element = cfg_list_next(element)) 423 { 424 const isc_sockaddr_t* sa; 425 isc_netaddr_t na; 426 const cfg_obj_t *address = cfg_listelt_value(element); 427 dns_rdatalist_t *rdatalist; 428 429 sa = cfg_obj_assockaddr(address); 430 if (isc_sockaddr_getport(sa) != 0) { 431 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 432 "port is not configurable for " 433 "static stub server-addresses"); 434 return (ISC_R_FAILURE); 435 } 436 isc_netaddr_fromsockaddr(&na, sa); 437 if (isc_netaddr_getzone(&na) != 0) { 438 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 439 "scoped address is not allowed " 440 "for static stub " 441 "server-addresses"); 442 return (ISC_R_FAILURE); 443 } 444 445 switch (na.family) { 446 case AF_INET: 447 region.length = sizeof(na.type.in); 448 rdatalist = rdatalist_a; 449 break; 450 default: 451 INSIST(na.family == AF_INET6); 452 region.length = sizeof(na.type.in6); 453 rdatalist = rdatalist_aaaa; 454 break; 455 } 456 457 rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); 458 if (rdata == NULL) 459 return (ISC_R_NOMEMORY); 460 region.base = (unsigned char *)(rdata + 1); 461 memcpy(region.base, &na.type, region.length); 462 dns_rdata_init(rdata); 463 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), 464 rdatalist->type, ®ion); 465 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 466 } 467 468 /* 469 * If no address is specified (unlikely in this context, but possible), 470 * there's nothing to do anymore. 471 */ 472 if (ISC_LIST_EMPTY(rdatalist_a->rdata) && 473 ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { 474 return (ISC_R_SUCCESS); 475 } 476 477 /* Add to the list an apex NS with the ns name being the origin name */ 478 dns_name_toregion(dns_zone_getorigin(zone), &sregion); 479 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); 480 if (rdata == NULL) { 481 /* 482 * Already allocated data will be freed in the caller, so 483 * we can simply return here. 484 */ 485 return (ISC_R_NOMEMORY); 486 } 487 region.length = sregion.length; 488 region.base = (unsigned char *)(rdata + 1); 489 memcpy(region.base, sregion.base, region.length); 490 dns_rdata_init(rdata); 491 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), 492 dns_rdatatype_ns, ®ion); 493 ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); 494 495 return (result); 496} 497 498/*% 499 * Configure an apex NS with an out-of-zone NS names for a static-stub zone. 500 * For example, for the zone named "example.com", something like the following 501 * RRs will be added to the zone DB: 502 * example.com. NS ns.example.net. 503 */ 504static isc_result_t 505configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, 506 dns_rdatalist_t *rdatalist, const char *zname) 507{ 508 const cfg_listelt_t *element; 509 isc_mem_t *mctx = dns_zone_getmctx(zone); 510 dns_rdata_t *rdata; 511 isc_region_t sregion, region; 512 isc_result_t result = ISC_R_SUCCESS; 513 514 for (element = cfg_list_first(zconfig); 515 element != NULL; 516 element = cfg_list_next(element)) 517 { 518 const cfg_obj_t *obj; 519 const char *str; 520 dns_fixedname_t fixed_name; 521 dns_name_t *nsname; 522 isc_buffer_t b; 523 524 obj = cfg_listelt_value(element); 525 str = cfg_obj_asstring(obj); 526 527 dns_fixedname_init(&fixed_name); 528 nsname = dns_fixedname_name(&fixed_name); 529 530 isc_buffer_init(&b, str, strlen(str)); 531 isc_buffer_add(&b, strlen(str)); 532 result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); 533 if (result != ISC_R_SUCCESS) { 534 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 535 "server-name '%s' is not a valid " 536 "name", str); 537 return (result); 538 } 539 if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { 540 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 541 "server-name '%s' must not be a " 542 "subdomain of zone name '%s'", 543 str, zname); 544 return (ISC_R_FAILURE); 545 } 546 547 dns_name_toregion(nsname, &sregion); 548 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); 549 if (rdata == NULL) 550 return (ISC_R_NOMEMORY); 551 region.length = sregion.length; 552 region.base = (unsigned char *)(rdata + 1); 553 memcpy(region.base, sregion.base, region.length); 554 dns_rdata_init(rdata); 555 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), 556 dns_rdatatype_ns, ®ion); 557 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 558 } 559 560 return (result); 561} 562 563/*% 564 * Configure static-stub zone. 565 */ 566static isc_result_t 567configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, 568 const char *zname, const char *dbtype) 569{ 570 int i = 0; 571 const cfg_obj_t *obj; 572 isc_mem_t *mctx = dns_zone_getmctx(zone); 573 dns_db_t *db = NULL; 574 dns_dbversion_t *dbversion = NULL; 575 dns_dbnode_t *apexnode = NULL; 576 dns_name_t apexname; 577 isc_result_t result; 578 dns_rdataset_t rdataset; 579 dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; 580 dns_rdatalist_t* rdatalists[] = { 581 &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL 582 }; 583 dns_rdata_t *rdata; 584 isc_region_t region; 585 586 /* Create the DB beforehand */ 587 RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), 588 dns_dbtype_stub, dns_zone_getclass(zone), 589 0, NULL, &db)); 590 dns_zone_setdb(zone, db); 591 592 dns_rdatalist_init(&rdatalist_ns); 593 rdatalist_ns.rdclass = dns_zone_getclass(zone); 594 rdatalist_ns.type = dns_rdatatype_ns; 595 rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; 596 597 dns_rdatalist_init(&rdatalist_a); 598 rdatalist_a.rdclass = dns_zone_getclass(zone); 599 rdatalist_a.type = dns_rdatatype_a; 600 rdatalist_a.ttl = STATICSTUB_SERVER_TTL; 601 602 dns_rdatalist_init(&rdatalist_aaaa); 603 rdatalist_aaaa.rdclass = dns_zone_getclass(zone); 604 rdatalist_aaaa.type = dns_rdatatype_aaaa; 605 rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; 606 607 /* Prepare zone RRs from the configuration */ 608 obj = NULL; 609 result = cfg_map_get(zconfig, "server-addresses", &obj); 610 if (result == ISC_R_SUCCESS) { 611 INSIST(obj != NULL); 612 result = configure_staticstub_serveraddrs(obj, zone, 613 &rdatalist_ns, 614 &rdatalist_a, 615 &rdatalist_aaaa); 616 if (result != ISC_R_SUCCESS) 617 goto cleanup; 618 } 619 620 obj = NULL; 621 result = cfg_map_get(zconfig, "server-names", &obj); 622 if (result == ISC_R_SUCCESS) { 623 INSIST(obj != NULL); 624 result = configure_staticstub_servernames(obj, zone, 625 &rdatalist_ns, 626 zname); 627 if (result != ISC_R_SUCCESS) 628 goto cleanup; 629 } 630 631 /* 632 * Sanity check: there should be at least one NS RR at the zone apex 633 * to trigger delegation. 634 */ 635 if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { 636 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 637 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 638 "No NS record is configured for a " 639 "static-stub zone '%s'", zname); 640 result = ISC_R_FAILURE; 641 goto cleanup; 642 } 643 644 /* 645 * Now add NS and glue A/AAAA RRsets to the zone DB. 646 * First open a new version for the add operation and get a pointer 647 * to the apex node (all RRs are of the apex name). 648 */ 649 result = dns_db_newversion(db, &dbversion); 650 if (result != ISC_R_SUCCESS) 651 goto cleanup; 652 dns_name_init(&apexname, NULL); 653 dns_name_clone(dns_zone_getorigin(zone), &apexname); 654 result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode); 655 if (result != ISC_R_SUCCESS) 656 goto cleanup; 657 658 /* Add NS RRset */ 659 dns_rdataset_init(&rdataset); 660 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) 661 == ISC_R_SUCCESS); 662 result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 663 0, NULL); 664 dns_rdataset_disassociate(&rdataset); 665 if (result != ISC_R_SUCCESS) 666 goto cleanup; 667 668 /* Add glue A RRset, if any */ 669 if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { 670 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset) 671 == ISC_R_SUCCESS); 672 result = dns_db_addrdataset(db, apexnode, dbversion, 0, 673 &rdataset, 0, NULL); 674 dns_rdataset_disassociate(&rdataset); 675 if (result != ISC_R_SUCCESS) 676 goto cleanup; 677 } 678 679 /* Add glue AAAA RRset, if any */ 680 if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { 681 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa, 682 &rdataset) 683 == ISC_R_SUCCESS); 684 result = dns_db_addrdataset(db, apexnode, dbversion, 0, 685 &rdataset, 0, NULL); 686 dns_rdataset_disassociate(&rdataset); 687 if (result != ISC_R_SUCCESS) 688 goto cleanup; 689 } 690 691 result = ISC_R_SUCCESS; 692 693 cleanup: 694 if (apexnode != NULL) 695 dns_db_detachnode(db, &apexnode); 696 if (dbversion != NULL) 697 dns_db_closeversion(db, &dbversion, ISC_TRUE); 698 if (db != NULL) 699 dns_db_detach(&db); 700 for (i = 0; rdatalists[i] != NULL; i++) { 701 while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { 702 ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); 703 dns_rdata_toregion(rdata, ®ion); 704 isc_mem_put(mctx, rdata, 705 sizeof(*rdata) + region.length); 706 } 707 } 708 709 return (result); 710} 711 712/*% 713 * Convert a config file zone type into a server zone type. 714 */ 715static inline dns_zonetype_t 716zonetype_fromconfig(const cfg_obj_t *map) { 717 const cfg_obj_t *obj = NULL; 718 isc_result_t result; 719 720 result = cfg_map_get(map, "type", &obj); 721 INSIST(result == ISC_R_SUCCESS && obj != NULL); 722 return (ns_config_getzonetype(obj)); 723} 724 725/*% 726 * Helper function for strtoargv(). Pardon the gratuitous recursion. 727 */ 728static isc_result_t 729strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, 730 char ***argvp, unsigned int n) 731{ 732 isc_result_t result; 733 734 /* Discard leading whitespace. */ 735 while (*s == ' ' || *s == '\t') 736 s++; 737 738 if (*s == '\0') { 739 /* We have reached the end of the string. */ 740 *argcp = n; 741 *argvp = isc_mem_get(mctx, n * sizeof(char *)); 742 if (*argvp == NULL) 743 return (ISC_R_NOMEMORY); 744 } else { 745 char *p = s; 746 while (*p != ' ' && *p != '\t' && *p != '\0') 747 p++; 748 if (*p != '\0') 749 *p++ = '\0'; 750 751 result = strtoargvsub(mctx, p, argcp, argvp, n + 1); 752 if (result != ISC_R_SUCCESS) 753 return (result); 754 (*argvp)[n] = s; 755 } 756 return (ISC_R_SUCCESS); 757} 758 759/*% 760 * Tokenize the string "s" into whitespace-separated words, 761 * return the number of words in '*argcp' and an array 762 * of pointers to the words in '*argvp'. The caller 763 * must free the array using isc_mem_put(). The string 764 * is modified in-place. 765 */ 766static isc_result_t 767strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { 768 return (strtoargvsub(mctx, s, argcp, argvp, 0)); 769} 770 771static void 772checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, 773 const cfg_obj_t **objp) 774{ 775 const char *zone = NULL; 776 isc_result_t result; 777 778 switch (ztype) { 779 case dns_zone_slave: zone = "slave"; break; 780 case dns_zone_master: zone = "master"; break; 781 default: 782 INSIST(0); 783 } 784 result = ns_checknames_get(maps, zone, objp); 785 INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL); 786} 787 788isc_result_t 789ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, 790 const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, 791 dns_zone_t *zone, dns_zone_t *raw) 792{ 793 isc_result_t result; 794 const char *zname; 795 dns_rdataclass_t zclass; 796 dns_rdataclass_t vclass; 797 const cfg_obj_t *maps[5]; 798 const cfg_obj_t *zoptions = NULL; 799 const cfg_obj_t *options = NULL; 800 const cfg_obj_t *obj; 801 const char *filename = NULL; 802 dns_notifytype_t notifytype = dns_notifytype_yes; 803 isc_sockaddr_t *addrs; 804 dns_name_t **keynames; 805 isc_uint32_t count; 806 char *cpval; 807 unsigned int dbargc; 808 char **dbargv; 809 static char default_dbtype[] = "rbt"; 810 isc_mem_t *mctx = dns_zone_getmctx(zone); 811 dns_dialuptype_t dialup = dns_dialuptype_no; 812 dns_zonetype_t ztype; 813 int i; 814 isc_int32_t journal_size; 815 isc_boolean_t multi; 816 isc_boolean_t alt; 817 dns_view_t *view; 818 isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE; 819 isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE; 820 isc_boolean_t ixfrdiff; 821 dns_masterformat_t masterformat; 822 isc_stats_t *zoneqrystats; 823 isc_boolean_t zonestats_on; 824 int seconds; 825 dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; 826 827 i = 0; 828 if (zconfig != NULL) { 829 zoptions = cfg_tuple_get(zconfig, "options"); 830 maps[i++] = zoptions; 831 } 832 if (vconfig != NULL) 833 maps[i++] = cfg_tuple_get(vconfig, "options"); 834 if (config != NULL) { 835 (void)cfg_map_get(config, "options", &options); 836 if (options != NULL) 837 maps[i++] = options; 838 } 839 maps[i++] = ns_g_defaults; 840 maps[i] = NULL; 841 842 if (vconfig != NULL) 843 RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"), 844 dns_rdataclass_in, &vclass)); 845 else 846 vclass = dns_rdataclass_in; 847 848 /* 849 * Configure values common to all zone types. 850 */ 851 852 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 853 854 RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"), 855 vclass, &zclass)); 856 dns_zone_setclass(zone, zclass); 857 if (raw != NULL) 858 dns_zone_setclass(raw, zclass); 859 860 ztype = zonetype_fromconfig(zoptions); 861 if (raw != NULL) { 862 dns_zone_settype(raw, ztype); 863 dns_zone_settype(zone, dns_zone_master); 864 } else 865 dns_zone_settype(zone, ztype); 866 867 868 obj = NULL; 869 result = cfg_map_get(zoptions, "database", &obj); 870 if (result == ISC_R_SUCCESS) 871 cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 872 else 873 cpval = default_dbtype; 874 875 if (cpval == NULL) 876 return(ISC_R_NOMEMORY); 877 878 result = strtoargv(mctx, cpval, &dbargc, &dbargv); 879 if (result != ISC_R_SUCCESS && cpval != default_dbtype) { 880 isc_mem_free(mctx, cpval); 881 return (result); 882 } 883 884 /* 885 * ANSI C is strange here. There is no logical reason why (char **) 886 * cannot be promoted automatically to (const char * const *) by the 887 * compiler w/o generating a warning. 888 */ 889 result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv); 890 isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv)); 891 if (cpval != default_dbtype) 892 isc_mem_free(mctx, cpval); 893 if (result != ISC_R_SUCCESS) 894 return (result); 895 896 obj = NULL; 897 result = cfg_map_get(zoptions, "file", &obj); 898 if (result == ISC_R_SUCCESS) 899 filename = cfg_obj_asstring(obj); 900 901 /* 902 * Unless we're using some alternative database, a master zone 903 * will be needing a master file. 904 */ 905 if (ztype == dns_zone_master && cpval == default_dbtype && 906 filename == NULL) { 907 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 908 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 909 "zone '%s': 'file' not specified", 910 zname); 911 return (ISC_R_FAILURE); 912 } 913 914 if (ztype == dns_zone_slave) 915 masterformat = dns_masterformat_raw; 916 else 917 masterformat = dns_masterformat_text; 918 obj = NULL; 919 result= ns_config_get(maps, "masterfile-format", &obj); 920 if (result == ISC_R_SUCCESS) { 921 const char *masterformatstr = cfg_obj_asstring(obj); 922 923 if (strcasecmp(masterformatstr, "text") == 0) 924 masterformat = dns_masterformat_text; 925 else if (strcasecmp(masterformatstr, "raw") == 0) 926 masterformat = dns_masterformat_raw; 927 else 928 INSIST(0); 929 } 930 931 if (raw != NULL) { 932#define SIGNED ".signed" 933 size_t signedlen = strlen(filename) + sizeof(SIGNED); 934 char *signedname; 935 936 RETERR(dns_zone_setfile2(raw, filename, masterformat)); 937 signedname = isc_mem_get(mctx, signedlen); 938 if (signedname == NULL) 939 return (ISC_R_NOMEMORY); 940 941 (void)snprintf(signedname, signedlen, "%s" SIGNED, filename); 942 result = dns_zone_setfile2(zone, signedname, 943 dns_masterformat_raw); 944 isc_mem_put(mctx, signedname, signedlen); 945 if (result != ISC_R_SUCCESS) 946 return (result); 947 } else 948 RETERR(dns_zone_setfile2(zone, filename, masterformat)); 949 950 obj = NULL; 951 result = cfg_map_get(zoptions, "journal", &obj); 952 if (result == ISC_R_SUCCESS) 953 RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); 954 955 /* 956 * Notify messages are processed by the raw zone if it exists. 957 */ 958 if (ztype == dns_zone_slave) 959 RETERR(configure_zone_acl(zconfig, vconfig, config, 960 allow_notify, ac, mayberaw, 961 dns_zone_setnotifyacl, 962 dns_zone_clearnotifyacl)); 963 964 /* 965 * XXXAG This probably does not make sense for stubs. 966 */ 967 RETERR(configure_zone_acl(zconfig, vconfig, config, 968 allow_query, ac, zone, 969 dns_zone_setqueryacl, 970 dns_zone_clearqueryacl)); 971 972 obj = NULL; 973 result = ns_config_get(maps, "dialup", &obj); 974 INSIST(result == ISC_R_SUCCESS && obj != NULL); 975 if (cfg_obj_isboolean(obj)) { 976 if (cfg_obj_asboolean(obj)) 977 dialup = dns_dialuptype_yes; 978 else 979 dialup = dns_dialuptype_no; 980 } else { 981 const char *dialupstr = cfg_obj_asstring(obj); 982 if (strcasecmp(dialupstr, "notify") == 0) 983 dialup = dns_dialuptype_notify; 984 else if (strcasecmp(dialupstr, "notify-passive") == 0) 985 dialup = dns_dialuptype_notifypassive; 986 else if (strcasecmp(dialupstr, "refresh") == 0) 987 dialup = dns_dialuptype_refresh; 988 else if (strcasecmp(dialupstr, "passive") == 0) 989 dialup = dns_dialuptype_passive; 990 else 991 INSIST(0); 992 } 993 if (raw != NULL) 994 dns_zone_setdialup(raw, dialup); 995 dns_zone_setdialup(zone, dialup); 996 997 obj = NULL; 998 result = ns_config_get(maps, "zone-statistics", &obj); 999 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1000 zonestats_on = cfg_obj_asboolean(obj); 1001 zoneqrystats = NULL; 1002 if (zonestats_on) { 1003 RETERR(isc_stats_create(mctx, &zoneqrystats, 1004 dns_nsstatscounter_max)); 1005 } 1006 dns_zone_setrequeststats(zone, zoneqrystats); 1007 if (zoneqrystats != NULL) 1008 isc_stats_detach(&zoneqrystats); 1009 1010 /* 1011 * Configure master functionality. This applies 1012 * to primary masters (type "master") and slaves 1013 * acting as masters (type "slave"), but not to stubs. 1014 */ 1015 if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && 1016 ztype != dns_zone_redirect) { 1017 obj = NULL; 1018 result = ns_config_get(maps, "notify", &obj); 1019 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1020 if (cfg_obj_isboolean(obj)) { 1021 if (cfg_obj_asboolean(obj)) 1022 notifytype = dns_notifytype_yes; 1023 else 1024 notifytype = dns_notifytype_no; 1025 } else { 1026 const char *notifystr = cfg_obj_asstring(obj); 1027 if (strcasecmp(notifystr, "explicit") == 0) 1028 notifytype = dns_notifytype_explicit; 1029 else if (strcasecmp(notifystr, "master-only") == 0) 1030 notifytype = dns_notifytype_masteronly; 1031 else 1032 INSIST(0); 1033 } 1034 if (raw != NULL) 1035 dns_zone_setnotifytype(raw, dns_notifytype_no); 1036 dns_zone_setnotifytype(zone, notifytype); 1037 1038 obj = NULL; 1039 result = ns_config_get(maps, "also-notify", &obj); 1040 if (result == ISC_R_SUCCESS) { 1041 isc_uint32_t addrcount; 1042 addrs = NULL; 1043 keynames = NULL; 1044 RETERR(ns_config_getipandkeylist(config, obj, mctx, 1045 &addrs, &keynames, 1046 &addrcount)); 1047 result = dns_zone_setalsonotifywithkeys(zone, addrs, 1048 keynames, 1049 addrcount); 1050 if (addrcount != 0) 1051 ns_config_putipandkeylist(mctx, &addrs, 1052 &keynames, addrcount); 1053 else 1054 INSIST(addrs == NULL && keynames == NULL); 1055 RETERR(result); 1056 } else 1057 RETERR(dns_zone_setalsonotify(zone, NULL, 0)); 1058 1059 obj = NULL; 1060 result = ns_config_get(maps, "notify-source", &obj); 1061 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1062 RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj))); 1063 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1064 1065 obj = NULL; 1066 result = ns_config_get(maps, "notify-source-v6", &obj); 1067 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1068 RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); 1069 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1070 1071 obj = NULL; 1072 result = ns_config_get(maps, "notify-to-soa", &obj); 1073 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1074 dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, 1075 cfg_obj_asboolean(obj)); 1076 1077 dns_zone_setisself(zone, ns_client_isself, NULL); 1078 1079 RETERR(configure_zone_acl(zconfig, vconfig, config, 1080 allow_transfer, ac, zone, 1081 dns_zone_setxfracl, 1082 dns_zone_clearxfracl)); 1083 1084 obj = NULL; 1085 result = ns_config_get(maps, "max-transfer-time-out", &obj); 1086 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1087 dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60); 1088 1089 obj = NULL; 1090 result = ns_config_get(maps, "max-transfer-idle-out", &obj); 1091 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1092 dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60); 1093 1094 obj = NULL; 1095 result = ns_config_get(maps, "max-journal-size", &obj); 1096 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1097 if (raw != NULL) 1098 dns_zone_setjournalsize(raw, -1); 1099 dns_zone_setjournalsize(zone, -1); 1100 if (cfg_obj_isstring(obj)) { 1101 const char *str = cfg_obj_asstring(obj); 1102 INSIST(strcasecmp(str, "unlimited") == 0); 1103 journal_size = ISC_UINT32_MAX / 2; 1104 } else { 1105 isc_resourcevalue_t value; 1106 value = cfg_obj_asuint64(obj); 1107 if (value > ISC_UINT32_MAX / 2) { 1108 cfg_obj_log(obj, ns_g_lctx, 1109 ISC_LOG_ERROR, 1110 "'max-journal-size " 1111 "%" ISC_PRINT_QUADFORMAT "d' " 1112 "is too large", 1113 value); 1114 RETERR(ISC_R_RANGE); 1115 } 1116 journal_size = (isc_uint32_t)value; 1117 } 1118 if (raw != NULL) 1119 dns_zone_setjournalsize(raw, journal_size); 1120 dns_zone_setjournalsize(zone, journal_size); 1121 1122 obj = NULL; 1123 result = ns_config_get(maps, "ixfr-from-differences", &obj); 1124 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1125 if (cfg_obj_isboolean(obj)) 1126 ixfrdiff = cfg_obj_asboolean(obj); 1127 else if (!strcasecmp(cfg_obj_asstring(obj), "master") && 1128 ztype == dns_zone_master) 1129 ixfrdiff = ISC_TRUE; 1130 else if (!strcasecmp(cfg_obj_asstring(obj), "slave") && 1131 ztype == dns_zone_slave) 1132 ixfrdiff = ISC_TRUE; 1133 else 1134 ixfrdiff = ISC_FALSE; 1135 if (raw != NULL) { 1136 dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, 1137 ISC_TRUE); 1138 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1139 ISC_TRUE); 1140 } else 1141 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, 1142 ixfrdiff); 1143 1144 obj = NULL; 1145 result = ns_config_get(maps, "request-ixfr", &obj); 1146 INSIST(result == ISC_R_SUCCESS); 1147 dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); 1148 1149 checknames(ztype, maps, &obj); 1150 INSIST(obj != NULL); 1151 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1152 fail = ISC_FALSE; 1153 check = ISC_TRUE; 1154 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1155 fail = check = ISC_TRUE; 1156 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1157 fail = check = ISC_FALSE; 1158 } else 1159 INSIST(0); 1160 if (raw != NULL) { 1161 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, 1162 check); 1163 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, 1164 fail); 1165 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, 1166 ISC_FALSE); 1167 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1168 ISC_FALSE); 1169 } else { 1170 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, 1171 check); 1172 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, 1173 fail); 1174 } 1175 1176 obj = NULL; 1177 result = ns_config_get(maps, "notify-delay", &obj); 1178 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1179 dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); 1180 1181 obj = NULL; 1182 result = ns_config_get(maps, "check-sibling", &obj); 1183 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1184 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, 1185 cfg_obj_asboolean(obj)); 1186 1187 obj = NULL; 1188 result = ns_config_get(maps, "zero-no-soa-ttl", &obj); 1189 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1190 dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); 1191 1192 obj = NULL; 1193 result = ns_config_get(maps, "nsec3-test-zone", &obj); 1194 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1195 dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, 1196 cfg_obj_asboolean(obj)); 1197 } else if (ztype == dns_zone_redirect) { 1198 dns_zone_setnotifytype(zone, dns_notifytype_no); 1199 1200 obj = NULL; 1201 result = ns_config_get(maps, "max-journal-size", &obj); 1202 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1203 dns_zone_setjournalsize(zone, -1); 1204 if (cfg_obj_isstring(obj)) { 1205 const char *str = cfg_obj_asstring(obj); 1206 INSIST(strcasecmp(str, "unlimited") == 0); 1207 journal_size = ISC_UINT32_MAX / 2; 1208 } else { 1209 isc_resourcevalue_t value; 1210 value = cfg_obj_asuint64(obj); 1211 if (value > ISC_UINT32_MAX / 2) { 1212 cfg_obj_log(obj, ns_g_lctx, 1213 ISC_LOG_ERROR, 1214 "'max-journal-size " 1215 "%" ISC_PRINT_QUADFORMAT "d' " 1216 "is too large", 1217 value); 1218 RETERR(ISC_R_RANGE); 1219 } 1220 journal_size = (isc_uint32_t)value; 1221 } 1222 dns_zone_setjournalsize(zone, journal_size); 1223 } 1224 1225 /* 1226 * Configure update-related options. These apply to 1227 * primary masters only. 1228 */ 1229 if (ztype == dns_zone_master) { 1230 dns_acl_t *updateacl; 1231 1232 RETERR(configure_zone_acl(zconfig, vconfig, config, 1233 allow_update, ac, mayberaw, 1234 dns_zone_setupdateacl, 1235 dns_zone_clearupdateacl)); 1236 1237 updateacl = dns_zone_getupdateacl(mayberaw); 1238 if (updateacl != NULL && dns_acl_isinsecure(updateacl)) 1239 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, 1240 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1241 "zone '%s' allows updates by IP " 1242 "address, which is insecure", 1243 zname); 1244 1245 RETERR(configure_zone_ssutable(zoptions, mayberaw, zname)); 1246 } 1247 1248 if (ztype == dns_zone_master || raw != NULL) { 1249 isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; 1250 1251 obj = NULL; 1252 result = ns_config_get(maps, "sig-validity-interval", &obj); 1253 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1254 { 1255 const cfg_obj_t *validity, *resign; 1256 1257 validity = cfg_tuple_get(obj, "validity"); 1258 seconds = cfg_obj_asuint32(validity) * 86400; 1259 dns_zone_setsigvalidityinterval(zone, seconds); 1260 1261 resign = cfg_tuple_get(obj, "re-sign"); 1262 if (cfg_obj_isvoid(resign)) { 1263 seconds /= 4; 1264 } else { 1265 if (seconds > 7 * 86400) 1266 seconds = cfg_obj_asuint32(resign) * 1267 86400; 1268 else 1269 seconds = cfg_obj_asuint32(resign) * 1270 3600; 1271 } 1272 dns_zone_setsigresigninginterval(zone, seconds); 1273 } 1274 1275 obj = NULL; 1276 result = ns_config_get(maps, "key-directory", &obj); 1277 if (result == ISC_R_SUCCESS) { 1278 filename = cfg_obj_asstring(obj); 1279 RETERR(dns_zone_setkeydirectory(zone, filename)); 1280 } 1281 1282 obj = NULL; 1283 result = ns_config_get(maps, "sig-signing-signatures", &obj); 1284 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1285 dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); 1286 1287 obj = NULL; 1288 result = ns_config_get(maps, "sig-signing-nodes", &obj); 1289 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1290 dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); 1291 1292 obj = NULL; 1293 result = ns_config_get(maps, "sig-signing-type", &obj); 1294 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1295 dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); 1296 1297 obj = NULL; 1298 result = ns_config_get(maps, "update-check-ksk", &obj); 1299 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1300 dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, 1301 cfg_obj_asboolean(obj)); 1302 1303 obj = NULL; 1304 result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj); 1305 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1306 dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, 1307 cfg_obj_asboolean(obj)); 1308 1309 obj = NULL; 1310 result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj); 1311 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1312 RETERR(dns_zone_setrefreshkeyinterval(zone, 1313 cfg_obj_asuint32(obj))); 1314 1315 obj = NULL; 1316 result = cfg_map_get(zoptions, "auto-dnssec", &obj); 1317 if (result == ISC_R_SUCCESS) { 1318 const char *arg = cfg_obj_asstring(obj); 1319 if (strcasecmp(arg, "allow") == 0) 1320 allow = ISC_TRUE; 1321 else if (strcasecmp(arg, "maintain") == 0) 1322 allow = maint = ISC_TRUE; 1323 else if (strcasecmp(arg, "off") == 0) 1324 ; 1325 else 1326 INSIST(0); 1327 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); 1328 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); 1329 } 1330 } 1331 1332 if (ztype == dns_zone_slave) { 1333 RETERR(configure_zone_acl(zconfig, vconfig, config, 1334 allow_update_forwarding, ac, 1335 mayberaw, dns_zone_setforwardacl, 1336 dns_zone_clearforwardacl)); 1337 } 1338 1339 /*% 1340 * Primary master functionality. 1341 */ 1342 if (ztype == dns_zone_master) { 1343 obj = NULL; 1344 result = ns_config_get(maps, "check-wildcard", &obj); 1345 if (result == ISC_R_SUCCESS) 1346 check = cfg_obj_asboolean(obj); 1347 else 1348 check = ISC_FALSE; 1349 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); 1350 1351 obj = NULL; 1352 result = ns_config_get(maps, "check-dup-records", &obj); 1353 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1354 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1355 fail = ISC_FALSE; 1356 check = ISC_TRUE; 1357 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1358 fail = check = ISC_TRUE; 1359 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1360 fail = check = ISC_FALSE; 1361 } else 1362 INSIST(0); 1363 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); 1364 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); 1365 1366 obj = NULL; 1367 result = ns_config_get(maps, "check-mx", &obj); 1368 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1369 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1370 fail = ISC_FALSE; 1371 check = ISC_TRUE; 1372 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1373 fail = check = ISC_TRUE; 1374 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1375 fail = check = ISC_FALSE; 1376 } else 1377 INSIST(0); 1378 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); 1379 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); 1380 1381 obj = NULL; 1382 result = ns_config_get(maps, "check-integrity", &obj); 1383 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1384 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, 1385 cfg_obj_asboolean(obj)); 1386 1387 obj = NULL; 1388 result = ns_config_get(maps, "check-mx-cname", &obj); 1389 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1390 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1391 warn = ISC_TRUE; 1392 ignore = ISC_FALSE; 1393 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1394 warn = ignore = ISC_FALSE; 1395 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1396 warn = ignore = ISC_TRUE; 1397 } else 1398 INSIST(0); 1399 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); 1400 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); 1401 1402 obj = NULL; 1403 result = ns_config_get(maps, "check-srv-cname", &obj); 1404 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1405 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { 1406 warn = ISC_TRUE; 1407 ignore = ISC_FALSE; 1408 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { 1409 warn = ignore = ISC_FALSE; 1410 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { 1411 warn = ignore = ISC_TRUE; 1412 } else 1413 INSIST(0); 1414 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); 1415 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, 1416 ignore); 1417 1418 obj = NULL; 1419 result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); 1420 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1421 dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE, 1422 cfg_obj_asboolean(obj)); 1423 1424 obj = NULL; 1425 result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); 1426 if (result == ISC_R_SUCCESS) { 1427 const char *arg = cfg_obj_asstring(obj); 1428 if (strcasecmp(arg, "no-resign") == 0) 1429 dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, 1430 ISC_TRUE); 1431 else if (strcasecmp(arg, "maintain") == 0) 1432 ; 1433 else 1434 INSIST(0); 1435 } 1436 1437 obj = NULL; 1438 result = ns_config_get(maps, "serial-update-method", &obj); 1439 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1440 if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) 1441 dns_zone_setserialupdatemethod(zone, 1442 dns_updatemethod_unixtime); 1443 else 1444 dns_zone_setserialupdatemethod(zone, 1445 dns_updatemethod_increment); 1446 } 1447 1448 /* 1449 * Configure slave functionality. 1450 */ 1451 switch (ztype) { 1452 case dns_zone_slave: 1453 case dns_zone_stub: 1454 case dns_zone_redirect: 1455 count = 0; 1456 obj = NULL; 1457 (void)cfg_map_get(zoptions, "masters", &obj); 1458 if (obj != NULL) { 1459 addrs = NULL; 1460 keynames = NULL; 1461 RETERR(ns_config_getipandkeylist(config, obj, mctx, 1462 &addrs, &keynames, 1463 &count)); 1464 result = dns_zone_setmasterswithkeys(mayberaw, addrs, 1465 keynames, count); 1466 if (count != 0) 1467 ns_config_putipandkeylist(mctx, &addrs, 1468 &keynames, count); 1469 else 1470 INSIST(addrs == NULL && keynames == NULL); 1471 } else 1472 result = dns_zone_setmasters(mayberaw, NULL, 0); 1473 RETERR(result); 1474 1475 multi = ISC_FALSE; 1476 if (count > 1) { 1477 obj = NULL; 1478 result = ns_config_get(maps, "multi-master", &obj); 1479 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1480 multi = cfg_obj_asboolean(obj); 1481 } 1482 dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); 1483 1484 obj = NULL; 1485 result = ns_config_get(maps, "max-transfer-time-in", &obj); 1486 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1487 dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60); 1488 1489 obj = NULL; 1490 result = ns_config_get(maps, "max-transfer-idle-in", &obj); 1491 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1492 dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60); 1493 1494 obj = NULL; 1495 result = ns_config_get(maps, "max-refresh-time", &obj); 1496 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1497 dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1498 1499 obj = NULL; 1500 result = ns_config_get(maps, "min-refresh-time", &obj); 1501 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1502 dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); 1503 1504 obj = NULL; 1505 result = ns_config_get(maps, "max-retry-time", &obj); 1506 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1507 dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); 1508 1509 obj = NULL; 1510 result = ns_config_get(maps, "min-retry-time", &obj); 1511 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1512 dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); 1513 1514 obj = NULL; 1515 result = ns_config_get(maps, "transfer-source", &obj); 1516 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1517 RETERR(dns_zone_setxfrsource4(mayberaw, 1518 cfg_obj_assockaddr(obj))); 1519 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1520 1521 obj = NULL; 1522 result = ns_config_get(maps, "transfer-source-v6", &obj); 1523 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1524 RETERR(dns_zone_setxfrsource6(mayberaw, 1525 cfg_obj_assockaddr(obj))); 1526 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 1527 1528 obj = NULL; 1529 result = ns_config_get(maps, "alt-transfer-source", &obj); 1530 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1531 RETERR(dns_zone_setaltxfrsource4(mayberaw, 1532 cfg_obj_assockaddr(obj))); 1533 1534 obj = NULL; 1535 result = ns_config_get(maps, "alt-transfer-source-v6", &obj); 1536 INSIST(result == ISC_R_SUCCESS && obj != NULL); 1537 RETERR(dns_zone_setaltxfrsource6(mayberaw, 1538 cfg_obj_assockaddr(obj))); 1539 1540 obj = NULL; 1541 (void)ns_config_get(maps, "use-alt-transfer-source", &obj); 1542 if (obj == NULL) { 1543 /* 1544 * Default off when views are in use otherwise 1545 * on for BIND 8 compatibility. 1546 */ 1547 view = dns_zone_getview(zone); 1548 if (view != NULL && strcmp(view->name, "_default") == 0) 1549 alt = ISC_TRUE; 1550 else 1551 alt = ISC_FALSE; 1552 } else 1553 alt = cfg_obj_asboolean(obj); 1554 dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt); 1555 1556 obj = NULL; 1557 (void)ns_config_get(maps, "try-tcp-refresh", &obj); 1558 dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, 1559 cfg_obj_asboolean(obj)); 1560 break; 1561 1562 case dns_zone_staticstub: 1563 RETERR(configure_staticstub(zoptions, zone, zname, 1564 default_dbtype)); 1565 break; 1566 1567 default: 1568 break; 1569 } 1570 1571 return (ISC_R_SUCCESS); 1572} 1573 1574 1575/* 1576 * Set up a DLZ zone as writeable 1577 */ 1578isc_result_t 1579ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, 1580 dns_rdataclass_t rdclass, dns_name_t *name) 1581{ 1582 dns_db_t *db = NULL; 1583 isc_time_t now; 1584 isc_result_t result; 1585 1586 TIME_NOW(&now); 1587 1588 dns_zone_settype(zone, dns_zone_dlz); 1589 result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); 1590 if (result != ISC_R_SUCCESS) 1591 return (result); 1592 result = dns_zone_dlzpostload(zone, db); 1593 dns_db_detach(&db); 1594 return (result); 1595} 1596 1597isc_boolean_t 1598ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { 1599 const cfg_obj_t *zoptions = NULL; 1600 const cfg_obj_t *obj = NULL; 1601 const char *cfilename; 1602 const char *zfilename; 1603 dns_zone_t *raw = NULL; 1604 isc_boolean_t has_raw; 1605 dns_zonetype_t ztype; 1606 1607 zoptions = cfg_tuple_get(zconfig, "options"); 1608 1609 /* 1610 * We always reconfigure a static-stub zone for simplicity, assuming 1611 * the amount of data to be loaded is small. 1612 */ 1613 if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) { 1614 dns_zone_log(zone, ISC_LOG_DEBUG(1), 1615 "not reusable: staticstub"); 1616 return (ISC_FALSE); 1617 } 1618 1619 /* If there's a raw zone, use that for filename and type comparison */ 1620 dns_zone_getraw(zone, &raw); 1621 if (raw != NULL) { 1622 zfilename = dns_zone_getfile(raw); 1623 ztype = dns_zone_gettype(raw); 1624 dns_zone_detach(&raw); 1625 has_raw = ISC_TRUE; 1626 } else { 1627 zfilename = dns_zone_getfile(zone); 1628 ztype = dns_zone_gettype(zone); 1629 has_raw = ISC_FALSE; 1630 } 1631 1632 obj = NULL; 1633 (void)cfg_map_get(zoptions, "inline-signing", &obj); 1634 if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) { 1635 dns_zone_log(zone, ISC_LOG_DEBUG(1), 1636 "not reusable: old zone was inline-signing"); 1637 return (ISC_FALSE); 1638 } else if ((obj != NULL && cfg_obj_asboolean(obj)) && !has_raw) { 1639 dns_zone_log(zone, ISC_LOG_DEBUG(1), 1640 "not reusable: old zone was not inline-signing"); 1641 return (ISC_FALSE); 1642 } 1643 1644 if (zonetype_fromconfig(zoptions) != ztype) { 1645 dns_zone_log(zone, ISC_LOG_DEBUG(1), 1646 "not reusable: type mismatch"); 1647 return (ISC_FALSE); 1648 } 1649 1650 obj = NULL; 1651 (void)cfg_map_get(zoptions, "file", &obj); 1652 if (obj != NULL) 1653 cfilename = cfg_obj_asstring(obj); 1654 else 1655 cfilename = NULL; 1656 if (!((cfilename == NULL && zfilename == NULL) || 1657 (cfilename != NULL && zfilename != NULL && 1658 strcmp(cfilename, zfilename) == 0))) 1659 { 1660 dns_zone_log(zone, ISC_LOG_DEBUG(1), 1661 "not reusable: filename mismatch"); 1662 return (ISC_FALSE); 1663 } 1664 1665 return (ISC_TRUE); 1666} 1667