session-keyname local-ddns;\n\
startup-notify-rate 20;\n\
sig0checks-quota 1;\n\
+ sig0key-checks-limit 16;\n\
+ sig0message-checks-limit 2;\n\
statistics-file \"named.stats\";\n\
tcp-advertised-timeout 300;\n\
tcp-clients 150;\n\
dns_view_settransports(view, transports);
dns_transport_list_detach(&transports);
+ /*
+ * Configure SIG(0) check limits when matching a DNS message to a view.
+ */
+ obj = NULL;
+ result = named_config_get(maps, "sig0key-checks-limit", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->sig0key_checks_limit = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "sig0message-checks-limit", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->sig0message_checks_limit = cfg_obj_asuint32(obj);
+
/*
* Configure the view's TSIG keys.
*/
cat_i <keyname.err
cat ns1/example1.db >ns1/example2-toomanykeys.db
-for i in 1 2 3; do
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17; do
keyname=$($KEYGEN -q -n HOST -a ${DEFAULT_ALGORITHM} -T KEY sig0.example2-toomanykeys 2>/dev/null)
if test -n "$keyname"; then
cat $keyname.key >>ns1/example2-toomanykeys.db
ret=0
good=0
bad=0
- for i in 1 2 3; do
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17; do
keyname=$(cat keyname$i)
$NSUPDATE -d -D -k $keyname.private -- - <<EOF >nsupdate.out.test$n.$i 2>&1 && good=$((good + 1)) || bad=$((bad + 1))
local 10.53.0.1
send
EOF
done
- # There are three keys in the zone but named checks the signature using
- # maximum two keys, so one of these updates should have been failed.
- [ $good = 2 ] && [ $bad = 1 ] || ret=1
+ # There are 17 keys in the zone but by default named checks maximum 16 keys
+ # to find a matching key, so one of these updates should have been failed.
+ [ $good = 16 ] && [ $bad = 1 ] || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
sig-validity-interval <integer> [ <integer> ]; // obsolete
sig0checks-quota <integer>; // experimental
sig0checks-quota-exempt { <address_match_element>; ... }; // experimental
+ sig0key-checks-limit <integer>;
+ sig0message-checks-limit <integer>;
stale-answer-client-timeout ( disabled | off | <integer> );
stale-answer-enable <boolean>;
stale-answer-ttl <duration>;
sig-signing-signatures <integer>;
sig-signing-type <integer>;
sig-validity-interval <integer> [ <integer> ]; // obsolete
+ sig0key-checks-limit <integer>;
+ sig0message-checks-limit <integer>;
stale-answer-client-timeout ( disabled | off | <integer> );
stale-answer-enable <boolean>;
stale-answer-ttl <duration>;
uint32_t fail_ttl;
dns_badcache_t *failcache;
unsigned int udpsize;
+ uint32_t sig0key_checks_limit;
+ uint32_t sig0message_checks_limit;
uint32_t maxrrperset;
uint32_t maxtypepername;
uint16_t max_queries;
dns_rdata_sig_t sig;
dns_rdataset_t keyset;
isc_result_t result;
- /*
- * In order to protect from a possible DoS attack, we are
- * going to check at most two KEY RRs.
- */
- const size_t max_keys = 2;
- size_t n;
+ uint32_t key_checks, message_checks;
result = dns_rdataset_first(msg->sig0);
INSIST(result == ISC_R_SUCCESS);
result = dns_rdataset_first(&keyset);
INSIST(result == ISC_R_SUCCESS);
- for (n = 0; result == ISC_R_SUCCESS && n < max_keys;
- n++, result = dns_rdataset_next(&keyset))
+ /*
+ * In order to protect from a possible DoS attack, this function
+ * supports limitations on how many keyid checks and how many
+ * key checks (message verifications using a matched key) are
+ * going to be allowed.
+ */
+ const uint32_t max_key_checks =
+ view->sig0key_checks_limit > 0
+ ? view->sig0key_checks_limit
+ : UINT32_MAX;
+ const uint32_t max_message_checks =
+ view->sig0message_checks_limit > 0
+ ? view->sig0message_checks_limit
+ : UINT32_MAX;
+
+ for (key_checks = 0, message_checks = 0;
+ result == ISC_R_SUCCESS && key_checks < max_key_checks &&
+ message_checks < max_message_checks;
+ key_checks++, result = dns_rdataset_next(&keyset))
{
dst_key_t *key = NULL;
if (result == ISC_R_SUCCESS) {
break;
}
+ message_checks++;
}
- if (result == ISC_R_NOMORE || n == max_keys) {
+ if (result == ISC_R_NOMORE) {
+ result = DNS_R_KEYUNAUTHORIZED;
+ } else if (key_checks == max_key_checks) {
+ isc_log_write(ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
+ "sig0key-checks-limit reached when "
+ "trying to check a message signature");
+ result = DNS_R_KEYUNAUTHORIZED;
+ } else if (message_checks == max_message_checks) {
+ isc_log_write(ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
+ "sig0message-checks-limit reached when "
+ "trying to check a message signature");
result = DNS_R_KEYUNAUTHORIZED;
}
{ "rrset-order", &cfg_type_rrsetorder, 0 },
{ "send-cookie", &cfg_type_boolean, 0 },
{ "servfail-ttl", &cfg_type_duration, 0 },
+ { "sig0key-checks-limit", &cfg_type_uint32, 0 },
+ { "sig0message-checks-limit", &cfg_type_uint32, 0 },
{ "sortlist", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_ANCIENT },
{ "stale-answer-enable", &cfg_type_boolean, 0 },
{ "stale-answer-client-timeout", &cfg_type_staleanswerclienttimeout,