An RRSIG whose Type-Covered field is RRSIG is not a meta-type, so it
passed the message parser, and for an insecure domain the resolver
cached it as a standalone signature. The QP cache pairs every RRSIG
header with the non-signature header it covers and never expects the
covered type to itself be a signature, so a signature covering a
signature broke that invariant and aborted named on a crafted response.
Reject the record in the parser, and tighten the cache precondition so
a positive signature header must cover a non-signature type.
covers = dns_rdata_covers(rdata);
/* A signature can only cover a real rdata type */
if (covers == dns_rdatatype_none ||
- dns_rdatatype_ismeta(covers))
+ dns_rdatatype_ismeta(covers) ||
+ dns_rdatatype_issig(covers))
{
DO_ERROR(DNS_R_FORMERR);
}
REQUIRE(rdtype != dns_rdatatype_none);
if (dns_rdatatype_issig(rdtype)) {
- /* signature must be either negative or cover something */
- REQUIRE(NEGATIVE(newheader) || covers != dns_rdatatype_none);
+ /*
+ * signature must be either negative or cover something
+ * that's not a signature
+ */
+ REQUIRE(NEGATIVE(newheader) || (covers != dns_rdatatype_none &&
+ !dns_rdatatype_issig(covers)));
} else {
/* non-signature it must cover nothing */
REQUIRE(covers == dns_rdatatype_none);