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