Now per device per link type pairing handlers are there

This commit is contained in:
Vineet Garg 2015-07-25 17:15:19 +05:30
parent 98d3cf46a6
commit 27515546a0
15 changed files with 172 additions and 77 deletions

View file

@ -25,6 +25,7 @@
#include <QtCrypto>
#include "core/networkpackage.h"
#include "pairinghandler.h"
class NetworkPackage;
class LinkProvider;
@ -38,9 +39,12 @@ public:
DeviceLink(const QString& deviceId, LinkProvider* parent);
virtual ~DeviceLink() { };
virtual QString name() = 0;
const QString& deviceId() { return mDeviceId; }
LinkProvider* provider() { return mLinkProvider; }
virtual PairingHandler* createPairingHandler(Device* device) = 0;
virtual bool sendPackage(NetworkPackage& np) = 0;
virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np) = 0;

View file

@ -30,6 +30,7 @@
#include "uploadjob.h"
#include "downloadjob.h"
#include "socketlinereader.h"
#include "lanpairinghandler.h"
LanDeviceLink::LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket)
: DeviceLink(deviceId, parent)
@ -49,10 +50,20 @@ LanDeviceLink::LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSsl
socket->setParent(this);
}
void LanDeviceLink::setOnSsl(bool value) {
QString LanDeviceLink::name()
{
return "LanDeviceLink";
}
void LanDeviceLink::setOnSsl(bool value)
{
onSsl = value;
}
PairingHandler* LanDeviceLink::createPairingHandler(Device* device)
{
return new LanPairingHandler(device);
}
bool LanDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np)
{

View file

@ -38,7 +38,9 @@ class LanDeviceLink
public:
LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket);
virtual QString name();
void setOnSsl(bool value);
virtual PairingHandler* createPairingHandler(Device* device);
bool sendPackage(NetworkPackage& np);
bool sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np);
UploadJob* sendPayload(NetworkPackage&);

View file

@ -51,8 +51,6 @@ LanLinkProvider::LanLinkProvider()
mServer = new Server(this);
connect(mServer,SIGNAL(newConnection()),this, SLOT(newConnection()));
m_pairingHandler = new LanPairingHandler();
//Detect when a network interface changes status, so we announce ourelves in the new network
QNetworkConfigurationManager* networkManager;
networkManager = new QNetworkConfigurationManager(this);
@ -66,7 +64,6 @@ LanLinkProvider::LanLinkProvider()
LanLinkProvider::~LanLinkProvider()
{
delete m_pairingHandler;
}
void LanLinkProvider::onStart()

View file

@ -21,9 +21,15 @@
#include <kdeconnectconfig.h>
#include "lanpairinghandler.h"
#include "networkpackagetypes.h"
#include "landevicelink.h"
LanPairingHandler::LanPairingHandler()
LanPairingHandler::LanPairingHandler(Device* device)
: PairingHandler(device)
{
m_pairingTimeout.setSingleShot(true);
m_pairingTimeout.setInterval(30 * 1000); //30 seconds of timeout
connect(&m_pairingTimeout, SIGNAL(timeout()),
this, SLOT(pairingTimeout()));
}
void LanPairingHandler::createPairPackage(NetworkPackage& np)
@ -32,51 +38,74 @@ void LanPairingHandler::createPairPackage(NetworkPackage& np)
np.set("publicKey", KdeConnectConfig::instance()->publicKey().toPEM());
}
bool LanPairingHandler::packageReceived(Device *device,const NetworkPackage& np)
bool LanPairingHandler::packageReceived(const NetworkPackage& np)
{
m_pairingTimeout.stop();
//Retrieve their public key
QString keyString = np.get<QString>("publicKey");
device->setPublicKey(QCA::RSAPublicKey::fromPEM(keyString));
if (device->publicKey().isNull()) {
m_device->setPublicKey(QCA::RSAPublicKey::fromPEM(keyString));
if (m_device->publicKey().isNull()) {
return false;
}
return true;
}
bool LanPairingHandler::requestPairing(Device *device)
bool LanPairingHandler::requestPairing()
{
NetworkPackage np(PACKAGE_TYPE_PAIR);
createPairPackage(np);
bool success = device->sendPackage(np);
bool success;
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
success = dl->sendPackage(np);
}
m_pairingTimeout.start();
return success;
}
bool LanPairingHandler::acceptPairing(Device *device)
bool LanPairingHandler::acceptPairing()
{
NetworkPackage np(PACKAGE_TYPE_PAIR);
createPairPackage(np);
bool success = device->sendPackage(np);
bool success;
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
success = dl->sendPackage(np);
}
return success;
}
void LanPairingHandler::rejectPairing(Device *device)
void LanPairingHandler::rejectPairing()
{
// TODO : check status of reject pairing
NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", false);
device->sendPackage(np);
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->sendPackage(np);
}
}
void LanPairingHandler::pairingDone(Device *device)
void LanPairingHandler::pairingDone()
{
// No need to worry, if either of certificate or public key is null an empty qstring will be returned
KdeConnectConfig::instance()->setDeviceProperty(device->id(), "key", device->publicKey().toPEM());
KdeConnectConfig::instance()->setDeviceProperty(device->id(), "certificate", QString(device->certificate().toPem()));
KdeConnectConfig::instance()->setDeviceProperty(m_device->id(), "key", m_device->publicKey().toPEM());
KdeConnectConfig::instance()->setDeviceProperty(m_device->id(), "certificate", QString(m_device->certificate().toPem()));
m_pairingTimeout.stop(); // Just in case it is started
}
void LanPairingHandler::unpair(Device *device) {
void LanPairingHandler::unpair() {
NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", false);
bool success = device->sendPackage(np);
Q_UNUSED(success);
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->sendPackage(np);
}
}
void LanPairingHandler::pairingTimeout()
{
NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", false);
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->sendPackage(np);
}
m_device->pairingTimeout();
}

