Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auth: move checkForCorrectTSIG into packethandler #14701

Merged
merged 2 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
46 changes: 41 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 @@ -1336,6 +1337,7 @@ bool PacketHandler::tryWildcard(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNS
}

//! Called by the Distributor to ask a question. Returns 0 in case of an error
// NOLINTNEXTLINE(readability-function-cognitive-complexity): TODO Clean this function up.
std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
{
DNSZoneRecord rr;
Expand Down Expand Up @@ -1394,10 +1396,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 +1413,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 +1847,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
Loading