[WIP] Room Verification Works!

This commit is contained in:
CH Chethan Reddy 2020-08-18 11:29:02 +05:30
parent 2e20049b36
commit 8a4bd37fea
9 changed files with 114 additions and 89 deletions

View file

@ -14,7 +14,7 @@ ApplicationWindow{
height: 650 height: 650
width: 420 width: 420
modality: Qt.WindowModal modality: Qt.WindowModal
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
palette: colors palette: colors
Connections{ Connections{

View file

@ -8,24 +8,31 @@
#include <QDateTime> #include <QDateTime>
#include <QTimer> #include <QTimer>
#include <iostream>
static constexpr int TIMEOUT = 2 * 60 * 1000; // 2 minutes static constexpr int TIMEOUT = 2 * 60 * 1000; // 2 minutes
namespace msgs = mtx::events::msg; namespace msgs = mtx::events::msg;
DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow::Type flow_type) DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
DeviceVerificationFlow::Type flow_type,
TimelineModel *model)
: type(flow_type) : type(flow_type)
, model_(model)
{ {
timeout = new QTimer(this); timeout = new QTimer(this);
timeout->setSingleShot(true); timeout->setSingleShot(true);
this->sas = olm::client()->sas_init(); this->sas = olm::client()->sas_init();
this->isMacVerified = false; this->isMacVerified = false;
connect(this->model_, if (model) {
&TimelineModel::updateFlowEventId, connect(this->model_,
this, &TimelineModel::updateFlowEventId,
[this](std::string event_id) { this->relation.in_reply_to.event_id = event_id; }); this,
[this](std::string event_id) {
this->relation.rel_type = mtx::common::RelationType::Reference;
this->relation.event_id = event_id;
this->transaction_id = event_id;
});
}
connect(timeout, &QTimer::timeout, this, [this]() { connect(timeout, &QTimer::timeout, this, [this]() {
emit timedout(); emit timedout();
@ -42,8 +49,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
if ((std::find(msg.key_agreement_protocols.begin(), if ((std::find(msg.key_agreement_protocols.begin(),
@ -69,8 +75,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
DeviceVerificationFlow::Error::UnknownMethod); DeviceVerificationFlow::Error::UnknownMethod);
return; return;
} }
this->acceptVerificationRequest();
this->canonical_json = nlohmann::json(msg); this->canonical_json = nlohmann::json(msg);
this->acceptVerificationRequest();
} else { } else {
this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod); this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
} }
@ -84,8 +90,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") && if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
@ -116,8 +121,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
emit verificationCanceled(); emit verificationCanceled();
@ -131,8 +135,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
this->sas->set_their_key(msg.key); this->sas->set_their_key(msg.key);
@ -157,6 +160,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
} else if (this->method == DeviceVerificationFlow::Method::Decimal) { } else if (this->method == DeviceVerificationFlow::Method::Decimal) {
this->sasList = this->sas->generate_bytes_decimal(info); this->sasList = this->sas->generate_bytes_decimal(info);
} }
if (this->sender == false) { if (this->sender == false) {
emit this->verificationRequestAccepted(this->method); emit this->verificationRequestAccepted(this->method);
this->sendVerificationKey(); this->sendVerificationKey();
@ -181,8 +185,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
std::string info = "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() + std::string info = "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() +
@ -227,12 +230,11 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
// this is just a workaround if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id =
msg.relates_to.value().in_reply_to.event_id;
if (msg.relates_to.value().in_reply_to.event_id !=
this->relation.in_reply_to.event_id)
return; return;
else {
this->deviceId = QString::fromStdString(msg.from_device);
}
} }
this->startVerificationRequest(); this->startVerificationRequest();
}); });
@ -245,8 +247,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow
if (msg.transaction_id.value() != this->transaction_id) if (msg.transaction_id.value() != this->transaction_id)
return; return;
} else if (msg.relates_to.has_value()) { } else if (msg.relates_to.has_value()) {
if (msg.relates_to.value().in_reply_to.event_id != if (msg.relates_to.value().event_id != this->relation.event_id)
this->relation.in_reply_to.event_id)
return; return;
} }
this->acceptDevice(); this->acceptDevice();
@ -297,12 +298,6 @@ DeviceVerificationFlow::getSasList()
return this->sasList; return this->sasList;
} }
void
DeviceVerificationFlow::setModel(TimelineModel *&model)
{
this->model_ = model;
}
void void
DeviceVerificationFlow::setTransactionId(QString transaction_id_) DeviceVerificationFlow::setTransactionId(QString transaction_id_)
{ {
@ -351,15 +346,17 @@ DeviceVerificationFlow::setType(Type type)
void void
DeviceVerificationFlow::setSender(bool sender_) DeviceVerificationFlow::setSender(bool sender_)
{ {
this->sender = sender_; this->sender = sender_;
this->transaction_id = http::client()->generate_txn_id(); if (this->sender)
this->transaction_id = http::client()->generate_txn_id();
} }
void void
DeviceVerificationFlow::setEventId(std::string event_id) DeviceVerificationFlow::setEventId(std::string event_id)
{ {
this->relation.in_reply_to.event_id = event_id; this->relation.rel_type = mtx::common::RelationType::Reference;
this->transaction_id = event_id; this->relation.event_id = event_id;
this->transaction_id = event_id;
} }
//! accepts a verification //! accepts a verification
@ -476,7 +473,8 @@ DeviceVerificationFlow::startVerificationRequest()
static_cast<int>(err->status_code)); static_cast<int>(err->status_code));
}); });
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) { } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
req.relates_to = this->relation; req.relates_to = this->relation;
this->canonical_json = nlohmann::json(req);
(model_)->sendMessage(req); (model_)->sendMessage(req);
} }
} }
@ -562,6 +560,7 @@ DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_c
} else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) { } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
req.relates_to = this->relation; req.relates_to = this->relation;
(model_)->sendMessage(req); (model_)->sendMessage(req);
this->deleteLater();
} }
// TODO : Handle Blocking user better // TODO : Handle Blocking user better

