return d_keymetadb->setDomainMetadata(zname, "PUBLISH_CDNSKEY", vector<string>());
}
+/**
+ * Returns all keys that are used to sign the DNSKEY RRSet in a zone
+ *
+ * @param zone DNSName of the zone
+ * @return a keyset_t with all keys that are used to sign the DNSKEY
+ * RRSet (these are the entrypoint(s) to the zone)
+ */
+DNSSECKeeper::keyset_t DNSSECKeeper::getEntryPoints(const DNSName& zone)
+{
+ DNSSECKeeper::keyset_t ret;
+ DNSSECKeeper::keyset_t keys = getKeys(zone);
+
+ set<int> algoHasKSK;
+
+ for(DNSSECKeeper::keyset_t::value_type& keymeta : keys) {
+ if(keymeta.second.active && keymeta.second.keyOrZone) {
+ // KSKs should always be returned
+ ret.push_back(keymeta);
+ algoHasKSK.insert(keymeta.first.d_algorithm);
+ }
+ }
+
+ // Now add ZSK EntryPoints
+ for(auto const &keymeta : keys) {
+ // Skip inactive keys, KSKs and algos that have a KSK
+ if (!keymeta.second.active || keymeta.second.keyOrZone || algoHasKSK.count(keymeta.first.d_algorithm))
+ continue;
+ ret.push_back(keymeta);
+ }
+ return ret;
+}
+
DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, boost::tribool allOrKeyOrZone, bool useCache)
{
unsigned int now = time(0);
}
bool isSecuredZone(const DNSName& zone);
static uint64_t dbdnssecCacheSizes(const std::string& str);
+ keyset_t getEntryPoints(const DNSName& zone);
keyset_t getKeys(const DNSName& zone, boost::tribool allOrKeyOrZone = boost::indeterminate, bool useCache = true);
DNSSECPrivateKey getKeyById(const DNSName& zone, unsigned int id);
bool addKey(const DNSName& zname, bool keyOrZone, int algorithm=5, int bits=0, bool active=true);
}
/**
- * This adds DNSKEY records to the answer packet. Returns true if one was added.
- * The optional doCDNSKEY parameter signifies that we need to add a CDNSKEY (RFC 7344)
- * instead of DNSKEY.
+ * This adds CDNSKEY records to the answer packet. Returns true if one was added.
*
* @param p Pointer to the DNSPacket containing the original question
* @param r Pointer to the DNSPacket where the records should be inserted into
- * @param sd SOAData of the zone for which DNSKEY records sets should be added
- * @param doCDNSKEY When set to true, add CDNSKEYs instead of DNSKEYs
+ * @param sd SOAData of the zone for which CDNSKEY records sets should be added
* @return bool that shows if any records were added
**/
-bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool doCDNSKEY=false)
+bool PacketHandler::addCDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd)
{
string publishCDNSKEY;
d_dk.getFromMeta(p->qdomain, "PUBLISH_CDNSKEY", publishCDNSKEY);
- if (doCDNSKEY && publishCDNSKEY != "1")
+ if (publishCDNSKEY != "1")
return false;
DNSResourceRecord rr;
bool haveOne=false;
DNSSECPrivateKey dpk;
+ DNSSECKeeper::keyset_t entryPoints = d_dk.getEntryPoints(p->qdomain);
+ for(const auto& value: entryPoints) {
+ rr.qtype=QType::CDNSKEY;
+ rr.ttl=sd.default_ttl;
+ rr.qname=p->qdomain;
+ rr.content=value.first.getDNSKEY().getZoneRepresentation();
+ rr.auth=true;
+ r->addRecord(rr);
+ haveOne=true;
+ }
+
+ if(::arg().mustDo("direct-dnskey")) {
+ B.lookup(QType(QType::CDNSKEY), p->qdomain, p, sd.domain_id);
+
+ while(B.get(rr)) {
+ rr.ttl=sd.default_ttl;
+ r->addRecord(rr);
+ haveOne=true;
+ }
+ }
+ return haveOne;
+}
+
+/**
+ * This adds DNSKEY records to the answer packet. Returns true if one was added.
+ *
+ * @param p Pointer to the DNSPacket containing the original question
+ * @param r Pointer to the DNSPacket where the records should be inserted into
+ * @param sd SOAData of the zone for which DNSKEY records sets should be added
+ * @return bool that shows if any records were added
+**/
+bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd)
+{
+ DNSResourceRecord rr;
+ bool haveOne=false;
+ DNSSECPrivateKey dpk;
+
DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain);
for(const auto& value: keyset) {
- if (doCDNSKEY && !value.second.keyOrZone) {
- // Don't send out CDNSKEY records for ZSKs
- continue;
- }
- rr.qtype=doCDNSKEY ? QType::CDNSKEY : QType::DNSKEY;
+ rr.qtype=QType::DNSKEY;
rr.ttl=sd.default_ttl;
rr.qname=p->qdomain;
rr.content=value.first.getDNSKEY().getZoneRepresentation();
}
if(::arg().mustDo("direct-dnskey")) {
- if(doCDNSKEY)
- B.lookup(QType(QType::CDNSKEY), p->qdomain, p, sd.domain_id);
- else
- B.lookup(QType(QType::DNSKEY), p->qdomain, p, sd.domain_id);
+ B.lookup(QType(QType::DNSKEY), p->qdomain, p, sd.domain_id);
while(B.get(rr)) {
rr.ttl=sd.default_ttl;
bool haveOne=false;
DNSSECPrivateKey dpk;
- DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain);
+ DNSSECKeeper::keyset_t keyset = d_dk.getEntryPoints(p->qdomain);
for(auto const &value : keyset) {
- if (!value.second.keyOrZone) {
- // Don't send out CDS records for ZSKs
- continue;
- }
for(auto const &digestAlgo : digestAlgos){
rr.content=makeDSFromDNSKey(p->qdomain, value.first.getDNSKEY(), std::stoi(digestAlgo)).getZoneRepresentation();
r->addRecord(rr);
if(!d_dk.isSecuredZone(sd.qname))
return;
-
+
addNSECX(p, r, target, DNSName(), sd.qname, 5);
if(sd.qname == p->qdomain) {
addDNSKEY(p, r, sd);
- addDNSKEY(p, r, sd, true);
+ addCDNSKEY(p, r, sd);
addCDS(p, r, sd);
addNSEC3PARAM(p, r, sd);
}
}
else if(p->qtype.getCode() == QType::CDNSKEY)
{
- if(addDNSKEY(p,r, sd, true))
+ if(addCDNSKEY(p,r, sd))
goto sendit;
}
else if(p->qtype.getCode() == QType::CDS)
int processNotify(DNSPacket *);
void addRootReferral(DNSPacket *r);
int doChaosRequest(DNSPacket *p, DNSPacket *r, DNSName &target);
- bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool doCDNSKEY);
+ bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd);
+ bool addCDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd);
bool addCDS(DNSPacket *p, DNSPacket *r, const SOAData& sd);
bool addNSEC3PARAM(DNSPacket *p, DNSPacket *r, const SOAData& sd);
int doAdditionalProcessingAndDropAA(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool retargeted);
dk.getFromMeta(q->qdomain, "PUBLISH_CDNSKEY", publishCDNSKEY);
dk.getFromMeta(q->qdomain, "PUBLISH_CDS", publishCDS);
vector<DNSResourceRecord> cds, cdnskey;
+ DNSSECKeeper::keyset_t entryPoints = dk.getEntryPoints(q->qdomain);
+ set<uint32_t> entryPointIds;
+ for (auto const& value : entryPoints)
+ entryPointIds.insert(value.second.id);
for(const DNSSECKeeper::keyset_t::value_type& value : keys) {
rr.qtype = QType(QType::DNSKEY);
csp.submit(rr);
// generate CDS and CDNSKEY records
- if(value.second.keyOrZone){
+ if(entryPointIds.count(value.second.id) > 0){
if(publishCDNSKEY == "1") {
rr.qtype=QType(QType::CDNSKEY);
rr.content = value.first.getDNSKEY().getZoneRepresentation();
24514dc104b22206daeb973ff9303545 ../regression-tests/zones/minimal.com
0b20d7a0250576451135483b863750bf ../regression-tests/zones/tsig.com
b1f775045fa2cf0a3b91aa834af06e49 ../regression-tests/zones/stest.com
+a98864b315f16bcf49ce577426063c42 ../regression-tests/zones/cdnskey-cds-test.com
2d30ff6855f531368c72e2195a76eabb ../modules/tinydnsbackend/data.cdb
type master;
file "stest.com";
};
+
+zone "cdnskey-cds-test.com"{
+ type master;
+ file "cdnskey-cds-test.com";
+};
$PDNSUTIL --config-dir=. $configname hsm create-key $zone $kid
else
$PDNSUTIL --config-dir=. $configname secure-zone $zone 2>&1
+ if [ "${zone: 0:20}" = "cdnskey-cds-test.com" ]; then
+ $PDNSUTIL --config-dir=. $configname set-publish-cds $zone 2>&1
+ $PDNSUTIL --config-dir=. $configname set-publish-cdnskey $zone 2>&1
+ fi
fi
fi
}
cleandig secure-delegated.dnssec-parent.com CDS dnssec
cleandig secure-delegated.dnssec-parent.com CDNSKEY dnssec
cleandig secure-delegated.dnssec-parent.com ANY dnssec tcp | grep 'CDS\|CDNSKEY' | grep -v 'NSEC'
+
+# We only want to know if we get these records when the default secure-zone is use
+# This means a single ZSK, we don't care about the conents
+cleandig cdnskey-cds-test.com CDS dnssec | perl -pe 's!86400.*!86400!g'
+cleandig cdnskey-cds-test.com CDNSKEY dnssec | perl -pe 's!86400.*!86400!g'
+cleandig cdnskey-cds-test.com ANY dnssec tcp | grep 'CDS\|CDNSKEY' | grep -v 'NSEC' | perl -pe 's!86400.*!86400!g'
0 secure-delegated.dnssec-parent.com. IN CDS 86400 54319 8 2 a0b9c38cd324182af0ef66830d0a0e85a1d58979c9834e18c871779e040857b7
0 secure-delegated.dnssec-parent.com. IN RRSIG 86400 CDNSKEY 8 3 86400 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
0 secure-delegated.dnssec-parent.com. IN RRSIG 86400 CDS 8 3 86400 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
+0 cdnskey-cds-test.com. IN CDS 86400
+0 cdnskey-cds-test.com. IN CDS 86400
+0 cdnskey-cds-test.com. IN RRSIG 86400
+2 . IN OPT 32768
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='cdnskey-cds-test.com.', qtype=CDS
+0 cdnskey-cds-test.com. IN CDNSKEY 86400
+0 cdnskey-cds-test.com. IN RRSIG 86400
+2 . IN OPT 32768
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='cdnskey-cds-test.com.', qtype=CDNSKEY
+0 cdnskey-cds-test.com. IN CDNSKEY 86400
+0 cdnskey-cds-test.com. IN CDS 86400
+0 cdnskey-cds-test.com. IN CDS 86400
+0 cdnskey-cds-test.com. IN RRSIG 86400
+0 cdnskey-cds-test.com. IN RRSIG 86400
OK
RETVAL: 0
+--- ldns-verify-zone -V2 cdnskey-cds-test.com
+RETVAL: 0
+
+--- named-checkzone cdnskey-cds-test.com
+zone cdnskey-cds-test.com/IN: loaded serial 2005092501 (DNSSEC signed)
+OK
+RETVAL: 0
+
OK
RETVAL: 0
+--- ldns-verify-zone -V2 cdnskey-cds-test.com
+RETVAL: 0
+
+--- named-checkzone cdnskey-cds-test.com
+zone cdnskey-cds-test.com/IN: loaded serial 2005092501 (DNSSEC signed)
+OK
+RETVAL: 0
+
OK
RETVAL: 0
+--- ldns-verify-zone -V2 cdnskey-cds-test.com
+RETVAL: 0
+
+--- named-checkzone cdnskey-cds-test.com
+zone cdnskey-cds-test.com/IN: loaded serial 2005092501 (DNSSEC signed)
+OK
+RETVAL: 0
+
--- /dev/null
+$TTL 3600
+$ORIGIN cdnskey-cds-test.com.
+@ IN SOA ns1.cdnskey-cds-test. ahu.example.com. ( 2005092501
+ 8H ; refresh
+ 2H ; retry
+ 1W ; expire
+ 1D ; default_ttl
+ )
+
+@ IN NS ns1
+@ IN NS ns2
+@ IN A 127.0.0.1
+ns1 IN A 1.1.1.1
+ns2 IN A 2.2.2.2