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