From: Pieter Lexis Date: Wed, 6 Mar 2019 12:34:21 +0000 (+0100) Subject: DNAME: synthesize and check CNAME from response X-Git-Tag: rec-4.2.0-beta1~6^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee9360745e74862a148e35b6a1b47474f420c678;p=thirdparty%2Fpdns.git DNAME: synthesize and check CNAME from response --- diff --git a/pdns/syncres.cc b/pdns/syncres.cc index f5d14e1307..db3dd5512b 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1045,11 +1045,20 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector } auto dnameSuffix = dnameRR->getTarget(); DNSName targetPrefix = qname.makeRelative(foundName); - dr.d_type = QType::CNAME; - dr.d_name = targetPrefix + foundName; - newTarget = targetPrefix + dnameSuffix; - dr.d_content = std::make_shared(CNAMERecordContent(newTarget)); - ret.push_back(dr); + try { + dr.d_type = QType::CNAME; + dr.d_name = targetPrefix + foundName; + newTarget = targetPrefix + dnameSuffix; + dr.d_content = std::make_shared(CNAMERecordContent(newTarget)); + ret.push_back(dr); + } catch (const std::exception &e) { + // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2) + // But this is consistent with processRecords + throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + foundName.toLogString() + + "', DNAME target: '" + dnameSuffix.toLogString() + "', substituted name: '" + + targetPrefix.toLogString() + "." + dnameSuffix.toLogString() + + "' : " + e.what()); + } LOG(prefix< 0 && // CNAME or DNAME answer s_redirectionQTypes.count(qtype.getCode()) == 0) { // But not in response to a CNAME or DNAME query if (rec.d_type == QType::CNAME && rec.d_name == qname) { + if (!dnameOwner.empty()) { // We synthesize ourselves + continue; + } ret.push_back(rec); if (auto content = getRR(rec)) { newtarget=content->getTarget(); @@ -2608,6 +2621,17 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co if (auto content = getRR(rec)) { dnameOwner = rec.d_name; dnameTarget = content->getTarget(); + dnameTTL = rec.d_ttl; + try { + newtarget = qname.makeRelative(dnameOwner) + dnameTarget; + } catch (const std::exception &e) { + // We should probably catch an std::range_error here and set the rcode to YXDOMAIN (RFC 6672, section 2.2) + // But there is no way to set the RCODE from this function + throw ImmediateServFailException("Unable to perform DNAME substitution(DNAME owner: '" + dnameOwner.toLogString() + + "', DNAME target: '" + dnameTarget.toLogString() + "', substituted name: '" + + qname.makeRelative(dnameOwner).toLogString() + "." + dnameTarget.toLogString() + + "' : " + e.what()); + } } } } @@ -2760,13 +2784,14 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co } } - if (!dnameTarget.empty() && !newtarget.empty()) { - DNSName substTarget = qname.makeRelative(dnameOwner) + dnameTarget; - if (substTarget != newtarget) { - throw ImmediateServFailException("Received wrong DNAME substitution. qname='" + qname.toLogString() + - "', DNAME owner='" + dnameOwner.toLogString() + "', DNAME target='" + dnameTarget.toLogString() + - "', received CNAME='" + newtarget.toLogString() + "', substituted CNAME='" + substTarget.toLogString() + "'"); - } + if (!dnameTarget.empty()) { + // Synthesize a CNAME + auto cnamerec = DNSRecord(); + cnamerec.d_name = qname; + cnamerec.d_type = QType::CNAME; + cnamerec.d_ttl = dnameTTL; + cnamerec.d_content = std::make_shared(CNAMERecordContent(newtarget)); + ret.push_back(cnamerec); } return done; }