r->addRecord(std::move(rr));
}
-void PacketHandler::emitNSEC3(std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent& ns3prc, const DNSName& name, const string& namehash, const string& nexthash, int mode)
+void PacketHandler::emitNSEC3(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent& ns3prc, const DNSName& name, const string& namehash, const string& nexthash, int mode)
{
NSEC3RecordContent n3rc;
n3rc.d_algorithm = ns3prc.d_algorithm;
}
}
}
+ } else if(mode == 6) {
+ if (p.qtype.getCode() != QType::CDS) {
+ n3rc.set(QType::CDS);
+ }
+ if (p.qtype.getCode() != QType::CDNSKEY) {
+ n3rc.set(QType::CDNSKEY);
+ }
}
#ifdef HAVE_LUA_RECORDS
mode 3 = Wildcard Answer Responses
mode 4 = Name Error Responses
mode 5 = Direct NSEC request
+ mode 6 = Authenticated DNSSEC bootstrapping (RFC 9615)
*/
void PacketHandler::addNSECX(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, int mode)
{
if (!after.empty()) {
DLOG(g_log<<"Done calling for matching, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
- emitNSEC3(r, ns3rc, unhashed, before, after, mode);
+ emitNSEC3(p, r, ns3rc, unhashed, before, after, mode);
}
}
getNSEC3Hashes(narrow, hashed, true, unhashed, before, after);
DLOG(g_log<<"Done calling for covering, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
- emitNSEC3( r, ns3rc, unhashed, before, after, mode);
+ emitNSEC3(p, r, ns3rc, unhashed, before, after, mode);
}
// wildcard denial
getNSEC3Hashes(narrow, hashed, (mode != 2), unhashed, before, after);
DLOG(g_log<<"Done calling for '*', hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
- emitNSEC3( r, ns3rc, unhashed, before, after, mode);
+ emitNSEC3(p, r, ns3rc, unhashed, before, after, mode);
}
}
}
}
+bool PacketHandler::tryAuthSignal(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target) {
+ DLOG(g_log<<Logger::Warning<<"Let's try authenticated DNSSEC bootstrapping (RFC 9615) ..."<<endl);
+
+ // Check for prefix mismatch
+ if(target.getRawLabel(0) != "_dsboot") {
+ makeNOError(p, r, target, DNSName(), 0); // could be ENT
+ return true;
+ }
+
+ // Check for qtype match
+ if(!(p.qtype.getCode() == QType::CDS || p.qtype.getCode() == QType::CDNSKEY)) {
+ // We don't know at this point whether CDS/CDNSKEY exist, so let's add both to DoE type map
+ makeNOError(p, r, target, DNSName(), 6);
+ return true;
+ }
+
+ // Extract target zone name and fetch zone
+ SOAData zone_sd;
+ ZoneName zone = ZoneName(target.makeRelative(d_sd.zonename));
+ zone.chopOff();
+ // Zone must exist, but need not be secured (could be using front-sign setup)
+ if(!B.getAuth(zone, p.qtype, &zone_sd, p.getRealRemote()) || zone_sd.zonename != zone) {
+ return false; // Bootstrap target zone unknown, NXDOMAIN at _dsboot is OK
+ }
+
+ // Insert synthetic response
+ bool haveOne = false;
+ bool autoPublish = !d_dk.isPresigned(zone);
+ if(p.qtype.getCode() == QType::CDS) {
+ d_dk.getPublishCDS(zone, val);
+ autoPublish &= !val.empty();
+ if(autoPublish)
+ haveOne = addCDS(p, r, zone_sd);
+ } else if(p.qtype.getCode() == QType::CDNSKEY) {
+ d_dk.getPublishCDNSKEY(zone, val);
+ autoPublish &= !val.empty();
+ if(autoPublish)
+ haveOne = addCDNSKEY(p, r, zone_sd);
+ }
+ if(!autoPublish) {
+ DNSZoneRecord rr;
+ B.lookup(p.qtype.getCode(), DNSName(zone), zone_sd.domain_id, &p);
+ while(B.get(rr)) {
+ rr.dr.d_name = p.qdomain;
+ r->addRecord(std::move(rr));
+ haveOne=true;
+ }
+ }
+ if(!haveOne)
+ makeNOError(p, r, target, DNSName(), 6); // other type might exist
+ return true;
+}
+
bool PacketHandler::tryDNAME(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target)
{
if(!d_doDNAME)
state.r->setRcode(RCode::YXDomain);
return true;
}
+ if(tryAuthSignal(pkt, state.r, state.target)) {
+ return true;
+ }
if (!(((pkt.qtype.getCode() == QType::CNAME) || (pkt.qtype.getCode() == QType::ANY)) && retargeted)) {
makeNXDomain(pkt, state.r, state.target, wildcard);
bool getNSEC3Hashes(bool narrow, const std::string& hashed, bool decrement, DNSName& unhashed, std::string& before, std::string& after, int mode=0);
void addNSEC3(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName &target, const DNSName &wildcard, const NSEC3PARAMRecordContent& nsec3param, bool narrow, int mode);
void emitNSEC(std::unique_ptr<DNSPacket>& r, const DNSName& name, const DNSName& next, int mode);
- void emitNSEC3(std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent &ns3rc, const DNSName& unhashed, const string& begin, const string& end, int mode);
+ void emitNSEC3(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent &ns3rc, const DNSName& unhashed, const string& begin, const string& end, int mode);
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);
void makeNOError(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, int mode);
vector<DNSZoneRecord> getBestReferralNS(DNSPacket& p, const DNSName &target);
void getBestDNAMESynth(DNSPacket& p, DNSName &target, vector<DNSZoneRecord> &ret);
+ bool tryAuthSignal(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target);
bool tryDNAME(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target);
bool tryReferral(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName &target, bool retargeted);