diff --git a/.not-formatted b/.not-formatted index 4d48f339e646..cd653a2fcc62 100644 --- a/.not-formatted +++ b/.not-formatted @@ -215,7 +215,6 @@ ./pdns/test-ueberbackend_cc.cc ./pdns/test-zoneparser_tng_cc.cc ./pdns/threadname.cc -./pdns/tkey.cc ./pdns/trusted-notification-proxy.cc ./pdns/trusted-notification-proxy.hh ./pdns/tsig-tests.cc diff --git a/meson.build b/meson.build index 0b426d1875cb..d2a909a67b4a 100644 --- a/meson.build +++ b/meson.build @@ -622,7 +622,6 @@ common_sources += files( src_dir / 'tcpreceiver.hh', src_dir / 'threadname.cc', src_dir / 'threadname.hh', - src_dir / 'tkey.cc', src_dir / 'trusted-notification-proxy.cc', src_dir / 'trusted-notification-proxy.hh', src_dir / 'tsigutils.cc', diff --git a/pdns/Makefile.am b/pdns/Makefile.am index bee1d58ef06d..b9a7d3d66339 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -277,7 +277,6 @@ pdns_server_SOURCES = \ svc-records.cc svc-records.hh \ tcpreceiver.cc tcpreceiver.hh \ threadname.hh threadname.cc \ - tkey.cc \ trusted-notification-proxy.hh trusted-notification-proxy.cc \ tsigutils.hh tsigutils.cc \ tsigverifier.cc tsigverifier.hh \ diff --git a/pdns/distributor.hh b/pdns/distributor.hh index cdee87b67dc7..a2f32f4bba68 100644 --- a/pdns/distributor.hh +++ b/pdns/distributor.hh @@ -199,7 +199,7 @@ templatevoid MultiThreadDistributor } --d_queued; auto questionData = std::move(*tempQD); - std::unique_ptr a = nullptr; + std::unique_ptr answer = nullptr; if (queuetimeout && questionData->Q.d_dt.udiff() > queuetimeout * 1000) { S.inc("timedout-packets"); continue; @@ -213,15 +213,13 @@ retry: allowRetry = false; b = make_unique(); } - a = b->question(questionData->Q); + answer = b->question(questionData->Q); } catch (const PDNSException &e) { b.reset(); if (!allowRetry) { g_log<Q.replyPacket(); - - a->setRcode(RCode::ServFail); + answer = questionData->Q.replyPacket(RCode::ServFail); S.inc("servfail-packets"); S.ringAccount("servfail-queries", questionData->Q.qdomain, questionData->Q.qtype); } else { @@ -233,9 +231,7 @@ retry: b.reset(); if (!allowRetry) { g_log<Q.replyPacket(); - - a->setRcode(RCode::ServFail); + answer = questionData->Q.replyPacket(RCode::ServFail); S.inc("servfail-packets"); S.ringAccount("servfail-queries", questionData->Q.qdomain, questionData->Q.qtype); } else { @@ -244,10 +240,10 @@ retry: } } - questionData->callback(a, questionData->start); + questionData->callback(answer, questionData->start); #ifdef ENABLE_GSS_TSIG - if (g_doGssTSIG && a != nullptr) { - questionData->Q.cleanupGSS(a->d.rcode); + if (g_doGssTSIG && answer != nullptr) { + questionData->Q.cleanupGSS(answer->d.rcode); } #endif questionData.reset(); @@ -272,7 +268,7 @@ retry: templateint SingleThreadDistributor::question(Question& q, callback_t callback) { int start = q.d_dt.udiff(); - std::unique_ptr a = nullptr; + std::unique_ptr answer = nullptr; bool allowRetry=true; retry: try { @@ -280,15 +276,13 @@ retry: allowRetry=false; b=make_unique(); } - a=b->question(q); // a can be NULL! + answer = b->question(q); // answer can be NULL! } catch(const PDNSException &e) { b.reset(); if (!allowRetry) { g_log<setRcode(RCode::ServFail); + answer = q.replyPacket(RCode::ServFail); S.inc("servfail-packets"); S.ringAccount("servfail-queries", q.qdomain, q.qtype); } else { @@ -300,9 +294,7 @@ retry: b.reset(); if (!allowRetry) { g_log<setRcode(RCode::ServFail); + answer = q.replyPacket(RCode::ServFail); S.inc("servfail-packets"); S.ringAccount("servfail-queries", q.qdomain, q.qtype); } else { @@ -310,10 +302,10 @@ retry: goto retry; } } - callback(a, start); + callback(answer, start); #ifdef ENABLE_GSS_TSIG - if (g_doGssTSIG && a != nullptr) { - q.cleanupGSS(a->d.rcode); + if (g_doGssTSIG && answer != nullptr) { + q.cleanupGSS(answer->d.rcode); } #endif return 0; diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc index e926a658b408..595999bc3fd5 100644 --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@ -421,7 +421,7 @@ void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype) } /** convenience function for creating a reply packet from a question packet. */ -std::unique_ptr DNSPacket::replyPacket() const +std::unique_ptr DNSPacket::replyPacket(int rcode, uint16_t extRCode) const { auto r=make_unique(false); r->setSocket(d_socket); @@ -434,6 +434,8 @@ std::unique_ptr DNSPacket::replyPacket() const r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it r->setID(d.id); r->setOpcode(d.opcode); + r->setRcode(rcode); + r->setEDNSRcode(extRCode); r->d_dt=d_dt; r->d.qdcount=1; diff --git a/pdns/dnspacket.hh b/pdns/dnspacket.hh index a9bd01004831..26a58c4091c8 100644 --- a/pdns/dnspacket.hh +++ b/pdns/dnspacket.hh @@ -116,7 +116,7 @@ public: vector getServiceRecords(); //!< Get a vector with all Service-style (SVCB) records void setCompress(bool compress); - std::unique_ptr replyPacket() const; //!< convenience function that creates a virgin answer packet to this question + std::unique_ptr replyPacket(int rcode = RCode::NoError, uint16_t extRCode = 0) const; //!< convenience function that creates a virgin answer packet to this question void commitD(); //!< copies 'd' into the stringbuffer unsigned int getMaxReplyLen(); //!< retrieve the maximum length of the packet we should send in response diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index 797922b38723..fa2846a6beb9 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -60,6 +60,8 @@ bool PacketHandler::s_SVCAutohints{false}; extern string g_programname; +[[nodiscard]] static std::unique_ptr tkeyHandler(const DNSPacket& p); + // See https://www.rfc-editor.org/rfc/rfc8078.txt and https://www.rfc-editor.org/errata/eid5049 for details const std::shared_ptr PacketHandler::s_deleteCDNSKEYContent = std::make_shared("0 3 0 AA=="); const std::shared_ptr PacketHandler::s_deleteCDSContent = std::make_shared("0 0 0 00"); @@ -276,12 +278,12 @@ bool PacketHandler::addNSEC3PARAM(const DNSPacket& p, std::unique_ptr } -// This is our chaos class requests handler. Return 1 if content was added, 0 if it wasn't -int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr& r, DNSName &target) const +// This is our chaos class request handler. Returns a reply packet. +[[nodiscard]] +static std::unique_ptr doChaosRequest(const DNSPacket& p, const DNSName &target) { - DNSZoneRecord rr; - if(p.qtype.getCode()==QType::TXT) { + DNSZoneRecord rr; static const DNSName versionbind("version.bind."), versionpdns("version.pdns."), idserver("id.server."); if (target==versionbind || target==versionpdns) { // modes: full, powerdns only, anonymous or custom @@ -292,8 +294,7 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr else if(mode=="powerdns") content="Served by PowerDNS - https://www.powerdns.com/"; else if(mode=="anonymous") { - r->setRcode(RCode::ServFail); - return 0; + return p.replyPacket(RCode::ServFail); } else content=mode; @@ -304,8 +305,7 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr const static string id=::arg()["server-id"]; if (id == "disabled") { - r->setRcode(RCode::Refused); - return 0; + return p.replyPacket(RCode::Refused); } string tid=id; if(!tid.empty() && tid[0]!='"') { // see #6010 however @@ -314,20 +314,20 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr rr.dr.setContent(DNSRecordContent::make(QType::TXT, 1, tid)); } else { - r->setRcode(RCode::Refused); - return 0; + return p.replyPacket(RCode::Refused); } rr.dr.d_ttl=5; rr.dr.d_name=target; rr.dr.d_type=QType::TXT; rr.dr.d_class=QClass::CHAOS; - r->addRecord(std::move(rr)); - return 1; + + auto reply = p.replyPacket(); + reply->addRecord(std::move(rr)); + return reply; } - r->setRcode(RCode::NotImp); - return 0; + return p.replyPacket(RCode::NotImp); } vector PacketHandler::getBestReferralNS(DNSPacket& p, const DNSName &target) @@ -1079,7 +1079,7 @@ int PacketHandler::tryAutoPrimarySynchronous(const DNSPacket& p, const DNSName& return RCode::NoError; } -int PacketHandler::processNotify(const DNSPacket& p) +uint8_t PacketHandler::processNotify(const DNSPacket& p) { /* now what? was this notification from an approved address? @@ -1196,8 +1196,7 @@ std::unique_ptr PacketHandler::question(DNSPacket& p) void PacketHandler::makeNXDomain(DNSPacket& p, std::unique_ptr& r, const DNSName& target, const DNSName& wildcard) { - DNSZoneRecord rr; - rr=makeEditedDNSZRFromSOAData(d_dk, d_sd, DNSResourceRecord::AUTHORITY); + DNSZoneRecord rr = makeEditedDNSZRFromSOAData(d_dk, d_sd, DNSResourceRecord::AUTHORITY); rr.dr.d_ttl=d_sd.getNegativeTTL(); r->addRecord(std::move(rr)); @@ -1338,23 +1337,6 @@ bool PacketHandler::tryWildcard(DNSPacket& p, std::unique_ptr& r, DNS //! Called by the Distributor to ask a question. Returns 0 in case of an error std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) { - DNSZoneRecord rr; - - int retargetcount=0; - set authSet; - - vector rrset; - bool weDone=false, weRedirected=false, weHaveUnauth=false, doSigs=false; - DNSName haveAlias; - uint8_t aliasScopeMask; - - std::unique_ptr r{nullptr}; - bool noCache=false; - -#ifdef HAVE_LUA_RECORDS - bool doLua=g_doLuaRecord; -#endif - if(p.d.qr) { // QR bit from dns packet (thanks RA from N) if(d_logDNSDetails) g_log< PacketHandler::doQuestion(DNSPacket& p) if (p.hasEDNS()) { if(p.getEDNSVersion() > 0) { - r = p.replyPacket(); - - // PacketWriter::addOpt will take care of setting this correctly in the packet - r->setEDNSRcode(ERCode::BADVERS); - return r; + // PacketWriter::addOpt will take care of setting ERCode in the packet + return p.replyPacket(0, ERCode::BADVERS); } if (p.hasEDNSCookie()) { if (!p.hasWellFormedEDNSCookie()) { - r = p.replyPacket(); - r->setRcode(RCode::FormErr); - return r; + return p.replyPacket(RCode::FormErr); } if (!p.hasValidEDNSCookie() && !p.d_tcp) { - r = p.replyPacket(); - r->setEDNSRcode(ERCode::BADCOOKIE); - return r; + return p.replyPacket(0, ERCode::BADCOOKIE); } } } @@ -1398,15 +1373,10 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) string secret; TSIGRecordContent trc; if(!p.checkForCorrectTSIG(&B, &keyname, &secret, &trc)) { - r=p.replyPacket(); // generate an empty reply packet if(d_logDNSDetails) g_log<setRcode(RCode::Refused); - else - r->setRcode(RCode::NotAuth); - return r; + return p.replyPacket(p.d.opcode == Opcode::Update ? RCode::Refused : RCode::NotAuth); // generate an empty reply packet } else { getTSIGHashEnum(trc.d_algoName, p.d_tsig_algo); #ifdef ENABLE_GSS_TSIG @@ -1419,18 +1389,13 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) #endif } p.setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket() - noCache=true; } - r=p.replyPacket(); // generate an empty reply packet, possibly with TSIG details inside - if (p.qtype == QType::TKEY) { - this->tkeyHandler(p, r); - return r; + return tkeyHandler(p); } try { - // XXX FIXME do this in DNSPacket::parse ? if(!validDNSName(p.qdomain)) { @@ -1439,68 +1404,90 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) S.inc("corrupt-packets"); S.ringAccount("remotes-corrupt", p.getInnerRemote()); S.inc("servfail-packets"); - r->setRcode(RCode::ServFail); - return r; - } - if(p.d.opcode) { // non-zero opcode (again thanks RA!) - if(p.d.opcode==Opcode::Update) { - S.inc("dnsupdate-queries"); - int res=processUpdate(p); - if (res == RCode::Refused) - S.inc("dnsupdate-refused"); - else if (res != RCode::ServFail) - S.inc("dnsupdate-answers"); - r->setRcode(res); - r->setOpcode(Opcode::Update); - return r; - } - else if(p.d.opcode==Opcode::Notify) { - S.inc("incoming-notifications"); - int res=processNotify(p); - if(res>=0) { - r->setRcode(res); - r->setOpcode(Opcode::Notify); - return r; - } - return nullptr; - } + return p.replyPacket(RCode::ServFail); + } + if (p.d.opcode == Opcode::Update) { + S.inc("dnsupdate-queries"); + int res = processUpdate(p); + if (res == RCode::Refused) + S.inc("dnsupdate-refused"); + else if (res != RCode::ServFail) + S.inc("dnsupdate-answers"); + return p.replyPacket(res); + } + else if (p.d.opcode == Opcode::Notify) { + S.inc("incoming-notifications"); + return p.replyPacket(processNotify(p)); + } + else if (p.d.opcode == Opcode::Query) { + return processQuery(p); + } else { g_log<setRcode(RCode::NotImp); - return r; + return p.replyPacket(RCode::NotImp); } + } + catch(const DBException &e) { + g_log< PacketHandler::processQuery(DNSPacket& p) { + int retargetcount=0; + set authSet; + + vector rrset; + bool weDone=false, weRedirected=false, weHaveUnauth=false, doSigs=false, noCache=false; + DNSName haveAlias; + uint8_t aliasScopeMask; + +#ifdef HAVE_LUA_RECORDS + bool doLua=g_doLuaRecord; +#endif // g_log<setRcode(RCode::Refused); - return r; + if (p.qtype == QType::IXFR) { + return p.replyPacket(RCode::Refused); } - DNSName target=p.qdomain; + DNSName target = p.qdomain; // catch chaos qclass requests if(p.qclass == QClass::CHAOS) { - if (doChaosRequest(p,r,target)) - goto sendit; - else - return r; + return doChaosRequest(p, target); } // we only know about qclass IN (and ANY), send Refused for everything else. if(p.qclass != QClass::IN && p.qclass!=QClass::ANY) { - r->setRcode(RCode::Refused); - return r; + return p.replyPacket(RCode::Refused); } // send TC for udp ANY query if any-to-tcp is enabled. if(p.qtype.getCode() == QType::ANY && !p.d_tcp && g_anyToTcp) { - r->d.tc = 1; - r->commitD(); - return r; + auto reply = p.replyPacket(); + reply->d.tc = 1; + reply->commitD(); + return reply; } + // We will now handle INternet class Queries. We expect to put a real reply into `r`. + auto r{p.replyPacket()}; + // for qclass ANY the response should never be authoritative unless the response covers all classes. if(p.qclass==QClass::ANY) r->setA(false); @@ -1509,9 +1496,7 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) retargeted:; if(retargetcount > 10) { // XXX FIXME, retargetcount++? g_log<setRcode(RCode::ServFail); - return r; + return p.replyPacket(RCode::ServFail); } if(!B.getAuth(target, p.qtype, &d_sd)) { @@ -1556,8 +1541,7 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) } if(p.qtype.getCode() == QType::SOA && d_sd.qname==p.qdomain) { - rr=makeEditedDNSZRFromSOAData(d_dk, d_sd); - r->addRecord(std::move(rr)); + r->addRecord(makeEditedDNSZRFromSOAData(d_dk, d_sd)); goto sendit; } @@ -1590,6 +1574,7 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) #endif // see what we get.. + DNSZoneRecord rr; B.lookup(QType(QType::ANY), target, d_sd.domain_id, &p); rrset.clear(); haveAlias.clear(); @@ -1625,10 +1610,7 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) catch(std::exception &e) { while (B.get(rr)) ; // don't leave DB handle in bad state - r=p.replyPacket(); - r->setRcode(RCode::ServFail); - - return r; + return p.replyPacket(RCode::ServFail); } } } @@ -1823,25 +1805,129 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) if(PC.enabled() && !noCache && p.couldBeCached()) PC.insert(p, *r, r->getMinTTL()); // in the packet cache + + return r; +} + +// tkeyHandler(const DNSPacket& p) { +#ifdef ENABLE_GSS_TSIG + if (g_doGssTSIG) { + auto [i,a,s] = GssContext::getCounts(); + g_log << Logger::Debug << "GSS #init_creds: " << i << " #accept_creds: " << a << " #secctxs: " << s << endl; } - catch(const DBException &e) { - g_log<setRcode(RCode::ServFail); - S.inc("servfail-packets"); - S.ringAccount("servfail-queries", p.qdomain, p.qtype); +#endif + + TKEYRecordContent tkey_in; + std::shared_ptr tkey_out(new TKEYRecordContent()); + DNSName name; +#ifdef ENABLE_GSS_TSIG + bool sign = false; +#endif + + if (!p.getTKEYRecord(&tkey_in, &name)) { + g_log<d_error = 0; + tkey_out->d_mode = tkey_in.d_mode; + tkey_out->d_algo = tkey_in.d_algo; + // coverity[store_truncates_time_t] + tkey_out->d_inception = inception; + tkey_out->d_expiration = tkey_out->d_inception+15; + + if (tkey_in.d_mode == 3) { // establish context +#ifdef ENABLE_GSS_TSIG + if (g_doGssTSIG) { + if (tkey_in.d_algo == DNSName("gss-tsig.")) { + std::vector meta; + DNSName tmpName(name); + do { + if (B.getDomainMetadata(tmpName, "GSS-ACCEPTOR-PRINCIPAL", meta) && meta.size()>0) { + break; + } + } while(tmpName.chopOff()); + + if (meta.size() == 0) { + tkey_out->d_error = 20; + } else { + GssContext ctx(name); + ctx.setLocalPrincipal(meta[0]); + // try to get a context + if (!ctx.accept(tkey_in.d_key, tkey_out->d_key)) { + ctx.destroy(); + tkey_out->d_error = 19; + } + else { + sign = true; + } + } + } else { + tkey_out->d_error = 21; // BADALGO + } + } else +#endif + { + tkey_out->d_error = 21; // BADALGO +#ifdef ENABLE_GSS_TSIG + g_log<d_error = 20; // BADNAME (because we have no support for anything here) + } + } else { + if (p.d_havetsig == false && tkey_in.d_mode != 2) { // unauthenticated + return p.replyPacket(p.d.opcode == Opcode::Update ? RCode::Refused : RCode::NotAuth); + } + tkey_out->d_error = 19; // BADMODE } - catch(const std::exception &e) { - g_log<setRcode(RCode::ServFail); - S.inc("servfail-packets"); - S.ringAccount("servfail-queries", p.qdomain, p.qtype); + + tkey_out->d_keysize = tkey_out->d_key.size(); + tkey_out->d_othersize = tkey_out->d_other.size(); + + DNSZoneRecord zrr; + + zrr.dr.d_name = name; + zrr.dr.d_ttl = 0; + zrr.dr.d_type = QType::TKEY; + zrr.dr.d_class = QClass::ANY; + zrr.dr.setContent(std::move(tkey_out)); + zrr.dr.d_place = DNSResourceRecord::ANSWER; + + std::unique_ptr reply = p.replyPacket(); + reply->addRecord(std::move(zrr)); + +#ifdef ENABLE_GSS_TSIG + if (sign) + { + TSIGRecordContent trc; + trc.d_algoName = DNSName("gss-tsig"); + trc.d_time = 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 name context + reply->setTSIGDetails(trc, name, name.toStringNoDot(), "", false); } - return r; +#endif + reply->commitD(); + return reply; } diff --git a/pdns/packethandler.hh b/pdns/packethandler.hh index 8af3bde2c9a8..cdd2fbae786c 100644 --- a/pdns/packethandler.hh +++ b/pdns/packethandler.hh @@ -69,9 +69,8 @@ public: private: int tryAutoPrimary(const DNSPacket& p, const DNSName& tsigkeyname); - int processNotify(const DNSPacket& ); + uint8_t processNotify(const DNSPacket& p); void addRootReferral(DNSPacket& r); - int doChaosRequest(const DNSPacket& p, std::unique_ptr& r, DNSName &target) const; bool addDNSKEY(DNSPacket& p, std::unique_ptr& r); bool addCDNSKEY(DNSPacket& p, std::unique_ptr& r); bool addCDS(DNSPacket& p, std::unique_ptr& r); @@ -87,6 +86,7 @@ private: void addNSEC3(DNSPacket& p, std::unique_ptr& r, const DNSName &target, const DNSName &wildcard, const NSEC3PARAMRecordContent& nsec3param, bool narrow, int mode); void emitNSEC(std::unique_ptr& r, const DNSName& name, const DNSName& next, int mode); void emitNSEC3(std::unique_ptr& r, const NSEC3PARAMRecordContent &ns3rc, const DNSName& unhashed, const string& begin, const string& end, int mode); + unique_ptr processQuery(DNSPacket& p); int processUpdate(DNSPacket& p); int forwardPacket(const string &msgPrefix, const DNSPacket& p, const DomainInfo& di); uint performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool isPresigned, bool* narrow, bool* haveNSEC3, NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial); @@ -106,8 +106,6 @@ private: bool addDSforNS(DNSPacket& p, std::unique_ptr& r, const DNSName& dsname); void completeANYRecords(DNSPacket& p, std::unique_ptr& r, const DNSName &target); - void tkeyHandler(const DNSPacket& p, std::unique_ptr& r); //& r) { -#ifdef ENABLE_GSS_TSIG - if (g_doGssTSIG) { - auto [i,a,s] = GssContext::getCounts(); - g_log << Logger::Debug << "GSS #init_creds: " << i << " #accept_creds: " << a << " #secctxs: " << s << endl; - } -#endif - - TKEYRecordContent tkey_in; - std::shared_ptr tkey_out(new TKEYRecordContent()); - DNSName name; -#ifdef ENABLE_GSS_TSIG - bool sign = false; -#endif - - if (!p.getTKEYRecord(&tkey_in, &name)) { - g_log<setRcode(RCode::FormErr); - return; - } - - auto inception = time(nullptr); - // retain original name for response - tkey_out->d_error = 0; - tkey_out->d_mode = tkey_in.d_mode; - tkey_out->d_algo = tkey_in.d_algo; - // coverity[store_truncates_time_t] - tkey_out->d_inception = inception; - tkey_out->d_expiration = tkey_out->d_inception+15; - - if (tkey_in.d_mode == 3) { // establish context -#ifdef ENABLE_GSS_TSIG - if (g_doGssTSIG) { - if (tkey_in.d_algo == DNSName("gss-tsig.")) { - std::vector meta; - DNSName tmpName(name); - do { - if (B.getDomainMetadata(tmpName, "GSS-ACCEPTOR-PRINCIPAL", meta) && meta.size()>0) { - break; - } - } while(tmpName.chopOff()); - - if (meta.size() == 0) { - tkey_out->d_error = 20; - } else { - GssContext ctx(name); - ctx.setLocalPrincipal(meta[0]); - // try to get a context - if (!ctx.accept(tkey_in.d_key, tkey_out->d_key)) { - ctx.destroy(); - tkey_out->d_error = 19; - } - else { - sign = true; - } - } - } else { - tkey_out->d_error = 21; // BADALGO - } - } else -#endif - { - tkey_out->d_error = 21; // BADALGO -#ifdef ENABLE_GSS_TSIG - g_log<setRcode(RCode::Refused); - else - r->setRcode(RCode::NotAuth); - return; - } - GssContext ctx(name); - 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) - r->setRcode(RCode::Refused); - else - r->setRcode(RCode::NotAuth); - return; - } - tkey_out->d_error = 19; // BADMODE - } - - tkey_out->d_keysize = tkey_out->d_key.size(); - tkey_out->d_othersize = tkey_out->d_other.size(); - - DNSZoneRecord zrr; - - zrr.dr.d_name = name; - zrr.dr.d_ttl = 0; - zrr.dr.d_type = QType::TKEY; - zrr.dr.d_class = QClass::ANY; - zrr.dr.setContent(std::move(tkey_out)); - zrr.dr.d_place = DNSResourceRecord::ANSWER; - r->addRecord(std::move(zrr)); - -#ifdef ENABLE_GSS_TSIG - if (sign) - { - TSIGRecordContent trc; - trc.d_algoName = DNSName("gss-tsig"); - trc.d_time = 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 name context - r->setTSIGDetails(trc, name, name.toStringNoDot(), "", false); - } -#endif - - r->commitD(); -}