--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISCCFG_KASPCONF_H
+#define ISCCFG_KASPCONF_H 1
+
+#include <isc/lang.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t* mctx,
+ dns_kasplist_t *kasplist, dns_kasp_t **kaspp);
+/*%<
+ * Create and configure a KASP. If 'config' is NULL, the default configuration
+ * is used. If a 'kasplist' is provided, a lookup happens and if a KASP
+ * already exists with the same name, no new KASP is created, and no attach to
+ * 'kaspp' happens.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'name' is a valid C string.
+ *
+ *\li kaspp != NULL && *kaspp == NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS If creating and configuring the KASP succeeds.
+ *\li #ISC_R_EXISTS If 'kasplist' already has a kasp structure with 'name'.
+ *\li #ISC_R_NOMEMORY
+ *
+ *\li Other errors are possible.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCFG_KASPCONF_H */
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+#include <isccfg/cfg.h>
+#include <isccfg/kaspconf.h>
+
+#include <dns/kasp.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+
+/*
+ * Utility function for getting a configuration option.
+ */
+static isc_result_t
+confget(cfg_obj_t const * const *maps, const char *name, const cfg_obj_t **obj)
+{
+ for (size_t i = 0;; i++) {
+ if (maps[i] == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+ }
+}
+
+/*
+ * Utility function for configuring durations.
+ */
+static time_t
+get_duration(const cfg_obj_t **maps, const char* option, time_t dfl)
+{
+ const cfg_obj_t *obj;
+ isc_result_t result;
+ obj = NULL;
+
+ result = confget(maps, option, &obj);
+ if (result == ISC_R_NOTFOUND) {
+ return (dfl);
+ }
+ INSIST(result == ISC_R_SUCCESS);
+ return (cfg_obj_asduration(obj));
+}
+
+/*
+ * Create a new kasp key derived from configuration.
+ */
+static isc_result_t
+cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t* kasp)
+{
+ isc_result_t result;
+ dns_kasp_key_t *key = NULL;
+
+ /* Create a new key reference. */
+ result = dns_kasp_key_create(kasp->mctx, &key);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ if (config == NULL) {
+ /* We are creating a key reference for the default kasp. */
+ key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK;
+ key->lifetime = 0;
+ key->algorithm = DNS_KEYALG_ECDSA256;
+ key->length = -1;
+ } else {
+ const char* rolestr;
+ const cfg_obj_t* obj;
+
+ rolestr = cfg_obj_asstring(cfg_tuple_get(config, "role"));
+ if (strcmp(rolestr, "ksk") == 0) {
+ key->role |= DNS_KASP_KEY_ROLE_KSK;
+ } else if (strcmp(rolestr, "zsk") == 0) {
+ key->role |= DNS_KASP_KEY_ROLE_ZSK;
+ } else if (strcmp(rolestr, "csk") == 0) {
+ key->role |= DNS_KASP_KEY_ROLE_KSK;
+ key->role |= DNS_KASP_KEY_ROLE_ZSK;
+ }
+ key->lifetime = cfg_obj_asduration(
+ cfg_tuple_get(config, "lifetime"));
+ key->algorithm = cfg_obj_asuint32(
+ cfg_tuple_get(config, "algorithm"));
+ obj = cfg_tuple_get(config, "length");
+ if (cfg_obj_isuint32(obj)) {
+ key->length = cfg_obj_asuint32(obj);
+ }
+ }
+ ISC_LIST_APPEND(kasp->keys, key, link);
+ ISC_INSIST(!(ISC_LIST_EMPTY(kasp->keys)));
+ return (result);
+}
+
+isc_result_t
+cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t* mctx,
+ dns_kasplist_t *kasplist, dns_kasp_t **kaspp)
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[2];
+ const cfg_obj_t *koptions = NULL;
+ const cfg_obj_t *keys = NULL;
+ const cfg_listelt_t *element = NULL;
+ const char *kaspname = NULL;
+ dns_kasp_t *kasp = NULL;
+ int i = 0;
+
+ REQUIRE(kaspp != NULL && *kaspp == NULL);
+
+ kaspname = (config != NULL) ?
+ cfg_obj_asstring(cfg_tuple_get(config, "name")) :
+ "default";
+
+ result = dns_kasplist_find(kasplist, kaspname, &kasp);
+
+ if (result == ISC_R_SUCCESS) {
+ return (ISC_R_EXISTS);
+ }
+ if (result != ISC_R_NOTFOUND) {
+ return (result);
+ }
+
+ /* No kasp with configured name was found in list, create new one. */
+ INSIST(kasp == NULL);
+ result = dns_kasp_create(mctx, kaspname, &kasp);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ INSIST(kasp != NULL);
+
+ /* Append it to the list for future lookups. */
+ ISC_LIST_APPEND(*kasplist, kasp, link);
+ ISC_INSIST(!(ISC_LIST_EMPTY(*kasplist)));
+
+ /* Now configure. */
+ INSIST(DNS_KASP_VALID(kasp));
+
+ if (config != NULL) {
+ koptions = cfg_tuple_get(config, "options");
+ maps[i++] = koptions;
+ }
+ maps[i] = NULL;
+
+ /* Configuration: Signatures */
+ kasp->signatures_refresh = get_duration(
+ maps, "signatures-refresh", DNS_KASP_SIG_REFRESH);
+ kasp->signatures_validity = get_duration(
+ maps, "signatures-validity", DNS_KASP_SIG_VALIDITY);
+ kasp->signatures_validity_dnskey = get_duration(
+ maps, "signatures-validity-dnskey",
+ DNS_KASP_SIG_VALIDITY_DNSKEY);
+
+ /* Configuration: Keys */
+ kasp->dnskey_ttl = get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL);
+ kasp->publish_safety = get_duration(maps, "publish-safety",
+ DNS_KASP_PUBLISH_SAFETY);
+ kasp->retire_safety = get_duration(maps, "retire-safety",
+ DNS_KASP_RETIRE_SAFETY);
+
+ (void)confget(maps, "keys", &keys);
+ if (keys == NULL) {
+ result = cfg_kaspkey_fromconfig(NULL, kasp);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ } else {
+ for (element = cfg_list_first(keys); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *kobj = cfg_listelt_value(element);
+ result = cfg_kaspkey_fromconfig(kobj, kasp);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+ }
+ }
+ ISC_INSIST(!(ISC_LIST_EMPTY(kasp->keys)));
+
+ // TODO: Rest of the configuration
+
+ /* Success: Attach the kasp to the pointer and return. */
+ dns_kasp_attach(kasp, kaspp);
+ return (ISC_R_SUCCESS);
+
+cleanup:
+
+ /* Something bad happened, detach (destroys kasp) and return error. */
+ dns_kasp_detach(&kasp);
+ return (result);
+}
./lib/isccfg/include/isccfg/cfg.h C 2000,2001,2002,2004,2005,2006,2007,2010,2013,2014,2015,2016,2018,2019
./lib/isccfg/include/isccfg/dnsconf.h C 2009,2016,2018,2019
./lib/isccfg/include/isccfg/grammar.h C 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2013,2014,2015,2016,2017,2018,2019
+./lib/isccfg/include/isccfg/kaspconf.h C 2019
./lib/isccfg/include/isccfg/log.h C 2001,2004,2005,2006,2007,2009,2016,2018,2019
./lib/isccfg/include/isccfg/namedconf.h C 2002,2004,2005,2006,2007,2009,2010,2014,2016,2018,2019
./lib/isccfg/include/isccfg/version.h C 2001,2004,2005,2006,2007,2016,2018,2019
+./lib/isccfg/kaspconf.c C 2019
./lib/isccfg/log.c C 2001,2004,2005,2006,2007,2016,2018,2019
./lib/isccfg/namedconf.c C 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
./lib/isccfg/parser.c C 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019