We are aware of the issue. This is the proposed fix. This will be
part of the next Coverity run (roughly weekly).
Mark
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 397048e..d02a5e7 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -6834,10 +6834,10 @@ answer_response(fetchctx_t *fctx) {
dns_name_t *name, *dname = NULL, *qname, tname, *ns_name;
dns_name_t *cname = NULL;
dns_rdataset_t *rdataset, *ns_rdataset;
- isc_boolean_t done, external, chaining, aa, found, want_chaining;
+ isc_boolean_t done, external, aa, found, want_chaining;
isc_boolean_t have_answer, found_cname, found_dname, found_type;
isc_boolean_t wanted_chaining;
- unsigned int aflag;
+ unsigned int aflag, chaining;
dns_rdatatype_t type;
dns_fixedname_t fdname, fqname;
dns_view_t *view;
@@ -6855,9 +6855,9 @@ answer_response(fetchctx_t *fctx) {
found_cname = ISC_FALSE;
found_dname = ISC_FALSE;
found_type = ISC_FALSE;
- chaining = ISC_FALSE;
have_answer = ISC_FALSE;
want_chaining = ISC_FALSE;
+ chaining = 0;
POST(want_chaining);
if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
aa = ISC_TRUE;
@@ -7004,7 +7004,7 @@ answer_response(fetchctx_t *fctx) {
rdataset->attributes |=
DNS_RDATASETATTR_CACHE;
rdataset->trust = dns_trust_answer;
- if (!chaining) {
+ if (chaining == 0) {
/*
* This data is "the" answer
* to our question only if
@@ -7081,8 +7081,8 @@ answer_response(fetchctx_t *fctx) {
* cause us to ignore the signatures of
* CNAMEs.
*/
- if (wanted_chaining)
- chaining = ISC_TRUE;
+ if (wanted_chaining && chaining < 2U)
+ chaining++;
} else {
dns_rdataset_t *dnameset = NULL;
@@ -7113,7 +7113,7 @@ answer_response(fetchctx_t *fctx) {
* If we're not chaining, then the DNAME and
* its signature should not be external.
*/
- if (!chaining && external) {
+ if (chaining == 0 && external) {
char qbuf[DNS_NAME_FORMATSIZE];
char obuf[DNS_NAME_FORMATSIZE];
@@ -7197,7 +7197,14 @@ answer_response(fetchctx_t *fctx) {
name->attributes |= DNS_NAMEATTR_CACHE;
rdataset->attributes |= DNS_RDATASETATTR_CACHE;
rdataset->trust = dns_trust_answer;
- if (!chaining) {
+ /*
+ * If we are not chaining or the first CNAME
+ * is a synthesised CNAME before the DNAME.
+ */
+ if ((chaining == 0) ||
+ (chaining == 1U &&
+ namereln == dns_namereln_commonancestor))
+ {
/*
* This data is "the" answer to
* our question only if we're
@@ -7245,8 +7252,12 @@ answer_response(fetchctx_t *fctx) {
dnameset->attributes |=
DNS_RDATASETATTR_CHAINING;
}
- if (wanted_chaining)
- chaining = ISC_TRUE;
+ /*
+ * Ensure that we can't ever get chaining == 1
+ * above if we have processed a DNAME.
+ */
+ if (wanted_chaining && chaining < 2U)
+ chaining += 2;
}
result = dns_message_nextname(message, DNS_SECTION_ANSWER);
}
@@ -7271,7 +7282,7 @@ answer_response(fetchctx_t *fctx) {
/*
* Did chaining end before we got the final answer?
*/
- if (chaining) {
+ if (chaining != 0) {
/*
* Yes. This may be a negative reply, so hand off
* authority section processing to the noanswer code.
@@ -7320,7 +7331,7 @@ answer_response(fetchctx_t *fctx) {
DNS_NAMEATTR_CACHE;
rdataset->attributes |=
DNS_RDATASETATTR_CACHE;
- if (aa && !chaining)
+ if (aa && chaining == 0)
rdataset->trust =
dns_trust_authauthority;
else
--
Mark Andrews, ISC
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742 INTERNET: marka@isc.org