You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.3 KiB
179 lines
5.3 KiB
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h |
|
index a6862fa..d999e75 100644 |
|
--- a/lib/dns/include/dns/message.h |
|
+++ b/lib/dns/include/dns/message.h |
|
@@ -210,6 +210,8 @@ struct dns_message { |
|
unsigned int verify_attempted : 1; |
|
unsigned int free_query : 1; |
|
unsigned int free_saved : 1; |
|
+ unsigned int tkey : 1; |
|
+ unsigned int rdclass_set : 1; |
|
|
|
unsigned int opt_reserved; |
|
unsigned int sig_reserved; |
|
@@ -1374,6 +1376,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 */ |
|
diff --git a/lib/dns/message.c b/lib/dns/message.c |
|
index 53efc5a..73def73 100644 |
|
--- a/lib/dns/message.c |
|
+++ b/lib/dns/message.c |
|
@@ -436,6 +436,8 @@ msginit(dns_message_t *m) { |
|
m->saved.base = NULL; |
|
m->saved.length = 0; |
|
m->free_saved = 0; |
|
+ m->tkey = 0; |
|
+ m->rdclass_set = 0; |
|
m->querytsig = NULL; |
|
} |
|
|
|
@@ -1086,13 +1088,19 @@ 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. |
|
*/ |
|
result = dns_message_find(name, rdclass, rdtype, 0, NULL); |
|
@@ -1236,12 +1244,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; |
|
} |
|
|
|
/* |
|
@@ -1251,7 +1259,7 @@ 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 |
|
@@ -1259,6 +1267,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, |
|
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. |
|
*/ |
|
if (rdtype == dns_rdatatype_tsig) { |
|
@@ -1372,6 +1390,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; |
|
@@ -1610,6 +1632,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. |
|
@@ -3550,3 +3573,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; |
|
+} |
|
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c |
|
index aa23b11..d220986 100644 |
|
--- a/lib/dns/resolver.c |
|
+++ b/lib/dns/resolver.c |
|
@@ -6964,6 +6964,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) { |
|
goto done; |
|
} |
|
|
|
+ dns_message_setclass(message, fctx->res->rdclass); |
|
+ |
|
result = dns_message_parse(message, &devent->buffer, 0); |
|
if (result != ISC_R_SUCCESS) { |
|
switch (result) { |
|
@@ -7036,6 +7038,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) { |
|
*/ |
|
log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); |
|
|
|
+ if (message->rdclass != fctx->res->rdclass) { |
|
+ resend = ISC_TRUE; |
|
+ FCTXTRACE("bad class"); |
|
+ goto done; |
|
+ } |
|
+ |
|
/* |
|
* Process receive opt record. |
|
*/ |
|
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c |
|
index 9ad8960..938373a 100644 |
|
--- a/lib/dns/xfrin.c |
|
+++ b/lib/dns/xfrin.c |
|
@@ -1241,6 +1241,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; |
|
|
|
|