View file

@ -52,7 +52,8 @@ public:
DeviceVerificationFlow( DeviceVerificationFlow(
QObject *parent = nullptr, QObject *parent = nullptr,
DeviceVerificationFlow::Type = DeviceVerificationFlow::Type::ToDevice); DeviceVerificationFlow::Type = DeviceVerificationFlow::Type::ToDevice,
TimelineModel *model = nullptr);
// getters // getters
QString getTransactionId(); QString getTransactionId();
QString getUserId(); QString getUserId();
@ -62,7 +63,6 @@ public:
std::vector<int> getSasList(); std::vector<int> getSasList();
bool getSender(); bool getSender();
// setters // setters
void setModel(TimelineModel *&model);
void setTransactionId(QString transaction_id_); void setTransactionId(QString transaction_id_);
void setUserId(QString userID); void setUserId(QString userID);
void setDeviceId(QString deviceID); void setDeviceId(QString deviceID);
@ -127,5 +127,5 @@ private:
std::optional<std::string> room_id; std::optional<std::string> room_id;
std::optional<std::string> event_id; std::optional<std::string> event_id;
TimelineModel *model_; TimelineModel *model_;
mtx::common::ReplyRelatesTo relation; mtx::common::ReactionRelatesTo relation;
}; };

View file

@ -211,10 +211,15 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
// relations shouldn't be encrypted... // relations shouldn't be encrypted...
mtx::common::ReplyRelatesTo relation; mtx::common::ReplyRelatesTo relation;
mtx::common::ReactionRelatesTo r_relation;
if (body["content"].contains("m.relates_to") && if (body["content"].contains("m.relates_to") &&
body["content"]["m.relates_to"].contains("m.in_reply_to")) { body["content"]["m.relates_to"].contains("m.in_reply_to")) {
relation = body["content"]["m.relates_to"]; relation = body["content"]["m.relates_to"];
body["content"].erase("m.relates_to"); body["content"].erase("m.relates_to");
} else if (body["content"]["m.relates_to"].contains("event_id")) {
r_relation = body["content"]["m.relates_to"];
body["content"].erase("m.relates_to");
} }
// Always check before for existence. // Always check before for existence.
@ -223,12 +228,13 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
// Prepare the m.room.encrypted event. // Prepare the m.room.encrypted event.
msg::Encrypted data; msg::Encrypted data;
data.ciphertext = std::string((char *)payload.data(), payload.size()); data.ciphertext = std::string((char *)payload.data(), payload.size());
data.sender_key = olm::client()->identity_keys().curve25519; data.sender_key = olm::client()->identity_keys().curve25519;
data.session_id = res.data.session_id; data.session_id = res.data.session_id;
data.device_id = device_id; data.device_id = device_id;
data.algorithm = MEGOLM_ALGO; data.algorithm = MEGOLM_ALGO;
data.relates_to = relation; data.relates_to = relation;
data.r_relates_to = r_relation;
auto message_index = olm_outbound_group_session_message_index(res.session); auto message_index = olm_outbound_group_session_message_index(res.session);
nhlog::crypto()->debug("next message_index {}", message_index); nhlog::crypto()->debug("next message_index {}", message_index);

