Merge branch 'matthijs-dnssec-policy-defaults-in-config-dot-c-v9_18' into 'v9_18'

[v9_18] Move built-in dnssec-policies into defaultconf

See merge request isc-projects/bind9!6493
This commit is contained in:
Matthijs Mekking 2022-06-28 13:30:26 +00:00
commit 1330732872
14 changed files with 516 additions and 306 deletions

View file

@ -1,3 +1,6 @@
5910. [cleanup] Move built-in dnssec-policies into the defaultconf.
These are now printed with 'named -C'. [GL !6467]
5909. [bug] The server-side destination port was missing from dnstap
captures of client traffic. [GL #3309]

View file

@ -29,6 +29,7 @@
#include <isc/util.h>
#include <dns/fixedname.h>
#include <dns/kasp.h>
#include <dns/name.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
@ -294,6 +295,32 @@ view \"_bind\" chaos {\n\
database \"_builtin id\";\n\
};\n\
};\n\
"
"#\n\
# Built-in DNSSEC key and signing policies.\n\
#\n\
dnssec-policy \"default\" {\n\
keys {\n\
csk key-directory lifetime unlimited algorithm 13;\n\
};\n\
\n\
dnskey-ttl " DNS_KASP_KEY_TTL ";\n\
publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\
retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\
purge-keys " DNS_KASP_PURGE_KEYS "; \n\
signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\
signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\
signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\
max-zone-ttl " DNS_KASP_ZONE_MAXTTL "; \n\
zone-propagation-delay " DNS_KASP_ZONE_PROPDELAY "; \n\
parent-ds-ttl " DNS_KASP_DS_TTL "; \n\
parent-propagation-delay " DNS_KASP_PARENT_PROPDELAY "; \n\
};\n\
\n\
dnssec-policy \"insecure\" {\n\
keys { };\n\
};\n\
\n\
"
"#\n\
# Default trusted key(s), used if \n\

View file

@ -8479,6 +8479,7 @@ load_configuration(const char *filename, named_server_t *server,
const cfg_obj_t *kasps;
dns_kasp_t *kasp = NULL;
dns_kasp_t *kasp_next = NULL;
dns_kasp_t *default_kasp = NULL;
dns_kasplist_t tmpkasplist, kasplist;
const cfg_obj_t *views;
dns_view_t *view = NULL;
@ -9204,6 +9205,32 @@ load_configuration(const char *filename, named_server_t *server,
*/
(void)configure_session_key(maps, server, named_g_mctx, first_time);
/*
* Create the built-in kasp policies ("default", "insecure").
*/
kasps = NULL;
(void)cfg_map_get(named_g_config, "dnssec-policy", &kasps);
for (element = cfg_list_first(kasps); element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *kconfig = cfg_listelt_value(element);
kasp = NULL;
CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx,
named_g_lctx, &kasplist, &kasp));
INSIST(kasp != NULL);
dns_kasp_freeze(kasp);
/* Insist that the first built-in policy is the default one. */
if (default_kasp == NULL) {
INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0);
dns_kasp_attach(kasp, &default_kasp);
}
dns_kasp_detach(&kasp);
}
INSIST(default_kasp != NULL);
/*
* Create the DNSSEC key and signing policies (KASP).
*/
@ -9214,29 +9241,14 @@ load_configuration(const char *filename, named_server_t *server,
{
cfg_obj_t *kconfig = cfg_listelt_value(element);
kasp = NULL;
CHECK(cfg_kasp_fromconfig(kconfig, NULL, named_g_mctx,
CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx,
named_g_lctx, &kasplist, &kasp));
INSIST(kasp != NULL);
dns_kasp_freeze(kasp);
dns_kasp_detach(&kasp);
}
/*
* Create the built-in kasp policies ("default", "insecure").
*/
kasp = NULL;
CHECK(cfg_kasp_fromconfig(NULL, "default", named_g_mctx, named_g_lctx,
&kasplist, &kasp));
INSIST(kasp != NULL);
dns_kasp_freeze(kasp);
dns_kasp_detach(&kasp);
kasp = NULL;
CHECK(cfg_kasp_fromconfig(NULL, "insecure", named_g_mctx, named_g_lctx,
&kasplist, &kasp));
INSIST(kasp != NULL);
dns_kasp_freeze(kasp);
dns_kasp_detach(&kasp);
dns_kasp_detach(&default_kasp);
tmpkasplist = server->kasplist;
server->kasplist = kasplist;
kasplist = tmpkasplist;

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-policy "test" {
dnskey-ttl xPT1H;
};

View file

@ -105,17 +105,17 @@ struct dns_kasp {
#define DNS_KASP_VALID(kasp) ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC)
/* Defaults */
#define DNS_KASP_SIG_REFRESH (86400 * 5)
#define DNS_KASP_SIG_VALIDITY (86400 * 14)
#define DNS_KASP_SIG_VALIDITY_DNSKEY (86400 * 14)
#define DNS_KASP_KEY_TTL (3600)
#define DNS_KASP_DS_TTL (86400)
#define DNS_KASP_PUBLISH_SAFETY (3600)
#define DNS_KASP_PURGE_KEYS (86400 * 90)
#define DNS_KASP_RETIRE_SAFETY (3600)
#define DNS_KASP_ZONE_MAXTTL (86400)
#define DNS_KASP_ZONE_PROPDELAY (300)
#define DNS_KASP_PARENT_PROPDELAY (3600)
#define DNS_KASP_SIG_REFRESH "P5D"
#define DNS_KASP_SIG_VALIDITY "P14D"
#define DNS_KASP_SIG_VALIDITY_DNSKEY "P14D"
#define DNS_KASP_KEY_TTL "3600"
#define DNS_KASP_DS_TTL "86400"
#define DNS_KASP_PUBLISH_SAFETY "3600"
#define DNS_KASP_PURGE_KEYS "P90D"
#define DNS_KASP_RETIRE_SAFETY "3600"
#define DNS_KASP_ZONE_MAXTTL "86400"
#define DNS_KASP_ZONE_PROPDELAY "300"
#define DNS_KASP_PARENT_PROPDELAY "3600"
/* Key roles */
#define DNS_KASP_KEY_ROLE_KSK 0x01

View file

@ -30,44 +30,26 @@
isc_result_t
dns_kasp_create(isc_mem_t *mctx, const char *name, dns_kasp_t **kaspp) {
dns_kasp_t *kasp;
dns_kasp_t k = {
.magic = DNS_KASP_MAGIC,
};
REQUIRE(name != NULL);
REQUIRE(kaspp != NULL && *kaspp == NULL);
kasp = isc_mem_get(mctx, sizeof(*kasp));
*kasp = k;
kasp->mctx = NULL;
isc_mem_attach(mctx, &kasp->mctx);
kasp->name = isc_mem_strdup(mctx, name);
isc_mutex_init(&kasp->lock);
kasp->frozen = false;
isc_refcount_init(&kasp->references, 1);
ISC_LINK_INIT(kasp, link);
kasp->signatures_refresh = DNS_KASP_SIG_REFRESH;
kasp->signatures_validity = DNS_KASP_SIG_VALIDITY;
kasp->signatures_validity_dnskey = DNS_KASP_SIG_VALIDITY_DNSKEY;
ISC_LIST_INIT(kasp->keys);
kasp->dnskey_ttl = DNS_KASP_KEY_TTL;
kasp->publish_safety = DNS_KASP_PUBLISH_SAFETY;
kasp->retire_safety = DNS_KASP_RETIRE_SAFETY;
kasp->purge_keys = DNS_KASP_PURGE_KEYS;
kasp->zone_max_ttl = DNS_KASP_ZONE_MAXTTL;
kasp->zone_propagation_delay = DNS_KASP_ZONE_PROPDELAY;
kasp->parent_ds_ttl = DNS_KASP_DS_TTL;
kasp->parent_propagation_delay = DNS_KASP_PARENT_PROPDELAY;
kasp->nsec3 = false;
kasp->magic = DNS_KASP_MAGIC;
*kaspp = kasp;
return (ISC_R_SUCCESS);
}

View file

@ -131,12 +131,12 @@ keymgr_settime_remove(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
dns_kasp_retiresafety(kasp);
}
remove = ksk_remove > zsk_remove ? ksk_remove : zsk_remove;
remove = ISC_MAX(ksk_remove, zsk_remove);
dst_key_settime(key->key, DST_TIME_DELETE, remove);
}
/*
* Set the SyncPublish time (when the DS may be submitted to the parent)
* Set the SyncPublish time (when the DS may be submitted to the parent).
*
*/
static void
@ -250,7 +250,7 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
dns_kasp_zonepropagationdelay(kasp);
}
syncpub = syncpub1 > syncpub2 ? syncpub1 : syncpub2;
syncpub = ISC_MAX(syncpub1, syncpub2);
dst_key_settime(key->key, DST_TIME_SYNCPUBLISH,
syncpub);
}

