mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '1750-dnssec-policy-none' into 'main'
Resolve 'dnssec-policy' graceful transition to insecure Closes #2341 and #1750 See merge request isc-projects/bind9!4474
This commit is contained in:
commit
1c26ab64a4
24 changed files with 869 additions and 182 deletions
9
CHANGES
9
CHANGES
|
|
@ -1,3 +1,12 @@
|
|||
5553. [bug] When reconfiguring named, removing "auto-dnssec"
|
||||
did not actually turn off DNSSEC maintenance.
|
||||
This has been fixed. [GL #2341]
|
||||
|
||||
5552. [func] When switching to "dnssec-policy none;", named
|
||||
now permits a safe transition to insecure mode
|
||||
and publishes the CDS and CDNSKEY DELETE
|
||||
records, as described in RFC 8078. [GL #1750]
|
||||
|
||||
5551. [bug] Only assign threads to CPUs in the CPU affinity set.
|
||||
Thanks to Ole Bjørn Hessen. [GL #2245]
|
||||
|
||||
|
|
|
|||
|
|
@ -269,8 +269,8 @@ kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
|
|||
continue;
|
||||
}
|
||||
|
||||
result = cfg_kasp_fromconfig(kconfig, mctx, lctx, &kasplist,
|
||||
&kasp);
|
||||
result = cfg_kasp_fromconfig(kconfig, NULL, mctx, lctx,
|
||||
&kasplist, &kasp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("failed to configure dnssec-policy '%s': %s",
|
||||
cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
|
||||
|
|
@ -284,7 +284,7 @@ kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
|
|||
*kaspp = kasp;
|
||||
|
||||
/*
|
||||
* Same cleanup for kasp list.
|
||||
* Cleanup kasp list.
|
||||
*/
|
||||
for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
|
||||
kasp_next = ISC_LIST_NEXT(kasp, link);
|
||||
|
|
@ -782,7 +782,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* Set dnssec-policy related metadata */
|
||||
if (ctx->policy) {
|
||||
if (ctx->policy != NULL) {
|
||||
dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
|
||||
dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
|
||||
dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
|
||||
|
|
|
|||
|
|
@ -9121,18 +9121,25 @@ load_configuration(const char *filename, named_server_t *server,
|
|||
{
|
||||
cfg_obj_t *kconfig = cfg_listelt_value(element);
|
||||
kasp = NULL;
|
||||
CHECK(cfg_kasp_fromconfig(kconfig, named_g_mctx, named_g_lctx,
|
||||
&kasplist, &kasp));
|
||||
CHECK(cfg_kasp_fromconfig(kconfig, NULL, named_g_mctx,
|
||||
named_g_lctx, &kasplist, &kasp));
|
||||
INSIST(kasp != NULL);
|
||||
dns_kasp_freeze(kasp);
|
||||
dns_kasp_detach(&kasp);
|
||||
}
|
||||
/*
|
||||
* Create the default kasp.
|
||||
* Create the built-in kasp policies ("default", "none").
|
||||
*/
|
||||
kasp = NULL;
|
||||
CHECK(cfg_kasp_fromconfig(NULL, named_g_mctx, named_g_lctx, &kasplist,
|
||||
&kasp));
|
||||
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, "none", named_g_mctx, named_g_lctx,
|
||||
&kasplist, &kasp));
|
||||
INSIST(kasp != NULL);
|
||||
dns_kasp_freeze(kasp);
|
||||
dns_kasp_detach(&kasp);
|
||||
|
|
@ -14528,7 +14535,6 @@ named_server_signing(named_server_t *server, isc_lex_t *lex,
|
|||
isc_buffer_t **text) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_zone_t *zone = NULL;
|
||||
dns_kasp_t *kasp = NULL;
|
||||
dns_name_t *origin;
|
||||
dns_db_t *db = NULL;
|
||||
dns_dbnode_t *node = NULL;
|
||||
|
|
@ -14647,8 +14653,7 @@ named_server_signing(named_server_t *server, isc_lex_t *lex,
|
|||
CHECK(ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
|
||||
kasp = dns_zone_getkasp(zone);
|
||||
if (kasp != NULL) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
(void)putstr(text, "zone uses dnssec-policy, use rndc dnssec "
|
||||
"command instead");
|
||||
(void)putnull(text);
|
||||
|
|
|
|||
|
|
@ -913,6 +913,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
bool check = false, fail = false;
|
||||
bool warn = false, ignore = false;
|
||||
bool ixfrdiff;
|
||||
bool use_kasp = false;
|
||||
dns_masterformat_t masterformat;
|
||||
const dns_master_style_t *masterstyle = &dns_master_style_default;
|
||||
isc_stats_t *zoneqrystats;
|
||||
|
|
@ -1248,19 +1249,15 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
result = named_config_get(maps, "dnssec-policy", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
kaspname = cfg_obj_asstring(obj);
|
||||
if (strcmp(kaspname, "none") != 0) {
|
||||
result = dns_kasplist_find(kasplist, kaspname,
|
||||
&kasp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, named_g_lctx,
|
||||
ISC_LOG_ERROR,
|
||||
"'dnssec-policy '%s' not "
|
||||
"found ",
|
||||
kaspname);
|
||||
RETERR(result);
|
||||
}
|
||||
dns_zone_setkasp(zone, kasp);
|
||||
result = dns_kasplist_find(kasplist, kaspname, &kasp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"'dnssec-policy '%s' not found ",
|
||||
kaspname);
|
||||
RETERR(result);
|
||||
}
|
||||
dns_zone_setkasp(zone, kasp);
|
||||
use_kasp = dns_zone_use_kasp(zone);
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
|
|
@ -1561,7 +1558,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
bool allow = false, maint = false;
|
||||
bool sigvalinsecs;
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
if (dns_kasp_nsec3(kasp)) {
|
||||
result = dns_zone_setnsec3param(
|
||||
zone, 1, dns_kasp_nsec3flags(kasp),
|
||||
|
|
@ -1575,7 +1572,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
INSIST(result == ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp);
|
||||
} else {
|
||||
obj = NULL;
|
||||
|
|
@ -1586,7 +1583,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
}
|
||||
dns_zone_setkeyvalidityinterval(zone, seconds);
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
seconds = (uint32_t)dns_kasp_sigvalidity(kasp);
|
||||
dns_zone_setsigvalidityinterval(zone, seconds);
|
||||
seconds = (uint32_t)dns_kasp_sigrefresh(kasp);
|
||||
|
|
@ -1673,7 +1670,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "auto-dnssec", &obj);
|
||||
if (dns_zone_getkasp(zone) != NULL) {
|
||||
if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
|
||||
{
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, true);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true);
|
||||
|
|
@ -1692,6 +1690,11 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
|
||||
} else {
|
||||
bool s2i = dns_zone_secure_to_insecure(zone, false);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, s2i);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
|
||||
dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, s2i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2139,11 +2142,15 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
|||
bool
|
||||
named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
||||
const cfg_obj_t *vconfig, const cfg_obj_t *config) {
|
||||
isc_result_t res;
|
||||
const cfg_obj_t *zoptions = NULL;
|
||||
const cfg_obj_t *voptions = NULL;
|
||||
const cfg_obj_t *options = NULL;
|
||||
const cfg_obj_t *signing = NULL;
|
||||
bool inline_signing;
|
||||
const cfg_obj_t *allowupdate = NULL;
|
||||
const cfg_obj_t *updatepolicy = NULL;
|
||||
bool zone_is_dynamic = false;
|
||||
bool inline_signing = false;
|
||||
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
|
||||
|
|
@ -2155,6 +2162,38 @@ named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
|||
inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) ==
|
||||
ISC_R_SUCCESS &&
|
||||
cfg_obj_asboolean(signing));
|
||||
if (inline_signing) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (cfg_map_get(zoptions, "update-policy", &updatepolicy) ==
|
||||
ISC_R_SUCCESS) {
|
||||
zone_is_dynamic = true;
|
||||
} else {
|
||||
res = cfg_map_get(zoptions, "allow-update", &allowupdate);
|
||||
if (res != ISC_R_SUCCESS && voptions != NULL) {
|
||||
res = cfg_map_get(voptions, "allow-update",
|
||||
&allowupdate);
|
||||
}
|
||||
if (res != ISC_R_SUCCESS && options != NULL) {
|
||||
res = cfg_map_get(options, "allow-update",
|
||||
&allowupdate);
|
||||
}
|
||||
if (res == ISC_R_SUCCESS) {
|
||||
dns_acl_t *acl = NULL;
|
||||
cfg_aclconfctx_t *actx = NULL;
|
||||
res = cfg_acl_fromconfig(
|
||||
allowupdate, config, named_g_lctx, actx,
|
||||
dns_zone_getmctx(zone), 0, &acl);
|
||||
if (res == ISC_R_SUCCESS && acl != NULL &&
|
||||
!dns_acl_isnone(acl)) {
|
||||
zone_is_dynamic = true;
|
||||
}
|
||||
if (acl != NULL) {
|
||||
dns_acl_detach(&acl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If inline-signing is not set, perhaps implictly through a
|
||||
|
|
@ -2164,51 +2203,24 @@ named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
|||
* inline-signing.
|
||||
*/
|
||||
signing = NULL;
|
||||
if (!inline_signing &&
|
||||
if (!inline_signing && !zone_is_dynamic &&
|
||||
cfg_map_get(zoptions, "dnssec-policy", &signing) == ISC_R_SUCCESS &&
|
||||
signing != NULL && strcmp(cfg_obj_asstring(signing), "none") != 0)
|
||||
signing != NULL)
|
||||
{
|
||||
{
|
||||
isc_result_t res;
|
||||
bool zone_is_dynamic = false;
|
||||
const cfg_obj_t *au = NULL;
|
||||
const cfg_obj_t *up = NULL;
|
||||
|
||||
if (cfg_map_get(zoptions, "update-policy", &up) ==
|
||||
ISC_R_SUCCESS) {
|
||||
zone_is_dynamic = true;
|
||||
} else {
|
||||
res = cfg_map_get(zoptions, "allow-update",
|
||||
&au);
|
||||
if (res != ISC_R_SUCCESS && voptions != NULL) {
|
||||
res = cfg_map_get(voptions,
|
||||
"allow-update", &au);
|
||||
}
|
||||
if (res != ISC_R_SUCCESS && options != NULL) {
|
||||
res = cfg_map_get(options,
|
||||
"allow-update", &au);
|
||||
}
|
||||
if (res == ISC_R_SUCCESS) {
|
||||
dns_acl_t *acl = NULL;
|
||||
cfg_aclconfctx_t *actx = NULL;
|
||||
res = cfg_acl_fromconfig(
|
||||
au, config, named_g_lctx, actx,
|
||||
dns_zone_getmctx(zone), 0,
|
||||
&acl);
|
||||
if (res == ISC_R_SUCCESS &&
|
||||
acl != NULL && !dns_acl_isnone(acl))
|
||||
{
|
||||
zone_is_dynamic = true;
|
||||
}
|
||||
if (acl != NULL) {
|
||||
dns_acl_detach(&acl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!zone_is_dynamic) {
|
||||
inline_signing = true;
|
||||
}
|
||||
if (strcmp(cfg_obj_asstring(signing), "none") != 0) {
|
||||
inline_signing = true;
|
||||
dns_zone_log(
|
||||
zone, ISC_LOG_DEBUG(1), "inline-signing: %s",
|
||||
inline_signing
|
||||
? "implicitly through dnssec-policy"
|
||||
: "no");
|
||||
} else {
|
||||
inline_signing = dns_zone_secure_to_insecure(zone,
|
||||
true);
|
||||
dns_zone_log(
|
||||
zone, ISC_LOG_DEBUG(1), "inline-signing: %s",
|
||||
inline_signing ? "transitioning to insecure"
|
||||
: "no");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,20 @@ zone "migrate-nomatch-alglen.kasp" {
|
|||
update-check-ksk yes;
|
||||
};
|
||||
|
||||
/* These zones are going insecure. */
|
||||
zone "step1.going-insecure.kasp" {
|
||||
type master;
|
||||
file "step1.going-insecure.kasp.db";
|
||||
dnssec-policy "migrate";
|
||||
};
|
||||
|
||||
zone "step1.going-insecure-dynamic.kasp" {
|
||||
type master;
|
||||
file "step1.going-insecure-dynamic.kasp.db";
|
||||
dnssec-policy "migrate";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
/* These are alorithm rollover test zones. */
|
||||
zone "step1.algorithm-roll.kasp" {
|
||||
type primary;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,33 @@ zone "migrate-nomatch-alglen.kasp" {
|
|||
dnssec-policy "migrate-nomatch-alglen";
|
||||
};
|
||||
|
||||
/* Zones for testing going insecure. */
|
||||
zone "step1.going-insecure.kasp" {
|
||||
type master;
|
||||
file "step1.going-insecure.kasp.db";
|
||||
dnssec-policy "none";
|
||||
};
|
||||
|
||||
zone "step2.going-insecure.kasp" {
|
||||
type master;
|
||||
file "step2.going-insecure.kasp.db";
|
||||
dnssec-policy "none";
|
||||
};
|
||||
|
||||
zone "step1.going-insecure-dynamic.kasp" {
|
||||
type master;
|
||||
file "step1.going-insecure-dynamic.kasp.db";
|
||||
dnssec-policy "none";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
zone "step2.going-insecure-dynamic.kasp" {
|
||||
type master;
|
||||
file "step2.going-insecure-dynamic.kasp.db";
|
||||
dnssec-policy "none";
|
||||
allow-update { any; };
|
||||
};
|
||||
|
||||
/*
|
||||
* Zones for testing KSK/ZSK algorithm roll.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -86,6 +86,46 @@ private_type_record $zone 5 "$KSK" >> "$infile"
|
|||
private_type_record $zone 5 "$ZSK" >> "$infile"
|
||||
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
|
||||
|
||||
# The child zones (step1, step2) beneath these zones represent the various
|
||||
# steps of unsigning a zone.
|
||||
for zn in going-insecure.kasp going-insecure-dynamic.kasp
|
||||
do
|
||||
# Step 1:
|
||||
# Set up a zone with dnssec-policy that is going insecure.
|
||||
setup step1.$zn
|
||||
echo "$zone" >> zones
|
||||
T="now-10d"
|
||||
ksktimes="-P $T -A $T -P sync $T"
|
||||
zsktimes="-P $T -A $T"
|
||||
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
|
||||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
|
||||
cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
|
||||
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
|
||||
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
|
||||
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
|
||||
|
||||
# Step 2:
|
||||
# Set up a zone with dnssec-policy that is going insecure. Don't add
|
||||
# this zone to the zones file, because this zone is no longer expected
|
||||
# to be fully signed.
|
||||
setup step2.$zn
|
||||
# The DS was withdrawn from the parent zone 26 hours ago.
|
||||
Trem="now-26h"
|
||||
ksktimes="-P $T -A $T -P sync $T"
|
||||
zsktimes="-P $T -A $T"
|
||||
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2> keygen.out.$zone.1)
|
||||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2> keygen.out.$zone.2)
|
||||
$SETTIME -s -g $H -k $O $T -r $O $T -d $U $Trem -D ds $Trem "$KSK" > settime.out.$zone.1 2>&1
|
||||
$SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" > settime.out.$zone.2 2>&1
|
||||
# Fake lifetime of old algorithm keys.
|
||||
echo "Lifetime: 0" >> "${KSK}.state"
|
||||
echo "Lifetime: 5184000" >> "${ZSK}.state"
|
||||
cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
|
||||
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >> "$infile"
|
||||
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >> "$infile"
|
||||
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
|
||||
done
|
||||
|
||||
#
|
||||
# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK
|
||||
# algorithm rollover.
|
||||
|
|
|
|||
|
|
@ -172,12 +172,26 @@ set_server() {
|
|||
# Set zone name for testing keys.
|
||||
set_zone() {
|
||||
ZONE=$1
|
||||
DYNAMIC="no"
|
||||
}
|
||||
# By default zones are considered static.
|
||||
# When testing dynamic zones, call 'set_dynamic' after 'set_zone'.
|
||||
set_dynamic() {
|
||||
DYNAMIC="yes"
|
||||
}
|
||||
|
||||
# Set policy settings (name $1, number of keys $2, dnskey ttl $3) for testing keys.
|
||||
set_policy() {
|
||||
POLICY=$1
|
||||
NUM_KEYS=$2
|
||||
DNSKEY_TTL=$3
|
||||
CDS_DELETE="no"
|
||||
}
|
||||
# By default policies are considered to be secure.
|
||||
# If a zone sets its policy to "none", call 'set_cdsdelete' to tell the system
|
||||
# test to expect a CDS and CDNSKEY Delete record.
|
||||
set_cdsdelete() {
|
||||
CDS_DELETE="yes"
|
||||
}
|
||||
|
||||
# Set key properties for testing keys.
|
||||
|
|
@ -946,22 +960,18 @@ check_dnssecstatus() {
|
|||
|
||||
rndccmd $_server dnssec -status $_zone in $_view > rndc.dnssec.status.out.$_zone.$n || log_error "rndc dnssec -status zone ${_zone} failed"
|
||||
|
||||
if [ "$_policy" = "none" ]; then
|
||||
grep "Zone does not have dnssec-policy" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for unsigned zone ${_zone}"
|
||||
else
|
||||
grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for signed zone ${_zone}"
|
||||
if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY1 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY2 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY3 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY4 ID) from dnssec status"
|
||||
fi
|
||||
grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for signed zone ${_zone}"
|
||||
if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY1 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY2 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY3 ID) from dnssec status"
|
||||
fi
|
||||
if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
|
||||
grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY4 ID) from dnssec status"
|
||||
fi
|
||||
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
|
|
@ -1044,6 +1054,14 @@ check_cds() {
|
|||
dig_with_opts "$ZONE" "@${SERVER}" "CDNSKEY" > "dig.out.$DIR.test$n.cdnskey" || log_error "dig ${ZONE} CDNSKEY failed"
|
||||
grep "status: NOERROR" "dig.out.$DIR.test$n.cdnskey" > /dev/null || log_error "mismatch status in DNS response"
|
||||
|
||||
if [ "$CDS_DELETE" = "no" ]; then
|
||||
grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" > /dev/null && log_error "unexpected CDS DELETE record in DNS response"
|
||||
grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" > /dev/null && log_error "unexpected CDNSKEY DELETE record in DNS response"
|
||||
else
|
||||
grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" > /dev/null || log_error "missing CDS DELETE record in DNS response"
|
||||
grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" > /dev/null || log_error "missing CDNSKEY DELETE record in DNS response"
|
||||
fi
|
||||
|
||||
if [ "$(key_get KEY1 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DS)" = "omnipresent" ]; then
|
||||
response_has_cds_for_key KEY1 "dig.out.$DIR.test$n.cds" || log_error "missing CDS record in response for key $(key_get KEY1 ID)"
|
||||
check_signatures "CDS" "dig.out.$DIR.test$n.cds" "KSK"
|
||||
|
|
@ -1210,7 +1228,13 @@ _loadkeys_on() {
|
|||
|
||||
nextpart $_dir/named.run > /dev/null
|
||||
rndccmd $_server loadkeys $_zone in $_view > rndc.dnssec.loadkeys.out.$_zone.$n
|
||||
wait_for_log 20 "zone ${_zone}/IN (signed): next key event" $_dir/named.run || return 1
|
||||
|
||||
if [ "${DYNAMIC}" = "yes" ]; then
|
||||
wait_for_log 20 "zone ${_zone}/IN: next key event" $_dir/named.run || return 1
|
||||
else
|
||||
# inline-signing zone adds "(signed)"
|
||||
wait_for_log 20 "zone ${_zone}/IN (signed): next key event" $_dir/named.run || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Tell named that the DS for the key in given zone has been seen in the
|
||||
|
|
@ -1228,21 +1252,23 @@ rndc_checkds() {
|
|||
_keycmd=""
|
||||
if [ "${_key}" != "-" ]; then
|
||||
_keyid=$(key_get $_key ID)
|
||||
_keycmd="-key ${_keyid}"
|
||||
_keycmd=" -key ${_keyid}"
|
||||
fi
|
||||
|
||||
_whencmd=""
|
||||
if [ "${_when}" != "now" ]; then
|
||||
_whencmd="-when ${_when}"
|
||||
_whencmd=" -when ${_when}"
|
||||
fi
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "calling rndc dnssec -checkds ${_keycmd} ${_whencmd} ${_what} zone ${_zone} ($n)"
|
||||
echo_i "calling rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} in ${_view} ($n)"
|
||||
ret=0
|
||||
|
||||
rndccmd $_server dnssec -checkds $_keycmd $_whencmd $_what $_zone in $_view > rndc.dnssec.checkds.out.$_zone.$n || log_error "rndc dnssec -checkds (${_keycmd} ${_whencmd} ${_what} zone ${_zone} failed"
|
||||
rndccmd $_server dnssec -checkds $_keycmd $_whencmd $_what $_zone in $_view > rndc.dnssec.checkds.out.$_zone.$n || log_error "rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} failed"
|
||||
|
||||
_loadkeys_on $_server $_dir $_zone || log_error "loadkeys zone ${_zone} failed ($n)"
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
_loadkeys_on $_server $_dir $_zone || log_error "loadkeys zone ${_zone} failed ($n)"
|
||||
fi
|
||||
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status+ret))
|
||||
|
|
@ -1346,6 +1372,7 @@ status=$((status+ret))
|
|||
# Zone: dynamic.kasp
|
||||
#
|
||||
set_zone "dynamic.kasp"
|
||||
set_dynamic
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties, timings and states same as above.
|
||||
|
|
@ -1378,6 +1405,7 @@ status=$((status+ret))
|
|||
# Zone: dynamic-inline-signing.kasp
|
||||
#
|
||||
set_zone "dynamic-inline-signing.kasp"
|
||||
set_dynamic
|
||||
set_policy "default" "1" "3600"
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Key properties, timings and states same as above.
|
||||
|
|
@ -2937,7 +2965,12 @@ check_next_key_event() {
|
|||
grep "zone ${ZONE}.*: next key event in .* seconds" "${DIR}/named.run" > "keyevent.out.$ZONE.test$n" || log_error "no next key event for zone ${ZONE}"
|
||||
|
||||
# Get the latest next key event.
|
||||
_time=$(awk '{print $10}' < "keyevent.out.$ZONE.test$n" | tail -1)
|
||||
if [ "${DYNAMIC}" = "yes" ]; then
|
||||
_time=$(awk '{print $9}' < "keyevent.out.$ZONE.test$n" | tail -1)
|
||||
else
|
||||
# inline-signing zone adds "(signed)"
|
||||
_time=$(awk '{print $10}' < "keyevent.out.$ZONE.test$n" | tail -1)
|
||||
fi
|
||||
|
||||
# The next key event time must within threshold of the
|
||||
# expected time.
|
||||
|
|
@ -4452,6 +4485,90 @@ dnssec_verify
|
|||
_migratenomatch_alglen_ksk=$(key_get KEY1 ID)
|
||||
_migratenomatch_alglen_zsk=$(key_get KEY2 ID)
|
||||
|
||||
#
|
||||
# Testing going insecure.
|
||||
#
|
||||
|
||||
#
|
||||
# Zone step1.going-insecure.kasp
|
||||
#
|
||||
set_zone "step1.going-insecure.kasp"
|
||||
set_policy "migrate" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
|
||||
# Policy parameters.
|
||||
# Lksk: 0
|
||||
# Lzsk: 60 days (5184000 seconds)
|
||||
# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (1h)
|
||||
# Iret(KSK): 1d2h (93600 seconds)
|
||||
# Iret(ZSK): RRSIG TTL (1d) + Dprp (5m) + Dsgn (9d) + retire-safety (1h)
|
||||
# Iret(ZSK): 10d1h5m (867900 seconds)
|
||||
Lksk=0
|
||||
Lzsk=5184000
|
||||
IretKSK=93600
|
||||
IretZSK=867900
|
||||
|
||||
init_migration_insecure() {
|
||||
key_clear "KEY1"
|
||||
set_keyrole "KEY1" "ksk"
|
||||
set_keylifetime "KEY1" "${Lksk}"
|
||||
set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
|
||||
set_keysigning "KEY1" "yes"
|
||||
set_zonesigning "KEY1" "no"
|
||||
|
||||
set_keystate "KEY1" "GOAL" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DS" "omnipresent"
|
||||
|
||||
key_clear "KEY2"
|
||||
set_keyrole "KEY2" "zsk"
|
||||
set_keylifetime "KEY2" "${Lzsk}"
|
||||
set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
|
||||
set_keysigning "KEY2" "no"
|
||||
set_zonesigning "KEY2" "yes"
|
||||
|
||||
set_keystate "KEY2" "GOAL" "omnipresent"
|
||||
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
|
||||
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
|
||||
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
}
|
||||
init_migration_insecure
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# We have set the timing metadata to now - 10 days (864000 seconds).
|
||||
rollover_predecessor_keytimes -864000
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# Zone step1.going-insecure-dynamic.kasp
|
||||
#
|
||||
|
||||
set_zone "step1.going-insecure-dynamic.kasp"
|
||||
set_dynamic
|
||||
set_policy "migrate" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
init_migration_insecure
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
|
||||
# We have set the timing metadata to now - 10 days (864000 seconds).
|
||||
rollover_predecessor_keytimes -864000
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy
|
||||
# changes).
|
||||
echo_i "reconfig dnssec-policy to trigger algorithm rollover"
|
||||
|
|
@ -4501,6 +4618,148 @@ wait_for_done_signing() {
|
|||
status=$((status+ret))
|
||||
}
|
||||
|
||||
#
|
||||
# Testing going insecure.
|
||||
#
|
||||
|
||||
#
|
||||
# Zone: step1.going-insecure.kasp
|
||||
#
|
||||
set_zone "step1.going-insecure.kasp"
|
||||
set_policy "none" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
# Expect a CDS/CDNSKEY Delete Record.
|
||||
set_cdsdelete
|
||||
|
||||
# Key goal states should be HIDDEN.
|
||||
init_migration_insecure
|
||||
set_keystate "KEY1" "GOAL" "hidden"
|
||||
set_keystate "KEY2" "GOAL" "hidden"
|
||||
# The DS may be removed if we are going insecure.
|
||||
set_keystate "KEY1" "STATE_DS" "unretentive"
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Tell named that the DS has been removed.
|
||||
rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE"
|
||||
wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when the DS becomes HIDDEN. This happens after the
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 1h + 1d = 26h = 93600 seconds.
|
||||
check_next_key_event 93600
|
||||
|
||||
#
|
||||
# Zone: step2.going-insecure.kasp
|
||||
#
|
||||
set_zone "step2.going-insecure.kasp"
|
||||
set_policy "none" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
# Expect a CDS/CDNSKEY Delete Record.
|
||||
set_cdsdelete
|
||||
|
||||
# The DS is long enough removed from the zone to be considered HIDDEN.
|
||||
# This means the DNSKEY and the KSK signatures can be removed.
|
||||
set_keystate "KEY1" "STATE_DS" "hidden"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
|
||||
set_keysigning "KEY1" "no"
|
||||
|
||||
set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
|
||||
set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
|
||||
set_zonesigning "KEY2" "no"
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
|
||||
# Next key event is when the DNSKEY becomes HIDDEN. This happens after the
|
||||
# propagation delay, plus DNSKEY TTL:
|
||||
# 5m + 2h = 125m = 7500 seconds.
|
||||
check_next_key_event 7500
|
||||
|
||||
#
|
||||
# Zone: step1.going-insecure-dynamic.kasp
|
||||
#
|
||||
set_zone "step1.going-insecure-dynamic.kasp"
|
||||
set_dynamic
|
||||
set_policy "none" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
# Expect a CDS/CDNSKEY Delete Record.
|
||||
set_cdsdelete
|
||||
|
||||
# Key goal states should be HIDDEN.
|
||||
init_migration_insecure
|
||||
set_keystate "KEY1" "GOAL" "hidden"
|
||||
set_keystate "KEY2" "GOAL" "hidden"
|
||||
# The DS may be removed if we are going insecure.
|
||||
set_keystate "KEY1" "STATE_DS" "unretentive"
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Tell named that the DS has been removed.
|
||||
rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE"
|
||||
wait_for_done_signing
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
|
||||
# Next key event is when the DS becomes HIDDEN. This happens after the
|
||||
# parent propagation delay, retire safety delay, and DS TTL:
|
||||
# 1h + 1h + 1d = 26h = 93600 seconds.
|
||||
check_next_key_event 93600
|
||||
|
||||
#
|
||||
# Zone: step2.going-insecure-dynamic.kasp
|
||||
#
|
||||
set_zone "step2.going-insecure-dynamic.kasp"
|
||||
set_dynamic
|
||||
set_policy "none" "2" "7200"
|
||||
set_server "ns6" "10.53.0.6"
|
||||
# Expect a CDS/CDNSKEY Delete Record.
|
||||
set_cdsdelete
|
||||
|
||||
# The DS is long enough removed from the zone to be considered HIDDEN.
|
||||
# This means the DNSKEY and the KSK signatures can be removed.
|
||||
set_keystate "KEY1" "STATE_DS" "hidden"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "unretentive"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "unretentive"
|
||||
set_keysigning "KEY1" "no"
|
||||
|
||||
set_keystate "KEY2" "STATE_DNSKEY" "unretentive"
|
||||
set_keystate "KEY2" "STATE_ZRRSIG" "unretentive"
|
||||
set_zonesigning "KEY2" "no"
|
||||
|
||||
# Various signing policy checks.
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
check_apex
|
||||
check_subdomain
|
||||
|
||||
# Next key event is when the DNSKEY becomes HIDDEN. This happens after the
|
||||
# propagation delay, plus DNSKEY TTL:
|
||||
# 5m + 2h = 125m = 7500 seconds.
|
||||
check_next_key_event 7500
|
||||
|
||||
#
|
||||
# Testing migration.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -462,7 +462,9 @@ grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
echo_i "reset the root server"
|
||||
n=$((n+1))
|
||||
echo_i "reset the root server ($n)"
|
||||
ret=0
|
||||
$SETTIME -D none -R none -K ns1 "$original" > /dev/null
|
||||
$SETTIME -D now -K ns1 "$standby1" > /dev/null
|
||||
$SETTIME -D now -K ns1 "$standby2" > /dev/null
|
||||
|
|
@ -470,6 +472,9 @@ $SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
|
|||
copy_setports ns1/named2.conf.in ns1/named.conf
|
||||
rm -f ns1/root.db.signed.jnl
|
||||
mkeys_reconfig_on 1 || ret=1
|
||||
mkeys_reload_on 1 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
echo_i "reinitialize trust anchors"
|
||||
stop_server --use-rndc --port "${CONTROLPORT}" mkeys ns2
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ or Best Current Practice (BCP) documents. The list is non exhaustive.
|
|||
RFC7793
|
||||
RFC7830 [15]
|
||||
RFC7929
|
||||
RFC8078 [20]
|
||||
RFC8080
|
||||
RFC8880
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,11 @@ Removed Features
|
|||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- ``ipv4only.arpa`` is now served when ``dns64`` is configured. [GL #385]
|
||||
- It is now possible to transition a zone from secure to insecure mode
|
||||
without making it bogus in the process: changing to ``dnssec-policy
|
||||
none;`` also causes CDS and CDNSKEY DELETE records to be published, to
|
||||
signal that the entire DS RRset at the parent must be removed, as
|
||||
described in RFC 8078. [GL #1750]
|
||||
|
||||
- When using the ``unixtime`` or ``date`` method to update the SOA
|
||||
serial number, ``named`` and ``dnssec-signzone`` silently fell back to
|
||||
|
|
@ -46,6 +50,5 @@ Feature Changes
|
|||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Only assign threads to CPUs in the CPU affinity set, so that ``named`` no
|
||||
longer attempts to run threads on CPUs outside the affinity set. Thanks to
|
||||
Ole Bjørn Hessen. [GL #2245]
|
||||
- When reconfiguring ``named``, removing ``auto-dnssec`` did actually not turn
|
||||
off DNSSEC maintenance. This has been fixed. [GL #2341]
|
||||
|
|
|
|||
|
|
@ -1015,9 +1015,9 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
|||
continue;
|
||||
}
|
||||
|
||||
ret = cfg_kasp_fromconfig(kconfig, mctx,
|
||||
logctx, &list,
|
||||
&kasp);
|
||||
ret = cfg_kasp_fromconfig(kconfig, NULL,
|
||||
mctx, logctx,
|
||||
&list, &kasp);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = ret;
|
||||
|
|
|
|||
154
lib/dns/dnssec.c
154
lib/dns/dnssec.c
|
|
@ -2010,24 +2010,50 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
|
|||
}
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(cds) && syncdelete(key->key, now))
|
||||
{
|
||||
/* Delete both SHA-1 and SHA-256 */
|
||||
if (exists(cds, &cds_sha1)) {
|
||||
RETERR(delrdata(&cds_sha1, diff, origin,
|
||||
cds->ttl, mctx));
|
||||
}
|
||||
if (exists(cds, &cds_sha256)) {
|
||||
RETERR(delrdata(&cds_sha256, diff, origin,
|
||||
cds->ttl, mctx));
|
||||
}
|
||||
}
|
||||
if (syncdelete(key->key, now)) {
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
dst_key_format(key->key, keystr, sizeof(keystr));
|
||||
|
||||
if (dns_rdataset_isassociated(cdnskey) &&
|
||||
syncdelete(key->key, now)) {
|
||||
if (exists(cdnskey, &cdnskeyrdata)) {
|
||||
RETERR(delrdata(&cdnskeyrdata, diff, origin,
|
||||
cdnskey->ttl, mctx));
|
||||
if (dns_rdataset_isassociated(cds)) {
|
||||
/* Delete both SHA-1 and SHA-256 */
|
||||
if (exists(cds, &cds_sha1)) {
|
||||
isc_log_write(dns_lctx,
|
||||
DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC,
|
||||
ISC_LOG_INFO,
|
||||
"CDS (SHA-1) for key %s "
|
||||
"is now deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cds_sha1, diff, origin,
|
||||
cds->ttl, mctx));
|
||||
}
|
||||
if (exists(cds, &cds_sha256)) {
|
||||
isc_log_write(dns_lctx,
|
||||
DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC,
|
||||
ISC_LOG_INFO,
|
||||
"CDS (SHA-256) for key "
|
||||
"%s is now deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cds_sha256, diff,
|
||||
origin, cds->ttl,
|
||||
mctx));
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(cdnskey)) {
|
||||
if (exists(cdnskey, &cdnskeyrdata)) {
|
||||
isc_log_write(dns_lctx,
|
||||
DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC,
|
||||
ISC_LOG_INFO,
|
||||
"CDNSKEY for key %s is "
|
||||
"now deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cdnskeyrdata, diff,
|
||||
origin, cdnskey->ttl,
|
||||
mctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2047,6 +2073,9 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
|
|||
dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
|
||||
dns_name_t *origin = dst_key_name(key->key);
|
||||
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
dst_key_format(key->key, keystr, sizeof(keystr));
|
||||
|
||||
RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
|
||||
&cdnskeyrdata));
|
||||
|
||||
|
|
@ -2058,10 +2087,21 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
|
|||
DNS_DSDIGEST_SHA256, dsbuf2,
|
||||
&cds_sha256));
|
||||
if (exists(cds, &cds_sha1)) {
|
||||
isc_log_write(
|
||||
dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDS (SHA-1) for key %s is now deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cds_sha1, diff, origin,
|
||||
cds->ttl, mctx));
|
||||
}
|
||||
if (exists(cds, &cds_sha256)) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC,
|
||||
ISC_LOG_INFO,
|
||||
"CDS (SHA-256) for key %s is now "
|
||||
"deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cds_sha256, diff, origin,
|
||||
cds->ttl, mctx));
|
||||
}
|
||||
|
|
@ -2069,6 +2109,11 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
|
|||
|
||||
if (dns_rdataset_isassociated(cdnskey)) {
|
||||
if (exists(cdnskey, &cdnskeyrdata)) {
|
||||
isc_log_write(
|
||||
dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDNSKEY for key %s is now deleted",
|
||||
keystr);
|
||||
RETERR(delrdata(&cdnskeyrdata, diff, origin,
|
||||
cdnskey->ttl, mctx));
|
||||
}
|
||||
|
|
@ -2081,6 +2126,81 @@ failure:
|
|||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
|
||||
dns_name_t *origin, dns_rdataclass_t zclass,
|
||||
dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx,
|
||||
bool dnssec_insecure) {
|
||||
unsigned char dsbuf[5] = { 0, 0, 0, 0, 0 }; /* CDS DELETE rdata */
|
||||
unsigned char keybuf[5] = { 0, 0, 3, 0, 0 }; /* CDNSKEY DELETE rdata */
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_rdata_t cds_delete = DNS_RDATA_INIT;
|
||||
dns_rdata_t cdnskey_delete = DNS_RDATA_INIT;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
r.base = keybuf;
|
||||
r.length = sizeof(keybuf);
|
||||
dns_rdata_fromregion(&cdnskey_delete, zclass, dns_rdatatype_cdnskey,
|
||||
&r);
|
||||
|
||||
r.base = dsbuf;
|
||||
r.length = sizeof(dsbuf);
|
||||
dns_rdata_fromregion(&cds_delete, zclass, dns_rdatatype_cds, &r);
|
||||
|
||||
dns_name_format(origin, namebuf, sizeof(namebuf));
|
||||
|
||||
if (dnssec_insecure) {
|
||||
if (!dns_rdataset_isassociated(cdnskey) ||
|
||||
!exists(cdnskey, &cdnskey_delete)) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDNSKEY (DELETE) for zone %s is now "
|
||||
"published",
|
||||
namebuf);
|
||||
RETERR(addrdata(&cdnskey_delete, diff, origin, ttl,
|
||||
mctx));
|
||||
}
|
||||
|
||||
if (!dns_rdataset_isassociated(cds) ||
|
||||
!exists(cds, &cds_delete)) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDS (DELETE) for zone %s is now "
|
||||
"published",
|
||||
namebuf);
|
||||
RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx));
|
||||
}
|
||||
} else {
|
||||
if (dns_rdataset_isassociated(cdnskey) &&
|
||||
exists(cdnskey, &cdnskey_delete)) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDNSKEY (DELETE) for zone %s is now "
|
||||
"deleted",
|
||||
namebuf);
|
||||
RETERR(delrdata(&cdnskey_delete, diff, origin,
|
||||
cdnskey->ttl, mctx));
|
||||
}
|
||||
|
||||
if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete))
|
||||
{
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
|
||||
"CDS (DELETE) for zone %s is now "
|
||||
"deleted",
|
||||
namebuf);
|
||||
RETERR(delrdata(&cds_delete, diff, origin, cds->ttl,
|
||||
mctx));
|
||||
}
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
failure:
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update 'keys' with information from 'newkeys'.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -649,12 +649,14 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
|
|||
filename, ".state");
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
key->kasp = false;
|
||||
result = dst_key_read_state(newfilename, mctx, &key);
|
||||
if (result == ISC_R_FILENOTFOUND) {
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
key->kasp = true;
|
||||
} else if (result == ISC_R_FILENOTFOUND) {
|
||||
/* Having no state is valid. */
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, newfilename, newfilenamelen);
|
||||
newfilename = NULL;
|
||||
RETERR(result);
|
||||
|
|
@ -2600,6 +2602,8 @@ dst_key_goal(dst_key_t *key) {
|
|||
dst_key_state_t state;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(VALID_KEY(key));
|
||||
|
||||
result = dst_key_getstate(key, DST_KEY_GOAL, &state);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return (state);
|
||||
|
|
@ -2607,6 +2611,13 @@ dst_key_goal(dst_key_t *key) {
|
|||
return (DST_KEY_STATE_HIDDEN);
|
||||
}
|
||||
|
||||
bool
|
||||
dst_key_haskasp(dst_key_t *key) {
|
||||
REQUIRE(VALID_KEY(key));
|
||||
|
||||
return (key->kasp);
|
||||
}
|
||||
|
||||
void
|
||||
dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) {
|
||||
dst_key_state_t state;
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ struct dst_key {
|
|||
bool keystateset[DST_MAX_KEYSTATES + 1]; /*%< data
|
||||
* set? */
|
||||
|
||||
bool kasp; /*%< key has kasp state */
|
||||
bool inactive; /*%< private key not present as it is
|
||||
* inactive */
|
||||
bool external; /*%< external key */
|
||||
|
|
|
|||
|
|
@ -357,6 +357,25 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
|
|||
isc_mem_t *mctx);
|
||||
/*%<
|
||||
* Update the CDS and CDNSKEY RRsets, adding and removing keys as needed.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS
|
||||
*\li Other values indicate error
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
|
||||
dns_name_t *origin, dns_rdataclass_t zclass,
|
||||
dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx,
|
||||
bool dnssec_insecure);
|
||||
/*%<
|
||||
* Add or remove the CDS DELETE record and the CDNSKEY DELETE record.
|
||||
* If 'dnssec_insecure' is true, the DELETE records should be present.
|
||||
* Otherwise, the DELETE records must be removed from the RRsets (if present).
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS
|
||||
*\li Other values indicate error
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
|
|
@ -694,6 +694,32 @@ dns_zone_getkasp(dns_zone_t *zone);
|
|||
*\li 'zone' to be a valid zone.
|
||||
*/
|
||||
|
||||
bool
|
||||
dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig);
|
||||
/*%<
|
||||
* Returns true if the zone is transitioning to insecure.
|
||||
* Only can happen if a zone previously used a dnssec-policy,
|
||||
* but changed the value to "none" (or removed the configuration
|
||||
* option). If 'reconfig' is true, only check the key files,
|
||||
* because the zone structure is not yet updated with the
|
||||
* newest configuration.
|
||||
*
|
||||
* Require:
|
||||
*\li 'zone' to be a valid zone.
|
||||
*/
|
||||
|
||||
bool
|
||||
dns_zone_use_kasp(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Check if zone needs to use kasp.
|
||||
* True if there is a policy that is not "none",
|
||||
* or if there are state files associated with the keys
|
||||
* related to this zone.
|
||||
*
|
||||
* Require:
|
||||
*\li 'zone' to be a valid zone.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -1103,6 +1103,15 @@ dst_key_isexternal(dst_key_t *key);
|
|||
* 'key' to be valid.
|
||||
*/
|
||||
|
||||
bool
|
||||
dst_key_haskasp(dst_key_t *key);
|
||||
/*%<
|
||||
* Check if this key has state (and thus uses KASP).
|
||||
*
|
||||
* Requires:
|
||||
* 'key' to be valid.
|
||||
*/
|
||||
|
||||
bool
|
||||
dst_key_is_unused(dst_key_t *key);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring,
|
|||
*/
|
||||
static bool
|
||||
keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
|
||||
dst_key_state_t next_state) {
|
||||
dst_key_state_t next_state, bool secure_to_insecure) {
|
||||
dst_key_state_t states[2][4] = {
|
||||
/* DNSKEY, ZRRSIG, KRRSIG, DS */
|
||||
{ NA, NA, NA, OMNIPRESENT }, /* DS present */
|
||||
|
|
@ -792,7 +792,10 @@ keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
|
|||
return (keymgr_key_exists_with_state(keyring, key, type, next_state,
|
||||
states[0], na, false, false) ||
|
||||
keymgr_key_exists_with_state(keyring, key, type, next_state,
|
||||
states[1], na, false, false));
|
||||
states[1], na, false, false) ||
|
||||
(secure_to_insecure &&
|
||||
keymgr_key_exists_with_state(keyring, key, type, next_state,
|
||||
na, na, false, false)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1022,14 +1025,17 @@ keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
|
|||
*/
|
||||
static bool
|
||||
keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
|
||||
int type, dst_key_state_t next_state) {
|
||||
int type, dst_key_state_t next_state,
|
||||
bool secure_to_insecure) {
|
||||
/* Debug logging. */
|
||||
if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) {
|
||||
bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b;
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
dst_key_format(key->key, keystr, sizeof(keystr));
|
||||
rule1a = keymgr_have_ds(keyring, key, type, NA);
|
||||
rule1b = keymgr_have_ds(keyring, key, type, next_state);
|
||||
rule1a = keymgr_have_ds(keyring, key, type, NA,
|
||||
secure_to_insecure);
|
||||
rule1b = keymgr_have_ds(keyring, key, type, next_state,
|
||||
secure_to_insecure);
|
||||
rule2a = keymgr_have_dnskey(keyring, key, type, NA);
|
||||
rule2b = keymgr_have_dnskey(keyring, key, type, next_state);
|
||||
rule3a = keymgr_have_rrsig(keyring, key, type, NA);
|
||||
|
|
@ -1054,8 +1060,9 @@ keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
|
|||
* invalid state. If the rule check passes, also check if
|
||||
* the next state is also still a valid situation.
|
||||
*/
|
||||
(!keymgr_have_ds(keyring, key, type, NA) ||
|
||||
keymgr_have_ds(keyring, key, type, next_state)) &&
|
||||
(!keymgr_have_ds(keyring, key, type, NA, secure_to_insecure) ||
|
||||
keymgr_have_ds(keyring, key, type, next_state,
|
||||
secure_to_insecure)) &&
|
||||
/*
|
||||
* Rule 2: There must be a DNSKEY at all times. Again, first
|
||||
* check the current situation, then assess the next state.
|
||||
|
|
@ -1246,7 +1253,7 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
|
|||
*/
|
||||
static isc_result_t
|
||||
keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now,
|
||||
isc_stdtime_t *nexttime) {
|
||||
isc_stdtime_t *nexttime, bool secure_to_insecure) {
|
||||
bool changed;
|
||||
|
||||
/* Repeat until nothing changed. */
|
||||
|
|
@ -1328,7 +1335,9 @@ transition:
|
|||
|
||||
/* Is the transition DNSSEC safe? */
|
||||
if (!keymgr_transition_allowed(keyring, dkey, i,
|
||||
next_state)) {
|
||||
next_state,
|
||||
secure_to_insecure))
|
||||
{
|
||||
/* No, this would make the zone bogus. */
|
||||
isc_log_write(
|
||||
dns_lctx, DNS_LOGCATEGORY_DNSSEC,
|
||||
|
|
@ -1677,6 +1686,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
|||
dns_dnsseckey_t *newkey = NULL;
|
||||
isc_dir_t dir;
|
||||
bool dir_open = false;
|
||||
bool secure_to_insecure = false;
|
||||
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
|
||||
|
|
@ -1832,8 +1842,14 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
|||
ISC_LIST_APPENDLIST(*keyring, newkeys, link);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the policy has an empty key list, this means the zone is going
|
||||
* back to unsigned.
|
||||
*/
|
||||
secure_to_insecure = dns_kasp_keylist_empty(kasp);
|
||||
|
||||
/* Read to update key states. */
|
||||
keymgr_update(keyring, kasp, now, nexttime);
|
||||
keymgr_update(keyring, kasp, now, nexttime, secure_to_insecure);
|
||||
|
||||
/* Store key states and update hints. */
|
||||
for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
|
||||
|
|
|
|||
|
|
@ -1087,7 +1087,6 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
bool keyset_kskonly) {
|
||||
isc_result_t result;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_kasp_t *kasp = dns_zone_getkasp(zone);
|
||||
dns_rdataset_t rdataset;
|
||||
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
|
||||
dns_stats_t *dnssecsignstats = dns_zone_getdnssecsignstats(zone);
|
||||
|
|
@ -1095,11 +1094,13 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
unsigned char data[1024]; /* XXX */
|
||||
unsigned int i, j;
|
||||
bool added_sig = false;
|
||||
bool use_kasp = false;
|
||||
isc_mem_t *mctx = diff->mctx;
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
check_ksk = false;
|
||||
keyset_kskonly = true;
|
||||
use_kasp = true;
|
||||
}
|
||||
|
||||
dns_rdataset_init(&rdataset);
|
||||
|
|
@ -1174,7 +1175,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
}
|
||||
}
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
/*
|
||||
* A dnssec-policy is found. Check what RRsets this
|
||||
* key should sign.
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ dns_dnssec_selfsigns
|
|||
dns_dnssec_sign
|
||||
dns_dnssec_signmessage
|
||||
dns_dnssec_signs
|
||||
dns_dnssec_syncupdate
|
||||
dns_dnssec_syncdelete
|
||||
dns_dnssec_syncupdate
|
||||
dns_dnssec_updatekeys
|
||||
dns_dnssec_verify
|
||||
|
|
@ -1278,6 +1278,7 @@ dns_zone_rekey
|
|||
dns_zone_replacedb
|
||||
dns_zone_rpz_enable
|
||||
dns_zone_rpz_enable_db
|
||||
dns_zone_secure_to_insecure
|
||||
dns_zone_set_parentcatz
|
||||
dns_zone_setadded
|
||||
dns_zone_setalsonotify
|
||||
|
|
@ -1366,6 +1367,7 @@ dns_zone_setzeronosoattl
|
|||
dns_zone_signwithkey
|
||||
dns_zone_synckeyzone
|
||||
dns_zone_unload
|
||||
dns_zone_use_kasp
|
||||
dns_zone_verifydb
|
||||
dns_zonekey_iszonekey
|
||||
dns_zonemgr_attach
|
||||
|
|
@ -1452,6 +1454,7 @@ dst_key_getstate
|
|||
dst_key_gettime
|
||||
dst_key_getttl
|
||||
dst_key_goal
|
||||
dst_key_haskasp
|
||||
dst_key_id
|
||||
dst_key_is_active
|
||||
dst_key_is_published
|
||||
|
|
|
|||
149
lib/dns/zone.c
149
lib/dns/zone.c
|
|
@ -1830,7 +1830,7 @@ dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
|
|||
}
|
||||
|
||||
/* Kasp zones are always dynamic. */
|
||||
if (dns_zone_getkasp(zone) != NULL) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
|
@ -5833,6 +5833,82 @@ dns_zone_getkasp(dns_zone_t *zone) {
|
|||
return (zone->kasp);
|
||||
}
|
||||
|
||||
static bool
|
||||
statefile_exist(dns_zone_t *zone) {
|
||||
isc_result_t ret;
|
||||
dns_dnsseckeylist_t keys;
|
||||
dns_dnsseckey_t *key = NULL;
|
||||
isc_stdtime_t now;
|
||||
isc_time_t timenow;
|
||||
bool found = false;
|
||||
|
||||
TIME_NOW(&timenow);
|
||||
now = isc_time_seconds(&timenow);
|
||||
|
||||
ISC_LIST_INIT(keys);
|
||||
|
||||
ret = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
|
||||
dns_zone_getkeydirectory(zone), now,
|
||||
dns_zone_getmctx(zone), &keys);
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
for (key = ISC_LIST_HEAD(keys); key != NULL;
|
||||
key = ISC_LIST_NEXT(key, link)) {
|
||||
if (dst_key_haskasp(key->key)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up keys */
|
||||
while (!ISC_LIST_EMPTY(keys)) {
|
||||
key = ISC_LIST_HEAD(keys);
|
||||
ISC_LIST_UNLINK(keys, key, link);
|
||||
dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
|
||||
}
|
||||
|
||||
return (found);
|
||||
}
|
||||
|
||||
bool
|
||||
dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
/*
|
||||
* If checking during reconfig, the zone is not yet updated
|
||||
* with the new kasp configuration, so only check the key
|
||||
* files.
|
||||
*/
|
||||
if (reconfig) {
|
||||
return (statefile_exist(zone));
|
||||
}
|
||||
|
||||
if (zone->kasp == NULL) {
|
||||
return (false);
|
||||
}
|
||||
if (strcmp(dns_kasp_getname(zone->kasp), "none") != 0) {
|
||||
return (false);
|
||||
}
|
||||
/*
|
||||
* "dnssec-policy none", but if there are key state files
|
||||
* this zone used to be secure but is transitioning back to
|
||||
* insecure.
|
||||
*/
|
||||
return (statefile_exist(zone));
|
||||
}
|
||||
|
||||
bool
|
||||
dns_zone_use_kasp(dns_zone_t *zone) {
|
||||
dns_kasp_t *kasp = dns_zone_getkasp(zone);
|
||||
|
||||
if (kasp == NULL) {
|
||||
return (false);
|
||||
} else if (strcmp(dns_kasp_getname(kasp), "none") != 0) {
|
||||
return (true);
|
||||
}
|
||||
return dns_zone_secure_to_insecure(zone, false);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
@ -6784,17 +6860,18 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
|
|||
isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
|
||||
isc_result_t result;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_kasp_t *kasp = dns_zone_getkasp(zone);
|
||||
dns_stats_t *dnssecsignstats;
|
||||
dns_rdataset_t rdataset;
|
||||
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
|
||||
unsigned char data[1024]; /* XXX */
|
||||
isc_buffer_t buffer;
|
||||
unsigned int i, j;
|
||||
bool use_kasp = false;
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
check_ksk = false;
|
||||
keyset_kskonly = true;
|
||||
use_kasp = true;
|
||||
}
|
||||
|
||||
dns_rdataset_init(&rdataset);
|
||||
|
|
@ -6872,8 +6949,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
/*
|
||||
* A dnssec-policy is found. Check what RRsets this
|
||||
* key should sign.
|
||||
|
|
@ -7308,7 +7384,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
|
|||
dns_rdata_reset(&rdata);
|
||||
}
|
||||
|
||||
if (kasp) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
dns_kasp_key_t *kkey;
|
||||
int zsk_count = 0;
|
||||
bool approved;
|
||||
|
|
@ -7425,7 +7501,6 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
|
|||
bool is_zsk, bool keyset_kskonly, bool is_bottom_of_zone,
|
||||
dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx) {
|
||||
isc_result_t result;
|
||||
dns_kasp_t *kasp = dns_zone_getkasp(zone);
|
||||
dns_rdatasetiter_t *iterator = NULL;
|
||||
dns_rdataset_t rdataset;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
|
|
@ -7521,7 +7596,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
|
|||
} else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
|
||||
inception, &when)) {
|
||||
/* Only applies to dnssec-policy. */
|
||||
if (kasp != NULL) {
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
goto next_rdataset;
|
||||
}
|
||||
}
|
||||
|
|
@ -9165,6 +9240,7 @@ zone_sign(dns_zone_t *zone) {
|
|||
bool is_bottom_of_zone;
|
||||
bool build_nsec = false;
|
||||
bool build_nsec3 = false;
|
||||
bool use_kasp = false;
|
||||
bool first;
|
||||
isc_result_t result;
|
||||
isc_stdtime_t now, inception, soaexpire, expire;
|
||||
|
|
@ -9221,7 +9297,6 @@ zone_sign(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
kasp = dns_zone_getkasp(zone);
|
||||
|
||||
sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
|
||||
inception = now - 3600; /* Allow for clock skew. */
|
||||
soaexpire = now + sigvalidityinterval;
|
||||
|
|
@ -9258,16 +9333,20 @@ zone_sign(dns_zone_t *zone) {
|
|||
signing = ISC_LIST_HEAD(zone->signing);
|
||||
first = true;
|
||||
|
||||
check_ksk = (kasp != NULL)
|
||||
? false
|
||||
: DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
|
||||
keyset_kskonly = (kasp != NULL)
|
||||
? true
|
||||
: DNS_ZONE_OPTION(zone,
|
||||
DNS_ZONEOPT_DNSKEYKSKONLY);
|
||||
if (dns_zone_use_kasp(zone)) {
|
||||
check_ksk = false;
|
||||
keyset_kskonly = true;
|
||||
use_kasp = true;
|
||||
} else {
|
||||
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
|
||||
keyset_kskonly = DNS_ZONE_OPTION(zone,
|
||||
DNS_ZONEOPT_DNSKEYKSKONLY);
|
||||
}
|
||||
dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
|
||||
use_kasp ? "yes" : "no");
|
||||
|
||||
/* Determine which type of chain to build */
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
build_nsec3 = dns_kasp_nsec3(kasp);
|
||||
build_nsec = !build_nsec3;
|
||||
} else {
|
||||
|
|
@ -9452,7 +9531,7 @@ zone_sign(dns_zone_t *zone) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
/*
|
||||
* A dnssec-policy is found. Check what
|
||||
* RRsets this key can sign.
|
||||
|
|
@ -16462,7 +16541,7 @@ copy_non_dnssec_records(dns_zone_t *zone, dns_db_t *db, dns_db_t *version,
|
|||
* Allow DNSSEC records with dnssec-policy.
|
||||
* WMM: Perhaps add config option for it.
|
||||
*/
|
||||
if (dns_zone_getkasp(zone) == NULL) {
|
||||
if (!dns_zone_use_kasp(zone)) {
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -19747,7 +19826,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
dns__zonediff_t zonediff;
|
||||
bool commit = false, newactive = false;
|
||||
bool newalg = false;
|
||||
bool fullsign;
|
||||
bool fullsign, use_kasp;
|
||||
dns_ttl_t ttl = 3600;
|
||||
const char *dir = NULL;
|
||||
isc_mem_t *mctx = NULL;
|
||||
|
|
@ -19818,9 +19897,10 @@ zone_rekey(dns_zone_t *zone) {
|
|||
* True when called from "rndc sign". Indicates the zone should be
|
||||
* fully signed now.
|
||||
*/
|
||||
kasp = dns_zone_getkasp(zone);
|
||||
fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
|
||||
|
||||
kasp = dns_zone_getkasp(zone);
|
||||
use_kasp = dns_zone_use_kasp(zone);
|
||||
if (kasp != NULL) {
|
||||
LOCK(&kasp->lock);
|
||||
}
|
||||
|
|
@ -19833,9 +19913,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (kasp != NULL &&
|
||||
(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
|
||||
ttl = dns_kasp_dnskeyttl(kasp);
|
||||
if (use_kasp && (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
|
||||
result = dns_keymgr_run(&zone->origin, zone->rdclass, dir, mctx,
|
||||
&keys, kasp, now, &nexttime);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -19851,6 +19929,16 @@ zone_rekey(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
bool insecure = dns_zone_secure_to_insecure(zone, false);
|
||||
|
||||
/*
|
||||
* Only update DNSKEY TTL if we have a policy.
|
||||
*/
|
||||
if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
|
||||
{
|
||||
ttl = dns_kasp_dnskeyttl(kasp);
|
||||
}
|
||||
|
||||
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
|
||||
&zone->origin, ttl, &diff, mctx,
|
||||
dnssec_report);
|
||||
|
|
@ -19878,6 +19966,17 @@ zone_rekey(dns_zone_t *zone) {
|
|||
goto failure;
|
||||
}
|
||||
|
||||
result = dns_dnssec_syncdelete(&cdsset, &cdnskeyset,
|
||||
&zone->origin, zone->rdclass,
|
||||
ttl, &diff, mctx, insecure);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dnssec_log(zone, ISC_LOG_ERROR,
|
||||
"zone_rekey:couldn't update CDS/CDNSKEY "
|
||||
"DELETE records: %s",
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if any pre-existing keys have newly become active;
|
||||
* also, see if any new key is for a new algorithm, as in that
|
||||
|
|
@ -20063,7 +20162,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
/*
|
||||
* If keymgr provided a next time, use the calculated next rekey time.
|
||||
*/
|
||||
if (kasp != NULL) {
|
||||
if (use_kasp) {
|
||||
isc_time_t timenext;
|
||||
uint32_t nexttime_seconds;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,22 +25,23 @@
|
|||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_result_t
|
||||
cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
|
||||
dns_kasplist_t *kasplist, dns_kasp_t **kaspp);
|
||||
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);
|
||||
/*%<
|
||||
* Create and configure a KASP. If 'config' is NULL, the default configuration
|
||||
* is used. If a 'kasplist' is provided, a lookup happens and if a KASP
|
||||
* already exists with the same name, no new KASP is created, and no attach to
|
||||
* 'kaspp' happens.
|
||||
* 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.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'name' is either NULL, or a valid C string.
|
||||
*
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*
|
||||
*\li 'logctx' is a valid logging context.
|
||||
*
|
||||
*\li 'name' is a valid C string.
|
||||
*
|
||||
*\li kaspp != NULL && *kaspp == NULL
|
||||
*
|
||||
* Returns:
|
||||
|
|
|
|||
|
|
@ -253,8 +253,9 @@ cfg_nsec3param_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
|
||||
dns_kasplist_t *kasplist, dns_kasp_t **kaspp) {
|
||||
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) {
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *maps[2];
|
||||
const cfg_obj_t *koptions = NULL;
|
||||
|
|
@ -267,11 +268,10 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
|
|||
|
||||
REQUIRE(kaspp != NULL && *kaspp == NULL);
|
||||
|
||||
kaspname = (config != NULL)
|
||||
kaspname = (name == NULL)
|
||||
? cfg_obj_asstring(cfg_tuple_get(config, "name"))
|
||||
: "default";
|
||||
|
||||
REQUIRE(strcmp(kaspname, "none") != 0);
|
||||
: name;
|
||||
INSIST(kaspname != NULL);
|
||||
|
||||
result = dns_kasplist_find(kasplist, kaspname, &kasp);
|
||||
|
||||
|
|
@ -317,12 +317,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
|
|||
DNS_KASP_RETIRE_SAFETY));
|
||||
|
||||
(void)confget(maps, "keys", &keys);
|
||||
if (keys == NULL) {
|
||||
result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (keys != NULL) {
|
||||
for (element = cfg_list_first(keys); element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
|
|
@ -332,8 +327,19 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
|
|||
goto cleanup;
|
||||
}
|
||||
}
|
||||
INSIST(!(dns_kasp_keylist_empty(kasp)));
|
||||
} else if (strcmp(kaspname, "none") == 0) {
|
||||
/* "dnssec-policy none": key list must be empty */
|
||||
INSIST(strcmp(kaspname, "none") == 0);
|
||||
INSIST(dns_kasp_keylist_empty(kasp));
|
||||
} else {
|
||||
/* No keys clause configured, use the "default". */
|
||||
result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
INSIST(!(dns_kasp_keylist_empty(kasp)));
|
||||
}
|
||||
INSIST(!(dns_kasp_keylist_empty(kasp)));
|
||||
|
||||
/* Configuration: NSEC3 */
|
||||
(void)confget(maps, "nsec3param", &nsec3);
|
||||
|
|
|
|||
Loading…
Reference in a new issue