From: Bert Hubert Date: Thu, 30 Dec 2010 14:41:17 +0000 (+0000) Subject: bindbackend can now do nsec3, gets at least some records right ;-) X-Git-Tag: auth-3.0~477 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=772e8b107686c81caad3648c288876c84d4ce991;p=pdns bindbackend can now do nsec3, gets at least some records right ;-) git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1770 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/backends/bind/bindbackend2.cc b/pdns/backends/bind/bindbackend2.cc index ad4bf2cc8..1c0cf2ec8 100644 --- a/pdns/backends/bind/bindbackend2.cc +++ b/pdns/backends/bind/bindbackend2.cc @@ -29,6 +29,9 @@ #include #include #include +#include "dnsseckeeper.hh" +#include "dnssecinfra.hh" +#include "base32.hh" using namespace std; #include "dns.hh" @@ -355,12 +358,12 @@ static string canonic(string ret) /** THIS IS AN INTERNAL FUNCTION! It does moadnsparser prio impedence matching This function adds a record to a domain with a certain id. Much of the complication is due to the efforts to benefit from std::string reference counting copy on write semantics */ -void Bind2Backend::insert(shared_ptr stage, int id, const string &qnameu, const QType &qtype, const string &content, int ttl=300, int prio=25) +void Bind2Backend::insert(shared_ptr stage, int id, const string &qnameu, const QType &qtype, const string &content, int ttl, int prio, const std::string& hashed) { BB2DomainInfo bb2 = stage->id_zone_map[id]; Bind2DNSRecord bdr; - vector& records=*bb2.d_records; + recordstorage_t& records=*bb2.d_records; bdr.qname=toLower(canonic(qnameu)); if(bb2.d_name.empty()) @@ -374,8 +377,9 @@ void Bind2Backend::insert(shared_ptr stage, int id, const string &qnameu, bdr.qname.swap(bdr.qname); - if(!records.empty() && bdr.qname==(records.end()-1)->qname) - bdr.qname=(records.end()-1)->qname; + + if(!records.empty() && bdr.qname==boost::prior(records.end())->qname) + bdr.qname=boost::prior(records.end())->qname; // cerr<<"Before reverse: '"< stage, int id, const string &qnameu, bdr.qtype=qtype.getCode(); bdr.content=content; + bdr.nsec3hash = hashed; if(bdr.qtype == QType::MX || bdr.qtype == QType::SRV) { prio=atoi(bdr.content.c_str()); @@ -399,7 +404,7 @@ void Bind2Backend::insert(shared_ptr stage, int id, const string &qnameu, bdr.ttl=ttl; bdr.priority=prio; - records.push_back(bdr); + records.insert(bdr); } void Bind2Backend::reload() @@ -573,7 +578,7 @@ void Bind2Backend::loadConfig(string* status) bbd->d_id=domain_id++; // this isn't necessary, we do this on the actual load - // bbd->d_records=shared_ptr > (new vector); + // bbd->d_records=shared_ptr (new recordstorage_t); bbd->setCheckInterval(getArgAsNum("check-interval")); bbd->d_lastnotified=0; @@ -596,50 +601,56 @@ void Bind2Backend::loadConfig(string* status) if(filenameChanged || !bbd->d_loaded || !bbd->current()) { L<name<<"' from file '"<filename<<"'"<name, &ns3pr); + if(ns3pr.d_salt.empty()) + cerr<<"no nsec3 for "<name<name<d_records=shared_ptr > (new vector); + bbd->d_records=shared_ptr (new recordstorage_t()); ZoneParserTNG zpt(i->filename, i->name, BP.getDirectory()); DNSResourceRecord rr; + string hashed; while(zpt.get(rr)) { - insert(staging, bbd->d_id, rr.qname, rr.qtype, rr.content, rr.ttl, rr.priority); + if(!ns3pr.d_salt.empty()) + hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname))); + insert(staging, bbd->d_id, rr.qname, rr.qtype, rr.content, rr.ttl, rr.priority, hashed); } - - // ZP.parse(i->filename, i->name, bbd->d_id); // calls callback for us - // L<name<<"'"<id_zone_map[bbd->d_id].d_records->size()<<" records"<id_zone_map[bbd->d_id].d_records->begin(), staging->id_zone_map[bbd->d_id].d_records->end()); - // cerr<<"Done loadconfig sorting"< > records=staging->id_zone_map[bbd->d_id].d_records; + + // sort(staging->id_zone_map[bbd->d_id].d_records->begin(), staging->id_zone_map[bbd->d_id].d_records->end()); + + shared_ptr records=staging->id_zone_map[bbd->d_id].d_records; + + pair range; + string sqname; + + BOOST_FOREACH(const Bind2DNSRecord& bdr, *records) { + bdr.auth=true; + if(bdr.qtype == QType::DS) // as are delegation signer records + continue; - pair::const_iterator, vector::const_iterator> range; - string sqname; - BOOST_FOREACH(Bind2DNSRecord& bdr, *records) { - bdr.auth=true; - if(bdr.qtype == QType::DS) // as are delegation signer records - continue; - - sqname = labelReverse(bdr.qname); - // cerr<<"sqname: '"<begin(), records->end(), sqname); - if(range.first != range.second) { - for(vector::const_iterator iter = range.first ; iter != range.second; ++iter) { - if(iter->qtype == QType::NS) { - // cerr<<"Have an NS hit for '"<qname<<"'"<begin(), records->end(), sqname); + if(range.first != range.second) { + for(recordstorage_t::const_iterator iter = range.first ; iter != range.second; ++iter) { + if(iter->qtype == QType::NS) { + // cerr<<"Have an NS hit for '"<qname<<"'"<id_zone_map[bbd->d_id].setCtime(); staging->id_zone_map[bbd->d_id].d_loaded=true; @@ -731,7 +742,7 @@ void Bind2Backend::loadConfig(string* status) void Bind2Backend::nukeZoneRecords(BB2DomainInfo *bbd) { bbd->d_loaded=0; // block further access - bbd->d_records = shared_ptr > (new vector); + bbd->d_records = shared_ptr (new recordstorage_t); } @@ -746,7 +757,7 @@ void Bind2Backend::queueReload(BB2DomainInfo *bbd) try { nukeZoneRecords(bbd); // ? do we need this? staging->id_zone_map[bbd->d_id]=s_state->id_zone_map[bbd->d_id]; - staging->id_zone_map[bbd->d_id].d_records=shared_ptr > (new vector); // nuke it + staging->id_zone_map[bbd->d_id].d_records=shared_ptr (new recordstorage_t); // nuke it ZoneParserTNG zpt(bbd->d_filename, bbd->d_name, s_binddirectory); DNSResourceRecord rr; @@ -754,7 +765,7 @@ void Bind2Backend::queueReload(BB2DomainInfo *bbd) insert(staging, bbd->d_id, rr.qname, rr.qtype, rr.content, rr.ttl, rr.priority); } // cerr<<"Start sort of "<id_zone_map[bbd->d_id].d_records->size()<<" records"<id_zone_map[bbd->d_id].d_records->begin(), staging->id_zone_map[bbd->d_id].d_records->end()); + // sort(staging->id_zone_map[bbd->d_id].d_records->begin(), staging->id_zone_map[bbd->d_id].d_records->end()); // cerr<<"Sorting done"<id_zone_map[bbd->d_id].setCtime(); @@ -779,20 +790,17 @@ void Bind2Backend::queueReload(BB2DomainInfo *bbd) } } - -bool Bind2Backend::getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after) +bool Bind2Backend::findBeforeAndAfterUnhashed(BB2DomainInfo& bbd, const std::string& qname, std::string& unhashed, std::string& before, std::string& after) { - shared_ptr state = s_state; - BB2DomainInfo& bbd = state->id_zone_map[id]; string domain=toLower(qname); string lname = labelReverse(domain); cout<<"starting lower bound for: '"<::const_iterator iter = lower_bound(bbd.d_records->begin(), bbd.d_records->end(), lname); + recordstorage_t::const_iterator iter = lower_bound(bbd.d_records->begin(), bbd.d_records->end(), lname); - while(iter != bbd.d_records->begin() && !(iter-1)->auth && (iter-1)->qtype!=QType::NS) { + while(iter != bbd.d_records->begin() && !boost::prior(iter)->auth && boost::prior(iter)->qtype!=QType::NS) { cerr<<"Going backwards.."<begin()) { - cerr<<"\tFound: '"<<(iter-1)->qname<<"', auth = "<<(iter-1)->auth<<"\n"; - before = (iter - 1)->qname; + cerr<<"\tFound: '"<qname<<"', auth = "<auth<<"\n"; + before = boost::prior(iter)->qname; } else { cerr<<"PANIC! Wanted something before the first record!"< state = s_state; + BB2DomainInfo& bbd = state->id_zone_map[id]; + DNSSECKeeper dk(::arg()["key-repository"]); + NSEC3PARAMRecordContent ns3pr; + string auth=state->id_zone_map[id].d_name; + + dk.getNSEC3PARAM(auth, &ns3pr); + if(ns3pr.d_salt.empty()) { + cerr<<"in bind2backend::getBeforeAndAfterAbsolute: no nsec3 for "<::type records_by_hashindex_t; + records_by_hashindex_t& ttdindex=boost::multi_index::get(*bbd.d_records); + + BOOST_FOREACH(const Bind2DNSRecord& bdr, ttdindex) { + cerr<<"Hash: "<nsec3hash == lqname) { + before = iter->nsec3hash; + unhashed = dotConcat(labelReverse(iter->qname), auth); + cerr<<"Had direct hit, setting unhashed: "<auth && boost::prior(iter)->qtype!=QType::NS) { + cerr<<"Going backwards.."<nsec3hash<<"', auth = "<auth<<"\n"; + before = boost::prior(iter)->nsec3hash; + unhashed = dotConcat(labelReverse(boost::prior(iter)->qname), auth); + } + else { + before = ttdindex.rbegin()->nsec3hash; // try the last one then.. + unhashed = dotConcat(labelReverse(ttdindex.rbegin()->qname), auth); + cerr<<"PANIC! Wanted something before the first record, inserted last: "<auth && iter->qtype != QType::NS)) + iter++; + + if(iter == ttdindex.end()) { + cerr<<"\tFound the end, inserting beginning"<nsec3hash; + // unhashed = ttdindex.begin()->qname; + } else { + cerr<<"\tFound: '"<nsec3hash<<"'"<nsec3hash; + // unhashed = iter->qname; + } + + cerr<<"Before: '"<empty()) DLOG(L<<"Query with no results"<::const_iterator, vector::const_iterator> range; + pair range; string lname=labelReverse(toLower(d_handle.qname)); // cout<<"starting equal range for: '"<id_zone_map[newid]; - bbd.d_records = shared_ptr >(new vector); + bbd.d_records = shared_ptr(new recordstorage_t); bbd.d_name = domain; bbd.setCheckInterval(getArgAsNum("check-interval")); bbd.d_masters.push_back(ip); diff --git a/pdns/backends/bind/bindbackend2.hh b/pdns/backends/bind/bindbackend2.hh index 07da53083..253776c18 100644 --- a/pdns/backends/bind/bindbackend2.hh +++ b/pdns/backends/bind/bindbackend2.hh @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -32,6 +36,7 @@ using namespace std; using namespace boost; +using namespace ::boost::multi_index; /** This struct is used within the Bind2Backend to store DNS information. It is almost identical to a DNSResourceRecord, but then a bit smaller and with different sorting rules, which make sure that the SOA record comes up front. @@ -40,10 +45,11 @@ struct Bind2DNSRecord { string qname; string content; + string nsec3hash; uint32_t ttl; uint16_t qtype; uint16_t priority; - bool auth; + mutable bool auth; bool operator<(const Bind2DNSRecord& rhs) const { if(qname < rhs.qname) @@ -54,10 +60,6 @@ struct Bind2DNSRecord return true; return tie(qtype,content, ttl) < tie(rhs.qtype, rhs.content, rhs.ttl); } - bool operator<(const string &b) const - { - return qname < b; - } }; inline bool operator<(const string &a, const Bind2DNSRecord &b) @@ -65,6 +67,21 @@ inline bool operator<(const string &a, const Bind2DNSRecord &b) return a < b.qname; } +inline bool operator<(const Bind2DNSRecord &a, const string& b) +{ + return a.qname < b; +} + + +struct HashedTag{}; + +typedef multi_index_container< + Bind2DNSRecord, + indexed_by < + ordered_non_unique >, + ordered_non_unique, member > + > +> recordstorage_t; /** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */ class BB2DomainInfo @@ -92,7 +109,7 @@ public: //! configure how often this domain should be checked for changes (on disk) void setCheckInterval(time_t seconds); - shared_ptr > d_records; //!< the actual records belonging to this domain + shared_ptr d_records; //!< the actual records belonging to this domain private: time_t getCtime(); @@ -135,7 +152,7 @@ public: id_zone_map_t id_zone_map; }; - static void insert(shared_ptr stage, int id, const string &qname, const QType &qtype, const string &content, int ttl, int prio); + static void insert(shared_ptr stage, int id, const string &qname, const QType &qtype, const string &content, int ttl=300, int prio=25, const std::string& hashed=string()); void rediscover(string *status=0); bool isMaster(const string &name, const string &ip); @@ -158,11 +175,11 @@ private: handle(); - shared_ptr > d_records; - vector::const_iterator d_iter, d_end_iter; + shared_ptr d_records; + recordstorage_t::const_iterator d_iter, d_end_iter; - vector::const_iterator d_qname_iter; - vector::const_iterator d_qname_end; + recordstorage_t::const_iterator d_qname_iter; + recordstorage_t::const_iterator d_qname_end; bool d_list; int id; @@ -199,7 +216,7 @@ private: handle d_handle; static void queueReload(BB2DomainInfo *bbd); - + bool findBeforeAndAfterUnhashed(BB2DomainInfo& bbd, const std::string& qname, std::string& unhashed, std::string& before, std::string& after); void reload(); static string DLDomStatusHandler(const vector&parts, Utility::pid_t ppid); static string DLListRejectsHandler(const vector&parts, Utility::pid_t ppid); diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc index 8f2f1c605..f49887c5c 100644 --- a/pdns/backends/gsql/gsqlbackend.cc +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -280,7 +280,7 @@ retryAfter: } if(after.empty() && !tmp.empty()) { - cerr<<"Oops, have to pick the first, there as no last!"<