diff options
author | Tobias Fella <fella@posteo.de> | 2022-04-08 23:23:07 +0200 |
---|---|---|
committer | Tobias Fella <fella@posteo.de> | 2022-04-09 15:52:11 +0200 |
commit | 5c93193508a49b79a92fd0d80cf4db14f1d0762e (patch) | |
tree | 44e4d602e248af8fce8b9c2e19bacd187f19e31e /lib | |
parent | 42abb01516ee4d3d0fe11ffddd47c7e76d786385 (diff) | |
download | libquotient-5c93193508a49b79a92fd0d80cf4db14f1d0762e.tar.gz libquotient-5c93193508a49b79a92fd0d80cf4db14f1d0762e.zip |
Make sure devices are known before decrypting olm messages
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 68 | ||||
-rw-r--r-- | lib/connection.h | 2 |
2 files changed, 53 insertions, 17 deletions
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<QString, int> oneTimeKeysCount; + std::vector<std::unique_ptr<EncryptedEvent>> pendingEncryptedEvents; + void handleEncryptedToDeviceEvent(const EncryptedEvent& event); // A map from SenderKey to vector of InboundSession UnorderedMap<QString, std::vector<QOlmSessionPtr>> 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<EncryptedEvent>(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: /** |