View file

@ -95,8 +95,8 @@ EventStore::EventStore(std::string room_id, QObject *)
room_id_, room_id_,
txn_id, txn_id,
e.content, e.content,
[this, txn_id](const mtx::responses::EventId &event_id, [this, txn_id, e](const mtx::responses::EventId &event_id,
mtx::http::RequestErr err) { mtx::http::RequestErr err) {
if (err) { if (err) {
const int status_code = const int status_code =
static_cast<int>(err->status_code); static_cast<int>(err->status_code);
@ -108,7 +108,21 @@ EventStore::EventStore(std::string room_id, QObject *)
emit messageFailed(txn_id); emit messageFailed(txn_id);
return; return;
} }
emit messageSent(txn_id, event_id.event_id.to_string()); emit messageSent(txn_id, event_id.event_id.to_string());
if constexpr (mtx::events::message_content_to_type<
decltype(e.content)> ==
mtx::events::EventType::RoomEncrypted) {
auto event =
decryptEvent({room_id_, e.event_id}, e);
if (auto dec =
std::get_if<mtx::events::RoomEvent<
mtx::events::msg::
KeyVerificationRequest>>(event)) {
emit updateFlowEventId(
event_id.event_id.to_string());
}
}
}); });
}, },
event->data); event->data);
@ -318,12 +332,12 @@ EventStore::reactions(const std::string &event_id)
if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>( if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
related_event)) { related_event)) {
auto &agg = aggregation[reaction->content.relates_to.key]; auto &agg = aggregation[reaction->content.relates_to.key.value()];
if (agg.count == 0) { if (agg.count == 0) {
Reaction temp{}; Reaction temp{};
temp.key_ = temp.key_ =
QString::fromStdString(reaction->content.relates_to.key); QString::fromStdString(reaction->content.relates_to.key.value());
reactions.push_back(temp); reactions.push_back(temp);
} }

View file

@ -100,6 +100,7 @@ signals:
void messageFailed(std::string txn_id); void messageFailed(std::string txn_id);
void startDMVerification( void startDMVerification(
mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg); mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg);
void updateFlowEventId(std::string event_id);
public slots: public slots:
void addPending(mtx::events::collections::TimelineEvents event); void addPending(mtx::events::collections::TimelineEvents event);

View file

@ -22,8 +22,6 @@
#include "Utils.h" #include "Utils.h"
#include "dialogs/RawMessage.h" #include "dialogs/RawMessage.h"
#include <iostream>
Q_DECLARE_METATYPE(QModelIndex) Q_DECLARE_METATYPE(QModelIndex)
namespace std { namespace std {
@ -237,6 +235,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
[this](mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> msg) { [this](mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> msg) {
ChatPage::instance()->recievedRoomDeviceVerificationRequest(msg, this); ChatPage::instance()->recievedRoomDeviceVerificationRequest(msg, this);
}); });
connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
this->updateFlowEventId(event_id);
});
} }
QHash<int, QByteArray> QHash<int, QByteArray>
@ -814,7 +815,6 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg)
json doc = { json doc = {
{"type", to_string(msg.type)}, {"content", json(msg.content)}, {"room_id", room_id}}; {"type", to_string(msg.type)}, {"content", json(msg.content)}, {"room_id", room_id}};
std::cout << doc.dump(2) << std::endl;
try { try {
// Check if we have already an outbound megolm session then we can use. // Check if we have already an outbound megolm session then we can use.
@ -1095,7 +1095,6 @@ struct SendMessageVisitor
void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg) void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
{ {
emit model_->updateFlowEventId(msg.event_id);
model_->sendEncryptedMessage(msg); model_->sendEncryptedMessage(msg);
} }
void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg) void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)

View file

