From: Kees Monshouwer Date: Sat, 27 Mar 2021 17:41:50 +0000 (+0100) Subject: auth: rectify() do not update ordernames/auth when there is no need X-Git-Tag: dnsdist-1.6.0-rc1~36^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc5245c3c4d3e40df9f6811f0f055411407c8f2c;p=thirdparty%2Fpdns.git auth: rectify() do not update ordernames/auth when there is no need --- diff --git a/modules/gmysqlbackend/gmysqlbackend.cc b/modules/gmysqlbackend/gmysqlbackend.cc index f1c10f7b4b..c6f9d6bc5a 100644 --- a/modules/gmysqlbackend/gmysqlbackend.cc +++ b/modules/gmysqlbackend/gmysqlbackend.cc @@ -95,7 +95,7 @@ public: declare(suffix, "any-query", "Any query", record_query + " disabled=0 and name=?"); declare(suffix, "any-id-query", "Any with ID query", record_query + " disabled=0 and name=? and domain_id=?"); - declare(suffix, "list-query", "AXFR query", record_query + " (disabled=0 OR ?) and domain_id=? order by name, type"); + declare(suffix, "list-query", "AXFR query", "SELECT content,ttl,prio,type,domain_id,disabled,name,auth,ordername FROM records WHERE (disabled=0 OR ?) and domain_id=? order by name, type"); declare(suffix, "list-subzone-query", "Subzone listing", record_query + " disabled=0 and (name=? OR name like ?) and domain_id=?"); declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=? and type is null"); diff --git a/modules/godbcbackend/godbcbackend.cc b/modules/godbcbackend/godbcbackend.cc index e61c8dafa1..b41bdc3509 100644 --- a/modules/godbcbackend/godbcbackend.cc +++ b/modules/godbcbackend/godbcbackend.cc @@ -75,7 +75,7 @@ public: declare(suffix, "any-query", "Any query", record_query + " disabled=0 and name=?"); declare(suffix, "any-id-query", "Any with ID query", record_query + " disabled=0 and name=? and domain_id=?"); - declare(suffix, "list-query", "AXFR query", record_query + " (disabled=0 OR disabled=?) and domain_id=? order by name, type"); + declare(suffix, "list-query", "AXFR query", "SELECT content,ttl,prio,type,domain_id,disabled,name,auth,CONVERT(varchar(255), ordername, 0) FROM records WHERE (disabled=0 OR disabled=?) and domain_id=? order by name, type"); declare(suffix, "list-subzone-query", "Subzone listing", record_query + " disabled=0 and (name=? OR name like ?) and domain_id=?"); declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=? and type is null"); diff --git a/modules/gpgsqlbackend/gpgsqlbackend.cc b/modules/gpgsqlbackend/gpgsqlbackend.cc index 7a2ad91ab7..1b7fce7541 100644 --- a/modules/gpgsqlbackend/gpgsqlbackend.cc +++ b/modules/gpgsqlbackend/gpgsqlbackend.cc @@ -102,7 +102,7 @@ public: declare(suffix, "any-query", "Any query", record_query + " disabled=false and name=$1"); declare(suffix, "any-id-query", "Any with ID query", record_query + " disabled=false and name=$1 and domain_id=$2"); - declare(suffix, "list-query", "AXFR query", record_query + " (disabled=false OR $1) and domain_id=$2 order by name, type"); + declare(suffix, "list-query", "AXFR query", "SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int,ordername FROM records WHERE (disabled=false OR $1) and domain_id=$2 order by name, type"); declare(suffix, "list-subzone-query", "Subzone listing", record_query + " disabled=false and (name=$1 OR name like $2) and domain_id=$3"); declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=$1 and type is null"); diff --git a/modules/gsqlite3backend/gsqlite3backend.cc b/modules/gsqlite3backend/gsqlite3backend.cc index b9670f4ab6..6d9fae416d 100644 --- a/modules/gsqlite3backend/gsqlite3backend.cc +++ b/modules/gsqlite3backend/gsqlite3backend.cc @@ -88,7 +88,7 @@ public: declare(suffix, "any-query", "Any query", record_query + " disabled=0 and name=:qname"); declare(suffix, "any-id-query", "Any with ID query", record_query + " disabled=0 and name=:qname and domain_id=:domain_id"); - declare(suffix, "list-query", "AXFR query", record_query + " (disabled=0 OR :include_disabled) and domain_id=:domain_id order by name, type"); + declare(suffix, "list-query", "AXFR query", "SELECT content,ttl,prio,type,domain_id,disabled,name,auth,ordername FROM records WHERE (disabled=0 OR :include_disabled) and domain_id=:domain_id order by name, type"); declare(suffix, "list-subzone-query", "Subzone listing", record_query + " disabled=0 and (name=:zone OR name like :wildzone) and domain_id=:domain_id"); declare(suffix, "remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=:domain_id and type is null"); diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc index 83c48fb530..e0724d1bd4 100644 --- a/pdns/backends/gsql/gsqlbackend.cc +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -1144,6 +1144,7 @@ void GSQLBackend::lookup(const QType &qtype,const DNSName &qname, int domain_id, throw PDNSException("GSQLBackend unable to lookup '" + qname.toLogString() + "|" + qtype.getName() + "':"+e.txtReason()); } + d_list=false; d_qname=qname; } @@ -1165,7 +1166,9 @@ bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabl throw PDNSException("GSQLBackend unable to list domain '" + target.toLogString() + "': "+e.txtReason()); } + d_list=true; d_qname.clear(); + return true; } @@ -1187,7 +1190,10 @@ bool GSQLBackend::listSubZone(const DNSName &zone, int domain_id) { catch(SSqlException &e) { throw PDNSException("GSQLBackend unable to list SubZones for domain '" + zone.toLogString() + "': "+e.txtReason()); } + + d_list=false; d_qname.clear(); + return true; } @@ -1200,7 +1206,12 @@ skiprow: if((*d_query_stmt)->hasNextRow()) { try { (*d_query_stmt)->nextRow(row); - ASSERT_ROW_COLUMNS(d_query_name, row, 8); + if (!d_list) { + ASSERT_ROW_COLUMNS(d_query_name, row, 8); // lookup(), listSubZone() + } + else { + ASSERT_ROW_COLUMNS(d_query_name, row, 9); // list() + } } catch (SSqlException &e) { throw PDNSException("GSQLBackend get: "+e.txtReason()); } @@ -1888,6 +1899,18 @@ void GSQLBackend::extractRecord(SSqlStatement::row_t& row, DNSResourceRecord& r) r.disabled = !row[5].empty() && row[5][0]=='1'; r.domain_id=pdns_stou(row[4]); + + if (row.size() > 8) { + if (!row.at(8).empty()) { + r.ordername=DNSName(boost::replace_all_copy(row.at(8), " ", ".")).labelReverse(); + } + else { + r.ordername.clear(); + } + } + else { + r.ordername.clear(); + } } void GSQLBackend::extractComment(SSqlStatement::row_t& row, Comment& comment) diff --git a/pdns/backends/gsql/gsqlbackend.hh b/pdns/backends/gsql/gsqlbackend.hh index fb964c0190..0aa79f54a6 100644 --- a/pdns/backends/gsql/gsqlbackend.hh +++ b/pdns/backends/gsql/gsqlbackend.hh @@ -264,6 +264,7 @@ protected: return d_inTransaction; } + bool d_list{false}; string d_query_name; DNSName d_qname; SSqlStatement::result_t d_result; diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc index dd79588cb0..5a052168d5 100644 --- a/pdns/dbdnsseckeeper.cc +++ b/pdns/dbdnsseckeeper.cc @@ -718,6 +718,15 @@ bool DNSSECKeeper::unSecureZone(const DNSName& zone, string& error, string& info return true; } + +struct RecordStatus +{ + DNSName ordername; + bool auth{false}; + bool update{false}; +}; + + /* Rectifies the zone * * \param zone The zone to rectify @@ -757,48 +766,60 @@ bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error, string& info, ostringstream infostream; DNSResourceRecord rr; set qnames, nsset, dsnames, insnonterm, delnonterm; - map nonterm; + std::unordered_map nonterm; vector rrs; + std::unordered_map rss; + + NSEC3PARAMRecordContent ns3pr; + bool securedZone = isSecuredZone(zone, doTransaction); + bool haveNSEC3 = false, isOptOut = false, narrow = false; + + if(securedZone) { + haveNSEC3 = getNSEC3PARAM(zone, &ns3pr, &narrow, doTransaction); + isOptOut = (haveNSEC3 && ns3pr.d_flags); + } while(sd.db->get(rr)) { rr.qname.makeUsLowerCase(); + + auto res=rss.insert({rr.qname,{rr.ordername, rr.auth, rr.ordername.empty() != (!securedZone || narrow)}}); // only a set ordername is reliable + if (!res.second && !res.first->second.update) { + res.first->second.update = res.first->second.auth != rr.auth || res.first->second.ordername != rr.ordername; + } + else if ((!securedZone || narrow) && rr.qname == zone) { + res.first->second.update = true; + } + 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); + rrs.emplace_back(rr); } else - delnonterm.insert(rr.qname); + delnonterm.insert(std::move(rr.qname)); } - NSEC3PARAMRecordContent ns3pr; - bool securedZone = isSecuredZone(zone, doTransaction); - bool haveNSEC3 = false, isOptOut = false, narrow = false; - if(securedZone) { - haveNSEC3 = getNSEC3PARAM(zone, &ns3pr, &narrow, doTransaction); - isOptOut = (haveNSEC3 && ns3pr.d_flags); - if(!haveNSEC3) { - infostream<<"Adding NSEC ordering information "; + infostream<<"Adding NSEC ordering information for zone '"< nsec3set; @@ -831,9 +852,11 @@ bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error, string& info, bool realrr=true; bool doent=true; + int updates=0; uint32_t maxent = ::arg().asNum("max-ent-entries"); dononterm:; + std::unordered_map::const_iterator it; for (const auto& qname: qnames) { bool auth=true; @@ -861,20 +884,32 @@ bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error, string& info, } } else if (realrr && securedZone) // NSEC + { ordername=qname.makeRelative(zone); + } - sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, auth); + it = rss.find(qname); + if(it == rss.end() || it->second.update || it->second.auth != auth || it->second.ordername != ordername) { + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, auth); + ++updates; + } if(realrr) { - if (dsnames.count(qname)) + if (dsnames.count(qname)) { sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, true, QType::DS); + ++updates; + } if (!auth || nsset.count(qname)) { ordername.clear(); - if(isOptOut && !dsnames.count(qname)) + if(isOptOut && !dsnames.count(qname)){ sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::NS); + ++updates; + } sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::A); + ++updates; sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::AAAA); + ++updates; } if(doent) @@ -930,6 +965,7 @@ bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error, string& info, if (doTransaction) sd.db->commitTransaction(); + infostream<<", "<