View file

@ -6,6 +6,7 @@ libisccfg_ladir = $(includedir)/isccfg
libisccfg_la_HEADERS = \
include/isccfg/aclconf.h \
include/isccfg/cfg.h \
include/isccfg/duration.h \
include/isccfg/grammar.h \
include/isccfg/kaspconf.h \
include/isccfg/log.h \
@ -15,6 +16,7 @@ libisccfg_la_SOURCES = \
$(libisccfg_la_HEADERS) \
aclconf.c \
dnsconf.c \
duration.c \
kaspconf.c \
log.c \
namedconf.c \

202
lib/isccfg/duration.c Normal file
View file

@ -0,0 +1,202 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <isc/buffer.h>
#include <isc/parseint.h>
#include <isc/print.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/ttl.h>
#include <isccfg/duration.h>
/*
* isccfg_duration_fromtext initially taken from OpenDNSSEC code base.
* Modified to fit the BIND 9 code.
*/
isc_result_t
isccfg_duration_fromtext(isc_textregion_t *source,
isccfg_duration_t *duration) {
char buf[DURATION_MAXLEN];
char *P, *X, *T, *W, *str;
bool not_weeks = false;
int i;
/*
* Copy the buffer as it may not be NULL terminated.
* Anyone having a duration longer than 63 characters is crazy.
*/
if (source->length > sizeof(buf) - 1) {
return (ISC_R_BADNUMBER);
}
/* Copy source->length bytes and NULL terminate. */
snprintf(buf, sizeof(buf), "%.*s", (int)source->length, source->base);
str = buf;
/* Clear out duration. */
for (i = 0; i < 7; i++) {
duration->parts[i] = 0;
}
duration->iso8601 = false;
duration->unlimited = false;
/* Every duration starts with 'P' */
if (toupper(str[0]) != 'P') {
return (ISC_R_BADNUMBER);
}
P = str;
/* Record the time indicator. */
T = strpbrk(str, "Tt");
/* Record years. */
X = strpbrk(str, "Yy");
if (X != NULL) {
duration->parts[0] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record months. */
X = strpbrk(str, "Mm");
/*
* M could be months or minutes. This is months if there is no time
* part, or this M indicator is before the time indicator.
*/
if (X != NULL && (T == NULL || (size_t)(X - P) < (size_t)(T - P))) {
duration->parts[1] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record days. */
X = strpbrk(str, "Dd");
if (X != NULL) {
duration->parts[3] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Time part? */
if (T != NULL) {
str = T;
not_weeks = true;
}
/* Record hours. */
X = strpbrk(str, "Hh");
if (X != NULL && T != NULL) {
duration->parts[4] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record minutes. */
X = strpbrk(str, "Mm");
/*
* M could be months or minutes. This is minutes if there is a time
* part and the M indicator is behind the time indicator.
*/
if (X != NULL && T != NULL && (size_t)(X - P) > (size_t)(T - P)) {
duration->parts[5] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record seconds. */
X = strpbrk(str, "Ss");
if (X != NULL && T != NULL) {
duration->parts[6] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Or is the duration configured in weeks? */
W = strpbrk(buf, "Ww");
if (W != NULL) {
if (not_weeks) {
/* Mix of weeks and other indicators is not allowed */
return (ISC_R_BADNUMBER);
} else {
duration->parts[2] = atoi(str + 1);
str = W;
}
}
/* Deal with trailing garbage. */
if (str[1] != '\0') {
return (ISC_R_BADNUMBER);
}
duration->iso8601 = true;
return (ISC_R_SUCCESS);
}
isc_result_t
isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration) {
isc_result_t result;
REQUIRE(duration != NULL);
duration->unlimited = false;
result = isccfg_duration_fromtext(source, duration);
if (result == ISC_R_BADNUMBER) {
/* Fallback to dns_ttl_fromtext. */
uint32_t ttl;
result = dns_ttl_fromtext(source, &ttl);
if (result == ISC_R_SUCCESS) {
/*
* With dns_ttl_fromtext() the information on optional
* units is lost, and is treated as seconds from now on.
*/
duration->iso8601 = false;
duration->parts[6] = ttl;
}
}
return (result);
}
uint32_t
isccfg_duration_toseconds(const isccfg_duration_t *duration) {
uint32_t seconds = 0;
REQUIRE(duration != NULL);
seconds += duration->parts[6]; /* Seconds */
seconds += duration->parts[5] * 60; /* Minutes */
seconds += duration->parts[4] * 3600; /* Hours */
seconds += duration->parts[3] * 86400; /* Days */
seconds += duration->parts[2] * 86400 * 7; /* Weeks */
/*
* The below additions are not entirely correct
* because days may very per month and per year.
*/
seconds += duration->parts[1] * 86400 * 31; /* Months */
seconds += duration->parts[0] * 86400 * 365; /* Years */
return (seconds);
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
/*! \file */
#include <inttypes.h>
#include <stdbool.h>
#include <isc/lang.h>
#include <isc/types.h>
ISC_LANG_BEGINDECLS
#define DURATION_MAXLEN 64
/*%
* A configuration object to store ISO 8601 durations.
*/
typedef struct isccfg_duration {
/*
* The duration is stored in multiple parts:
* [0] Years
* [1] Months
* [2] Weeks
* [3] Days
* [4] Hours
* [5] Minutes
* [6] Seconds
*/
uint32_t parts[7];
bool iso8601;
bool unlimited;
} isccfg_duration_t;
isc_result_t
isccfg_duration_fromtext(isc_textregion_t *source, isccfg_duration_t *duration);
/*%<
* Converts an ISO 8601 duration style value.
*
* Returns:
*\li ISC_R_SUCCESS
*\li DNS_R_BADNUMBER
*/
isc_result_t
isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration);
/*%<
* Converts a duration string to a ISO 8601 duration.
* If the string does not start with a P (or p), fall back to TTL-style value.
* In that case the duration will be treated in seconds only.
*
* Returns:
*\li ISC_R_SUCCESS
*\li DNS_R_BADNUMBER
*\li DNS_R_BADTTL
*/
uint32_t
isccfg_duration_toseconds(const isccfg_duration_t *duration);
/*%<
* Converts an ISO 8601 duration to seconds.
* The conversion is approximate:
* - Months will be treated as 31 days.
* - Years will be treated as 365 days.
*
* Returns:
*\li The duration in seconds.
*/
ISC_LANG_ENDDECLS

View file

@ -25,6 +25,7 @@
#include <isc/types.h>
#include <isccfg/cfg.h>
#include <isccfg/duration.h>
/*
* Definitions shared between the configuration parser
@ -77,11 +78,8 @@ typedef struct cfg_clausedef cfg_clausedef_t;
typedef struct cfg_tuplefielddef cfg_tuplefielddef_t;
typedef struct cfg_printer cfg_printer_t;
typedef ISC_LIST(cfg_listelt_t) cfg_list_t;
typedef struct cfg_map cfg_map_t;
typedef struct cfg_rep cfg_rep_t;
typedef struct cfg_duration cfg_duration_t;
#define CFG_DURATION_MAXLEN 64
typedef struct cfg_map cfg_map_t;
typedef struct cfg_rep cfg_rep_t;
/*
* Function types for configuration object methods
@ -155,25 +153,6 @@ struct cfg_netprefix {
unsigned int prefixlen;
};
/*%
* A configuration object to store ISO 8601 durations.
*/
struct cfg_duration {
/*
* The duration is stored in multiple parts:
* [0] Years
* [1] Months
* [2] Weeks
* [3] Days
* [4] Hours
* [5] Minutes
* [6] Seconds
*/
uint32_t parts[7];
bool iso8601;
bool unlimited;
};
/*%
* A configuration data representation.
*/
@ -202,8 +181,8 @@ struct cfg_obj {
isc_sockaddr_t sockaddr;
isc_dscp_t dscp;
} sockaddrdscp;
cfg_netprefix_t netprefix;
cfg_duration_t duration;
cfg_netprefix_t netprefix;
isccfg_duration_t duration;
} value;
isc_refcount_t references; /*%< reference counter */
const char *file;

View file

@ -15,8 +15,6 @@
#include <isc/lang.h>
#include <dns/types.h>
#include <isccfg/cfg.h>
/***
@ -26,14 +24,15 @@
ISC_LANG_BEGINDECLS
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);
cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
isc_mem_t *mctx, isc_log_t *logctx,
dns_kasplist_t *kasplist, dns_kasp_t **kaspp);
/*%<
* Create and configure a KASP. If 'config' is NULL, a built-in configuration
* is used, referred to by 'name'. 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.
* Create and configure a KASP. If 'default_kasp' is not NULL, the built-in
* default configuration is used to set values that are not explicitly set in
* the policy. 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:
*

View file

@ -20,6 +20,7 @@
#include <isc/region.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
#include <dns/kasp.h>
@ -27,8 +28,10 @@
#include <dns/log.h>
#include <dns/nsec3.h>
#include <dns/secalg.h>
#include <dns/ttl.h>
#include <isccfg/cfg.h>
#include <isccfg/duration.h>
#include <isccfg/kaspconf.h>
#include <isccfg/namedconf.h>
@ -50,18 +53,37 @@ confget(cfg_obj_t const *const *maps, const char *name, const cfg_obj_t **obj) {
}
}
/*
* Utility function for parsing durations from string.
*/
static uint32_t
parse_duration(const char *str) {
uint32_t time = 0;
isccfg_duration_t duration;
isc_result_t result;
isc_textregion_t tr;
DE_CONST(str, tr.base);
tr.length = strlen(tr.base);
result = isccfg_parse_duration(&tr, &duration);
if (result == ISC_R_SUCCESS) {
time = isccfg_duration_toseconds(&duration);
}
return (time);
}
/*
* Utility function for configuring durations.
*/
static uint32_t
get_duration(const cfg_obj_t **maps, const char *option, uint32_t dfl) {
get_duration(const cfg_obj_t **maps, const char *option, const char *dfl) {
const cfg_obj_t *obj;
isc_result_t result;
obj = NULL;
result = confget(maps, option, &obj);
if (result == ISC_R_NOTFOUND) {
return (dfl);
return (parse_duration(dfl));
}
INSIST(result == ISC_R_SUCCESS);
return (cfg_obj_asduration(obj));
@ -278,9 +300,9 @@ cfg_nsec3param_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
}
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) {
cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
isc_mem_t *mctx, isc_log_t *logctx,
dns_kasplist_t *kasplist, dns_kasp_t **kaspp) {
isc_result_t result;
const cfg_obj_t *maps[2];
const cfg_obj_t *koptions = NULL;
@ -291,16 +313,21 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
dns_kasp_t *kasp = NULL;
size_t i = 0;
uint32_t sigrefresh = 0, sigvalidity = 0;
uint32_t dnskeyttl = 0, dsttl = 0, maxttl = 0;
uint32_t publishsafety = 0, retiresafety = 0;
uint32_t zonepropdelay = 0, parentpropdelay = 0;
uint32_t ipub = 0, iret = 0;
uint32_t ksk_min_lifetime = 0, zsk_min_lifetime = 0;
REQUIRE(config != NULL);
REQUIRE(kaspp != NULL && *kaspp == NULL);
kaspname = (name == NULL)
? cfg_obj_asstring(cfg_tuple_get(config, "name"))
: name;
kaspname = cfg_obj_asstring(cfg_tuple_get(config, "name"));
INSIST(kaspname != NULL);
cfg_obj_log(config, logctx, ISC_LOG_DEBUG(1),
"dnssec-policy: load policy '%s'", kaspname);
result = dns_kasplist_find(kasplist, kaspname, &kasp);
if (result == ISC_R_SUCCESS) {
@ -352,10 +379,11 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
sigvalidity = get_duration(maps, "signatures-validity",
DNS_KASP_SIG_VALIDITY);
if (sigrefresh >= (sigvalidity * 0.9)) {
cfg_obj_log(config, logctx, ISC_LOG_ERROR,
"dnssec-policy: policy '%s' signatures-refresh "
"must be at most 90%% of the signatures-validity",
kaspname);
cfg_obj_log(
config, logctx, ISC_LOG_ERROR,
"dnssec-policy: policy '%s' signatures-refresh must be "
"at most 90%% of the signatures-validity",
kaspname);
result = ISC_R_FAILURE;
}
dns_kasp_setsigvalidity(kasp, sigvalidity);
@ -364,34 +392,43 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
goto cleanup;
}
/* Configuration: Zone settings */
maxttl = get_duration(maps, "max-zone-ttl", DNS_KASP_ZONE_MAXTTL);
dns_kasp_setzonemaxttl(kasp, maxttl);
zonepropdelay = get_duration(maps, "zone-propagation-delay",
DNS_KASP_ZONE_PROPDELAY);
dns_kasp_setzonepropagationdelay(kasp, zonepropdelay);
/* Configuration: Parent settings */
dsttl = get_duration(maps, "parent-ds-ttl", DNS_KASP_DS_TTL);
dns_kasp_setdsttl(kasp, dsttl);
parentpropdelay = get_duration(maps, "parent-propagation-delay",
DNS_KASP_PARENT_PROPDELAY);
dns_kasp_setparentpropagationdelay(kasp, parentpropdelay);
/* Configuration: Keys */
dns_kasp_setdnskeyttl(
kasp, get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL));
dns_kasp_setpublishsafety(kasp, get_duration(maps, "publish-safety",
DNS_KASP_PUBLISH_SAFETY));
dns_kasp_setretiresafety(kasp, get_duration(maps, "retire-safety",
DNS_KASP_RETIRE_SAFETY));
dnskeyttl = get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL);
dns_kasp_setdnskeyttl(kasp, dnskeyttl);
publishsafety = get_duration(maps, "publish-safety",
DNS_KASP_PUBLISH_SAFETY);
dns_kasp_setpublishsafety(kasp, publishsafety);
retiresafety = get_duration(maps, "retire-safety",
DNS_KASP_RETIRE_SAFETY);
dns_kasp_setretiresafety(kasp, retiresafety);
dns_kasp_setpurgekeys(
kasp, get_duration(maps, "purge-keys", DNS_KASP_PURGE_KEYS));
ipub = get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL) +
get_duration(maps, "publish-safety", DNS_KASP_PUBLISH_SAFETY) +
get_duration(maps, "zone-propagation-delay",
DNS_KASP_ZONE_PROPDELAY);
iret = get_duration(maps, "parent-ds-ttl", DNS_KASP_DS_TTL) +
get_duration(maps, "retire-safety", DNS_KASP_RETIRE_SAFETY) +
get_duration(maps, "parent-propagation-delay",
DNS_KASP_PARENT_PROPDELAY);
ipub = dnskeyttl + publishsafety + zonepropdelay;
iret = dsttl + retiresafety + parentpropdelay;
ksk_min_lifetime = ISC_MAX(ipub, iret);
iret = (sigvalidity - sigrefresh) +
get_duration(maps, "max-zone-ttl", DNS_KASP_ZONE_MAXTTL) +
get_duration(maps, "retire-safety", DNS_KASP_RETIRE_SAFETY) +
get_duration(maps, "zone-propagation-delay",
DNS_KASP_ZONE_PROPDELAY);
iret = (sigvalidity - sigrefresh) + maxttl + retiresafety +
zonepropdelay;
zsk_min_lifetime = ISC_MAX(ipub, iret);
(void)confget(maps, "keys", &keys);
@ -411,7 +448,6 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
goto cleanup;
}
}
INSIST(!(dns_kasp_keylist_empty(kasp)));
dns_kasp_freeze(kasp);
for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
kkey = ISC_LIST_NEXT(kkey, link))
@ -464,23 +500,55 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
} else if (strcmp(kaspname, "insecure") == 0) {
/* "dnssec-policy insecure": key list must be empty */
INSIST(strcmp(kaspname, "insecure") == 0);
INSIST(dns_kasp_keylist_empty(kasp));
} else {
/* No keys clause configured, use the "default". */
result = cfg_kaspkey_fromconfig(NULL, kasp, logctx, 0, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
} else if (default_kasp) {
dns_kasp_key_t *key, *new_key;
/*
* If there are no specific keys configured in the policy,
* inherit from the default policy (except for the built-in
* "insecure" policy).
*/
for (key = ISC_LIST_HEAD(dns_kasp_keys(default_kasp));
key != NULL; key = ISC_LIST_NEXT(key, link))
{
/* Create a new key reference. */
new_key = NULL;
result = dns_kasp_key_create(kasp, &new_key);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
if (dns_kasp_key_ksk(key)) {
new_key->role |= DNS_KASP_KEY_ROLE_KSK;
}
if (dns_kasp_key_zsk(key)) {
new_key->role |= DNS_KASP_KEY_ROLE_ZSK;
}
new_key->lifetime = dns_kasp_key_lifetime(key);
new_key->algorithm = dns_kasp_key_algorithm(key);
new_key->length = dns_kasp_key_size(key);
dns_kasp_addkey(kasp, new_key);
}
}
if (strcmp(kaspname, "insecure") == 0) {
/* "dnssec-policy insecure": key list must be empty */
INSIST(dns_kasp_keylist_empty(kasp));
} else if (default_kasp != NULL) {
/* There must be keys configured. */
INSIST(!(dns_kasp_keylist_empty(kasp)));
}
/* Configuration: NSEC3 */
(void)confget(maps, "nsec3param", &nsec3);
if (nsec3 == NULL) {
dns_kasp_setnsec3(kasp, false);
if (default_kasp != NULL && dns_kasp_nsec3(default_kasp)) {
dns_kasp_setnsec3param(
kasp, dns_kasp_nsec3iter(default_kasp),
(dns_kasp_nsec3flags(default_kasp) == 0x01),
dns_kasp_nsec3saltlen(default_kasp));
} else {
dns_kasp_setnsec3(kasp, false);
}
} else {
dns_kasp_setnsec3(kasp, true);
result = cfg_nsec3param_fromconfig(nsec3, kasp, logctx);
@ -489,20 +557,6 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
}
}
/* Configuration: Zone settings */
dns_kasp_setzonemaxttl(
kasp, get_duration(maps, "max-zone-ttl", DNS_KASP_ZONE_MAXTTL));
dns_kasp_setzonepropagationdelay(
kasp, get_duration(maps, "zone-propagation-delay",
DNS_KASP_ZONE_PROPDELAY));
/* Configuration: Parent settings */
dns_kasp_setdsttl(kasp,
get_duration(maps, "parent-ds-ttl", DNS_KASP_DS_TTL));
dns_kasp_setparentpropagationdelay(
kasp, get_duration(maps, "parent-propagation-delay",
DNS_KASP_PARENT_PROPDELAY));
/* Append it to the list for future lookups. */
ISC_LIST_APPEND(*kasplist, kasp, link);
INSIST(!(ISC_LIST_EMPTY(*kasplist)));

View file

@ -12,9 +12,6 @@
*/
/*
* duration_fromtext initially taken from OpenDNSSEC code base.
* Modified to fit the BIND 9 code.
*
* Copyright (c) 2009-2018 NLNet Labs.
* All rights reserved.
*
@ -1033,12 +1030,12 @@ numlen(uint32_t num) {
*/
void
cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
char buf[CFG_DURATION_MAXLEN];
char buf[DURATION_MAXLEN];
char *str;
const char *indicators = "YMWDHMS";
int count, i;
int durationlen[7];
cfg_duration_t duration;
isccfg_duration_t duration;
/*
* D ? The duration has a date part.
* T ? The duration has a time part.
@ -1090,7 +1087,7 @@ cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (T) {
count++;
}
INSIST(count < CFG_DURATION_MAXLEN);
INSIST(count < DURATION_MAXLEN);
/* Now print the duration. */
for (i = 0; i < 6; i++) {
@ -1119,7 +1116,7 @@ cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj) {
void
cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_duration_t duration;
isccfg_duration_t duration;
REQUIRE(pctx != NULL);
REQUIRE(obj != NULL);
@ -1142,163 +1139,17 @@ cfg_obj_isduration(const cfg_obj_t *obj) {
uint32_t
cfg_obj_asduration(const cfg_obj_t *obj) {
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_duration);
uint32_t duration = 0;
duration += obj->value.duration.parts[6]; /* Seconds */
duration += obj->value.duration.parts[5] * 60; /* Minutes */
duration += obj->value.duration.parts[4] * 3600; /* Hours */
duration += obj->value.duration.parts[3] * 86400; /* Days */
duration += obj->value.duration.parts[2] * 86400 * 7; /* Weaks */
/*
* The below additions are not entirely correct
* because days may very per month and per year.
*/
duration += obj->value.duration.parts[1] * 86400 * 31; /* Months */
duration += obj->value.duration.parts[0] * 86400 * 365; /* Years */
return (duration);
}
static isc_result_t
duration_fromtext(isc_textregion_t *source, cfg_duration_t *duration) {
char buf[CFG_DURATION_MAXLEN];
char *P, *X, *T, *W, *str;
bool not_weeks = false;
int i;
/*
* Copy the buffer as it may not be NULL terminated.
* Anyone having a duration longer than 63 characters is crazy.
*/
if (source->length > sizeof(buf) - 1) {
return (ISC_R_BADNUMBER);
}
/* Copy source->length bytes and NULL terminate. */
snprintf(buf, sizeof(buf), "%.*s", (int)source->length, source->base);
str = buf;
/* Clear out duration. */
for (i = 0; i < 7; i++) {
duration->parts[i] = 0;
}
/* Every duration starts with 'P' */
P = strpbrk(str, "Pp");
if (P == NULL) {
return (ISC_R_BADNUMBER);
}
/* Record the time indicator. */
T = strpbrk(str, "Tt");
/* Record years. */
X = strpbrk(str, "Yy");
if (X != NULL) {
duration->parts[0] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record months. */
X = strpbrk(str, "Mm");
/*
* M could be months or minutes. This is months if there is no time
* part, or this M indicator is before the time indicator.
*/
if (X != NULL && (T == NULL || (size_t)(X - P) < (size_t)(T - P))) {
duration->parts[1] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record days. */
X = strpbrk(str, "Dd");
if (X != NULL) {
duration->parts[3] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Time part? */
if (T != NULL) {
str = T;
not_weeks = true;
}
/* Record hours. */
X = strpbrk(str, "Hh");
if (X != NULL && T != NULL) {
duration->parts[4] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record minutes. */
X = strpbrk(str, "Mm");
/*
* M could be months or minutes. This is minutes if there is a time
* part and the M indicator is behind the time indicator.
*/
if (X != NULL && T != NULL && (size_t)(X - P) > (size_t)(T - P)) {
duration->parts[5] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Record seconds. */
X = strpbrk(str, "Ss");
if (X != NULL && T != NULL) {
duration->parts[6] = atoi(str + 1);
str = X;
not_weeks = true;
}
/* Or is the duration configured in weeks? */
W = strpbrk(buf, "Ww");
if (W != NULL) {
if (not_weeks) {
/* Mix of weeks and other indicators is not allowed */
return (ISC_R_BADNUMBER);
} else {
duration->parts[2] = atoi(str + 1);
str = W;
}
}
/* Deal with trailing garbage. */
if (str[1] != '\0') {
return (ISC_R_BADNUMBER);
}
return (ISC_R_SUCCESS);
return isccfg_duration_toseconds(&(obj->value.duration));
}
static isc_result_t
parse_duration(cfg_parser_t *pctx, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
cfg_duration_t duration;
isccfg_duration_t duration;
duration.unlimited = false;
if (toupper((unsigned char)TOKEN_STRING(pctx)[0]) == 'P') {
result = duration_fromtext(&pctx->token.value.as_textregion,
&duration);
duration.iso8601 = true;
} else {
uint32_t ttl;
result = dns_ttl_fromtext(&pctx->token.value.as_textregion,
&ttl);
/*
* With dns_ttl_fromtext() the information on optional units.
* is lost, and is treated as seconds from now on.
*/
for (int i = 0; i < 6; i++) {
duration.parts[i] = 0;
}
duration.parts[6] = ttl;
duration.iso8601 = false;
}
result = isccfg_parse_duration(&pctx->token.value.as_textregion,
&duration);
if (result == ISC_R_RANGE) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
@ -1346,7 +1197,7 @@ cfg_parse_duration_or_unlimited(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
cfg_duration_t duration;
isccfg_duration_t duration;
UNUSED(type);