aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autotests/CMakeLists.txt1
-rw-r--r--autotests/testkeyverification.cpp59
-rw-r--r--autotests/testolmaccount.cpp22
-rw-r--r--autotests/testutils.h32
-rw-r--r--lib/connection.cpp44
-rw-r--r--lib/connection.h11
-rw-r--r--lib/events/keyverificationevent.h74
-rw-r--r--lib/keyverificationsession.cpp136
-rw-r--r--lib/keyverificationsession.h11
9 files changed, 205 insertions, 185 deletions
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index c11901bf..48edb168 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -19,4 +19,5 @@ if(${PROJECT_NAME}_ENABLE_E2EE)
quotient_add_test(NAME testolmsession)
quotient_add_test(NAME testolmutility)
quotient_add_test(NAME testfilecrypto)
+ quotient_add_test(NAME testkeyverification)
endif()
diff --git a/autotests/testkeyverification.cpp b/autotests/testkeyverification.cpp
new file mode 100644
index 00000000..1fa6d8c6
--- /dev/null
+++ b/autotests/testkeyverification.cpp
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+
+#include <QTest>
+#include "testutils.h"
+#include <qt_connection_util.h>
+
+class TestKeyVerificationSession : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void testVerification()
+ {
+ CREATE_CONNECTION(a, "alice1", "secret", "AliceDesktop")
+ CREATE_CONNECTION(b, "alice1", "secret", "AlicePhone")
+
+ QPointer<KeyVerificationSession> aSession{};
+ connect(a.get(), &Connection::newKeyVerificationSession, this, [&](KeyVerificationSession* session) {
+ aSession = session;
+ QVERIFY(session->remoteDeviceId() == b->deviceId());
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORREADY);
+ connectSingleShot(session, &KeyVerificationSession::stateChanged, this, [=](){
+ QVERIFY(session->state() == KeyVerificationSession::ACCEPTED || session->state() == KeyVerificationSession::READY);
+ connectSingleShot(session, &KeyVerificationSession::stateChanged, this, [=](){
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORVERIFICATION);
+ session->sendMac();
+ });
+ });
+ });
+ a->startKeyVerificationSession(b->deviceId());
+ connect(b.get(), &Connection::newKeyVerificationSession, this, [=](KeyVerificationSession* session) {
+ QVERIFY(session->remoteDeviceId() == a->deviceId());
+ QVERIFY(session->state() == KeyVerificationSession::INCOMING);
+ session->sendReady();
+ // KeyVerificationSession::READY is skipped because we have only one method
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORACCEPT);
+ connectSingleShot(session, &KeyVerificationSession::stateChanged, this, [=](){
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORKEY || session->state() == KeyVerificationSession::ACCEPTED);
+ connectSingleShot(session, &KeyVerificationSession::stateChanged, this, [=]() {
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORVERIFICATION);
+ QVERIFY(aSession);
+ QVERIFY(aSession->sasEmojis() == session->sasEmojis());
+ session->sendMac();
+ QVERIFY(session->state() == KeyVerificationSession::WAITINGFORMAC);
+ });
+ });
+
+ });
+ b->syncLoop();
+ a->syncLoop();
+ QSignalSpy spy(aSession, &KeyVerificationSession::finished);
+ spy.wait(10000);
+ }
+};
+QTEST_GUILESS_MAIN(TestKeyVerificationSession)
+#include "testkeyverification.moc"
diff --git a/autotests/testolmaccount.cpp b/autotests/testolmaccount.cpp
index 4b32393d..280705d0 100644
--- a/autotests/testolmaccount.cpp
+++ b/autotests/testolmaccount.cpp
@@ -14,6 +14,8 @@
#include <networkaccessmanager.h>
#include <room.h>
+#include "testutils.h"
+
using namespace Quotient;
void TestOlmAccount::pickleUnpickledTest()
@@ -168,26 +170,6 @@ void TestOlmAccount::encryptedFile()
QCOMPARE(file.key.kty, "oct");
}
-#define CREATE_CONNECTION(VAR, USERNAME, SECRET, DEVICE_NAME) \
- NetworkAccessManager::instance()->ignoreSslErrors(true); \
- auto VAR = std::make_shared<Connection>(); \
- (VAR)->resolveServer("@" USERNAME ":localhost:1234"); \
- connect((VAR).get(), &Connection::loginFlowsChanged, this, [=] { \
- (VAR)->loginWithPassword((USERNAME), SECRET, DEVICE_NAME, ""); \
- }); \
- connect((VAR).get(), &Connection::networkError, [](const QString& error) { \
- QWARN(qUtf8Printable(error)); \
- QFAIL("Network error: make sure synapse is running"); \
- }); \
- connect((VAR).get(), &Connection::loginError, [](const QString& error) { \
- QWARN(qUtf8Printable(error)); \
- QFAIL("Login failed"); \
- }); \
- QSignalSpy spy##VAR((VAR).get(), &Connection::loginFlowsChanged); \
- QSignalSpy spy2##VAR((VAR).get(), &Connection::connected); \
- QVERIFY(spy##VAR.wait(10000)); \
- QVERIFY(spy2##VAR.wait(10000));
-
void TestOlmAccount::uploadIdentityKey()
{
CREATE_CONNECTION(conn, "alice1", "secret", "AlicePhone")
diff --git a/autotests/testutils.h b/autotests/testutils.h
new file mode 100644
index 00000000..7d016a34
--- /dev/null
+++ b/autotests/testutils.h
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#pragma once
+
+#include <connection.h>
+#include <networkaccessmanager.h>
+
+#include <QtTest/QSignalSpy>
+
+using namespace Quotient;
+
+#define CREATE_CONNECTION(VAR, USERNAME, SECRET, DEVICE_NAME) \
+ NetworkAccessManager::instance()->ignoreSslErrors(true); \
+ auto VAR = std::make_shared<Connection>(); \
+ (VAR)->resolveServer("@" USERNAME ":localhost:1234"); \
+ connect((VAR).get(), &Connection::loginFlowsChanged, this, [=] { \
+ (VAR)->loginWithPassword((USERNAME), SECRET, DEVICE_NAME, ""); \
+ }); \
+ connect((VAR).get(), &Connection::networkError, [](const QString& error) { \
+ QWARN(qUtf8Printable(error)); \
+ QFAIL("Network error: make sure synapse is running"); \
+ }); \
+ connect((VAR).get(), &Connection::loginError, [](const QString& error) { \
+ QWARN(qUtf8Printable(error)); \
+ QFAIL("Login failed"); \
+ }); \
+ QSignalSpy spy##VAR((VAR).get(), &Connection::loginFlowsChanged); \
+ QSignalSpy spy2##VAR((VAR).get(), &Connection::connected); \
+ QVERIFY(spy##VAR.wait(10000)); \
+ QVERIFY(spy2##VAR.wait(10000));
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 5de02b8c..8ca76ceb 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -124,6 +124,7 @@ public:
// A map from SenderKey to vector of InboundSession
UnorderedMap<QString, std::vector<QOlmSessionPtr>> olmSessions;
+ QHash<QString, KeyVerificationSession*> verificationSessions;
#endif
GetCapabilitiesJob* capabilitiesJob = nullptr;
@@ -971,6 +972,8 @@ void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents)
qCDebug(E2EE) << "Consuming" << toDeviceEvents.size()
<< "to-device events";
for (auto&& tdEvt : toDeviceEvents) {
+ if (processIfVerificationEvent(*tdEvt, false))
+ continue;
if (auto&& event = eventCast<EncryptedEvent>(std::move(tdEvt))) {
if (event->algorithm() != OlmV1Curve25519AesSha2AlgoKey) {
qCDebug(E2EE) << "Unsupported algorithm" << event->id()
@@ -985,9 +988,7 @@ void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents)
outdatedUsers += event->senderId();
encryptionUpdateRequired = true;
pendingEncryptedEvents.push_back(std::move(event));
- continue;
}
- processIfVerificationEvent(*tdEvt, false);
}
}
#endif
@@ -998,33 +999,22 @@ bool Connection::Private::processIfVerificationEvent(const Event& evt,
bool encrypted)
{
return switchOnType(evt,
- [this, encrypted](const KeyVerificationRequestEvent& event) {
- auto session =
- new KeyVerificationSession(q->userId(), event, q, encrypted);
- emit q->newKeyVerificationSession(session);
- return true;
- }, [this](const KeyVerificationReadyEvent& event) {
- emit q->incomingKeyVerificationReady(event);
- return true;
- }, [this](const KeyVerificationStartEvent& event) {
- emit q->incomingKeyVerificationStart(event);
- return true;
- }, [this](const KeyVerificationAcceptEvent& event) {
- emit q->incomingKeyVerificationAccept(event);
- return true;
- }, [this](const KeyVerificationKeyEvent& event) {
- emit q->incomingKeyVerificationKey(event);
+ [this, encrypted](const KeyVerificationRequestEvent& reqEvt) {
+ const auto sessionIter = verificationSessions.insert(
+ reqEvt.transactionId(),
+ new KeyVerificationSession(q->userId(), reqEvt, q, encrypted));
+ emit q->newKeyVerificationSession(*sessionIter);
return true;
- }, [this](const KeyVerificationMacEvent& event) {
- emit q->incomingKeyVerificationMac(event);
- return true;
- }, [this](const KeyVerificationDoneEvent& event) {
- emit q->incomingKeyVerificationDone(event);
- return true;
- }, [this](const KeyVerificationCancelEvent& event) {
- emit q->incomingKeyVerificationCancel(event);
+ },
+ [this](const KeyVerificationEvent& kvEvt) {
+ if (auto* const session =
+ verificationSessions.value(kvEvt.transactionId())) {
+ session->handleEvent(kvEvt);
+ emit q->keyVerificationStateChanged(session, session->state());
+ }
return true;
- }, false);
+ },
+ false);
}
void Connection::Private::handleEncryptedToDeviceEvent(const EncryptedEvent& event)
diff --git a/lib/connection.h b/lib/connection.h
index 79c23c9a..75faf370 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -864,15 +864,10 @@ Q_SIGNALS:
void devicesListLoaded();
#ifdef Quotient_E2EE_ENABLED
- void incomingKeyVerificationReady(const KeyVerificationReadyEvent& event);
- void incomingKeyVerificationStart(const KeyVerificationStartEvent& event);
- void incomingKeyVerificationAccept(const KeyVerificationAcceptEvent& event);
- void incomingKeyVerificationKey(const KeyVerificationKeyEvent& event);
- void incomingKeyVerificationMac(const KeyVerificationMacEvent& event);
- void incomingKeyVerificationDone(const KeyVerificationDoneEvent& event);
- void incomingKeyVerificationCancel(const KeyVerificationCancelEvent& event);
-
void newKeyVerificationSession(KeyVerificationSession* session);
+ void keyVerificationStateChanged(
+ const KeyVerificationSession* session,
+ Quotient::KeyVerificationSession::State state);
void sessionVerified(const QString& userId, const QString& deviceId);
#endif
diff --git a/lib/events/keyverificationevent.h b/lib/events/keyverificationevent.h
index 0ffd8b2c..0e939508 100644
--- a/lib/events/keyverificationevent.h
+++ b/lib/events/keyverificationevent.h
@@ -9,13 +9,24 @@ namespace Quotient {
static constexpr auto SasV1Method = "m.sas.v1"_ls;
+class QUOTIENT_API KeyVerificationEvent : public Event {
+public:
+ QUO_BASE_EVENT(KeyVerificationEvent, "m.key.*"_ls, Event::BaseMetaType)
+
+ using Event::Event;
+
+ /// An opaque identifier for the verification request. Must
+ /// be unique with respect to the devices involved.
+ QUO_CONTENT_GETTER(QString, transactionId)
+};
+
/// Requests a key verification with another user's devices.
/// Typically sent as a to-device event.
-class QUOTIENT_API KeyVerificationRequestEvent : public Event {
+class QUOTIENT_API KeyVerificationRequestEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationRequestEvent, "m.key.verification.request")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationRequestEvent(const QString& transactionId,
const QString& fromDevice,
const QStringList& methods,
@@ -30,10 +41,6 @@ public:
/// The device ID which is initiating the request.
QUO_CONTENT_GETTER(QString, fromDevice)
- /// An opaque identifier for the verification request. Must
- /// be unique with respect to the devices involved.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The verification methods supported by the sender.
QUO_CONTENT_GETTER(QStringList, methods)
@@ -44,11 +51,11 @@ public:
QUO_CONTENT_GETTER(QDateTime, timestamp)
};
-class QUOTIENT_API KeyVerificationReadyEvent : public Event {
+class QUOTIENT_API KeyVerificationReadyEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationReadyEvent, "m.key.verification.ready")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationReadyEvent(const QString& transactionId,
const QString& fromDevice,
const QStringList& methods)
@@ -61,19 +68,16 @@ public:
/// The device ID which is accepting the request.
QUO_CONTENT_GETTER(QString, fromDevice)
- /// The transaction id of the verification request
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The verification methods supported by the sender.
QUO_CONTENT_GETTER(QStringList, methods)
};
/// Begins a key verification process.
-class QUOTIENT_API KeyVerificationStartEvent : public Event {
+class QUOTIENT_API KeyVerificationStartEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationStartEvent, "m.key.verification.start")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationStartEvent(const QString& transactionId,
const QString& fromDevice)
: KeyVerificationStartEvent(
@@ -92,10 +96,6 @@ public:
/// The device ID which is initiating the process.
QUO_CONTENT_GETTER(QString, fromDevice)
- /// An opaque identifier for the verification request. Must
- /// be unique with respect to the devices involved.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The verification method to use.
QUO_CONTENT_GETTER(QString, method)
@@ -140,11 +140,11 @@ public:
/// Accepts a previously sent m.key.verification.start message.
/// Typically sent as a to-device event.
-class QUOTIENT_API KeyVerificationAcceptEvent : public Event {
+class QUOTIENT_API KeyVerificationAcceptEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationAcceptEvent, "m.key.verification.accept")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationAcceptEvent(const QString& transactionId,
const QString& commitment)
: KeyVerificationAcceptEvent(basicJson(
@@ -158,9 +158,6 @@ public:
{ "commitment"_ls, commitment } }))
{}
- /// An opaque identifier for the verification process.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The verification method to use. Must be 'm.sas.v1'.
QUO_CONTENT_GETTER(QString, method)
@@ -170,10 +167,7 @@ public:
/// The hash method the device is choosing to use, out of the
/// options in the m.key.verification.start message.
- QString hashData() const
- {
- return contentPart<QString>("hash"_ls);
- }
+ QUO_CONTENT_GETTER_X(QString, hashData, "hash"_ls)
/// The message authentication code the device is choosing to use, out
/// of the options in the m.key.verification.start message.
@@ -188,11 +182,11 @@ public:
QUO_CONTENT_GETTER(QString, commitment)
};
-class QUOTIENT_API KeyVerificationCancelEvent : public Event {
+class QUOTIENT_API KeyVerificationCancelEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationCancelEvent, "m.key.verification.cancel")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationCancelEvent(const QString& transactionId,
const QString& reason)
: KeyVerificationCancelEvent(
@@ -203,9 +197,6 @@ public:
}))
{}
- /// An opaque identifier for the verification process.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// A human readable description of the code. The client should only
/// rely on this string if it does not understand the code.
QUO_CONTENT_GETTER(QString, reason)
@@ -216,30 +207,27 @@ public:
/// Sends the ephemeral public key for a device to the partner device.
/// Typically sent as a to-device event.
-class QUOTIENT_API KeyVerificationKeyEvent : public Event {
+class KeyVerificationKeyEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationKeyEvent, "m.key.verification.key")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationKeyEvent(const QString& transactionId, const QString& key)
: KeyVerificationKeyEvent(
basicJson(TypeId, { { "transaction_id"_ls, transactionId },
{ "key"_ls, key } }))
{}
- /// An opaque identifier for the verification process.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The device's ephemeral public key, encoded as unpadded base64.
QUO_CONTENT_GETTER(QString, key)
};
/// Sends the MAC of a device's key to the partner device.
-class QUOTIENT_API KeyVerificationMacEvent : public Event {
+class QUOTIENT_API KeyVerificationMacEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationMacEvent, "m.key.verification.mac")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
KeyVerificationMacEvent(const QString& transactionId, const QString& keys,
const QJsonObject& mac)
: KeyVerificationMacEvent(
@@ -248,9 +236,6 @@ public:
{ "mac"_ls, mac } }))
{}
- /// An opaque identifier for the verification process.
- QUO_CONTENT_GETTER(QString, transactionId)
-
/// The device's ephemeral public key, encoded as unpadded base64.
QUO_CONTENT_GETTER(QString, keys)
@@ -260,17 +245,14 @@ public:
}
};
-class QUOTIENT_API KeyVerificationDoneEvent : public Event {
+class QUOTIENT_API KeyVerificationDoneEvent : public KeyVerificationEvent {
public:
QUO_EVENT(KeyVerificationDoneEvent, "m.key.verification.done")
- using Event::Event;
+ using KeyVerificationEvent::KeyVerificationEvent;
explicit KeyVerificationDoneEvent(const QString& transactionId)
: KeyVerificationDoneEvent(
basicJson(TypeId, { { "transaction_id"_ls, transactionId } }))
{}
-
- /// The same transactionId as before
- QUO_CONTENT_GETTER(QString, transactionId)
};
} // namespace Quotient
diff --git a/lib/keyverificationsession.cpp b/lib/keyverificationsession.cpp
index 541ca49b..3f76eac1 100644
--- a/lib/keyverificationsession.cpp
+++ b/lib/keyverificationsession.cpp
@@ -68,42 +68,6 @@ KeyVerificationSession::KeyVerificationSession(QString userId, QString deviceId,
void KeyVerificationSession::init(milliseconds timeout)
{
- connect(m_connection, &Connection::incomingKeyVerificationReady, this, [this](const KeyVerificationReadyEvent& event) {
- if (event.transactionId() == m_transactionId && event.fromDevice() == m_remoteDeviceId) {
- handleReady(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationStart, this, [this](const KeyVerificationStartEvent& event) {
- if (event.transactionId() == m_transactionId && event.fromDevice() == m_remoteDeviceId) {
- handleStart(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationAccept, this, [this](const KeyVerificationAcceptEvent& event) {
- if (event.transactionId() == m_transactionId) {
- handleAccept(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationKey, this, [this](const KeyVerificationKeyEvent& event) {
- if (event.transactionId() == m_transactionId) {
- handleKey(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationMac, this, [this](const KeyVerificationMacEvent& event) {
- if (event.transactionId() == m_transactionId) {
- handleMac(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationDone, this, [this](const KeyVerificationDoneEvent& event) {
- if (event.transactionId() == m_transactionId) {
- handleDone(event);
- }
- });
- connect(m_connection, &Connection::incomingKeyVerificationCancel, this, [this](const KeyVerificationCancelEvent& event) {
- if (event.transactionId() == m_transactionId) {
- handleCancel(event);
- }
- });
-
QTimer::singleShot(timeout, this, [this] { cancelVerification(TIMEOUT); });
m_sas = olm_sas(new std::byte[olm_sas_size()]);
@@ -118,6 +82,53 @@ KeyVerificationSession::~KeyVerificationSession()
delete[] reinterpret_cast<std::byte*>(m_sas);
}
+void KeyVerificationSession::handleEvent(const KeyVerificationEvent& baseEvent)
+{
+ if (!switchOnType(
+ baseEvent,
+ [this](const KeyVerificationCancelEvent& event) {
+ setError(stringToError(event.code()));
+ setState(CANCELED);
+ return true;
+ },
+ [this](const KeyVerificationStartEvent& event) {
+ if (state() != WAITINGFORREADY && state() != READY)
+ return false;
+ handleStart(event);
+ return true;
+ },
+ [this](const KeyVerificationReadyEvent& event) {
+ if (state() == WAITINGFORREADY)
+ handleReady(event);
+ // ACCEPTED is also fine here because it's possible to receive
+ // ready and start in the same sync, in which case start might
+ // be handled before ready.
+ return state() == WAITINGFORREADY || state() == ACCEPTED;
+ },
+ [this](const KeyVerificationAcceptEvent& event) {
+ if (state() != WAITINGFORACCEPT)
+ return false;
+ m_commitment = event.commitment();
+ sendKey();
+ setState(WAITINGFORKEY);
+ return true;
+ },
+ [this](const KeyVerificationKeyEvent& event) {
+ if (state() != ACCEPTED && state() != WAITINGFORKEY)
+ return false;
+ handleKey(event);
+ return true;
+ },
+ [this](const KeyVerificationMacEvent& event) {
+ if (state() != WAITINGFORMAC)
+ return false;
+ handleMac(event);
+ return true;
+ },
+ [this](const KeyVerificationDoneEvent&) { return state() == DONE; }))
+ cancelVerification(UNEXPECTED_MESSAGE);
+}
+
struct EmojiStoreEntry : EmojiEntry {
QHash<QString, QString> translatedDescriptions;
@@ -154,10 +165,6 @@ EmojiEntry emojiForCode(int code, const QString& language)
void KeyVerificationSession::handleKey(const KeyVerificationKeyEvent& event)
{
- if (state() != WAITINGFORKEY && state() != WAITINGFORVERIFICATION) {
- cancelVerification(UNEXPECTED_MESSAGE);
- return;
- }
auto eventKey = event.key().toLatin1();
olm_sas_set_their_key(m_sas, eventKey.data(), eventKey.size());
@@ -176,7 +183,6 @@ void KeyVerificationSession::handleKey(const KeyVerificationKeyEvent& event)
} else {
sendKey();
}
- setState(WAITINGFORVERIFICATION);
std::string key(olm_sas_pubkey_length(m_sas), '\0');
olm_sas_get_pubkey(m_sas, key.data(), key.size());
@@ -214,6 +220,7 @@ void KeyVerificationSession::handleKey(const KeyVerificationKeyEvent& event)
emit sasEmojisChanged();
emit keyReceived();
+ setState(WAITINGFORVERIFICATION);
}
QString KeyVerificationSession::calculateMac(const QString& input,
@@ -319,30 +326,18 @@ void KeyVerificationSession::sendStartSas()
void KeyVerificationSession::handleReady(const KeyVerificationReadyEvent& event)
{
- if (state() != WAITINGFORREADY) {
- cancelVerification(UNEXPECTED_MESSAGE);
- return;
- }
setState(READY);
m_remoteSupportedMethods = event.methods();
auto methods = commonSupportedMethods(m_remoteSupportedMethods);
- if (methods.isEmpty()) {
+ if (methods.isEmpty())
cancelVerification(UNKNOWN_METHOD);
- return;
- }
-
- if (methods.size() == 1) {
- sendStartSas();
- }
+ else if (methods.size() == 1)
+ sendStartSas(); // -> WAITINGFORACCEPT
}
void KeyVerificationSession::handleStart(const KeyVerificationStartEvent& event)
{
- if (state() != READY) {
- cancelVerification(UNEXPECTED_MESSAGE);
- return;
- }
if (startSentByUs) {
if (m_remoteUserId > m_connection->userId() || (m_remoteUserId == m_connection->userId() && m_remoteDeviceId > m_connection->deviceId())) {
return;
@@ -363,17 +358,6 @@ void KeyVerificationSession::handleStart(const KeyVerificationStartEvent& event)
setState(ACCEPTED);
}
-void KeyVerificationSession::handleAccept(const KeyVerificationAcceptEvent& event)
-{
- if(state() != WAITINGFORACCEPT) {
- cancelVerification(UNEXPECTED_MESSAGE);
- return;
- }
- m_commitment = event.commitment();
- sendKey();
- setState(WAITINGFORKEY);
-}
-
void KeyVerificationSession::handleMac(const KeyVerificationMacEvent& event)
{
QStringList keys = event.mac().keys();
@@ -412,19 +396,6 @@ void KeyVerificationSession::trustKeys()
}
}
-void KeyVerificationSession::handleDone(const KeyVerificationDoneEvent&)
-{
- if (state() != DONE) {
- cancelVerification(UNEXPECTED_MESSAGE);
- }
-}
-
-void KeyVerificationSession::handleCancel(const KeyVerificationCancelEvent& event)
-{
- setError(stringToError(event.code()));
- setState(CANCELED);
-}
-
QVector<EmojiEntry> KeyVerificationSession::sasEmojis() const
{
return m_sasEmojis;
@@ -524,3 +495,8 @@ KeyVerificationSession::Error KeyVerificationSession::stringToError(const QStrin
}
return NONE;
}
+
+QString KeyVerificationSession::remoteDeviceId() const
+{
+ return m_remoteDeviceId;
+}
diff --git a/lib/keyverificationsession.h b/lib/keyverificationsession.h
index 075ea1e2..32a91cfc 100644
--- a/lib/keyverificationsession.h
+++ b/lib/keyverificationsession.h
@@ -19,6 +19,9 @@ struct QUOTIENT_API EmojiEntry {
Q_GADGET
Q_PROPERTY(QString emoji MEMBER emoji CONSTANT)
Q_PROPERTY(QString description MEMBER description CONSTANT)
+
+public:
+ bool operator==(const EmojiEntry& rhs) const = default;
};
/** A key verification session. Listen for incoming sessions by connecting to Connection::newKeyVerificationSession.
@@ -88,11 +91,15 @@ public:
~KeyVerificationSession() override;
Q_DISABLE_COPY_MOVE(KeyVerificationSession)
+ void handleEvent(const KeyVerificationEvent& baseEvent);
+
QVector<EmojiEntry> sasEmojis() const;
State state() const;
Error error() const;
+ QString remoteDeviceId() const;
+
public Q_SLOTS:
void sendRequest();
void sendReady();
@@ -103,7 +110,6 @@ public Q_SLOTS:
void cancelVerification(Error error);
Q_SIGNALS:
- void startReceived();
void keyReceived();
void sasEmojisChanged();
void stateChanged();
@@ -130,11 +136,8 @@ private:
void handleReady(const KeyVerificationReadyEvent& event);
void handleStart(const KeyVerificationStartEvent& event);
- void handleAccept(const KeyVerificationAcceptEvent& event);
void handleKey(const KeyVerificationKeyEvent& event);
void handleMac(const KeyVerificationMacEvent& event);
- void handleDone(const KeyVerificationDoneEvent&);
- void handleCancel(const KeyVerificationCancelEvent& event);
void init(std::chrono::milliseconds timeout);
void setState(State state);
void setError(Error error);