summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-10-20 19:46:37 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-10-20 19:46:37 +0200
commitcea7f4574f92929c31cd89706075e769d2bfcf56 (patch)
treeb6d7756171f6026c7144b929468b5dfc8568e0c8
parentShare code for sending encrypted olm messages (diff)
downloadnheko-cea7f4574f92929c31cd89706075e769d2bfcf56.tar.xz
Clean up key requests + autoreload
-rw-r--r--CMakeLists.txt2
-rw-r--r--io.github.NhekoReborn.Nheko.json2
-rw-r--r--src/ChatPage.cpp6
-rw-r--r--src/ChatPage.h2
-rw-r--r--src/Olm.cpp47
-rw-r--r--src/Olm.h8
-rw-r--r--src/timeline/EventStore.cpp51
-rw-r--r--src/timeline/EventStore.h8
-rw-r--r--src/timeline/TimelineModel.h4
-rw-r--r--src/timeline/TimelineViewManager.cpp9
-rw-r--r--src/timeline/TimelineViewManager.h1
11 files changed, 84 insertions, 56 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f83a865..4f6a6a38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -340,7 +340,7 @@ if(USE_BUNDLED_MTXCLIENT)
 	FetchContent_Declare(
 		MatrixClient
 		GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
-		GIT_TAG        ad5575bc24089dc385e97d9ace026414b618775c
+		GIT_TAG        da9958e14e035fbf22d498074d381b2ea0092a9d
 		)
 	FetchContent_MakeAvailable(MatrixClient)
 else()
diff --git a/io.github.NhekoReborn.Nheko.json b/io.github.NhekoReborn.Nheko.json
index 59f4fa46..5f08dee0 100644
--- a/io.github.NhekoReborn.Nheko.json
+++ b/io.github.NhekoReborn.Nheko.json
@@ -146,7 +146,7 @@
       "name": "mtxclient",
       "sources": [
         {
-          "commit": "ad5575bc24089dc385e97d9ace026414b618775c",
+          "commit": "da9958e14e035fbf22d498074d381b2ea0092a9d",
           "type": "git",
           "url": "https://github.com/Nheko-Reborn/mtxclient.git"
         }
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index e61df263..8b6f1123 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -1250,6 +1250,12 @@ ChatPage::unbanUser(QString userid, QString reason)
 }
 
 void
+ChatPage::receivedSessionKey(const std::string &room_id, const std::string &session_id)
+{
+        view_manager_->receivedSessionKey(room_id, session_id);
+}
+
+void
 ChatPage::sendTypingNotifications()
 {
         if (!userSettings_->typingNotifications())
diff --git a/src/ChatPage.h b/src/ChatPage.h
index f0e12ab5..bf649cc9 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -107,6 +107,8 @@ public slots:
         void banUser(QString userid, QString reason);
         void unbanUser(QString userid, QString reason);
 
+        void receivedSessionKey(const std::string &room_id, const std::string &session_id);
+
 signals:
         void connectionLost();
         void connectionRestored();
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 730a3ea5..79b00774 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -388,9 +388,10 @@ import_inbound_megolm_session(
                 return;
         }
 
-        // TODO(Nico): Reload messages encrypted with this key.
         nhlog::crypto()->info(
           "established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
+
+        ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
 }
 
 void
@@ -401,48 +402,24 @@ mark_keys_as_published()
 }
 
 void
-request_keys(const std::string &room_id, const std::string &event_id)
-{
-        nhlog::crypto()->info("requesting keys for event {} at {}", event_id, room_id);
-
-        http::client()->get_event(
-          room_id,
-          event_id,
-          [event_id, room_id](const mtx::events::collections::TimelineEvents &res,
-                              mtx::http::RequestErr err) {
-                  using namespace mtx::events;
-
-                  if (err) {
-                          nhlog::net()->warn(
-                            "failed to retrieve event {} from {}", event_id, room_id);
-                          return;
-                  }
-
-                  if (!std::holds_alternative<EncryptedEvent<msg::Encrypted>>(res)) {
-                          nhlog::net()->info(
-                            "retrieved event is not encrypted: {} from {}", event_id, room_id);
-                          return;
-                  }
-
-                  olm::send_key_request_for(room_id, std::get<EncryptedEvent<msg::Encrypted>>(res));
-          });
-}
-
-void
-send_key_request_for(const std::string &room_id,
-                     const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e)
+send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
+                     const std::string &request_id,
+                     bool cancel)
 {
         using namespace mtx::events;
 
-        nhlog::crypto()->debug("sending key request: {}", json(e).dump(2));
+        nhlog::crypto()->debug("sending key request: sender_key {}, session_id {}",
+                               e.content.sender_key,
+                               e.content.session_id);
 
         mtx::events::msg::KeyRequest request;
-        request.action               = mtx::events::msg::RequestAction::Request;
+        request.action = !cancel ? mtx::events::msg::RequestAction::Request
+                                 : mtx::events::msg::RequestAction::Cancellation;
         request.algorithm            = MEGOLM_ALGO;
-        request.room_id              = room_id;
+        request.room_id              = e.room_id;
         request.sender_key           = e.content.sender_key;
         request.session_id           = e.content.session_id;
-        request.request_id           = "key_request." + http::client()->generate_txn_id();
+        request.request_id           = request_id;
         request.requesting_device_id = http::client()->device_id();
 
         nhlog::crypto()->debug("m.room_key_request: {}", json(request).dump(2));
diff --git a/src/Olm.h b/src/Olm.h
index ce362e26..322affa1 100644
--- a/src/Olm.h
+++ b/src/Olm.h
@@ -96,11 +96,9 @@ mark_keys_as_published();
 
 //! Request the encryption keys from sender's device for the given event.
 void
-request_keys(const std::string &room_id, const std::string &event_id);
-
-void
-send_key_request_for(const std::string &room_id,
-                     const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &);
+send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
+                     const std::string &request_id,
+                     bool cancel = false);
 
 void
 handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> &);
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 3564ffc0..22809a20 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -213,6 +213,28 @@ EventStore::clearTimeline()
 }
 
 void
