2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-27 04:28:33 +00:00
bind/lib/dns/kasp.c
Matthijs Mekking 32686beabc Change default TTLsig to one week
Commit dc6dafdad1bce4c59bec0dbc355650c384cfc4d9 allows larger TTL values
in zones that go insecure, and ignores the maximum zone TTL.

This means that if you use TTL values larger than 1 day in your zone,
your zone runs the risk of going bogus before it moves safely to
insecure.

Most resolvers by default cap the maximum TTL that they cache RRsets,
at one day (Unbound, Knot, PowerDNS) so that is fine. However, BIND 9's
default is one week.

Change the default TTLsig to one week, so that also for BIND 9
resolvers in the default cases responses for zones that are going
insecure will not be evaluated as bogus.

This change does mean that when unsigning your zone, it will take six
days longer to safely go insecure, regardless of what TTL values you
use in the zone.
2023-08-02 11:16:50 +02:00

594 lines
11 KiB
C

/*
* 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 <string.h>
#include <isc/assertions.h>
#include <isc/buffer.h>
#include <isc/file.h>
#include <isc/hex.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/util.h>
#include <dns/kasp.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dst/dst.h>
/* Default TTLsig (maximum zone ttl) */
#define DEFAULT_TTLSIG 604800 /* one week */
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,
.digests = ISC_LIST_INITIALIZER,
.keys = ISC_LIST_INITIALIZER,
.link = ISC_LINK_INITIALIZER,
};
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);
isc_refcount_init(&kasp->references, 1);
*kaspp = kasp;
return (ISC_R_SUCCESS);
}
void
dns_kasp_attach(dns_kasp_t *source, dns_kasp_t **targetp) {
REQUIRE(DNS_KASP_VALID(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
static void
destroy(dns_kasp_t *kasp) {
dns_kasp_key_t *key, *key_next;
dns_kasp_digest_t *digest, *digest_next;
REQUIRE(!ISC_LINK_LINKED(kasp, link));
for (key = ISC_LIST_HEAD(kasp->keys); key != NULL; key = key_next) {
key_next = ISC_LIST_NEXT(key, link);
ISC_LIST_UNLINK(kasp->keys, key, link);
dns_kasp_key_destroy(key);
}
INSIST(ISC_LIST_EMPTY(kasp->keys));
for (digest = ISC_LIST_HEAD(kasp->digests); digest != NULL;
digest = digest_next)
{
digest_next = ISC_LIST_NEXT(digest, link);
ISC_LIST_UNLINK(kasp->digests, digest, link);
isc_mem_put(kasp->mctx, digest, sizeof(*digest));
}
INSIST(ISC_LIST_EMPTY(kasp->digests));
isc_mutex_destroy(&kasp->lock);
isc_mem_free(kasp->mctx, kasp->name);
isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp));
}
void
dns_kasp_detach(dns_kasp_t **kaspp) {
REQUIRE(kaspp != NULL && DNS_KASP_VALID(*kaspp));
dns_kasp_t *kasp = *kaspp;
*kaspp = NULL;
if (isc_refcount_decrement(&kasp->references) == 1) {
destroy(kasp);
}
}
const char *
dns_kasp_getname(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
return (kasp->name);
}
void
dns_kasp_freeze(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->frozen = true;
}
void
dns_kasp_thaw(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
kasp->frozen = false;
}
uint32_t
dns_kasp_signdelay(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->signatures_validity - kasp->signatures_refresh);
}
uint32_t
dns_kasp_sigrefresh(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->signatures_refresh);
}
void
dns_kasp_setsigrefresh(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->signatures_refresh = value;
}
uint32_t
dns_kasp_sigvalidity(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->signatures_validity);
}
void
dns_kasp_setsigvalidity(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->signatures_validity = value;
}
uint32_t
dns_kasp_sigvalidity_dnskey(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->signatures_validity_dnskey);
}
void
dns_kasp_setsigvalidity_dnskey(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->signatures_validity_dnskey = value;
}
dns_ttl_t
dns_kasp_dnskeyttl(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->dnskey_ttl);
}
void
dns_kasp_setdnskeyttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->dnskey_ttl = ttl;
}
uint32_t
dns_kasp_purgekeys(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->purge_keys);
}
void
dns_kasp_setpurgekeys(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->purge_keys = value;
}
uint32_t
dns_kasp_publishsafety(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->publish_safety);
}
void
dns_kasp_setpublishsafety(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->publish_safety = value;
}
uint32_t
dns_kasp_retiresafety(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->retire_safety);
}
void
dns_kasp_setretiresafety(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->retire_safety = value;
}
bool
dns_kasp_inlinesigning(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->inline_signing);
}
void
dns_kasp_setinlinesigning(dns_kasp_t *kasp, bool value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->inline_signing = value;
}
dns_ttl_t
dns_kasp_zonemaxttl(dns_kasp_t *kasp, bool fallback) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
if (kasp->zone_max_ttl == 0 && fallback) {
return (DEFAULT_TTLSIG);
}
return (kasp->zone_max_ttl);
}
void
dns_kasp_setzonemaxttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->zone_max_ttl = ttl;
}
uint32_t
dns_kasp_zonepropagationdelay(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->zone_propagation_delay);
}
void
dns_kasp_setzonepropagationdelay(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->zone_propagation_delay = value;
}
dns_ttl_t
dns_kasp_dsttl(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->parent_ds_ttl);
}
void
dns_kasp_setdsttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->parent_ds_ttl = ttl;
}
uint32_t
dns_kasp_parentpropagationdelay(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->parent_propagation_delay);
}
void
dns_kasp_setparentpropagationdelay(dns_kasp_t *kasp, uint32_t value) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
kasp->parent_propagation_delay = value;
}
isc_result_t
dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp) {
dns_kasp_t *kasp = NULL;
REQUIRE(kaspp != NULL && *kaspp == NULL);
if (list == NULL) {
return (ISC_R_NOTFOUND);
}
for (kasp = ISC_LIST_HEAD(*list); kasp != NULL;
kasp = ISC_LIST_NEXT(kasp, link))
{
if (strcmp(kasp->name, name) == 0) {
break;
}
}
if (kasp == NULL) {
return (ISC_R_NOTFOUND);
}
dns_kasp_attach(kasp, kaspp);
return (ISC_R_SUCCESS);
}
dns_kasp_keylist_t
dns_kasp_keys(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->keys);
}
bool
dns_kasp_keylist_empty(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
return (ISC_LIST_EMPTY(kasp->keys));
}
void
dns_kasp_addkey(dns_kasp_t *kasp, dns_kasp_key_t *key) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
REQUIRE(key != NULL);
ISC_LIST_APPEND(kasp->keys, key, link);
}
isc_result_t
dns_kasp_key_create(dns_kasp_t *kasp, dns_kasp_key_t **keyp) {
dns_kasp_key_t *key;
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(keyp != NULL && *keyp == NULL);
key = isc_mem_get(kasp->mctx, sizeof(*key));
key->mctx = NULL;
isc_mem_attach(kasp->mctx, &key->mctx);
ISC_LINK_INIT(key, link);
key->lifetime = 0;
key->algorithm = 0;
key->length = -1;
key->role = 0;
*keyp = key;
return (ISC_R_SUCCESS);
}
void
dns_kasp_key_destroy(dns_kasp_key_t *key) {
REQUIRE(key != NULL);
isc_mem_putanddetach(&key->mctx, key, sizeof(*key));
}
uint32_t
dns_kasp_key_algorithm(dns_kasp_key_t *key) {
REQUIRE(key != NULL);
return (key->algorithm);
}
unsigned int
dns_kasp_key_size(dns_kasp_key_t *key) {
unsigned int size = 0;
unsigned int min = 0;
REQUIRE(key != NULL);
switch (key->algorithm) {
case DNS_KEYALG_RSASHA1:
case DNS_KEYALG_NSEC3RSASHA1:
case DNS_KEYALG_RSASHA256:
case DNS_KEYALG_RSASHA512:
min = (key->algorithm == DNS_KEYALG_RSASHA512) ? 1024 : 512;
if (key->length > -1) {
size = (unsigned int)key->length;
if (size < min) {
size = min;
}
if (size > 4096) {
size = 4096;
}
} else {
size = 2048;
}
break;
case DNS_KEYALG_ECDSA256:
size = 256;
break;
case DNS_KEYALG_ECDSA384:
size = 384;
break;
case DNS_KEYALG_ED25519:
size = 256;
break;
case DNS_KEYALG_ED448:
size = 456;
break;
default:
/* unsupported */
break;
}
return (size);
}
uint32_t
dns_kasp_key_lifetime(dns_kasp_key_t *key) {
REQUIRE(key != NULL);
return (key->lifetime);
}
bool
dns_kasp_key_ksk(dns_kasp_key_t *key) {
REQUIRE(key != NULL);
return (key->role & DNS_KASP_KEY_ROLE_KSK);
}
bool
dns_kasp_key_zsk(dns_kasp_key_t *key) {
REQUIRE(key != NULL);
return (key->role & DNS_KASP_KEY_ROLE_ZSK);
}
uint8_t
dns_kasp_nsec3iter(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
REQUIRE(kasp->nsec3);
return (kasp->nsec3param.iterations);
}
uint8_t
dns_kasp_nsec3flags(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
REQUIRE(kasp->nsec3);
if (kasp->nsec3param.optout) {
return (0x01);
}
return (0x00);
}
uint8_t
dns_kasp_nsec3saltlen(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
REQUIRE(kasp->nsec3);
return (kasp->nsec3param.saltlen);
}
bool
dns_kasp_nsec3(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
return kasp->nsec3;
}
void
dns_kasp_setnsec3(dns_kasp_t *kasp, bool nsec3) {
REQUIRE(kasp != NULL);
REQUIRE(!kasp->frozen);
kasp->nsec3 = nsec3;
}
void
dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout,
uint8_t saltlen) {
REQUIRE(kasp != NULL);
REQUIRE(!kasp->frozen);
REQUIRE(kasp->nsec3);
kasp->nsec3param.iterations = iter;
kasp->nsec3param.optout = optout;
kasp->nsec3param.saltlen = saltlen;
}
bool
dns_kasp_cdnskey(dns_kasp_t *kasp) {
REQUIRE(kasp != NULL);
REQUIRE(kasp->frozen);
return kasp->cdnskey;
}
void
dns_kasp_setcdnskey(dns_kasp_t *kasp, bool cdnskey) {
REQUIRE(kasp != NULL);
REQUIRE(!kasp->frozen);
kasp->cdnskey = cdnskey;
}
dns_kasp_digestlist_t
dns_kasp_digests(dns_kasp_t *kasp) {
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(kasp->frozen);
return (kasp->digests);
}
void
dns_kasp_adddigest(dns_kasp_t *kasp, dns_dsdigest_t alg) {
dns_kasp_digest_t *digest;
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(!kasp->frozen);
/* Suppress unsupported algorithms */
if (!dst_ds_digest_supported(alg)) {
return;
}
/* Suppress duplicates */
for (dns_kasp_digest_t *d = ISC_LIST_HEAD(kasp->digests); d != NULL;
d = ISC_LIST_NEXT(d, link))
{
if (d->digest == alg) {
return;
}
}
digest = isc_mem_get(kasp->mctx, sizeof(*digest));
digest->digest = alg;
ISC_LINK_INIT(digest, link);
ISC_LIST_APPEND(kasp->digests, digest, link);
}