Skip to content

Instantly share code, notes, and snippets.

@Habbie
Created April 26, 2013 11:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Habbie/5466759 to your computer and use it in GitHub Desktop.
Save Habbie/5466759 to your computer and use it in GitHub Desktop.
Patch 2.0
diff -ur pdns-3.1/pdns/packethandler.cc pdns-3.1.new/pdns/packethandler.cc
--- pdns-3.1/pdns/packethandler.cc 2012-05-04 12:13:23.000000000 +0200
+++ pdns-3.1.new/pdns/packethandler.cc 2012-07-28 20:26:50.000000000 +0200
@@ -309,7 +309,7 @@
return ret;
}
-bool PacketHandler::getBestWildcard(DNSPacket *p, SOAData& sd, const string &target, vector<DNSResourceRecord>* ret)
+bool PacketHandler::getBestWildcard(DNSPacket *p, SOAData& sd, const string &target, string &wildcard, vector<DNSResourceRecord>* ret)
{
ret->clear();
DNSResourceRecord rr;
@@ -320,6 +320,7 @@
while(B.get(rr)) {
if(rr.qtype == p->qtype ||rr.qtype.getCode() == QType::CNAME || p->qtype.getCode() == QType::ANY)
ret->push_back(rr);
+ wildcard="*."+subdomain;
haveSomething=true;
}
@@ -486,7 +487,7 @@
// we can leave ttl untouched, either it is the default, or it is what we retrieved above
rr.qtype=QType::NSEC;
rr.content=nrc.getZoneRepresentation();
- rr.d_place = (mode == 2 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
+ rr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
rr.auth = true;
r->addRecord(rr);
@@ -521,7 +522,7 @@
rr.qtype=QType::NSEC3;
rr.content=n3rc.getZoneRepresentation();
- rr.d_place = (mode == 2 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
+ rr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
rr.auth = true;
r->addRecord(rr);
}
@@ -532,19 +533,22 @@
}
-/* mode 0 = no error -> an NSEC that starts with 'target', in authority section
- mode 1 = NXDOMAIN -> an NSEC from auth to first + a covering NSEC
- mode 2 = ANY or direct NSEC request -> an NSEC that starts with 'target'
- mode 3 = a covering NSEC in the authority section (like 1, except for first)
+/*
+ mode 0 = No Data Responses, QTYPE is not DS
+ mode 1 = No Data Responses, QTYPE is DS (can we do this already?)
+ mode 2 = Wildcard No Data Responses
+ mode 3 = Wildcard Answer Responses
+ mode 4 = Name Error Responses
+ mode 5 = ANY or direct NSEC request
*/
-void PacketHandler::addNSECX(DNSPacket *p, DNSPacket *r, const string& target, const string& auth, int mode)
+void PacketHandler::addNSECX(DNSPacket *p, DNSPacket *r, const string& target, const string& target3, const string& auth, int mode)
{
NSEC3PARAMRecordContent ns3rc;
// cerr<<"Doing NSEC3PARAM lookup for '"<<auth<<"', "<<p->qdomain<<"|"<<p->qtype.getName()<<": ";
bool narrow;
if(d_dk.getNSEC3PARAM(auth, &ns3rc, &narrow)) {
// cerr<<"Present, narrow="<<narrow<<endl;
- addNSEC3(p, r, target, auth, ns3rc, narrow, mode);
+ addNSEC3(p, r, target3, auth, ns3rc, narrow, mode);
}
else {
// cerr<<"Not present"<<endl;
@@ -605,7 +609,7 @@
void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, const string& auth, const NSEC3PARAMRecordContent& ns3rc, bool narrow, int mode)
{
- string hashed;
+ // L<<"mode="<<mode<<" target="<<target<<" auth="<<auth<<endl;
SOAData sd;
sd.db = (DNSBackend*)-1;
@@ -614,30 +618,70 @@
return;
}
// cerr<<"salt in ph: '"<<makeHexDump(ns3rc.d_salt)<<"', narrow="<<narrow<<endl;
- string unhashed, before,after;
+ string unhashed, hashed, before, after;
+ string closest(target);
+
+ if (mode == 2 || mode == 3) {
+ chopOff(closest);
+ }
+
+ if (mode == 1 || mode == 4) {
+ DNSResourceRecord rr;
+ while( chopOff( closest ) && (closest != sd.qname)) { // stop at SOA
+ B.lookup(QType(QType::ANY), closest, p, sd.domain_id);
+ if (B.get(rr)) {
+ while(B.get(rr));
+ break;
+ }
+ }
+ }
+
+ // add matching NSEC3 RR
+ if (mode != 3) {
+ if (mode == 0 || mode == 5) {
+ unhashed=target;
+ }
+ else if (mode == 1 || mode == 2 || mode == 4) {
+ unhashed=closest;
+ }
+ else {
+ unhashed=auth;
+ }
+ hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
+ // L<<"1 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl;
+
+ getNSEC3Hashes(narrow, sd.db, sd.domain_id, hashed, false, unhashed, before, after);
+ DLOG(L<<"Done calling for matching, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+ emitNSEC3(ns3rc, sd, unhashed, before, after, target, r, mode);
+ }
- // now add the closest encloser
- unhashed=auth;
- hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
-
- getNSEC3Hashes(narrow, sd.db, sd.domain_id, hashed, false, unhashed, before, after);
- DLOG(L<<"Done calling for closest encloser, before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"', unhashed: '"<<unhashed<<"'"<<endl);
- emitNSEC3(ns3rc, sd, unhashed, before, after, target, r, mode);
-
- // now add the main nsec3
- unhashed = p->qdomain;
- hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
- getNSEC3Hashes(narrow, sd.db,sd.domain_id, hashed, true, unhashed, before, after);
- DLOG(L<<"Done calling for main, before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"', unhashed: '"<<unhashed<<"'"<<endl);
- emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
-
- // now add the *
- unhashed=dotConcat("*", auth);
- hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
-
- getNSEC3Hashes(narrow, sd.db, sd.domain_id, hashed, true, unhashed, before, after);
- DLOG(L<<"Done calling for '*', before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"', unhashed: '"<<unhashed<<"'"<<endl);
- emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+ // add covering NSEC3 RR
+ if (mode != 0 && mode != 5) {
+ string next(p->qdomain);
+ do {
+ unhashed=next;
+ }
+ while( chopOff( next ) && !pdns_iequals(next, closest));
+
+ hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
+ // L<<"2 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl;
+
+ getNSEC3Hashes(narrow, sd.db,sd.domain_id, hashed, true, unhashed, before, after);
+ DLOG(L<<"Done calling for covering, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+ emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+ }
+
+ // wildcard denial
+ if (mode == 4) {
+ unhashed=dotConcat("*", closest);
+
+ hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
+ // L<<"3 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl;
+
+ getNSEC3Hashes(narrow, sd.db, sd.domain_id, hashed, true, unhashed, before, after);
+ DLOG(L<<"Done calling for '*', hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+ emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+ }
}
void PacketHandler::addNSEC(DNSPacket *p, DNSPacket *r, const string& target, const string& auth, int mode)
@@ -659,20 +703,31 @@
string before,after;
//cerr<<"Calling getBeforeandAfter!"<<endl;
- sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
+ if (mode == 2) {
+ sd.db->getBeforeAndAfterNames(sd.domain_id, auth, p->qdomain, before, after);
+ }
+ else {
+ sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
+ }
// cerr<<"Done calling, before='"<<before<<"', after='"<<after<<"'"<<endl;
// this stuff is wrong (but it appears to work)
- if(mode ==0 || mode==2)
+ if(mode == 0 || mode == 1 || mode == 5)
emitNSEC(target, after, target, sd, r, mode);
- if(mode == 1) {
+ if(mode == 2 || mode == 4) {
emitNSEC(before, after, target, sd, r, mode);
- // this one does wildcard denial, if applicable
- sd.db->getBeforeAndAfterNames(sd.domain_id, auth, auth, before, after);
- emitNSEC(before, after, auth, sd, r, mode);
+ if (mode == 2) {
+ sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
+ emitNSEC(target, after, auth, sd, r, mode);
+ }
+ else {
+ // this one does wildcard denial, if applicable
+ sd.db->getBeforeAndAfterNames(sd.domain_id, auth, auth, before, after);
+ emitNSEC(auth, after, auth, sd, r, mode);
+ }
}
if(mode == 3)
@@ -939,13 +994,13 @@
r->addRecord(rr);
if(p->d_dnssecOk && d_dk.isSecuredZone(sd.qname))
- addNSECX(p, r, target, sd.qname, 1);
+ addNSECX(p, r, target, target, sd.qname, 4);
r->setRcode(RCode::NXDomain);
S.ringAccount("nxdomain-queries",p->qdomain+"/"+p->qtype.getName());
}
-void PacketHandler::makeNOError(DNSPacket* p, DNSPacket* r, const std::string& target, SOAData& sd)
+void PacketHandler::makeNOError(DNSPacket* p, DNSPacket* r, const std::string& target, SOAData& sd, int mode)
{
DNSResourceRecord rr;
rr.qname=sd.qname;
@@ -958,7 +1013,7 @@
r->addRecord(rr);
if(p->d_dnssecOk && d_dk.isSecuredZone(sd.qname))
- addNSECX(p, r, target, sd.qname, 0);
+ addNSECX(p, r, target, target, sd.qname, mode);
S.ringAccount("noerror-queries",p->qdomain+"/"+p->qtype.getName());
}
@@ -994,7 +1049,7 @@
r->setA(false);
if(p->d_dnssecOk && d_dk.isSecuredZone(sd.qname) && !addDSforNS(p, r, sd, rrset.begin()->qname))
- addNSECX(p, r, rrset.begin()->qname, sd.qname, 0);
+ addNSECX(p, r, rrset.begin()->qname, rrset.begin()->qname, sd.qname, 1);
return true;
}
@@ -1008,7 +1063,7 @@
if(!d_dk.isSecuredZone(sd.qname))
return;
- addNSECX(p, r, target, sd.qname, 2);
+ addNSECX(p, r, target, target, sd.qname, 5);
if(pdns_iequals(sd.qname, p->qdomain)) {
DNSSECKeeper::keyset_t zskset = d_dk.getKeys(p->qdomain);
DNSResourceRecord rr;
@@ -1023,12 +1078,12 @@
}
}
-bool PacketHandler::tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, string &target, bool& retargeted, bool& nodata)
+bool PacketHandler::tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, string &target, string &wildcard, bool& retargeted, bool& nodata)
{
retargeted = nodata = false;
vector<DNSResourceRecord> rrset;
- if(!getBestWildcard(p, sd, target, &rrset))
+ if(!getBestWildcard(p, sd, target, wildcard, &rrset))
return false;
if(rrset.empty()) {
@@ -1051,8 +1106,8 @@
r->addRecord(rr);
}
}
- if(p->d_dnssecOk && d_dk.isSecuredZone(sd.qname)) {
- addNSECX(p, r, p->qdomain, sd.qname, 3);
+ if(p->d_dnssecOk && d_dk.isSecuredZone(sd.qname) && !nodata) {
+ addNSECX(p, r, p->qdomain, wildcard, sd.qname, 3);
}
return true;
}
@@ -1209,7 +1264,7 @@
// this TRUMPS a cname!
if(p->qtype.getCode() == QType::NSEC && p->d_dnssecOk && d_dk.isSecuredZone(sd.qname) && !d_dk.getNSEC3PARAM(sd.qname, 0)) {
- addNSEC(p, r, target, sd.qname, 2); // only NSEC please
+ addNSEC(p, r, target, sd.qname, 5); // only NSEC please
goto sendit;
}
@@ -1256,7 +1311,7 @@
DLOG(L<<"After first ANY query for '"<<target<<"', id="<<sd.domain_id<<": weDone="<<weDone<<", weHaveUnauth="<<weHaveUnauth<<", weRedirected="<<weRedirected<<endl);
if(p->qtype.getCode() == QType::DS && weHaveUnauth && !weDone && !weRedirected && d_dk.isSecuredZone(sd.qname)) {
DLOG(L<<"Q for DS of a name for which we do have NS, but for which we don't have on a zone with DNSSEC need to provide an AUTH answer that proves we don't"<<endl);
- makeNOError(p, r, target, sd);
+ makeNOError(p, r, target, sd, 1);
goto sendit;
}
@@ -1274,13 +1329,16 @@
DLOG(L<<Logger::Warning<<"Found nothing in the by-name ANY, but let's try wildcards.."<<endl);
bool wereRetargeted(false), nodata(false);
- if(tryWildcard(p, r, sd, target, wereRetargeted, nodata)) {
+ string wildcard;
+ if(tryWildcard(p, r, sd, target, wildcard, wereRetargeted, nodata)) {
if(wereRetargeted) {
retargetcount++;
goto retargeted;
}
- if(nodata)
- makeNOError(p, r, target, sd);
+ if(nodata) {
+ target=wildcard;
+ makeNOError(p, r, target, sd, 2);
+ }
goto sendit;
}
else
@@ -1321,7 +1379,7 @@
}
else {
DLOG(L<<"Have some data, but not the right data"<<endl);
- makeNOError(p, r, target, sd);
+ makeNOError(p, r, target, sd, 0);
}
sendit:;
diff -ur pdns-3.1/pdns/packethandler.hh pdns-3.1.new/pdns/packethandler.hh
--- pdns-3.1/pdns/packethandler.hh 2012-05-04 12:13:23.000000000 +0200
+++ pdns-3.1.new/pdns/packethandler.hh 2012-07-27 14:33:20.000000000 +0200
@@ -98,7 +98,7 @@
bool getTLDAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);
int doAdditionalProcessingAndDropAA(DNSPacket *p, DNSPacket *r, const SOAData& sd);
bool doDNSSECProcessing(DNSPacket* p, DNSPacket *r);
- void addNSECX(DNSPacket *p, DNSPacket* r, const string &target, const std::string& auth, int mode);
+ void addNSECX(DNSPacket *p, DNSPacket* r, const string &target, const string& target3, const std::string& auth, int mode);
void addNSEC(DNSPacket *p, DNSPacket* r, const string &target, const std::string& auth, int mode);
void addNSEC3(DNSPacket *p, DNSPacket* r, const string &target, const std::string& auth, const NSEC3PARAMRecordContent& nsec3param, bool narrow, int mode);
void emitNSEC(const std::string& before, const std::string& after, const std::string& toNSEC, const SOAData& sd, DNSPacket *r, int mode);
@@ -107,12 +107,12 @@
void synthesiseRRSIGs(DNSPacket* p, DNSPacket* r);
void makeNXDomain(DNSPacket* p, DNSPacket* r, const std::string& target, SOAData& sd);
- void makeNOError(DNSPacket* p, DNSPacket* r, const std::string& target, SOAData& sd);
+ void makeNOError(DNSPacket* p, DNSPacket* r, const std::string& target, SOAData& sd, int mode);
vector<DNSResourceRecord> getBestReferralNS(DNSPacket *p, SOAData& sd, const string &target);
bool tryReferral(DNSPacket *p, DNSPacket*r, SOAData& sd, const string &target);
- bool getBestWildcard(DNSPacket *p, SOAData& sd, const string &target, vector<DNSResourceRecord>* ret);
- bool tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, string &target, bool& retargeted, bool& nodata);
+ bool getBestWildcard(DNSPacket *p, SOAData& sd, const string &target, string &wildcard, vector<DNSResourceRecord>* ret);
+ bool tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, string &target, string &wildcard, bool& retargeted, bool& nodata);
bool addDSforNS(DNSPacket* p, DNSPacket* r, SOAData& sd, const string& dsname);
void completeANYRecords(DNSPacket *p, DNSPacket*r, SOAData& sd, const string &target);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment