mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-25 08:07:12 -04:00
4260. [security] Insufficient testing when parsing a message allowed
records with an incorrect class to be be accepted,
triggering a REQUIRE failure when those records
were subsequently cached. (CVE-2015-8000) [RT #4098]
(cherry picked from commit c8821d124c)
This commit is contained in:
parent
c8a643d37a
commit
3a4c24c4a5
8 changed files with 83 additions and 9 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
4260. [security] Insufficient testing when parsing a message allowed
|
||||
records with an incorrect class to be be accepted,
|
||||
triggering a REQUIRE failure when those records
|
||||
were subsequently cached. (CVE-2015-8000) [RT #4098]
|
||||
|
||||
4258. [bug] Limit rndc query message sizes to 32 KiB. This should
|
||||
not break any legitimate rndc commands, but will
|
||||
prevent a rogue rndc query from allocating too
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ else
|
|||
TESTSOCK6=false
|
||||
fi
|
||||
|
||||
PYTHON=@PYTHON@
|
||||
|
||||
#
|
||||
# Determine if we support various optional features.
|
||||
#
|
||||
|
|
@ -115,4 +117,4 @@ ZLIB=@ZLIB@
|
|||
|
||||
export NAMED LWRESD DIG NSUPDATE KEYGEN KEYFRLAB SIGNER KEYSIGNER KEYSETTOOL \
|
||||
PERL SUBDIRS RNDC CHECKZONE PK11GEN PK11LIST PK11DEL TESTSOCK6 \
|
||||
JOURNALPRINT ARPANAME RESOLVE RRCHECKER NSLOOKUP DESCRIPTION
|
||||
JOURNALPRINT ARPANAME RESOLVE RRCHECKER NSLOOKUP DESCRIPTION PYTHON
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ my $NAMED = $ENV{'NAMED'};
|
|||
my $LWRESD = $ENV{'LWRESD'};
|
||||
my $DIG = $ENV{'DIG'};
|
||||
my $PERL = $ENV{'PERL'};
|
||||
my $PYTHON = $ENV{'PYTHON'};
|
||||
|
||||
# Start the server(s)
|
||||
|
||||
|
|
@ -233,7 +234,9 @@ sub start_server {
|
|||
$pid_file = "lwresd.pid";
|
||||
} elsif ($server =~ /^ans/) {
|
||||
$cleanup_files = "{ans.run}";
|
||||
if (-e "$testdir/$server/ans.pl") {
|
||||
if (-e "$testdir/$server/ans.py") {
|
||||
$command = "$PYTHON ans.py 10.53.0.$' 5300";
|
||||
} elsif (-e "$testdir/$server/ans.pl") {
|
||||
$command = "$PERL ans.pl";
|
||||
} else {
|
||||
$command = "$PERL $topdir/ans.pl 10.53.0.$'";
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@
|
|||
<section xml:id="relnotes_security"><info><title>Security Fixes</title></info>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Insufficient testing when parsing a message allowed
|
||||
records with an incorrect class to be be accepted,
|
||||
triggering a REQUIRE failure when those records
|
||||
were subsequently cached. This flaw is disclosed
|
||||
in CVE-2015-8000. [RT #4098]
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
An incorrect boundary check in the OPENPGPKEY rdatatype
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef DNS_MESSAGE_H
|
||||
#define DNS_MESSAGE_H 1
|
||||
|
||||
|
|
@ -219,6 +217,8 @@ struct dns_message {
|
|||
unsigned int free_saved : 1;
|
||||
unsigned int sitok : 1;
|
||||
unsigned int sitbad : 1;
|
||||
unsigned int tkey : 1;
|
||||
unsigned int rdclass_set : 1;
|
||||
|
||||
unsigned int opt_reserved;
|
||||
unsigned int sig_reserved;
|
||||
|
|
@ -1398,6 +1398,15 @@ dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt,
|
|||
* \li other.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass);
|
||||
/*%<
|
||||
* Set the expected class of records in the response.
|
||||
*
|
||||
* Requires:
|
||||
* \li msg be a valid message with parsing intent.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_MESSAGE_H */
|
||||
|
|
|
|||
|
|
@ -442,6 +442,8 @@ msginit(dns_message_t *m) {
|
|||
m->free_saved = 0;
|
||||
m->sitok = 0;
|
||||
m->sitbad = 0;
|
||||
m->tkey = 0;
|
||||
m->rdclass_set = 0;
|
||||
m->querytsig = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1094,12 +1096,18 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
* If this class is different than the one we already read,
|
||||
* this is an error.
|
||||
*/
|
||||
if (msg->state == DNS_SECTION_ANY) {
|
||||
msg->state = DNS_SECTION_QUESTION;
|
||||
if (msg->rdclass_set == 0) {
|
||||
msg->rdclass = rdclass;
|
||||
msg->rdclass_set = 1;
|
||||
} else if (msg->rdclass != rdclass)
|
||||
DO_FORMERR;
|
||||
|
||||
/*
|
||||
* Is this a TKEY query?
|
||||
*/
|
||||
if (rdtype == dns_rdatatype_tkey)
|
||||
msg->tkey = 1;
|
||||
|
||||
/*
|
||||
* Can't ask the same question twice.
|
||||
*/
|
||||
|
|
@ -1244,12 +1252,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
* If there was no question section, we may not yet have
|
||||
* established a class. Do so now.
|
||||
*/
|
||||
if (msg->state == DNS_SECTION_ANY &&
|
||||
if (msg->rdclass_set == 0 &&
|
||||
rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
|
||||
rdtype != dns_rdatatype_tsig && /* class is ANY */
|
||||
rdtype != dns_rdatatype_tkey) { /* class is undefined */
|
||||
msg->rdclass = rdclass;
|
||||
msg->state = DNS_SECTION_QUESTION;
|
||||
msg->rdclass_set = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1259,13 +1267,23 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
if (msg->opcode != dns_opcode_update
|
||||
&& rdtype != dns_rdatatype_tsig
|
||||
&& rdtype != dns_rdatatype_opt
|
||||
&& rdtype != dns_rdatatype_dnskey /* in a TKEY query */
|
||||
&& rdtype != dns_rdatatype_key /* in a TKEY query */
|
||||
&& rdtype != dns_rdatatype_sig /* SIG(0) */
|
||||
&& rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
|
||||
&& msg->rdclass != dns_rdataclass_any
|
||||
&& msg->rdclass != rdclass)
|
||||
DO_FORMERR;
|
||||
|
||||
/*
|
||||
* If this is not a TKEY query/response then the KEY
|
||||
* record's class needs to match.
|
||||
*/
|
||||
if (msg->opcode != dns_opcode_update && !msg->tkey &&
|
||||
rdtype == dns_rdatatype_key &&
|
||||
msg->rdclass != dns_rdataclass_any &&
|
||||
msg->rdclass != rdclass)
|
||||
DO_FORMERR;
|
||||
|
||||
/*
|
||||
* Special type handling for TSIG, OPT, and TKEY.
|
||||
*/
|
||||
|
|
@ -1381,6 +1399,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
skip_name_search = ISC_TRUE;
|
||||
skip_type_search = ISC_TRUE;
|
||||
issigzero = ISC_TRUE;
|
||||
} else {
|
||||
if (msg->rdclass != dns_rdataclass_any &&
|
||||
msg->rdclass != rdclass)
|
||||
DO_FORMERR;
|
||||
}
|
||||
} else
|
||||
covers = 0;
|
||||
|
|
@ -1625,6 +1647,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
|
|||
msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
|
||||
|
||||
msg->header_ok = 1;
|
||||
msg->state = DNS_SECTION_QUESTION;
|
||||
|
||||
/*
|
||||
* -1 means no EDNS.
|
||||
|
|
@ -3726,3 +3749,15 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
|
|||
dns_message_puttemprdatalist(message, &rdatalist);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) {
|
||||
|
||||
REQUIRE(DNS_MESSAGE_VALID(msg));
|
||||
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
|
||||
REQUIRE(msg->state == DNS_SECTION_ANY);
|
||||
REQUIRE(msg->rdclass_set == 0);
|
||||
|
||||
msg->rdclass = rdclass;
|
||||
msg->rdclass_set = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7687,6 +7687,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
}
|
||||
|
||||
dns_message_setclass(message, res->rdclass);
|
||||
|
||||
if ((options & DNS_FETCHOPT_TCP) == 0) {
|
||||
if ((options & DNS_FETCHOPT_NOEDNS0) == 0)
|
||||
dns_adb_setudpsize(fctx->adb, query->addrinfo,
|
||||
|
|
@ -7769,6 +7771,13 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
&dns_master_style_comment,
|
||||
ISC_LOG_DEBUG(10),
|
||||
res->mctx);
|
||||
|
||||
if (message->rdclass != res->rdclass) {
|
||||
resend = ISC_TRUE;
|
||||
FCTXTRACE("bad class");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process receive opt record.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1235,6 +1235,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
|||
msg->tsigctx = xfr->tsigctx;
|
||||
xfr->tsigctx = NULL;
|
||||
|
||||
dns_message_setclass(msg, xfr->rdclass);
|
||||
|
||||
if (xfr->nmsg > 0)
|
||||
msg->tcp_continuation = 1;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue