#include "dnssecinfra.hh"
#include "base64.hh"
#include "ednssubnet.hh"
+#include "gss_context.hh"
bool DNSPacket::s_doEDNSSubnetProcessing;
uint16_t DNSPacket::s_udpTruncationThreshold;
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<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: TSIG signature mismatch using '"<<*keyname<<"' and algorithm '"<<trc->d_algoName<<"'"<<endl;
+ return false;
+ }
+ return true;
+ }
+
string secret64;
if(!B->getTSIGKey(*keyname, &algoName, &secret64)) {
L<<Logger::Error<<"Packet for domain '"<<q->qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<<algoName<<"'"<<endl;
bool d_dnssecOk;
bool d_havetsig;
+ string d_peer_principal;
+ TSIGHashEnum d_tsig_algo;
+
bool getTSIGDetails(TSIGRecordContent* tr, string* keyname, string* message) const;
void setTSIGDetails(const TSIGRecordContent& tr, const string& keyname, const string& secret, const string& previous, bool timersonly=false);
bool getTKEYRecord(TKEYRecordContent* tr, string* keyname) const;
#ifdef HAVE_P11KIT1
#include "pkcs11signers.hh"
#endif
+#include "gss_context.hh"
using namespace boost::assign;
{
TSIGHashEnum algo;
if (!getTSIGHashEnum(trc->d_algoName, algo)) {
- L<<Logger::Error<<"Unsupported TSIG HMAC algorithm " << trc->d_algoName << endl;
- return;
+ throw PDNSException(string("Unsupported TSIG HMAC algorithm ") + trc->d_algoName);
}
string toSign;
const vector<uint8_t>& 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();
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<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
+ }
+ }
}
p->setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket()
noCache=true;
void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) {
TKEYRecordContent tkey_in;
std::shared_ptr<TKEYRecordContent> tkey_out(new TKEYRecordContent());
- string label, lcLabel;
+ string label;
+ bool sign = false;
if (!p->getTKEYRecord(&tkey_in, &label)) {
L<<Logger::Error<<"TKEY request but no TKEY RR found"<<endl;
}
// retain original label for response
- lcLabel = toLowerCanonic(label);
-
tkey_out->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<std::string> 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);
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)
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();
}
#include "packetcache.hh"
#include "dnsseckeeper.hh"
#include "lua-auth.hh"
+#include "gss_context.hh"
#include "namespaces.hh"
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.
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<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
+ }
+ }
+ }
+
DNSSECKeeper dk;
string algorithm=toLowerCanonic(trc.d_algoName);