From 77dd28b6006c301a679a208926835e516c3fa4fb Mon Sep 17 00:00:00 2001 From: blue Date: Thu, 2 Mar 2023 21:17:06 +0300 Subject: [PATCH] some further work on omemo, far from done yet --- core/account.cpp | 2 ++ core/handlers/discoveryhandler.cpp | 6 ++--- core/handlers/omemohandler.cpp | 13 +++++++++++ core/handlers/omemohandler.h | 28 ++++++++++++++--------- core/handlers/trusthandler.cpp | 14 ++++++++++++ core/handlers/trusthandler.h | 36 ++++++++++++++++-------------- core/handlers/vcardhandler.cpp | 16 +++++++++++++ external/qxmpp | 2 +- shared/enums.h | 4 +++- shared/keyinfo.cpp | 2 +- shared/keyinfo.h | 2 +- ui/models/info/omemo/keys.cpp | 6 +++++ ui/models/info/omemo/keys.h | 1 + ui/widgets/info/info.cpp | 25 +++++++++++++++++++++ ui/widgets/info/info.h | 12 ++++++++++ ui/widgets/info/omemo/omemo.cpp | 22 +++++++++++++----- ui/widgets/info/omemo/omemo.h | 9 +++++++- ui/widgets/info/omemo/omemo.ui | 4 ++-- 18 files changed, 161 insertions(+), 43 deletions(-) diff --git a/core/account.cpp b/core/account.cpp index 0970a6e..0a6c59c 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -106,6 +106,8 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& #ifdef WITH_OMEMO client.addExtension(tm); client.addExtension(om); + om->setSecurityPolicy(QXmpp::Toakafa); + om->setNewDeviceAutoSessionBuildingEnabled(true); if (oh->hasOwnDevice()) { QXmppTask future = om->load(); diff --git a/core/handlers/discoveryhandler.cpp b/core/handlers/discoveryhandler.cpp index 20e982c..977dda2 100644 --- a/core/handlers/discoveryhandler.cpp +++ b/core/handlers/discoveryhandler.cpp @@ -110,10 +110,10 @@ void Core::DiscoveryHandler::onInfoReceived(const QXmppDiscoveryIq& info) } } acc->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported); - } else { - qDebug() << "Received info for account" << accName << "about" << from; + } else { QString node = info.queryNode(); if (!node.isEmpty()) { + qDebug() << "Received features and identities for account" << accName << "about" << from; QStringList feats = info.features(); std::set identities; std::set features(feats.begin(), feats.end()); @@ -135,7 +135,7 @@ void Core::DiscoveryHandler::onInfoReceived(const QXmppDiscoveryIq& info) } else { Contact* cont = acc->rh->getContact(from); if (cont != nullptr) { - qDebug() << "Received info for account" << accName << "about" << from; + qDebug() << "Received info for account" << accName << "about contact" << from; QList identities = info.identities(); bool pepSupported = false; for (const QXmppDiscoveryIq::Identity& identity : identities) { diff --git a/core/handlers/omemohandler.cpp b/core/handlers/omemohandler.cpp index 2b864e1..ce82a96 100644 --- a/core/handlers/omemohandler.cpp +++ b/core/handlers/omemohandler.cpp @@ -154,6 +154,19 @@ QXmppTask Core::OmemoHandler::resetAll() { return Core::makeReadyTask(); } +void Core::OmemoHandler::getDevices(const QString& jid, std::list& out) const { + QHash devs; + try { + devs = devices->getRecord(jid); + } catch (const DataBase::NotFound& error) {} + + for (QHash::const_iterator itr = devs.begin(), end = devs.end(); itr != end; ++itr) { + const Device& dev = itr.value(); + out.emplace_back(itr.key(), dev.keyId, dev.label, QDateTime(), Shared::TrustLevel::undecided, Shared::EncryptionProtocol::omemo2, false); + } +} + + QDataStream & operator >> (QDataStream& in, QXmppOmemoStorage::Device& device) { in >> device.label; in >> device.keyId; diff --git a/core/handlers/omemohandler.h b/core/handlers/omemohandler.h index 7783c04..050677c 100644 --- a/core/handlers/omemohandler.h +++ b/core/handlers/omemohandler.h @@ -17,9 +17,15 @@ #ifndef CORE_OMEMOHANDLER_H #define CORE_OMEMOHANDLER_H +#include +#include + #include #include +#include +#include + Q_DECLARE_METATYPE(QXmppOmemoStorage::OwnDevice); Q_DECLARE_METATYPE(QXmppOmemoStorage::Device); @@ -34,24 +40,26 @@ public: OmemoHandler(Account* account); ~OmemoHandler() override; - QXmppTask allData() override; + virtual QXmppTask allData() override; - QXmppTask setOwnDevice(const std::optional &device) override; + virtual QXmppTask setOwnDevice(const std::optional &device) override; - QXmppTask addSignedPreKeyPair(uint32_t keyId, const QXmppOmemoStorage::SignedPreKeyPair &keyPair) override; - QXmppTask removeSignedPreKeyPair(uint32_t keyId) override; + virtual QXmppTask addSignedPreKeyPair(uint32_t keyId, const QXmppOmemoStorage::SignedPreKeyPair &keyPair) override; + virtual QXmppTask removeSignedPreKeyPair(uint32_t keyId) override; - QXmppTask addPreKeyPairs(const QHash &keyPairs) override; - QXmppTask removePreKeyPair(uint32_t keyId) override; + virtual QXmppTask addPreKeyPairs(const QHash &keyPairs) override; + virtual QXmppTask removePreKeyPair(uint32_t keyId) override; - QXmppTask addDevice(const QString &jid, uint32_t deviceId, const Device &device) override; - QXmppTask removeDevice(const QString &jid, uint32_t deviceId) override; - QXmppTask removeDevices(const QString &jid) override; + virtual QXmppTask addDevice(const QString &jid, uint32_t deviceId, const Device &device) override; + virtual QXmppTask removeDevice(const QString &jid, uint32_t deviceId) override; + virtual QXmppTask removeDevices(const QString &jid) override; - QXmppTask resetAll() override; + virtual QXmppTask resetAll() override; bool hasOwnDevice(); + void getDevices(const QString& jid, std::list& out) const; + private: Account* acc; std::optional ownDevice; diff --git a/core/handlers/trusthandler.cpp b/core/handlers/trusthandler.cpp index 3ea6e47..50fbcbf 100644 --- a/core/handlers/trusthandler.cpp +++ b/core/handlers/trusthandler.cpp @@ -326,6 +326,20 @@ QXmppTask TrustHandler::setSecurityPolicy( return Core::makeReadyTask(); } +Core::TrustHandler::Keys Core::TrustHandler::getKeys(const QString& protocol, const QString& jid) const { + std::map::const_iterator itr = keysByProtocol.find(protocol); + if (itr != keysByProtocol.end()) { + try { + Keys map = itr->second->getRecord(jid); + return map; + } catch (const DataBase::NotFound& e) { + return Keys(); + } + } else { + return Keys(); + } +} + Shared::TrustLevel Core::TrustHandler::convert(Core::TrustHandler::TL level) { switch (level) { diff --git a/core/handlers/trusthandler.h b/core/handlers/trusthandler.h index e46c7b3..677a4f7 100644 --- a/core/handlers/trusthandler.h +++ b/core/handlers/trusthandler.h @@ -41,27 +41,29 @@ public: typedef std::map Keys; typedef DataBase::Cache KeyCache; - virtual QXmppTask resetAll(CSR encryption); - virtual QXmppTask trustLevel(CSR encryption, CSR keyOwnerJid, const QByteArray& keyId); - virtual QXmppTask setTrustLevel(CSR encryption, CLSR keyOwnerJids, TL oldTrustLevel, TL newTrustLevel); - virtual QXmppTask setTrustLevel(CSR encryption, const MultySB& keyIds, TL trustLevel); - virtual QXmppTask hasKey(CSR encryption, CSR keyOwnerJid, QXmpp::TrustLevels trustLevels); - virtual QXmppTask keys(CSR encryption, CLSR keyOwnerJids, QXmpp::TrustLevels trustLevels); - virtual QXmppTask> keys(CSR encryption, QXmpp::TrustLevels trustLevels); - virtual QXmppTask removeKeys(CSR encryption); - virtual QXmppTask removeKeys(CSR encryption, CSR keyOwnerJid); - virtual QXmppTask removeKeys(CSR encryption, CLBAR keyIds); - virtual QXmppTask addKeys(CSR encryption, CSR keyOwnerJid, CLBAR keyIds, TL trustLevel); - virtual QXmppTask ownKey(CSR encryption); - virtual QXmppTask resetOwnKey(CSR encryption); - virtual QXmppTask setOwnKey(CSR encryption, const QByteArray& keyId); - virtual QXmppTask securityPolicy(CSR encryption); - virtual QXmppTask resetSecurityPolicy(CSR encryption); - virtual QXmppTask setSecurityPolicy(CSR encryption, QXmpp::TrustSecurityPolicy securityPolicy); + virtual QXmppTask resetAll(CSR encryption) override; + virtual QXmppTask trustLevel(CSR encryption, CSR keyOwnerJid, const QByteArray& keyId) override; + virtual QXmppTask setTrustLevel(CSR encryption, CLSR keyOwnerJids, TL oldTrustLevel, TL newTrustLevel) override; + virtual QXmppTask setTrustLevel(CSR encryption, const MultySB& keyIds, TL trustLevel) override; + virtual QXmppTask hasKey(CSR encryption, CSR keyOwnerJid, QXmpp::TrustLevels trustLevels) override; + virtual QXmppTask keys(CSR encryption, CLSR keyOwnerJids, QXmpp::TrustLevels trustLevels) override; + virtual QXmppTask> keys(CSR encryption, QXmpp::TrustLevels trustLevels) override; + virtual QXmppTask removeKeys(CSR encryption) override; + virtual QXmppTask removeKeys(CSR encryption, CSR keyOwnerJid) override; + virtual QXmppTask removeKeys(CSR encryption, CLBAR keyIds) override; + virtual QXmppTask addKeys(CSR encryption, CSR keyOwnerJid, CLBAR keyIds, TL trustLevel) override; + virtual QXmppTask ownKey(CSR encryption) override; + virtual QXmppTask resetOwnKey(CSR encryption) override; + virtual QXmppTask setOwnKey(CSR encryption, const QByteArray& keyId) override; + virtual QXmppTask securityPolicy(CSR encryption) override; + virtual QXmppTask resetSecurityPolicy(CSR encryption) override; + virtual QXmppTask setSecurityPolicy(CSR encryption, QXmpp::TrustSecurityPolicy securityPolicy) override; static TL convert(Shared::TrustLevel level); static Shared::TrustLevel convert(TL level); + Keys getKeys(const QString& protocol, const QString& jid) const; + private: KeyCache* createNewCache(const QString& encryption); KeyCache* getCache(const QString& encryption); diff --git a/core/handlers/vcardhandler.cpp b/core/handlers/vcardhandler.cpp index 33c9cdb..6c5cb5b 100644 --- a/core/handlers/vcardhandler.cpp +++ b/core/handlers/vcardhandler.cpp @@ -17,6 +17,8 @@ #include "vcardhandler.h" #include "core/account.h" +constexpr const char* ns_omemo_2 = "urn:xmpp:omemo:2"; + Core::VCardHandler::VCardHandler(Account* account): QObject(), acc(account), @@ -102,6 +104,20 @@ void Core::VCardHandler::onVCardReceived(const QXmppVCardIq& card) { Shared::Info info(jid, Shared::EntryType::contact); item->handleResponseVCard(card, resource, info.getVCardRef()); +#ifdef WITH_OMEMO + std::list& aks = info.getActiveKeysRef(); + acc->oh->getDevices(jid, aks); + std::map trustLevels = acc->th->getKeys(ns_omemo_2, jid); + + qDebug() << "OMEMO info for " << jid << " devices:" << aks.size() << ", trustLevels:" << trustLevels.size(); + for (Shared::KeyInfo& key : aks) { + std::map::const_iterator itr = trustLevels.find(key.fingerPrint); + if (itr != trustLevels.end()) { + key.trustLevel = itr->second; + qDebug() << "Found a trust level for a device!"; + } + } +#endif emit acc->infoReady(info); } diff --git a/external/qxmpp b/external/qxmpp index d2c2acd..9d57624 160000 --- a/external/qxmpp +++ b/external/qxmpp @@ -1 +1 @@ -Subproject commit d2c2acd4848f815d0dc3d108f8bc306f9015fc89 +Subproject commit 9d5762499fbddb3dd1ed8eeca16f9db70adc27d0 diff --git a/shared/enums.h b/shared/enums.h index 46d954a..aff22b9 100644 --- a/shared/enums.h +++ b/shared/enums.h @@ -160,7 +160,9 @@ static const TrustLevel TrustLevelHighest = TrustLevel::undecided; static const TrustLevel TrustLevelLowest = TrustLevel::authenticated; enum class EncryptionProtocol { - omemo + omemo, + omemo1, + omemo2 }; Q_ENUM_NS(EncryptionProtocol) diff --git a/shared/keyinfo.cpp b/shared/keyinfo.cpp index db3ce2b..f7d9e90 100644 --- a/shared/keyinfo.cpp +++ b/shared/keyinfo.cpp @@ -43,7 +43,7 @@ Shared::KeyInfo::KeyInfo(): label(), lastInteraction(), trustLevel(TrustLevel::undecided), - protocol(EncryptionProtocol::omemo), + protocol(EncryptionProtocol::omemo2), currentDevice(false) { } diff --git a/shared/keyinfo.h b/shared/keyinfo.h index 1befbc9..8d7db0a 100644 --- a/shared/keyinfo.h +++ b/shared/keyinfo.h @@ -36,7 +36,7 @@ public: const QString& label, const QDateTime& lastInteraction, TrustLevel trustLevel, - EncryptionProtocol protocol = EncryptionProtocol::omemo, + EncryptionProtocol protocol = EncryptionProtocol::omemo2, bool currentDevice = false ); KeyInfo(); diff --git a/ui/models/info/omemo/keys.cpp b/ui/models/info/omemo/keys.cpp index fa753c0..e4dc8d2 100644 --- a/ui/models/info/omemo/keys.cpp +++ b/ui/models/info/omemo/keys.cpp @@ -134,5 +134,11 @@ void Models::Keys::setTrustLevel(int row, Shared::TrustLevel level) { dataChanged(index, index, {Keys::Dirty}); } +void Models::Keys::clear() { + beginResetModel(); + keys.clear(); + modified.clear(); + endResetModel(); +} diff --git a/ui/models/info/omemo/keys.h b/ui/models/info/omemo/keys.h index 2710bab..49948a2 100644 --- a/ui/models/info/omemo/keys.h +++ b/ui/models/info/omemo/keys.h @@ -33,6 +33,7 @@ public: ~Keys(); void addKey(const Shared::KeyInfo& info); + void clear(); QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; diff --git a/ui/widgets/info/info.cpp b/ui/widgets/info/info.cpp index a400f22..6a1105d 100644 --- a/ui/widgets/info/info.cpp +++ b/ui/widgets/info/info.cpp @@ -24,6 +24,9 @@ UI::Info::Info(const QString& p_jid, QWidget* parent): m_ui(new Ui::Info()), contactGeneral(nullptr), contactContacts(nullptr), +#ifdef WITH_OMEMO + omemo(nullptr), +#endif description(nullptr), overlay(new QWidget()), progress(new Progress(100)), @@ -57,6 +60,9 @@ void UI::Info::setData(const Shared::Info& info) { initializeContactGeneral(jid, card, editable); initializeContactContacts(jid, card, editable); initializeDescription(card.getDescription(), editable); +#ifdef WITH_OMEMO + initializeOmemo(info.getActiveKeysRef()); +#endif type = info.getType(); } break; @@ -170,5 +176,24 @@ void UI::Info::clear() { description->deleteLater(); description = nullptr; } + +#ifdef WITH_OMEMO + if (omemo != nullptr) { + omemo->deleteLater(); + omemo = nullptr; + } +#endif + type = Shared::EntryType::none; } + +#ifdef WITH_OMEMO +void UI::Info::initializeOmemo(const std::list& keys) { + if (omemo == nullptr) { + omemo = new Omemo(); + m_ui->tabWidget->addTab(omemo, omemo->title()); + } + omemo->setData(keys); +} + +#endif diff --git a/ui/widgets/info/info.h b/ui/widgets/info/info.h index 14829e7..10bc063 100644 --- a/ui/widgets/info/info.h +++ b/ui/widgets/info/info.h @@ -17,6 +17,8 @@ #ifndef UI_WIDGETS_INFO_H #define UI_WIDGETS_INFO_H +#include + #include #include #include @@ -30,6 +32,10 @@ #include "contactgeneral.h" #include "contactcontacts.h" #include "description.h" +#ifdef WITH_OMEMO +#include "omemo/omemo.h" +#endif + namespace UI { namespace Ui @@ -58,6 +64,9 @@ private: void initializeContactGeneral(const QString& jid, const Shared::VCard& card, bool editable); void initializeContactContacts(const QString& jid, const Shared::VCard& card, bool editable); void initializeDescription(const QString& description, bool editable); +#ifdef WITH_OMEMO + void initializeOmemo(const std::list& keys); +#endif void initializeOverlay(); void initializeButtonBox(); void clear(); @@ -68,6 +77,9 @@ private: QScopedPointer m_ui; ContactGeneral* contactGeneral; ContactContacts* contactContacts; +#ifdef WITH_OMEMO + Omemo* omemo; +#endif Description* description; QWidget* overlay; Progress* progress; diff --git a/ui/widgets/info/omemo/omemo.cpp b/ui/widgets/info/omemo/omemo.cpp index 16414ee..d3722fe 100644 --- a/ui/widgets/info/omemo/omemo.cpp +++ b/ui/widgets/info/omemo/omemo.cpp @@ -20,7 +20,7 @@ #include constexpr uint8_t fingerprintLength = 32; -Omemo::Omemo(QWidget* parent): +UI::Omemo::Omemo(QWidget* parent): QWidget(parent), m_ui(new Ui::Omemo()), keysDelegate(), @@ -31,8 +31,6 @@ Omemo::Omemo(QWidget* parent): { m_ui->setupUi(this); - generateMockData(); - m_ui->keysView->setItemDelegate(&keysDelegate); m_ui->keysView->setModel(&keysModel); m_ui->unusedKeysView->setItemDelegate(&unusedKeysDelegate); @@ -42,12 +40,12 @@ Omemo::Omemo(QWidget* parent): connect(m_ui->keysView, &QWidget::customContextMenuRequested, this, &Omemo::onActiveKeysContextMenu); } -Omemo::~Omemo() +UI::Omemo::~Omemo() { contextMenu->deleteLater(); } -void Omemo::generateMockData() { +void UI::Omemo::generateMockData() { std::random_device rd; std::uniform_int_distribution dist(CHAR_MIN, CHAR_MAX); for (int i = 0; i < 5; ++i) { @@ -67,7 +65,19 @@ void Omemo::generateMockData() { } } -void Omemo::onActiveKeysContextMenu(const QPoint& pos) { +void UI::Omemo::setData(const std::list& keys) { + keysModel.clear(); + unusedKeysModel.clear(); + for (const Shared::KeyInfo& key : keys) { + keysModel.addKey(key); + } +} + +const QString UI::Omemo::title() const { + return m_ui->OMEMOHeading->text();} + + +void UI::Omemo::onActiveKeysContextMenu(const QPoint& pos) { contextMenu->clear(); QModelIndex index = m_ui->keysView->indexAt(pos); if (index.isValid()) { diff --git a/ui/widgets/info/omemo/omemo.h b/ui/widgets/info/omemo/omemo.h index 7c6b5a1..a279492 100644 --- a/ui/widgets/info/omemo/omemo.h +++ b/ui/widgets/info/omemo/omemo.h @@ -17,6 +17,8 @@ #ifndef VCARD_OMEMO_H #define VCARD_OMEMO_H +#include + #include #include #include @@ -24,7 +26,9 @@ #include "ui/models/info/omemo/keys.h" #include "keydelegate.h" #include "shared/icons.h" +#include "shared/keyinfo.h" +namespace UI { namespace Ui { class Omemo; @@ -36,6 +40,9 @@ public: Omemo(QWidget* parent = nullptr); ~Omemo(); + void setData(const std::list& keys); + const QString title() const; + private slots: void onActiveKeysContextMenu(const QPoint& pos); @@ -50,5 +57,5 @@ private: Models::Keys unusedKeysModel; QMenu* contextMenu; }; - +} #endif // VCARD_OMEMO_H diff --git a/ui/widgets/info/omemo/omemo.ui b/ui/widgets/info/omemo/omemo.ui index d9f55b1..745b981 100644 --- a/ui/widgets/info/omemo/omemo.ui +++ b/ui/widgets/info/omemo/omemo.ui @@ -1,7 +1,7 @@ - Omemo - + UI::Omemo + 0