From: Peter van Dijk Date: Wed, 28 Nov 2012 12:42:34 +0000 (+0000) Subject: import patches from Kees Monshouwer to improve direct RRSIG query behaviour. Includes... X-Git-Tag: auth-3.2-rc2~74 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=14b8677552842725c4d6329e625230f42c469eba;p=pdns import patches from Kees Monshouwer to improve direct RRSIG query behaviour. Includes two tests. git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2927 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/dnssecinfra.hh b/pdns/dnssecinfra.hh index 25d1568b2..6ad04378a 100644 --- a/pdns/dnssecinfra.hh +++ b/pdns/dnssecinfra.hh @@ -118,7 +118,7 @@ struct DNSSECPrivateKey; void fillOutRRSIG(DNSSECPrivateKey& dpk, const std::string& signQName, RRSIGRecordContent& rrc, vector >& toSign); uint32_t getCurrentInception(unsigned int safety=0); -void addSignature(DNSSECKeeper& dk, DNSBackend& db, const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, +void addSignature(DNSSECKeeper& dk, DNSBackend& db, const std::string& signer, const std::string signQName, const std::string& wildcardname, uint16_t signQType, uint32_t signTTL, DNSPacketWriter::Place signPlace, vector >& toSign, vector& outsigned, uint32_t origTTL); int getRRSIGsForRRSET(DNSSECKeeper& dk, const std::string& signer, const std::string signQName, uint16_t signQType, uint32_t signTTL, vector >& toSign, vector &rrc, bool ksk); diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index e86bbb21f..90301f094 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -824,13 +824,15 @@ DNSPacket *PacketHandler::question(DNSPacket *p) void PacketHandler::synthesiseRRSIGs(DNSPacket* p, DNSPacket* r) { - DLOG(L<<"Need to fake up the RRSIGs if someone asked for them explicitly"< > > records_t; + typedef map ttls_t; records_t records; + ttls_t ttls; NSECRecordContent nrc; + NSEC3RecordContent n3rc; nrc.d_set.insert(QType::RRSIG); - nrc.d_set.insert(QType::NSEC); DNSResourceRecord rr; @@ -838,13 +840,18 @@ void PacketHandler::synthesiseRRSIGs(DNSPacket* p, DNSPacket* r) sd.db=(DNSBackend *)-1; // force uncached answer getAuth(p, &sd, p->qdomain, 0); - rr.ttl=sd.default_ttl; + bool narrow; + NSEC3PARAMRecordContent ns3pr; + bool doNSEC3= d_dk.getNSEC3PARAM(sd.qname, &ns3pr, &narrow); + B.lookup(QType(QType::ANY), p->qdomain, p); + bool haveone=false; while(B.get(rr)) { - if(!rr.auth) + haveone=true; + if(!((rr.auth && rr.qtype.getCode()) || (!(doNSEC3 && ns3pr.d_flags) && rr.qtype.getCode() == QType::NS))) continue; - + // make sure all fields are present in the SOA content if(rr.qtype.getCode() == QType::SOA) { rr.content = serializeSOAData(sd); @@ -855,6 +862,11 @@ void PacketHandler::synthesiseRRSIGs(DNSPacket* p, DNSPacket* r) rr.content = lexical_cast(rr.priority) + " " + rr.content; } + // fix direct DNSKEY ttl + if(::arg().mustDo("direct-dnskey") && rr.qtype.getCode() == QType::DNSKEY) { + rr.ttl = sd.default_ttl; + } + if(!rr.content.empty() && rr.qtype.getCode()==QType::TXT && rr.content[0]!='"') { rr.content="\""+rr.content+"\""; } @@ -863,46 +875,86 @@ void PacketHandler::synthesiseRRSIGs(DNSPacket* p, DNSPacket* r) shared_ptr drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); records[rr.qtype.getCode()].push_back(drc); + ttls[rr.qtype.getCode()]=rr.ttl; nrc.d_set.insert(rr.qtype.getCode()); } - bool narrow; - NSEC3PARAMRecordContent ns3pr; - bool doNSEC3= d_dk.getNSEC3PARAM(sd.qname, &ns3pr, &narrow); + + if(records.empty()) { + if (haveone) + makeNOError(p, r, p->qdomain, "", sd, 0); + return; + } + + if(pdns_iequals(p->qdomain, sd.qname)) { // Add DNSKEYs at apex + DNSSECPrivateKey dpk; + + DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain); + BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, keyset) { + + records[QType::DNSKEY].push_back(shared_ptr(DNSRecordContent::mastermake(QType::DNSKEY, 1, value.first.getDNSKEY().getZoneRepresentation()))); + ttls[QType::DNSKEY]=sd.default_ttl; + nrc.d_set.insert(QType::DNSKEY); + } + } + + string before,after; + string unhashed(p->qdomain); + if(doNSEC3) { - DLOG(L<<"We don't yet add NSEC3 to explicit RRSIG queries correctly yet! (narrow="<qdomain, sd.qname)) { + ns3pr.d_flags = 0; // the NSEC3PARAM 'flag' is defined to always be zero in RFC5155. + + records[QType::NSEC3PARAM].push_back(shared_ptr(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, ns3pr.getZoneRepresentation()))); + ttls[QType::NSEC3PARAM]=sd.default_ttl; + n3rc.d_set.insert(QType::NSEC3PARAM); + } + + records[QType::NSEC3].push_back(shared_ptr(DNSRecordContent::mastermake(QType::NSEC3, 1, n3rc.getZoneRepresentation()))); + ttls[QType::NSEC3]=sd.default_ttl; + + // ok, the NSEC3 and NSEC3PARAM are in.. } else { // now get the NSEC too (since we must sign it!) - string before,after; sd.db->getBeforeAndAfterNames(sd.domain_id, sd.qname, p->qdomain, before, after); - + + nrc.d_set.insert(QType::NSEC); nrc.d_next=after; - - rr.qname=p->qdomain; - // rr.ttl is already set.. we hope - rr.qtype=QType::NSEC; - rr.content=nrc.getZoneRepresentation(); - records[QType::NSEC].push_back(shared_ptr(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content))); - + + records[QType::NSEC].push_back(shared_ptr(DNSRecordContent::mastermake(QType::NSEC, 1, nrc.getZoneRepresentation()))); + ttls[QType::NSEC]=sd.default_ttl; + // ok, the NSEC is in.. } DLOG(L<<"Have "<qdomain; - // again, rr.ttl is already set rr.auth = 0; // please don't sign this! rr.d_place = DNSResourceRecord::ANSWER; rr.qtype = QType::RRSIG; + vector rrsigs; + BOOST_FOREACH(records_t::value_type& iter, records) { - vector rrcs; - - getRRSIGsForRRSET(d_dk, sd.qname, p->qdomain, iter.first, 3600, iter.second, rrcs, iter.first == QType::DNSKEY); - BOOST_FOREACH(RRSIGRecordContent& rrc, rrcs) { - rr.content=rrc.getZoneRepresentation(); - r->addRecord(rr); - } + rr.qname=(doNSEC3 && iter.first == QType::NSEC3) ? unhashed : p->qdomain; + rr.ttl=ttls[iter.first]; + + addSignature(d_dk, B, sd.qname, rr.qname, rr.qname, iter.first, rr.ttl, DNSPacketWriter::ANSWER, iter.second, rrsigs, rr.ttl); } + + BOOST_FOREACH(DNSResourceRecord& rr, rrsigs) + r->addRecord(rr); } void PacketHandler::makeNXDomain(DNSPacket* p, DNSPacket* r, const std::string& target, const std::string& wildcard, SOAData& sd) diff --git a/regression-tests/direct-dnskey/command b/regression-tests/direct-dnskey/command new file mode 100755 index 000000000..6329f548a --- /dev/null +++ b/regression-tests/direct-dnskey/command @@ -0,0 +1,2 @@ +#!/bin/sh +cleandig example.com DNSKEY dnssec diff --git a/regression-tests/direct-dnskey/description b/regression-tests/direct-dnskey/description new file mode 100644 index 000000000..ad97597de --- /dev/null +++ b/regression-tests/direct-dnskey/description @@ -0,0 +1 @@ +Query DNSKEY directly. diff --git a/regression-tests/direct-dnskey/expected_result b/regression-tests/direct-dnskey/expected_result new file mode 100644 index 000000000..43c411dfd --- /dev/null +++ b/regression-tests/direct-dnskey/expected_result @@ -0,0 +1,4 @@ +1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2000081501 28800 7200 604800 86400 +2 . IN OPT 32768 +Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0 +Reply to question for qname='example.com.', qtype=DNSKEY diff --git a/regression-tests/direct-dnskey/expected_result.dnssec b/regression-tests/direct-dnskey/expected_result.dnssec new file mode 100644 index 000000000..07a787c58 --- /dev/null +++ b/regression-tests/direct-dnskey/expected_result.dnssec @@ -0,0 +1,7 @@ +0 example.com. IN DNSKEY 86400 256 3 8 ... +0 example.com. IN DNSKEY 86400 256 3 8 ... +0 example.com. IN DNSKEY 86400 257 3 8 ... +0 example.com. IN RRSIG 86400 DNSKEY 8 2 86400 [expiry] [inception] [keytag] example.com. ... +2 . IN OPT 32768 +Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0 +Reply to question for qname='example.com.', qtype=DNSKEY diff --git a/regression-tests/direct-rrsig/command b/regression-tests/direct-rrsig/command new file mode 100755 index 000000000..b21880c2f --- /dev/null +++ b/regression-tests/direct-rrsig/command @@ -0,0 +1,2 @@ +#!/bin/sh +cleandig example.com RRSIG diff --git a/regression-tests/direct-rrsig/description b/regression-tests/direct-rrsig/description new file mode 100644 index 000000000..2626926a2 --- /dev/null +++ b/regression-tests/direct-rrsig/description @@ -0,0 +1 @@ +Query apex RRSIGs directly. diff --git a/regression-tests/direct-rrsig/expected_result b/regression-tests/direct-rrsig/expected_result new file mode 100644 index 000000000..8632b850c --- /dev/null +++ b/regression-tests/direct-rrsig/expected_result @@ -0,0 +1,3 @@ +1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2000081501 28800 7200 604800 86400 +Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0 +Reply to question for qname='example.com.', qtype=RRSIG diff --git a/regression-tests/direct-rrsig/expected_result.dnssec b/regression-tests/direct-rrsig/expected_result.dnssec new file mode 100644 index 000000000..0e19bc516 --- /dev/null +++ b/regression-tests/direct-rrsig/expected_result.dnssec @@ -0,0 +1,4 @@ +0 example.com. IN RRSIG 100000 SOA 8 2 100000 [expiry] [inception] [keytag] example.com. ... +0 example.com. IN RRSIG 120 NS 8 2 120 [expiry] [inception] [keytag] example.com. ... +Rcode: 0, RD: 0, QR: 1, TC: 1, AA: 1, opcode: 0 +Reply to question for qname='example.com.', qtype=RRSIG diff --git a/regression-tests/direct-rrsig/skip-q b/regression-tests/direct-rrsig/skip-q new file mode 100644 index 000000000..e69de29bb