From da2043256c0c40cd82ccaf7e670648e8dd1c7f3e Mon Sep 17 00:00:00 2001 From: Pieter Lexis Date: Wed, 31 Aug 2016 14:05:20 +0200 Subject: [PATCH] DNSSEC: generalize getDenial() function * Add qname denial check for NSEC * Add qtype denial checks * Hook up to getKeysFor() --- pdns/validate.cc | 168 +++++++++++++++++++---------------------------- pdns/validate.hh | 2 +- 2 files changed, 70 insertions(+), 100 deletions(-) diff --git a/pdns/validate.cc b/pdns/validate.cc index 3bda3ca5a..131522800 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -12,7 +12,7 @@ void dotNode(string type, DNSName name, string tag, string content); string dotName(string type, DNSName name, string tag); string dotEscape(string name); -const char *dStates[]={"nodata", "nxdomain", "empty non-terminal", "insecure (no-DS proof)"}; +const char *dStates[]={"nodata", "nxdomain", "nxqtype", "empty non-terminal", "insecure"}; const char *vStates[]={"Indeterminate", "Bogus", "Insecure", "Secure", "NTA"}; typedef set keyset_t; @@ -25,58 +25,75 @@ vector getByTag(const keyset_t& keys, uint16_t tag) return ret; } - -static string nsec3Hash(const DNSName &qname, const NSEC3RecordContent& nrc) +// FIXME: needs a zone argument, to avoid things like 6840 4.1 +// FIXME: Add ENT support +// FIXME: Make usable for non-DS records and hook up to validateRecords (or another place) +static dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t& qtype) { - NSEC3PARAMRecordContent ns3pr; - ns3pr.d_iterations = nrc.d_iterations; - ns3pr.d_salt = nrc.d_salt; - return toBase32Hex(hashQNameWithSalt(ns3pr, qname)); -} + for(const auto& v : validrrsets) { + LOG("Do have: "<getZoneRepresentation()<(r); + if(!nsec) + continue; + + /* check if the type is denied */ + if(qname == v.first.first && !nsec->d_set.count(qtype)) { + LOG("Denies existence of type "<d_next)) { + LOG("Denies existence of name "< nsec3s; + LOG("Did not deny existence of "<d_set.count(qtype)<<", next: "<d_next<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname); + // cerr<<"Salt length: "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<<*(zoneCutIter+1)<d_set.count(qtype)) { + LOG("Denies existence of type "<d_set.count(QType::NS)) { + LOG("However, no NS record exists at this level!"<first.second != QType::NSEC3) continue; - - for(auto j=i->second.records.begin(); j!=i->second.records.end(); ++j) { - NSEC3RecordContent ns3r = dynamic_cast (**j); - // nsec3.insert(new nsec3() - // cerr<first.first, ns3r)); - } - } - // cerr<<"got "< parts = i->first.getRawLabels(); - - string base=toLower(parts[0]); - string next=toLower(toBase32Hex(i->second.d_nexthash)); - string hashed = nsec3Hash(qname, i->second); - // cerr<second.d_set.count(qtype)<second.d_set.count(qtype) == 0) return INSECURE; // FIXME need to require 'NS in bitmap' here, otherwise no delegation! (but first, make sure this is reliable - does not work that way for direct auth queries) - } else if ((hashed > base && hashed < next) || - (next < base && (hashed < next || hashed > base))) { - bool optout=(1 & i->second.d_flags); - // cerr<<"negative name proof, optout = "<d_nexthash) || // no wrap BEGINNING --- HASH -- END + (nsec3->d_nexthash > h && beginHash > nsec3->d_nexthash) || // wrap HASH --- END --- BEGINNING + (nsec3->d_nexthash < beginHash && beginHash < h) || // wrap other case END --- BEGINNING --- HASH + beginHash == nsec3->d_nexthash)) // "we have only 1 NSEC3 record, LOL!" + { + LOG("Denies existence of name "<getZoneRepresentation()<(r); - if(nsec) { - if(v.first.first == *(zoneCutIter+1) && !nsec->d_set.count(QType::DS)) { - LOG("Denies existence of DS!"<d_set.count(QType::DS)<<", next: "<d_next<getZoneRepresentation()<(r); - string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, *(zoneCutIter+1)); - // cerr<<"Salt length: "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<<*(zoneCutIter+1)<d_nexthash) || - (nsec3->d_nexthash > h && beginHash > nsec3->d_nexthash) || // wrap // HASH --- END --- BEGINNING - (nsec3->d_nexthash < beginHash && beginHash < h) || // wrap other case // END -- BEGINNING -- HASH - beginHash == nsec3->d_nexthash) // "we have only 1 NSEC3 record, LOL!" - { - LOG("Denies existence of DS!"<d_set.count(QType::DS)) { - LOG("Denies existence of DS (not opt-out)"<