+EventStore::receivedSessionKey(const std::string &session_id)
+{
+        if (!pending_key_requests.count(session_id))
+                return;
+
+        auto request = pending_key_requests.at(session_id);
+        pending_key_requests.erase(session_id);
+
+        olm::send_key_request_for(request.events.front(), request.request_id, true);
+
+        for (const auto &e : request.events) {
+                auto idx = idToIndex(e.event_id);
+                if (idx) {
+                        decryptedEvents_.remove({room_id_, e.event_id});
+                        events_by_id_.remove({room_id_, e.event_id});
+                        events_.remove({room_id_, toInternalIdx(*idx)});
+                        emit dataChanged(*idx, *idx);
+                }
+        }
+}
+
+void
 EventStore::handleSync(const mtx::responses::Timeline &events)
 {
         if (this->thread() != QThread::currentThread())
@@ -294,18 +316,6 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
                               *d_event)) {
                                 handle_room_verification(*d_event);
                         }
-                        // else {
-                        //        // only the key.verification.ready sent by localuser's other
-                        //        device
-                        //        // is of significance as it is used for detecting accepted request
-                        //        if (std::get_if<mtx::events::RoomEvent<
-                        //              mtx::events::msg::KeyVerificationReady>>(d_event)) {
-                        //                auto msg = std::get_if<mtx::events::RoomEvent<
-                        //                  mtx::events::msg::KeyVerificationReady>>(d_event);
-                        //                ChatPage::instance()->receivedDeviceVerificationReady(
-                        //                  msg->content);
-                        //        }
-                        //}
                 }
         }
 }
@@ -501,7 +511,7 @@ EventStore::decryptEvent(const IdIndex &idx,
 
         if (decryptionResult.error) {
                 switch (*decryptionResult.error) {
-                case olm::DecryptionErrorCode::MissingSession:
+                case olm::DecryptionErrorCode::MissingSession: {
                         dummy.content.body =
                           tr("-- Encrypted Event (No keys found for decryption) --",
                              "Placeholder, when the message was not decrypted yet or can't be "
@@ -512,8 +522,21 @@ EventStore::decryptEvent(const IdIndex &idx,
                                               index.session_id,
                                               e.sender);
                         // TODO: Check if this actually works and look in key backup
-                        olm::send_key_request_for(room_id_, e);
+                        auto copy    = e;
+                        copy.room_id = room_id_;
+                        if (pending_key_requests.count(e.content.session_id)) {
+                                pending_key_requests.at(e.content.session_id)
+                                  .events.push_back(copy);
+                        } else {
+                                PendingKeyRequests request;
+                                request.request_id =
+                                  "key_request." + http::client()->generate_txn_id();
+                                request.events.push_back(copy);
+                                olm::send_key_request_for(copy, request.request_id);
+                                pending_key_requests[e.content.session_id] = request;
+                        }
                         break;
+                }
                 case olm::DecryptionErrorCode::DbError:
                         nhlog::db()->critical(
                           "failed to retrieve megolm session with index ({}, {}, {})",
diff --git a/src/timeline/EventStore.h b/src/timeline/EventStore.h
index 7f8e2396..2d5fb1be 100644
--- a/src/timeline/EventStore.h
+++ b/src/timeline/EventStore.h
@@ -104,6 +104,7 @@ signals:
 
 public slots:
         void addPending(mtx::events::collections::TimelineEvents event);
+        void receivedSessionKey(const std::string &session_id);
         void clearTimeline();
 
 private:
@@ -121,6 +122,13 @@ private:
         static QCache<Index, mtx::events::collections::TimelineEvents> events_;
         static QCache<IdIndex, mtx::events::collections::TimelineEvents> events_by_id_;
 
+        struct PendingKeyRequests
+        {
+                std::string request_id;
+                std::vector<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>> events;
+        };
+        std::map<std::string, PendingKeyRequests> pending_key_requests;
+
         std::string current_txn;
         int current_txn_error_count = 0;
         bool noMoreMessages         = false;
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 9f250b33..e1fb9196 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -264,6 +264,10 @@ public slots:
         }
         void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
         void clearTimeline() { events.clearTimeline(); }
+        void receivedSessionKey(const std::string &session_key)
+        {
+                events.receivedSessionKey(session_key);
+        }
 
         QString roomName() const;
         QString roomTopic() const;
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 783584c9..1e8ed243 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -441,6 +441,15 @@ TimelineViewManager::updateReadReceipts(const QString &room_id,
 }
 
 void
+TimelineViewManager::receivedSessionKey(const std::string &room_id, const std::string &session_id)
+{
+        auto room = models.find(QString::fromStdString(room_id));
+        if (room != models.end()) {
+                room.value()->receivedSessionKey(session_id);
+        }
+}
+
+void
 TimelineViewManager::initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs)
 {
         for (const auto &e : msgs) {
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 5e441562..b6f8b443 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -92,6 +92,7 @@ signals:
 
 public slots:
         void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
+        void receivedSessionKey(const std::string &room_id, const std::string &session_id);
         void initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs);
 
         void setHistoryView(const QString &room_id);