Commit 7bfac503 authored by Matthijs Mekking's avatar Matthijs Mekking 🏡

Add code for creating kasp from config

Add code for creating, configuring, and destroying KASP keys.  When
using the default policy, create one CSK, no rollover.
parent 1a9692f5
......@@ -35,11 +35,11 @@ SUBDIRS = include
TESTDIRS = @UNITTESTS@
# Alphabetically
OBJS = aclconf.@O@ dnsconf.@O@ log.@O@ namedconf.@O@ \
OBJS = aclconf.@O@ dnsconf.@O@ kaspconf.@O@ log.@O@ namedconf.@O@ \
parser.@O@ version.@O@
# Alphabetically
SRCS = aclconf.c dnsconf.c log.c namedconf.c \
SRCS = aclconf.c dnsconf.c kaspconf.c log.c namedconf.c \
parser.c version.c
TARGETS = timestamp
......
/*
* 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 */
/*
* 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);
}
......@@ -24,6 +24,7 @@ cfg_doc_tuple
cfg_doc_void
cfg_gettoken
cfg_is_enum
cfg_kasp_fromconfig
cfg_list_first
cfg_list_length
cfg_list_next
......
......@@ -30,6 +30,9 @@
<ClCompile Include="..\dnsconf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\kaspconf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\log.c">
<Filter>Source Files</Filter>
</ClCompile>
......@@ -53,6 +56,9 @@
<ClInclude Include="..\include\isccfg\grammar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isccfg\kaspconf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\isccfg\log.h">
<Filter>Header Files</Filter>
</ClInclude>
......@@ -63,4 +69,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -116,6 +116,7 @@
<ItemGroup>
<ClCompile Include="..\aclconf.c" />
<ClCompile Include="..\dnsconf.c" />
<ClCompile Include="..\kaspconf.c" />
<ClCompile Include="..\log.c" />
<ClCompile Include="..\namedconf.c" />
<ClCompile Include="..\parser.c" />
......@@ -127,6 +128,7 @@
<ClInclude Include="..\include\isccfg\dnsconf.h" />
<ClInclude Include="..\include\isccfg\cfg.h" />
<ClInclude Include="..\include\isccfg\grammar.h" />
<ClInclude Include="..\include\isccfg\kaspconf.h" />
<ClInclude Include="..\include\isccfg\log.h" />
<ClInclude Include="..\include\isccfg\namedconf.h" />
<ClInclude Include="..\include\isccfg\version.h" />
......
......@@ -2437,9 +2437,11 @@
./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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment