mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-27 12:13:20 -04:00
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:
commit
1330732872
14 changed files with 516 additions and 306 deletions
3
CHANGES
3
CHANGES
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
16
bin/tests/system/checkconf/bad-duration.conf
Normal file
16
bin/tests/system/checkconf/bad-duration.conf
Normal 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;
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
202
lib/isccfg/duration.c
Normal 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);
|
||||
}
|
||||
83
lib/isccfg/include/isccfg/duration.h
Normal file
83
lib/isccfg/include/isccfg/duration.h
Normal 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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue