#include "trust_db.h" #include #include #include #include #include #include #include #include TrustDb::TrustDb(const QString &jid, const JidDb &db) : jid(jid), db(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) { for (const auto &t : tsp_levels) if (t.policy == securityPolicy) return t.str; return "unknown"; } static QString toString(const QXmpp::TrustLevel &trustLevel) { for (const auto &t : trustlevels) if (t.level == trustLevel) return t.str; return "unknown"; } static int toSecurityPolicy(const QString &s, QXmpp::TrustSecurityPolicy &securityPolicy) { 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; } QString TrustDb::service() const { return "xxcc/trust/" + jid; } QXmppTask TrustDb::setSecurityPolicy(const QString &encryption, const QXmpp::TrustSecurityPolicy securityPolicy) { if (db.store(encryption, toString(securityPolicy))) std::cerr << "TrustDb::setSecurityPolicy: store failed" << std::endl; return QXmpp::Private::makeReadyTask(); } QXmppTask TrustDb::resetSecurityPolicy(const QString &encryption) { if (db.store(encryption, QString())) std::cerr << "TrustDb::resetSecurityPolicy: store failed" << std::endl; return QXmpp::Private::makeReadyTask(); } QXmppTask TrustDb::securityPolicy( const QString &encryption) { const auto s = db.securityPolicy(encryption); QXmpp::TrustSecurityPolicy policy; if (toSecurityPolicy(s, policy)) std::cerr << "TrustDb::securityPolicy: toSecurityPolicy failed" << std::endl; return QXmpp::Private::makeReadyTask(QXmpp::TrustSecurityPolicy(policy)); } QXmppTask TrustDb::setOwnKey(const QString &encryption, const QByteArray &keyId) { if (db.store(encryption, keyId)) std::cerr << "TrustDb::setOwnKey: db.store failed" << std::endl; return QXmpp::Private::makeReadyTask(); } QXmppTask TrustDb::resetOwnKey(const QString &encryption) { return QXmpp::Private::makeReadyTask(); } QXmppTask TrustDb::ownKey(const QString &encryption) { return QXmpp::Private::makeReadyTask(db.ownKeyId(encryption)); } QXmppTask TrustDb::addKeys(const QString &encryption, const QString &keyOwnerJid, const QList &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 TrustDb::removeKeys(const QString &encryption, const QList &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 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 TrustDb::removeKeys(const QString &encryption) { db.removeKeys(encryption); return QXmpp::Private::makeReadyTask(); } QXmppTask>> TrustDb::keys(const QString &encryption, const QXmpp::TrustLevels trustLevels) { QHash> 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 mh; for (const auto &key : k.keys) mh.insert(k.owner, key); ret.insert(level, mh); } return QXmpp::Private::makeReadyTask(QHash>(ret)); } QXmppTask>> TrustDb::keys(const QString &encryption, const QList &keyOwnerJids, const QXmpp::TrustLevels trustLevels) { QHash> 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 h; for (const auto &key : k.keys) h.insert(key, level); ret.insert(jid, h); break; } return QXmpp::Private::makeReadyTask(QHash>(ret)); } QXmppTask TrustDb::hasKey(const QString &encryption, const QString &keyOwnerJid, QXmpp::TrustLevels trustLevels) { 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>> TrustDb::setTrustLevel( const QString &encryption, const QMultiHash &keyIds, const QXmpp::TrustLevel trustLevel) { QHash> 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 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>(ret)); } QXmppTask>> TrustDb::setTrustLevel( const QString &encryption, const QList &keyOwnerJids, const QXmpp::TrustLevel oldTrustLevel, const QXmpp::TrustLevel newTrustLevel) { QHash> 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 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>(ret)); } QXmppTask TrustDb::trustLevel(const QString &encryption, const QString &keyOwnerJid, const QByteArray &keyId) { 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 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); } }