From: Otto Moerbeek Date: Wed, 17 May 2023 10:22:18 +0000 (+0200) Subject: Delint validate.cc and related files X-Git-Tag: rec-4.9.0-beta1~5^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F12837%2Fhead;p=thirdparty%2Fpdns.git Delint validate.cc and related files --- diff --git a/.clang-tidy.full b/.clang-tidy.full index bf8c8c8eca..f6ba38ee2e 100644 --- a/.clang-tidy.full +++ b/.clang-tidy.full @@ -113,7 +113,7 @@ CheckOptions: - key: readability-function-size.LineThreshold value: '4294967295' - key: bugprone-easily-swappable-parameters.MinimumLength - value: '2' + value: '4' - key: portability-simd-intrinsics.Suggest value: 'false' - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader diff --git a/pdns/recursordist/validate-recursor.cc b/pdns/recursordist/validate-recursor.cc index ba8c2cae21..1a676792a9 100644 --- a/pdns/recursordist/validate-recursor.cc +++ b/pdns/recursordist/validate-recursor.cc @@ -46,26 +46,26 @@ bool updateTrustAnchorsFromFile(const std::string& fname, map& { map newDSAnchors; try { - auto zp = ZoneParserTNG(fname); - zp.disableGenerate(); - DNSResourceRecord rr; - DNSRecord dr; - while (zp.get(rr)) { - dr = DNSRecord(rr); - if (rr.qtype == QType::DS) { - auto dsr = getRR(dr); + auto zoneParser = ZoneParserTNG(fname); + zoneParser.disableGenerate(); + DNSResourceRecord resourceRecord; + DNSRecord dnsrecord; + while (zoneParser.get(resourceRecord)) { + dnsrecord = DNSRecord(resourceRecord); + if (resourceRecord.qtype == QType::DS) { + auto dsr = getRR(dnsrecord); if (dsr == nullptr) { - throw PDNSException("Unable to parse DS record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() + "'"); + throw PDNSException("Unable to parse DS record '" + resourceRecord.qname.toString() + " " + resourceRecord.getZoneRepresentation() + "'"); } - newDSAnchors[rr.qname].insert(*dsr); + newDSAnchors[resourceRecord.qname].insert(*dsr); } - if (rr.qtype == QType::DNSKEY) { - auto dnskeyr = getRR(dr); + if (resourceRecord.qtype == QType::DNSKEY) { + auto dnskeyr = getRR(dnsrecord); if (dnskeyr == nullptr) { - throw PDNSException("Unable to parse DNSKEY record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() + "'"); + throw PDNSException("Unable to parse DNSKEY record '" + resourceRecord.qname.toString() + " " + resourceRecord.getZoneRepresentation() + "'"); } - auto dsr = makeDSFromDNSKey(rr.qname, *dnskeyr, DNSSECKeeper::DIGEST_SHA256); - newDSAnchors[rr.qname].insert(dsr); + auto dsr = makeDSFromDNSKey(resourceRecord.qname, *dnskeyr, DNSSECKeeper::DIGEST_SHA256); + newDSAnchors[resourceRecord.qname].insert(dsr); } } if (dsAnchors == newDSAnchors) { diff --git a/pdns/validate.cc b/pdns/validate.cc index af4f9d69af..8306d9aae5 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -1,3 +1,25 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #include "validate.hh" #include "misc.hh" #include "dnssecinfra.hh" @@ -53,20 +75,20 @@ static vector > getByTag(const skeyset_t& return ret; } -bool isCoveredByNSEC3Hash(const std::string& h, const std::string& beginHash, const std::string& nextHash) +bool isCoveredByNSEC3Hash(const std::string& hash, const std::string& beginHash, const std::string& nextHash) { - return ((beginHash < h && h < nextHash) || // no wrap BEGINNING --- HASH -- END - (nextHash > h && beginHash > nextHash) || // wrap HASH --- END --- BEGINNING - (nextHash < beginHash && beginHash < h) || // wrap other case END --- BEGINNING --- HASH - (beginHash == nextHash && h != beginHash)); // "we have only 1 NSEC3 record, LOL!" + return ((beginHash < hash && hash < nextHash) || // no wrap BEGINNING --- HASH -- END + (nextHash > hash && beginHash > nextHash) || // wrap HASH --- END --- BEGINNING + (nextHash < beginHash && beginHash < hash) || // wrap other case END --- BEGINNING --- HASH + (beginHash == nextHash && hash != beginHash)); // "we have only 1 NSEC3 record, LOL!" } -bool isCoveredByNSEC3Hash(const DNSName& h, const DNSName& beginHash, const DNSName& nextHash) +bool isCoveredByNSEC3Hash(const DNSName& name, const DNSName& beginHash, const DNSName& nextHash) { - return ((beginHash.canonCompare(h) && h.canonCompare(nextHash)) || // no wrap BEGINNING --- HASH -- END - (h.canonCompare(nextHash) && nextHash.canonCompare(beginHash)) || // wrap HASH --- END --- BEGINNING - (nextHash.canonCompare(beginHash) && beginHash.canonCompare(h)) || // wrap other case END --- BEGINNING --- HASH - (beginHash == nextHash && h != beginHash)); // "we have only 1 NSEC3 record, LOL!" + return ((beginHash.canonCompare(name) && name.canonCompare(nextHash)) || // no wrap BEGINNING --- HASH -- END + (name.canonCompare(nextHash) && nextHash.canonCompare(beginHash)) || // wrap HASH --- END --- BEGINNING + (nextHash.canonCompare(beginHash) && beginHash.canonCompare(name)) || // wrap other case END --- BEGINNING --- HASH + (beginHash == nextHash && name != beginHash)); // "we have only 1 NSEC3 record, LOL!" } bool isCoveredByNSEC(const DNSName& name, const DNSName& begin, const DNSName& next) @@ -92,15 +114,15 @@ static std::string getHashFromNSEC3(const DNSName& qname, const NSEC3RecordConte { std::string result; - if (g_maxNSEC3Iterations && nsec3.d_iterations > g_maxNSEC3Iterations) { + if (g_maxNSEC3Iterations != 0 && nsec3.d_iterations > g_maxNSEC3Iterations) { return result; } auto key = std::make_tuple(qname, nsec3.d_salt, nsec3.d_iterations); - auto it = cache.find(key); - if (it != cache.end()) + auto iter = cache.find(key); + if (iter != cache.end()) { - return it->second; + return iter->second; } result = hashQNameWithSalt(nsec3.d_salt, nsec3.d_iterations, qname); @@ -139,17 +161,17 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector& continue; } - const string h = getHashFromNSEC3(zone, *nsec3, cache); - if (h.empty()) { + const string hash = getHashFromNSEC3(zone, *nsec3, cache); + if (hash.empty()) { return false; } const string beginHash = fromBase32Hex(record.d_name.getRawLabels()[0]); - if (beginHash == h) { + if (beginHash == hash) { return !nsec3->isSet(QType::NS); } - if (isCoveredByNSEC3Hash(h, beginHash, nsec3->d_nexthash)) { + if (isCoveredByNSEC3Hash(hash, beginHash, nsec3->d_nexthash)) { return !(nsec3->isOptOut()); } } @@ -165,11 +187,7 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector& */ bool isWildcardExpanded(unsigned int labelCount, const RRSIGRecordContent& sign) { - if (sign.d_labels < labelCount) { - return true; - } - - return false; + return sign.d_labels < labelCount; } static bool isWildcardExpanded(const DNSName& owner, const std::vector >& signatures) @@ -185,11 +203,8 @@ static bool isWildcardExpanded(const DNSName& owner, const std::vector >& signatures) @@ -246,17 +261,17 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con { const DNSName wildcard = g_wildcarddnsname + closestEncloser; VLOG(log, qname << ": Trying to prove that there is no data in wildcard for "<getZoneRepresentation()<(r); + for (const auto& validset : validrrsets) { + VLOG(log, qname << ": Do have: "<getZoneRepresentation()<(record); if (!nsec) { continue; } - DNSName owner = getNSECOwnerName(v.first.first, v.second.signatures); + DNSName owner = getNSECOwnerName(validset.first.first, validset.second.signatures); if (owner != wildcard) { continue; } @@ -293,17 +308,17 @@ static bool provesNoWildCard(const DNSName& qname, const uint16_t qtype, const D { VLOG(log, qname << ": Trying to prove that there is no wildcard for "<getZoneRepresentation()<(r); + for (const auto& validset : validrrsets) { + VLOG(log, qname << ": Do have: "<getZoneRepresentation()<(records); if (!nsec) { continue; } - const DNSName owner = getNSECOwnerName(v.first.first, v.second.signatures); + const DNSName owner = getNSECOwnerName(validset.first.first, validset.second.signatures); VLOG(log, qname << ": Comparing owner: "<isSet(QType::DNAME)) { @@ -342,32 +357,32 @@ static bool provesNSEC3NoWildCard(const DNSName& closestEncloser, uint16_t const auto wildcard = g_wildcarddnsname + closestEncloser; VLOG(log, closestEncloser << ": Trying to prove that there is no wildcard for "<getZoneRepresentation()<(r); + for (const auto& validset : validrrsets) { + VLOG(log, closestEncloser << ": Do have: "<getZoneRepresentation()<(records); if (!nsec3) { continue; } - const DNSName signer = getSigner(v.second.signatures); - if (!v.first.first.isPartOf(signer)) { + const DNSName signer = getSigner(validset.second.signatures); + if (!validset.first.first.isPartOf(signer)) { continue; } - string h = getHashFromNSEC3(wildcard, *nsec3, cache); - if (h.empty()) { + string hash = getHashFromNSEC3(wildcard, *nsec3, cache); + if (hash.empty()) { return false; } - VLOG(log, closestEncloser << ":\tWildcard hash: "< "<d_nexthash)<d_nexthash)) { + if (isCoveredByNSEC3Hash(hash, beginHash, nsec3->d_nexthash)) { VLOG(log, closestEncloser << ":\tWildcard hash is covered"<getZoneRepresentation()<getZoneRepresentation()<(r); + auto nsec = std::dynamic_pointer_cast(record); if (!nsec) { continue; } - const DNSName owner = getNSECOwnerName(v.first.first, v.second.signatures); - const DNSName signer = getSigner(v.second.signatures); - if (!v.first.first.isPartOf(signer) || !owner.isPartOf(signer) ) { + const DNSName owner = getNSECOwnerName(validset.first.first, validset.second.signatures); + const DNSName signer = getSigner(validset.second.signatures); + if (!validset.first.first.isPartOf(signer) || !owner.isPartOf(signer) ) { continue; } @@ -528,7 +543,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16 */ if (qname.isPartOf(owner) && isNSECAncestorDelegation(signer, owner, *nsec)) { /* this is an "ancestor delegation" NSEC RR */ - if (!(qtype == QType::DS && qname == owner)) { + if (qtype != QType::DS || qname != owner) { VLOG(log, qname << ": An ancestor delegation NSEC RR can only deny the existence of a DS"<isSet(qtype)<<", next: "<d_next<isSet(qtype)<<", next: "<d_next<getZoneRepresentation()<(r); + } else if(validset.first.second==QType::NSEC3) { + for (const auto& record : validset.second.records) { + VLOG(log, qname << ":\t"<getZoneRepresentation()<(record); if (!nsec3) { continue; } - if (v.second.signatures.empty()) { + if (validset.second.signatures.empty()) { continue; } - const DNSName& hashedOwner = v.first.first; - const DNSName signer = getSigner(v.second.signatures); + const DNSName& hashedOwner = validset.first.first; + const DNSName signer = getSigner(validset.second.signatures); if (!hashedOwner.isPartOf(signer)) { VLOG(log, qname << ": Owner "<getZoneRepresentation()<(r); + for(const auto& validset : validrrsets) { + if(validset.first.second==QType::NSEC3) { + for(const auto& record : validset.second.records) { + VLOG(log, qname << ":\t"<getZoneRepresentation()<(record); if (!nsec3) { continue; } - const DNSName signer = getSigner(v.second.signatures); - if (!v.first.first.isPartOf(signer)) { - VLOG(log, qname << ": Owner "<getZoneRepresentation()<(r); - if(!nsec3) + for(const auto& validset : validrrsets) { + if(validset.first.second==QType::NSEC3) { + for(const auto& record : validset.second.records) { + VLOG(log, qname << ":\t"<getZoneRepresentation()<(record); + if (!nsec3) { continue; + } - string h = getHashFromNSEC3(nextCloser, *nsec3, cache); - if (h.empty()) { + string hash = getHashFromNSEC3(nextCloser, *nsec3, cache); + if (hash.empty()) { return dState::INSECURE; } - const DNSName signer = getSigner(v.second.signatures); - if (!v.first.first.isPartOf(signer)) { - VLOG(log, qname << ": Owner "< "<d_nexthash)<d_nexthash)) { + VLOG(log, qname << ": Comparing "< "<d_nexthash)<d_nexthash)) { VLOG(log, qname << ": Denies existence of name "<(rec); @@ -1031,25 +1045,25 @@ cspmap_t harvestCSPFromRecs(const vector& recs) bool getTrustAnchor(const map& anchors, const DNSName& zone, dsmap_t &res) { - const auto& it = anchors.find(zone); + const auto& iter = anchors.find(zone); - if (it == anchors.cend()) { + if (iter == anchors.cend()) { return false; } - res = it->second; + res = iter->second; return true; } bool haveNegativeTrustAnchor(const map& negAnchors, const DNSName& zone, std::string& reason) { - const auto& it = negAnchors.find(zone); + const auto& iter = negAnchors.find(zone); - if (it == negAnchors.cend()) { + if (iter == negAnchors.cend()) { return false; } - reason = it->second; + reason = iter->second; return true; } @@ -1061,10 +1075,10 @@ vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& */ for (const auto& dsrc : dsmap) { - auto r = getByTag(tkeys, dsrc.d_tag, dsrc.d_algorithm, log); + auto record = getByTag(tkeys, dsrc.d_tag, dsrc.d_algorithm, log); // cerr<<"looking at DS with tag "< >& } } - return DNSName(); + return {}; } const std::string& vStateToString(vState state) @@ -1220,17 +1232,17 @@ const std::string& vStateToString(vState state) return vStates.at(static_cast(state)); } -std::ostream& operator<<(std::ostream &os, const vState d) +std::ostream& operator<<(std::ostream &ostr, const vState dstate) { - os< dStates = {"no denial", "inconclusive", "nxdomain", "nxqtype", "empty non-terminal", "insecure", "opt-out"}; - os<(d)); - return os; + ostr<(dstate)); + return ostr; } void updateDNSSECValidationState(vState& state, const vState stateUpdate) @@ -1241,10 +1253,7 @@ void updateDNSSECValidationState(vState& state, const vState stateUpdate) else if (stateUpdate == vState::NTA) { state = vState::Insecure; } - else if (vStateIsBogus(stateUpdate)) { - state = stateUpdate; - } - else if (state == vState::Indeterminate) { + else if (vStateIsBogus(stateUpdate) || state == vState::Indeterminate) { state = stateUpdate; } else if (stateUpdate == vState::Insecure) { diff --git a/pdns/validate.hh b/pdns/validate.hh index 1660d98eac..9ca589572d 100644 --- a/pdns/validate.hh +++ b/pdns/validate.hh @@ -43,13 +43,18 @@ inline bool vStateIsBogus(vState state) // NSEC(3) results enum class dState : uint8_t { NODENIAL, INCONCLUSIVE, NXDOMAIN, NXQTYPE, ENT, INSECURE, OPTOUT}; -std::ostream& operator<<(std::ostream &os, const vState d); -std::ostream& operator<<(std::ostream &os, const dState d); +std::ostream& operator<<(std::ostream &, vState); +std::ostream& operator<<(std::ostream &, dState); class DNSRecordOracle { public: - virtual std::vector get(const DNSName& qname, uint16_t qtype)=0; + virtual ~DNSRecordOracle() = default; + DNSRecordOracle(const DNSRecordOracle&) = default; + DNSRecordOracle(DNSRecordOracle&&) = default; + DNSRecordOracle& operator=(const DNSRecordOracle&) = default; + DNSRecordOracle& operator=(DNSRecordOracle&&) = default; + virtual std::vector get(const DNSName& qname, uint16_t qtype) = 0; }; @@ -59,37 +64,37 @@ struct ContentSigPair vector> signatures; // ponder adding a validate method that accepts a key }; -typedef map, ContentSigPair> cspmap_t; -typedef std::set dsmap_t; +using cspmap_t = map, ContentSigPair>; +using dsmap_t = std::set; struct sharedDNSKeyRecordContentCompare { - bool operator() (const shared_ptr& a, const shared_ptr& b) const + bool operator() (const shared_ptr& lhs, const shared_ptr& rhs) const { - return *a < *b; + return *lhs < *rhs; } }; -typedef set, sharedDNSKeyRecordContentCompare > skeyset_t; +using skeyset_t = set, sharedDNSKeyRecordContentCompare>; -vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& records, const vector >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs=true); +vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& toSign, const vector >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs=true); bool isCoveredByNSEC(const DNSName& name, const DNSName& begin, const DNSName& next); -bool isCoveredByNSEC3Hash(const std::string& h, const std::string& beginHash, const std::string& nextHash); -bool isCoveredByNSEC3Hash(const DNSName& h, const DNSName& beginHash, const DNSName& nextHash); +bool isCoveredByNSEC3Hash(const std::string& hash, const std::string& beginHash, const std::string& nextHash); +bool isCoveredByNSEC3Hash(const DNSName& name, const DNSName& beginHash, const DNSName& nextHash); cspmap_t harvestCSPFromRecs(const vector& recs); bool getTrustAnchor(const map& anchors, const DNSName& zone, dsmap_t &res); bool haveNegativeTrustAnchor(const map& negAnchors, const DNSName& zone, std::string& reason); vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, const sortedRecords_t& toSign, const vector >& sigs, skeyset_t& validkeys, const OptLog&); -dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t qtype, bool referralToUnsigned, bool wantsNoDataProof, const OptLog& log = std::nullopt, bool needsWildcardProof=true, unsigned int wildcardLabelsCount=0); -bool isSupportedDS(const DSRecordContent& ds, const OptLog&); +dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, uint16_t qtype, bool referralToUnsigned, bool wantsNoDataProof, const OptLog& log = std::nullopt, bool needWildcardProof=true, unsigned int wildcardLabelsCount=0); +bool isSupportedDS(const DSRecordContent& dsRecordContent, const OptLog&); DNSName getSigner(const std::vector >& signatures); bool denialProvesNoDelegation(const DNSName& zone, const std::vector& dsrecords); -bool isRRSIGNotExpired(const time_t now, const RRSIGRecordContent& sig); -bool isRRSIGIncepted(const time_t now, const RRSIGRecordContent& sig); +bool isRRSIGNotExpired(time_t now, const RRSIGRecordContent& sig); +bool isRRSIGIncepted(time_t now, const RRSIGRecordContent& sig); bool isWildcardExpanded(unsigned int labelCount, const RRSIGRecordContent& sign); bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const RRSIGRecordContent& sign); -void updateDNSSECValidationState(vState& state, const vState stateUpdate); +void updateDNSSECValidationState(vState& state, vState stateUpdate); dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner, const NSECRecordContent& nsec, const std::vector>& signatures, const OptLog&);