From a2979c2df1b2059e2e8a969f5c1a3a804bd2550c Mon Sep 17 00:00:00 2001 From: CH Chethan Reddy <40890937+Chethan2k1@users.noreply.github.com> Date: Mon, 6 Jul 2020 21:32:21 +0530 Subject: [PATCH] Updating keys of outdated encrypted users --- src/Cache.cpp | 56 ++++++++++++++++++++++++++++------ src/Cache.h | 3 ++ src/CacheCryptoStructs.h | 29 +++++++++++++++--- src/Cache_p.h | 5 +-- src/DeviceVerificationFlow.cpp | 8 ++--- src/ui/UserProfile.cpp | 17 +++++------ src/ui/UserProfile.h | 3 +- 7 files changed, 89 insertions(+), 32 deletions(-) diff --git a/src/Cache.cpp b/src/Cache.cpp index 553d1e97..1008277a 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -31,8 +31,10 @@ #include "Cache.h" #include "Cache_p.h" +#include "ChatPage.h" #include "EventAccessors.h" #include "Logging.h" +#include "MatrixClient.h" #include "Utils.h" //! Should be changed when a breaking change occurs in the cache format. @@ -1009,6 +1011,8 @@ Cache::saveState(const mtx::responses::Sync &res) savePresence(txn, res.presence); + updateUserCache(res.device_lists); + removeLeftRooms(txn, res.rooms.leave); txn.commit(); @@ -2885,17 +2889,13 @@ Cache::statusMessage(const std::string &user_id) void to_json(json &j, const UserCache &info) { - j["is_user_verified"] = info.is_user_verified; - j["cross_verified"] = info.cross_verified; - j["keys"] = info.keys; + j["keys"] = info.keys; } void from_json(const json &j, UserCache &info) { - info.is_user_verified = j.at("is_user_verified"); - info.cross_verified = j.at("cross_verified").get>(); - info.keys = j.at("keys").get(); + info.keys = j.at("keys").get(); } std::optional @@ -2932,6 +2932,32 @@ Cache::setUserCache(const std::string &user_id, const UserCache &body) return res; } +void +Cache::updateUserCache(const mtx::responses::DeviceLists body) +{ + for (auto user_id : body.changed) { + mtx::requests::QueryKeys req; + req.device_keys[user_id] = {}; + + http::client()->query_keys( + req, + [user_id, this](const mtx::responses::QueryKeys res, mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to query device keys: {},{}", + err->matrix_error.errcode, + static_cast(err->status_code)); + return; + } + + setUserCache(user_id, UserCache{std::move(res)}); + }); + } + + for (std::string user_id : body.left) { + deleteUserCache(user_id); + } +} + int Cache::deleteUserCache(const std::string &user_id) { @@ -2947,15 +2973,19 @@ Cache::deleteUserCache(const std::string &user_id) void to_json(json &j, const DeviceVerifiedCache &info) { - j["device_verified"] = info.device_verified; - j["device_blocked"] = info.device_blocked; + j["is_user_verified"] = info.is_user_verified; + j["cross_verified"] = info.cross_verified; + j["device_verified"] = info.device_verified; + j["device_blocked"] = info.device_blocked; } void from_json(const json &j, DeviceVerifiedCache &info) { - info.device_verified = j.at("device_verified").get>(); - info.device_blocked = j.at("device_blocked").get>(); + info.is_user_verified = j.at("is_user_verified"); + info.cross_verified = j.at("cross_verified").get>(); + info.device_verified = j.at("device_verified").get>(); + info.device_blocked = j.at("device_blocked").get>(); } std::optional @@ -3178,6 +3208,12 @@ getUserCache(const std::string &user_id) return instance_->getUserCache(user_id); } +void +updateUserCache(const mtx::responses::DeviceLists body) +{ + instance_->updateUserCache(body); +} + int setUserCache(const std::string &user_id, const UserCache &body) { diff --git a/src/Cache.h b/src/Cache.h index 0c955c92..82d909ae 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -64,6 +64,9 @@ statusMessage(const std::string &user_id); std::optional getUserCache(const std::string &user_id); +void +updateUserCache(const mtx::responses::DeviceLists body); + int setUserCache(const std::string &user_id, const UserCache &body); diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h index 241cac76..ba746f59 100644 --- a/src/CacheCryptoStructs.h +++ b/src/CacheCryptoStructs.h @@ -66,14 +66,16 @@ struct OlmSessionStorage std::mutex group_inbound_mtx; }; +// this will store the keys of the user with whom a encrypted room is shared with struct UserCache { - //! this stores if the user is verified (with cross-signing) - bool is_user_verified = false; - //! list of verified device_ids with cross-signing - std::vector cross_verified; //! map of public key key_ids and their public_key mtx::responses::QueryKeys keys; + + UserCache(mtx::responses::QueryKeys res) + : keys(res) + {} + UserCache() {} }; void @@ -81,11 +83,30 @@ to_json(nlohmann::json &j, const UserCache &info); void from_json(const nlohmann::json &j, UserCache &info); +// the reason these are stored in a seperate cache rather than storing it in the user cache is +// UserCache stores only keys of users with which encrypted room is shared struct DeviceVerifiedCache { //! list of verified device_ids with device-verification std::vector device_verified; + //! list of verified device_ids with cross-signing + std::vector cross_verified; + //! list of devices the user blocks std::vector device_blocked; + //! this stores if the user is verified (with cross-signing) + bool is_user_verified = false; + + DeviceVerifiedCache(std::vector device_verified_, + std::vector cross_verified_, + std::vector device_blocked_, + bool is_user_verified_ = false) + : device_verified(device_verified_) + , cross_verified(cross_verified_) + , device_blocked(device_blocked_) + , is_user_verified(is_user_verified_) + {} + + DeviceVerifiedCache() {} }; void diff --git a/src/Cache_p.h b/src/Cache_p.h index 60fa930f..f75b0f4e 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -56,6 +56,7 @@ public: // user cache stores user keys std::optional getUserCache(const std::string &user_id); + void updateUserCache(const mtx::responses::DeviceLists body); int setUserCache(const std::string &user_id, const UserCache &body); int deleteUserCache(const std::string &user_id); @@ -521,12 +522,12 @@ private: lmdb::dbi getUserCacheDb(lmdb::txn &txn) { - return lmdb::dbi::open(txn, std::string("user_cache").c_str(), MDB_CREATE); + return lmdb::dbi::open(txn, "user_cache", MDB_CREATE); } lmdb::dbi getDeviceVerifiedDb(lmdb::txn &txn) { - return lmdb::dbi::open(txn, std::string("verified").c_str(), MDB_CREATE); + return lmdb::dbi::open(txn, "verified", MDB_CREATE); } //! Retrieves or creates the database that stores the open OLM sessions between our device diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp index 7829c41d..0122e691 100644 --- a/src/DeviceVerificationFlow.cpp +++ b/src/DeviceVerificationFlow.cpp @@ -477,7 +477,7 @@ DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_c } else { cache::setVerifiedCache( this->userId.toStdString(), - DeviceVerifiedCache{{}, {this->deviceId.toStdString()}}); + DeviceVerifiedCache{{}, {}, {this->deviceId.toStdString()}}); } this->deleteLater(); }); @@ -564,8 +564,9 @@ DeviceVerificationFlow::acceptDevice() } cache::setVerifiedCache(this->userId.toStdString(), verified_cache.value()); } else { - cache::setVerifiedCache(this->userId.toStdString(), - DeviceVerifiedCache{{this->deviceId.toStdString()}, {}}); + cache::setVerifiedCache( + this->userId.toStdString(), + DeviceVerifiedCache{{this->deviceId.toStdString()}, {}, {}}); } emit deviceVerified(); @@ -616,5 +617,4 @@ DeviceVerificationFlow::unverify() } emit refreshProfile(); - this->deleteLater(); } diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp index b4938e8d..6ae04d0b 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp @@ -77,8 +77,7 @@ UserProfile::avatarUrl() void UserProfile::callback_fn(const mtx::responses::QueryKeys &res, mtx::http::RequestErr err, - std::string user_id, - std::optional> cross_verified) + std::string user_id) { if (err) { nhlog::net()->warn("failed to query device keys: {},{}", @@ -101,16 +100,15 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res, // TODO: Verify signatures and ignore those that don't pass. verification::Status verified = verification::Status::UNVERIFIED; - if (cross_verified.has_value()) { - if (std::find(cross_verified->begin(), cross_verified->end(), d.first) != - cross_verified->end()) + if (device_verified.has_value()) { + if (std::find(device_verified->cross_verified.begin(), + device_verified->cross_verified.end(), + d.first) != device_verified->cross_verified.end()) verified = verification::Status::VERIFIED; - } else if (device_verified.has_value()) { if (std::find(device_verified->device_verified.begin(), device_verified->device_verified.end(), d.first) != device_verified->device_verified.end()) verified = verification::Status::VERIFIED; - } else if (device_verified.has_value()) { if (std::find(device_verified->device_blocked.begin(), device_verified->device_blocked.end(), d.first) != device_verified->device_blocked.end()) @@ -138,8 +136,7 @@ UserProfile::fetchDeviceList(const QString &userID) auto user_cache = cache::getUserCache(userID.toStdString()); if (user_cache.has_value()) { - this->callback_fn( - user_cache->keys, {}, userID.toStdString(), user_cache->cross_verified); + this->callback_fn(user_cache->keys, {}, userID.toStdString()); } else { mtx::requests::QueryKeys req; req.device_keys[userID.toStdString()] = {}; @@ -147,7 +144,7 @@ UserProfile::fetchDeviceList(const QString &userID) req, [user_id = userID.toStdString(), this](const mtx::responses::QueryKeys &res, mtx::http::RequestErr err) { - this->callback_fn(res, err, user_id, {}); + this->callback_fn(res, err, user_id); }); } } diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h index 99c6a755..4e048400 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h @@ -103,6 +103,5 @@ private: void callback_fn(const mtx::responses::QueryKeys &res, mtx::http::RequestErr err, - std::string user_id, - std::optional> cross_verified); + std::string user_id); };