From: Pieter Lexis Date: Wed, 4 Oct 2017 14:20:07 +0000 (+0200) Subject: Move rectifyZone from pdnsutil to DNSSECKeeper X-Git-Tag: rec-4.1.0-rc2~36^2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=25b1ce1347e677e6c64dbf2312046883ecb8bc0b;p=pdns Move rectifyZone from pdnsutil to DNSSECKeeper --- diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc index 86e89f7e3..514043216 100644 --- a/pdns/dbdnsseckeeper.cc +++ b/pdns/dbdnsseckeeper.cc @@ -35,6 +35,7 @@ #include #include // for 'operator+=()' #include +#include "base32.hh" #include "base64.hh" #include "cachecleaner.hh" #include "arguments.hh" @@ -563,6 +564,181 @@ bool DNSSECKeeper::getTSIGForAccess(const DNSName& zone, const string& master, D return false; } +bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error) { + if (isPresigned(zone)) { + error = "Rectify presigned zone '"+zone.toLogString()+"' is not allowed/necessary."; + return false; + } + + UeberBackend B("default"); + SOAData sd; + + if(!B.getSOAUncached(zone, sd)) { + error = "No SOA known for '" + zone.toLogString() + "', is such a zone in the database?"; + return false; + } + + sd.db->list(zone, sd.domain_id); + + DNSResourceRecord rr; + set qnames, nsset, dsnames, insnonterm, delnonterm; + map nonterm; + vector rrs; + + while(sd.db->get(rr)) { + rr.qname.makeUsLowerCase(); + if (rr.qtype.getCode()) + { + rrs.push_back(rr); + qnames.insert(rr.qname); + if(rr.qtype.getCode() == QType::NS && rr.qname != zone) + nsset.insert(rr.qname); + if(rr.qtype.getCode() == QType::DS) + dsnames.insert(rr.qname); + } + else + delnonterm.insert(rr.qname); + } + + NSEC3PARAMRecordContent ns3pr; + bool narrow; + bool haveNSEC3 = getNSEC3PARAM(zone, &ns3pr, &narrow); + bool isOptOut = (haveNSEC3 && ns3pr.d_flags); + + set nsec3set; + if (haveNSEC3 && !narrow) { + for (auto &rr: rrs) { + bool skip=false; + DNSName shorter = rr.qname; + if (shorter != zone && shorter.chopOff() && shorter != zone) { + do { + if(nsset.count(shorter)) { + skip=true; + break; + } + } while(shorter.chopOff() && shorter != zone); + } + shorter = rr.qname; + if(!skip && (rr.qtype.getCode() != QType::NS || !isOptOut)) { + + do { + if(!nsec3set.count(shorter)) { + nsec3set.insert(shorter); + } + } while(shorter != zone && shorter.chopOff()); + } + } + } + + sd.db->startTransaction(zone, -1); + + bool realrr=true; + bool doent=true; + uint32_t maxent = ::arg().asNum("max-ent-entries"); + + dononterm:; + for (const auto& qname: qnames) + { + bool auth=true; + DNSName ordername; + auto shorter(qname); + + if(realrr) { + do { + if(nsset.count(shorter)) { + auth=false; + break; + } + } while(shorter.chopOff()); + } else { + auth=nonterm.find(qname)->second; + } + + if(haveNSEC3) // NSEC3 + { + if(!narrow && nsec3set.count(qname)) { + ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, qname))); + if(!realrr) + auth=true; + } else if(!realrr) + auth=false; + } + else if (realrr) // NSEC + ordername=qname.makeRelative(zone); + + /* + if(g_verbose) + cerr<<"'"< '"<< ordername <<"'"<updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, auth); + + if(realrr) + { + if (dsnames.count(qname)) + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, true, QType::DS); + if (!auth || nsset.count(qname)) { + ordername.clear(); + if(isOptOut && !dsnames.count(qname)) + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::NS); + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::A); + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::AAAA); + } + + if(doent) + { + shorter=qname; + while(shorter!=zone && shorter.chopOff()) + { + if(!qnames.count(shorter)) + { + if(!(maxent)) + { + L<(shorter, auth)); + --maxent; + } else if (auth) + nonterm[shorter]=true; + } + } + } + } + } + + if(realrr) + { + //cerr<<"Total: "<updateEmptyNonTerminals(sd.domain_id, insnonterm, delnonterm, !doent); + } + if(doent) + { + realrr=false; + qnames.clear(); + for(const auto& nt : nonterm){ + qnames.insert(nt.first); + } + goto dononterm; + } + } + + sd.db->commitTransaction(); + + return true; +} + void DNSSECKeeper::cleanup() { struct timeval now; diff --git a/pdns/dnsseckeeper.hh b/pdns/dnsseckeeper.hh index a84e49762..12ba75480 100644 --- a/pdns/dnsseckeeper.hh +++ b/pdns/dnsseckeeper.hh @@ -209,6 +209,7 @@ public: void getFromMeta(const DNSName& zname, const std::string& key, std::string& value); void getSoaEdit(const DNSName& zname, std::string& value); + bool rectifyZone(const DNSName& zone, std::string& error); private: diff --git a/pdns/pdnsutil.cc b/pdns/pdnsutil.cc index db522db8d..d2e6900ef 100644 --- a/pdns/pdnsutil.cc +++ b/pdns/pdnsutil.cc @@ -135,196 +135,14 @@ void loadMainConfig(const std::string& configdir) UeberBackend::go(); } -// irritatingly enough, rectifyZone needs its own ueberbackend and can't therefore benefit from transactions outside its scope -// I think this has to do with interlocking transactions between B and DK, but unsure. bool rectifyZone(DNSSECKeeper& dk, const DNSName& zone) { - if(dk.isPresigned(zone)){ - cerr<<"Rectify presigned zone '"<list(zone, sd.domain_id); - - DNSResourceRecord rr; - set qnames, nsset, dsnames, insnonterm, delnonterm; - map nonterm; - vector rrs; - - while(sd.db->get(rr)) { - rr.qname.makeUsLowerCase(); - if (rr.qtype.getCode()) - { - rrs.push_back(rr); - qnames.insert(rr.qname); - if(rr.qtype.getCode() == QType::NS && rr.qname != zone) - nsset.insert(rr.qname); - if(rr.qtype.getCode() == QType::DS) - dsnames.insert(rr.qname); - } - else - delnonterm.insert(rr.qname); - } - - NSEC3PARAMRecordContent ns3pr; - bool narrow; - bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow); - bool isOptOut=(haveNSEC3 && ns3pr.d_flags); - if(dk.isSecuredZone(zone)) - { - if(!haveNSEC3) - cerr<<"Adding NSEC ordering information "< nsec3set; - if (haveNSEC3 && !narrow) { - for (auto &rr: rrs) { - bool skip=false; - DNSName shorter = rr.qname; - if (shorter != zone && shorter.chopOff() && shorter != zone) { - do { - if(nsset.count(shorter)) { - skip=true; - break; - } - } while(shorter.chopOff() && shorter != zone); - } - shorter = rr.qname; - if(!skip && (rr.qtype.getCode() != QType::NS || !isOptOut)) { - - do { - if(!nsec3set.count(shorter)) { - nsec3set.insert(shorter); - } - } while(shorter != zone && shorter.chopOff()); - } - } - } - - if(doTransaction) - sd.db->startTransaction(zone, -1); - - bool realrr=true; - bool doent=true; - uint32_t maxent = ::arg().asNum("max-ent-entries"); - - dononterm:; - for (const auto& qname: qnames) - { - bool auth=true; - DNSName ordername; - auto shorter(qname); - - if(realrr) { - do { - if(nsset.count(shorter)) { - auth=false; - break; - } - } while(shorter.chopOff()); - } else { - auth=nonterm.find(qname)->second; - } - - if(haveNSEC3) // NSEC3 - { - if(!narrow && nsec3set.count(qname)) { - ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, qname))); - if(!realrr) - auth=true; - } else if(!realrr) - auth=false; - } - else if (realrr) // NSEC - ordername=qname.makeRelative(zone); - - if(g_verbose) - cerr<<"'"< '"<< ordername <<"'"<updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, auth); - - if(realrr) - { - if (dsnames.count(qname)) - sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, true, QType::DS); - if (!auth || nsset.count(qname)) { - ordername.clear(); - if(isOptOut && !dsnames.count(qname)) - sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::NS); - sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::A); - sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::AAAA); - } - - if(doent) - { - shorter=qname; - while(shorter!=zone && shorter.chopOff()) - { - if(!qnames.count(shorter)) - { - if(!(maxent)) - { - cerr<<"Zone '"<(shorter, auth)); - --maxent; - } else if (auth) - nonterm[shorter]=true; - } - } - } - } + string error; + bool ret = dk.rectifyZone(zone, error); + if (!ret) { + cerr<updateEmptyNonTerminals(sd.domain_id, insnonterm, delnonterm, !doent); - } - if(doent) - { - realrr=false; - qnames.clear(); - for(const auto& nt : nonterm){ - qnames.insert(nt.first); - } - goto dononterm; - } - } - - if(doTransaction) - sd.db->commitTransaction(); - - return true; + return ret; } void dbBench(const std::string& fname)