diff options
| author | Melvin Keskin <melvo@olomono.de> | 2021-08-28 14:39:02 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2021-09-16 18:43:00 +0200 |
| commit | bb8780ecdbfe7eddb8280e696871e71b744d0bff (patch) | |
| tree | 585989b6e6a58c3f2af42c0681d87e93e2c592e7 /src | |
| parent | b147ea5f4004cbd9aa2e7ae3936734a869bf3a44 (diff) | |
| download | qxmpp-bb8780ecdbfe7eddb8280e696871e71b744d0bff.tar.gz | |
Add QXmppAtmManager
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants.cpp | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants_p.h | 2 | ||||
| -rw-r--r-- | src/base/QXmppMessage.cpp | 39 | ||||
| -rw-r--r-- | src/base/QXmppMessage.h | 3 | ||||
| -rw-r--r-- | src/client/QXmppAtmManager.cpp | 505 | ||||
| -rw-r--r-- | src/client/QXmppAtmManager.h | 68 |
7 files changed, 621 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b12c3ee..86849223 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,6 +85,7 @@ set(INSTALL_HEADER_FILES # Client client/QXmppArchiveManager.h + client/QXmppAtmManager.h client/QXmppAttentionManager.h client/QXmppBookmarkManager.h client/QXmppCarbonManager.h @@ -189,6 +190,7 @@ set(SOURCE_FILES # Client client/QXmppArchiveManager.cpp + client/QXmppAtmManager.cpp client/QXmppAttentionManager.cpp client/QXmppBookmarkManager.cpp client/QXmppCarbonManager.cpp diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp index db896683..c6ae77de 100644 --- a/src/base/QXmppConstants.cpp +++ b/src/base/QXmppConstants.cpp @@ -186,3 +186,5 @@ const char* ns_mix_misc = "urn:xmpp:mix:misc:0"; const char* ns_fallback_indication = "urn:xmpp:fallback:0"; // XEP-0434: Trust Messages (TM) const char* ns_tm = "urn:xmpp:tm:0"; +// XEP-0450: Automatic Trust Management (ATM) +const char* ns_atm = "urn:xmpp:atm:1"; diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h index 1d55ad03..2b9e70d6 100644 --- a/src/base/QXmppConstants_p.h +++ b/src/base/QXmppConstants_p.h @@ -198,5 +198,7 @@ extern const char* ns_mix_misc; extern const char* ns_fallback_indication; // XEP-0434: Trust Messages (TM) extern const char* ns_tm; +// XEP-0450: Automatic Trust Management (ATM) +extern const char* ns_atm; #endif // QXMPPCONSTANTS_H diff --git a/src/base/QXmppMessage.cpp b/src/base/QXmppMessage.cpp index f975ae3c..e97731ae 100644 --- a/src/base/QXmppMessage.cpp +++ b/src/base/QXmppMessage.cpp @@ -108,6 +108,7 @@ public: QString thread; QString parentThread; QXmppMessage::Type type; + QString senderKey; // XEP-0066: Out of Band Data QString outOfBandUrl; @@ -325,6 +326,44 @@ void QXmppMessage::setParentThread(const QString &parent) } /// +/// Returns the ID of this message's sender's public long-term key. +/// +/// The key ID is not part of a transmitted message and thus not de- / +/// serialized. +/// Instead, the key ID is set by an encryption protocol such as +/// \xep{0384, OMEMO Encryption} when it decrypts this message. +/// It can be used by trust management protocols such as +/// \xep{0450, Automatic Trust Management (ATM)}. +/// +/// \return the ID of the sender's key +/// +/// \since QXmpp 1.5 +/// +QString QXmppMessage::senderKey() const +{ + return d->senderKey; +} + +/// +/// Sets the ID of this message's sender's public long-term key. +/// +/// The key ID is not part of a transmitted message and thus not de- / +/// serialized. +/// Instead, the key ID is set by an encryption protocol such as +/// \xep{0384, OMEMO Encryption} when it decrypts this message. +/// It can be used by trust management protocols such as +/// \xep{0450, Automatic Trust Management (ATM)}. +/// +/// \param keyId ID of the sender's key +/// +/// \since QXmpp 1.5 +/// +void QXmppMessage::setSenderKey(const QString &keyId) +{ + d->senderKey = keyId; +} + +/// /// Returns a possibly attached URL from \xep{0066}: Out of Band Data /// /// \since QXmpp 1.0 diff --git a/src/base/QXmppMessage.h b/src/base/QXmppMessage.h index 6688d3b6..b2cb972d 100644 --- a/src/base/QXmppMessage.h +++ b/src/base/QXmppMessage.h @@ -136,6 +136,9 @@ public: QXmppMessage::Type type() const; void setType(QXmppMessage::Type); + QString senderKey() const; + void setSenderKey(const QString &keyId); + // XEP-0066: Out of Band Data QString outOfBandUrl() const; void setOutOfBandUrl(const QString &); diff --git a/src/client/QXmppAtmManager.cpp b/src/client/QXmppAtmManager.cpp new file mode 100644 index 00000000..df3b1350 --- /dev/null +++ b/src/client/QXmppAtmManager.cpp @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2008-2021 The QXmpp developers + * + * Author: + * Melvin Keskin <melvo@olomono.de> + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include "QXmppAtmManager.h" + +#include "QXmppCarbonManager.h" +#include "QXmppClient.h" +#include "QXmppConstants_p.h" +#include "QXmppFutureUtils_p.h" +#include "QXmppTrustMessageElement.h" +#include "QXmppUtils.h" + +#include <QCoreApplication> +#include <QDomElement> +#include <QList> + +using namespace QXmpp::Private; + +/// +/// \class QXmppAtmManager +/// +/// \brief The QXmppAtmManager class represents a manager for +/// \xep{0450, Automatic Trust Management (ATM)}. +/// +/// For interacting with the storage, a corresponding implementation of the +/// storage interface must be added. +/// That implementation has to be adapted to your storage such as a database. +/// In case you only need memory and no peristent storage, you can use the +/// existing implementation: +/// +///\code +/// QXmppTrustStorage *trustStorage = new QXmppTrustMemoryStorage; +/// \endcode +/// +/// Afterwards, this manager must be added with the storage: +/// \code +/// QXmppAtmManager *manager = new QXmppAtmManager(trustStorage); +/// client->addExtension(manager); +/// \endcode +/// +/// It is strongly recommended to enable \xep{0280, Message Carbons} with +/// \code +/// QXmppCarbonManager *carbonManager = new QXmppCarbonManager; +/// carbonManager->setCarbonsEnabled(true); +/// client->addExtension(carbonManager); +/// \endcode +/// and \xep{0313, Message Archive Management} with +/// \code +/// QXmppMamManager *mamManager = new QXmppMamManager; +/// client->addExtension(mamManager); +/// \endcode +/// for delivering trust messages to all online and offline endpoints. +/// +/// In addition, archiving via MAM must be enabled on the server. +/// +/// \warning THIS API IS NOT FINALIZED YET! +/// +/// \ingroup Managers +/// +/// \since QXmpp 1.5 +/// + +/// +/// Constructs an ATM manager. +/// +/// \param trustStorage trust storage implementation +/// +QXmppAtmManager::QXmppAtmManager(QXmppTrustStorage *trustStorage) +{ + m_trustStorage = trustStorage; +} + +/// +/// Authenticates or distrusts keys manually (e.g., by the Trust Message URI of +/// a scanned QR code or after entering key IDs by hand) and sends corresponding +/// trust messages. +/// +/// \param encryption encryption protocol namespace +/// \param keyOwnerJid JID of the key owner +/// \param keyIdsForAuthentication IDs of the keys being authenticated +/// \param keyIdsForDistrusting IDs of the keys being distrusted +/// +QFuture<void> QXmppAtmManager::makeTrustDecisions(const QString &encryption, const QString &keyOwnerJid, const QList<QString> &keyIdsForAuthentication, const QList<QString> &keyIdsForDistrusting) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + auto future = m_trustStorage->keys(encryption, QXmppTrustStorage::Authenticated | QXmppTrustStorage::ManuallyDistrusted); + await(future, this, [=](const QHash<QXmppTrustStorage::TrustLevel, QMultiHash<QString, QString>> &&keys) { + const auto authenticatedKeys = keys.value(QXmppTrustStorage::Authenticated); + const auto manuallyDistrustedKeys = keys.value(QXmppTrustStorage::ManuallyDistrusted); + const auto ownJid = client()->configuration().jidBare(); + const auto ownAuthenticatedKeys = authenticatedKeys.values(ownJid); + + // Create a key owner for the keys being authenticated or + // distrusted. + QXmppTrustMessageKeyOwner keyOwner; + keyOwner.setJid(keyOwnerJid); + + QList<QString> modifiedAuthenticatedKeys; + QList<QString> modifiedManuallyDistrustedKeys; + + for (const auto &keyId : keyIdsForAuthentication) { + if (!authenticatedKeys.contains(keyOwnerJid, keyId)) { + modifiedAuthenticatedKeys.append(keyId); + } + } + + for (const auto &keyId : keyIdsForDistrusting) { + if (!manuallyDistrustedKeys.contains(keyOwnerJid, keyId)) { + modifiedManuallyDistrustedKeys.append(keyId); + } + } + + if (modifiedAuthenticatedKeys.isEmpty() && modifiedManuallyDistrustedKeys.isEmpty()) { + // Skip further processing if there are no changes. + interface->reportFinished(); + } else { + keyOwner.setTrustedKeys(modifiedAuthenticatedKeys); + keyOwner.setDistrustedKeys(modifiedManuallyDistrustedKeys); + + QMultiHash<QString, QString> keysBeingAuthenticated; + QMultiHash<QString, QString> keysBeingDistrusted; + + for (const auto &key : std::as_const(modifiedAuthenticatedKeys)) { + keysBeingAuthenticated.insert(keyOwnerJid, key); + } + + for (const auto &key : std::as_const(modifiedManuallyDistrustedKeys)) { + keysBeingDistrusted.insert(keyOwnerJid, key); + } + + // Create a key owner for authenticated and distrusted keys of own + // endpoints. + QXmppTrustMessageKeyOwner ownKeyOwner; + ownKeyOwner.setJid(ownJid); + + if (!ownAuthenticatedKeys.isEmpty()) { + ownKeyOwner.setTrustedKeys(ownAuthenticatedKeys); + } + + const auto ownManuallyDistrustedKeys = manuallyDistrustedKeys.values(ownJid); + if (!ownManuallyDistrustedKeys.isEmpty()) { + ownKeyOwner.setDistrustedKeys(ownManuallyDistrustedKeys); + } + + const auto areOwnKeysProcessed = keyOwnerJid == ownJid; + if (areOwnKeysProcessed) { + auto authenticatedKeysTemp = authenticatedKeys; + authenticatedKeysTemp.remove(ownJid); + const auto contactsAuthenticatedKeys = authenticatedKeysTemp; + + const auto contactsWithAuthenticatedKeys = contactsAuthenticatedKeys.uniqueKeys(); + + // Send trust messages for the keys of the own endpoints being + // authenticated or distrusted to endpoints of contacts with + // authenticated keys. + // Own endpoints with authenticated keys can receive the trust + // messages via Message Carbons. + for (const auto &contactJid : contactsWithAuthenticatedKeys) { + sendTrustMessage(encryption, { keyOwner }, contactJid); + } + + // Send a trust message for the keys of the own endpoints being + // authenticated or distrusted to other own endpoints with + // authenticated keys. + // It is skipped if a trust message is already delivered via + // Message Carbons or there are no other own endpoints with + // authenticated keys. + const auto *carbonManager = client()->findExtension<QXmppCarbonManager>(); + const auto isMessageCarbonsDisabled = !carbonManager || !carbonManager->carbonsEnabled(); + if (isMessageCarbonsDisabled || (contactsAuthenticatedKeys.isEmpty() && !ownAuthenticatedKeys.isEmpty())) { + sendTrustMessage(encryption, { keyOwner }, ownJid); + } + + auto future = makeTrustDecisions(encryption, keysBeingAuthenticated, keysBeingDistrusted); + await(future, this, [=]() { + // Send a trust message for all authenticated or distrusted + // keys to the own endpoints whose keys have been + // authenticated. + // It is skipped if no keys of own endpoints have been + // authenticated. + if (!keyOwner.trustedKeys().isEmpty()) { + auto manuallyDistrustedKeysTemp = manuallyDistrustedKeys; + manuallyDistrustedKeysTemp.remove(ownJid); + const auto contactsManuallyDistrustedKeys = manuallyDistrustedKeysTemp; + + auto contactJids = contactsManuallyDistrustedKeys.uniqueKeys() << contactsWithAuthenticatedKeys; + + // Remove duplicates from contactJids. + std::sort(contactJids.begin(), contactJids.end()); + contactJids.erase(std::unique(contactJids.begin(), contactJids.end()), contactJids.end()); + + QList<QXmppTrustMessageKeyOwner> contactsKeyOwners; + + for (const auto &contactJid : std::as_const(contactJids)) { + QXmppTrustMessageKeyOwner contactKeyOwner; + contactKeyOwner.setJid(contactJid); + contactKeyOwner.setTrustedKeys(contactsAuthenticatedKeys.values(contactJid)); + + if (const auto contactManuallyDistrustedKeys = contactsManuallyDistrustedKeys.values(contactJid); !contactsManuallyDistrustedKeys.isEmpty()) { + contactKeyOwner.setDistrustedKeys(contactManuallyDistrustedKeys); + } + + contactsKeyOwners.append(contactKeyOwner); + } + + auto allKeyOwners = contactsKeyOwners; + + if (!(ownKeyOwner.trustedKeys().isEmpty() && ownKeyOwner.distrustedKeys().isEmpty())) { + allKeyOwners.append(ownKeyOwner); + } + + if (!allKeyOwners.isEmpty()) { + sendTrustMessage(encryption, allKeyOwners, ownJid); + } + } + + interface->reportFinished(); + }); + } else { + // Send a trust message for the keys of the contact's endpoints + // being authenticated or distrusted to own endpoints + // with authenticated keys. + if (!ownAuthenticatedKeys.isEmpty()) { + sendTrustMessage(encryption, { keyOwner }, ownJid); + } + + auto future = makeTrustDecisions(encryption, keysBeingAuthenticated, keysBeingDistrusted); + await(future, this, [=]() { + // Send a trust message for own authenticated or distrusted + // keys to the contact's endpoints whose keys have been + // authenticated. + // It is skipped if no keys of contacts have been + // authenticated or there are no keys for the trust message. + if (!keyOwner.trustedKeys().isEmpty() && !(ownKeyOwner.trustedKeys().isEmpty() && ownKeyOwner.distrustedKeys().isEmpty())) { + sendTrustMessage(encryption, { ownKeyOwner }, keyOwnerJid); + } + + interface->reportFinished(); + }); + } + } + }); + + return interface->future(); +} + +/// \cond +bool QXmppAtmManager::handleStanza(const QDomElement &) +{ + return false; +} + +void QXmppAtmManager::setClient(QXmppClient *client) +{ + QXmppClientExtension::setClient(client); + connect(client, &QXmppClient::messageReceived, this, &QXmppAtmManager::handleMessageReceived); +} + +void QXmppAtmManager::handleMessageReceived(const QXmppMessage &message) +{ + handleMessage(message); +} +/// \endcond + +/// +/// Authenticates or distrusts keys. +/// +/// \param encryption encryption protocol namespace +/// \param keyIdsForAuthentication key owners' bare JIDs mapped to the IDs of +/// their keys being authenticated +/// \param keyIdsForDistrusting key owners' bare JIDs mapped to the IDs of their +/// keys being distrusted +/// +QFuture<void> QXmppAtmManager::makeTrustDecisions(const QString &encryption, const QMultiHash<QString, QString> &keyIdsForAuthentication, const QMultiHash<QString, QString> &keyIdsForDistrusting) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + auto future = authenticate(encryption, keyIdsForAuthentication); + await(future, this, [=]() { + auto future = distrust(encryption, keyIdsForDistrusting); + await(future, this, [=]() { + interface->reportFinished(); + }); + }); + + return interface->future(); +} + +/// +/// Handles incoming messages and uses included trust message elements for +/// making automatic trust decisions. +/// +/// \param message message that can contain a trust message element +/// +QFuture<void> QXmppAtmManager::handleMessage(const QXmppMessage &message) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + if (const auto trustMessageElement = message.trustMessageElement(); trustMessageElement && trustMessageElement->usage() == ns_atm && message.from() != client()->configuration().jid()) { + const auto senderJid = QXmppUtils::jidToBareJid(message.from()); + const auto senderKey = message.senderKey(); + const auto encryption = trustMessageElement->encryption(); + + auto future = m_trustStorage->trustLevel(encryption, senderKey); + await(future, this, [=](const auto &&senderKeyTrustLevel) { + const auto isSenderKeyAuthenticated = senderKeyTrustLevel == QXmppTrustStorage::Authenticated; + + // key owner JIDs mapped to key IDs + QMultiHash<QString, QString> keysBeingAuthenticated; + QMultiHash<QString, QString> keysBeingDistrusted; + + QList<QXmppTrustMessageKeyOwner> keyOwnersForPostponedTrustDecisions; + + const auto ownJid = client()->configuration().jidBare(); + const auto isOwnTrustMessage = senderJid == ownJid; + const auto keyOwners = trustMessageElement->keyOwners(); + + for (const auto &keyOwner : keyOwners) { + const auto keyOwnerJid = keyOwner.jid(); + + // A trust message from an own endpoint is allowed to + // authenticate or distrust the keys of own endpoints and + // endpoints of contacts. + // Whereas a trust message from an endpoint of a contact is + // only allowed to authenticate or distrust the keys of that + // contact's own endpoints. + const auto isSenderQualifiedForTrustDecisions = isOwnTrustMessage || senderJid == keyOwnerJid; + if (isSenderQualifiedForTrustDecisions) { + // Make trust decisions if the key of the sender is + // authenticated. + // Othwerwise, store the keys of the trust message for + // making the trust decisions as soon as the key of the + // sender is authenticated. + if (isSenderKeyAuthenticated) { + const auto trustedKeys = keyOwner.trustedKeys(); + for (const auto &key : trustedKeys) { + keysBeingAuthenticated.insert(keyOwnerJid, key); + } + + const auto distrustedKeys = keyOwner.distrustedKeys(); + for (const auto &key : distrustedKeys) { + keysBeingDistrusted.insert(keyOwnerJid, key); + } + } else { + keyOwnersForPostponedTrustDecisions.append(keyOwner); + } + } + } + + auto future = m_trustStorage->addKeysForPostponedTrustDecisions(encryption, senderKey, keyOwnersForPostponedTrustDecisions); + await(future, this, [=]() { + auto future = makeTrustDecisions(encryption, keysBeingAuthenticated, keysBeingDistrusted); + await(future, this, [=]() { + interface->reportFinished(); + }); + }); + }); + } else { + // Skip further processing in the following cases: + // 1. The message does not contain a trust message element. + // 2. The trust message is sent by this endpoint and reflected via + // Message Carbons. + interface->reportFinished(); + } + + return interface->future(); +} + +/// +/// Authenticates keys automatically by the content of a trust message. +/// +/// \param encryption encryption protocol namespace +/// \param keyIds key owners' bare JIDs mapped to the IDs of their keys +/// +QFuture<void> QXmppAtmManager::authenticate(const QString &encryption, const QMultiHash<QString, QString> &keyIds) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + if (keyIds.isEmpty()) { + interface->reportFinished(); + } else { + auto future = m_trustStorage->setTrustLevel(encryption, keyIds, QXmppTrustStorage::Authenticated); + await(future, this, [=]() { + auto future = distrustAutomaticallyTrustedKeys(encryption, keyIds.uniqueKeys()); + await(future, this, [=]() { + auto future = makePostponedTrustDecisions(encryption, keyIds.values()); + await(future, this, [=]() { + interface->reportFinished(); + }); + }); + }); + } + + return interface->future(); +} + +/// +/// Distrusts keys automatically by the content of a trust message. +/// +/// \param encryption encryption protocol namespace +/// \param keyIds key owners' bare JIDs mapped to the IDs of their keys +/// +QFuture<void> QXmppAtmManager::distrust(const QString &encryption, const QMultiHash<QString, QString> &keyIds) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + if (keyIds.isEmpty()) { + interface->reportFinished(); + } else { + auto future = m_trustStorage->setTrustLevel(encryption, keyIds, QXmppTrustStorage::ManuallyDistrusted); + await(future, this, [=]() { + auto future = m_trustStorage->removeKeysForPostponedTrustDecisions(encryption, keyIds.values()); + await(future, this, [=]() { + interface->reportFinished(); + }); + }); + } + + return interface->future(); +} + +/// +/// Distrusts all formerly automatically trusted keys (as specifed by the +/// security policy TOAKAFA). +/// +/// \param encryption encryption protocol namespace +/// \param keyOwnerJids bare JIDs of the key owners +/// +QFuture<void> QXmppAtmManager::distrustAutomaticallyTrustedKeys(const QString &encryption, const QList<QString> &keyOwnerJids) +{ + return m_trustStorage->setTrustLevel(encryption, keyOwnerJids, QXmppTrustStorage::AutomaticallyTrusted, QXmppTrustStorage::AutomaticallyDistrusted); +} + +/// +/// Authenticates or distrusts keys for whom earlier trust messages were +/// received but not used for authenticating or distrusting at that time. +/// +/// As soon as the senders' keys have been authenticated, all postponed trust +/// decisions can be performed by this method. +/// +/// \param encryption encryption protocol namespace +/// \param senderKeyIds IDs of the keys that were used by the senders +/// +QFuture<void> QXmppAtmManager::makePostponedTrustDecisions(const QString &encryption, const QList<QString> &senderKeyIds) +{ + auto interface = std::make_shared<QFutureInterface<void>>(QFutureInterfaceBase::Started); + + auto future = m_trustStorage->keysForPostponedTrustDecisions(encryption, senderKeyIds); + await(future, this, [=](const QHash<bool, QMultiHash<QString, QString>> &&keysForPostponedTrustDecisions) { + // JIDs of key owners mapped to the IDs of their keys + const auto keysBeingAuthenticated = keysForPostponedTrustDecisions.value(true); + const auto keysBeingDistrusted = keysForPostponedTrustDecisions.value(false); + + auto future = m_trustStorage->removeKeysForPostponedTrustDecisions(encryption, keysBeingAuthenticated.values(), keysBeingDistrusted.values()); + await(future, this, [=]() { + auto future = makeTrustDecisions(encryption, keysBeingAuthenticated, keysBeingDistrusted); + await(future, this, [=]() { + interface->reportFinished(); + }); + }); + }); + + return interface->future(); +} + +/// +/// Sends a trust message. +/// +/// \param encryption namespace of the encryption +/// \param keyOwners key owners containing the data for authentication or distrusting +/// \param recipientJid JID of the recipient +/// +QFuture<QXmpp::SendResult> QXmppAtmManager::sendTrustMessage(const QString &encryption, const QList<QXmppTrustMessageKeyOwner> &keyOwners, const QString &recipientJid) +{ + QXmppTrustMessageElement trustMessageElement; + trustMessageElement.setUsage(ns_atm); + trustMessageElement.setEncryption(encryption); + trustMessageElement.setKeyOwners(keyOwners); + + QXmppMessage message; + message.setTo(recipientJid); + message.setTrustMessageElement(trustMessageElement); + return client()->send(message); +} diff --git a/src/client/QXmppAtmManager.h b/src/client/QXmppAtmManager.h new file mode 100644 index 00000000..2df2dfce --- /dev/null +++ b/src/client/QXmppAtmManager.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008-2021 The QXmpp developers + * + * Author: + * Melvin Keskin <melvo@olomono.de> + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPATMMANAGER_H +#define QXMPPATMMANAGER_H + +#include "QXmppClientExtension.h" +#include "QXmppMessage.h" +#include "QXmppSendResult.h" +#include "QXmppTrustMessageKeyOwner.h" +#include "QXmppTrustStorage.h" + +class QXMPP_EXPORT QXmppAtmManager : public QXmppClientExtension +{ + Q_OBJECT + +public: + QXmppAtmManager(QXmppTrustStorage *trustStorage); + QFuture<void> makeTrustDecisions(const QString &encryption, const QString &keyOwnerJid, const QList<QString> &keyIdsForAuthentication, const QList<QString> &keyIdsForDistrusting = {}); + + /// \cond + bool handleStanza(const QDomElement &stanza) override; + +protected: + void setClient(QXmppClient *client) override; + +private slots: + void handleMessageReceived(const QXmppMessage &message); + /// \endcond + +private: + QFuture<void> makeTrustDecisions(const QString &encryption, const QMultiHash<QString, QString> &keyIdsForAuthentication, const QMultiHash<QString, QString> &keyIdsForDistrusting); + QFuture<void> handleMessage(const QXmppMessage &message); + + QFuture<void> authenticate(const QString &encryption, const QMultiHash<QString, QString> &keyIds); + QFuture<void> distrust(const QString &encryption, const QMultiHash<QString, QString> &keyIds); + + QFuture<void> distrustAutomaticallyTrustedKeys(const QString &encryption, const QList<QString> &keyOwnerJids); + QFuture<void> makePostponedTrustDecisions(const QString &encryption, const QList<QString> &senderKeyIds); + + QFuture<QXmpp::SendResult> sendTrustMessage(const QString &encryption, const QList<QXmppTrustMessageKeyOwner> &keyOwners, const QString &recipientJid); + + QXmppTrustStorage *m_trustStorage; + + friend class tst_QXmppAtmManager; +}; + +#endif // QXMPPATMMANAGER_H |
