Fix in room verification

This commit is contained in:
Nicolas Werner 2020-10-06 17:02:41 +02:00
parent 8a4d85f801
commit 64d5a193f1
5 changed files with 103 additions and 107 deletions

View File

@ -7,6 +7,8 @@ import im.nheko 1.0
ApplicationWindow { ApplicationWindow {
property var flow property var flow
onClosing: TimelineManager.removeVerificationFlow(flow)
title: stack.currentItem.title title: stack.currentItem.title
id: dialog id: dialog

View File

@ -13,6 +13,15 @@ static constexpr int TIMEOUT = 2 * 60 * 1000; // 2 minutes
namespace msgs = mtx::events::msg; namespace msgs = mtx::events::msg;
static mtx::events::msg::KeyVerificationMac
key_verification_mac(mtx::crypto::SAS *sas,
mtx::identifiers::User sender,
const std::string &senderDevice,
mtx::identifiers::User receiver,
const std::string &receiverDevice,
const std::string &transactionId,
std::map<std::string, std::string> keys);
DeviceVerificationFlow::DeviceVerificationFlow(QObject *, DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
DeviceVerificationFlow::Type flow_type, DeviceVerificationFlow::Type flow_type,
TimelineModel *model, TimelineModel *model,
@ -45,11 +54,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
return; return;
} }
for (const auto &[algorithm, key] : this->their_keys = res;
res.device_keys.at(deviceId.toStdString()).keys) {
// TODO: Verify Signatures
this->device_keys[algorithm] = key;
}
}); });
if (model) { if (model) {
@ -115,7 +120,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
return; return;
} }
error_ = User; error_ = User;
Emit errorChanged(); emit errorChanged();
setState(Failed); setState(Failed);
}); });
@ -160,6 +165,8 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
"|" + this->transaction_id; "|" + this->transaction_id;
} }
nhlog::ui()->info("Info is: '{}'", info);
if (this->sender == false) { if (this->sender == false) {
this->sendVerificationKey(); this->sendVerificationKey();
} else { } else {
@ -193,28 +200,40 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
if (msg.relates_to.value().event_id != this->relation.event_id) if (msg.relates_to.value().event_id != this->relation.event_id)
return; return;
} }
std::string info = "MATRIX_KEY_VERIFICATION_MAC" + this->toClient.to_string() +
this->deviceId.toStdString() +
http::client()->user_id().to_string() +
http::client()->device_id() + this->transaction_id;
std::vector<std::string> key_list; std::map<std::string, std::string> key_list;
std::string key_string; std::string key_string;
for (auto mac : msg.mac) { for (const auto &mac : msg.mac) {
key_string += mac.first + ","; for (const auto &[deviceid, key] : their_keys.device_keys)
if (device_keys[mac.first] != "") { if (key.keys.count(mac.first))
if (mac.second == key_list[mac.first] = key.keys.at(mac.first);
this->sas->calculate_mac(this->device_keys[mac.first],
info + mac.first)) { if (their_keys.master_keys.keys.count(mac.first))
} else { key_list[mac.first] = their_keys.master_keys.keys[mac.first];
this->cancelVerification( if (their_keys.user_signing_keys.keys.count(mac.first))
DeviceVerificationFlow::Error::KeyMismatch); key_list[mac.first] =
return; their_keys.user_signing_keys.keys[mac.first];
} if (their_keys.self_signing_keys.keys.count(mac.first))
key_list[mac.first] =
their_keys.self_signing_keys.keys[mac.first];
}
auto macs = key_verification_mac(sas.get(),
toClient,
this->deviceId.toStdString(),
http::client()->user_id(),
http::client()->device_id(),
this->transaction_id,
key_list);
for (const auto &[key, mac] : macs.mac) {
if (mac != msg.mac.at(key)) {
this->cancelVerification(
DeviceVerificationFlow::Error::KeyMismatch);
return;
} }
} }
key_string = key_string.substr(0, key_string.length() - 1);
if (msg.keys == this->sas->calculate_mac(key_string, info + "KEY_IDS")) { if (msg.keys == macs.keys) {
this->isMacVerified = true; this->isMacVerified = true;
this->acceptDevice(); this->acceptDevice();
} else { } else {
@ -630,9 +649,13 @@ DeviceVerificationFlow::NewInRoomVerification(QObject *parent_,
QString event_id_) QString event_id_)
{ {
QSharedPointer<DeviceVerificationFlow> flow( QSharedPointer<DeviceVerificationFlow> flow(
new DeviceVerificationFlow(parent_, Type::RoomMsg, timelineModel_, other_user_, "")); new DeviceVerificationFlow(parent_,
Type::RoomMsg,
timelineModel_,
other_user_,
QString::fromStdString(msg.from_device)));
flow->event_id = event_id_.toStdString(); flow->setEventId(event_id_.toStdString());
if (std::find(msg.methods.begin(), if (std::find(msg.methods.begin(),
msg.methods.end(), msg.methods.end(),

View File

@ -56,7 +56,6 @@ using sas_ptr = std::unique_ptr<mtx::crypto::SAS>;
class DeviceVerificationFlow : public QObject class DeviceVerificationFlow : public QObject
{ {
Q_OBJECT Q_OBJECT
// Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
Q_PROPERTY(QString state READ state NOTIFY stateChanged) Q_PROPERTY(QString state READ state NOTIFY stateChanged)
Q_PROPERTY(Error error READ error NOTIFY errorChanged) Q_PROPERTY(Error error READ error NOTIFY errorChanged)
Q_PROPERTY(QString userId READ getUserId CONSTANT) Q_PROPERTY(QString userId READ getUserId CONSTANT)
@ -179,11 +178,7 @@ private:
//! Completes the verification flow //! Completes the verification flow
void acceptDevice(); void acceptDevice();
// for to_device messages
std::string transaction_id; std::string transaction_id;
// for room messages
std::optional<std::string> room_id;
std::optional<std::string> event_id;
bool sender; bool sender;
Type type; Type type;
@ -198,7 +193,7 @@ private:
nlohmann::json canonical_json; nlohmann::json canonical_json;
std::vector<int> sasList; std::vector<int> sasList;
std::map<std::string, std::string> device_keys; UserKeyCache their_keys;
TimelineModel *model_; TimelineModel *model_;
mtx::common::RelatesTo relation; mtx::common::RelatesTo relation;

View File

@ -280,8 +280,6 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
} }
} }
handle_room_verification(event);
// decrypting and checking some encrypted messages // decrypting and checking some encrypted messages
if (auto encrypted = if (auto encrypted =
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>( std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
@ -292,81 +290,65 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
[](auto e) { return (e.sender != utils::localUser().toStdString()); }, [](auto e) { return (e.sender != utils::localUser().toStdString()); },
*d_event)) { *d_event)) {
handle_room_verification(*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);
}
} }
// 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);
// }
//}
} }
} }
}
if (last_verification_request_event.has_value()) { namespace {
if (last_verification_request_event.value().origin_server_ts > template<class... Ts>
last_verification_cancel_event.origin_server_ts) { struct overloaded : Ts...
emit startDMVerification(last_verification_request_event.value()); {
last_verification_request_event = {}; using Ts::operator()...;
} };
} template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
} }
void void
EventStore::handle_room_verification(mtx::events::collections::TimelineEvents event) EventStore::handle_room_verification(mtx::events::collections::TimelineEvents event)
{ {
if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>(&event)) { std::visit(
auto msg = overloaded{
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>(event); [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg) {
last_verification_request_event = msg; emit startDMVerification(msg);
return; },
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>>( [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg) {
&event)) { ChatPage::instance()->receivedDeviceVerificationCancel(msg.content);
auto msg = },
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>>(event); [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg) {
last_verification_cancel_event = msg; ChatPage::instance()->receivedDeviceVerificationAccept(msg.content);
ChatPage::instance()->receivedDeviceVerificationCancel(msg.content); },
return; [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg) {
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept>>( ChatPage::instance()->receivedDeviceVerificationKey(msg.content);
&event)) { },
auto msg = [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg) {
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept>>(event); ChatPage::instance()->receivedDeviceVerificationMac(msg.content);
ChatPage::instance()->receivedDeviceVerificationAccept(msg.content); },
return; [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg) {
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey>>( ChatPage::instance()->receivedDeviceVerificationReady(msg.content);
&event)) { },
auto msg = [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg) {
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey>>(event); ChatPage::instance()->receivedDeviceVerificationDone(msg.content);
ChatPage::instance()->receivedDeviceVerificationKey(msg.content); },
return; [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg) {
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac>>( ChatPage::instance()->receivedDeviceVerificationStart(msg.content, msg.sender);
&event)) { },
auto msg = [](const auto &) {},
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac>>(event); },
ChatPage::instance()->receivedDeviceVerificationMac(msg.content); event);
return;
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady>>(
&event)) {
auto msg =
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady>>(event);
ChatPage::instance()->receivedDeviceVerificationReady(msg.content);
return;
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone>>(
&event)) {
auto msg =
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone>>(event);
ChatPage::instance()->receivedDeviceVerificationDone(msg.content);
return;
} else if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart>>(
&event)) {
auto msg =
std::get<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart>>(event);
ChatPage::instance()->receivedDeviceVerificationStart(msg.content, msg.sender);
return;
}
} }
QVariantList QVariantList

View File

@ -99,7 +99,7 @@ signals:
void messageSent(std::string txn_id, std::string event_id); void messageSent(std::string txn_id, std::string event_id);
void messageFailed(std::string txn_id); void messageFailed(std::string txn_id);
void startDMVerification( void startDMVerification(
mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg); const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg);
void updateFlowEventId(std::string event_id); void updateFlowEventId(std::string event_id);
public slots: public slots:
@ -123,10 +123,4 @@ private:
std::string current_txn; std::string current_txn;
int current_txn_error_count = 0; int current_txn_error_count = 0;
// probably not the best way to do
std::optional<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>
last_verification_request_event;
mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>
last_verification_cancel_event;
}; };