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/QXmppAtmTrustMemoryStorage.cpp | 145 ++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/client/QXmppAtmTrustMemoryStorage.cpp (limited to 'src/client/QXmppAtmTrustMemoryStorage.cpp') diff --git a/src/client/QXmppAtmTrustMemoryStorage.cpp b/src/client/QXmppAtmTrustMemoryStorage.cpp new file mode 100644 index 00000000..404c5564 --- /dev/null +++ b/src/client/QXmppAtmTrustMemoryStorage.cpp @@ -0,0 +1,145 @@ +// SPDX-FileCopyrightText: 2022 Melvin Keskin +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "QXmppAtmTrustMemoryStorage.h" + +#include "QXmppFutureUtils_p.h" +#include "QXmppTrustMessageKeyOwner.h" + +using namespace QXmpp::Private; + +/// +/// \class QXmppAtmTrustMemoryStorage +/// +/// \brief The QXmppAtmTrustMemoryStorage class stores trust data for +/// \xep{0450, Automatic Trust Management (ATM)} in the memory. +/// +/// \warning THIS API IS NOT FINALIZED YET! +/// +/// \since QXmpp 1.5 +/// + +struct UnprocessedKey +{ + QByteArray id; + QString ownerJid; + QByteArray senderKeyId; + bool trust; +}; + +class QXmppAtmTrustMemoryStoragePrivate +{ +public: + // encryption protocols mapped to trust message data received from endpoints + // with unauthenticated keys + QMultiHash keys; +}; + +/// +/// Constructs an ATM trust memory storage. +/// +QXmppAtmTrustMemoryStorage::QXmppAtmTrustMemoryStorage() + : d(new QXmppAtmTrustMemoryStoragePrivate) +{ +} + +QXmppAtmTrustMemoryStorage::~QXmppAtmTrustMemoryStorage() = default; + +/// \cond +QFuture QXmppAtmTrustMemoryStorage::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->keys.find(encryption); itr != d->keys.end() && itr.key() == encryption; ++itr) { + auto &key = itr.value(); + if (key.id == keyId && key.ownerJid == keyOwner.jid() && key.senderKeyId == senderKeyId) { + // Update the stored trust if it differs from the new one. + if (key.trust != trust) { + key.trust = trust; + } + + isKeyFound = true; + break; + } + } + + // Create a new entry and store it if there is no such entry yet. + if (!isKeyFound) { + UnprocessedKey key; + key.id = keyId; + key.ownerJid = keyOwner.jid(); + key.senderKeyId = senderKeyId; + key.trust = trust; + d->keys.insert(encryption, key); + } + } + }; + + for (const auto &keyOwner : keyOwners) { + addKeys(keyOwner, true, keyOwner.trustedKeys()); + addKeys(keyOwner, false, keyOwner.distrustedKeys()); + } + + return makeReadyFuture(); +} + +QFuture QXmppAtmTrustMemoryStorage::removeKeysForPostponedTrustDecisions(const QString &encryption, const QList &keyIdsForAuthentication, const QList &keyIdsForDistrusting) +{ + for (auto itr = d->keys.find(encryption); + itr != d->keys.end() && itr.key() == encryption;) { + const auto &key = itr.value(); + if ((key.trust && keyIdsForAuthentication.contains(key.id)) || + (!key.trust && keyIdsForDistrusting.contains(key.id))) { + itr = d->keys.erase(itr); + } else { + ++itr; + } + } + + return makeReadyFuture(); +} + +QFuture QXmppAtmTrustMemoryStorage::removeKeysForPostponedTrustDecisions(const QString &encryption, const QList &senderKeyIds) +{ + for (auto itr = d->keys.find(encryption); + itr != d->keys.end() && itr.key() == encryption;) { + if (senderKeyIds.contains(itr.value().senderKeyId)) { + itr = d->keys.erase(itr); + } else { + ++itr; + } + } + + return makeReadyFuture(); +} + +QFuture QXmppAtmTrustMemoryStorage::removeKeysForPostponedTrustDecisions(const QString &encryption) +{ + d->keys.remove(encryption); + return makeReadyFuture(); +} + +QFuture>> QXmppAtmTrustMemoryStorage::keysForPostponedTrustDecisions(const QString &encryption, const QList &senderKeyIds) +{ + QHash> keys; + + const auto storedKeys = d->keys.values(encryption); + for (const auto &key : storedKeys) { + if (senderKeyIds.contains(key.senderKeyId) || senderKeyIds.isEmpty()) { + keys[key.trust].insert(key.ownerJid, key.id); + } + } + + return makeReadyFuture(std::move(keys)); +} + +QFuture QXmppAtmTrustMemoryStorage::resetAll(const QString &encryption) +{ + QXmppTrustMemoryStorage::resetAll(encryption); + d->keys.remove(encryption); + return makeReadyFuture(); +} +/// \endcond -- cgit v1.2.3