2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

add test cases for several FORMERR code paths:

- duplicated question
  - duplicated answer
  - qtype as an answer
  - two question types
  - question names
  - nsec3 bad owner name
  - short record
  - short question
  - mismatching question class
  - bad record owner name
  - mismatched class in record
  - mismatched KEY class
  - OPT wrong owner name
  - invalid RRSIG "covers" type
  - UPDATE malformed delete type
  - TSIG wrong class
  - TSIG not the last record
This commit is contained in:
Mark Andrews 2024-01-29 10:21:37 -08:00
parent 6a9ac65f0c
commit 6e9ed4983e
21 changed files with 300 additions and 11 deletions

View File

@ -39,10 +39,25 @@ Files: **/*.after*
bin/tests/system/doth/CA/index.txt bin/tests/system/doth/CA/index.txt
bin/tests/system/doth/CA/index.txt.attr bin/tests/system/doth/CA/index.txt.attr
bin/tests/system/doth/CA/serial bin/tests/system/doth/CA/serial
bin/tests/system/notify/ns4/named.port.in bin/tests/system/formerr/badnsec3owner
bin/tests/system/formerr/badrecordname
bin/tests/system/formerr/dupans
bin/tests/system/formerr/dupquestion
bin/tests/system/formerr/keyclass
bin/tests/system/formerr/malformeddeltype
bin/tests/system/formerr/malformedrrsig
bin/tests/system/formerr/nametoolong bin/tests/system/formerr/nametoolong
bin/tests/system/formerr/noquestions bin/tests/system/formerr/noquestions
bin/tests/system/formerr/twoquestions bin/tests/system/formerr/optwrongname
bin/tests/system/formerr/qtypeasanswer
bin/tests/system/formerr/questionclass
bin/tests/system/formerr/shortquestion
bin/tests/system/formerr/shortrecord
bin/tests/system/formerr/tsignotlast
bin/tests/system/formerr/tsigwrongclass
bin/tests/system/formerr/twoquestionnames
bin/tests/system/formerr/twoquestiontypes
bin/tests/system/formerr/wrongclass
bin/tests/system/forward/CA/CA.cfg bin/tests/system/forward/CA/CA.cfg
bin/tests/system/forward/CA/README bin/tests/system/forward/CA/README
bin/tests/system/forward/CA/index.txt bin/tests/system/forward/CA/index.txt
@ -59,6 +74,7 @@ Files: **/*.after*
bin/tests/system/masterfile/knowngood.include bin/tests/system/masterfile/knowngood.include
bin/tests/system/masterfile/knowngood.ttl1 bin/tests/system/masterfile/knowngood.ttl1
bin/tests/system/masterfile/knowngood.ttl2 bin/tests/system/masterfile/knowngood.ttl2
bin/tests/system/notify/ns4/named.port.in
bin/tests/system/nsupdate/CA/CA.cfg bin/tests/system/nsupdate/CA/CA.cfg
bin/tests/system/nsupdate/CA/README bin/tests/system/nsupdate/CA/README
bin/tests/system/nsupdate/CA/index.txt bin/tests/system/nsupdate/CA/index.txt

View File

@ -0,0 +1,7 @@
# bad NSEC3 owner (:) not in base32hex valid characters
# header: id=0008 opcode=query questions=1 authority=1
00 08 00 00 00 01 00 00 00 01 00 00
# question: ./A/IN
00 00 01 00 01
# :./NSEC3/IN/1 length=7 hashtype=240 flags=0 interations=0 salt=- hashlen=1 hash=ff
01 58 00 00 32 00 01 00 00 00 01 00 07 f0 00 00 00 00 01 ff

View File

@ -0,0 +1,21 @@
# oversized owner name
# header: additional=1
00 00 00 00 00 00 00 00 00 00 00 01
# owner name too big (256 octets) A/IN/1 0.0.0.0
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01 00 01 00 00 00 01 00 04 00 00 00 00

View File

@ -11,10 +11,26 @@
# See the COPYRIGHT file distributed with this work for additional # See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership. # information regarding copyright ownership.
rm -f badnsec3owner.out
rm -f badrecordname.out
rm -f dupans.out
rm -f dupquestion.out
rm -f keyclass.out
rm -f malformeddeltype.out
rm -f malformedrrsig.out
rm -f nametoolong.out rm -f nametoolong.out
rm -f twoquestions.out
rm -f noquestions.out rm -f noquestions.out
rm -f ns*/named.conf rm -f optwrongname.out
rm -f ns*/named.run
rm -f ns*/named.memstats
rm -f ns*/managed-keys.bind* rm -f ns*/managed-keys.bind*
rm -f ns*/named.conf
rm -f ns*/named.memstats
rm -f ns*/named.run
rm -f qtypeasanswer.out
rm -f questionclass.out
rm -f shortquestion.out
rm -f shortrecord.out
rm -f tsignotlast.out
rm -f tsigwrongclass.out
rm -f twoquestionnames.out
rm -f twoquestiontypes.out
rm -f wrongclass.out

