From deff288b6358619dd16c660aded02716a929b4be Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Thu, 2 Jan 2025 10:17:16 +0100 Subject: [PATCH] Ignore unreachable TSIG keys in getTSIGKeys. Pre-v5 database schema would (incorrectly) allow for multiple TSIG keys to be created with the same name and algorithm. Once the database gets converted to v5 schema, those redundant keys can no longer be used, yet would appear in pdnsutil list-tsig-key output. Change the list logic to only report reachable keys. Fixes 14779 --- modules/lmdbbackend/lmdbbackend.cc | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index 8b6860ee5a08..988639b147b6 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -2668,8 +2668,34 @@ bool LMDBBackend::getTSIGKeys(std::vector& keys) auto txn = d_ttsig->getROTransaction(); keys.clear(); - for (auto iter = txn.begin(); iter != txn.end(); ++iter) { - keys.push_back(*iter); + // In a perfect world, we would simply iterate over txn and add every + // item to the returned vector: + // for (auto iter = txn.begin(); iter != txn.end(); ++iter) { + // keys.push_back(*iter); + // } + // But databases converted from older (< 5) schemas _may_ have multiple + // entries for the same TSIG key name and algorithm, something which is not + // allowed in the v5 database schema. These extra entries will not be found + // by get_multi<> during regular operations, and would only appear in the + // results of this method. + // In order to prevent this, we first only gather the list of key names, and + // in a second step, query for them using a similar logic as getTSIGKey(). + // Unfortunately, there does not seem to be a way to know if the database had + // been created using the v5 schema (not converted), in which case we could + // use the above, simpler logic. + std::unordered_set keynames; + for (const auto& iter : txn) { + keynames.insert(iter.name); + } + for (const auto& iter : keynames) { + LmdbIdVec ids; + txn.get_multi<0>(iter, ids); + for (auto key_id : ids) { + TSIGKey key; + if (txn.get(key_id, key)) { + keys.push_back(key); + } + } } return true; }