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