View file

@ -21,22 +21,34 @@
#ifndef KDECONNECT_LANPAIRINGHANDLER_H
#define KDECONNECT_LANPAIRINGHANDLER_H
#include <QTimer>
#include <backends/devicelink.h>
#include "../../device.h"
#include "../pairinghandler.h"
// This class is used pairing related stuff. It has direct access to links and can directly send packages
class LanPairingHandler
: public PairingHandler
{
private:
QTimer m_pairingTimeout;
private Q_SLOTS:
void pairingTimeout();
public:
LanPairingHandler();
LanPairingHandler(Device* device);
virtual ~LanPairingHandler() { }
virtual void createPairPackage(NetworkPackage& np) Q_DECL_OVERRIDE;
virtual bool packageReceived(Device *device,const NetworkPackage& np) Q_DECL_OVERRIDE;
virtual bool requestPairing(Device *device) Q_DECL_OVERRIDE;
virtual bool acceptPairing(Device *device) Q_DECL_OVERRIDE;
virtual void rejectPairing(Device *device) Q_DECL_OVERRIDE;
virtual void pairingDone(Device *device) Q_DECL_OVERRIDE;
virtual void unpair(Device* device) Q_DECL_OVERRIDE;
virtual bool packageReceived(const NetworkPackage& np) Q_DECL_OVERRIDE;
virtual bool requestPairing() Q_DECL_OVERRIDE;
virtual bool acceptPairing() Q_DECL_OVERRIDE;
virtual void rejectPairing() Q_DECL_OVERRIDE;
virtual void pairingDone() Q_DECL_OVERRIDE;
virtual void unpair() Q_DECL_OVERRIDE;
};

View file

