diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-08-28 00:20:54 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-09-18 10:35:30 +0200 |
| commit | 5bbe04c9ca091a0626f34afe5e3ba2141e2963de (patch) | |
| tree | 35e76183618fe557b4ded5735fb846e3c6cf3995 /trust_db.cpp | |
| parent | d32b9e93572c5e6999a7323139de38cc1a7197cf (diff) | |
WIP OMEMO TrustDb/JidDb
Diffstat (limited to 'trust_db.cpp')
| -rw-r--r-- | trust_db.cpp | 376 |
1 files changed, 272 insertions, 104 deletions
diff --git a/trust_db.cpp b/trust_db.cpp index 138c028..0d8073b 100644 --- a/trust_db.cpp +++ b/trust_db.cpp @@ -1,8 +1,9 @@ #include "trust_db.h" +#include <QXmppTrustLevel.h> +#include <QXmppTrustSecurityPolicy.h> #include <QXmppConfiguration.h> #include <QXmppFutureUtils_p.h> #include <QXmppPromise.h> -#include <qt5keychain/keychain.h> #include <QEventLoop> #include <QtConcurrent> #include <iostream> @@ -13,16 +14,44 @@ TrustDb::TrustDb(const QString &jid, const JidDb &db) : { } +static const struct +{ + QXmpp::TrustLevel level; + const char *str; +} trustlevels[] = +{ + {QXmpp::TrustLevel::Undecided, "Undecided"}, + {QXmpp::TrustLevel::AutomaticallyDistrusted, "AutomaticallyDistrusted"}, + {QXmpp::TrustLevel::ManuallyDistrusted, "ManuallyDistrusted"}, + {QXmpp::TrustLevel::AutomaticallyTrusted, "AutomaticallyTrusted"}, + {QXmpp::TrustLevel::ManuallyTrusted, "ManuallyTrusted"}, + {QXmpp::TrustLevel::Authenticated, "Authenticated"} +}; + +static const struct +{ + QXmpp::TrustSecurityPolicy policy; + const char *str; +} tsp_levels[] = +{ + {QXmpp::NoSecurityPolicy, "NoSecurityPolicy"}, + {QXmpp::Toakafa, "Toakafa"} +}; + static QString toString(const QXmpp::TrustSecurityPolicy securityPolicy) { - switch (securityPolicy) - { - case QXmpp::NoSecurityPolicy: - return "NoSecurityPolicy"; + for (const auto &t : tsp_levels) + if (t.policy == securityPolicy) + return t.str; - case QXmpp::Toakafa: - return "Toakafa"; - } + return "unknown"; +} + +static QString toString(const QXmpp::TrustLevel &trustLevel) +{ + for (const auto &t : trustlevels) + if (t.level == trustLevel) + return t.str; return "unknown"; } @@ -30,16 +59,24 @@ static QString toString(const QXmpp::TrustSecurityPolicy securityPolicy) static int toSecurityPolicy(const QString &s, QXmpp::TrustSecurityPolicy &securityPolicy) { - if (s == "NoSecurityPolicy") - { - securityPolicy = QXmpp::NoSecurityPolicy; - return 0; - } - else if (s == "Toakafa") - { - securityPolicy = QXmpp::Toakafa; - return 0; - } + for (const auto &t : tsp_levels) + if (t.str == s) + { + securityPolicy = t.policy; + return 0; + } + + return -1; +} + +static int toTrustLevel(const QString &tstr, QXmpp::TrustLevel &trustLevel) +{ + for (const auto &t : trustlevels) + if (t.str == tstr) + { + trustLevel = t.level; + return 0; + } return -1; } @@ -52,35 +89,18 @@ QString TrustDb::service() const QXmppTask<void> TrustDb::setSecurityPolicy(const QString &encryption, const QXmpp::TrustSecurityPolicy securityPolicy) { - QKeychain::WritePasswordJob job(service()); - QEventLoop loop; - - job.setKey("securityPolicy/" + encryption); - job.setTextData(toString(securityPolicy)); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) - std::cerr << "Failed to store security policy: " - << qPrintable(job.errorString()) << std::endl; + if (db.store(encryption, toString(securityPolicy))) + std::cerr << "TrustDb::setSecurityPolicy: store failed" + << std::endl; return QXmpp::Private::makeReadyTask(); } QXmppTask<void> TrustDb::resetSecurityPolicy(const QString &encryption) { - QKeychain::DeletePasswordJob job(service()); - QEventLoop loop; - - job.setKey("securityPolicy/" + encryption); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) - std::cerr << "Failed to reset security policy: " - << qPrintable(job.errorString()) << std::endl; + if (db.store(encryption, QString())) + std::cerr << "TrustDb::resetSecurityPolicy: store failed" + << std::endl; return QXmpp::Private::makeReadyTask(); } @@ -88,23 +108,11 @@ QXmppTask<void> TrustDb::resetSecurityPolicy(const QString &encryption) QXmppTask<QXmpp::TrustSecurityPolicy> TrustDb::securityPolicy( const QString &encryption) { - QKeychain::ReadPasswordJob job(service()); - QEventLoop loop; - - job.setKey("securityPolicy/" + encryption); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); + const auto s = db.securityPolicy(encryption); + QXmpp::TrustSecurityPolicy policy; - if (job.error()) - std::cerr << "Failed to read security policy: " - << qPrintable(job.errorString()) << std::endl; - - QXmpp::TrustSecurityPolicy policy = QXmpp::Toakafa; - const QString data = job.textData(); - - if (toSecurityPolicy(data, policy)) - std::cerr << "Invalid security policy " << qPrintable(data) + if (toSecurityPolicy(s, policy)) + std::cerr << "TrustDb::securityPolicy: toSecurityPolicy failed" << std::endl; return QXmpp::Private::makeReadyTask(QXmpp::TrustSecurityPolicy(policy)); @@ -113,81 +121,80 @@ QXmppTask<QXmpp::TrustSecurityPolicy> TrustDb::securityPolicy( QXmppTask<void> TrustDb::setOwnKey(const QString &encryption, const QByteArray &keyId) { - QKeychain::WritePasswordJob job(service()); - QEventLoop loop; - - job.setKey("key/" + encryption); - job.setBinaryData(keyId); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) - std::cerr << "Failed to store own key: " - << qPrintable(job.errorString()) << std::endl; + if (db.store(encryption, keyId)) + std::cerr << "TrustDb::setOwnKey: db.store failed" << std::endl; return QXmpp::Private::makeReadyTask(); } QXmppTask<void> TrustDb::resetOwnKey(const QString &encryption) { - QKeychain::DeletePasswordJob job(service()); - QEventLoop loop; - - job.setKey("key/" + encryption); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) - std::cerr << "Failed to reset own key: " - << qPrintable(job.errorString()) << std::endl; - return QXmpp::Private::makeReadyTask(); } QXmppTask<QByteArray> TrustDb::ownKey(const QString &encryption) { - QKeychain::ReadPasswordJob job(service()); - QEventLoop loop; - - job.setKey("key/" + encryption); - job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - QByteArray ret; - - if (job.error()) - std::cerr << "Failed to read own key: " - << qPrintable(job.errorString()) << std::endl; - else - ret = job.binaryData(); - - return QXmpp::Private::makeReadyTask(QByteArray(ret)); + return QXmpp::Private::makeReadyTask(db.ownKeyId(encryption)); } QXmppTask<void> TrustDb::addKeys(const QString &encryption, const QString &keyOwnerJid, const QList<QByteArray> &keyIds, const QXmpp::TrustLevel trustLevel) { + const struct JidDb::Keys keys(keyOwnerJid, toString(trustLevel), keyIds); + + if (db.store(encryption, keys)) + std::cerr << "TrustDb::addKeys: store failed" << std::endl; + return QXmpp::Private::makeReadyTask(); } QXmppTask<void> TrustDb::removeKeys(const QString &encryption, const QList<QByteArray> &keyIds) { + auto keys = db.keys(encryption); + + for (const auto &id : keyIds) + for (auto &k : keys) + { + const auto i = k.keys.indexOf(id); + + if (i != -1) + { + k.keys.removeAt(i); + break; + } + } + + for (const auto &k : keys) + if (db.store(encryption, k)) + std::cerr << "TrustDb::removeKeys: store failed" << std::endl; + return QXmpp::Private::makeReadyTask(); } QXmppTask<void> TrustDb::removeKeys(const QString &encryption, const QString &keyOwnerJid) { + auto keys = db.keys(encryption); + + for (int i = 0; i < keys.count(); i++) + if (keys[i].owner == keyOwnerJid) + { + keys.removeAt(i); + break; + } + + for (const auto &k : keys) + if (db.store(encryption, k)) + std::cerr << "TrustDb::removeKeys: store failed" << std::endl; + return QXmpp::Private::makeReadyTask(); } QXmppTask<void> TrustDb::removeKeys(const QString &encryption) { + db.removeKeys(encryption); return QXmpp::Private::makeReadyTask(); } @@ -195,8 +202,32 @@ QXmppTask<QHash<QXmpp::TrustLevel, QMultiHash<QString, QByteArray>>> TrustDb::keys(const QString &encryption, const QXmpp::TrustLevels trustLevels) { + QHash<QXmpp::TrustLevel, QMultiHash<QString, QByteArray>> ret; + const auto keys = db.keys(encryption); + + for (const auto &k : keys) + { + QXmpp::TrustLevel level; + + if (toTrustLevel(k.trust_level, level)) + { + std::cerr << "TrustDb::keys: invalid trust level: " + << qPrintable(k.trust_level) << std::endl; + continue; + } + else if (!trustLevels.testFlag(level)) + continue; + + QMultiHash<QString, QByteArray> mh; + + for (const auto &key : k.keys) + mh.insert(k.owner, key); + + ret.insert(level, mh); + } + return QXmpp::Private::makeReadyTask(QHash<QXmpp::TrustLevel, - QMultiHash<QString, QByteArray>>()); + QMultiHash<QString, QByteArray>>(ret)); } QXmppTask<QHash<QString, @@ -204,14 +235,66 @@ QXmppTask<QHash<QString, const QList<QString> &keyOwnerJids, const QXmpp::TrustLevels trustLevels) { + QHash<QString, QHash<QByteArray, QXmpp::TrustLevel>> ret; + const auto keys = db.keys(encryption); + + for (const auto &jid : keyOwnerJids) + for (const auto &k : keys) + { + if (k.owner != jid) + continue; + + QXmpp::TrustLevel level; + + if (toTrustLevel(k.trust_level, level)) + { + std::cerr << "TrustDb::keys: invalid trust level: " + << qPrintable(k.trust_level) << std::endl; + continue; + } + else if (!trustLevels.testFlag(level)) + continue; + + QHash<QByteArray, QXmpp::TrustLevel> h; + + for (const auto &key : k.keys) + h.insert(key, level); + + ret.insert(jid, h); + break; + } + return QXmpp::Private::makeReadyTask(QHash<QString, - QHash<QByteArray, QXmpp::TrustLevel>>()); + QHash<QByteArray, QXmpp::TrustLevel>>(ret)); } QXmppTask<bool> TrustDb::hasKey(const QString &encryption, const QString &keyOwnerJid, QXmpp::TrustLevels trustLevels) { - return QXmpp::Private::makeReadyTask(bool()); + bool ret = false; + const auto keys = db.keys(encryption); + + for (const auto &k : keys) + { + if (k.owner != keyOwnerJid) + continue; + + QXmpp::TrustLevel level; + + if (toTrustLevel(k.trust_level, level)) + { + std::cerr << "TrustDb::keys: invalid trust level: " + << qPrintable(k.trust_level) << std::endl; + break; + } + else if (!trustLevels.testFlag(level)) + break; + + ret = true; + break; + } + + return QXmpp::Private::makeReadyTask(bool(ret)); } QXmppTask<QHash<QString, @@ -220,8 +303,33 @@ QXmppTask<QHash<QString, const QMultiHash<QString, QByteArray> &keyIds, const QXmpp::TrustLevel trustLevel) { + QHash<QString, QMultiHash<QString, QByteArray>> ret; + auto keys = db.keys(encryption); + const auto str = toString(trustLevel); + + for (const auto &owner : keyIds.keys()) + for (auto &k : keys) + { + if (k.owner != owner) + continue; + + k.trust_level = str; + QMultiHash<QString, QByteArray> mh; + + for (const auto &id : k.keys) + mh.insert(owner, id); + + ret.insert(owner, mh); + break; + } + + for (const auto &key : keys) + if (db.store(encryption, key)) + std::cerr << "TrustDb::setTrustLevel: store failed" + << std::endl; + return QXmpp::Private::makeReadyTask(QHash<QString, - QMultiHash<QString, QByteArray>>()); + QMultiHash<QString, QByteArray>>(ret)); } QXmppTask<QHash<QString, @@ -231,17 +339,77 @@ QXmppTask<QHash<QString, const QXmpp::TrustLevel oldTrustLevel, const QXmpp::TrustLevel newTrustLevel) { + QHash<QString, QMultiHash<QString, QByteArray>> ret; + auto keys = db.keys(encryption); + const auto str = toString(newTrustLevel); + + for (const auto &owner : keyOwnerJids) + for (auto &k : keys) + { + QXmpp::TrustLevel trust_level; + + if (k.owner != owner + || toTrustLevel(k.trust_level, trust_level) + || trust_level != oldTrustLevel) + continue; + + k.trust_level = str; + QMultiHash<QString, QByteArray> mh; + + for (const auto &id : k.keys) + mh.insert(owner, id); + + ret.insert(owner, mh); + break; + } + + for (const auto &key : keys) + if (db.store(encryption, key)) + std::cerr << "TrustDb::setTrustLevel: store failed" << std::endl; + return QXmpp::Private::makeReadyTask(QHash<QString, - QMultiHash<QString, QByteArray>>()); + QMultiHash<QString, QByteArray>>(ret)); } QXmppTask<QXmpp::TrustLevel> TrustDb::trustLevel(const QString &encryption, const QString &keyOwnerJid, const QByteArray &keyId) { - return QXmpp::Private::makeReadyTask(QXmpp::TrustLevel()); + const auto keys = db.keys(encryption); + + for (const auto &k : keys) + { + if (k.owner != keyOwnerJid) + continue; + + for (const auto &id : k.keys) + if (id == keyId) + { + QXmpp::TrustLevel ret(QXmpp::TrustLevel::Undecided); + + if (toTrustLevel(k.trust_level, ret)) + std::cerr << "toTrustLevel failed" << std::endl; + + return QXmpp::Private::makeReadyTask( QXmpp::TrustLevel(ret)); + } + } + + return QXmpp::Private::makeReadyTask(QXmpp::TrustLevel( + QXmpp::TrustLevel::Undecided)); } QXmppTask<void> TrustDb::resetAll(const QString &encryption) { + db.removeKeys(encryption); + return QXmpp::Private::makeReadyTask(); } + +namespace QXmpp +{ + +uint qHash(const TrustLevel &key, uint seed) +{ + return qHash(key, seed); +} + +} |
