From: Miod Vallat Date: Wed, 21 Jan 2026 13:56:06 +0000 (+0100) Subject: Implement an optional RRSet TTL check. X-Git-Tag: rec-5.4.0-beta1~17^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5235ce20e211240a137a9c160116a2527ab2fa8e;p=thirdparty%2Fpdns.git Implement an optional RRSet TTL check. Perform such checks in pdnsutil and the HTTP API when performing RRSet modifications. Signed-off-by: Miod Vallat --- diff --git a/pdns/check-zone.cc b/pdns/check-zone.cc index 64d854029e..4add9bf07e 100644 --- a/pdns/check-zone.cc +++ b/pdns/check-zone.cc @@ -78,6 +78,18 @@ void checkRRSet(const vector& oldrrs, vector& cmds) } std::vector> errors; - Check::RRSetFlags flags{0}; + Check::RRSetFlags flags{Check::RRSET_CHECK_TTL}; if (allowUnderscores) { - flags = Check::RRSET_ALLOW_UNDERSCORES; + flags = static_cast(flags | Check::RRSET_ALLOW_UNDERSCORES); } Check::checkRRSet(oldrrs, newrrs, zone, flags, errors); oldrrs.clear(); // no longer needed diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 1ab78613fe..6ed1ecb6b6 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -1685,14 +1685,10 @@ static bool areUnderscoresAllowed(const ZoneName& zonename, DNSBackend& backend) // Wrapper around checkRRSet; returns true if all checks successful, false if // not, in which case the response body and status have been filled up. -static bool checkNewRecords(HttpResponse* resp, vector& records, const ZoneName& zone, bool allowUnderscores) +static bool checkNewRecords(HttpResponse* resp, vector& records, const ZoneName& zone, Check::RRSetFlags flags) { std::vector> errors; - Check::RRSetFlags flags{0}; - if (allowUnderscores) { - flags = Check::RRSET_ALLOW_UNDERSCORES; - } Check::checkRRSet({}, records, zone, flags, errors); if (errors.empty()) { return true; @@ -2067,7 +2063,9 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) } } - if (!checkNewRecords(resp, new_records, zonename, false)) { // no RFC1123-CONFORMANCE metadata on new zones + // Flags = 0, as new zones do not have RFC1123-CONFORMANCE metadata yet, and + // all records use the same default ttl value. + if (!checkNewRecords(resp, new_records, zonename, static_cast(0))) { return; } @@ -2244,7 +2242,11 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) } bool allowUnderscores = areUnderscoresAllowed(zoneData.zoneName, *zoneData.domainInfo.backend); - if (!checkNewRecords(resp, new_records, zoneData.zoneName, allowUnderscores)) { + Check::RRSetFlags flags{Check::RRSET_CHECK_TTL}; + if (allowUnderscores) { + flags = static_cast(flags | Check::RRSET_ALLOW_UNDERSCORES); + } + if (!checkNewRecords(resp, new_records, zoneData.zoneName, flags)) { return; } @@ -2545,7 +2547,12 @@ static applyResult applyReplace(const DomainInfo& domainInfo, const ZoneName& zo soa.edit_done = increaseSOARecord(resourceRecord, soa.edit_api_kind, soa.edit_kind, zonename); } } - if (!checkNewRecords(resp, new_records, zonename, allowUnderscores)) { + // All records use the same TTL, no need to check for discrepancy. + Check::RRSetFlags flags{0}; + if (allowUnderscores) { + flags = Check::RRSET_ALLOW_UNDERSCORES; + } + if (!checkNewRecords(resp, new_records, zonename, flags)) { // Proper error response has been set up, no need to do anything further. return ABORT; } @@ -2578,6 +2585,7 @@ static applyResult applyReplace(const DomainInfo& domainInfo, const ZoneName& zo return SUCCESS; } +// Apply a PRUNE or EXTEND changetype. static applyResult applyPruneOrExtend(const DomainInfo& domainInfo, const ZoneName& zonename, const Json& container, DNSName& qname, QType& qtype, bool allowUnderscores, soaEditSettings& soa, HttpResponse* resp, changeType operationType, std::vector& rrset) { if (!container["records"].is_array()) { @@ -2598,7 +2606,11 @@ static applyResult applyPruneOrExtend(const DomainInfo& domainInfo, const ZoneNa soa.edit_done = increaseSOARecord(new_record, soa.edit_api_kind, soa.edit_kind, zonename); } - if (!checkNewRecords(resp, new_records, zonename, allowUnderscores)) { + Check::RRSetFlags flags{Check::RRSET_CHECK_TTL}; + if (allowUnderscores) { + flags = static_cast(flags | Check::RRSET_ALLOW_UNDERSCORES); + } + if (!checkNewRecords(resp, new_records, zonename, flags)) { // Proper error response has been set up, no need to do anything further. return ABORT; }