@ -25,6 +25,7 @@
#include <QSslError>
#include <QtNetwork/qsslsocket.h>
// This class overrides QTcpServer to bind QSslSocket to native socket descriptor instead of QTcpSocket
class Server
: public QTcpServer
{

View file

@ -46,11 +46,6 @@ public:
virtual QString name() = 0;
virtual int priority() = 0;
PairingHandler* pairingHandler() { return m_pairingHandler;}
protected:
PairingHandler* m_pairingHandler;
public Q_SLOTS:
virtual void onStart() = 0;

View file

@ -21,6 +21,7 @@
#include "loopbackdevicelink.h"
#include "loopbacklinkprovider.h"
#include "../lan/lanpairinghandler.h"
LoopbackDeviceLink::LoopbackDeviceLink(const QString& deviceId, LoopbackLinkProvider* provider)
: DeviceLink(deviceId, provider)
@ -28,6 +29,15 @@ LoopbackDeviceLink::LoopbackDeviceLink(const QString& deviceId, LoopbackLinkProv
}
QString LoopbackDeviceLink::name()
{
return "LoopbackDeviceLink";
}
PairingHandler* LoopbackDeviceLink::createPairingHandler(Device *device)
{
return new LanPairingHandler(device);
}
bool LoopbackDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& input)
{
if (mPrivateKey.isNull() || key.isNull()) {

View file

@ -32,6 +32,8 @@ class LoopbackDeviceLink
public:
LoopbackDeviceLink(const QString& d, LoopbackLinkProvider* a);
virtual QString name();
virtual PairingHandler* createPairingHandler(Device* device);
virtual bool sendPackage(NetworkPackage& np);
virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np);

View file

@ -20,6 +20,21 @@
#include "pairinghandler.h"
PairingHandler::PairingHandler() {
//gcc complains if we don't add something to compile on a class with virtual functions
PairingHandler::PairingHandler(Device* device)
{
m_device = device;
}
void PairingHandler::addLink(DeviceLink *dl)
{
m_deviceLinks.append(dl);
}
void PairingHandler::linkDestroyed(QObject* o)
{
DeviceLink* dl = static_cast<DeviceLink*>(o);
m_deviceLinks.removeOne(dl);
if (m_deviceLinks.isEmpty()) {
Q_EMIT noLinkAvailable();
}
}

View file

@ -21,23 +21,35 @@
#ifndef KDECONNECT_PAIRINGHANDLER_H
#define KDECONNECT_PAIRINGHANDLER_H
#include "device.h"
#include "networkpackage.h"
#include "devicelink.h"
#include <networkpackage.h>
#include <device.h>
class PairingHandler {
class PairingHandler : public QObject
{
Q_OBJECT
protected:
Device* m_device;
QVector<DeviceLink*> m_deviceLinks;
public:
PairingHandler();
PairingHandler(Device* device);
virtual ~PairingHandler() { }
void addLink(DeviceLink* dl);
virtual void createPairPackage(NetworkPackage& np) = 0;
virtual bool packageReceived(Device *device,const NetworkPackage& np) = 0;
virtual bool requestPairing(Device *device) = 0;
virtual bool acceptPairing(Device *device) = 0;
virtual void rejectPairing(Device *device) = 0;
virtual void pairingDone(Device *device) = 0;
virtual void unpair(Device *device) = 0;
virtual bool packageReceived(const NetworkPackage& np) = 0;
virtual bool requestPairing() = 0;
virtual bool acceptPairing() = 0;
virtual void rejectPairing() = 0;
virtual void pairingDone() = 0;
virtual void unpair() = 0;
public Q_SLOTS:
void linkDestroyed(QObject*);
Q_SIGNALS:
void noLinkAvailable();
};

View file

@ -58,11 +58,6 @@ Device::Device(QObject* parent, const QString& id)
m_deviceType = str2type(info.deviceType);
m_publicKey = QCA::RSAPublicKey::fromPEM(info.publicKey);
m_pairingTimeout.setSingleShot(true);
m_pairingTimeout.setInterval(30 * 1000); //30 seconds of timeout
connect(&m_pairingTimeout, SIGNAL(timeout()),
this, SLOT(pairingTimeout()));
//Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
}
@ -93,7 +88,7 @@ Device::Device(QObject* parent, const NetworkPackage& identityPackage, DeviceLin
Device::~Device()
{
Q_FOREACH(PairingHandler* ph, m_pairingHandlers) delete ph; // Delete all pairing handlers on deletion of device
}
bool Device::hasPlugin(const QString& name) const
@ -209,8 +204,8 @@ void Device::requestPair()
m_pairStatus = Device::Requested;
//Send our own public key
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
bool success = dl->provider()->pairingHandler()->requestPairing(this);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
bool success = ph->requestPairing();
if (!success) {
m_pairStatus = Device::NotPaired;
@ -222,15 +217,13 @@ void Device::requestPair()
if (m_pairStatus == Device::Paired) {
return;
}
m_pairingTimeout.start();
}
void Device::unpair()
{
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->provider()->pairingHandler()->unpair(this);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
ph->unpair();
}
unpairInternal();
@ -249,9 +242,6 @@ void Device::unpairInternal()
void Device::pairingTimeout()
{
NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", false);
sendPackage(np);
m_pairStatus = Device::NotPaired;
Q_EMIT pairingFailed(i18n("Timed out"));
}
@ -302,6 +292,15 @@ void Device::addLink(const NetworkPackage& identityPackage, DeviceLink* link)
plugin->connected();
}
}
// One pairing handler per type of device link, so check if there is already a pairing handler of same type, if not add it to the list
if (!m_pairingHandlers.contains(link->name())) {
PairingHandler* pairingHandler = link->createPairingHandler(this);
m_pairingHandlers.insert(link->name(), pairingHandler);
connect(m_pairingHandlers[link->name()], SIGNAL(noLinkAvailable()), this, SLOT(destroyPairingHandler()));
}
m_pairingHandlers[link->name()]->addLink(link);
connect(link, SIGNAL(destroyed(QObject*)), m_pairingHandlers[link->name()], SLOT(linkDestroyed(QObject*)));
}
void Device::linkDestroyed(QObject* o)
@ -321,6 +320,13 @@ void Device::removeLink(DeviceLink* link)
}
}
void Device::destroyPairingHandler()
{
PairingHandler* ph = qobject_cast<PairingHandler*>(sender());
m_pairingHandlers.remove(m_pairingHandlers.key(ph));
delete ph;
}
bool Device::sendPackage(NetworkPackage& np)
{
if (np.type() != PACKAGE_TYPE_PAIR && isPaired()) {
@ -349,12 +355,11 @@ void Device::privateReceivedPackage(const NetworkPackage& np)
qCDebug(KDECONNECT_CORE) << "Already" << (wantsPair? "paired":"unpaired");
if (m_pairStatus == Device::Requested) {
m_pairStatus = Device::NotPaired;
m_pairingTimeout.stop();
Q_EMIT pairingFailed(i18n("Canceled by other peer"));
} else if (m_pairStatus == Device::Paired) {
// If other request's pairing, and we have pair status Paired, send accept pairing
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->provider()->pairingHandler()->acceptPairing(this);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
ph->acceptPairing();
}
}
return;
@ -362,12 +367,11 @@ void Device::privateReceivedPackage(const NetworkPackage& np)
if (wantsPair) {
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
bool success = dl->provider()->pairingHandler()->packageReceived(this, np);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
bool success = ph->packageReceived(np);
if (!success) {
if (m_pairStatus == Device::Requested) {
m_pairStatus = Device::NotPaired;
m_pairingTimeout.stop();
}
Q_EMIT pairingFailed(i18n("Received incorrect key"));
return;
@ -395,7 +399,6 @@ void Device::privateReceivedPackage(const NetworkPackage& np)
m_pairStatus = Device::NotPaired;
if (prevPairStatus == Device::Requested) {
m_pairingTimeout.stop();
Q_EMIT pairingFailed(i18n("Canceled by other peer"));
} else if (prevPairStatus == Device::Paired) {
unpairInternal();
@ -431,8 +434,8 @@ void Device::rejectPairing()
m_pairStatus = Device::NotPaired;
Q_FOREACH(DeviceLink* link, m_deviceLinks) {
link->provider()->pairingHandler()->rejectPairing(this);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
ph->rejectPairing();
}
Q_EMIT pairingFailed(i18n("Canceled by the user"));
@ -446,8 +449,8 @@ void Device::acceptPairing()
qCDebug(KDECONNECT_CORE) << "Accepted pairing";
bool success;
Q_FOREACH(DeviceLink* link, m_deviceLinks) {
success = link->provider()->pairingHandler()->acceptPairing(this);
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
success = ph->acceptPairing();
}
if (!success) {
@ -466,8 +469,6 @@ void Device::setAsPaired()
m_pairStatus = Device::Paired;
m_pairingTimeout.stop(); //Just in case it was started
//Save device info in the config
KdeConnectConfig::instance()->addTrustedDevice(id(), name(), type2str(m_deviceType), m_publicKey.toPEM(), QString::fromLatin1(m_certificate.toPem()));

View file

@ -26,14 +26,14 @@
#include <QVector>
#include <QSet>
#include <QSslKey>
#include <QTimer>
#include <QtCrypto>
#include <QtNetwork/qsslcertificate.h>
#include <QSslCertificate>
#include "networkpackage.h"
class DeviceLink;
class KdeConnectPlugin;
class PairingHandler;
class KDECONNECTCORE_EXPORT Device
: public QObject
@ -109,6 +109,8 @@ public:
Q_SCRIPTABLE QString pluginsConfigFile() const;
void pairingTimeout();
public Q_SLOTS:
///sends a @p np package to the device
virtual bool sendPackage(NetworkPackage& np);
@ -124,7 +126,7 @@ public Q_SLOTS:
private Q_SLOTS:
void privateReceivedPackage(const NetworkPackage& np);
void linkDestroyed(QObject* o);
void pairingTimeout();
void destroyPairingHandler();
Q_SIGNALS:
Q_SCRIPTABLE void pluginsChanged();
@ -154,10 +156,10 @@ private: //Fields (TODO: dPointer!)
QVector<DeviceLink*> m_deviceLinks;
QHash<QString, KdeConnectPlugin*> m_plugins;
QMap<QString, PairingHandler*> m_pairingHandlers;
QMultiMap<QString, KdeConnectPlugin*> m_pluginsByIncomingInterface;
QMultiMap<QString, KdeConnectPlugin*> m_pluginsByOutgoingInterface;
QTimer m_pairingTimeout;
const QSet<QString> m_incomingCapabilities;
const QSet<QString> m_outgoingCapabilities;

View file

@ -24,6 +24,8 @@
#include <KJob>
#include <KProcess>
#include <QTimer>
#include "sftpplugin.h"
class Mounter