]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth: move checkForCorrectTSIG into packethandler
authorChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Tue, 27 Aug 2024 19:28:36 +0000 (21:28 +0200)
committerChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Mon, 23 Sep 2024 08:01:47 +0000 (10:01 +0200)
To avoid DNSPacket pulling UeberBackend.

pdns/dnspacket.cc
pdns/dnspacket.hh
pdns/packethandler.cc
pdns/packethandler.hh
pdns/tcpreceiver.cc

index 324399cd3ca886a73a8987b28bc165b5f6f6d42d..8588f2c21a151990792e98d6d195e0dedbd553d3 100644 (file)
@@ -535,6 +535,17 @@ bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_
   return true;
 }
 
+bool DNSPacket::validateTSIG(const TSIGTriplet& tsigTriplet, const TSIGRecordContent& tsigContent, const std::string& previousMAC, const std::string& theirMAC, bool timersOnly) const
+{
+  MOADNSParser mdp(d_isQuery, d_rawpacket);
+  uint16_t tsigPos = mdp.getTSIGPos();
+  if (tsigPos == 0) {
+    return false;
+  }
+
+  return ::validateTSIG(d_rawpacket, tsigPos, tsigTriplet, tsigContent, previousMAC, theirMAC, timersOnly);
+}
+
 bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
 {
   MOADNSParser mdp(d_isQuery, d_rawpacket);
@@ -724,43 +735,6 @@ void DNSPacket::commitD()
   d_rawpacket.replace(0,12,(char *)&d,12); // copy in d
 }
 
-bool DNSPacket::checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const
-{
-  uint16_t tsigPos;
-
-  if (!this->getTSIGDetails(trc, keyname, &tsigPos)) {
-    return false;
-  }
-
-  TSIGTriplet tt;
-  tt.name = *keyname;
-  tt.algo = trc->d_algoName;
-  if (tt.algo == DNSName("hmac-md5.sig-alg.reg.int"))
-    tt.algo = DNSName("hmac-md5");
-
-  if (tt.algo != DNSName("gss-tsig")) {
-    string secret64;
-    if(!B->getTSIGKey(*keyname, tt.algo, secret64)) {
-      g_log << Logger::Error << "Packet for domain '" << this->qdomain << "' denied: can't find TSIG key with name '" << *keyname << "' and algorithm '" << tt.algo << "'" << endl;
-      return false;
-    }
-    B64Decode(secret64, *secret);
-    tt.secret = *secret;
-  }
-
-  bool result;
-
-  try {
-    result = validateTSIG(d_rawpacket, tsigPos, tt, *trc, "", trc->d_mac, false);
-  }
-  catch(const std::runtime_error& err) {
-    g_log<<Logger::Error<<"Packet for '"<<this->qdomain<<"' denied: "<<err.what()<<endl;
-    return false;
-  }
-
-  return result;
-}
-
 const DNSName& DNSPacket::getTSIGKeyname() const {
   return d_tsigkeyname;
 }
index a9bd01004831298cfbeddfe75e0085dbcf066a0a..67b84c651a237ff772e786d03c60f39ce641ee08 100644 (file)
@@ -44,9 +44,6 @@
 #include "pdnsexception.hh"
 #include "dnsrecords.hh"
 
-class UeberBackend;
-class DNSSECKeeper;
-
 
 //! This class represents DNS packets, either received or to be sent.
 class DNSPacket
@@ -165,10 +162,10 @@ public:
 
   bool getTSIGDetails(TSIGRecordContent* tr, DNSName* keyname, uint16_t* tsigPos=nullptr) const;
   void setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly=false);
+  bool validateTSIG(const TSIGTriplet& tsigTriplet, const TSIGRecordContent& tsigContent, const std::string& previousMAC, const std::string& theirMAC, bool timersOnly) const;
   bool getTKEYRecord(TKEYRecordContent* tr, DNSName* keyname) const;
 
   vector<DNSZoneRecord>& getRRS() { return d_rrs; }
-  bool checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const;
 
   static uint16_t s_udpTruncationThreshold;
   static bool s_doEDNSSubnetProcessing;
index 3d385ed7b54ce6f6996d4762e270fc7a42b37b6f..b8aa267ddcb46e218eca36f44214fc74eb541302 100644 (file)
@@ -25,6 +25,7 @@
 #include "packetcache.hh"
 #include "utility.hh"
 #include "base32.hh"
+#include "base64.hh"
 #include <string>
 #include <sys/types.h>
 #include <boost/algorithm/string.hpp>
@@ -1394,10 +1395,10 @@ std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
   }
 
   if(p.d_havetsig) {
-    DNSName keyname;
+    DNSName tsigkeyname;
     string secret;
     TSIGRecordContent trc;
-    if(!p.checkForCorrectTSIG(&B, &keyname, &secret, &trc)) {
+    if (!checkForCorrectTSIG(p, &tsigkeyname, &secret, &trc)) {
       r=p.replyPacket();  // generate an empty reply packet
       if(d_logDNSDetails)
         g_log<<Logger::Error<<"Received a TSIG signed message with a non-validating key"<<endl;
@@ -1411,14 +1412,14 @@ std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
       getTSIGHashEnum(trc.d_algoName, p.d_tsig_algo);
 #ifdef ENABLE_GSS_TSIG
       if (g_doGssTSIG && p.d_tsig_algo == TSIG_GSS) {
-        GssContext gssctx(keyname);
+        GssContext gssctx(tsigkeyname);
         if (!gssctx.getPeerPrincipal(p.d_peer_principal)) {
-          g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
+          g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<tsigkeyname<<"'"<<endl;
         }
       }
 #endif
     }
-    p.setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket()
+    p.setTSIGDetails(trc, tsigkeyname, secret, trc.d_mac); // this will get copied by replyPacket()
     noCache=true;
   }
 
@@ -1845,3 +1846,37 @@ std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
   return r;
 
 }
