grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${qtype}.*257.*.3.*${KEY1[$ALG_NUM]}" dig.out.$DIR.test$n > /dev/null || log_error "missing ${qtype} record in response"
lines=$(get_keys_which_signed $qtype dig.out.$DIR.test$n | wc -l)
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-get_keys_which_signed $qtype dig.out.$DIR.test$n | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with ${KEY_ID}"
+get_keys_which_signed $qtype dig.out.$DIR.test$n | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*${qtype}.*mname1\..*\." dig.out.$DIR.test$n > /dev/null || log_error "missing ${qtype} record in response"
lines=$(get_keys_which_signed $qtype dig.out.$DIR.test$n | wc -l)
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-get_keys_which_signed $qtype dig.out.$DIR.test$n | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with ${KEY_ID}"
+get_keys_which_signed $qtype dig.out.$DIR.test$n | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" dig.out.$DIR.test$n.a > /dev/null || log_error "missing a.${ZONE} A record in response"
lines=$(get_keys_which_signed A dig.out.$DIR.test$n.a | wc -l)
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
- get_keys_which_signed A dig.out.$DIR.test$n.a | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with ${KEY_ID}"
+ get_keys_which_signed A dig.out.$DIR.test$n.a | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
dig_with_opts "d.${ZONE}" @10.53.0.3 A > dig.out.$DIR.test$n.d || log_error "dig d.${ZONE} A failed"
grep "status: NOERROR" dig.out.$DIR.test$n.d > /dev/null || log_error "mismatch status in DNS response"
grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" dig.out.$DIR.test$n.d > /dev/null || log_error "missing d.${ZONE} A record in response"
lines=$(get_keys_which_signed A dig.out.$DIR.test$n.d | wc -l)
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
- get_keys_which_signed A dig.out.$DIR.test$n.d | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with ${KEY_ID}"
+ get_keys_which_signed A dig.out.$DIR.test$n.d | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
i=`expr $i + 1`
if [ $ret = 0 ]; then break; fi
if [ "${KEY1[$_expect_type]}" == "yes" ] && [ "${KEY1[$_role]}" == "yes" ]; then
get_keys_which_signed $_qtype $_file | grep "^${KEY1[$ID]}$" > /dev/null || log_error "${_qtype} RRset not signed with key ${KEY1[$ID]}"
elif [ "${KEY1[$EXPECT]}" == "yes" ]; then
- get_keys_which_signed $_qtype $_file | grep "^${KEY1[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with ${KEY1[$ID]}"
+ get_keys_which_signed $_qtype $_file | grep "^${KEY1[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key ${KEY1[$ID]}"
fi
if [ "${KEY2[$_expect_type]}" == "yes" ] && [ "${KEY2[$_role]}" == "yes" ]; then
- get_keys_which_signed $_qtype $_file | grep "^${KEY2[$ID]}$" > /dev/null || log_error "${_qtype} RRset not signed with ${KEY2[$ID]}"
+ get_keys_which_signed $_qtype $_file | grep "^${KEY2[$ID]}$" > /dev/null || log_error "${_qtype} RRset not signed with key ${KEY2[$ID]}"
elif [ "${KEY2[$EXPECT]}" == "yes" ]; then
- get_keys_which_signed $_qtype $_file | grep "^${KEY2[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with ${KEY2[$ID]}"
+ get_keys_which_signed $_qtype $_file | grep "^${KEY2[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key ${KEY2[$ID]}"
fi
if [ "${KEY3[$_expect_type]}" == "yes" ] && [ "${KEY3[$_role]}" == "yes" ]; then
- get_keys_which_signed $_qtype $_file | grep "^${KEY3[$ID]}$" > /dev/null || log_error "${_qtype} RRset not signed with ${KEY3[$ID]}"
+ get_keys_which_signed $_qtype $_file | grep "^${KEY3[$ID]}$" > /dev/null || log_error "${_qtype} RRset not signed with key ${KEY3[$ID]}"
elif [ "${KEY3[$EXPECT]}" == "yes" ]; then
- get_keys_which_signed $_qtype $_file | grep "^${KEY3[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with ${KEY3[$ID]}"
+ get_keys_which_signed $_qtype $_file | grep "^${KEY3[$ID]}$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key ${KEY3[$ID]}"
fi
}
+# Test CDS and CDNSKEY publication.
+check_cds() {
+
+ _qtype="CDS"
+ _key_algnum="${KEY1[$ALG_NUM]}"
+
+ n=$((n+1))
+ echo_i "check ${_qtype} rrset is signed correctly for zone ${ZONE} ($n)"
+ ret=0
+ dig_with_opts $ZONE @10.53.0.3 $_qtype > dig.out.$DIR.test$n || log_error "dig ${ZONE} ${_qtype} failed"
+ grep "status: NOERROR" dig.out.$DIR.test$n > /dev/null || log_error "mismatch status in DNS response"
+
+ if [ "${KEY1[$STATE_DS]}" == "rumoured" ] || [ "${KEY1[$STATE_DS]}" == "omnipresent" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY1[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null || log_error "missing ${_qtype} record in response for key ${KEY1[$ID]}"
+ check_signatures $_qtype dig.out.$DIR.test$n $KSK
+ elif [ "${KEY1[$EXPECT]}" == "yes" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY1[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null && log_error "unexpected ${_qtype} record in response for key ${KEY1[$ID]}"
+ fi
+
+ if [ "${KEY2[$STATE_DS]}" == "rumoured" ] || [ "${KEY2[$STATE_DS]}" == "omnipresent" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY2[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null || log_error "missing ${_qtype} record in response for key ${KEY2[$ID]}"
+ check_signatures $_qtype dig.out.$DIR.test$n $KSK
+ elif [ "${KEY2[$EXPECT]}" == "yes" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY2[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null && log_error "unexpected ${_qtype} record in response for key ${KEY2[$ID]}"
+ fi
+
+ if [ "${KEY3[$STATE_DS]}" == "rumoured" ] || [ "${KEY3[$STATE_DS]}" == "omnipresent" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY3[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null || log_error "missing ${_qtype} record in response for key ${KEY3[$ID]}"
+ check_signatures $_qtype dig.out.$DIR.test$n $KSK
+ elif [ "${KEY3[$EXPECT]}" == "yes" ]; then
+ grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*${KEY3[$ID]}.*${_key_algnum}.*2" dig.out.$DIR.test$n > /dev/null && log_error "unexpected ${_qtype} record in response for key ${KEY3[$ID]}"
+ fi
+
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+}
+
# Test the apex of a configured zone. This checks that the SOA and DNSKEY
# RRsets are signed correctly and with the appropriate keys.
check_apex() {
check_signatures $_qtype dig.out.$DIR.test$n $ZSK
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
+
+ # Test CDS publication.
+ check_cds
}
# Test an RRset below the apex and verify it is signed correctly.
* Indicate whether a key is scheduled to to have CDS/CDNSKEY records
* published now.
*
- * Returns true iff.
+ * Returns true if.
+ * - kasp says the DS record should be published (e.g. the DS state is in
+ * RUMOURED or OMNIPRESENT state).
+ * Or:
* - SyncPublish is set and in the past, AND
* - SyncDelete is unset or in the future
*/
syncpublish(dst_key_t *key, isc_stdtime_t now) {
isc_result_t result;
isc_stdtime_t when;
+ dst_key_state_t state;
int major, minor;
/*
/*
* Smart signing started with key format 1.3
*/
- if (major == 1 && minor <= 2)
+ if (major == 1 && minor <= 2) {
return (false);
+ }
+
+ /* Check kasp state first. */
+ result = dst_key_getstate(key, DST_KEY_DS, &state);
+ if (result == ISC_R_SUCCESS) {
+ return (state == DST_KEY_STATE_RUMOURED ||
+ state == DST_KEY_STATE_OMNIPRESENT);
+ }
+ /* If no kasp state, check timings. */
result = dst_key_gettime(key, DST_TIME_SYNCPUBLISH, &when);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
return (false);
-
+ }
result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
return (true);
- if (when <= now)
+ }
+ if (when <= now) {
return (false);
+ }
return (true);
}
* Indicate whether a key is scheduled to to have CDS/CDNSKEY records
* deleted now.
*
- * Returns true iff. SyncDelete is set and in the past.
+ * Returns true if:
+ * - kasp says the DS record should be unpublished (e.g. the DS state is in
+ * UNRETENTIVE or HIDDEN state).
+ * Or:
+ * - SyncDelete is set and in the past.
*/
static bool
syncdelete(dst_key_t *key, isc_stdtime_t now) {
isc_result_t result;
isc_stdtime_t when;
+ dst_key_state_t state;
int major, minor;
/*
/*
* Smart signing started with key format 1.3.
*/
- if (major == 1 && minor <= 2)
+ if (major == 1 && minor <= 2) {
return (false);
+ }
+
+ /* Check kasp state first. */
+ result = dst_key_getstate(key, DST_KEY_DS, &state);
+ if (result == ISC_R_SUCCESS) {
+ return (state == DST_KEY_STATE_UNRETENTIVE ||
+ state == DST_KEY_STATE_HIDDEN);
+ }
+ /* If no kasp state, check timings. */
result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
return (false);
- if (when <= now)
+ }
+ if (when <= now) {
return (true);
+ }
return (false);
}
/* Printable version of key2 (the old key, if any) */
dst_key_format(key2->key, keystr2, sizeof(keystr2));
+ /* Copy key metadata. */
+ dst_key_copy_metadata(key2->key, key1->key);
+
/* Match found: remove or update it as needed */
if (key1->hint_remove) {
RETERR(remove_key(diff, key2, origin, ttl, mctx,