From 6491c55011d8c677b776a7ba66c21031f689c2d2 Mon Sep 17 00:00:00 2001 From: Melvin Keskin Date: Sat, 15 Jan 2022 13:55:18 +0100 Subject: Split up ATM parts of trust storage and refactor (#388) QXmppTrustStorage is now the base class for all trust storages used by end-to-end encryption managers. QXmppAtmTrustStorage is used by QXmppAtmManager. QXmppTrustMemoryStorage is now the base class for all trust storages that use the memory for storing data. QXmppAtmTrustMemoryStorage can be used by QXmppAtmManager. Methods needed by the upcoming OMEMO implementation are added. Some existing methods are refactored. --- src/client/QXmppTrustMemoryStorage.cpp | 221 +++++++++++++-------------------- 1 file changed, 85 insertions(+), 136 deletions(-) (limited to 'src/client/QXmppTrustMemoryStorage.cpp') diff --git a/src/client/QXmppTrustMemoryStorage.cpp b/src/client/QXmppTrustMemoryStorage.cpp index f5e99b33..5a1b6e61 100644 --- a/src/client/QXmppTrustMemoryStorage.cpp +++ b/src/client/QXmppTrustMemoryStorage.cpp @@ -5,7 +5,6 @@ #include "QXmppTrustMemoryStorage.h" #include "QXmppFutureUtils_p.h" -#include "QXmppTrustMessageKeyOwner.h" using namespace QXmpp::Private; @@ -20,21 +19,13 @@ using namespace QXmpp::Private; /// \since QXmpp 1.5 /// -struct ProcessedKey +struct Key { QByteArray id; QString ownerJid; QXmppTrustStorage::TrustLevel trustLevel; }; -struct UnprocessedKey -{ - QByteArray id; - QString ownerJid; - QByteArray senderKeyId; - bool trust; -}; - class QXmppTrustMemoryStoragePrivate { public: @@ -45,11 +36,7 @@ public: QMap ownKeys; // encryption protocols mapped to keys with specified trust levels - QMultiHash processedKeys; - - // encryption protocols mapped to trust message data received from endpoints - // with unauthenticated keys - QMultiHash unprocessedKeys; + QMultiHash keys; }; /// @@ -63,16 +50,15 @@ QXmppTrustMemoryStorage::QXmppTrustMemoryStorage() QXmppTrustMemoryStorage::~QXmppTrustMemoryStorage() = default; /// \cond -QFuture QXmppTrustMemoryStorage::setSecurityPolicies(const QString &encryption, const QXmppTrustStorage::SecurityPolicy securityPolicy) +QFuture QXmppTrustMemoryStorage::setSecurityPolicy(const QString &encryption, const QXmppTrustStorage::SecurityPolicy securityPolicy) { - if (encryption.isEmpty()) { - d->securityPolicies.clear(); - } else if (securityPolicy == QXmppTrustStorage::NoSecurityPolicy) { - d->securityPolicies.remove(encryption); - } else { - d->securityPolicies.insert(encryption, securityPolicy); - } + d->securityPolicies.insert(encryption, securityPolicy); + return makeReadyFuture(); +} +QFuture QXmppTrustMemoryStorage::resetSecurityPolicy(const QString &encryption) +{ + d->securityPolicies.remove(encryption); return makeReadyFuture(); } @@ -81,13 +67,13 @@ QFuture QXmppTrustMemoryStorage::securityPoli return makeReadyFuture(std::move(d->securityPolicies.value(encryption))); } -QFuture QXmppTrustMemoryStorage::addOwnKey(const QString &encryption, const QByteArray &keyId) +QFuture QXmppTrustMemoryStorage::setOwnKey(const QString &encryption, const QByteArray &keyId) { d->ownKeys.insert(encryption, keyId); return makeReadyFuture(); } -QFuture QXmppTrustMemoryStorage::removeOwnKey(const QString &encryption) +QFuture QXmppTrustMemoryStorage::resetOwnKey(const QString &encryption) { d->ownKeys.remove(encryption); return makeReadyFuture(); @@ -102,11 +88,11 @@ QFuture QXmppTrustMemoryStorage::ownKey(const QString &encryption) QFuture QXmppTrustMemoryStorage::addKeys(const QString &encryption, const QString &keyOwnerJid, const QList &keyIds, const QXmppTrustStorage::TrustLevel trustLevel) { for (const auto &keyId : keyIds) { - ProcessedKey key; + Key key; key.id = keyId; key.ownerJid = keyOwnerJid; key.trustLevel = trustLevel; - d->processedKeys.insert(encryption, key); + d->keys.insert(encryption, key); } return makeReadyFuture(); @@ -114,30 +100,44 @@ QFuture QXmppTrustMemoryStorage::addKeys(const QString &encryption, const QFuture QXmppTrustMemoryStorage::removeKeys(const QString &encryption, const QList &keyIds) { - if (encryption.isEmpty()) { - d->processedKeys.clear(); - } else if (keyIds.isEmpty()) { - d->processedKeys.remove(encryption); - } else { - for (auto itr = d->processedKeys.find(encryption); - itr != d->processedKeys.end() && itr.key() == encryption;) { - if (keyIds.contains(itr.value().id)) { - itr = d->processedKeys.erase(itr); - } else { - itr++; - } + for (auto itr = d->keys.find(encryption); + itr != d->keys.end() && itr.key() == encryption;) { + if (keyIds.contains(itr.value().id)) { + itr = d->keys.erase(itr); + } else { + ++itr; } } return makeReadyFuture(); } +QFuture QXmppTrustMemoryStorage::removeKeys(const QString &encryption, const QString &keyOwnerJid) +{ + for (auto itr = d->keys.find(encryption); + itr != d->keys.end() && itr.key() == encryption;) { + if (itr.value().ownerJid == keyOwnerJid) { + itr = d->keys.erase(itr); + } else { + ++itr; + } + } + + return makeReadyFuture(); +} + +QFuture QXmppTrustMemoryStorage::removeKeys(const QString &encryption) +{ + d->keys.remove(encryption); + return makeReadyFuture(); +} + QFuture>> QXmppTrustMemoryStorage::keys(const QString &encryption, const TrustLevels trustLevels) { QHash> keys; - const auto processedKeys = d->processedKeys.values(encryption); - for (const auto &key : processedKeys) { + const auto storedKeys = d->keys.values(encryption); + for (const auto &key : storedKeys) { const auto trustLevel = key.trustLevel; if (trustLevels.testFlag(trustLevel) || !trustLevels) { keys[trustLevel].insert(key.ownerJid, key.id); @@ -147,6 +147,34 @@ QFuture>> Q return makeReadyFuture(std::move(keys)); } +QFuture>> QXmppTrustMemoryStorage::keys(const QString &encryption, const QList &keyOwnerJids, TrustLevels trustLevels) +{ + QHash> keys; + + const auto storedKeys = d->keys.values(encryption); + for (const auto &key : storedKeys) { + const auto keyOwnerJid = key.ownerJid; + const auto trustLevel = key.trustLevel; + if (keyOwnerJids.contains(keyOwnerJid) && (trustLevels.testFlag(trustLevel) || !trustLevels)) { + keys[keyOwnerJid].insert(key.id, trustLevel); + } + } + + return makeReadyFuture(std::move(keys)); +} + +QFuture QXmppTrustMemoryStorage::hasKey(const QString &encryption, const QString &keyOwnerJid, TrustLevels trustLevels) +{ + const auto storedKeys = d->keys.values(encryption); + for (const auto &key : storedKeys) { + if (key.ownerJid == keyOwnerJid && trustLevels.testFlag(key.trustLevel)) { + return makeReadyFuture(std::move(true)); + } + } + + return makeReadyFuture(std::move(false)); +} + QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, const QMultiHash &keyIds, const TrustLevel trustLevel) { for (auto itr = keyIds.constBegin(); itr != keyIds.constEnd(); ++itr) { @@ -155,13 +183,13 @@ QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, auto isKeyFound = false; - for (auto itrProcessedKeys = d->processedKeys.find(encryption); - itrProcessedKeys != d->processedKeys.end() && itrProcessedKeys.key() == encryption; - ++itrProcessedKeys) { - auto &key = itrProcessedKeys.value(); + for (auto itrKeys = d->keys.find(encryption); + itrKeys != d->keys.end() && itrKeys.key() == encryption; + ++itrKeys) { + auto &key = itrKeys.value(); if (key.id == keyId && key.ownerJid == keyOwnerJid) { + // Update the stored trust level if it differs from the new one. if (key.trustLevel != trustLevel) { - // Update the stored trust level if it differs from the new one. key.trustLevel = trustLevel; } @@ -170,13 +198,13 @@ QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, } } + // Create a new entry and store it if there is no such entry yet. if (!isKeyFound) { - // Create a new entry and store it if there is no such entry yet. - ProcessedKey key; + Key key; key.id = keyId; key.ownerJid = keyOwnerJid; key.trustLevel = trustLevel; - d->processedKeys.insert(encryption, key); + d->keys.insert(encryption, key); } } @@ -185,7 +213,7 @@ QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, const QList &keyOwnerJids, const QXmppTrustStorage::TrustLevel oldTrustLevel, const QXmppTrustStorage::TrustLevel newTrustLevel) { - for (auto itr = d->processedKeys.find(encryption); itr != d->processedKeys.end() && itr.key() == encryption; ++itr) { + for (auto itr = d->keys.find(encryption); itr != d->keys.end() && itr.key() == encryption; ++itr) { auto &key = itr.value(); if (keyOwnerJids.contains(key.ownerJid) && key.trustLevel == oldTrustLevel) { key.trustLevel = newTrustLevel; @@ -197,101 +225,22 @@ QFuture QXmppTrustMemoryStorage::setTrustLevel(const QString &encryption, QFuture QXmppTrustMemoryStorage::trustLevel(const QString &encryption, const QByteArray &keyId) { - const auto processedKeys = d->processedKeys.values(encryption); - for (const auto &key : processedKeys) { + const auto keys = d->keys.values(encryption); + for (const auto &key : keys) { if (key.id == keyId) { return makeReadyFuture(std::move(QXmppTrustStorage::TrustLevel(key.trustLevel))); } } - return makeReadyFuture(std::move(TrustLevel::AutomaticallyDistrusted)); -} - -QFuture QXmppTrustMemoryStorage::addKeysForPostponedTrustDecisions(const QString &encryption, const QByteArray &senderKeyId, const QList &keyOwners) -{ - const auto addKeys = [&](const QXmppTrustMessageKeyOwner &keyOwner, bool trust, const QList &keyIds) { - for (const auto &keyId : keyIds) { - auto isKeyFound = false; - - for (auto itr = d->unprocessedKeys.find(encryption); itr != d->unprocessedKeys.end() && itr.key() == encryption; ++itr) { - auto &key = itr.value(); - if (key.id == keyId && key.ownerJid == keyOwner.jid() && key.senderKeyId == senderKeyId) { - if (key.trust != trust) { - // Update the stored trust if it differs from the new one. - key.trust = trust; - } - - isKeyFound = true; - break; - } - } - - if (!isKeyFound) { - // Create a new entry and store it if there is no such entry yet. - UnprocessedKey key; - key.id = keyId; - key.ownerJid = keyOwner.jid(); - key.senderKeyId = senderKeyId; - key.trust = trust; - d->unprocessedKeys.insert(encryption, key); - } - } - }; - - for (const auto &keyOwner : keyOwners) { - addKeys(keyOwner, true, keyOwner.trustedKeys()); - addKeys(keyOwner, false, keyOwner.distrustedKeys()); - } - - return makeReadyFuture(); -} - -QFuture QXmppTrustMemoryStorage::removeKeysForPostponedTrustDecisions(const QString &encryption, const QList &keyIdsForAuthentication, const QList &keyIdsForDistrusting) -{ - for (auto itr = d->unprocessedKeys.find(encryption); - itr != d->unprocessedKeys.end() && itr.key() == encryption;) { - const auto &key = itr.value(); - if ((key.trust && keyIdsForAuthentication.contains(key.id)) || - (!key.trust && keyIdsForDistrusting.contains(key.id))) { - itr = d->unprocessedKeys.erase(itr); - } else { - ++itr; - } - } - return makeReadyFuture(); + return makeReadyFuture(std::move(QXmppTrustStorage::Undecided)); } -QFuture QXmppTrustMemoryStorage::removeKeysForPostponedTrustDecisions(const QString &encryption, const QList &senderKeyIds) +QFuture QXmppTrustMemoryStorage::resetAll(const QString &encryption) { - if (encryption.isEmpty()) { - d->unprocessedKeys.clear(); - } else if (senderKeyIds.isEmpty()) { - d->unprocessedKeys.remove(encryption); - } else { - for (auto itr = d->unprocessedKeys.find(encryption); - itr != d->unprocessedKeys.end() && itr.key() == encryption;) { - if (senderKeyIds.contains(itr.value().senderKeyId)) { - itr = d->unprocessedKeys.erase(itr); - } else { - ++itr; - } - } - } + d->securityPolicies.remove(encryption); + d->ownKeys.remove(encryption); + d->keys.remove(encryption); return makeReadyFuture(); } - -QFuture>> QXmppTrustMemoryStorage::keysForPostponedTrustDecisions(const QString &encryption, const QList &senderKeyIds) -{ - QHash> keys; - - const auto unprocessedKeys = d->unprocessedKeys.values(encryption); - for (const auto &key : unprocessedKeys) { - if (senderKeyIds.contains(key.senderKeyId) || senderKeyIds.isEmpty()) { - keys[key.trust].insert(key.ownerJid, key.id); - } - } - - return makeReadyFuture(std::move(keys)); -} /// \endcond -- cgit v1.2.3