Skip to content

Commit feef1ec

Browse files
author
Peter van Dijk
committed
fix missing NSEC3 for secure delegation, thanks @mind04, closes #682
1 parent 1df6d21 commit feef1ec

File tree

3 files changed

+50
-36
lines changed

3 files changed

+50
-36
lines changed

pdns/tcpreceiver.cc

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ namespace {
454454
{
455455
set<uint16_t> d_set;
456456
unsigned int d_ttl;
457+
bool d_auth;
457458
};
458459

459460
DNSResourceRecord makeDNSRRFromSOAData(const SOAData& sd)
@@ -651,11 +652,12 @@ int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int out
651652
continue;
652653

653654
records++;
654-
if(securedZone && (rr.auth || (!NSEC3Zone && rr.qtype.getCode() == QType::NS) || rr.qtype.getCode() == QType::DS)) { // this is probably NSEC specific, NSEC3 is different
655+
if(securedZone && (rr.auth || rr.qtype.getCode() == QType::NS)) {
655656
if (NSEC3Zone || rr.qtype.getCode()) {
656657
keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
657658
NSECXEntry& ne = nsecxrepo[keyname];
658659
ne.d_ttl = sd.default_ttl;
660+
ne.d_auth = (ne.d_auth || rr.auth);
659661
if (rr.qtype.getCode()) {
660662
ne.d_set.insert(rr.qtype.getCode());
661663
}
@@ -689,42 +691,49 @@ int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int out
689691
cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
690692
cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
691693
*/
692-
if(securedZone) {
694+
if(securedZone) {
693695
if(NSEC3Zone) {
694696
for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
695-
NSEC3RecordContent n3rc;
696-
n3rc.d_set = iter->second.d_set;
697-
if (n3rc.d_set.size())
698-
n3rc.d_set.insert(QType::RRSIG);
699-
n3rc.d_salt=ns3pr.d_salt;
700-
n3rc.d_flags = ns3pr.d_flags;
701-
n3rc.d_iterations = ns3pr.d_iterations;
702-
n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now
703-
if(boost::next(iter) != nsecxrepo.end()) {
704-
n3rc.d_nexthash = boost::next(iter)->first;
705-
}
706-
else
707-
n3rc.d_nexthash=nsecxrepo.begin()->first;
708-
709-
rr.qname = dotConcat(toLower(toBase32Hex(iter->first)), sd.qname);
710-
711-
rr.ttl = sd.default_ttl;
712-
rr.content = n3rc.getZoneRepresentation();
713-
rr.qtype = QType::NSEC3;
714-
rr.d_place = DNSResourceRecord::ANSWER;
715-
rr.auth=true;
716-
if(csp.submit(rr)) {
717-
for(;;) {
718-
outpacket->getRRS() = csp.getChunk();
719-
if(!outpacket->getRRS().empty()) {
720-
if(!tsigkeyname.empty())
721-
outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
722-
sendPacket(outpacket, outsock);
723-
trc.d_mac=outpacket->d_trc.d_mac;
724-
outpacket=getFreshAXFRPacket(q);
697+
if(iter->second.d_auth) {
698+
NSEC3RecordContent n3rc;
699+
n3rc.d_set = iter->second.d_set;
700+
if (n3rc.d_set.size() && (n3rc.d_set.size() != 1 || !n3rc.d_set.count(QType::NS)))
701+
n3rc.d_set.insert(QType::RRSIG);
702+
n3rc.d_salt=ns3pr.d_salt;
703+
n3rc.d_flags = ns3pr.d_flags;
704+
n3rc.d_iterations = ns3pr.d_iterations;
705+
n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now
706+
nsecxrepo_t::const_iterator inext = iter;
707+
inext++;
708+
if(inext == nsecxrepo.end())
709+
inext = nsecxrepo.begin();
710+
while(!(inext->second.d_auth) && inext != iter)
711+
{
712+
inext++;
713+
if(inext == nsecxrepo.end())
714+
inext = nsecxrepo.begin();
715+
}
716+
n3rc.d_nexthash = inext->first;
717+
rr.qname = dotConcat(toLower(toBase32Hex(iter->first)), sd.qname);
718+
719+
rr.ttl = sd.default_ttl;
720+
rr.content = n3rc.getZoneRepresentation();
721+
rr.qtype = QType::NSEC3;
722+
rr.d_place = DNSResourceRecord::ANSWER;
723+
rr.auth=true;
724+
if(csp.submit(rr)) {
725+
for(;;) {
726+
outpacket->getRRS() = csp.getChunk();
727+
if(!outpacket->getRRS().empty()) {
728+
if(!tsigkeyname.empty())
729+
outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
730+
sendPacket(outpacket, outsock);
731+
trc.d_mac=outpacket->d_trc.d_mac;
732+
outpacket=getFreshAXFRPacket(q);
733+
}
734+
else
735+
break;
725736
}
726-
else
727-
break;
728737
}
729738
}
730739
}

regression-tests/dnssec-parent.com

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ delegated IN NS ns1.delegated.dnssec-parent.com.
1616
delegated IN NS ns2.delegated.dnssec-parent.com.
1717
ns1.delegated IN A 4.5.6.7
1818
ns2.delegated IN A 5.6.7.8
19+
secure-delegated IN DS 54319 8 2 a0b9c38cd324182af0ef66830d0a0e85a1d58979c9834e18c871779e040857b7
20+
secure-delegated IN NS ns1.secure-delegated.dnssec-parent.com.
21+
secure-delegated IN NS ns2.secure-delegated.dnssec-parent.com.
22+
ns1.secure-delegated IN A 1.2.3.4
23+
ns2.secure-delegated IN A 5.6.7.8
1924

regression-tests/ds-at-unsecure-zone-cut/expected_result.nsec3

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
1 29ceqcf4ekgl2gr9i0vjjtk62h5lqs40.dnssec-parent.com. IN NSEC3 86400 1 1 1 abcd DVKUO8KJA65GCSQ600E6DI9U719LSJ8U A RRSIG
2-
1 29ceqcf4ekgl2gr9i0vjjtk62h5lqs40.dnssec-parent.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
1+
1 7on3vems0f8k9999ikei0ig4lfijekdr.dnssec-parent.com. IN NSEC3 86400 1 1 1 abcd DVKUO8KJA65GCSQ600E6DI9U719LSJ8U NS DS RRSIG
2+
1 7on3vems0f8k9999ikei0ig4lfijekdr.dnssec-parent.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
33
1 dnssec-parent.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
44
1 dnssec-parent.com. IN SOA 3600 ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
55
1 dvkuo8kja65gcsq600e6di9u719lsj8u.dnssec-parent.com. IN NSEC3 86400 1 1 1 abcd 1SCAQA30LQ0DO5EIRNE4KPJFBEBFGR54 A NS SOA RRSIG DNSKEY NSEC3PARAM

0 commit comments

Comments
 (0)