mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-13 20:49:59 -04:00
[master] tag initializing keys
4798. [func] Keys specified in "managed-keys" statements are tagged as "initializing" until they have been updated by a key refresh query. If initialization fails it will be visible from "rndc secroots". [RT #46267]
This commit is contained in:
parent
1d57d460d4
commit
c9f8165a06
24 changed files with 664 additions and 121 deletions
6
CHANGES
6
CHANGES
|
|
@ -1,3 +1,9 @@
|
|||
4798. [func] Keys specified in "managed-keys" statements
|
||||
are tagged as "initializing" until they have been
|
||||
updated by a key refresh query. If initialization
|
||||
fails it will be visible from "rndc secroots".
|
||||
[RT #46267]
|
||||
|
||||
4797. [func] Removed "isc-hmac-fixup", as the versions of BIND that
|
||||
had the bug it worked around are long past end of
|
||||
life. [RT #46411]
|
||||
|
|
|
|||
|
|
@ -805,6 +805,11 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
|
|||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load keys from configuration into key table. If 'keyname' is specified,
|
||||
* only load keys matching that name. If 'managed' is true, load the key as
|
||||
* an initializing key.
|
||||
*/
|
||||
static isc_result_t
|
||||
load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
|
||||
dns_view_t *view, isc_boolean_t managed,
|
||||
|
|
@ -820,12 +825,14 @@ load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
|
|||
|
||||
for (elt = cfg_list_first(keys);
|
||||
elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
elt = cfg_list_next(elt))
|
||||
{
|
||||
keylist = cfg_listelt_value(elt);
|
||||
|
||||
for (elt2 = cfg_list_first(keylist);
|
||||
elt2 != NULL;
|
||||
elt2 = cfg_list_next(elt2)) {
|
||||
elt2 = cfg_list_next(elt2))
|
||||
{
|
||||
key = cfg_listelt_value(elt2);
|
||||
result = dstkey_fromconfig(vconfig, key, managed,
|
||||
&dstkey, mctx);
|
||||
|
|
@ -833,8 +840,9 @@ load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
|
|||
result = ISC_R_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* If keyname was specified, we only add that key.
|
||||
|
|
@ -846,17 +854,27 @@ load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
|
|||
continue;
|
||||
}
|
||||
|
||||
CHECK(dns_keytable_add(secroots, managed, &dstkey));
|
||||
/*
|
||||
* This key is taken from the configuration, so
|
||||
* if it's a managed key then it's an
|
||||
* initializing key; that's why 'managed'
|
||||
* is duplicated below.
|
||||
*/
|
||||
CHECK(dns_keytable_add2(secroots, managed,
|
||||
managed, &dstkey));
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (dstkey != NULL)
|
||||
if (dstkey != NULL) {
|
||||
dst_key_free(&dstkey);
|
||||
if (secroots != NULL)
|
||||
}
|
||||
if (secroots != NULL) {
|
||||
dns_keytable_detach(&secroots);
|
||||
if (result == DST_R_NOCRYPTO)
|
||||
}
|
||||
if (result == DST_R_NOCRYPTO) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
@ -1026,7 +1044,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
|
|||
}
|
||||
|
||||
/*
|
||||
* Add key zone for managed-keys.
|
||||
* Add key zone for managed keys.
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)named_config_get(maps, "managed-keys-directory", &obj);
|
||||
|
|
@ -1050,6 +1068,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
|
|||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(add_keydata_zone(view, directory, named_g_mctx));
|
||||
|
||||
cleanup:
|
||||
|
|
@ -6443,16 +6462,19 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
|
|||
}
|
||||
nextnode = NULL;
|
||||
(void)dns_keytable_nextkeynode(keytable, keynode, &nextnode);
|
||||
if (keynode != firstnode)
|
||||
if (keynode != firstnode) {
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
}
|
||||
keynode = nextnode;
|
||||
} while (keynode != NULL);
|
||||
|
||||
if (n == 0)
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n > 1)
|
||||
if (n > 1) {
|
||||
qsort(ids, n, sizeof(ids[0]), cid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of
|
||||
|
|
@ -6460,22 +6482,25 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
|
|||
*/
|
||||
label[0] = 0;
|
||||
r.base = label;
|
||||
r.length = sizeof(label);;
|
||||
r.length = sizeof(label);
|
||||
m = snprintf(r.base, r.length, "_ta");
|
||||
if (m < 0 || (unsigned)m > r.length)
|
||||
if (m < 0 || (unsigned)m > r.length) {
|
||||
return;
|
||||
}
|
||||
isc_textregion_consume(&r, m);
|
||||
for (i = 0; i < n; i++) {
|
||||
m = snprintf(r.base, r.length, "-%04x", ids[i]);
|
||||
if (m < 0 || (unsigned)m > r.length)
|
||||
if (m < 0 || (unsigned)m > r.length) {
|
||||
return;
|
||||
}
|
||||
isc_textregion_consume(&r, m);
|
||||
}
|
||||
dns_fixedname_init(&fixed);
|
||||
tatname = dns_fixedname_name(&fixed);
|
||||
result = dns_name_fromstring2(tatname, label, name, 0, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
dns_name_format(tatname, namebuf, sizeof(namebuf));
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
|
|
@ -6484,8 +6509,9 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
|
|||
view->name, namebuf);
|
||||
|
||||
tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
|
||||
if (tat == NULL)
|
||||
if (tat == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
tat->mctx = NULL;
|
||||
tat->task = NULL;
|
||||
|
|
|
|||
|
|
@ -16,16 +16,8 @@ is used so it will send TAT queries once per second.
|
|||
|
||||
ns3 is a validator with a broken key in managed-keys.
|
||||
|
||||
Tests TODO:
|
||||
ns4 is a validator with a deliberately broken managed-keys.bind and
|
||||
managed-keys.jnl, causing RFC 5011 initialization to fail.
|
||||
|
||||
- initial working KSK
|
||||
|
||||
TODO: test using delv with new trusted key too
|
||||
|
||||
- introduce a REVOKE bit
|
||||
|
||||
- later remove a signature
|
||||
|
||||
- corrupt a signature
|
||||
|
||||
TODO: also same things with dlv auto updates of trust anchor
|
||||
ns5 is a validator which is prevented from getting a response from the
|
||||
root server, causing key refresh queries to fail.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ rm -f */K* */*.signed */trusted.conf */*.jnl */*.bk
|
|||
rm -f dsset-. ns1/dsset-.
|
||||
rm -f ns*/named.lock
|
||||
rm -f */managed-keys.bind* */named.secroots
|
||||
rm -f */managed.conf ns1/managed.key ns1/managed.key.id
|
||||
rm -f */managed*.conf ns1/managed.key ns1/managed.key.id
|
||||
rm -f */named.memstats */named.run
|
||||
rm -f dig.out* delv.out* rndc.out* signer.out*
|
||||
rm -f ns1/named.secroots ns1/root.db.signed* ns1/root.db.tmp
|
||||
rm -f ns1/named.conf
|
||||
rm -rf ns4/nope
|
||||
rm -f ns5/named.args
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
|
||||
controls { /* empty */ };
|
||||
|
||||
acl allowed {
|
||||
! 10.53.0.5;
|
||||
any;
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
|
|
@ -22,6 +27,7 @@ options {
|
|||
notify no;
|
||||
dnssec-enable yes;
|
||||
dnssec-validation yes;
|
||||
allow-query { allowed; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
|
||||
controls { /* empty */ };
|
||||
|
||||
acl allowed {
|
||||
! 10.53.0.5;
|
||||
any;
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
|
|
@ -22,6 +27,7 @@ options {
|
|||
notify no;
|
||||
dnssec-enable yes;
|
||||
dnssec-validation yes;
|
||||
allow-query { allowed; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
39
bin/tests/system/mkeys/ns1/named3.conf
Normal file
39
bin/tests/system/mkeys/ns1/named3.conf
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// NS1
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify no;
|
||||
dnssec-enable yes;
|
||||
dnssec-validation yes;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type master;
|
||||
file "root.db.signed";
|
||||
};
|
||||
|
|
@ -28,6 +28,8 @@ managed-keys {
|
|||
EOF
|
||||
' > managed.conf
|
||||
cp managed.conf ../ns2/managed.conf
|
||||
cp managed.conf ../ns4/managed.conf
|
||||
cp managed.conf ../ns5/managed.conf
|
||||
|
||||
# Configure a trusted key statement (used by delve)
|
||||
cat $keyname.key | grep -v '^; ' | $PERL -n -e '
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/20/40
|
||||
-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/20/40 -T tat=1
|
||||
|
|
|
|||
41
bin/tests/system/mkeys/ns4/named.conf
Normal file
41
bin/tests/system/mkeys/ns4/named.conf
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// NS4
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.4;
|
||||
notify-source 10.53.0.4;
|
||||
transfer-source 10.53.0.4;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
notify no;
|
||||
dnssec-enable yes;
|
||||
dnssec-validation auto;
|
||||
bindkeys-file "managed.conf";
|
||||
managed-keys-directory "nope";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.4 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
};
|
||||
38
bin/tests/system/mkeys/ns5/named.conf
Normal file
38
bin/tests/system/mkeys/ns5/named.conf
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
// NS5
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.5;
|
||||
notify-source 10.53.0.5;
|
||||
transfer-source 10.53.0.5;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.5; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
notify no;
|
||||
dnssec-enable yes;
|
||||
dnssec-validation auto;
|
||||
bindkeys-file "managed.conf";
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
};
|
||||
1
bin/tests/system/mkeys/ns5/named1.args
Normal file
1
bin/tests/system/mkeys/ns5/named1.args
Normal file
|
|
@ -0,0 +1 @@
|
|||
-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g
|
||||
1
bin/tests/system/mkeys/ns5/named2.args
Normal file
1
bin/tests/system/mkeys/ns5/named2.args
Normal file
|
|
@ -0,0 +1 @@
|
|||
-m record,size,mctx -T clienttest -c named.conf -d 99 -X named.lock -g -T mkeytimers=2/20/40
|
||||
|
|
@ -14,5 +14,14 @@ $SHELL clean.sh
|
|||
test -r $RANDFILE || $GENRANDOM 800 $RANDFILE
|
||||
|
||||
cp ns1/named1.conf ns1/named.conf
|
||||
cp ns5/named1.args ns5/named.args
|
||||
|
||||
cd ns1 && $SHELL sign.sh
|
||||
( cd ns1 && $SHELL sign.sh )
|
||||
|
||||
cp ns2/managed.conf ns2/managed1.conf
|
||||
|
||||
cd ns4
|
||||
mkdir nope
|
||||
touch nope/managed-keys.bind
|
||||
touch nope/managed.keys.bind.jnl
|
||||
chmod 444 nope/*
|
||||
|
|
|
|||
|
|
@ -215,9 +215,36 @@ t2=`grep "trust pending" ns2/managed-keys.bind`
|
|||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I: reinitialize trust anchors"
|
||||
echo "I: reinitialize trust anchors, add second key to bind.keys"
|
||||
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns2
|
||||
rm -f ns2/managed-keys.bind*
|
||||
cat ns1/$standby1.key | grep -v '^; ' | $PERL -n -e '
|
||||
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
|
||||
local $key = join("", @rest);
|
||||
local $originalkey = `grep initial-key ns2/managed1.conf`;
|
||||
print <<EOF
|
||||
managed-keys {
|
||||
$originalkey
|
||||
"$dn" initial-key $flags $proto $alg "$key";
|
||||
};
|
||||
EOF
|
||||
' > ns2/managed.conf
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check that no key from bind.keys is marked as an initializing key ($n)"
|
||||
ret=0
|
||||
sleep 3
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 secroots | sed 's/^/I: ns2 /'
|
||||
sleep 1
|
||||
grep '; initializing' ns2/named.secroots > /dev/null 2>&1 && ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I: reinitialize trust anchors, revert to one key in bind.keys"
|
||||
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns2
|
||||
rm -f ns2/managed-keys.bind*
|
||||
mv ns2/managed1.conf ns2/managed.conf
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
|
||||
|
||||
n=`expr $n + 1`
|
||||
|
|
@ -446,7 +473,6 @@ rm -f ${revoked}.key ${revoked}.private
|
|||
$SETTIME -D none -R none -K ns1 `cat ns1/managed.key` > /dev/null
|
||||
$SETTIME -D now -K ns1 $standby1 > /dev/null
|
||||
$SETTIME -D now -K ns1 $standby2 > /dev/null
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 flush | sed 's/^/I: ns1 /'
|
||||
sleep 1
|
||||
$SIGNER -Sg -K ns1 -N unixtime -r $RANDFILE -o . ns1/root.db > /dev/null 2>&-
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload . | sed 's/^/I: ns1 /'
|
||||
|
|
@ -454,6 +480,7 @@ sleep 3
|
|||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys refresh | sed 's/^/I: ns2 /'
|
||||
sleep 1
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 managed-keys status > rndc.out.$n 2>&1
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 flush | sed 's/^/I: ns1 /'
|
||||
$DIG $DIGOPTS +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
|
||||
grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
|
||||
|
|
@ -537,14 +564,14 @@ status=`expr $status + $ret`
|
|||
n=`expr $n + 1`
|
||||
echo "I: check that trust-anchor-telemetry queries are logged ($n)"
|
||||
ret=0
|
||||
grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns3/named.run > /dev/null || ret=1
|
||||
grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns2/named.run > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check that trust-anchor-telemetry queries are received ($n)"
|
||||
ret=0
|
||||
grep "query '_ta-[0-9a-f]*/NULL/IN' approved" ns1/named.run > /dev/null || ret=1
|
||||
grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
|
@ -562,5 +589,82 @@ grep "name: \." rndc.out.$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check that trust-anchor-telemetry queries contain the correct key ($n)"
|
||||
ret=0
|
||||
# convert the hexadecimal key from the TAT query into decimal and
|
||||
# compare against the known key.
|
||||
tathex=`grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/'`
|
||||
tatkey=`$PERL -e 'printf("%d\n", hex(@ARGV[0]));' $tathex`
|
||||
realkey=`$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 secroots - | grep '; managed' | sed 's#.*SHA256/\([0-9][0-9]*\) ; managed.*#\1#'`
|
||||
[ "$tatkey" -eq "$realkey" ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check initialization fails if managed-keys can't be created ($n)"
|
||||
ret=0
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 secroots | sed 's/^/I: ns4 /'
|
||||
grep '; initializing managed' ns4/named.secroots > /dev/null 2>&1 || ret=1
|
||||
grep '; managed' ns4/named.secroots > /dev/null 2>&1 && ret=1
|
||||
grep '; trusted' ns4/named.secroots > /dev/null 2>&1 && ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check failure to contact root servers does not prevent key refreshes after restart ($n)"
|
||||
ret=0
|
||||
# By the time we get here, ns5 should have attempted refreshing its managed
|
||||
# keys. These attempts should fail as ns1 is configured to REFUSE all queries
|
||||
# from ns5. Note that named1.args does not contain "-T mkeytimers"; this is to
|
||||
# ensure key refresh retry will be scheduled to one actual hour after the first
|
||||
# key refresh failure instead of just a few seconds, in order to prevent races
|
||||
# between the next scheduled key refresh time and startup time of restarted ns5.
|
||||
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns5
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns5
|
||||
sleep 2
|
||||
# ns5/named.run will contain logs from both the old instance and the new
|
||||
# instance. In order for the test to pass, both must attempt a fetch.
|
||||
count=`grep -c "Creating key fetch" ns5/named.run`
|
||||
[ $count -lt 2 ] && ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: check key refreshes are resumed after root servers become available ($n)"
|
||||
ret=0
|
||||
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns5
|
||||
# Prevent previous check from affecting this one
|
||||
rm -f ns2/managed-keys.bind*
|
||||
# named2.args adds "-T mkeytimers=2/20/40" to named1.args as we need to wait for
|
||||
# an "hour" until keys are refreshed again after initial failure
|
||||
cp ns5/named2.args ns5/named.args
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns5
|
||||
sleep 2
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.5 -p 9953 secroots | sed 's/^/I: ns4 /'
|
||||
sleep 1
|
||||
grep '; initializing managed' ns5/named.secroots > /dev/null 2>&1 || ret=1
|
||||
# ns1 should still REFUSE queries from ns5, so resolving should be impossible
|
||||
$DIG $DIGOPTS +noauth example. @10.53.0.5 txt > dig.out.ns5.a.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns5.a.test$n > /dev/null && ret=1
|
||||
grep "example..*.RRSIG..*TXT" dig.out.ns5.a.test$n > /dev/null && ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns5.a.test$n > /dev/null || ret=1
|
||||
# Allow queries from ns5 to ns1
|
||||
cp ns1/named3.conf ns1/named.conf
|
||||
rm -f ns1/root.db.signed.jnl
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reconfig
|
||||
sleep 3
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.5 -p 9953 secroots | sed 's/^/I: ns4 /'
|
||||
sleep 1
|
||||
grep '; managed' ns5/named.secroots > /dev/null 2>&1 || ret=1
|
||||
# ns1 should not longer REFUSE queries from ns5, so managed keys should be
|
||||
# correctly refreshed and resolving should succeed
|
||||
$DIG $DIGOPTS +noauth example. @10.53.0.5 txt > dig.out.ns5.b.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns5.b.test$n > /dev/null || ret=1
|
||||
grep "example..*.RRSIG..*TXT" dig.out.ns5.b.test$n > /dev/null || ret=1
|
||||
grep "status: NOERROR" dig.out.ns5.b.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
|
|
|||
|
|
@ -566,6 +566,16 @@
|
|||
are not writable by the effective user ID. [RT #46077]
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Initializing keys specified in a <command>managed-keys</command>
|
||||
statement or by <command>dnssec-validation auto;</command> are
|
||||
now tagged as "initializing", until they have been updated by a
|
||||
key refresh query. If key maintenance fails to initialize,
|
||||
this will be visible when running <command>rndc secroots</command>.
|
||||
[RT #46267]
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Previously, <command>update-policy local;</command> accepted
|
||||
|
|
|
|||
|
|
@ -1546,7 +1546,7 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
|
|||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
result = dns_keytable_add(secroots, ISC_FALSE, &dstkey);
|
||||
result = dns_keytable_add2(secroots, ISC_FALSE, ISC_FALSE, &dstkey);
|
||||
|
||||
cleanup:
|
||||
if (dstkey != NULL)
|
||||
|
|
|
|||
|
|
@ -102,10 +102,18 @@ dns_keytable_detach(dns_keytable_t **keytablep);
|
|||
|
||||
isc_result_t
|
||||
dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
dst_key_t **keyp);
|
||||
dst_key_t **keyp) ISC_DEPRECATED;
|
||||
isc_result_t
|
||||
dns_keytable_add2(dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
isc_boolean_t initial, dst_key_t **keyp);
|
||||
/*%<
|
||||
* Add '*keyp' to 'keytable' (using the name in '*keyp').
|
||||
* The value of keynode->managed is set to 'managed'
|
||||
* The value of keynode->managed is set to 'managed', and the
|
||||
* value of keynode->initial is set to 'initial'. (Note: 'initial'
|
||||
* should only be used when adding managed-keys from configuration.
|
||||
* This indicates the key is in "initializing" state, and has not yet
|
||||
* been confirmed with a key refresh query. Once a key refresh query
|
||||
* has validated, we update the keynode with inital == ISC_FALSE.)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
|
|
@ -117,6 +125,8 @@ dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
|
|||
*
|
||||
*\li 'keytable' points to a valid keytable.
|
||||
*
|
||||
*\li if 'initial' is true then 'managed' must also be true.
|
||||
*
|
||||
*\li keyp != NULL && *keyp is a valid dst_key_t *.
|
||||
*
|
||||
* Ensures:
|
||||
|
|
@ -402,6 +412,19 @@ dns_keynode_managed(dns_keynode_t *keynode);
|
|||
* Is this flagged as a managed key?
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_keynode_initial(dns_keynode_t *keynode);
|
||||
/*%<
|
||||
* Is this flagged as an initializing key?
|
||||
*/
|
||||
|
||||
void
|
||||
dns_keynode_trust(dns_keynode_t *keynode);
|
||||
/*%<
|
||||
* Sets keynode->initial to ISC_FALSE in order to mark the key as
|
||||
* trusted: no longer an initializing key.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -614,6 +614,12 @@ dns_resolver_setnonbackofftries(dns_resolver_t *resolver, unsigned int tries);
|
|||
|
||||
unsigned int
|
||||
dns_resolver_getoptions(dns_resolver_t *resolver);
|
||||
/*%<
|
||||
* Get the resolver options.
|
||||
*
|
||||
* Requires:
|
||||
* \li resolver to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_addbadcache(dns_resolver_t *resolver, const dns_name_t *name,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct dns_keynode {
|
|||
isc_refcount_t refcount;
|
||||
dst_key_t * key;
|
||||
isc_boolean_t managed;
|
||||
isc_boolean_t initial;
|
||||
struct dns_keynode * next;
|
||||
};
|
||||
|
||||
|
|
@ -164,83 +165,169 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
|
|||
*keytablep = NULL;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Search "node" for either a null key node or a key node for the exact same
|
||||
* key as the one supplied in "keyp" and, if found, update it accordingly.
|
||||
*/
|
||||
static isc_result_t
|
||||
insert(dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
const dns_name_t *keyname, dst_key_t **keyp)
|
||||
update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, isc_boolean_t initial) {
|
||||
dns_keynode_t *knode;
|
||||
|
||||
REQUIRE(keyp != NULL && *keyp != NULL);
|
||||
REQUIRE(node != NULL);
|
||||
|
||||
for (knode = node->data; knode != NULL; knode = knode->next) {
|
||||
if (knode->key == NULL) {
|
||||
/*
|
||||
* Null key node found. Attach the supplied key to it,
|
||||
* making it a non-null key node and transferring key
|
||||
* ownership to the keytable.
|
||||
*/
|
||||
knode->key = *keyp;
|
||||
*keyp = NULL;
|
||||
return (ISC_R_SUCCESS);
|
||||
} else if (dst_key_compare(knode->key, *keyp)) {
|
||||
/*
|
||||
* Key node found for the supplied key. Free the
|
||||
* supplied copy of the key and update the found key
|
||||
* node's flags if necessary.
|
||||
*/
|
||||
dst_key_free(keyp);
|
||||
if (!initial) {
|
||||
dns_keynode_trust(knode);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Create a key node for "keyp" (or a null key node if "keyp" is NULL), set
|
||||
* "managed" and "initial" as requested and make the created key node the first
|
||||
* one attached to "node" in "keytable".
|
||||
*/
|
||||
static isc_result_t
|
||||
prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
|
||||
dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
isc_boolean_t initial)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_keynode_t *knode = NULL;
|
||||
dns_rbtnode_t *node;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(keyp == NULL || *keyp != NULL);
|
||||
REQUIRE(VALID_KEYTABLE(keytable));
|
||||
REQUIRE(!initial || managed);
|
||||
|
||||
result = dns_keynode_create(keytable->mctx, &knode);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a key was supplied, transfer its ownership to the keytable.
|
||||
*/
|
||||
if (keyp) {
|
||||
knode->key = *keyp;
|
||||
*keyp = NULL;
|
||||
}
|
||||
|
||||
knode->managed = managed;
|
||||
knode->initial = initial;
|
||||
knode->next = node->data;
|
||||
node->data = knode;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Add key "keyp" at "keyname" in "keytable". If the key already exists at the
|
||||
* requested name, update its flags. If "keyp" is NULL, add a null key to
|
||||
* indicate that "keyname" should be treated as a secure domain without
|
||||
* supplying key data which would allow the domain to be validated.
|
||||
*/
|
||||
static isc_result_t
|
||||
insert(dns_keytable_t *keytable, isc_boolean_t managed, isc_boolean_t initial,
|
||||
const dns_name_t *keyname, dst_key_t **keyp)
|
||||
{
|
||||
dns_rbtnode_t *node = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(VALID_KEYTABLE(keytable));
|
||||
|
||||
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
||||
|
||||
node = NULL;
|
||||
result = dns_rbt_addnode(keytable->table, keyname, &node);
|
||||
|
||||
if (keyp != NULL) {
|
||||
if (result == ISC_R_EXISTS) {
|
||||
/* Key already in table? */
|
||||
dns_keynode_t *k;
|
||||
for (k = node->data; k != NULL; k = k->next) {
|
||||
if (k->key == NULL) {
|
||||
k->key = *keyp;
|
||||
*keyp = NULL; /* transfer ownership */
|
||||
break;
|
||||
}
|
||||
if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (k == NULL)
|
||||
result = ISC_R_SUCCESS;
|
||||
else if (*keyp != NULL)
|
||||
dst_key_free(keyp);
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
knode->key = *keyp;
|
||||
knode->next = node->data;
|
||||
*keyp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
node->data = knode;
|
||||
knode = NULL;
|
||||
/*
|
||||
* There was no node for "keyname" in "keytable" yet, so one
|
||||
* was created. Create a new key node for the supplied key (or
|
||||
* a null key node if "keyp" is NULL) and attach it to the
|
||||
* created node.
|
||||
*/
|
||||
result = prepend_keynode(keyp, node, keytable, managed,
|
||||
initial);
|
||||
} else if (result == ISC_R_EXISTS) {
|
||||
/*
|
||||
* A node already exists for "keyname" in "keytable".
|
||||
*/
|
||||
if (keyp == NULL) {
|
||||
/*
|
||||
* We were told to add a null key at "keyname", which
|
||||
* means there is nothing left to do as there is either
|
||||
* a null key at this node already or there is a
|
||||
* non-null key node which would not be affected.
|
||||
* Reset result to reflect the fact that the node for
|
||||
* "keyname" is already marked as secure.
|
||||
*/
|
||||
result = ISC_R_SUCCESS;
|
||||
} else {
|
||||
/*
|
||||
* We were told to add the key supplied in "keyp" at
|
||||
* "keyname". Try to find an already existing key node
|
||||
* we could reuse for the supplied key (i.e. a null key
|
||||
* node or a key node for the exact same key) and, if
|
||||
* found, update it accordingly.
|
||||
*/
|
||||
result = update_keynode(keyp, node, initial);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
/*
|
||||
* The node for "keyname" only contains key
|
||||
* nodes for keys different than the supplied
|
||||
* one. Create a new key node for the supplied
|
||||
* key and prepend it before the others.
|
||||
*/
|
||||
result = prepend_keynode(keyp, node, keytable,
|
||||
managed, initial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Key was already there? That's the same as a success */
|
||||
if (result == ISC_R_EXISTS)
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
||||
|
||||
if (knode != NULL)
|
||||
dns_keynode_detach(keytable->mctx, &knode);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
dst_key_t **keyp)
|
||||
{
|
||||
return (dns_keytable_add2(keytable, managed, ISC_FALSE, keyp));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_keytable_add2(dns_keytable_t *keytable, isc_boolean_t managed,
|
||||
isc_boolean_t initial, dst_key_t **keyp)
|
||||
{
|
||||
REQUIRE(keyp != NULL && *keyp != NULL);
|
||||
return (insert(keytable, managed, dst_key_name(*keyp), keyp));
|
||||
REQUIRE(!initial || managed);
|
||||
return (insert(keytable, managed, initial, dst_key_name(*keyp), keyp));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
|
||||
return (insert(keytable, ISC_TRUE, name, NULL));
|
||||
return (insert(keytable, ISC_TRUE, ISC_FALSE, name, NULL));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -644,8 +731,9 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
|
|||
if (knode->key == NULL)
|
||||
continue;
|
||||
dst_key_format(knode->key, pbuf, sizeof(pbuf));
|
||||
snprintf(obuf, sizeof(obuf), "%s ; %s\n", pbuf,
|
||||
knode->managed ? "managed" : "trusted");
|
||||
snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf,
|
||||
knode->initial ? "initializing " : "",
|
||||
knode->managed ? "managed" : "trusted");
|
||||
result = putstr(text, obuf);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
|
|
@ -703,11 +791,6 @@ dns_keytable_forall(dns_keytable_t *keytable,
|
|||
|
||||
dst_key_t *
|
||||
dns_keynode_key(dns_keynode_t *keynode) {
|
||||
|
||||
/*
|
||||
* Get the DST key associated with keynode.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_KEYNODE(keynode));
|
||||
|
||||
return (keynode->key);
|
||||
|
|
@ -715,14 +798,25 @@ dns_keynode_key(dns_keynode_t *keynode) {
|
|||
|
||||
isc_boolean_t
|
||||
dns_keynode_managed(dns_keynode_t *keynode) {
|
||||
/*
|
||||
* Is this a managed key?
|
||||
*/
|
||||
REQUIRE(VALID_KEYNODE(keynode));
|
||||
|
||||
return (keynode->managed);
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_keynode_initial(dns_keynode_t *keynode) {
|
||||
REQUIRE(VALID_KEYNODE(keynode));
|
||||
|
||||
return (keynode->initial);
|
||||
}
|
||||
|
||||
void
|
||||
dns_keynode_trust(dns_keynode_t *keynode) {
|
||||
REQUIRE(VALID_KEYNODE(keynode));
|
||||
|
||||
keynode->initial = ISC_FALSE;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
||||
isc_result_t result;
|
||||
|
|
@ -736,6 +830,7 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
|||
|
||||
knode->magic = KEYNODE_MAGIC;
|
||||
knode->managed = ISC_FALSE;
|
||||
knode->initial = ISC_FALSE;
|
||||
knode->key = NULL;
|
||||
knode->next = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -10595,8 +10595,8 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, const dns_name_t *name,
|
|||
if (!fuzzing_resolver)
|
||||
#endif
|
||||
{
|
||||
(void) dns_badcache_add(resolver->badcache, name, type,
|
||||
ISC_FALSE, 0, expire);
|
||||
dns_badcache_add(resolver->badcache, name, type,
|
||||
ISC_FALSE, 0, expire);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,12 @@ create_tables() {
|
|||
|
||||
/* Add a normal key */
|
||||
create_key(257, 3, 5, "example.com", keystr1, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_FALSE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
|
||||
/* Add an initializing managed key */
|
||||
create_key(257, 3, 5, "managed.com", keystr1, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_TRUE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
|
||||
/* Add a null key */
|
||||
|
|
@ -185,7 +190,7 @@ ATF_TC_BODY(add, tc) {
|
|||
* nextkeynode() should still return NOTFOUND.
|
||||
*/
|
||||
create_key(257, 3, 5, "example.com", keystr1, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_FALSE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_NOTFOUND);
|
||||
|
|
@ -193,23 +198,129 @@ ATF_TC_BODY(add, tc) {
|
|||
/* Add another key (different keydata) */
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
create_key(257, 3, 5, "example.com", keystr2, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_FALSE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_SUCCESS);
|
||||
dns_keytable_detachkeynode(keytable, &next_keynode);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Get the keynode for the managed.com key. There's no other key for
|
||||
* the name, so nextkeynode() should return NOTFOUND. Ensure the
|
||||
* retrieved key is an initializing key, then mark it as trusted using
|
||||
* dns_keynode_trust() and ensure the latter works as expected.
|
||||
*/
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("managed.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_TRUE);
|
||||
dns_keynode_trust(keynode);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add a different managed key for managed.com, marking it as an
|
||||
* initializing key. Ensure nextkeynode() no longer returns
|
||||
* ISC_R_NOTFOUND and that the added key is an initializing key.
|
||||
*/
|
||||
create_key(257, 3, 5, "managed.com", keystr2, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_TRUE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("managed.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_TRUE);
|
||||
dns_keytable_detachkeynode(keytable, &next_keynode);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add the same managed key again, but this time mark it as a
|
||||
* non-initializing key. Ensure the previously added key is upgraded
|
||||
* to a non-initializing key and make sure there are still two key
|
||||
* nodes for managed.com, both containing non-initializing keys.
|
||||
*/
|
||||
create_key(257, 3, 5, "managed.com", keystr2, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("managed.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_SUCCESS);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
keynode = next_keynode;
|
||||
next_keynode = NULL;
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_NOTFOUND);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add a managed key at a new node, two.com, marking it as an
|
||||
* initializing key. Ensure nextkeynode() returns ISC_R_NOTFOUND and
|
||||
* that the added key is an initializing key.
|
||||
*/
|
||||
create_key(257, 3, 5, "two.com", keystr1, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_TRUE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("two.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_NOTFOUND);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_TRUE);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add a different managed key for two.com, marking it as a
|
||||
* non-initializing key. Ensure nextkeynode() no longer returns
|
||||
* ISC_R_NOTFOUND and that the added key is not an initializing key.
|
||||
*/
|
||||
create_key(257, 3, 5, "two.com", keystr2, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("two.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
dns_keytable_detachkeynode(keytable, &next_keynode);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add the first managed key again, but this time mark it as a
|
||||
* non-initializing key. Ensure the previously added key is upgraded
|
||||
* to a non-initializing key and make sure there are still two key
|
||||
* nodes for two.com, both containing non-initializing keys.
|
||||
*/
|
||||
create_key(257, 3, 5, "two.com", keystr1, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_TRUE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("two.com"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_SUCCESS);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
keynode = next_keynode;
|
||||
next_keynode = NULL;
|
||||
ATF_REQUIRE_EQ(dns_keynode_initial(keynode), ISC_FALSE);
|
||||
ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode,
|
||||
&next_keynode), ISC_R_NOTFOUND);
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
|
||||
/*
|
||||
* Add a normal key to a name that has a null key. The null key node
|
||||
* will be updated with the normal key.
|
||||
*/
|
||||
dns_keytable_detachkeynode(keytable, &keynode);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
|
||||
&null_keynode), ISC_R_SUCCESS);
|
||||
create_key(257, 3, 5, "null.example", keystr2, &key);
|
||||
ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key),
|
||||
ATF_REQUIRE_EQ(dns_keytable_add2(keytable, ISC_FALSE, ISC_FALSE, &key),
|
||||
ISC_R_SUCCESS);
|
||||
ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"),
|
||||
&keynode), ISC_R_SUCCESS);
|
||||
|
|
@ -523,7 +634,7 @@ ATF_TC_BODY(nta, tc) {
|
|||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
create_key(257, 3, 5, "example", keystr1, &key);
|
||||
result = dns_keytable_add(keytable, ISC_FALSE, &key);
|
||||
result = dns_keytable_add2(keytable, ISC_FALSE, ISC_FALSE, &key);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
|
|
|||
|
|
@ -431,10 +431,13 @@ dns_keynode_attach
|
|||
dns_keynode_create
|
||||
dns_keynode_detach
|
||||
dns_keynode_detachall
|
||||
dns_keynode_initial
|
||||
dns_keynode_key
|
||||
dns_keynode_managed
|
||||
dns_keynode_trust
|
||||
dns_keyring_restore
|
||||
dns_keytable_add
|
||||
dns_keytable_add2
|
||||
dns_keytable_attach
|
||||
dns_keytable_attachkeynode
|
||||
dns_keytable_create
|
||||
|
|
|
|||
|
|
@ -3891,7 +3891,8 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
|
|||
*/
|
||||
static void
|
||||
trust_key(dns_zone_t *zone, dns_name_t *keyname,
|
||||
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
|
||||
dns_rdata_dnskey_t *dnskey, isc_boolean_t initial,
|
||||
isc_mem_t *mctx)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
|
|
@ -3910,7 +3911,7 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname,
|
|||
goto failure;
|
||||
|
||||
CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
|
||||
CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
|
||||
CHECK(dns_keytable_add2(sr, ISC_TRUE, initial, &dstkey));
|
||||
dns_keytable_detach(&sr);
|
||||
|
||||
failure:
|
||||
|
|
@ -3996,7 +3997,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
|
|||
|
||||
/* Add to keytables. */
|
||||
trusted++;
|
||||
trust_key(zone, name, &dnskey, mctx);
|
||||
trust_key(zone, name, &dnskey,
|
||||
ISC_TF(keydata.addhd == 0), mctx);
|
||||
}
|
||||
|
||||
if (trusted == 0 && pending != 0) {
|
||||
|
|
@ -4731,8 +4733,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
|
||||
case dns_zone_key:
|
||||
result = sync_keyzone(zone, db);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -4882,9 +4885,17 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
return (result);
|
||||
|
||||
cleanup:
|
||||
if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"failed to initialize managed-keys (%s): "
|
||||
"DNSSEC validation is at risk",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
for (inc = ISC_LIST_HEAD(zone->newincludes);
|
||||
inc != NULL;
|
||||
inc = ISC_LIST_HEAD(zone->newincludes)) {
|
||||
inc = ISC_LIST_HEAD(zone->newincludes))
|
||||
{
|
||||
ISC_LIST_UNLINK(zone->newincludes, inc, link);
|
||||
isc_mem_free(zone->mctx, inc->name);
|
||||
isc_mem_put(zone->mctx, inc, sizeof(*inc));
|
||||
|
|
@ -9045,7 +9056,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
dst_key_t *dstkey;
|
||||
isc_stdtime_t now;
|
||||
int pending = 0;
|
||||
isc_boolean_t secure = ISC_FALSE;
|
||||
isc_boolean_t secure = ISC_FALSE, initial = ISC_FALSE;
|
||||
isc_boolean_t free_needed;
|
||||
|
||||
UNUSED(task);
|
||||
|
|
@ -9122,7 +9133,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
*/
|
||||
for (result = dns_rdataset_first(&kfetch->dnskeysigset);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(&kfetch->dnskeysigset)) {
|
||||
result = dns_rdataset_next(&kfetch->dnskeysigset))
|
||||
{
|
||||
dns_keynode_t *keynode = NULL;
|
||||
|
||||
dns_rdata_reset(&sigrr);
|
||||
|
|
@ -9141,7 +9153,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
break;
|
||||
|
||||
if (dst_key_alg(dstkey) == sig.algorithm &&
|
||||
dst_key_id(dstkey) == sig.keyid) {
|
||||
dst_key_id(dstkey) == sig.keyid)
|
||||
{
|
||||
result = dns_dnssec_verify2(keyname,
|
||||
&kfetch->dnskeyset,
|
||||
dstkey, ISC_FALSE,
|
||||
|
|
@ -9159,6 +9172,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
dns_trust_secure;
|
||||
kfetch->dnskeysigset.trust =
|
||||
dns_trust_secure;
|
||||
secure = ISC_TRUE;
|
||||
initial = dns_keynode_initial(keynode);
|
||||
dns_keynode_trust(keynode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -9169,11 +9185,11 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
keynode = nextnode;
|
||||
}
|
||||
|
||||
if (keynode != NULL)
|
||||
if (keynode != NULL) {
|
||||
dns_keytable_detachkeynode(secroots, &keynode);
|
||||
}
|
||||
|
||||
if (kfetch->dnskeyset.trust == dns_trust_secure) {
|
||||
secure = ISC_TRUE;
|
||||
if (secure) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -9182,7 +9198,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
* If we were not able to verify the answer using the current
|
||||
* trusted keys then all we can do is look at any revoked keys.
|
||||
*/
|
||||
|
||||
if (!secure) {
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(3),
|
||||
"DNSKEY set for zone '%s' could not be verified "
|
||||
|
|
@ -9422,10 +9437,13 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
trustkey = ISC_TRUE;
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"Key %d for zone %s "
|
||||
"acceptance timer "
|
||||
"complete: "
|
||||
"key now trusted",
|
||||
keytag, namebuf);
|
||||
"is now trusted (%s)",
|
||||
keytag, namebuf,
|
||||
initial
|
||||
? "initializing key "
|
||||
"verified"
|
||||
: "acceptance timer "
|
||||
"complete");
|
||||
}
|
||||
} else if (keydata.addhd > now) {
|
||||
/*
|
||||
|
|
@ -9524,7 +9542,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
/* Trust this key. */
|
||||
result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
trust_key(zone, keyname, &dnskey, mctx);
|
||||
trust_key(zone, keyname, &dnskey, ISC_FALSE, mctx);
|
||||
}
|
||||
|
||||
if (secure && !deletekey) {
|
||||
|
|
@ -9546,7 +9564,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
fail_secure(zone, keyname);
|
||||
|
||||
done:
|
||||
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
/* Write changes to journal file. */
|
||||
CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
|
||||
|
|
@ -9559,7 +9576,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
failure:
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"error during managed-keys processing (%s): "
|
||||
"DNSSEC validation may be at risk",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
dns_diff_clear(&diff);
|
||||
if (ver != NULL)
|
||||
dns_db_closeversion(kfetch->db, &ver, commit);
|
||||
|
|
@ -9669,7 +9691,7 @@ zone_refreshkeys(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
/* Acceptance timer expired? */
|
||||
if (kd.addhd != 0 && kd.addhd < now)
|
||||
if (kd.addhd < now)
|
||||
timer = kd.addhd;
|
||||
|
||||
/* Or do we just need to refresh the keyset? */
|
||||
|
|
|
|||
Loading…
Reference in a new issue