1*4afad4b7Schristos /* $NetBSD: kaspconf.c,v 1.1 2024/02/18 20:57:58 christos Exp $ */
2*4afad4b7Schristos
3*4afad4b7Schristos /*
4*4afad4b7Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5*4afad4b7Schristos *
6*4afad4b7Schristos * SPDX-License-Identifier: MPL-2.0
7*4afad4b7Schristos *
8*4afad4b7Schristos * This Source Code Form is subject to the terms of the Mozilla Public
9*4afad4b7Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this
10*4afad4b7Schristos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11*4afad4b7Schristos *
12*4afad4b7Schristos * See the COPYRIGHT file distributed with this work for additional
13*4afad4b7Schristos * information regarding copyright ownership.
14*4afad4b7Schristos */
15*4afad4b7Schristos
16*4afad4b7Schristos #include <inttypes.h>
17*4afad4b7Schristos #include <stdbool.h>
18*4afad4b7Schristos #include <stdlib.h>
19*4afad4b7Schristos
20*4afad4b7Schristos #include <isc/mem.h>
21*4afad4b7Schristos #include <isc/print.h>
22*4afad4b7Schristos #include <isc/region.h>
23*4afad4b7Schristos #include <isc/string.h>
24*4afad4b7Schristos #include <isc/util.h>
25*4afad4b7Schristos
26*4afad4b7Schristos #include <dns/kasp.h>
27*4afad4b7Schristos #include <dns/keyvalues.h>
28*4afad4b7Schristos #include <dns/log.h>
29*4afad4b7Schristos #include <dns/nsec3.h>
30*4afad4b7Schristos #include <dns/result.h>
31*4afad4b7Schristos #include <dns/secalg.h>
32*4afad4b7Schristos
33*4afad4b7Schristos #include <isccfg/cfg.h>
34*4afad4b7Schristos #include <isccfg/kaspconf.h>
35*4afad4b7Schristos #include <isccfg/namedconf.h>
36*4afad4b7Schristos
37*4afad4b7Schristos #define DEFAULT_NSEC3PARAM_ITER 5
38*4afad4b7Schristos #define DEFAULT_NSEC3PARAM_SALTLEN 8
39*4afad4b7Schristos
40*4afad4b7Schristos /*
41*4afad4b7Schristos * Utility function for getting a configuration option.
42*4afad4b7Schristos */
43*4afad4b7Schristos static isc_result_t
confget(cfg_obj_t const * const * maps,const char * name,const cfg_obj_t ** obj)44*4afad4b7Schristos confget(cfg_obj_t const *const *maps, const char *name, const cfg_obj_t **obj) {
45*4afad4b7Schristos for (size_t i = 0;; i++) {
46*4afad4b7Schristos if (maps[i] == NULL) {
47*4afad4b7Schristos return (ISC_R_NOTFOUND);
48*4afad4b7Schristos }
49*4afad4b7Schristos if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) {
50*4afad4b7Schristos return (ISC_R_SUCCESS);
51*4afad4b7Schristos }
52*4afad4b7Schristos }
53*4afad4b7Schristos }
54*4afad4b7Schristos
55*4afad4b7Schristos /*
56*4afad4b7Schristos * Utility function for configuring durations.
57*4afad4b7Schristos */
58*4afad4b7Schristos static uint32_t
get_duration(const cfg_obj_t ** maps,const char * option,uint32_t dfl)59*4afad4b7Schristos get_duration(const cfg_obj_t **maps, const char *option, uint32_t dfl) {
60*4afad4b7Schristos const cfg_obj_t *obj;
61*4afad4b7Schristos isc_result_t result;
62*4afad4b7Schristos obj = NULL;
63*4afad4b7Schristos
64*4afad4b7Schristos result = confget(maps, option, &obj);
65*4afad4b7Schristos if (result == ISC_R_NOTFOUND) {
66*4afad4b7Schristos return (dfl);
67*4afad4b7Schristos }
68*4afad4b7Schristos INSIST(result == ISC_R_SUCCESS);
69*4afad4b7Schristos return (cfg_obj_asduration(obj));
70*4afad4b7Schristos }
71*4afad4b7Schristos
72*4afad4b7Schristos /*
73*4afad4b7Schristos * Create a new kasp key derived from configuration.
74*4afad4b7Schristos */
75*4afad4b7Schristos static isc_result_t
cfg_kaspkey_fromconfig(const cfg_obj_t * config,dns_kasp_t * kasp,isc_log_t * logctx)76*4afad4b7Schristos cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
77*4afad4b7Schristos isc_log_t *logctx) {
78*4afad4b7Schristos isc_result_t result;
79*4afad4b7Schristos dns_kasp_key_t *key = NULL;
80*4afad4b7Schristos
81*4afad4b7Schristos /* Create a new key reference. */
82*4afad4b7Schristos result = dns_kasp_key_create(kasp, &key);
83*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
84*4afad4b7Schristos return (result);
85*4afad4b7Schristos }
86*4afad4b7Schristos
87*4afad4b7Schristos if (config == NULL) {
88*4afad4b7Schristos /* We are creating a key reference for the default kasp. */
89*4afad4b7Schristos key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK;
90*4afad4b7Schristos key->lifetime = 0; /* unlimited */
91*4afad4b7Schristos key->algorithm = DNS_KEYALG_ECDSA256;
92*4afad4b7Schristos key->length = -1;
93*4afad4b7Schristos } else {
94*4afad4b7Schristos const char *rolestr = NULL;
95*4afad4b7Schristos const cfg_obj_t *obj = NULL;
96*4afad4b7Schristos isc_consttextregion_t alg;
97*4afad4b7Schristos
98*4afad4b7Schristos rolestr = cfg_obj_asstring(cfg_tuple_get(config, "role"));
99*4afad4b7Schristos if (strcmp(rolestr, "ksk") == 0) {
100*4afad4b7Schristos key->role |= DNS_KASP_KEY_ROLE_KSK;
101*4afad4b7Schristos } else if (strcmp(rolestr, "zsk") == 0) {
102*4afad4b7Schristos key->role |= DNS_KASP_KEY_ROLE_ZSK;
103*4afad4b7Schristos } else if (strcmp(rolestr, "csk") == 0) {
104*4afad4b7Schristos key->role |= DNS_KASP_KEY_ROLE_KSK;
105*4afad4b7Schristos key->role |= DNS_KASP_KEY_ROLE_ZSK;
106*4afad4b7Schristos }
107*4afad4b7Schristos
108*4afad4b7Schristos key->lifetime = 0; /* unlimited */
109*4afad4b7Schristos obj = cfg_tuple_get(config, "lifetime");
110*4afad4b7Schristos if (cfg_obj_isduration(obj)) {
111*4afad4b7Schristos key->lifetime = cfg_obj_asduration(obj);
112*4afad4b7Schristos }
113*4afad4b7Schristos
114*4afad4b7Schristos obj = cfg_tuple_get(config, "algorithm");
115*4afad4b7Schristos alg.base = cfg_obj_asstring(obj);
116*4afad4b7Schristos alg.length = strlen(alg.base);
117*4afad4b7Schristos result = dns_secalg_fromtext(&key->algorithm,
118*4afad4b7Schristos (isc_textregion_t *)&alg);
119*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
120*4afad4b7Schristos cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
121*4afad4b7Schristos "dnssec-policy: bad algorithm %s",
122*4afad4b7Schristos alg.base);
123*4afad4b7Schristos result = DNS_R_BADALG;
124*4afad4b7Schristos goto cleanup;
125*4afad4b7Schristos }
126*4afad4b7Schristos
127*4afad4b7Schristos obj = cfg_tuple_get(config, "length");
128*4afad4b7Schristos if (cfg_obj_isuint32(obj)) {
129*4afad4b7Schristos uint32_t min, size;
130*4afad4b7Schristos size = cfg_obj_asuint32(obj);
131*4afad4b7Schristos
132*4afad4b7Schristos switch (key->algorithm) {
133*4afad4b7Schristos case DNS_KEYALG_RSASHA1:
134*4afad4b7Schristos case DNS_KEYALG_NSEC3RSASHA1:
135*4afad4b7Schristos case DNS_KEYALG_RSASHA256:
136*4afad4b7Schristos case DNS_KEYALG_RSASHA512:
137*4afad4b7Schristos min = DNS_KEYALG_RSASHA512 ? 1024 : 512;
138*4afad4b7Schristos if (size < min || size > 4096) {
139*4afad4b7Schristos cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
140*4afad4b7Schristos "dnssec-policy: key with "
141*4afad4b7Schristos "algorithm %s has invalid "
142*4afad4b7Schristos "key length %u",
143*4afad4b7Schristos alg.base, size);
144*4afad4b7Schristos result = ISC_R_RANGE;
145*4afad4b7Schristos goto cleanup;
146*4afad4b7Schristos }
147*4afad4b7Schristos break;
148*4afad4b7Schristos case DNS_KEYALG_ECDSA256:
149*4afad4b7Schristos case DNS_KEYALG_ECDSA384:
150*4afad4b7Schristos case DNS_KEYALG_ED25519:
151*4afad4b7Schristos case DNS_KEYALG_ED448:
152*4afad4b7Schristos cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
153*4afad4b7Schristos "dnssec-policy: key algorithm %s "
154*4afad4b7Schristos "has predefined length; ignoring "
155*4afad4b7Schristos "length value %u",
156*4afad4b7Schristos alg.base, size);
157*4afad4b7Schristos default:
158*4afad4b7Schristos break;
159*4afad4b7Schristos }
160*4afad4b7Schristos
161*4afad4b7Schristos key->length = size;
162*4afad4b7Schristos }
163*4afad4b7Schristos }
164*4afad4b7Schristos
165*4afad4b7Schristos dns_kasp_addkey(kasp, key);
166*4afad4b7Schristos return (ISC_R_SUCCESS);
167*4afad4b7Schristos
168*4afad4b7Schristos cleanup:
169*4afad4b7Schristos
170*4afad4b7Schristos dns_kasp_key_destroy(key);
171*4afad4b7Schristos return (result);
172*4afad4b7Schristos }
173*4afad4b7Schristos
174*4afad4b7Schristos static isc_result_t
cfg_nsec3param_fromconfig(const cfg_obj_t * config,dns_kasp_t * kasp,isc_log_t * logctx)175*4afad4b7Schristos cfg_nsec3param_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
176*4afad4b7Schristos isc_log_t *logctx) {
177*4afad4b7Schristos dns_kasp_key_t *kkey;
178*4afad4b7Schristos unsigned int min_keysize = 4096;
179*4afad4b7Schristos const cfg_obj_t *obj = NULL;
180*4afad4b7Schristos uint32_t iter = DEFAULT_NSEC3PARAM_ITER;
181*4afad4b7Schristos uint32_t saltlen = DEFAULT_NSEC3PARAM_SALTLEN;
182*4afad4b7Schristos uint32_t badalg = 0;
183*4afad4b7Schristos bool optout = false;
184*4afad4b7Schristos isc_result_t ret = ISC_R_SUCCESS;
185*4afad4b7Schristos
186*4afad4b7Schristos /* How many iterations. */
187*4afad4b7Schristos obj = cfg_tuple_get(config, "iterations");
188*4afad4b7Schristos if (cfg_obj_isuint32(obj)) {
189*4afad4b7Schristos iter = cfg_obj_asuint32(obj);
190*4afad4b7Schristos }
191*4afad4b7Schristos dns_kasp_freeze(kasp);
192*4afad4b7Schristos for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
193*4afad4b7Schristos kkey = ISC_LIST_NEXT(kkey, link))
194*4afad4b7Schristos {
195*4afad4b7Schristos unsigned int keysize = dns_kasp_key_size(kkey);
196*4afad4b7Schristos uint32_t keyalg = dns_kasp_key_algorithm(kkey);
197*4afad4b7Schristos
198*4afad4b7Schristos if (keysize < min_keysize) {
199*4afad4b7Schristos min_keysize = keysize;
200*4afad4b7Schristos }
201*4afad4b7Schristos
202*4afad4b7Schristos /* NSEC3 cannot be used with certain key algorithms. */
203*4afad4b7Schristos if (keyalg == DNS_KEYALG_RSAMD5 || keyalg == DNS_KEYALG_DH ||
204*4afad4b7Schristos keyalg == DNS_KEYALG_DSA || keyalg == DNS_KEYALG_RSASHA1)
205*4afad4b7Schristos {
206*4afad4b7Schristos badalg = keyalg;
207*4afad4b7Schristos }
208*4afad4b7Schristos }
209*4afad4b7Schristos dns_kasp_thaw(kasp);
210*4afad4b7Schristos
211*4afad4b7Schristos if (badalg > 0) {
212*4afad4b7Schristos char algstr[DNS_SECALG_FORMATSIZE];
213*4afad4b7Schristos dns_secalg_format((dns_secalg_t)badalg, algstr, sizeof(algstr));
214*4afad4b7Schristos cfg_obj_log(
215*4afad4b7Schristos obj, logctx, ISC_LOG_ERROR,
216*4afad4b7Schristos "dnssec-policy: cannot use nsec3 with algorithm '%s'",
217*4afad4b7Schristos algstr);
218*4afad4b7Schristos return (DNS_R_NSEC3BADALG);
219*4afad4b7Schristos }
220*4afad4b7Schristos
221*4afad4b7Schristos if (iter > dns_nsec3_maxiterations()) {
222*4afad4b7Schristos ret = DNS_R_NSEC3ITERRANGE;
223*4afad4b7Schristos }
224*4afad4b7Schristos
225*4afad4b7Schristos if (ret == DNS_R_NSEC3ITERRANGE) {
226*4afad4b7Schristos cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
227*4afad4b7Schristos "dnssec-policy: nsec3 iterations value %u "
228*4afad4b7Schristos "out of range",
229*4afad4b7Schristos iter);
230*4afad4b7Schristos return (ret);
231*4afad4b7Schristos }
232*4afad4b7Schristos
233*4afad4b7Schristos /* Opt-out? */
234*4afad4b7Schristos obj = cfg_tuple_get(config, "optout");
235*4afad4b7Schristos if (cfg_obj_isboolean(obj)) {
236*4afad4b7Schristos optout = cfg_obj_asboolean(obj);
237*4afad4b7Schristos }
238*4afad4b7Schristos
239*4afad4b7Schristos /* Salt */
240*4afad4b7Schristos obj = cfg_tuple_get(config, "salt-length");
241*4afad4b7Schristos if (cfg_obj_isuint32(obj)) {
242*4afad4b7Schristos saltlen = cfg_obj_asuint32(obj);
243*4afad4b7Schristos }
244*4afad4b7Schristos if (saltlen > 0xff) {
245*4afad4b7Schristos cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
246*4afad4b7Schristos "dnssec-policy: nsec3 salt length %u too high",
247*4afad4b7Schristos saltlen);
248*4afad4b7Schristos return (DNS_R_NSEC3SALTRANGE);
249*4afad4b7Schristos }
250*4afad4b7Schristos
251*4afad4b7Schristos dns_kasp_setnsec3param(kasp, iter, optout, saltlen);
252*4afad4b7Schristos return (ISC_R_SUCCESS);
253*4afad4b7Schristos }
254*4afad4b7Schristos
255*4afad4b7Schristos isc_result_t
cfg_kasp_fromconfig(const cfg_obj_t * config,const char * name,isc_mem_t * mctx,isc_log_t * logctx,dns_kasplist_t * kasplist,dns_kasp_t ** kaspp)256*4afad4b7Schristos cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
257*4afad4b7Schristos isc_log_t *logctx, dns_kasplist_t *kasplist,
258*4afad4b7Schristos dns_kasp_t **kaspp) {
259*4afad4b7Schristos isc_result_t result;
260*4afad4b7Schristos const cfg_obj_t *maps[2];
261*4afad4b7Schristos const cfg_obj_t *koptions = NULL;
262*4afad4b7Schristos const cfg_obj_t *keys = NULL;
263*4afad4b7Schristos const cfg_obj_t *nsec3 = NULL;
264*4afad4b7Schristos const cfg_listelt_t *element = NULL;
265*4afad4b7Schristos const char *kaspname = NULL;
266*4afad4b7Schristos dns_kasp_t *kasp = NULL;
267*4afad4b7Schristos size_t i = 0;
268*4afad4b7Schristos
269*4afad4b7Schristos REQUIRE(kaspp != NULL && *kaspp == NULL);
270*4afad4b7Schristos
271*4afad4b7Schristos kaspname = (name == NULL)
272*4afad4b7Schristos ? cfg_obj_asstring(cfg_tuple_get(config, "name"))
273*4afad4b7Schristos : name;
274*4afad4b7Schristos INSIST(kaspname != NULL);
275*4afad4b7Schristos
276*4afad4b7Schristos result = dns_kasplist_find(kasplist, kaspname, &kasp);
277*4afad4b7Schristos
278*4afad4b7Schristos if (result == ISC_R_SUCCESS) {
279*4afad4b7Schristos cfg_obj_log(
280*4afad4b7Schristos config, logctx, ISC_LOG_ERROR,
281*4afad4b7Schristos "dnssec-policy: duplicately named policy found '%s'",
282*4afad4b7Schristos kaspname);
283*4afad4b7Schristos dns_kasp_detach(&kasp);
284*4afad4b7Schristos return (ISC_R_EXISTS);
285*4afad4b7Schristos }
286*4afad4b7Schristos if (result != ISC_R_NOTFOUND) {
287*4afad4b7Schristos return (result);
288*4afad4b7Schristos }
289*4afad4b7Schristos
290*4afad4b7Schristos /* No kasp with configured name was found in list, create new one. */
291*4afad4b7Schristos INSIST(kasp == NULL);
292*4afad4b7Schristos result = dns_kasp_create(mctx, kaspname, &kasp);
293*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
294*4afad4b7Schristos return (result);
295*4afad4b7Schristos }
296*4afad4b7Schristos INSIST(kasp != NULL);
297*4afad4b7Schristos
298*4afad4b7Schristos /* Now configure. */
299*4afad4b7Schristos INSIST(DNS_KASP_VALID(kasp));
300*4afad4b7Schristos
301*4afad4b7Schristos if (config != NULL) {
302*4afad4b7Schristos koptions = cfg_tuple_get(config, "options");
303*4afad4b7Schristos maps[i++] = koptions;
304*4afad4b7Schristos }
305*4afad4b7Schristos maps[i] = NULL;
306*4afad4b7Schristos
307*4afad4b7Schristos /* Configuration: Signatures */
308*4afad4b7Schristos dns_kasp_setsigrefresh(kasp, get_duration(maps, "signatures-refresh",
309*4afad4b7Schristos DNS_KASP_SIG_REFRESH));
310*4afad4b7Schristos dns_kasp_setsigvalidity(kasp, get_duration(maps, "signatures-validity",
311*4afad4b7Schristos DNS_KASP_SIG_VALIDITY));
312*4afad4b7Schristos dns_kasp_setsigvalidity_dnskey(
313*4afad4b7Schristos kasp, get_duration(maps, "signatures-validity-dnskey",
314*4afad4b7Schristos DNS_KASP_SIG_VALIDITY_DNSKEY));
315*4afad4b7Schristos
316*4afad4b7Schristos /* Configuration: Keys */
317*4afad4b7Schristos dns_kasp_setdnskeyttl(
318*4afad4b7Schristos kasp, get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL));
319*4afad4b7Schristos dns_kasp_setpublishsafety(kasp, get_duration(maps, "publish-safety",
320*4afad4b7Schristos DNS_KASP_PUBLISH_SAFETY));
321*4afad4b7Schristos dns_kasp_setretiresafety(kasp, get_duration(maps, "retire-safety",
322*4afad4b7Schristos DNS_KASP_RETIRE_SAFETY));
323*4afad4b7Schristos dns_kasp_setpurgekeys(
324*4afad4b7Schristos kasp, get_duration(maps, "purge-keys", DNS_KASP_PURGE_KEYS));
325*4afad4b7Schristos
326*4afad4b7Schristos (void)confget(maps, "keys", &keys);
327*4afad4b7Schristos if (keys != NULL) {
328*4afad4b7Schristos char role[256] = { 0 };
329*4afad4b7Schristos dns_kasp_key_t *kkey = NULL;
330*4afad4b7Schristos
331*4afad4b7Schristos for (element = cfg_list_first(keys); element != NULL;
332*4afad4b7Schristos element = cfg_list_next(element))
333*4afad4b7Schristos {
334*4afad4b7Schristos cfg_obj_t *kobj = cfg_listelt_value(element);
335*4afad4b7Schristos result = cfg_kaspkey_fromconfig(kobj, kasp, logctx);
336*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
337*4afad4b7Schristos goto cleanup;
338*4afad4b7Schristos }
339*4afad4b7Schristos }
340*4afad4b7Schristos INSIST(!(dns_kasp_keylist_empty(kasp)));
341*4afad4b7Schristos dns_kasp_freeze(kasp);
342*4afad4b7Schristos for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
343*4afad4b7Schristos kkey = ISC_LIST_NEXT(kkey, link))
344*4afad4b7Schristos {
345*4afad4b7Schristos uint32_t keyalg = dns_kasp_key_algorithm(kkey);
346*4afad4b7Schristos INSIST(keyalg < ARRAY_SIZE(role));
347*4afad4b7Schristos
348*4afad4b7Schristos if (dns_kasp_key_zsk(kkey)) {
349*4afad4b7Schristos role[keyalg] |= DNS_KASP_KEY_ROLE_ZSK;
350*4afad4b7Schristos }
351*4afad4b7Schristos
352*4afad4b7Schristos if (dns_kasp_key_ksk(kkey)) {
353*4afad4b7Schristos role[keyalg] |= DNS_KASP_KEY_ROLE_KSK;
354*4afad4b7Schristos }
355*4afad4b7Schristos }
356*4afad4b7Schristos dns_kasp_thaw(kasp);
357*4afad4b7Schristos for (i = 0; i < ARRAY_SIZE(role); i++) {
358*4afad4b7Schristos if (role[i] != 0 && role[i] != (DNS_KASP_KEY_ROLE_ZSK |
359*4afad4b7Schristos DNS_KASP_KEY_ROLE_KSK))
360*4afad4b7Schristos {
361*4afad4b7Schristos cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
362*4afad4b7Schristos "dnssec-policy: algorithm %zu "
363*4afad4b7Schristos "requires both KSK and ZSK roles",
364*4afad4b7Schristos i);
365*4afad4b7Schristos result = ISC_R_FAILURE;
366*4afad4b7Schristos }
367*4afad4b7Schristos }
368*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
369*4afad4b7Schristos goto cleanup;
370*4afad4b7Schristos }
371*4afad4b7Schristos } else if (strcmp(kaspname, "insecure") == 0) {
372*4afad4b7Schristos /* "dnssec-policy insecure": key list must be empty */
373*4afad4b7Schristos INSIST(strcmp(kaspname, "insecure") == 0);
374*4afad4b7Schristos INSIST(dns_kasp_keylist_empty(kasp));
375*4afad4b7Schristos } else {
376*4afad4b7Schristos /* No keys clause configured, use the "default". */
377*4afad4b7Schristos result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
378*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
379*4afad4b7Schristos goto cleanup;
380*4afad4b7Schristos }
381*4afad4b7Schristos INSIST(!(dns_kasp_keylist_empty(kasp)));
382*4afad4b7Schristos }
383*4afad4b7Schristos
384*4afad4b7Schristos /* Configuration: NSEC3 */
385*4afad4b7Schristos (void)confget(maps, "nsec3param", &nsec3);
386*4afad4b7Schristos if (nsec3 == NULL) {
387*4afad4b7Schristos dns_kasp_setnsec3(kasp, false);
388*4afad4b7Schristos } else {
389*4afad4b7Schristos dns_kasp_setnsec3(kasp, true);
390*4afad4b7Schristos result = cfg_nsec3param_fromconfig(nsec3, kasp, logctx);
391*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
392*4afad4b7Schristos goto cleanup;
393*4afad4b7Schristos }
394*4afad4b7Schristos }
395*4afad4b7Schristos
396*4afad4b7Schristos /* Configuration: Zone settings */
397*4afad4b7Schristos dns_kasp_setzonemaxttl(
398*4afad4b7Schristos kasp, get_duration(maps, "max-zone-ttl", DNS_KASP_ZONE_MAXTTL));
399*4afad4b7Schristos dns_kasp_setzonepropagationdelay(
400*4afad4b7Schristos kasp, get_duration(maps, "zone-propagation-delay",
401*4afad4b7Schristos DNS_KASP_ZONE_PROPDELAY));
402*4afad4b7Schristos
403*4afad4b7Schristos /* Configuration: Parent settings */
404*4afad4b7Schristos dns_kasp_setdsttl(kasp,
405*4afad4b7Schristos get_duration(maps, "parent-ds-ttl", DNS_KASP_DS_TTL));
406*4afad4b7Schristos dns_kasp_setparentpropagationdelay(
407*4afad4b7Schristos kasp, get_duration(maps, "parent-propagation-delay",
408*4afad4b7Schristos DNS_KASP_PARENT_PROPDELAY));
409*4afad4b7Schristos
410*4afad4b7Schristos /* Append it to the list for future lookups. */
411*4afad4b7Schristos ISC_LIST_APPEND(*kasplist, kasp, link);
412*4afad4b7Schristos INSIST(!(ISC_LIST_EMPTY(*kasplist)));
413*4afad4b7Schristos
414*4afad4b7Schristos /* Success: Attach the kasp to the pointer and return. */
415*4afad4b7Schristos dns_kasp_attach(kasp, kaspp);
416*4afad4b7Schristos
417*4afad4b7Schristos /* Don't detach as kasp is on '*kasplist' */
418*4afad4b7Schristos return (ISC_R_SUCCESS);
419*4afad4b7Schristos
420*4afad4b7Schristos cleanup:
421*4afad4b7Schristos
422*4afad4b7Schristos /* Something bad happened, detach (destroys kasp) and return error. */
423*4afad4b7Schristos dns_kasp_detach(&kasp);
424*4afad4b7Schristos return (result);
425*4afad4b7Schristos }
426