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