mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 14:19:59 -04:00
4517. [security] Named could mishandle authority sections that were
missing RRSIGs triggering an assertion failure.
(CVE-2016-9444) [RT # 43632]
(cherry picked from commit 1df30cfd27c5a3c57fce357c54aaf6c702227d51)
This commit is contained in:
parent
7b1835c467
commit
f3bf3905c3
3 changed files with 84 additions and 17 deletions
4
CHANGES
4
CHANGES
|
|
@ -88,7 +88,9 @@
|
|||
compatibility, "yes" is a synonym for "local".
|
||||
[RT #42585]
|
||||
|
||||
4517. [placeholder]
|
||||
4517. [security] Named could mishandle authority sections that were
|
||||
missing RRSIGs triggering an assertion failure.
|
||||
(CVE-2016-9444) [RT # 43632]
|
||||
|
||||
4516. [bug] isc_socketmgr_renderjson was missing from the
|
||||
windows build. [RT #43602]
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,63 @@ update(dns_section_t section, dns_rdataclass_t rdclass) {
|
|||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have
|
||||
* covering RRSIGs.
|
||||
*/
|
||||
static isc_boolean_t
|
||||
auth_signed(dns_namelist_t *section) {
|
||||
dns_name_t *name;
|
||||
|
||||
for (name = ISC_LIST_HEAD(*section);
|
||||
name != NULL;
|
||||
name = ISC_LIST_NEXT(name, link))
|
||||
{
|
||||
int auth_dnssec = 0, auth_rrsig = 0;
|
||||
dns_rdataset_t *rds;
|
||||
|
||||
for (rds = ISC_LIST_HEAD(name->list);
|
||||
rds != NULL;
|
||||
rds = ISC_LIST_NEXT(rds, link))
|
||||
{
|
||||
switch (rds->type) {
|
||||
case dns_rdatatype_ds:
|
||||
auth_dnssec |= 0x1;
|
||||
break;
|
||||
case dns_rdatatype_nsec:
|
||||
auth_dnssec |= 0x2;
|
||||
break;
|
||||
case dns_rdatatype_nsec3:
|
||||
auth_dnssec |= 0x4;
|
||||
break;
|
||||
case dns_rdatatype_rrsig:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (rds->covers) {
|
||||
case dns_rdatatype_ds:
|
||||
auth_rrsig |= 0x1;
|
||||
break;
|
||||
case dns_rdatatype_nsec:
|
||||
auth_rrsig |= 0x2;
|
||||
break;
|
||||
case dns_rdatatype_nsec3:
|
||||
auth_rrsig |= 0x4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (auth_dnssec != auth_rrsig)
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
dns_section_t sectionid, unsigned int options)
|
||||
|
|
@ -1175,12 +1232,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
|
||||
seen_problem = ISC_FALSE;
|
||||
|
||||
section = &msg->sections[sectionid];
|
||||
|
||||
for (count = 0; count < msg->counts[sectionid]; count++) {
|
||||
int recstart = source->current;
|
||||
isc_boolean_t skip_name_search, skip_type_search;
|
||||
|
||||
section = &msg->sections[sectionid];
|
||||
|
||||
skip_name_search = ISC_FALSE;
|
||||
skip_type_search = ISC_FALSE;
|
||||
free_rdataset = ISC_FALSE;
|
||||
|
|
@ -1354,7 +1411,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
goto cleanup;
|
||||
rdata->rdclass = rdclass;
|
||||
issigzero = ISC_FALSE;
|
||||
if (rdtype == dns_rdatatype_rrsig &&
|
||||
if (rdtype == dns_rdatatype_rrsig &&
|
||||
rdata->flags == 0) {
|
||||
covers = dns_rdata_covers(rdata);
|
||||
if (covers == 0)
|
||||
|
|
@ -1565,6 +1622,19 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
|||
INSIST(free_rdataset == ISC_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If any of DS, NSEC or NSEC3 appeared in the
|
||||
* authority section of a query response without
|
||||
* a covering RRSIG, FORMERR
|
||||
*/
|
||||
if (sectionid == DNS_SECTION_AUTHORITY &&
|
||||
msg->opcode == dns_opcode_query &&
|
||||
((msg->flags & DNS_MESSAGEFLAG_QR) != 0) &&
|
||||
((msg->flags & DNS_MESSAGEFLAG_TC) == 0) &&
|
||||
!preserve_order &&
|
||||
!auth_signed(section))
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
|
||||
if (seen_problem)
|
||||
return (DNS_R_RECOVERABLE);
|
||||
return (ISC_R_SUCCESS);
|
||||
|
|
|
|||
|
|
@ -5525,16 +5525,13 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
|
|||
rdataset->type,
|
||||
&noqname);
|
||||
if (tresult == ISC_R_SUCCESS &&
|
||||
noqname != NULL) {
|
||||
tresult =
|
||||
dns_rdataset_addnoqname(
|
||||
noqname != NULL)
|
||||
(void) dns_rdataset_addnoqname(
|
||||
rdataset, noqname);
|
||||
RUNTIME_CHECK(tresult ==
|
||||
ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
|
||||
options = DNS_DBADD_PREFETCH;
|
||||
if ((fctx->options &
|
||||
DNS_FETCHOPT_PREFETCH) != 0)
|
||||
options = DNS_DBADD_PREFETCH;
|
||||
addedrdataset = ardataset;
|
||||
result = dns_db_addrdataset(fctx->cache, node,
|
||||
NULL, now, rdataset,
|
||||
|
|
@ -5667,11 +5664,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
|
|||
tresult = findnoqname(fctx, name,
|
||||
rdataset->type, &noqname);
|
||||
if (tresult == ISC_R_SUCCESS &&
|
||||
noqname != NULL) {
|
||||
tresult = dns_rdataset_addnoqname(
|
||||
rdataset, noqname);
|
||||
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
|
||||
}
|
||||
noqname != NULL)
|
||||
(void) dns_rdataset_addnoqname(
|
||||
rdataset, noqname);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue