Skip to content

Commit

Permalink
auth: move checkForCorrectTSIG into packethandler
Browse files Browse the repository at this point in the history
To avoid DNSPacket pulling UeberBackend.
  • Loading branch information
zeha committed Sep 23, 2024
1 parent cf7d385 commit dc3c6f8
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 55 deletions.
48 changes: 11 additions & 37 deletions pdns/dnspacket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
5 changes: 1 addition & 4 deletions pdns/dnspacket.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
45 changes: 40 additions & 5 deletions pdns/packethandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
}
1 change: 1 addition & 0 deletions pdns/packethandler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 9 additions & 9 deletions pdns/tcpreceiver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
}
Expand Down

0 comments on commit dc3c6f8

Please sign in to comment.