mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +00:00
Add a new option 'manual-mode' to 'dnssec-policy'. The intended use is that if it is enabled, it will not automatically move to the next state transition (RUMOURED, UNRETENTIVE), only after manual confirmation. The intended state transition should be logged.
684 lines
13 KiB
C
684 lines
13 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 <dst/dst.h>
|
|
|
|
/* Default TTLsig (maximum zone ttl) */
|
|
#define DEFAULT_TTLSIG 604800 /* one week */
|
|
|
|
void
|
|
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;
|
|
}
|
|
|
|
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) {
|
|
REQUIRE(!ISC_LINK_LINKED(kasp, link));
|
|
|
|
ISC_LIST_FOREACH(kasp->keys, key, link) {
|
|
ISC_LIST_UNLINK(kasp->keys, key, link);
|
|
dns_kasp_key_destroy(key);
|
|
}
|
|
INSIST(ISC_LIST_EMPTY(kasp->keys));
|
|
|
|
ISC_LIST_FOREACH(kasp->digests, 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_sigjitter(dns_kasp_t *kasp) {
|
|
REQUIRE(DNS_KASP_VALID(kasp));
|
|
REQUIRE(kasp->frozen);
|
|
|
|
return kasp->signatures_jitter;
|
|
}
|
|
|
|
void
|
|
dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value) {
|
|
REQUIRE(DNS_KASP_VALID(kasp));
|
|
REQUIRE(!kasp->frozen);
|
|
|
|
kasp->signatures_jitter = value;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
bool
|
|
dns_kasp_manualmode(dns_kasp_t *kasp) {
|
|
REQUIRE(DNS_KASP_VALID(kasp));
|
|
REQUIRE(kasp->frozen);
|
|
|
|
return kasp->manual_mode;
|
|
}
|
|
|
|
void
|
|
dns_kasp_setmanualmode(dns_kasp_t *kasp, bool value) {
|
|
REQUIRE(DNS_KASP_VALID(kasp));
|
|
REQUIRE(!kasp->frozen);
|
|
|
|
kasp->manual_mode = 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) {
|
|
REQUIRE(kaspp != NULL && *kaspp == NULL);
|
|
|
|
if (list == NULL) {
|
|
return ISC_R_NOTFOUND;
|
|
}
|
|
|
|
ISC_LIST_FOREACH(*list, kasp, link) {
|
|
if (strcmp(kasp->name, name) == 0) {
|
|
dns_kasp_attach(kasp, kaspp);
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return ISC_R_NOTFOUND;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
dns_kasp_key_create(dns_kasp_t *kasp, dns_kasp_key_t **keyp) {
|
|
dns_kasp_key_t *key = NULL;
|
|
dns_kasp_key_t k = { .tag_max = 0xffff, .length = -1 };
|
|
|
|
REQUIRE(DNS_KASP_VALID(kasp));
|
|
REQUIRE(keyp != NULL && *keyp == NULL);
|
|
|
|
key = isc_mem_get(kasp->mctx, sizeof(*key));
|
|
*key = k;
|
|
|
|
key->mctx = NULL;
|
|
isc_mem_attach(kasp->mctx, &key->mctx);
|
|
|
|
ISC_LINK_INIT(key, link);
|
|
|
|
*keyp = key;
|
|
}
|
|
|
|
void
|
|
dns_kasp_key_destroy(dns_kasp_key_t *key) {
|
|
REQUIRE(key != NULL);
|
|
|
|
if (key->keystore != NULL) {
|
|
dns_keystore_detach(&key->keystore);
|
|
}
|
|
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 DST_ALG_RSASHA1:
|
|
case DST_ALG_NSEC3RSASHA1:
|
|
case DST_ALG_RSASHA256:
|
|
case DST_ALG_RSASHA512:
|
|
case DST_ALG_RSASHA256PRIVATEOID:
|
|
case DST_ALG_RSASHA512PRIVATEOID:
|
|
min = (key->algorithm == DST_ALG_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 DST_ALG_ECDSA256:
|
|
size = 256;
|
|
break;
|
|
case DST_ALG_ECDSA384:
|
|
size = 384;
|
|
break;
|
|
case DST_ALG_ED25519:
|
|
size = 256;
|
|
break;
|
|
case DST_ALG_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;
|
|
}
|
|
|
|
dns_keystore_t *
|
|
dns_kasp_key_keystore(dns_kasp_key_t *key) {
|
|
REQUIRE(key != NULL);
|
|
|
|
return key->keystore;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
uint16_t
|
|
dns_kasp_key_tagmin(dns_kasp_key_t *key) {
|
|
REQUIRE(key != NULL);
|
|
return key->tag_min;
|
|
}
|
|
|
|
uint16_t
|
|
dns_kasp_key_tagmax(dns_kasp_key_t *key) {
|
|
REQUIRE(key != NULL);
|
|
return key->tag_min;
|
|
}
|
|
|
|
bool
|
|
dns_kasp_key_match(dns_kasp_key_t *key, dns_dnsseckey_t *dkey) {
|
|
isc_result_t ret;
|
|
bool role = false;
|
|
|
|
REQUIRE(key != NULL);
|
|
REQUIRE(dkey != NULL);
|
|
|
|
/* Matching algorithms? */
|
|
if (dst_key_alg(dkey->key) != dns_kasp_key_algorithm(key)) {
|
|
return false;
|
|
}
|
|
/* Matching length? */
|
|
if (dst_key_size(dkey->key) != dns_kasp_key_size(key)) {
|
|
return false;
|
|
}
|
|
/* Matching role? */
|
|
ret = dst_key_getbool(dkey->key, DST_BOOL_KSK, &role);
|
|
if (ret != ISC_R_SUCCESS || role != dns_kasp_key_ksk(key)) {
|
|
return false;
|
|
}
|
|
ret = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &role);
|
|
if (ret != ISC_R_SUCCESS || role != dns_kasp_key_zsk(key)) {
|
|
return false;
|
|
}
|
|
/* Valid key tag range? */
|
|
uint16_t id = dst_key_id(dkey->key);
|
|
uint16_t rid = dst_key_rid(dkey->key);
|
|
if (id < key->tag_min || id > key->tag_max) {
|
|
return false;
|
|
}
|
|
if (rid < key->tag_min || rid > key->tag_max) {
|
|
return false;
|
|
}
|
|
|
|
/* Found a match. */
|
|
return true;
|
|
}
|
|
|
|
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_offlineksk(dns_kasp_t *kasp) {
|
|
REQUIRE(kasp != NULL);
|
|
REQUIRE(kasp->frozen);
|
|
|
|
return kasp->offlineksk;
|
|
}
|
|
|
|
void
|
|
dns_kasp_setofflineksk(dns_kasp_t *kasp, bool offlineksk) {
|
|
REQUIRE(kasp != NULL);
|
|
REQUIRE(!kasp->frozen);
|
|
|
|
kasp->offlineksk = offlineksk;
|
|
}
|
|
|
|
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 */
|
|
ISC_LIST_FOREACH(kasp->digests, 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);
|
|
}
|