900526
diff --git a/lib/dns/message.c b/lib/dns/message.c
900526
index 869d258..c1f9498 100644
900526
--- a/lib/dns/message.c
900526
+++ b/lib/dns/message.c
900526
@@ -1150,6 +1150,63 @@ update(dns_section_t section, dns_rdataclass_t rdclass) {
900526
 	return (ISC_FALSE);
900526
 }
900526
 
900526
+/*
900526
+ * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have
900526
+ * covering RRSIGs.
900526
+ */
900526
+static isc_boolean_t
900526
+auth_signed(dns_namelist_t *section) {
900526
+	dns_name_t *name;
900526
+
900526
+	for (name = ISC_LIST_HEAD(*section);
900526
+	     name != NULL;
900526
+	     name = ISC_LIST_NEXT(name, link))
900526
+	{
900526
+		int auth_dnssec = 0, auth_rrsig = 0;
900526
+		dns_rdataset_t *rds;
900526
+
900526
+		for (rds = ISC_LIST_HEAD(name->list);
900526
+		     rds != NULL;
900526
+		     rds = ISC_LIST_NEXT(rds, link))
900526
+		{
900526
+			switch (rds->type) {
900526
+			case dns_rdatatype_ds:
900526
+				auth_dnssec |= 0x1;
900526
+				break;
900526
+			case dns_rdatatype_nsec:
900526
+				auth_dnssec |= 0x2;
900526
+				break;
900526
+			case dns_rdatatype_nsec3:
900526
+				auth_dnssec |= 0x4;
900526
+				break;
900526
+			case dns_rdatatype_rrsig:
900526
+				break;
900526
+			default:
900526
+				continue;
900526
+			}
900526
+
900526
+			switch (rds->covers) {
900526
+			case dns_rdatatype_ds:
900526
+				auth_rrsig |= 0x1;
900526
+				break;
900526
+			case dns_rdatatype_nsec:
900526
+				auth_rrsig |= 0x2;
900526
+				break;
900526
+			case dns_rdatatype_nsec3:
900526
+				auth_rrsig |= 0x4;
900526
+				break;
900526
+			default:
900526
+				break;
900526
+			}
900526
+		}
900526
+
900526
+		if (auth_dnssec != auth_rrsig)
900526
+			return (ISC_FALSE);
900526
+	}
900526
+
900526
+	return (ISC_TRUE);
900526
+}
900526
+
900526
 static isc_result_t
900526
 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
900526
 	   dns_section_t sectionid, unsigned int options)
900526
@@ -1175,12 +1232,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
900526
 	best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
900526
 	seen_problem = ISC_FALSE;
900526
 
900526
+	section = &msg->sections[sectionid];
900526
+
900526
 	for (count = 0; count < msg->counts[sectionid]; count++) {
900526
 		int recstart = source->current;
900526
 		isc_boolean_t skip_name_search, skip_type_search;
900526
 
900526
-		section = &msg->sections[sectionid];
900526
-
900526
 		skip_name_search = ISC_FALSE;
900526
 		skip_type_search = ISC_FALSE;
900526
 		free_rdataset = ISC_FALSE;
900526
@@ -1354,7 +1411,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
900526
 			goto cleanup;
900526
 		rdata->rdclass = rdclass;
900526
 		issigzero = ISC_FALSE;
900526
-		if (rdtype == dns_rdatatype_rrsig  &&
900526
+		if (rdtype == dns_rdatatype_rrsig &&
900526
 		    rdata->flags == 0) {
900526
 			covers = dns_rdata_covers(rdata);
900526
 			if (covers == 0)
900526
@@ -1565,6 +1622,19 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
900526
 		INSIST(free_rdataset == ISC_FALSE);
900526
 	}
900526
 
900526
+	/*
900526
+	 * If any of DS, NSEC or NSEC3 appeared in the
900526
+	 * authority section of a query response without
900526
+	 * a covering RRSIG, FORMERR
900526
+	 */
900526
+	if (sectionid == DNS_SECTION_AUTHORITY &&
900526
+	    msg->opcode == dns_opcode_query &&
900526
+	    ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) &&
900526
+	    ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) &&
900526
+	    !preserve_order &&
900526
+	    !auth_signed(section))
900526
+		DO_FORMERR;
900526
+
900526
 	if (seen_problem)
900526
 		return (DNS_R_RECOVERABLE);
900526
 	return (ISC_R_SUCCESS);
900526
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
900526
index 2bc4461..e5600a3 100644
900526
--- a/lib/dns/resolver.c
900526
+++ b/lib/dns/resolver.c
900526
@@ -5194,13 +5194,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
900526
 							      rdataset->type,
900526
 							      &noqname);
900526
 					if (tresult == ISC_R_SUCCESS &&
900526
-					    noqname != NULL) {
900526
-						tresult =
900526
-						     dns_rdataset_addnoqname(
900526
+					    noqname != NULL)
900526
+						(void) dns_rdataset_addnoqname(
900526
 							    rdataset, noqname);
900526
-						RUNTIME_CHECK(tresult ==
900526
-							      ISC_R_SUCCESS);
900526
-					}
900526
 				}
900526
 				addedrdataset = ardataset;
900526
 				result = dns_db_addrdataset(fctx->cache, node,
900526
@@ -5330,11 +5326,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
900526
 				tresult = findnoqname(fctx, name,
900526
 						      rdataset->type, &noqname);
900526
 				if (tresult == ISC_R_SUCCESS &&
900526
-				    noqname != NULL) {
900526
-					tresult = dns_rdataset_addnoqname(
900526
-							    rdataset, noqname);
900526
-					RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
900526
-				}
900526
+				    noqname != NULL)
900526
+					(void) dns_rdataset_addnoqname(
900526
+						       rdataset, noqname);
900526
 			}
900526
 
900526
 			/*