View File

@ -0,0 +1,8 @@
# multiple singletons (SOA)
# header questions=1 answers=2
00 00 00 00 00 01 00 02 00 00 00 00
# question SOA/IN
00 00 06 00 01
# 2 SOA records that differ in expire
00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05
00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06

View File

@ -0,0 +1,10 @@
# header: 2 questions
00 00 00 00 00 02 00 00 00 00 00 00
# question: AAAAAAAAAAAAAA./A/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01
00 01
# question: AAAAAAAAAAAAAA./A/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01
00 01

View File

@ -0,0 +1,7 @@
# mismatched key class
# header: questions=1 additional=1
00 00 00 00 00 01 00 00 00 00 00 01
# question: ./A/IN
00 00 01 00 01
# additional: ./KEY/CLASS2 flags=0 protocol=0 algorithm=248 keydata=00
00 00 19 00 02 00 00 00 01 00 05 00 00 00 f8 00

View File

@ -0,0 +1,5 @@
# UPDATE malformed 'delete type' update change (non empty data)
# header: UPDATE authority=1
00 00 28 00 00 00 00 00 00 01 00 00
# ./A/ANY TTL=0 length=1 data=00
00 00 01 00 ff 00 00 00 00 00 01 00

View File

@ -0,0 +1,5 @@
# malformed RRRSIG
# header: QUERY, additional=1
00 00 00 00 00 00 00 00 00 00 00 01
# ./RRSIG/IN TTL=1 covers=0 algorithm=240 labels=0 ttl=1 expire=2 signed=3 id=0
00 00 2e 00 01 00 00 00 01 00 14 00 00 f0 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 00

View File

@ -0,0 +1,5 @@
# OPT record with wrong name (not .)
# header: QUERY, additional=1
00 00 00 00 00 00 00 00 00 00 00 01
# OPT record (owner A.)
01 41 00 00 29 00 01 00 00 00 00 00 00

View File

@ -0,0 +1,5 @@
# QTYPE-only type as answer
# header, answers=1
00 00 00 00 00 00 00 01 00 00 00 00
# ./MAILB/IN
00 00 fd 00 01 00 00 00 01 00 00

View File

@ -0,0 +1,7 @@
# two questions of different classes
# header: QUERY, questions=2
00 00 00 00 00 02 00 00 00 00 00 00
# ./A/IN
00 00 01 00 01
# ./A/CLASS2
00 00 01 00 02

View File

@ -0,0 +1,5 @@
# truncated question section
# header: QUERY, questions=1
00 00 00 00 00 01 00 00 00 00 00 00
# truncated question (no class)
00 00 01

View File

@ -0,0 +1,5 @@
# truncated record
# header: QUERY, additional=1
00 09 00 00 00 00 00 00 00 00 00 01
# truncated A record (no ttl, length or data)
00 00 01 00 01

View File

