aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTobias Fella <fella@posteo.de>2022-04-08 23:23:07 +0200
committerTobias Fella <fella@posteo.de>2022-04-09 15:52:11 +0200
commit5c93193508a49b79a92fd0d80cf4db14f1d0762e (patch)
tree44e4d602e248af8fce8b9c2e19bacd187f19e31e /lib
parent42abb01516ee4d3d0fe11ffddd47c7e76d786385 (diff)
downloadlibquotient-5c93193508a49b79a92fd0d80cf4db14f1d0762e.tar.gz
libquotient-5c93193508a49b79a92fd0d80cf4db14f1d0762e.zip
Make sure devices are known before decrypting olm messages
Diffstat (limited to 'lib')
-rw-r--r--lib/connection.cpp68
-rw-r--r--lib/connection.h2
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:
/**