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