From 5c93193508a49b79a92fd0d80cf4db14f1d0762e Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Fri, 8 Apr 2022 23:23:07 +0200 Subject: Make sure devices are known before decrypting olm messages --- lib/connection.cpp | 68 ++++++++++++++++++++++++++++++++++++++++-------------- lib/connection.h | 2 ++ 2 files changed, 53 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 1250eddf..d7460f08 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -118,6 +118,8 @@ public: PicklingMode picklingMode = Unencrypted {}; Database *database = nullptr; QHash oneTimeKeysCount; + std::vector> pendingEncryptedEvents; + void handleEncryptedToDeviceEvent(const EncryptedEvent& event); // A map from SenderKey to vector of InboundSession UnorderedMap> olmSessions; @@ -937,30 +939,44 @@ void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents) qCDebug(E2EE) << "Unsupported algorithm" << event.id() << "for event" << event.algorithm(); return; } - const auto decryptedEvent = sessionDecryptMessage(event); - if(!decryptedEvent) { - qCWarning(E2EE) << "Failed to decrypt event" << event.id(); + if (q->isKnownCurveKey(event.senderId(), event.senderKey())) { + handleEncryptedToDeviceEvent(event); return; } - - switchOnType(*decryptedEvent, - [this, senderKey = event.senderKey()](const RoomKeyEvent& roomKeyEvent) { - if (auto* detectedRoom = q->room(roomKeyEvent.roomId())) { - detectedRoom->handleRoomKeyEvent(roomKeyEvent, senderKey); - } else { - qCDebug(E2EE) << "Encrypted event room id" << roomKeyEvent.roomId() - << "is not found at the connection" << q->objectName(); - } - }, - [](const Event& evt) { - qCDebug(E2EE) << "Skipping encrypted to_device event, type" - << evt.matrixType(); - }); + trackedUsers += event.senderId(); + outdatedUsers += event.senderId(); + encryptionUpdateRequired = true; + pendingEncryptedEvents.push_back(std::make_unique(event.fullJson())); + }, [](const Event& e){ + // Unhandled }); } #endif } +void Connection::Private::handleEncryptedToDeviceEvent(const EncryptedEvent& event) +{ + const auto decryptedEvent = sessionDecryptMessage(event); + if(!decryptedEvent) { + qCWarning(E2EE) << "Failed to decrypt event" << event.id(); + return; + } + + switchOnType(*decryptedEvent, + [this, senderKey = event.senderKey()](const RoomKeyEvent& roomKeyEvent) { + if (auto* detectedRoom = q->room(roomKeyEvent.roomId())) { + detectedRoom->handleRoomKeyEvent(roomKeyEvent, senderKey); + } else { + qCDebug(E2EE) << "Encrypted event room id" << roomKeyEvent.roomId() + << "is not found at the connection" << q->objectName(); + } + }, + [](const Event& evt) { + qCDebug(E2EE) << "Skipping encrypted to_device event, type" + << evt.matrixType(); + }); +} + void Connection::Private::consumeDevicesList(DevicesList&& devicesList) { #ifdef Quotient_E2EE_ENABLED @@ -2046,6 +2062,15 @@ void Connection::Private::loadOutdatedUserDevices() outdatedUsers -= user; } saveDevicesList(); + + for(size_t i = 0; i < pendingEncryptedEvents.size();) { + if (q->isKnownCurveKey(pendingEncryptedEvents[i]->fullJson()[SenderKeyL].toString(), pendingEncryptedEvents[i]->contentJson()["sender_key"].toString())) { + handleEncryptedToDeviceEvent(*(pendingEncryptedEvents[i].get())); + pendingEncryptedEvents.erase(pendingEncryptedEvents.begin() + i); + } else { + i++; + } + } }); } @@ -2192,4 +2217,13 @@ QString Connection::edKeyForUserDevice(const QString& user, const QString& devic return d->deviceKeys[user][device].keys["ed25519:" % device]; } +bool Connection::isKnownCurveKey(const QString& user, const QString& curveKey) +{ + auto query = database()->prepareQuery(QStringLiteral("SELECT * FROM tracked_devices WHERE matrixId=:matrixId AND curveKey=:curveKey")); + query.bindValue(":matrixId", user); + query.bindValue(":curveKey", curveKey); + database()->execute(query); + return query.next(); +} + #endif diff --git a/lib/connection.h b/lib/connection.h index a4986b06..9f23902b 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -684,6 +684,7 @@ public Q_SLOTS: QStringList devicesForUser(User* user) const; QString curveKeyForUserDevice(const QString &user, const QString& device) const; QString edKeyForUserDevice(const QString& user, const QString& device) const; + bool isKnownCurveKey(const QString& user, const QString& curveKey); #endif Q_SIGNALS: /// \brief Initial server resolution has failed @@ -841,6 +842,7 @@ Q_SIGNALS: void cacheStateChanged(); void lazyLoadingChanged(); void turnServersChanged(const QJsonObject& servers); + void devicesListLoaded(); protected: /** -- cgit v1.2.3