|
|
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 |
/*
|