@ -194,13 +194,12 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
[this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message, [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
TimelineModel *model) { TimelineModel *model) {
if (!(this->dvList->exist(QString::fromStdString(message.event_id)))) { if (!(this->dvList->exist(QString::fromStdString(message.event_id)))) {
auto flow = auto flow = new DeviceVerificationFlow(
new DeviceVerificationFlow(this, DeviceVerificationFlow::Type::RoomMsg); this, DeviceVerificationFlow::Type::RoomMsg, model);
if (std::find(message.content.methods.begin(), if (std::find(message.content.methods.begin(),
message.content.methods.end(), message.content.methods.end(),
mtx::events::msg::VerificationMethods::SASv1) != mtx::events::msg::VerificationMethods::SASv1) !=
message.content.methods.end()) { message.content.methods.end()) {
flow->setModel(model);
flow->setEventId(message.event_id); flow->setEventId(message.event_id);
emit newDeviceVerificationRequest( emit newDeviceVerificationRequest(
std::move(flow), std::move(flow),
@ -241,42 +240,48 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
&ChatPage::recievedDeviceVerificationStart, &ChatPage::recievedDeviceVerificationStart,
this, this,
[this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) { [this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) {
if (!(this->dvList->exist(QString::fromStdString(msg.transaction_id.value())))) { if (msg.transaction_id.has_value()) {
auto flow = new DeviceVerificationFlow(this); if (!(this->dvList->exist(
flow->canonical_json = nlohmann::json(msg); QString::fromStdString(msg.transaction_id.value())))) {
if ((std::find(msg.key_agreement_protocols.begin(), auto flow = new DeviceVerificationFlow(this);
msg.key_agreement_protocols.end(), flow->canonical_json = nlohmann::json(msg);
"curve25519-hkdf-sha256") != if ((std::find(msg.key_agreement_protocols.begin(),
msg.key_agreement_protocols.end()) && msg.key_agreement_protocols.end(),
(std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") != "curve25519-hkdf-sha256") !=
msg.hashes.end()) && msg.key_agreement_protocols.end()) &&
(std::find(msg.message_authentication_codes.begin(), (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") !=
msg.message_authentication_codes.end(), msg.hashes.end()) &&
"hmac-sha256") != (std::find(msg.message_authentication_codes.begin(),
msg.message_authentication_codes.end())) { msg.message_authentication_codes.end(),
if (std::find(msg.short_authentication_string.begin(), "hmac-sha256") !=
msg.short_authentication_string.end(), msg.message_authentication_codes.end())) {
mtx::events::msg::SASMethods::Emoji) != if (std::find(msg.short_authentication_string.begin(),
msg.short_authentication_string.end()) { msg.short_authentication_string.end(),
flow->setMethod(DeviceVerificationFlow::Method::Emoji); mtx::events::msg::SASMethods::Emoji) !=
} else if (std::find(msg.short_authentication_string.begin(), msg.short_authentication_string.end()) {
flow->setMethod(
DeviceVerificationFlow::Method::Emoji);
} else if (std::find(
msg.short_authentication_string.begin(),
msg.short_authentication_string.end(), msg.short_authentication_string.end(),
mtx::events::msg::SASMethods::Decimal) != mtx::events::msg::SASMethods::Decimal) !=
msg.short_authentication_string.end()) { msg.short_authentication_string.end()) {
flow->setMethod(DeviceVerificationFlow::Method::Decimal); flow->setMethod(
DeviceVerificationFlow::Method::Decimal);
} else {
flow->cancelVerification(
DeviceVerificationFlow::Error::UnknownMethod);
return;
}
emit newDeviceVerificationRequest(
std::move(flow),
QString::fromStdString(msg.transaction_id.value()),
QString::fromStdString(sender),
QString::fromStdString(msg.from_device));
} else { } else {
flow->cancelVerification( flow->cancelVerification(
DeviceVerificationFlow::Error::UnknownMethod); DeviceVerificationFlow::Error::UnknownMethod);
return;
} }
emit newDeviceVerificationRequest(
std::move(flow),
QString::fromStdString(msg.transaction_id.value()),
QString::fromStdString(sender),
QString::fromStdString(msg.from_device));
} else {
flow->cancelVerification(
DeviceVerificationFlow::Error::UnknownMethod);
} }
} }
}); });

View file

@ -211,8 +211,9 @@ UserProfile::createFlow(bool isVerifyUser)
<< std::endl; << std::endl;
if (this->roomid_.toStdString() == room_id) { if (this->roomid_.toStdString() == room_id) {
auto newflow = new DeviceVerificationFlow( auto newflow = new DeviceVerificationFlow(
this, DeviceVerificationFlow::Type::RoomMsg); this,
newflow->setModel(this->model); DeviceVerificationFlow::Type::RoomMsg,
this->model);
return (std::move(newflow)); return (std::move(newflow));
} else { } else {
std::cout << "FOUND A ENCRYPTED ROOM BUT CURRENTLY " std::cout << "FOUND A ENCRYPTED ROOM BUT CURRENTLY "