forked from blue/squawk
work progress: trust manager. DOESN'T START!
This commit is contained in:
parent
0b61b6e928
commit
db3bc358a7
@ -142,6 +142,7 @@ if (NOT SYSTEM_QXMPP)
|
||||
add_subdirectory(external/qxmpp)
|
||||
|
||||
target_link_libraries(squawk PRIVATE qxmpp)
|
||||
target_link_libraries(squawk PRIVATE QXmppOmemo)
|
||||
else ()
|
||||
target_link_libraries(squawk PRIVATE QXmpp::QXmpp)
|
||||
endif ()
|
||||
|
@ -31,6 +31,17 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
config(),
|
||||
presence(),
|
||||
state(Shared::ConnectionState::disconnected),
|
||||
|
||||
mh(new MessageHandler(this)),
|
||||
rh(new RosterHandler(this)),
|
||||
vh(new VCardHandler(this)),
|
||||
dh(new DiscoveryHandler(this)),
|
||||
#ifdef WITH_OMEMO
|
||||
th(new TrustHandler(this)),
|
||||
oh(new OmemoHandler(this)),
|
||||
tm(new QXmppTrustManager(th)),
|
||||
om(new QXmppOmemoManager(oh)),
|
||||
#endif
|
||||
cm(new QXmppCarbonManager()),
|
||||
am(new QXmppMamManager()),
|
||||
mm(new QXmppMucManager()),
|
||||
@ -40,9 +51,6 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
um(new QXmppUploadRequestManager()),
|
||||
dm(client.findExtension<QXmppDiscoveryManager>()),
|
||||
rcpm(new QXmppMessageReceiptManager()),
|
||||
#ifdef WITH_OMEMO
|
||||
om(new QXmppOmemoManager()),
|
||||
#endif
|
||||
reconnectScheduled(false),
|
||||
reconnectTimer(new QTimer),
|
||||
network(p_net),
|
||||
@ -50,11 +58,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
lastError(Error::none),
|
||||
pepSupport(Shared::Support::unknown),
|
||||
active(p_active),
|
||||
notReadyPassword(false),
|
||||
mh(new MessageHandler(this)),
|
||||
rh(new RosterHandler(this)),
|
||||
vh(new VCardHandler(this)),
|
||||
dh(new DiscoveryHandler(this))
|
||||
notReadyPassword(false)
|
||||
{
|
||||
config.setUser(p_login);
|
||||
config.setDomain(p_server);
|
||||
@ -62,6 +66,10 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
config.setAutoAcceptSubscriptions(true);
|
||||
//config.setAutoReconnectionEnabled(false);
|
||||
|
||||
rh->initialize();
|
||||
vh->initialize();
|
||||
dh->initialize();
|
||||
|
||||
QObject::connect(&client, &QXmppClient::stateChanged, this, &Account::onClientStateChange);
|
||||
QObject::connect(&client, &QXmppClient::presenceReceived, this, &Account::onPresenceReceived);
|
||||
QObject::connect(&client, &QXmppClient::messageReceived, mh, &MessageHandler::onMessageReceived);
|
||||
@ -92,6 +100,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
||||
QObject::connect(rcpm, &QXmppMessageReceiptManager::messageDelivered, mh, &MessageHandler::onReceiptReceived);
|
||||
|
||||
#ifdef WITH_OMEMO
|
||||
client.addExtension(tm);
|
||||
client.addExtension(om);
|
||||
qDebug("Added OMEMO manager");
|
||||
#endif
|
||||
|
@ -42,9 +42,6 @@
|
||||
#include <QXmppUploadRequestManager.h>
|
||||
#include <QXmppVCardManager.h>
|
||||
#include <QXmppMessageReceiptManager.h>
|
||||
#ifdef WITH_OMEMO
|
||||
#include <QXmppOmemoManager.h>
|
||||
#endif
|
||||
|
||||
#include <shared/shared.h>
|
||||
#include <shared/identity.h>
|
||||
@ -57,6 +54,13 @@
|
||||
#include "handlers/vcardhandler.h"
|
||||
#include "handlers/discoveryhandler.h"
|
||||
|
||||
#ifdef WITH_OMEMO
|
||||
#include <QXmppOmemoManager.h>
|
||||
#include <QXmppTrustManager.h>
|
||||
#include "handlers/trusthandler.h"
|
||||
#include "handlers/omemohandler.h"
|
||||
#endif
|
||||
|
||||
namespace Core
|
||||
{
|
||||
|
||||
@ -170,6 +174,18 @@ private:
|
||||
QXmppConfiguration config;
|
||||
QXmppPresence presence;
|
||||
Shared::ConnectionState state;
|
||||
|
||||
MessageHandler* mh;
|
||||
RosterHandler* rh;
|
||||
VCardHandler* vh;
|
||||
DiscoveryHandler* dh;
|
||||
#ifdef WITH_OMEMO
|
||||
TrustHandler* th;
|
||||
OmemoHandler* oh;
|
||||
|
||||
QXmppTrustManager* tm;
|
||||
QXmppOmemoManager* om;
|
||||
#endif
|
||||
QXmppCarbonManager* cm;
|
||||
QXmppMamManager* am;
|
||||
QXmppMucManager* mm;
|
||||
@ -179,9 +195,6 @@ private:
|
||||
QXmppUploadRequestManager* um;
|
||||
QXmppDiscoveryManager* dm;
|
||||
QXmppMessageReceiptManager* rcpm;
|
||||
#ifdef WITH_OMEMO
|
||||
QXmppOmemoManager* om;
|
||||
#endif
|
||||
bool reconnectScheduled;
|
||||
QTimer* reconnectTimer;
|
||||
|
||||
@ -192,11 +205,6 @@ private:
|
||||
bool active;
|
||||
bool notReadyPassword;
|
||||
|
||||
MessageHandler* mh;
|
||||
RosterHandler* rh;
|
||||
VCardHandler* vh;
|
||||
DiscoveryHandler* dh;
|
||||
|
||||
private slots:
|
||||
void onClientStateChange(QXmppClient::State state);
|
||||
void onClientError(QXmppClient::Error err);
|
||||
|
@ -19,27 +19,28 @@
|
||||
#include <QDebug>
|
||||
|
||||
Core::ClientCache::ClientCache():
|
||||
db("clients"),
|
||||
cache(db.addCache<QString, Shared::ClientInfo>("info")),
|
||||
requested(),
|
||||
cache("clients"),
|
||||
specific()
|
||||
{
|
||||
cache.open();
|
||||
db.open();
|
||||
}
|
||||
|
||||
Core::ClientCache::~ClientCache() {
|
||||
cache.close();
|
||||
db.close();
|
||||
}
|
||||
|
||||
void Core::ClientCache::open() {
|
||||
cache.open();}
|
||||
db.open();}
|
||||
|
||||
void Core::ClientCache::close() {
|
||||
cache.close();}
|
||||
db.close();}
|
||||
|
||||
|
||||
bool Core::ClientCache::checkClient(const QString& node, const QString& ver, const QString& hash) {
|
||||
QString id = node + "/" + ver;
|
||||
if (requested.count(id) == 0 && !cache.checkRecord(id)) {
|
||||
if (requested.count(id) == 0 && !cache->checkRecord(id)) {
|
||||
Shared::ClientInfo& info = requested.insert(std::make_pair(id, Shared::ClientInfo())).first->second;
|
||||
info.node = node;
|
||||
info.verification = ver;
|
||||
@ -65,7 +66,7 @@ bool Core::ClientCache::registerClientInfo (
|
||||
|
||||
bool valid = info.valid();
|
||||
if (valid) {
|
||||
cache.addRecord(id, info);
|
||||
cache->addRecord(id, info);
|
||||
} else {
|
||||
info.specificPresence = sourceFullJid;
|
||||
specific.insert(std::make_pair(sourceFullJid, info));
|
||||
|
@ -23,7 +23,8 @@
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include <core/storage/cache.h>
|
||||
#include <cache.h>
|
||||
|
||||
#include <shared/clientinfo.h>
|
||||
#include <shared/identity.h>
|
||||
|
||||
@ -46,8 +47,9 @@ public slots:
|
||||
bool registerClientInfo(const QString& sourceFullJid, const QString& id, const std::set<Shared::Identity>& identities, const std::set<QString>& features);
|
||||
|
||||
private:
|
||||
DataBase db;
|
||||
DataBase::Cache<QString, Shared::ClientInfo>* cache;
|
||||
std::map<QString, Shared::ClientInfo> requested;
|
||||
Cache<QString, Shared::ClientInfo> cache;
|
||||
std::map<QString, Shared::ClientInfo> specific;
|
||||
};
|
||||
|
||||
|
@ -9,4 +9,6 @@ target_sources(squawk PRIVATE
|
||||
discoveryhandler.h
|
||||
omemohandler.cpp
|
||||
omemohandler.h
|
||||
trusthandler.cpp
|
||||
trusthandler.h
|
||||
)
|
||||
|
@ -21,7 +21,11 @@
|
||||
|
||||
Core::DiscoveryHandler::DiscoveryHandler(Core::Account* account):
|
||||
QObject(),
|
||||
acc(account)
|
||||
acc(account) {}
|
||||
|
||||
Core::DiscoveryHandler::~DiscoveryHandler() {}
|
||||
|
||||
void Core::DiscoveryHandler::initialize()
|
||||
{
|
||||
QObject::connect(acc->dm, &QXmppDiscoveryManager::itemsReceived, this, &DiscoveryHandler::onItemsReceived);
|
||||
QObject::connect(acc->dm, &QXmppDiscoveryManager::infoReceived, this, &DiscoveryHandler::onInfoReceived);
|
||||
@ -32,11 +36,6 @@ Core::DiscoveryHandler::DiscoveryHandler(Core::Account* account):
|
||||
acc->dm->setClientCapabilitiesNode("https://git.macaw.me/blue/squawk");
|
||||
}
|
||||
|
||||
Core::DiscoveryHandler::~DiscoveryHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Core::DiscoveryHandler::onItemsReceived(const QXmppDiscoveryIq& items)
|
||||
{
|
||||
QString server = acc->getServer();
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
DiscoveryHandler(Account* account);
|
||||
~DiscoveryHandler();
|
||||
|
||||
void initialize();
|
||||
|
||||
private slots:
|
||||
void onItemsReceived (const QXmppDiscoveryIq& items);
|
||||
void onInfoReceived (const QXmppDiscoveryIq& info);
|
||||
|
@ -22,7 +22,7 @@ Core::OmemoHandler::OmemoHandler(Account* account) :
|
||||
QXmppOmemoStorage(),
|
||||
acc(account),
|
||||
ownDevice(std::nullopt),
|
||||
db("omemo"),
|
||||
db(acc->getName() + "/omemo"),
|
||||
meta(db.addCache<QString, QVariant>("meta")),
|
||||
devices(db.addCache<QString, QHash<uint32_t, Device>>("devices")),
|
||||
preKeyPairs(db.addCache<uint32_t, QByteArray>("preKeyPairs")),
|
||||
@ -155,7 +155,60 @@ QFuture<void> Core::OmemoHandler::resetAll() {
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream& in, QXmppOmemoStorage::Device& device) {
|
||||
in >> device.label;
|
||||
in >> device.keyId;
|
||||
in >> device.session;
|
||||
in >> device.unrespondedSentStanzasCount;
|
||||
in >> device.unrespondedReceivedStanzasCount;
|
||||
in >> device.removalFromDeviceListDate;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
QDataStream & operator << (QDataStream& out, const QXmppOmemoStorage::Device& device) {
|
||||
out << device.label;
|
||||
out << device.keyId;
|
||||
out << device.session;
|
||||
out << device.unrespondedSentStanzasCount;
|
||||
out << device.unrespondedReceivedStanzasCount;
|
||||
out << device.removalFromDeviceListDate;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream& in, QXmppOmemoStorage::OwnDevice& device) {
|
||||
in >> device.id;
|
||||
in >> device.label;
|
||||
in >> device.privateIdentityKey;
|
||||
in >> device.publicIdentityKey;
|
||||
in >> device.latestSignedPreKeyId;
|
||||
in >> device.latestPreKeyId;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
QDataStream & operator << (QDataStream& out, const QXmppOmemoStorage::OwnDevice& device) {
|
||||
out << device.id;
|
||||
out << device.label;
|
||||
out << device.privateIdentityKey;
|
||||
out << device.publicIdentityKey;
|
||||
out << device.latestSignedPreKeyId;
|
||||
out << device.latestPreKeyId;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream& in, QXmppOmemoStorage::SignedPreKeyPair& pair) {
|
||||
in >> pair.creationDate;
|
||||
in >> pair.data;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
QDataStream & operator << (QDataStream& out, const QXmppOmemoStorage::SignedPreKeyPair& pair) {
|
||||
out << pair.creationDate;
|
||||
out << pair.data;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <cache.h>
|
||||
|
||||
Q_DECLARE_METATYPE(QXmppOmemoStorage::OwnDevice);
|
||||
Q_DECLARE_METATYPE(QXmppOmemoStorage::Device);
|
||||
Q_DECLARE_METATYPE(QXmppOmemoStorage::SignedPreKeyPair);
|
||||
|
||||
namespace Core {
|
||||
class Account;
|
||||
@ -63,9 +65,12 @@ private:
|
||||
}
|
||||
|
||||
QDataStream& operator << (QDataStream &out, const QXmppOmemoStorage::Device& device);
|
||||
QDataStream& operator >> (QDataStream &out, QXmppOmemoStorage::Device device);
|
||||
QDataStream& operator >> (QDataStream &in, QXmppOmemoStorage::Device& device);
|
||||
|
||||
QDataStream& operator << (QDataStream &out, const QXmppOmemoStorage::OwnDevice& device);
|
||||
QDataStream& operator >> (QDataStream &in, QXmppOmemoStorage::OwnDevice& device);
|
||||
|
||||
QDataStream& operator << (QDataStream &out, const QXmppOmemoStorage::SignedPreKeyPair& device);
|
||||
QDataStream& operator >> (QDataStream &out, QXmppOmemoStorage::SignedPreKeyPair device);
|
||||
QDataStream& operator >> (QDataStream &in, QXmppOmemoStorage::SignedPreKeyPair& device);
|
||||
|
||||
#endif // CORE_OMEMOHANDLER_H
|
||||
|
@ -26,8 +26,9 @@ Core::RosterHandler::RosterHandler(Core::Account* account):
|
||||
conferences(),
|
||||
groups(),
|
||||
queuedContacts(),
|
||||
outOfRosterContacts()
|
||||
{
|
||||
outOfRosterContacts() {}
|
||||
|
||||
void Core::RosterHandler::initialize() {
|
||||
connect(acc->rm, &QXmppRosterManager::rosterReceived, this, &RosterHandler::onRosterReceived);
|
||||
connect(acc->rm, &QXmppRosterManager::itemAdded, this, &RosterHandler::onRosterItemAdded);
|
||||
connect(acc->rm, &QXmppRosterManager::itemRemoved, this, &RosterHandler::onRosterItemRemoved);
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
void storeConferences();
|
||||
void clearConferences();
|
||||
|
||||
void initialize();
|
||||
|
||||
private slots:
|
||||
void onRosterReceived();
|
||||
void onRosterItemAdded(const QString& bareJid);
|
||||
|
390
core/handlers/trusthandler.cpp
Normal file
390
core/handlers/trusthandler.cpp
Normal file
@ -0,0 +1,390 @@
|
||||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "trusthandler.h"
|
||||
#include "core/account.h"
|
||||
|
||||
using namespace Core;
|
||||
|
||||
Core::TrustHandler::TrustHandler(Account* account):
|
||||
acc(account),
|
||||
db(acc->getName() + "/trust"),
|
||||
protocols(db.createDirectory() + "/protocols"),
|
||||
securityPolicies(db.addCache<QString, uint8_t>("securityPolicies")),
|
||||
ownKeys(db.addCache<QString, QByteArray>("ownKeys")),
|
||||
keysByProtocol()
|
||||
{
|
||||
if (!protocols.open(QIODevice::ReadWrite | QIODevice::Text)) { //never supposed to happen since I have just created a directory;
|
||||
throw DataBase::Directory(protocols.fileName().toStdString());
|
||||
}
|
||||
|
||||
QTextStream in(&protocols);
|
||||
while(!in.atEnd()) {
|
||||
QString protocol = in.readLine();
|
||||
|
||||
if (protocol.size() > 1) { //I'm afraid of reading some nonsence like separately standing \n or EF or BOM, so... let it be at least 2 chars long
|
||||
KeyCache* cache = db.addCache<QString, Keys>(protocol.toStdString());
|
||||
keysByProtocol.insert(std::make_pair(protocol, cache));
|
||||
}
|
||||
}
|
||||
|
||||
protocols.close();
|
||||
db.open();
|
||||
}
|
||||
|
||||
Core::TrustHandler::~TrustHandler() {
|
||||
protocols.close();
|
||||
db.close();
|
||||
}
|
||||
|
||||
Core::TrustHandler::KeyCache * Core::TrustHandler::getCache(const QString& encryption) {
|
||||
std::map<QString, KeyCache*>::iterator itr = keysByProtocol.find(encryption);
|
||||
if (itr == keysByProtocol.end()) {
|
||||
return createNewCache(encryption);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
Core::TrustHandler::KeyCache * Core::TrustHandler::createNewCache(const QString& encryption) {
|
||||
db.close();
|
||||
KeyCache* cache = db.addCache<QString, Keys>(encryption.toStdString());
|
||||
keysByProtocol.insert(std::make_pair(encryption, cache));
|
||||
|
||||
if(!protocols.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
|
||||
throw DataBase::Directory(protocols.fileName().toStdString());
|
||||
}
|
||||
QTextStream out(&protocols);
|
||||
out << encryption + "\n";
|
||||
protocols.close();
|
||||
|
||||
db.open();
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
QFuture<void> Core::TrustHandler::emptyVoidFuture() {
|
||||
QFutureInterface<QXmppOmemoStorage::OmemoData> result(QFutureInterfaceBase::Started);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
|
||||
QFuture<void> Core::TrustHandler::resetAll(const QString& encryption) {
|
||||
securityPolicies->removeRecord(encryption);
|
||||
ownKeys->removeRecord(encryption);
|
||||
getCache(encryption)->drop();
|
||||
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<QXmpp::TrustLevel> Core::TrustHandler::trustLevel(
|
||||
const QString& encryption,
|
||||
const QString& keyOwnerJid,
|
||||
const QByteArray& keyId)
|
||||
{
|
||||
Keys map = getCache(encryption)->getRecord(keyOwnerJid);
|
||||
Shared::TrustLevel level = map.at(keyId);
|
||||
|
||||
QFutureInterface<QXmpp::TrustLevel> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(convert(level));
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::setTrustLevel(
|
||||
const QString& encryption,
|
||||
const QList<QString>& keyOwnerJids,
|
||||
QXmpp::TrustLevel oldTrustLevel,
|
||||
QXmpp::TrustLevel newTrustLevel)
|
||||
{
|
||||
QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys;
|
||||
Shared::TrustLevel oldLevel = convert(oldTrustLevel);
|
||||
Shared::TrustLevel newLevel = convert(newTrustLevel);
|
||||
KeyCache* cache = getCache(encryption);
|
||||
for (const QString& keyOwnerJid : keyOwnerJids) {
|
||||
Keys map = cache->getRecord(keyOwnerJid);
|
||||
uint count = 0;
|
||||
for (std::pair<const QByteArray, Shared::TrustLevel>& pair : map) {
|
||||
Shared::TrustLevel& current = pair.second;
|
||||
if (current == oldLevel) {
|
||||
current = newLevel;
|
||||
modifiedKeys[encryption].insert(keyOwnerJid, pair.first);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
cache->changeRecord(keyOwnerJid, map);
|
||||
}
|
||||
}
|
||||
|
||||
QFutureInterface<QHash<QString, QMultiHash<QString, QByteArray>>> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(modifiedKeys);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<QHash<QString, QMultiHash<QString, QByteArray>>> Core::TrustHandler::setTrustLevel(
|
||||
const QString& encryption,
|
||||
const QMultiHash<QString, QByteArray>& keyIds,
|
||||
QXmpp::TrustLevel trustLevel)
|
||||
{
|
||||
QHash<QString, QMultiHash<QString, QByteArray>> modifiedKeys;
|
||||
Shared::TrustLevel level = convert(trustLevel);
|
||||
KeyCache* cache = getCache(encryption);
|
||||
|
||||
for (MultySB::const_iterator itr = keyIds.begin(), end = keyIds.end(); itr != end; ++itr) {
|
||||
const QString& keyOwnerJid = itr.key();
|
||||
const QByteArray& keyId = itr.value();
|
||||
Keys map = cache->getRecord(keyOwnerJid);
|
||||
std::pair<Keys::iterator, bool> result = map.insert(std::make_pair(keyId, level));
|
||||
if (result.second) {
|
||||
modifiedKeys[encryption].insert(keyOwnerJid, keyId);
|
||||
cache->changeRecord(keyOwnerJid, map);
|
||||
} else if (result.first->second != level) {
|
||||
result.first->second = level;
|
||||
modifiedKeys[encryption].insert(keyOwnerJid, keyId);
|
||||
cache->changeRecord(keyOwnerJid, map);
|
||||
}
|
||||
}
|
||||
|
||||
QFutureInterface<QHash<QString, QMultiHash<QString, QByteArray>>> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(modifiedKeys);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<bool> TrustHandler::hasKey(const QString& encryption,
|
||||
const QString& keyOwnerJid,
|
||||
QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
KeyCache* cache = getCache(encryption);
|
||||
bool found = false;
|
||||
try {
|
||||
Keys map = cache->getRecord(keyOwnerJid);
|
||||
for (const std::pair<const QByteArray, Shared::TrustLevel>& pair : map) {
|
||||
if (trustLevels.testFlag(convert(pair.second))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
|
||||
QFutureInterface<bool> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(found);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<QHash<QString, QHash<QByteArray, QXmpp::TrustLevel>>> TrustHandler::keys(
|
||||
const QString& encryption,
|
||||
const QList<QString>& keyOwnerJids,
|
||||
QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
HSHBTL res;
|
||||
|
||||
KeyCache* cache = getCache(encryption);
|
||||
for (const QString& keyOwnerJid : keyOwnerJids) {
|
||||
try {
|
||||
Keys map = cache->getRecord(keyOwnerJid);
|
||||
QHash<QByteArray, QXmpp::TrustLevel>& pRes = res[keyOwnerJid];
|
||||
for (const std::pair<const QByteArray, Shared::TrustLevel>& pair : map) {
|
||||
QXmpp::TrustLevel level = convert(pair.second);
|
||||
if (!trustLevels || trustLevels.testFlag(level)) {
|
||||
pRes.insert(pair.first, level);
|
||||
}
|
||||
}
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
}
|
||||
|
||||
QFutureInterface<HSHBTL> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(res);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<QHash<QXmpp::TrustLevel, QMultiHash<QString, QByteArray>>> TrustHandler::keys(
|
||||
const QString& encryption,
|
||||
QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
QHash<TL, MultySB> res;
|
||||
KeyCache* cache = getCache(encryption);
|
||||
std::map<QString, Keys> storage = cache->readAll();
|
||||
for (const std::pair<const QString, Keys>& value : storage) {
|
||||
for (const std::pair<const QByteArray, Shared::TrustLevel>& pair : value.second) {
|
||||
QXmpp::TrustLevel level = convert(pair.second);
|
||||
if (!trustLevels || trustLevels.testFlag(level)) {
|
||||
res[level].insert(value.first, pair.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QFutureInterface<QHash<TL, MultySB>> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(res);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::removeKeys(const QString& encryption) {
|
||||
getCache(encryption)->drop();
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::removeKeys(const QString& encryption, const QString& keyOwnerJid) {
|
||||
getCache(encryption)->removeRecord(keyOwnerJid);
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::removeKeys(const QString& encryption, const QList<QByteArray>& keyIds) {
|
||||
std::set<QByteArray> set;
|
||||
for (const QByteArray& keyId : keyIds) {
|
||||
set.insert(keyId);
|
||||
}
|
||||
|
||||
KeyCache* cache = getCache(encryption);
|
||||
std::map<QString, Keys> data = cache->readAll();
|
||||
bool changed = false;
|
||||
for (std::map<QString, Keys>::iterator cItr = data.begin(), cEnd = data.end(); cItr != cEnd; /*no increment*/) {
|
||||
Keys& byOwner = cItr->second;
|
||||
for (Keys::const_iterator itr = byOwner.begin(), end = byOwner.end(); itr != end; /*no increment*/) {
|
||||
const QByteArray& keyId = itr->first;
|
||||
if (set.erase(keyId)) {
|
||||
byOwner.erase(itr++);
|
||||
changed = true;
|
||||
} else {
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
if (byOwner.size() > 0) {
|
||||
data.erase(cItr++);
|
||||
} else {
|
||||
++cItr;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
cache->replaceAll(data);
|
||||
}
|
||||
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::addKeys(
|
||||
const QString& encryption,
|
||||
const QString& keyOwnerJid,
|
||||
const QList<QByteArray>& keyIds,
|
||||
QXmpp::TrustLevel trustLevel)
|
||||
{
|
||||
KeyCache* cache = getCache(encryption);
|
||||
Shared::TrustLevel level = convert(trustLevel);
|
||||
Keys data;
|
||||
bool had = false;
|
||||
try {
|
||||
data = cache->getRecord(keyOwnerJid);
|
||||
had = true;
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
for (const QByteArray& keyId : keyIds) {
|
||||
std::pair<Keys::iterator, bool> result = data.insert(std::make_pair(keyId, level));
|
||||
if (!result.second) {
|
||||
result.first->second = level;
|
||||
}
|
||||
}
|
||||
|
||||
if (had) {
|
||||
cache->changeRecord(keyOwnerJid, data);
|
||||
} else {
|
||||
cache->addRecord(keyOwnerJid, data);
|
||||
}
|
||||
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<QByteArray> TrustHandler::ownKey(const QString& encryption) {
|
||||
QByteArray res;
|
||||
try {
|
||||
res = ownKeys->getRecord(encryption);
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
|
||||
QFutureInterface<QByteArray> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(res);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::resetOwnKey(const QString& encryption) {
|
||||
try {
|
||||
ownKeys->removeRecord(encryption);
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::setOwnKey(const QString& encryption, const QByteArray& keyId) {
|
||||
ownKeys->forceRecord(encryption, keyId);
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<QXmpp::TrustSecurityPolicy> TrustHandler::securityPolicy(const QString& encryption) {
|
||||
QXmpp::TrustSecurityPolicy res;
|
||||
try {
|
||||
res = static_cast<QXmpp::TrustSecurityPolicy>(securityPolicies->getRecord(encryption));
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
|
||||
QFutureInterface<QXmpp::TrustSecurityPolicy> result(QFutureInterfaceBase::Started);
|
||||
result.reportResult(res);
|
||||
result.reportFinished();
|
||||
return result.future();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::resetSecurityPolicy(const QString& encryption) {
|
||||
try {
|
||||
securityPolicies->removeRecord(encryption);
|
||||
} catch (const DataBase::NotFound& e) {}
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
QFuture<void> TrustHandler::setSecurityPolicy(
|
||||
const QString& encryption,
|
||||
QXmpp::TrustSecurityPolicy securityPolicy)
|
||||
{
|
||||
uint8_t pol = securityPolicy;
|
||||
securityPolicies->forceRecord(encryption, pol);
|
||||
|
||||
return emptyVoidFuture();
|
||||
}
|
||||
|
||||
Shared::TrustLevel Core::TrustHandler::convert(Core::TrustHandler::TL level)
|
||||
{
|
||||
switch (level) {
|
||||
case QXmpp::TrustLevel::Undecided: return Shared::TrustLevel::Undecided;
|
||||
case QXmpp::TrustLevel::AutomaticallyDistrusted: return Shared::TrustLevel::AutomaticallyDistrusted;
|
||||
case QXmpp::TrustLevel::ManuallyDistrusted: return Shared::TrustLevel::ManuallyDistrusted;
|
||||
case QXmpp::TrustLevel::AutomaticallyTrusted: return Shared::TrustLevel::AutomaticallyTrusted;
|
||||
case QXmpp::TrustLevel::ManuallyTrusted: return Shared::TrustLevel::ManuallyTrusted;
|
||||
case QXmpp::TrustLevel::Authenticated: return Shared::TrustLevel::Authenticated;
|
||||
}
|
||||
}
|
||||
|
||||
Core::TrustHandler::TL Core::TrustHandler::convert(Shared::TrustLevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case Shared::TrustLevel::Undecided: return QXmpp::TrustLevel::Undecided;
|
||||
case Shared::TrustLevel::AutomaticallyDistrusted: return QXmpp::TrustLevel::AutomaticallyDistrusted;
|
||||
case Shared::TrustLevel::ManuallyDistrusted: return QXmpp::TrustLevel::ManuallyDistrusted;
|
||||
case Shared::TrustLevel::AutomaticallyTrusted: return QXmpp::TrustLevel::AutomaticallyTrusted;
|
||||
case Shared::TrustLevel::ManuallyTrusted: return QXmpp::TrustLevel::ManuallyTrusted;
|
||||
case Shared::TrustLevel::Authenticated: return QXmpp::TrustLevel::Authenticated;
|
||||
}
|
||||
}
|
81
core/handlers/trusthandler.h
Normal file
81
core/handlers/trusthandler.h
Normal file
@ -0,0 +1,81 @@
|
||||
// Squawk messenger.
|
||||
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CORE_TRUSTHANDLER_H
|
||||
#define CORE_TRUSTHANDLER_H
|
||||
|
||||
#include <shared/enums.h>
|
||||
|
||||
#include <QXmppTrustStorage.h>
|
||||
#include <cache.h>
|
||||
|
||||
namespace Core {
|
||||
class Account;
|
||||
|
||||
class TrustHandler : public QXmppTrustStorage {
|
||||
public:
|
||||
TrustHandler(Account* account);
|
||||
~TrustHandler();
|
||||
|
||||
typedef QMultiHash<QString, QByteArray> MultySB;
|
||||
typedef QHash<QString, MultySB> HashSM;
|
||||
typedef const QList<QString>& CLSR;
|
||||
typedef const QList<QByteArray>& CLBAR;
|
||||
typedef const QString& CSR;
|
||||
typedef QXmpp::TrustLevel TL;
|
||||
typedef QHash<QString, QHash<QByteArray, TL>> HSHBTL;
|
||||
|
||||
typedef std::map<QByteArray, Shared::TrustLevel> Keys;
|
||||
typedef DataBase::Cache<QString, Keys> KeyCache;
|
||||
|
||||
virtual QFuture<void> resetAll(CSR encryption);
|
||||
virtual QFuture<TL> trustLevel(CSR encryption, CSR keyOwnerJid, const QByteArray& keyId);
|
||||
virtual QFuture<HashSM> setTrustLevel(CSR encryption, CLSR keyOwnerJids, TL oldTrustLevel, TL newTrustLevel);
|
||||
virtual QFuture<HashSM> setTrustLevel(CSR encryption, const MultySB& keyIds, TL trustLevel);
|
||||
virtual QFuture<bool> hasKey(CSR encryption, CSR keyOwnerJid, QXmpp::TrustLevels trustLevels);
|
||||
virtual QFuture<HSHBTL> keys(CSR encryption, CLSR keyOwnerJids, QXmpp::TrustLevels trustLevels);
|
||||
virtual QFuture<QHash<TL, MultySB>> keys(CSR encryption, QXmpp::TrustLevels trustLevels);
|
||||
virtual QFuture<void> removeKeys(CSR encryption);
|
||||
virtual QFuture<void> removeKeys(CSR encryption, CSR keyOwnerJid);
|
||||
virtual QFuture<void> removeKeys(CSR encryption, CLBAR keyIds);
|
||||
virtual QFuture<void> addKeys(CSR encryption, CSR keyOwnerJid, CLBAR keyIds, TL trustLevel);
|
||||
virtual QFuture<QByteArray> ownKey(CSR encryption);
|
||||
virtual QFuture<void> resetOwnKey(CSR encryption);
|
||||
virtual QFuture<void> setOwnKey(CSR encryption, const QByteArray& keyId);
|
||||
virtual QFuture<QXmpp::TrustSecurityPolicy> securityPolicy(CSR encryption);
|
||||
virtual QFuture<void> resetSecurityPolicy(CSR encryption);
|
||||
virtual QFuture<void> setSecurityPolicy(CSR encryption, QXmpp::TrustSecurityPolicy securityPolicy);
|
||||
|
||||
static TL convert(Shared::TrustLevel level);
|
||||
static Shared::TrustLevel convert(TL level);
|
||||
|
||||
private:
|
||||
static QFuture<void> emptyVoidFuture();
|
||||
KeyCache* createNewCache(const QString& encryption);
|
||||
KeyCache* getCache(const QString& encryption);
|
||||
|
||||
private:
|
||||
Account* acc;
|
||||
DataBase db;
|
||||
QFile protocols;
|
||||
DataBase::Cache<QString, uint8_t>* securityPolicies;
|
||||
DataBase::Cache<QString, QByteArray>* ownKeys;
|
||||
std::map<QString, KeyCache*> keysByProtocol;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CORE_TRUSTHANDLER_H
|
@ -25,10 +25,6 @@ Core::VCardHandler::VCardHandler(Account* account):
|
||||
avatarHash(),
|
||||
avatarType()
|
||||
{
|
||||
connect(acc->vm, &QXmppVCardManager::vCardReceived, this, &VCardHandler::onVCardReceived);
|
||||
//for some reason it doesn't work, launching from common handler
|
||||
//connect(acc->vm, &QXmppVCardManager::clientVCardReceived, this, &VCardHandler::onOwnVCardReceived);
|
||||
|
||||
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||
path += "/" + acc->name;
|
||||
QDir dir(path);
|
||||
@ -67,6 +63,15 @@ Core::VCardHandler::VCardHandler(Account* account):
|
||||
avatarType = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::VCardHandler::~VCardHandler() {}
|
||||
|
||||
void Core::VCardHandler::initialize() {
|
||||
connect(acc->vm, &QXmppVCardManager::vCardReceived, this, &VCardHandler::onVCardReceived);
|
||||
//for some reason it doesn't work, launching from common handler
|
||||
//connect(acc->vm, &QXmppVCardManager::clientVCardReceived, this, &VCardHandler::onOwnVCardReceived);
|
||||
|
||||
if (avatarType.size() != 0) {
|
||||
acc->presence.setVCardUpdateType(QXmppPresence::VCardUpdateValidPhoto);
|
||||
acc->presence.setPhotoHash(avatarHash.toUtf8());
|
||||
@ -75,10 +80,6 @@ Core::VCardHandler::VCardHandler(Account* account):
|
||||
}
|
||||
}
|
||||
|
||||
Core::VCardHandler::~VCardHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Core::VCardHandler::onVCardReceived(const QXmppVCardIq& card)
|
||||
{
|
||||
|
@ -48,6 +48,8 @@ public:
|
||||
void uploadVCard(const Shared::VCard& card);
|
||||
QString getAvatarPath() const;
|
||||
|
||||
void initialize();
|
||||
|
||||
private slots:
|
||||
void onVCardReceived(const QXmppVCardIq& card);
|
||||
void onOwnVCardReceived(const QXmppVCardIq& card);
|
||||
|
@ -1,10 +1,10 @@
|
||||
target_sources(squawk PRIVATE
|
||||
archive.cpp
|
||||
archive.h
|
||||
storage.hpp
|
||||
storage.h
|
||||
# storage.hpp
|
||||
# storage.h
|
||||
urlstorage.cpp
|
||||
urlstorage.h
|
||||
cache.hpp
|
||||
cache.h
|
||||
# cache.hpp
|
||||
# cache.h
|
||||
)
|
||||
|
2
external/qxmpp
vendored
2
external/qxmpp
vendored
@ -1 +1 @@
|
||||
Subproject commit f6e7591e21b4c55319918ac296b2341b2e9f1988
|
||||
Subproject commit befab2fe2e71330170bba48f173258be724c65b9
|
2
external/storage
vendored
2
external/storage
vendored
@ -1 +1 @@
|
||||
Subproject commit 08daad48ad36d9f12dc6485a085190e31e4cf49e
|
||||
Subproject commit a79dae8fd07b36446041f6f85e2ad42cf5ae5264
|
@ -124,5 +124,25 @@ enum class Support {
|
||||
};
|
||||
Q_ENUM_NS(Support)
|
||||
|
||||
enum class TrustLevel {
|
||||
/// The key's trust is not decided.
|
||||
Undecided,
|
||||
/// The key is automatically distrusted (e.g., by the security policy TOAKAFA).
|
||||
/// \see SecurityPolicy
|
||||
AutomaticallyDistrusted,
|
||||
/// The key is manually distrusted (e.g., by clicking a button or \xep{0450, Automatic Trust
|
||||
/// Management (ATM)}).
|
||||
ManuallyDistrusted,
|
||||
/// The key is automatically trusted (e.g., by the client for all keys of a bare JID until one
|
||||
/// of it is authenticated).
|
||||
AutomaticallyTrusted,
|
||||
/// The key is manually trusted (e.g., by clicking a button).
|
||||
ManuallyTrusted,
|
||||
/// The key is authenticated (e.g., by QR code scanning or \xep{0450, Automatic Trust
|
||||
/// Management (ATM)}).
|
||||
Authenticated
|
||||
};
|
||||
Q_ENUM_NS(TrustLevel)
|
||||
|
||||
}
|
||||
#endif // SHARED_ENUMS_H
|
||||
|
Loading…
Reference in New Issue
Block a user