416 lines
11 KiB
C++
416 lines
11 KiB
C++
#include "trust_db.h"
|
|
#include <QXmppTrustLevel.h>
|
|
#include <QXmppTrustSecurityPolicy.h>
|
|
#include <QXmppConfiguration.h>
|
|
#include <QXmppFutureUtils_p.h>
|
|
#include <QXmppPromise.h>
|
|
#include <QEventLoop>
|
|
#include <QtConcurrent>
|
|
#include <iostream>
|
|
|
|
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<void> 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<void> TrustDb::resetSecurityPolicy(const QString &encryption)
|
|
{
|
|
if (db.store(encryption, QString()))
|
|
std::cerr << "TrustDb::resetSecurityPolicy: store failed"
|
|
<< std::endl;
|
|
|
|
return QXmpp::Private::makeReadyTask();
|
|
}
|
|
|
|
QXmppTask<QXmpp::TrustSecurityPolicy> 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<void> 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<void> TrustDb::resetOwnKey(const QString &encryption)
|
|
{
|
|
return QXmpp::Private::makeReadyTask();
|
|
}
|
|
|
|
QXmppTask<QByteArray> TrustDb::ownKey(const QString &encryption)
|
|
{
|
|
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();
|
|
}
|
|
|
|
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>>(ret));
|
|
}
|
|
|
|
QXmppTask<QHash<QString,
|
|
QHash<QByteArray, QXmpp::TrustLevel>>> TrustDb::keys(const QString &encryption,
|
|
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>>(ret));
|
|
}
|
|
|
|
QXmppTask<bool> 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<QHash<QString,
|
|
QMultiHash<QString, QByteArray>>> TrustDb::setTrustLevel(
|
|
const QString &encryption,
|
|
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>>(ret));
|
|
}
|
|
|
|
QXmppTask<QHash<QString,
|
|
QMultiHash<QString, QByteArray>>> TrustDb::setTrustLevel(
|
|
const QString &encryption,
|
|
const QList<QString> &keyOwnerJids,
|
|
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>>(ret));
|
|
}
|
|
|
|
QXmppTask<QXmpp::TrustLevel> 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<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);
|
|
}
|
|
|
|
}
|