@ -25,14 +25,46 @@ if [ "${ans}" != "got: 000080010000000000000000" ]; then
status=$((status + 1)) status=$((status + 1))
fi fi
echo_i "two questions" echo_i "two question names"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestions >twoquestions.out $PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestionnames >twoquestionnames.out
ans=$(grep got: twoquestions.out) ans=$(grep got: twoquestionnames.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed" echo_i "failed"
status=$((status + 1)) status=$((status + 1))
fi fi
echo_i "two question types"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestiontypes >twoquestiontypes.out
ans=$(grep got: twoquestiontypes.out)
if [ "${ans}" != "got: 0000800100020000000000000e41414141414141414141414141410000010001c00c00020001" ]; then
echo_i "failed"
status=$((status + 1))
fi
echo_i "duplicate questions"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} dupquestion >dupquestion.out
ans=$(grep got: dupquestion.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "duplicate answer"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} dupans >dupans.out
ans=$(grep got: dupans.out)
if [ "${ans}" != "got: 0000800100010000000000000000060001" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "question only type in answer"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} qtypeasanswer >qtypeasanswer.out
ans=$(grep got: qtypeasanswer.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
# this would be NOERROR if it included a COOKIE option, # this would be NOERROR if it included a COOKIE option,
# but is a FORMERR without one. # but is a FORMERR without one.
echo_i "empty question section (and no COOKIE option)" echo_i "empty question section (and no COOKIE option)"
@ -43,6 +75,103 @@ if [ "${ans}" != "got: 000080010000000000000000" ]; then
status=$((status + 1)) status=$((status + 1))
fi fi
echo_i "bad nsec3 owner"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} badnsec3owner >badnsec3owner.out
ans=$(grep got: badnsec3owner.out)
# SERVFAIL (2) rather than FORMERR (1)
if [ "${ans}" != "got: 0008800200010000000000000000010001" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "short record before rdata "
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} shortrecord >shortrecord.out
ans=$(grep got: shortrecord.out)
if [ "${ans}" != "got: 000980010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "short question"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} shortquestion >shortquestion.out
ans=$(grep got: shortquestion.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "mismatch classes in question section"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} questionclass >questionclass.out
ans=$(grep got: questionclass.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "bad record owner name"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} badrecordname >badrecordname.out
ans=$(grep got: badrecordname.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "mismatched class in record"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} wrongclass >wrongclass.out
ans=$(grep got: wrongclass.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "mismatched KEY class"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} keyclass >keyclass.out
ans=$(grep got: keyclass.out)
if [ "${ans}" != "got: 0000800100010000000000000000010001" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "OPT wrong owner name"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} optwrongname >optwrongname.out
ans=$(grep got: optwrongname.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "RRSIG invalid covers"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} malformedrrsig >malformedrrsig.out
ans=$(grep got: malformedrrsig.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "UPDATE malformed delete type"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} malformeddeltype >malformeddeltype.out
ans=$(grep got: malformeddeltype.out)
if [ "${ans}" != "got: 0000a8010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "TSIG wrong class"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} tsigwrongclass >tsigwrongclass.out
ans=$(grep got: tsigwrongclass.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "TSIG not last"
$PERL formerr.pl -a 10.53.0.1 -p ${PORT} tsignotlast >tsignotlast.out
ans=$(grep got: tsignotlast.out)
if [ "${ans}" != "got: 000080010000000000000000" ]; then
echo_i "failed"
status=$(expr $status + 1)
fi
echo_i "exit status: $status" echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1 [ $status -eq 0 ] || exit 1

View File

@ -0,0 +1,8 @@
# SIG not last in additional
# header: QUERY additional=2
00 00 00 00 00 00 00 00 00 00 00 02
# Additional records:
# SIG record (class ANY)
00 00 fa 00 ff 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00
# A record
00 00 01 00 01 00 00 00 01 00 04 00 00 00 00

View File

@ -0,0 +1,5 @@
# TSIG wrong class
# header: QUERY, additional=1
00 00 00 00 00 00 00 00 00 00 00 01
# class should be ANY (00 ff) not IN (00 01)
00 00 fa 00 01 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00

View File

@ -0,0 +1,11 @@
# two questions with different names
00 00 00 00 00 02 00 00 00 00 00 00
# AAAAAAAAAAAAAA./A/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01
00 01
# AAAAAAAAAAAAAB./A/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 42 00
00 01
00 01

View File

@ -1,7 +1,10 @@
# two questions that differ by type
00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00
# AAAAAAAAAAAAAAA./A/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01 00 01
00 01
# AAAAAAAAAAAAAAA./NS/IN
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 02 00 02
0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
00 01
00 01 00 01

View File

@ -0,0 +1,7 @@
# class mismatch
# header: QUERY, additional=2
00 00 00 00 00 00 00 00 00 00 00 02
# ./A/IN
00 00 01 00 01 00 00 00 01 00 04 00 00 00 00
# ./TYPE65280/CLASS256
00 ff 00 01 00 02 00 00 01 00 04 00 00 00 00

View File

@ -1125,6 +1125,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
} }
if (seen_problem) { if (seen_problem) {
/* XXX test coverage */
result = DNS_R_RECOVERABLE; result = DNS_R_RECOVERABLE;
} }
@ -1453,6 +1454,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
if (msg->rdclass != dns_rdataclass_any && if (msg->rdclass != dns_rdataclass_any &&
msg->rdclass != rdclass) msg->rdclass != rdclass)
{ {
/* XXX test coverage */
DO_ERROR(DNS_R_FORMERR); DO_ERROR(DNS_R_FORMERR);
} }
} }
@ -1676,6 +1678,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
if (seen_problem) { if (seen_problem) {
if (free_name) { if (free_name) {
/* XXX test coverage */
dns_message_puttempname(msg, &name); dns_message_puttempname(msg, &name);
} }
free_name = false; free_name = false;
@ -1694,6 +1697,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && !preserve_order && ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && !preserve_order &&
!auth_signed(section)) !auth_signed(section))
{ {
/* XXX test coverage */
DO_ERROR(DNS_R_FORMERR); DO_ERROR(DNS_R_FORMERR);
} }