From 182f7513802bffb4ab3dd373eadb8f1a64012e22 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Sat, 26 Dec 2015 20:30:11 +0200 Subject: [PATCH] Verify domain ownership GSQLBackend must ensure it checks that it won't return true for domains that it does not actually have any ownership for, if it does, it will block other backends from working. --- modules/gmysqlbackend/gmysqlbackend.cc | 1 + modules/godbcbackend/godbcbackend.cc | 1 + modules/goraclebackend/goraclebackend.cc | 1 + modules/gpgsqlbackend/gpgsqlbackend.cc | 2 +- modules/gsqlite3backend/gsqlite3backend.cc | 1 + pdns/backends/gsql/gsqlbackend.cc | 63 +++++++++++++++++++++- pdns/backends/gsql/gsqlbackend.hh | 8 ++- 7 files changed, 72 insertions(+), 5 deletions(-) diff --git a/modules/gmysqlbackend/gmysqlbackend.cc b/modules/gmysqlbackend/gmysqlbackend.cc index 33173c175..434ffcaa6 100644 --- a/modules/gmysqlbackend/gmysqlbackend.cc +++ b/modules/gmysqlbackend/gmysqlbackend.cc @@ -129,6 +129,7 @@ public: declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=?"); declare(suffix, "search-records-query", "", record_query+" name LIKE ? OR content LIKE ? LIMIT ?"); declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE ? OR comment LIKE ? LIMIT ?"); + declare(suffix, "is-our-domain-query", "", "SELECT id FROM domains WHERE id = ? OR name = ?"); } DNSBackend *make(const string &suffix="") diff --git a/modules/godbcbackend/godbcbackend.cc b/modules/godbcbackend/godbcbackend.cc index c5d1811ad..4d787046f 100644 --- a/modules/godbcbackend/godbcbackend.cc +++ b/modules/godbcbackend/godbcbackend.cc @@ -130,6 +130,7 @@ public: declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=?"); declare(suffix, "search-records-query", "", record_query+" name LIKE ? OR content LIKE ? LIMIT ?"); declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE ? OR comment LIKE ? LIMIT ?"); + declare(suffix, "is-our-domain-query", "", "SELECT id FROM domains WHERE id = ? OR name = ?"); } //! Constructs a new gODBCBackend object. diff --git a/modules/goraclebackend/goraclebackend.cc b/modules/goraclebackend/goraclebackend.cc index 88a507497..5414a66af 100644 --- a/modules/goraclebackend/goraclebackend.cc +++ b/modules/goraclebackend/goraclebackend.cc @@ -142,6 +142,7 @@ public: declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=:domain_id"); declare(suffix, "search-records-query", "", record_query+" name LIKE :value OR content LIKE :value2 LIMIT :limit"); declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE :value OR comment LIKE :value2 LIMIT :limit"); + declare(suffix, "is-our-domain-query", "", "SELECT id FROM domains WHERE id = :id OR name = :zone"); } diff --git a/modules/gpgsqlbackend/gpgsqlbackend.cc b/modules/gpgsqlbackend/gpgsqlbackend.cc index 9f2b55472..832f9a90f 100644 --- a/modules/gpgsqlbackend/gpgsqlbackend.cc +++ b/modules/gpgsqlbackend/gpgsqlbackend.cc @@ -124,7 +124,7 @@ public: declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=$1"); declare(suffix, "search-records-query", "", record_query+" name LIKE $1 OR content LIKE $2 LIMIT $3"); declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE $1 OR comment LIKE $2 LIMIT $3"); - + declare(suffix, "is-our-domain-query", "", "SELECT id FROM domains WHERE id = $1 OR name = $2"); } DNSBackend *make(const string &suffix="") diff --git a/modules/gsqlite3backend/gsqlite3backend.cc b/modules/gsqlite3backend/gsqlite3backend.cc index 888b399b5..a764d8eed 100644 --- a/modules/gsqlite3backend/gsqlite3backend.cc +++ b/modules/gsqlite3backend/gsqlite3backend.cc @@ -140,6 +140,7 @@ public: declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=:domain_id"); declare(suffix, "search-records-query", "", record_query+" name LIKE :value OR content LIKE :value2 LIMIT :limit"); declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE :value OR comment LIKE :value2 LIMIT :limit"); + declare(suffix, "is-our-domain-query", "", "SELECT id FROM domains WHERE id = :id OR name = :zone"); } //! Constructs a new gSQLite3Backend object. diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc index 9d2c02e18..f39612948 100644 --- a/pdns/backends/gsql/gsqlbackend.cc +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -129,6 +129,8 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix) d_SearchRecordsQuery = getArg("search-records-query"); d_SearchCommentsQuery = getArg("search-comments-query"); + d_IsOurDomainQuery = getArg("is-our-domain-query"); + d_query_stmt = NULL; d_NoIdQuery_stmt = NULL; d_IdQuery_stmt = NULL; @@ -191,6 +193,7 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix) d_DeleteCommentsQuery_stmt = NULL; d_SearchRecordsQuery_stmt = NULL; d_SearchCommentsQuery_stmt = NULL; + d_IsOurDomainQuery_stmt = NULL; } void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial) @@ -223,6 +226,8 @@ void GSQLBackend::setFresh(uint32_t domain_id) bool GSQLBackend::isMaster(const DNSName &domain, const string &ip) { + if (!isOurDomain(domain)) return false; + try { d_MasterOfDomainsZoneQuery_stmt-> bind("domain", domain)-> @@ -254,6 +259,8 @@ bool GSQLBackend::isMaster(const DNSName &domain, const string &ip) bool GSQLBackend::setMaster(const DNSName &domain, const string &ip) { + if (!isOurDomain(domain)) return false; + try { d_UpdateMasterOfZoneQuery_stmt-> bind("master", ip)-> @@ -269,6 +276,8 @@ bool GSQLBackend::setMaster(const DNSName &domain, const string &ip) bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind) { + if (!isOurDomain(domain)) return false; + try { d_UpdateKindOfZoneQuery_stmt-> bind("kind", toUpper(DomainInfo::getKindString(kind)))-> @@ -284,6 +293,8 @@ bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind ki bool GSQLBackend::setAccount(const DNSName &domain, const string &account) { + if (!isOurDomain(domain)) return false; + try { d_UpdateAccountOfZoneQuery_stmt-> bind("account", account)-> @@ -299,6 +310,8 @@ bool GSQLBackend::setAccount(const DNSName &domain, const string &account) bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di) { + if (!isOurDomain(domain)) return false; + /* fill DomainInfo from database info: id,name,master IP(s),last_check,notified_serial,type,account */ try { @@ -440,6 +453,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName { if(!d_dnssecQueries) return false; + if (!isOurDomain(DNSName(""), domain_id)) return false; if (!ordername.empty()) { if (qtype == QType::ANY) { @@ -503,6 +517,8 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, const DNSName& zonename, set& insert, set& erase, bool remove) { + if (!isOurDomain(DNSName(""), domain_id)) return false; + if(remove) { try { d_removeEmptyNonTerminalsFromZoneQuery_stmt-> @@ -558,6 +574,8 @@ bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const string& qnam { if(!d_dnssecQueries) return false; + if (!isOurDomain(DNSName(""),id)) return false; + // cerr<<"gsql before/after called for id="< @@ -675,6 +694,7 @@ bool GSQLBackend::activateDomainKey(const DNSName& name, unsigned int id) { if(!d_dnssecQueries) return false; + if (!isOurDomain(name)) return false; try { d_ActivateDomainKeyQuery_stmt-> @@ -693,6 +713,7 @@ bool GSQLBackend::deactivateDomainKey(const DNSName& name, unsigned int id) { if(!d_dnssecQueries) return false; + if (!isOurDomain(name)) return false; try { d_DeactivateDomainKeyQuery_stmt-> @@ -711,6 +732,7 @@ bool GSQLBackend::removeDomainKey(const DNSName& name, unsigned int id) { if(!d_dnssecQueries) return false; + if (!isOurDomain(name)) return false; try { d_RemoveDomainKeyQuery_stmt-> @@ -820,6 +842,7 @@ bool GSQLBackend::getDomainKeys(const DNSName& name, unsigned int kind, std::vec { if(!d_dnssecQueries) return false; + if (!isOurDomain(name)) return false; try { d_ListDomainKeysQuery_stmt-> @@ -862,6 +885,8 @@ void GSQLBackend::alsoNotifies(const DNSName &domain, set *ips) bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { + if (!isOurDomain(name)) return false; + try { d_GetAllDomainMetadataQuery_stmt-> bind("domain", name)-> @@ -919,6 +944,7 @@ bool GSQLBackend::setDomainMetadata(const DNSName& name, const std::string& kind { if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) return false; + if (!isOurDomain(name)) return false; try { d_ClearDomainMetadataQuery_stmt-> @@ -990,6 +1016,8 @@ void GSQLBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabled) { + if (!isOurDomain(target, domain_id)) return false; + DLOG(L<<"GSQLBackend constructing handle for list of domain id '"< *domains, bool include_disabl bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) { + if (!isOurDomain(DNSName(""), domain_id)) return false; + try { if (qt != QType::ANY) { d_DeleteRRSetQuery_stmt-> @@ -1318,6 +1349,8 @@ bool GSQLBackend::feedRecord(const DNSResourceRecord &r, string *ordername) bool GSQLBackend::feedEnts(int domain_id, map& nonterm) { + if (!isOurDomain(DNSName(""), domain_id)) return false; + for(const auto& nt: nonterm) { try { d_InsertEntQuery_stmt-> @@ -1338,6 +1371,7 @@ bool GSQLBackend::feedEnts3(int domain_id, const DNSName &domain, map=0 && !isOurDomain(DNSName(""), domain_id)) return false; + try { d_db->startTransaction(); if(domain_id >= 0) { @@ -1410,11 +1446,12 @@ bool GSQLBackend::abortTransaction() bool GSQLBackend::calculateSOASerial(const DNSName& domain, const SOAData& sd, time_t& serial) { + if (!isOurDomain(DNSName(""), sd.domain_id)) return false; if (d_ZoneLastChangeQuery.empty()) { // query not set => fall back to default impl return DNSBackend::calculateSOASerial(domain, sd, serial); } - + try { d_ZoneLastChangeQuery_stmt-> bind("domain_id", sd.domain_id)-> @@ -1438,6 +1475,8 @@ bool GSQLBackend::calculateSOASerial(const DNSName& domain, const SOAData& sd, t bool GSQLBackend::listComments(const uint32_t domain_id) { + if (!isOurDomain(DNSName(""), domain_id)) return false; + try { d_query_name = "list-comments-query"; d_query_stmt = d_ListCommentsQuery_stmt; @@ -1659,6 +1698,26 @@ void GSQLBackend::extractComment(const SSqlStatement::row_t& row, Comment& comme comment.content = row[5]; } +bool GSQLBackend::isOurDomain(const DNSName &zone, int domain_id) { + try { + d_IsOurDomainQuery_stmt-> + bind("id", domain_id)-> + bind("zone", zone)-> + execute()-> + getResult(d_result)-> + reset(); + + if (!d_result.empty()) { + d_result.clear(); + return true; + } + } catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to verify ownership of domain: "+e.txtReason()); + } + + return false; +} + SSqlStatement::~SSqlStatement() { // make sure vtable won't break } diff --git a/pdns/backends/gsql/gsqlbackend.hh b/pdns/backends/gsql/gsqlbackend.hh index 1029c42c9..b0c511dcb 100644 --- a/pdns/backends/gsql/gsqlbackend.hh +++ b/pdns/backends/gsql/gsqlbackend.hh @@ -92,6 +92,7 @@ public: d_DeleteCommentsQuery_stmt = d_db->prepare(d_DeleteCommentsQuery, 1); d_SearchRecordsQuery_stmt = d_db->prepare(d_SearchRecordsQuery, 3); d_SearchCommentsQuery_stmt = d_db->prepare(d_SearchCommentsQuery, 3); + d_IsOurDomainQuery_stmt = d_db->prepare(d_IsOurDomainQuery, 2); } } @@ -162,6 +163,7 @@ public: release(&d_DeleteCommentsQuery_stmt); release(&d_SearchRecordsQuery_stmt); release(&d_SearchCommentsQuery_stmt); + release(&d_IsOurDomainQuery_stmt); } void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1); @@ -223,7 +225,7 @@ public: string directBackendCmd(const string &query); bool searchRecords(const string &pattern, int maxResults, vector& result); bool searchComments(const string &pattern, int maxResults, vector& result); - + bool isOurDomain(const DNSName &zone, int domain_id=-1); protected: string pattern2SQLPattern(const string& pattern); void extractRecord(const SSqlStatement::row_t& row, DNSResourceRecord& rr); @@ -311,6 +313,8 @@ private: string d_SearchRecordsQuery; string d_SearchCommentsQuery; + string d_IsOurDomainQuery; + SSqlStatement* d_query_stmt; SSqlStatement* d_NoIdQuery_stmt; @@ -374,7 +378,7 @@ private: SSqlStatement* d_DeleteCommentsQuery_stmt; SSqlStatement* d_SearchRecordsQuery_stmt; SSqlStatement* d_SearchCommentsQuery_stmt; - + SSqlStatement* d_IsOurDomainQuery_stmt; protected: bool d_dnssecQueries; }; -- 2.40.0