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; }