+
+bool PacketHandler::checkForCorrectTSIG(const DNSPacket& packet, DNSName* tsigkeyname, string* secret, TSIGRecordContent* tsigContent)
+{
+  uint16_t tsigPos{0};
+
+  if (!packet.getTSIGDetails(tsigContent, tsigkeyname, &tsigPos)) {
+    return false;
+  }
+
+  TSIGTriplet tsigTriplet;
+  tsigTriplet.name = *tsigkeyname;
+  tsigTriplet.algo = tsigContent->d_algoName;
+  if (tsigTriplet.algo == DNSName("hmac-md5.sig-alg.reg.int")) {
+    tsigTriplet.algo = DNSName("hmac-md5");
+  }
+
+  if (tsigTriplet.algo != DNSName("gss-tsig")) {
+    string secret64;
+    if (!B.getTSIGKey(*tsigkeyname, tsigTriplet.algo, secret64)) {
+      g_log << Logger::Error << "Packet for domain '" << packet.qdomain << "' denied: can't find TSIG key with name '" << *tsigkeyname << "' and algorithm '" << tsigTriplet.algo << "'" << endl;
+      return false;
+    }
+    B64Decode(secret64, *secret);
+    tsigTriplet.secret = *secret;
+  }
+
+  try {
+    return packet.validateTSIG(tsigTriplet, *tsigContent, "", tsigContent->d_mac, false);
+  }
+  catch(const std::runtime_error& err) {
+    g_log<<Logger::Error<<"Packet for '"<<packet.qdomain<<"' denied: "<<err.what()<<endl;
+    return false;
+  }
+}
index 8af3bde2c9a83b7ba01c30e9d19f241a539a3231..716aa5a3df10871bba02a8625931293b16d35b5c 100644 (file)
@@ -61,6 +61,7 @@ public:
   UeberBackend *getBackend();
 
   int tryAutoPrimarySynchronous(const DNSPacket& p, const DNSName& tsigkeyname);
+  bool checkForCorrectTSIG(const DNSPacket& packet, DNSName* tsigkeyname, string* secret, TSIGRecordContent* tsigContent);
   static NetmaskGroup s_allowNotifyFrom;
   static set<string> s_forwardNotify;
   static bool s_SVCAutohints;
index 8dfa9573158846c888f277b22611fe236c7d2b6a..c4696a8f72ccd0d93e34ea9dca1ad8cfdc2cfc28 100644 (file)
@@ -463,18 +463,18 @@ bool TCPNameserver::canDoAXFR(std::unique_ptr<DNSPacket>& q, bool isAXFR, std::u
   string logPrefix=string(isAXFR ? "A" : "I")+"XFR-out zone '"+q->qdomain.toLogString()+"', client '"+q->getInnerRemote().toStringWithPort()+"', ";
 
   if(q->d_havetsig) { // if you have one, it must be good
-    TSIGRecordContent trc;
-    DNSName keyname;
+    TSIGRecordContent tsigContent;
+    DNSName tsigkeyname;
     string secret;
-    if(!q->checkForCorrectTSIG(packetHandler->getBackend(), &keyname, &secret, &trc)) {
+    if (!packetHandler->checkForCorrectTSIG(*q, &tsigkeyname, &secret, &tsigContent)) {
       return false;
     } else {
-      getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo);
+      getTSIGHashEnum(tsigContent.d_algoName, q->d_tsig_algo);
 #ifdef ENABLE_GSS_TSIG
       if (g_doGssTSIG && q->d_tsig_algo == TSIG_GSS) {
-        GssContext gssctx(keyname);
+        GssContext gssctx(tsigkeyname);
         if (!gssctx.getPeerPrincipal(q->d_peer_principal)) {
-          g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
+          g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<tsigkeyname<<"'"<<endl;
         }
       }
 #endif
@@ -495,12 +495,12 @@ bool TCPNameserver::canDoAXFR(std::unique_ptr<DNSPacket>& q, bool isAXFR, std::u
       return false;
     }
 #endif
-    if(!dk.TSIGGrantsAccess(q->qdomain, keyname)) {
-      g_log<<Logger::Warning<<logPrefix<<"denied: key with name '"<<keyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"' does not grant access"<<endl;
+    if(!dk.TSIGGrantsAccess(q->qdomain, tsigkeyname)) {
+      g_log<<Logger::Warning<<logPrefix<<"denied: key with name '"<<tsigkeyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"' does not grant access"<<endl;
       return false;
     }
     else {
-      g_log<<Logger::Notice<<logPrefix<<"allowed: TSIG signed request with authorized key '"<<keyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"'"<<endl;
+      g_log<<Logger::Notice<<logPrefix<<"allowed: TSIG signed request with authorized key '"<<tsigkeyname<<"' and algorithm '"<<getTSIGAlgoName(q->d_tsig_algo)<<"'"<<endl;
       return true;
     }
   }