summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-06-10 20:03:45 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-06-10 20:03:45 +0300
commit626c68091126f84819091840a011c50e26dcbd8d (patch)
tree132afdb12f858a6a2a20e00e0c2a0417caf4ae13 /include
parentMigrate to mtxclient for the http calls (diff)
downloadnheko-626c68091126f84819091840a011c50e26dcbd8d.tar.xz
Add support for displaying decrypted messages
Diffstat (limited to 'include')
-rw-r--r--include/Cache.h131
-rw-r--r--include/ChatPage.h8
-rw-r--r--include/Logging.hpp3
-rw-r--r--include/MainWindow.h1
-rw-r--r--include/MatrixClient.h5
-rw-r--r--include/Olm.hpp65
-rw-r--r--include/timeline/TimelineView.h3
7 files changed, 211 insertions, 5 deletions
diff --git a/include/Cache.h b/include/Cache.h

index afc7a148..994a6da7 100644 --- a/include/Cache.h +++ b/include/Cache.h
@@ -17,13 +17,16 @@ #pragma once -#include <QDebug> #include <QDir> #include <QImage> + #include <json.hpp> #include <lmdb++.h> #include <mtx/events/join_rules.hpp> #include <mtx/responses.hpp> +#include <mtxclient/crypto/client.hpp> +#include <mutex> + using mtx::events::state::JoinRule; struct RoomMember @@ -140,6 +143,83 @@ struct RoomSearchResult Q_DECLARE_METATYPE(RoomSearchResult) Q_DECLARE_METATYPE(RoomInfo) +// Extra information associated with an outbound megolm session. +struct OutboundGroupSessionData +{ + std::string session_id; + std::string session_key; + uint64_t message_index = 0; +}; + +inline void +to_json(nlohmann::json &obj, const OutboundGroupSessionData &msg) +{ + obj["session_id"] = msg.session_id; + obj["session_key"] = msg.session_key; + obj["message_index"] = msg.message_index; +} + +inline void +from_json(const nlohmann::json &obj, OutboundGroupSessionData &msg) +{ + msg.session_id = obj.at("session_id"); + msg.session_key = obj.at("session_key"); + msg.message_index = obj.at("message_index"); +} + +struct OutboundGroupSessionDataRef +{ + OlmOutboundGroupSession *session; + OutboundGroupSessionData data; +}; + +struct DevicePublicKeys +{ + std::string ed25519; + std::string curve25519; +}; + +inline void +to_json(nlohmann::json &obj, const DevicePublicKeys &msg) +{ + obj["ed25519"] = msg.ed25519; + obj["curve25519"] = msg.curve25519; +} + +inline void +from_json(const nlohmann::json &obj, DevicePublicKeys &msg) +{ + msg.ed25519 = obj.at("ed25519"); + msg.curve25519 = obj.at("curve25519"); +} + +//! Represents a unique megolm session identifier. +struct MegolmSessionIndex +{ + //! The room in which this session exists. + std::string room_id; + //! The session_id of the megolm session. + std::string session_id; + //! The curve25519 public key of the sender. + std::string sender_key; + + //! Representation to be used in a hash map. + std::string to_hash() const { return room_id + session_id + sender_key; } +}; + +struct OlmSessionStorage +{ + std::map<std::string, mtx::crypto::OlmSessionPtr> outbound_sessions; + std::map<std::string, mtx::crypto::InboundGroupSessionPtr> group_inbound_sessions; + std::map<std::string, mtx::crypto::OutboundGroupSessionPtr> group_outbound_sessions; + std::map<std::string, OutboundGroupSessionData> group_outbound_session_data; + + // Guards for accessing critical data. + std::mutex outbound_mtx; + std::mutex group_outbound_mtx; + std::mutex group_inbound_mtx; +}; + class Cache : public QObject { Q_OBJECT @@ -260,6 +340,48 @@ public: //! Check if we have sent a desktop notification for the given event id. bool isNotificationSent(const std::string &event_id); + //! Mark a room that uses e2e encryption. + void setEncryptedRoom(const std::string &room_id); + //! Save the public keys for a device. + void saveDeviceKeys(const std::string &device_id); + void getDeviceKeys(const std::string &device_id); + + //! Save the device list for a user. + void setDeviceList(const std::string &user_id, const std::vector<std::string> &devices); + std::vector<std::string> getDeviceList(const std::string &user_id); + + // + // Outbound Megolm Sessions + // + void saveOutboundMegolmSession(const MegolmSessionIndex &index, + const OutboundGroupSessionData &data, + mtx::crypto::OutboundGroupSessionPtr session); + OutboundGroupSessionDataRef getOutboundMegolmSession(const MegolmSessionIndex &index); + bool outboundMegolmSessionExists(const MegolmSessionIndex &index) noexcept; + + // + // Inbound Megolm Sessions + // + void saveInboundMegolmSession(const MegolmSessionIndex &index, + mtx::crypto::InboundGroupSessionPtr session); + OlmInboundGroupSession *getInboundMegolmSession(const MegolmSessionIndex &index); + bool inboundMegolmSessionExists(const MegolmSessionIndex &index) noexcept; + + // + // Outbound Olm Sessions + // + void saveOutboundOlmSession(const std::string &curve25519, + mtx::crypto::OlmSessionPtr session); + OlmSession *getOutboundOlmSession(const std::string &curve25519); + bool outboundOlmSessionsExists(const std::string &curve25519) noexcept; + + void saveOlmAccount(const std::string &pickled); + std::string restoreOlmAccount(); + + void restoreSessions(); + + OlmSessionStorage session_storage; + private: //! Save an invited room. void saveInvite(lmdb::txn &txn, @@ -451,6 +573,13 @@ private: lmdb::dbi readReceiptsDb_; lmdb::dbi notificationsDb_; + lmdb::dbi devicesDb_; + lmdb::dbi deviceKeysDb_; + + lmdb::dbi inboundMegolmSessionDb_; + lmdb::dbi outboundMegolmSessionDb_; + lmdb::dbi outboundOlmSessionDb_; + QString localUserId_; QString cacheDirectory_; }; diff --git a/include/ChatPage.h b/include/ChatPage.h
index e99e94ba..d8582993 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h
@@ -29,8 +29,7 @@ #include "Cache.h" #include "CommunitiesList.h" #include "Community.h" - -#include <mtx.hpp> +#include "MatrixClient.h" class OverlayModal; class QuickSwitcher; @@ -119,6 +118,7 @@ signals: void loggedOut(); void trySyncCb(); + void tryDelayedSyncCb(); void tryInitialSyncCb(); void leftRoom(const QString &room_id); @@ -146,8 +146,12 @@ private slots: private: static ChatPage *instance_; + //! Handler callback for initial sync. It doesn't run on the main thread so all + //! communication with the GUI should be done through signals. + void initialSyncHandler(const mtx::responses::Sync &res, mtx::http::RequestErr err); void tryInitialSync(); void trySync(); + void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts); //! Check if the given room is currently open. bool isRoomActive(const QString &room_id) diff --git a/include/Logging.hpp b/include/Logging.hpp
index c301d80d..bdbd3e2c 100644 --- a/include/Logging.hpp +++ b/include/Logging.hpp
@@ -15,4 +15,7 @@ net(); std::shared_ptr<spdlog::logger> db(); + +std::shared_ptr<spdlog::logger> +crypto(); } diff --git a/include/MainWindow.h b/include/MainWindow.h
index f0fa9a08..b068e8f6 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h
@@ -59,7 +59,6 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); static MainWindow *instance() { return instance_; }; void saveCurrentWindowSize(); diff --git a/include/MatrixClient.h b/include/MatrixClient.h
index 832d6cad..7ea5e0b7 100644 --- a/include/MatrixClient.h +++ b/include/MatrixClient.h
@@ -11,12 +11,15 @@ Q_DECLARE_METATYPE(mtx::responses::Notifications) Q_DECLARE_METATYPE(mtx::responses::Rooms) Q_DECLARE_METATYPE(mtx::responses::Sync) Q_DECLARE_METATYPE(std::string) -Q_DECLARE_METATYPE(std::vector<std::string>); +Q_DECLARE_METATYPE(std::vector<std::string>) namespace http { namespace v2 { mtx::http::Client * client(); + +bool +is_logged_in(); } //! Initialize the http module diff --git a/include/Olm.hpp b/include/Olm.hpp new file mode 100644
index 00000000..2f7b1d64 --- /dev/null +++ b/include/Olm.hpp
@@ -0,0 +1,65 @@ +#pragma once + +#include <memory> +#include <mtxclient/crypto/client.hpp> + +constexpr auto OLM_ALGO = "m.olm.v1.curve25519-aes-sha2"; + +namespace olm { + +struct OlmCipherContent +{ + std::string body; + uint8_t type; +}; + +inline void +from_json(const nlohmann::json &obj, OlmCipherContent &msg) +{ + msg.body = obj.at("body"); + msg.type = obj.at("type"); +} + +struct OlmMessage +{ + std::string sender_key; + std::string sender; + + using RecipientKey = std::string; + std::map<RecipientKey, OlmCipherContent> ciphertext; +}; + +inline void +from_json(const nlohmann::json &obj, OlmMessage &msg) +{ + if (obj.at("type") != "m.room.encrypted") + throw std::invalid_argument("invalid type for olm message"); + + if (obj.at("content").at("algorithm") != OLM_ALGO) + throw std::invalid_argument("invalid algorithm for olm message"); + + msg.sender = obj.at("sender"); + msg.sender_key = obj.at("content").at("sender_key"); + msg.ciphertext = + obj.at("content").at("ciphertext").get<std::map<std::string, OlmCipherContent>>(); +} + +mtx::crypto::OlmClient * +client(); + +void +handle_to_device_messages(const std::vector<nlohmann::json> &msgs); + +void +handle_olm_message(const OlmMessage &msg); + +void +handle_olm_normal_message(const std::string &sender, + const std::string &sender_key, + const OlmCipherContent &content); + +void +handle_pre_key_olm_message(const std::string &sender, + const std::string &sender_key, + const OlmCipherContent &content); +} // namespace olm diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h
index 30af97fb..88857222 100644 --- a/include/timeline/TimelineView.h +++ b/include/timeline/TimelineView.h
@@ -149,6 +149,9 @@ private: QWidget *relativeWidget(TimelineItem *item, int dt) const; + TimelineEvent parseEncryptedEvent( + const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e); + //! Callback for all message sending. void sendRoomMessageHandler(const std::string &txn_id, const mtx::responses::EventId &res,