mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-27 12:13:20 -04:00
Validate DNS message CLASS early in request processing
Reject requests with unsupported or misused CLASS values before further processing. Only IN, CH, HS, RESERVED0 (for DNS Cookies), ANY (for TKEY negotiation), and NONE (for DNS UPDATE) are accepted; all other classes return NOTIMP. Misuse of NONE or ANY outside their allowed contexts returns FORMERR. This adds further protection against bugs of the same general class as YWH-PGM40640-70 and YWH-PGM40640-73. (cherry picked from commit 0a687451505037e9f9a850c9cb113aed4995b03f)
This commit is contained in:
parent
04092ed136
commit
b247dbb350
2 changed files with 55 additions and 13 deletions
|
|
@ -25,6 +25,11 @@ dig_cmd() {
|
|||
"$DIG" $DIGOPTS "$@" | grep -v '^;'
|
||||
}
|
||||
|
||||
dig_full() {
|
||||
# shellcheck disable=SC2086
|
||||
"$DIG" $DIGOPTS "$@"
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "querying for various representations of an IN A record ($n)"
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
||||
|
|
@ -81,8 +86,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE1 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
echo '\# 4 0A000001' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -93,8 +98,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TXT record ($n)"
|
||||
for i in 1 2 3 4; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
echo '"hello"' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -105,8 +110,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE123 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
echo '\# 1 00' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <dns/dispatch.h>
|
||||
#include <dns/dnstap.h>
|
||||
#include <dns/edns.h>
|
||||
#include <dns/enumclass.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/peer.h>
|
||||
|
|
@ -2083,7 +2084,9 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
}
|
||||
}
|
||||
|
||||
if (client->message->rdclass == 0) {
|
||||
char classbuf[DNS_RDATACLASS_FORMATSIZE];
|
||||
switch (client->message->rdclass) {
|
||||
case dns_rdataclass_reserved0:
|
||||
if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
|
||||
client->message->opcode == dns_opcode_query &&
|
||||
client->message->counts[DNS_SECTION_QUESTION] == 0U)
|
||||
|
|
@ -2102,12 +2105,46 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
return;
|
||||
}
|
||||
|
||||
ns_client_dumpmessage(client,
|
||||
"message class could not be determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
return;
|
||||
case dns_rdataclass_in:
|
||||
break;
|
||||
case dns_rdataclass_chaos:
|
||||
break;
|
||||
case dns_rdataclass_hs:
|
||||
break;
|
||||
case dns_rdataclass_none:
|
||||
if (client->message->opcode != dns_opcode_update) {
|
||||
ns_client_dumpmessage(client,
|
||||
"message class NONE can be only "
|
||||
"used in DNS updates");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case dns_rdataclass_any:
|
||||
/*
|
||||
* Required for TKEY negotiation.
|
||||
*/
|
||||
if (client->message->tkey == 0) {
|
||||
ns_client_dumpmessage(client,
|
||||
"message class ANY can be only "
|
||||
"used for TKEY negotiation");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dns_rdataclass_format(client->message->rdclass, classbuf,
|
||||
sizeof(classbuf));
|
||||
ns_client_dumpmessage(client, NULL);
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"message class could not be determined");
|
||||
ns_client_dumpmessage(client, "message class could not be "
|
||||
"determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
"invalid message class: %s", classbuf);
|
||||
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2140,7 +2177,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"no matching view in class '%s'", classname);
|
||||
ns_client_dumpmessage(client, "no matching view in class");
|
||||
ns_client_dumpmessage(client, NULL);
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
|
||||
return;
|
||||
|
|
@ -2781,7 +2818,7 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
|
|||
int len = 1024;
|
||||
isc_result_t result;
|
||||
|
||||
if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
|
||||
if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1)) || reason == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue