diff options
-rw-r--r-- | lib/connection.cpp | 13 | ||||
-rw-r--r-- | lib/connection.h | 2 | ||||
-rw-r--r-- | lib/database.cpp | 37 | ||||
-rw-r--r-- | lib/database.h | 6 | ||||
-rw-r--r-- | lib/room.cpp | 6 |
5 files changed, 51 insertions, 13 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index ae8532c3..45888bcb 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -216,7 +216,7 @@ public: qCWarning(E2EE) << "Failed to pickle olm session. Error" << std::get<QOlmError>(pickleResult); return; } - q->database()->saveOlmSession(senderKey, session->sessionId(), std::get<QByteArray>(pickleResult)); + q->database()->saveOlmSession(senderKey, session->sessionId(), std::get<QByteArray>(pickleResult), QDateTime::currentDateTime()); } QString sessionDecryptPrekey(const QOlmMessage& message, const QString &senderKey, std::unique_ptr<QOlmAccount>& olmAccount) { @@ -227,6 +227,7 @@ public: qCDebug(E2EE) << "Found inbound session"; const auto result = session->decrypt(message); if(std::holds_alternative<QString>(result)) { + q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime()); return std::get<QString>(result); } else { qCDebug(E2EE) << "Failed to decrypt prekey message"; @@ -261,6 +262,7 @@ public: for(auto& session : olmSessions[senderKey]) { const auto result = session->decrypt(message); if(std::holds_alternative<QString>(result)) { + q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime()); return std::get<QString>(result); } } @@ -320,6 +322,11 @@ public: << "in Olm plaintext"; return {}; } + //TODO make this do the check mentioned in the E2EE Implementation guide instead + if (decryptedEvent->fullJson()["keys"]["ed25519"].toString().isEmpty()) { + qCDebug(E2EE) << "Event does not contain an ed25519 key"; + return {}; + } // TODO: keys to constants const auto decryptedEventObject = decryptedEvent->fullJson(); @@ -2157,9 +2164,9 @@ UnorderedMap<std::pair<QString, QString>, QOlmInboundGroupSessionPtr> Connection return database()->loadMegolmSessions(room->id(), picklingMode()); } -void Connection::saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session) +void Connection::saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session, const QString& ed25519Key) { - database()->saveMegolmSession(room->id(), senderKey, session->sessionId(), session->pickle(picklingMode())); + database()->saveMegolmSession(room->id(), senderKey, session->sessionId(), ed25519Key, session->pickle(picklingMode())); } QStringList Connection::devicesForUser(User* user) const diff --git a/lib/connection.h b/lib/connection.h index 4a475319..a4986b06 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -318,7 +318,7 @@ public: QOlmAccount* olmAccount() const; Database* database(); UnorderedMap<std::pair<QString, QString>, QOlmInboundGroupSessionPtr> loadRoomMegolmSessions(Room* room); - void saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session); + void saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session, const QString& ed25519Key); #endif // Quotient_E2EE_ENABLED Q_INVOKABLE Quotient::SyncJob* syncJob() const; Q_INVOKABLE int millisToReconnect() const; diff --git a/lib/database.cpp b/lib/database.cpp index 84c93046..70dc1b9b 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -28,6 +28,7 @@ Database::Database(const QString& matrixId, const QString& deviceId, QObject* pa switch(version()) { case 0: migrateTo1(); + case 1: migrateTo2(); } } @@ -94,6 +95,22 @@ void Database::migrateTo1() commit(); } +void Database::migrateTo2() +{ + qCDebug(DATABASE) << "Migrating database to version 2"; + transaction(); + execute(QStringLiteral("ALTER TABLE inbound_megolm_sessions ADD ed25519Key TEXT")); + execute(QStringLiteral("ALTER TABLE olm_sessions ADD lastReceived TEXT")); + + // Add indexes for improving queries speed on larger database + execute(QStringLiteral("CREATE INDEX sessions_session_idx ON olm_sessions(sessionId)")); + execute(QStringLiteral("CREATE INDEX outbound_room_idx ON outbound_megolm_sessions(roomId)")); + execute(QStringLiteral("CREATE INDEX inbound_room_idx ON inbound_megolm_sessions(roomId)")); + execute(QStringLiteral("CREATE INDEX group_session_idx ON group_session_record_index(roomId, sessionId, i)")); + execute(QStringLiteral("PRAGMA user_version = 2;")); + commit(); +} + QByteArray Database::accountPickle() { auto query = prepareQuery(QStringLiteral("SELECT pickle FROM accounts;")); @@ -131,12 +148,13 @@ void Database::clear() } -void Database::saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle) +void Database::saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle, const QDateTime& timestamp) { - auto query = prepareQuery(QStringLiteral("INSERT INTO olm_sessions(senderKey, sessionId, pickle) VALUES(:senderKey, :sessionId, :pickle);")); + auto query = prepareQuery(QStringLiteral("INSERT INTO olm_sessions(senderKey, sessionId, pickle, lastReceived) VALUES(:senderKey, :sessionId, :pickle, :lastReceived);")); query.bindValue(":senderKey", senderKey); query.bindValue(":sessionId", sessionId); query.bindValue(":pickle", pickle); + query.bindValue(":lastReceived", timestamp); transaction(); execute(query); commit(); @@ -179,12 +197,13 @@ UnorderedMap<std::pair<QString, QString>, QOlmInboundGroupSessionPtr> Database:: return sessions; } -void Database::saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionId, const QByteArray& pickle) +void Database::saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionId, const QString& ed25519Key, const QByteArray& pickle) { - auto query = prepareQuery(QStringLiteral("INSERT INTO inbound_megolm_sessions(roomId, senderKey, sessionId, pickle) VALUES(:roomId, :senderKey, :sessionId, :pickle);")); + auto query = prepareQuery(QStringLiteral("INSERT INTO inbound_megolm_sessions(roomId, senderKey, sessionId, ed25519Key, pickle) VALUES(:roomId, :senderKey, :sessionId, :ed25519Key, :pickle);")); query.bindValue(":roomId", roomId); query.bindValue(":senderKey", senderKey); query.bindValue(":sessionId", sessionId); + query.bindValue(":ed25519Key", ed25519Key); query.bindValue(":pickle", pickle); transaction(); execute(query); @@ -242,3 +261,13 @@ void Database::clearRoomData(const QString& roomId) execute(query3); commit(); } + +void Database::setOlmSessionLastReceived(const QString& sessionId, const QDateTime& timestamp) +{ + auto query = prepareQuery(QStringLiteral("UPDATE olm_sessions SET lastReceived=:lastReceived WHERE sessionId=:sessionId;")); + query.bindValue(":lastReceived", timestamp); + query.bindValue(":sessionId", sessionId); + transaction(); + execute(query); + commit(); +} diff --git a/lib/database.h b/lib/database.h index d4d5fb56..cf241dbc 100644 --- a/lib/database.h +++ b/lib/database.h @@ -27,16 +27,18 @@ public: QByteArray accountPickle(); void setAccountPickle(const QByteArray &pickle); void clear(); - void saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle); + void saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle, const QDateTime& timestamp); UnorderedMap<QString, std::vector<QOlmSessionPtr>> loadOlmSessions(const PicklingMode& picklingMode); UnorderedMap<std::pair<QString, QString>, QOlmInboundGroupSessionPtr> loadMegolmSessions(const QString& roomId, const PicklingMode& picklingMode); - void saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionKey, const QByteArray& pickle); + void saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionKey, const QString& ed25519Key, const QByteArray& pickle); void addGroupSessionIndexRecord(const QString& roomId, const QString& sessionId, uint32_t index, const QString& eventId, qint64 ts); std::pair<QString, qint64> groupSessionIndexRecord(const QString& roomId, const QString& sessionId, qint64 index); void clearRoomData(const QString& roomId); + void setOlmSessionLastReceived(const QString& sessionId, const QDateTime& timestamp); private: void migrateTo1(); + void migrateTo2(); QString m_matrixId; }; } diff --git a/lib/room.cpp b/lib/room.cpp index 6197b3a2..88aa1d07 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -341,7 +341,7 @@ public: UnorderedMap<std::pair<QString, QString>, QOlmInboundGroupSessionPtr> groupSessions; bool addInboundGroupSession(QString senderKey, QString sessionId, - QString sessionKey) + QString sessionKey, QString ed25519Key) { if (groupSessions.find({senderKey, sessionId}) != groupSessions.end()) { qCWarning(E2EE) << "Inbound Megolm session" << sessionId @@ -356,7 +356,7 @@ public: return false; } qCWarning(E2EE) << "Adding inbound session"; - connection->saveMegolmSession(q, senderKey, megolmSession.get()); + connection->saveMegolmSession(q, senderKey, megolmSession.get(), ed25519Key); groupSessions[{senderKey, sessionId}] = std::move(megolmSession); return true; } @@ -1509,7 +1509,7 @@ void Room::handleRoomKeyEvent(const RoomKeyEvent& roomKeyEvent, << roomKeyEvent.algorithm() << "in m.room_key event"; } if (d->addInboundGroupSession(senderKey, roomKeyEvent.sessionId(), - roomKeyEvent.sessionKey())) { + roomKeyEvent.sessionKey(), roomKeyEvent.fullJson()["keys"]["ed25519"].toString())) { qCWarning(E2EE) << "added new inboundGroupSession:" << d->groupSessions.size(); for (const auto& eventId : d->undecryptedEvents[roomKeyEvent.sessionId()]) { |