From: Aki Tuomi Date: Thu, 21 May 2015 19:30:53 +0000 (+0300) Subject: Hook GSS-TSIG feature to code X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~79^2~9^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7f9ac49b819466edfb9ea515107ffebfdd91a18d;p=thirdparty%2Fpdns.git Hook GSS-TSIG feature to code --- diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc index e202004edd..73151cee2a 100644 --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@ -47,6 +47,7 @@ #include "dnssecinfra.hh" #include "base64.hh" #include "ednssubnet.hh" +#include "gss_context.hh" bool DNSPacket::s_doEDNSSubnetProcessing; uint16_t DNSPacket::s_udpTruncationThreshold; @@ -636,6 +637,14 @@ bool checkForCorrectTSIG(const DNSPacket* q, UeberBackend* B, string* keyname, s if (algoName == "hmac-md5.sig-alg.reg.int") algoName = "hmac-md5"; + if (algoName == "gss-tsig") { + if (!gss_verify_signature(*keyname, message, trc->d_mac)) { + L<qdomain<<"' denied: TSIG signature mismatch using '"<<*keyname<<"' and algorithm '"<d_algoName<<"'"<getTSIGKey(*keyname, &algoName, &secret64)) { L<qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<d_algoName, algo)) { - L<d_algoName << endl; - return; + throw PDNSException(string("Unsupported TSIG HMAC algorithm ") + trc->d_algoName); } string toSign; @@ -647,8 +647,14 @@ void addTSIG(DNSPacketWriter& pw, TSIGRecordContent* trc, const string& tsigkeyn const vector& signRecord=dw.getRecordBeingWritten(); toSign.append(&*signRecord.begin(), &*signRecord.end()); - trc->d_mac = calculateHMAC(tsigsecret, toSign, algo); - // d_trc->d_mac[0]++; // sabotage + if (algo == TSIG_GSS) { + if (!gss_add_signature(tsigkeyname, toSign, trc->d_mac)) { + throw PDNSException(string("Could not add TSIG signature with algorithm 'gss-tsig' and key name '")+tsigkeyname+string("'")); + } + } else { + trc->d_mac = calculateHMAC(tsigsecret, toSign, algo); + // d_trc->d_mac[0]++; // sabotage + } pw.startRecord(tsigkeyname, QType::TSIG, 0, QClass::ANY, DNSPacketWriter::ADDITIONAL, false); trc->toPacket(pw); pw.commit(); diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index af58d62756..d35e543c92 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -1058,6 +1058,14 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) else r->setRcode(RCode::NotAuth); return r; + } else { + getTSIGHashEnum(trc.d_algoName, p->d_tsig_algo); + if (p->d_tsig_algo == TSIG_GSS) { + GssContext gssctx(keyname); + if (!gssctx.getPeerPrincipal(p->d_peer_principal)) { + L<setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket() noCache=true; @@ -1420,7 +1428,8 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) { TKEYRecordContent tkey_in; std::shared_ptr tkey_out(new TKEYRecordContent()); - string label, lcLabel; + string label; + bool sign = false; if (!p->getTKEYRecord(&tkey_in, &label)) { L<d_error = 0; tkey_out->d_mode = tkey_in.d_mode; tkey_out->d_algo = tkey_in.d_algo; tkey_out->d_inception = time((time_t*)NULL); tkey_out->d_expiration = tkey_out->d_inception+15; - if (tkey_in.d_mode == 3) { - tkey_out->d_error = 19; // BADMODE - } else if (tkey_in.d_mode == 5) { + GssContext ctx(label); + + if (tkey_in.d_mode == 3) { // establish context + if (tkey_in.d_algo == "gss-tsig.") { + std::vector meta; + string tmpLabel = toLowerCanonic(label); + bool ok = true; + while(ok) { + if (B.getDomainMetadata(tmpLabel, "GSS-ACCEPTOR-PRINCIPAL", meta) && meta.size()>0) { + break; + } + ok = chopOff(tmpLabel); + } + + if (meta.size()>0) { + ctx.setLocalPrincipal(meta[0]); + } + // try to get a context + if (!ctx.accept(tkey_in.d_key, tkey_out->d_key)) + tkey_out->d_error = 19; + else + sign = true; + } else { + tkey_out->d_error = 21; // BADALGO + } + } else if (tkey_in.d_mode == 5) { // destroy context if (p->d_havetsig == false) { // unauthenticated if (p->d.opcode == Opcode::Update) r->setRcode(RCode::Refused); @@ -1447,7 +1477,10 @@ void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) { r->setRcode(RCode::NotAuth); return; } - tkey_out->d_error = 20; // BADNAME (because we have no support for anything here) + if (ctx.valid()) + ctx.destroy(); + else + tkey_out->d_error = 20; // BADNAME (because we have no support for anything here) } else { if (p->d_havetsig == false && tkey_in.d_mode != 2) { // unauthenticated if (p->d.opcode == Opcode::Update) @@ -1474,5 +1507,20 @@ void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) { rr.qtype = QType::TKEY; rr.d_place = DNSResourceRecord::ANSWER; r->addRecord(rr); + + if (sign) + { + TSIGRecordContent trc; + trc.d_algoName = "gss-tsig"; + trc.d_time = tkey_out->d_inception; + trc.d_fudge = 300; + trc.d_mac = ""; + trc.d_origID = p->d.id; + trc.d_eRcode = 0; + trc.d_otherData = ""; + // this should cause it to lookup label context + r->setTSIGDetails(trc, label, label, "", false); + } + r->commitD(); } diff --git a/pdns/packethandler.hh b/pdns/packethandler.hh index 645e8fca5f..352ecf60b6 100644 --- a/pdns/packethandler.hh +++ b/pdns/packethandler.hh @@ -30,6 +30,7 @@ #include "packetcache.hh" #include "dnsseckeeper.hh" #include "lua-auth.hh" +#include "gss_context.hh" #include "namespaces.hh" diff --git a/pdns/resolver.cc b/pdns/resolver.cc index a4e8475658..6f8778d171 100644 --- a/pdns/resolver.cc +++ b/pdns/resolver.cc @@ -505,11 +505,18 @@ int AXFRRetriever::getChunk(Resolver::res_t &res) // Implementation is making su throw ResolverException("Unsupported TSIG HMAC algorithm " + d_trc.d_algoName); } - string ourMac=calculateHMAC(d_tsigsecret, message, algo); + if (algo == TSIG_GSS) { + GssContext gssctx(d_tsigkeyname); + if (!gss_verify_signature(d_tsigkeyname, message, theirMac)) { + throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tsigkeyname+"'"); + } + } else { + string ourMac=calculateHMAC(d_tsigsecret, message, algo); - // ourMac[0]++; // sabotage == for testing :-) - if(ourMac != theirMac) { - throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tsigkeyname+"'"); + // ourMac[0]++; // sabotage == for testing :-) + if(ourMac != theirMac) { + throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tsigkeyname+"'"); + } } // Reset and store some values for the next chunks. diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index 36b3468831..e6710b797d 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -420,7 +420,16 @@ bool TCPNameserver::canDoAXFR(shared_ptr q) string keyname, secret; if(!checkForCorrectTSIG(q.get(), s_P->getBackend(), &keyname, &secret, &trc)) return false; - + } else { + getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo); + if (q->d_tsig_algo == TSIG_GSS) { + GssContext gssctx(keyname); + if (!gssctx.getPeerPrincipal(q->d_peer_principal)) { + L<