"Fossies" - the Fresh Open Source Software Archive

Member "pdns-auth-4.2.0/modules/bindbackend/bindbackend2.hh" (27 Aug 2019, 12711 Bytes) of package /linux/misc/dns/pdns-auth-4.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "bindbackend2.hh" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.13_vs_4.2.0.

    1 /*
    2  * This file is part of PowerDNS or dnsdist.
    3  * Copyright -- PowerDNS.COM B.V. and its contributors
    4  *
    5  * This program is free software; you can redistribute it and/or modify
    6  * it under the terms of version 2 of the GNU General Public License as
    7  * published by the Free Software Foundation.
    8  *
    9  * In addition, for the avoidance of any doubt, permission is granted to
   10  * link this program with OpenSSL and to (re)distribute the binaries
   11  * produced as the result of such linking.
   12  *
   13  * This program is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  * GNU General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU General Public License
   19  * along with this program; if not, write to the Free Software
   20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   21  */
   22 
   23 #ifndef PDNS_BINDBACKEND_HH
   24 #define PDNS_BINDBACKEND_HH
   25 
   26 #include <string>
   27 #include <map>
   28 #include <set>
   29 #include <pthread.h>
   30 #include <time.h>
   31 #include <fstream>
   32 #include <boost/utility.hpp>
   33 
   34 #include <boost/tuple/tuple.hpp>
   35 #include <boost/tuple/tuple_comparison.hpp>
   36 #include <boost/multi_index_container.hpp>
   37 #include <boost/multi_index/hashed_index.hpp>
   38 #include <boost/multi_index/ordered_index.hpp>
   39 #include <boost/multi_index/identity.hpp>
   40 #include <boost/multi_index/member.hpp>
   41 #include <sys/types.h>
   42 #include <sys/stat.h>
   43 #include <unistd.h>
   44 #include "pdns/lock.hh"
   45 #include "pdns/misc.hh"
   46 #include "pdns/dnsbackend.hh"
   47 #include "pdns/namespaces.hh"
   48 #include "pdns/backends/gsql/ssql.hh"
   49 
   50 using namespace ::boost::multi_index;
   51 
   52 /**
   53   This struct is used within the Bind2Backend to store DNS information. It is
   54   almost identical to a DNSResourceRecord, but then a bit smaller and with
   55   different sorting rules, which make sure that the SOA record comes up front.
   56 */
   57 
   58 struct Bind2DNSRecord
   59 {
   60   DNSName qname;
   61   string content;
   62   string nsec3hash;
   63   uint32_t ttl;
   64   uint16_t qtype;
   65   mutable bool auth;
   66   bool operator<(const Bind2DNSRecord& rhs) const
   67   {
   68     if(qname.canonCompare(rhs.qname))
   69       return true;
   70     if(rhs.qname.canonCompare(qname))
   71       return false;
   72     if(qtype==QType::SOA && rhs.qtype!=QType::SOA)
   73       return true;
   74     return tie(qtype,content, ttl) < tie(rhs.qtype, rhs.content, rhs.ttl);
   75   }
   76 };
   77 
   78 struct Bind2DNSCompare : std::less<Bind2DNSRecord> 
   79 { 
   80     using std::less<Bind2DNSRecord>::operator(); 
   81     // use operator< 
   82     bool operator() (const DNSName& a, const Bind2DNSRecord& b) const
   83     {return a.canonCompare(b.qname);}
   84     bool operator() (const Bind2DNSRecord& a, const DNSName& b) const
   85     {return a.qname.canonCompare(b);}
   86     bool operator() (const Bind2DNSRecord& a, const Bind2DNSRecord& b) const
   87     {return a.qname.canonCompare(b.qname);}
   88 };
   89 
   90 struct NSEC3Tag{};
   91 struct UnorderedNameTag{};
   92 
   93 typedef multi_index_container<
   94   Bind2DNSRecord,
   95   indexed_by  <
   96                 ordered_non_unique<identity<Bind2DNSRecord>, Bind2DNSCompare >,
   97                 hashed_non_unique<tag<UnorderedNameTag>, member<Bind2DNSRecord, DNSName, &Bind2DNSRecord::qname> >,
   98                 ordered_non_unique<tag<NSEC3Tag>, member<Bind2DNSRecord, std::string, &Bind2DNSRecord::nsec3hash> >
   99               >
  100 > recordstorage_t;
  101 
  102 template <typename T>
  103 class LookButDontTouch //  : public boost::noncopyable
  104 {
  105 public:
  106   LookButDontTouch() 
  107   {
  108     pthread_mutex_init(&d_lock, 0);
  109     pthread_mutex_init(&d_swaplock, 0);
  110   }
  111   LookButDontTouch(shared_ptr<T> records) : d_records(records)
  112   {
  113     pthread_mutex_init(&d_lock, 0);
  114     pthread_mutex_init(&d_swaplock, 0);
  115   }
  116 
  117   shared_ptr<const T> get()
  118   {
  119     shared_ptr<const T> ret;
  120     {
  121       Lock l(&d_lock);
  122       ret = d_records;
  123     }
  124     return ret;
  125   }
  126 
  127   shared_ptr<T> getWRITABLE()
  128   {
  129     shared_ptr<T> ret;
  130     {
  131       Lock l(&d_lock);
  132       ret = d_records;
  133     }
  134     return ret;
  135   }
  136 
  137 
  138   void swap(shared_ptr<T> records)
  139   {
  140     Lock l(&d_lock);
  141     Lock l2(&d_swaplock);
  142     d_records.swap(records);
  143   }
  144   pthread_mutex_t d_lock;
  145   pthread_mutex_t d_swaplock;
  146 private:
  147   shared_ptr<T> d_records;
  148 };
  149 
  150 
  151 /** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */
  152 class BB2DomainInfo
  153 {
  154 public:
  155   BB2DomainInfo();
  156   void setCtime();
  157   bool current();
  158   //! configure how often this domain should be checked for changes (on disk)
  159   void setCheckInterval(time_t seconds);
  160 
  161   DNSName d_name;   //!< actual name of the domain
  162   DomainInfo::DomainKind d_kind; //!< the kind of domain
  163   string d_filename; //!< full absolute filename of the zone on disk
  164   string d_status; //!< message describing status of a domain, for human consumption
  165   vector<ComboAddress> d_masters;     //!< IP address of the master of this domain
  166   set<string> d_also_notify; //!< IP list of hosts to also notify
  167   LookButDontTouch<recordstorage_t> d_records;  //!< the actual records belonging to this domain
  168   time_t d_ctime{0};  //!< last known ctime of the file on disk
  169   time_t d_lastcheck{0}; //!< last time domain was checked for freshness
  170   uint32_t d_lastnotified{0}; //!< Last serial number we notified our slaves of
  171   unsigned int d_id;  //!< internal id of the domain
  172   mutable bool d_checknow; //!< if this domain has been flagged for a check
  173   bool d_loaded;  //!< if a domain is loaded
  174   bool d_wasRejectedLastReload{false}; //!< if the domain was rejected during Bind2Backend::queueReloadAndStore
  175 
  176 private:
  177   time_t getCtime();
  178   time_t d_checkinterval;
  179 };
  180 
  181 class SSQLite3;
  182 class NSEC3PARAMRecordContent;
  183 
  184 struct NameTag
  185 {};
  186 
  187 class Bind2Backend : public DNSBackend
  188 {
  189 public:
  190   Bind2Backend(const string &suffix="", bool loadZones=true); 
  191   ~Bind2Backend();
  192   void getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains) override;
  193   void getUpdatedMasters(vector<DomainInfo> *changedDomains) override;
  194   bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true ) override;
  195   time_t getCtime(const string &fname);
  196    // DNSSEC
  197   bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
  198   void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1) override;
  199   bool list(const DNSName &target, int id, bool include_disabled=false) override;
  200   bool get(DNSResourceRecord &) override;
  201   void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false) override;
  202 
  203   static DNSBackend *maker();
  204   static pthread_mutex_t s_startup_lock;
  205 
  206   void setFresh(uint32_t domain_id) override;
  207   void setNotified(uint32_t id, uint32_t serial) override;
  208   bool startTransaction(const DNSName &qname, int id) override;
  209   bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false) override;
  210   bool commitTransaction() override;
  211   bool abortTransaction() override;
  212   void alsoNotifies(const DNSName &domain, set<string> *ips) override;
  213   bool searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result) override;
  214 
  215 // the DNSSEC related (getDomainMetadata has broader uses too)
  216   bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta) override;
  217   bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override;
  218   bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override;
  219   bool getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) override;
  220   bool removeDomainKey(const DNSName& name, unsigned int id) override;
  221   bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override;
  222   bool activateDomainKey(const DNSName& name, unsigned int id) override;
  223   bool deactivateDomainKey(const DNSName& name, unsigned int id) override;
  224   bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override;
  225   bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override;
  226   bool deleteTSIGKey(const DNSName& name) override;
  227   bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override;
  228   bool doesDNSSEC() override;
  229   // end of DNSSEC 
  230 
  231   typedef multi_index_container < BB2DomainInfo , 
  232                   indexed_by < ordered_unique<member<BB2DomainInfo, unsigned int, &BB2DomainInfo::d_id> >,
  233                            ordered_unique<tag<NameTag>, member<BB2DomainInfo, DNSName, &BB2DomainInfo::d_name> >
  234                            > > state_t;
  235   static state_t s_state;
  236   static pthread_rwlock_t s_state_lock;
  237 
  238   void parseZoneFile(BB2DomainInfo *bbd);
  239   void insertRecord(BB2DomainInfo& bbd, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed=string(), bool *auth=0);
  240   void rediscover(string *status=0) override;
  241 
  242 
  243   // for supermaster support
  244   bool superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db) override;
  245   static pthread_mutex_t s_supermaster_config_lock;
  246   bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) override;
  247 
  248 private:
  249   void setupDNSSEC();
  250   void setupStatements();
  251   void freeStatements();
  252   void release(SSqlStatement**);
  253   static bool safeGetBBDomainInfo(int id, BB2DomainInfo* bbd);
  254   static void safePutBBDomainInfo(const BB2DomainInfo& bbd);
  255   static bool safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd);
  256   static bool safeRemoveBBDomainInfo(const DNSName& name);
  257   bool GetBBDomainInfo(int id, BB2DomainInfo** bbd);
  258   shared_ptr<SSQLite3> d_dnssecdb;
  259   bool getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p);
  260   class handle
  261   {
  262   public:
  263     bool get(DNSResourceRecord &);
  264     void reset();
  265     
  266     handle();
  267 
  268     shared_ptr<const recordstorage_t > d_records;
  269     recordstorage_t::index<UnorderedNameTag>::type::const_iterator d_iter, d_end_iter;
  270 
  271     recordstorage_t::const_iterator d_qname_iter, d_qname_end;
  272 
  273     DNSName qname;
  274     DNSName domain;
  275 
  276     int id;
  277     QType qtype;
  278     bool d_list;
  279     bool mustlog;
  280 
  281   private:
  282     bool get_normal(DNSResourceRecord &);
  283     bool get_list(DNSResourceRecord &);
  284 
  285     void operator=(const handle& ); // don't go copying this
  286     handle(const handle &);
  287   };
  288 
  289   unique_ptr<SSqlStatement> d_getAllDomainMetadataQuery_stmt;
  290   unique_ptr<SSqlStatement> d_getDomainMetadataQuery_stmt;
  291   unique_ptr<SSqlStatement> d_deleteDomainMetadataQuery_stmt;
  292   unique_ptr<SSqlStatement> d_insertDomainMetadataQuery_stmt;
  293   unique_ptr<SSqlStatement> d_getDomainKeysQuery_stmt;
  294   unique_ptr<SSqlStatement> d_deleteDomainKeyQuery_stmt;
  295   unique_ptr<SSqlStatement> d_insertDomainKeyQuery_stmt;
  296   unique_ptr<SSqlStatement> d_GetLastInsertedKeyIdQuery_stmt;
  297   unique_ptr<SSqlStatement> d_activateDomainKeyQuery_stmt;
  298   unique_ptr<SSqlStatement> d_deactivateDomainKeyQuery_stmt;
  299   unique_ptr<SSqlStatement> d_getTSIGKeyQuery_stmt;
  300   unique_ptr<SSqlStatement> d_setTSIGKeyQuery_stmt;
  301   unique_ptr<SSqlStatement> d_deleteTSIGKeyQuery_stmt;
  302   unique_ptr<SSqlStatement> d_getTSIGKeysQuery_stmt;
  303 
  304   string d_transaction_tmpname;
  305   string d_logprefix;
  306   set<string> alsoNotify; //!< this is used to store the also-notify list of interested peers.
  307   std::unique_ptr<ofstream> d_of;
  308   handle d_handle;
  309   static string s_binddirectory;                              //!< this is used to store the 'directory' setting of the bind configuration
  310   static int s_first;                                  //!< this is raised on construction to prevent multiple instances of us being generated
  311   int d_transaction_id;
  312   static bool s_ignore_broken_records;
  313   bool d_hybrid;
  314 
  315   BB2DomainInfo createDomainEntry(const DNSName& domain, const string &filename); //!< does not insert in s_state
  316 
  317   void queueReloadAndStore(unsigned int id);
  318   bool findBeforeAndAfterUnhashed(BB2DomainInfo& bbd, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after);
  319   void reload() override;
  320   static string DLDomStatusHandler(const vector<string>&parts, Utility::pid_t ppid);
  321   static string DLListRejectsHandler(const vector<string>&parts, Utility::pid_t ppid);
  322   static string DLReloadNowHandler(const vector<string>&parts, Utility::pid_t ppid);
  323   static string DLAddDomainHandler(const vector<string>&parts, Utility::pid_t ppid);
  324   static void fixupOrderAndAuth(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr);
  325   void doEmptyNonTerminals(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr);
  326   void loadConfig(string *status=0);
  327   static void nukeZoneRecords(BB2DomainInfo *bbd);
  328 
  329 };
  330 
  331 #endif /* PDNS_BINDBACKEND_HH */