2013-08-07 10:29:56 +01:00
|
|
|
/**
|
|
|
|
* Copyright 2013 Albert Vaca <albertvaka@gmail.com>
|
|
|
|
*
|
|
|
|
* 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 2 of
|
|
|
|
* the License or (at your option) version 3 or any later version
|
|
|
|
* accepted by the membership of KDE e.V. (or its successor approved
|
|
|
|
* by the membership of KDE e.V.), which shall act as a proxy
|
|
|
|
* defined in Section 14 of version 3 of the license.
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
#include "lanlinkprovider.h"
|
2014-09-21 23:59:34 +01:00
|
|
|
#include "core_debug.h"
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2013-10-30 00:18:25 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
|
2013-08-07 10:29:56 +01:00
|
|
|
#include <QHostInfo>
|
|
|
|
#include <QTcpServer>
|
|
|
|
#include <QUdpSocket>
|
2015-04-04 18:05:55 +01:00
|
|
|
#include <QtGlobal>
|
2015-06-14 21:29:00 +01:00
|
|
|
#include <QNetworkSession>
|
|
|
|
#include <QNetworkConfigurationManager>
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-09 22:51:08 +01:00
|
|
|
#include "../../daemon.h"
|
2013-09-09 17:35:56 +01:00
|
|
|
#include "landevicelink.h"
|
2015-07-09 22:51:08 +01:00
|
|
|
#include "lanpairinghandler.h"
|
2015-03-02 04:16:07 +00:00
|
|
|
#include <kdeconnectconfig.h>
|
2015-07-09 22:51:08 +01:00
|
|
|
#include <QDBusPendingReply>
|
2015-07-05 14:23:53 +01:00
|
|
|
#include <QtNetwork/qsslcipher.h>
|
|
|
|
#include <QtNetwork/qsslconfiguration.h>
|
2013-08-12 15:09:52 +01:00
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
LanLinkProvider::LanLinkProvider()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2015-04-04 18:05:55 +01:00
|
|
|
mTcpPort = 0;
|
2013-08-07 10:29:56 +01:00
|
|
|
|
|
|
|
mUdpServer = new QUdpSocket(this);
|
|
|
|
connect(mUdpServer, SIGNAL(readyRead()), this, SLOT(newUdpConnection()));
|
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
mServer = new Server(this);
|
2015-07-09 23:27:27 +01:00
|
|
|
connect(mServer,SIGNAL(newConnection()),this, SLOT(newConnection()));
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-06-14 21:29:00 +01:00
|
|
|
//Detect when a network interface changes status, so we announce ourelves in the new network
|
|
|
|
QNetworkConfigurationManager* networkManager;
|
|
|
|
networkManager = new QNetworkConfigurationManager(this);
|
|
|
|
connect(networkManager, &QNetworkConfigurationManager::configurationChanged, [this, networkManager](QNetworkConfiguration config) {
|
2015-06-15 03:20:59 +01:00
|
|
|
Q_UNUSED(config);
|
2015-06-14 21:29:00 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << config.name() << " state changed to " << config.state();
|
|
|
|
//qCDebug(KDECONNECT_CORE) << "Online status: " << (networkManager->isOnline()? "online":"offline");
|
|
|
|
onNetworkChange();
|
|
|
|
});
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 18:05:55 +01:00
|
|
|
LanLinkProvider::~LanLinkProvider()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::onStart()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2014-11-29 08:11:47 +00:00
|
|
|
mUdpServer->bind(QHostAddress::Any, port, QUdpSocket::ShareAddress);
|
2013-08-08 03:11:20 +01:00
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
mTcpPort = port;
|
2015-07-05 14:23:53 +01:00
|
|
|
while (!mServer->listen(QHostAddress::Any, mTcpPort)) {
|
2014-04-14 20:45:41 +01:00
|
|
|
mTcpPort++;
|
2015-03-22 06:11:50 +00:00
|
|
|
if (mTcpPort > 1764) { //No ports available?
|
|
|
|
qCritical(KDECONNECT_CORE) << "Error opening a port in range 1714-1764";
|
|
|
|
mTcpPort = 0;
|
|
|
|
return;
|
|
|
|
}
|
2014-04-14 20:45:41 +01:00
|
|
|
}
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-04-05 00:32:15 +01:00
|
|
|
onNetworkChange();
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::onStop()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
|
|
|
mUdpServer->close();
|
2015-07-05 14:23:53 +01:00
|
|
|
mServer->close();
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//I'm in a new network, let's be polite and introduce myself
|
2015-04-05 00:32:15 +01:00
|
|
|
void LanLinkProvider::onNetworkChange()
|
2013-08-08 03:11:20 +01:00
|
|
|
{
|
2015-07-05 14:23:53 +01:00
|
|
|
if (!mServer->isListening()) {
|
2015-04-05 00:32:15 +01:00
|
|
|
//Not started
|
2014-04-14 20:45:41 +01:00
|
|
|
return;
|
|
|
|
}
|
2013-10-03 16:25:17 +01:00
|
|
|
|
2015-04-04 18:05:55 +01:00
|
|
|
Q_ASSERT(mTcpPort != 0);
|
|
|
|
|
2015-06-14 21:29:00 +01:00
|
|
|
qCDebug(KDECONNECT_CORE()) << "Broadcasting identity packet";
|
2013-08-07 10:29:56 +01:00
|
|
|
NetworkPackage np("");
|
|
|
|
NetworkPackage::createIdentityPackage(&np);
|
2014-04-14 20:45:41 +01:00
|
|
|
np.set("tcpPort", mTcpPort);
|
|
|
|
mUdpSocket.writeDatagram(np.serialize(), QHostAddress("255.255.255.255"), port);
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2015-01-07 05:48:25 +00:00
|
|
|
//I'm the existing device, a new device is kindly introducing itself.
|
|
|
|
//I will create a TcpSocket and try to connect. This can result in either connected() or connectError().
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::newUdpConnection()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
|
|
|
while (mUdpServer->hasPendingDatagrams()) {
|
2015-07-05 14:23:53 +01:00
|
|
|
|
2013-08-07 10:29:56 +01:00
|
|
|
QByteArray datagram;
|
|
|
|
datagram.resize(mUdpServer->pendingDatagramSize());
|
|
|
|
QHostAddress sender;
|
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
mUdpServer->readDatagram(datagram.data(), datagram.size(), &sender);
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
NetworkPackage* receivedPackage = new NetworkPackage("");
|
2015-01-07 05:48:25 +00:00
|
|
|
bool success = NetworkPackage::unserialize(datagram, receivedPackage);
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "Datagram " << datagram.data() ;
|
2015-07-05 14:23:53 +01:00
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
if (!success || receivedPackage->type() != PACKAGE_TYPE_IDENTITY) {
|
|
|
|
delete receivedPackage;
|
2015-05-05 00:04:50 +01:00
|
|
|
continue;
|
2014-04-14 20:45:41 +01:00
|
|
|
}
|
2013-08-07 12:40:39 +01:00
|
|
|
|
2015-03-02 04:16:07 +00:00
|
|
|
if (receivedPackage->get<QString>("deviceId") == KdeConnectConfig::instance()->deviceId()) {
|
2015-03-22 06:12:04 +00:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "Ignoring my own broadcast";
|
2015-01-07 05:48:25 +00:00
|
|
|
delete receivedPackage;
|
2015-05-05 00:04:50 +01:00
|
|
|
continue;
|
2014-04-14 20:45:41 +01:00
|
|
|
}
|
2013-08-16 04:35:00 +01:00
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
int tcpPort = receivedPackage->get<int>("tcpPort", port);
|
2013-08-08 03:11:20 +01:00
|
|
|
|
2015-03-22 06:12:04 +00:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "Received Udp identity package from" << sender << " asking for a tcp connection on port " << tcpPort;
|
2013-08-08 03:11:20 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
QSslSocket* socket = new QSslSocket(this);
|
2014-04-14 20:45:41 +01:00
|
|
|
receivedIdentityPackages[socket].np = receivedPackage;
|
|
|
|
receivedIdentityPackages[socket].sender = sender;
|
|
|
|
connect(socket, SIGNAL(connected()), this, SLOT(connected()));
|
|
|
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError()));
|
|
|
|
socket->connectToHost(sender, tcpPort);
|
2013-08-07 12:40:39 +01:00
|
|
|
}
|
|
|
|
}
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::connectError()
|
2013-08-07 12:40:39 +01:00
|
|
|
{
|
2015-07-05 14:23:53 +01:00
|
|
|
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
|
2015-01-07 05:48:25 +00:00
|
|
|
if (!socket) return;
|
2013-08-07 12:40:39 +01:00
|
|
|
disconnect(socket, SIGNAL(connected()), this, SLOT(connected()));
|
2015-01-07 05:48:25 +00:00
|
|
|
disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError()));
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-04-05 00:32:15 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "Fallback (1), try reverse connection (send udp packet)";
|
2013-08-08 03:11:20 +01:00
|
|
|
NetworkPackage np("");
|
|
|
|
NetworkPackage::createIdentityPackage(&np);
|
2014-04-14 20:45:41 +01:00
|
|
|
np.set("tcpPort", mTcpPort);
|
|
|
|
mUdpSocket.writeDatagram(np.serialize(), receivedIdentityPackages[socket].sender, port);
|
2013-08-07 12:40:39 +01:00
|
|
|
|
2015-01-07 05:48:25 +00:00
|
|
|
//The socket we created didn't work, and we didn't manage
|
|
|
|
//to create a LanDeviceLink from it, deleting everything.
|
2015-07-14 13:04:04 +01:00
|
|
|
delete receivedIdentityPackages.take(socket).np;
|
2015-01-07 05:48:25 +00:00
|
|
|
delete socket;
|
2013-08-07 12:40:39 +01:00
|
|
|
}
|
|
|
|
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::connected()
|
2013-08-07 12:40:39 +01:00
|
|
|
{
|
2015-07-05 14:23:53 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "Socket connected";
|
2015-07-13 15:25:22 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
|
2014-09-17 15:22:23 +01:00
|
|
|
if (!socket) return;
|
2013-08-07 12:40:39 +01:00
|
|
|
disconnect(socket, SIGNAL(connected()), this, SLOT(connected()));
|
|
|
|
disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError()));
|
|
|
|
|
2013-10-30 00:18:25 +00:00
|
|
|
configureSocket(socket);
|
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
// If socket disconnects due to any reason after connection, link on ssl faliure
|
|
|
|
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
|
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
NetworkPackage* receivedPackage = receivedIdentityPackages[socket].np;
|
|
|
|
const QString& deviceId = receivedPackage->get<QString>("deviceId");
|
2014-09-21 22:54:27 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "Connected" << socket->isWritable();
|
2013-08-07 12:40:39 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
// If network is on ssl, do not believe when they are connected, believe when handshake is completed
|
2013-08-07 12:40:39 +01:00
|
|
|
|
|
|
|
NetworkPackage np2("");
|
|
|
|
NetworkPackage::createIdentityPackage(&np2);
|
2015-07-05 14:23:53 +01:00
|
|
|
socket->write(np2.serialize());
|
|
|
|
bool success = socket->waitForBytesWritten();
|
2013-08-07 12:40:39 +01:00
|
|
|
|
|
|
|
if (success) {
|
2013-08-16 05:22:37 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "Handshaking done (i'm the existing device)";
|
|
|
|
|
|
|
|
// if ssl supported
|
|
|
|
if (NetworkPackage::ProtocolVersion <= receivedPackage->get<int>("protocolVersion")) {
|
|
|
|
// since I support ssl and remote device support ssl
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Setting up ssl server";
|
|
|
|
|
|
|
|
bool isDeviceTrusted = KdeConnectConfig::instance()->trustedDevices().contains(deviceId);
|
|
|
|
|
2015-07-05 22:05:26 +01:00
|
|
|
socket->setPeerVerifyName(receivedPackage->get<QString>("deviceId"));
|
2015-07-05 14:23:53 +01:00
|
|
|
|
|
|
|
if (isDeviceTrusted) {
|
|
|
|
qDebug() << "Device trusted";
|
|
|
|
QString certString = KdeConnectConfig::instance()->getTrustedDevice(deviceId).certificate;
|
|
|
|
socket->addCaCertificate(QSslCertificate(certString.toLatin1()));
|
|
|
|
socket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
|
|
|
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
|
|
|
|
} else {
|
|
|
|
qDebug() << "Device untrusted";
|
|
|
|
// Do not care about ssl errors here, socket will not be closed due to errors because of query peer
|
|
|
|
socket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
|
|
|
}
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Starting server ssl";
|
|
|
|
connect(socket, SIGNAL(encrypted()), this, SLOT(encrypted()));
|
|
|
|
|
|
|
|
socket->startServerEncryption();
|
2015-07-07 19:52:10 +01:00
|
|
|
return; // Return statement prevents from deleting received package, needed in slot "encrypted"
|
2015-07-05 14:23:53 +01:00
|
|
|
} else {
|
2015-07-07 19:52:10 +01:00
|
|
|
addLink(deviceId, socket, receivedPackage);
|
2013-08-16 05:22:37 +01:00
|
|
|
}
|
|
|
|
|
2013-08-07 12:40:39 +01:00
|
|
|
} else {
|
2015-01-07 05:48:25 +00:00
|
|
|
//I think this will never happen, but if it happens the deviceLink
|
|
|
|
//(or the socket that is now inside it) might not be valid. Delete them.
|
2015-04-05 00:32:15 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "Fallback (2), try reverse connection (send udp packet)";
|
2014-04-14 20:45:41 +01:00
|
|
|
mUdpSocket.writeDatagram(np2.serialize(), receivedIdentityPackages[socket].sender, port);
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
delete receivedPackage;
|
2015-01-07 05:48:25 +00:00
|
|
|
receivedIdentityPackages.remove(socket);
|
|
|
|
//We don't delete the socket because now it's owned by the LanDeviceLink
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 13:04:04 +01:00
|
|
|
void LanLinkProvider::encrypted()
|
|
|
|
{
|
2015-07-05 14:23:53 +01:00
|
|
|
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Socket encrypted";
|
2015-07-13 15:25:22 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
|
2015-07-07 19:52:10 +01:00
|
|
|
if (!socket) return;
|
2015-07-05 14:23:53 +01:00
|
|
|
disconnect(socket, SIGNAL(encrypted()), this, SLOT(encrypted()));
|
|
|
|
disconnect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
|
|
|
|
|
|
|
|
NetworkPackage* receivedPackage = receivedIdentityPackages[socket].np;
|
|
|
|
const QString& deviceId = receivedPackage->get<QString>("deviceId");
|
|
|
|
//qCDebug(KDECONNECT_CORE) << "Connected" << socket->isWritable();
|
|
|
|
|
|
|
|
receivedPackage->set("certificate", socket->peerCertificate().toPem());
|
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
addLink(deviceId, socket, receivedPackage);
|
2015-07-05 14:23:53 +01:00
|
|
|
|
|
|
|
// Copied from connected slot, now delete received package
|
|
|
|
delete receivedPackage;
|
|
|
|
receivedIdentityPackages.remove(socket);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-14 13:04:04 +01:00
|
|
|
void LanLinkProvider::sslErrors(const QList<QSslError>& errors)
|
2015-07-05 14:23:53 +01:00
|
|
|
{
|
|
|
|
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
|
2015-07-07 19:52:10 +01:00
|
|
|
if (!socket) return;
|
2015-07-05 14:23:53 +01:00
|
|
|
disconnect(socket, SIGNAL(encrypted()), this, SLOT(encrypted()));
|
|
|
|
disconnect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
|
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
foreach(QSslError error, errors) {
|
|
|
|
qCDebug(KDECONNECT_CORE) << "SSL Error :" << error.errorString();
|
2015-07-09 22:51:08 +01:00
|
|
|
switch (error.error()) {
|
|
|
|
case QSslError::CertificateSignatureFailed:
|
|
|
|
case QSslError::CertificateNotYetValid:
|
|
|
|
case QSslError::CertificateExpired:
|
|
|
|
case QSslError::CertificateUntrusted:
|
|
|
|
case QSslError::SelfSignedCertificate:
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Unpairing device due to " << error.errorString();
|
|
|
|
// Not able to find an alternative now
|
|
|
|
Daemon::instance()->getDevice(socket->peerVerifyName())->unpair();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
// Lots of warnings without this
|
|
|
|
|
|
|
|
}
|
2015-07-07 19:52:10 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 13:04:04 +01:00
|
|
|
delete receivedIdentityPackages.take(socket).np;
|
2015-07-07 19:52:10 +01:00
|
|
|
// Socket disconnects itself on ssl error and will be deleted by deleteLater slot, no need to delete manually
|
2015-07-05 14:23:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-07 05:48:25 +00:00
|
|
|
//I'm the new device and this is the answer to my UDP identity package (no data received yet)
|
2015-07-09 23:27:27 +01:00
|
|
|
void LanLinkProvider::newConnection()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2015-07-14 13:04:04 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "LanLinkProvider newConnection";
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-09 23:27:27 +01:00
|
|
|
while (mServer->hasPendingConnections()) {
|
|
|
|
QSslSocket* socket = mServer->nextPendingConnection();
|
|
|
|
configureSocket(socket);
|
|
|
|
//This socket is still managed by us (and child of the QTcpServer), if
|
|
|
|
//it disconnects before we manage to pass it to a LanDeviceLink, it's
|
|
|
|
//our responsability to delete it. We do so with this connection.
|
|
|
|
connect(socket, SIGNAL(disconnected()),
|
|
|
|
socket, SLOT(deleteLater()));
|
|
|
|
connect(socket, SIGNAL(readyRead()),
|
|
|
|
this, SLOT(dataReceived()));
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-09 23:27:27 +01:00
|
|
|
}
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2015-01-07 05:48:25 +00:00
|
|
|
//I'm the new device and this is the answer to my UDP identity package (data received)
|
2013-08-28 22:47:39 +01:00
|
|
|
void LanLinkProvider::dataReceived()
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2015-07-05 14:23:53 +01:00
|
|
|
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2014-04-14 20:45:41 +01:00
|
|
|
const QByteArray data = socket->readLine();
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "LanLinkProvider received reply:" << data;
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
NetworkPackage* np = new NetworkPackage("");
|
|
|
|
bool success = NetworkPackage::unserialize(data, np);
|
2015-07-13 15:25:22 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
if (!success || np->type() != PACKAGE_TYPE_IDENTITY) {
|
2014-09-21 22:54:27 +01:00
|
|
|
qCDebug(KDECONNECT_CORE) << "LanLinkProvider/newConnection: Not an identification package (wuh?)";
|
2014-04-14 20:45:41 +01:00
|
|
|
return;
|
|
|
|
}
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-14 13:04:04 +01:00
|
|
|
// Needed in "encrypted" if ssl is used, similar to "connected"
|
|
|
|
receivedIdentityPackages[socket].np = np;
|
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
const QString& deviceId = np->get<QString>("deviceId");
|
2014-09-21 22:54:27 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "Handshaking done (i'm the new device)";
|
2013-08-16 05:22:37 +01:00
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
//This socket will now be owned by the LanDeviceLink or we don't want more data to be received, forget about it
|
|
|
|
disconnect(socket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
|
2013-08-16 05:22:37 +01:00
|
|
|
|
2013-08-16 06:20:34 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
if (NetworkPackage::ProtocolVersion <= np->get<int>("protocolVersion")) {
|
|
|
|
// since I support ssl and remote device support ssl
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Setting up ssl client";
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
bool isDeviceTrusted = KdeConnectConfig::instance()->trustedDevices().contains(deviceId);
|
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
socket->setPeerVerifyName(deviceId);
|
2015-07-05 14:23:53 +01:00
|
|
|
|
|
|
|
if (isDeviceTrusted) {
|
|
|
|
qDebug() << "Device trusted";
|
|
|
|
QString certString = KdeConnectConfig::instance()->getTrustedDevice(deviceId).certificate;
|
|
|
|
socket->addCaCertificate(QSslCertificate(certString.toLatin1()));
|
|
|
|
socket->setPeerVerifyMode(QSslSocket::VerifyPeer);
|
|
|
|
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
|
|
|
|
} else {
|
|
|
|
qDebug() << "Device untrusted";
|
|
|
|
// Do not care about ssl errors here, socket will not be closed due to errors because of query peer
|
|
|
|
socket->setPeerVerifyMode(QSslSocket::QueryPeer);
|
|
|
|
}
|
|
|
|
qCDebug(KDECONNECT_CORE) << "Starting client ssl";
|
|
|
|
connect(socket, SIGNAL(encrypted()), this, SLOT(encrypted()));
|
2013-08-07 10:29:56 +01:00
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
socket->startClientEncryption();
|
2015-07-14 13:04:04 +01:00
|
|
|
return;
|
2015-07-05 14:23:53 +01:00
|
|
|
} else {
|
2015-07-07 19:52:10 +01:00
|
|
|
addLink(deviceId, socket, np);
|
2015-07-05 14:23:53 +01:00
|
|
|
}
|
2014-04-14 20:45:41 +01:00
|
|
|
|
2015-07-14 13:04:04 +01:00
|
|
|
delete np;
|
|
|
|
receivedIdentityPackages.remove(socket);
|
|
|
|
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2014-04-15 19:14:22 +01:00
|
|
|
void LanLinkProvider::deviceLinkDestroyed(QObject* destroyedDeviceLink)
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2014-09-21 22:54:27 +01:00
|
|
|
//qCDebug(KDECONNECT_CORE) << "deviceLinkDestroyed";
|
2014-04-15 19:14:22 +01:00
|
|
|
const QString id = destroyedDeviceLink->property("deviceId").toString();
|
2014-04-14 20:45:41 +01:00
|
|
|
QMap< QString, DeviceLink* >::iterator oldLinkIterator = mLinks.find(id);
|
2014-04-15 19:14:22 +01:00
|
|
|
if (oldLinkIterator != mLinks.end() && oldLinkIterator.value() == destroyedDeviceLink) {
|
2014-04-14 20:45:41 +01:00
|
|
|
mLinks.erase(oldLinkIterator);
|
2013-08-16 05:22:37 +01:00
|
|
|
}
|
|
|
|
|
2013-08-07 10:29:56 +01:00
|
|
|
}
|
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
void LanLinkProvider::configureSocket(QSslSocket* socket)
|
2013-08-07 10:29:56 +01:00
|
|
|
{
|
2015-04-04 18:05:55 +01:00
|
|
|
int fd = socket->socketDescriptor();
|
|
|
|
|
|
|
|
socket->setSocketOption(QAbstractSocket::KeepAliveOption, QVariant(1));
|
|
|
|
|
2015-07-05 14:23:53 +01:00
|
|
|
// Configure for ssl
|
|
|
|
socket->setLocalCertificate(KdeConnectConfig::instance()->certificate());
|
|
|
|
socket->setPrivateKey(KdeConnectConfig::instance()->privateKeyPath());
|
|
|
|
socket->setProtocol(QSsl::TlsV1_2);
|
|
|
|
|
2015-04-04 18:05:55 +01:00
|
|
|
#ifdef TCP_KEEPIDLE
|
|
|
|
// time to start sending keepalive packets (seconds)
|
|
|
|
int maxIdle = 10;
|
|
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef TCP_KEEPINTVL
|
|
|
|
// interval between keepalive packets after the initial period (seconds)
|
|
|
|
int interval = 5;
|
|
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef TCP_KEEPCNT
|
|
|
|
// number of missed keepalive packets before disconnecting
|
|
|
|
int count = 3;
|
|
|
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
|
|
|
|
#endif
|
2013-08-07 10:29:56 +01:00
|
|
|
|
|
|
|
}
|
2015-07-05 14:23:53 +01:00
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
void LanLinkProvider::addLink(QString deviceId, QSslSocket* socket, NetworkPackage* receivedPackage) {
|
2015-07-05 14:23:53 +01:00
|
|
|
|
2015-07-07 19:52:10 +01:00
|
|
|
LanDeviceLink* deviceLink = new LanDeviceLink(deviceId, this, socket);
|
|
|
|
connect(deviceLink, SIGNAL(destroyed(QObject*)), this, SLOT(deviceLinkDestroyed(QObject*)));
|
|
|
|
|
|
|
|
// Socket disconnection will now be handled by LanDeviceLink
|
|
|
|
disconnect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
|
|
|
|
|
|
|
|
if (socket->isEncrypted()) {
|
|
|
|
deviceLink->setOnSsl(true);
|
|
|
|
}
|
2015-07-05 14:23:53 +01:00
|
|
|
|
|
|
|
//We kill any possible link from this same device
|
|
|
|
QMap< QString, DeviceLink* >::iterator oldLinkIterator = mLinks.find(deviceLink->deviceId());
|
|
|
|
if (oldLinkIterator != mLinks.end()) {
|
|
|
|
DeviceLink* oldLink = oldLinkIterator.value();
|
|
|
|
disconnect(oldLink, SIGNAL(destroyed(QObject*)),
|
|
|
|
this, SLOT(deviceLinkDestroyed(QObject*)));
|
|
|
|
oldLink->deleteLater();
|
|
|
|
mLinks.erase(oldLinkIterator);
|
|
|
|
}
|
|
|
|
|
|
|
|
mLinks[deviceLink->deviceId()] = deviceLink;
|
|
|
|
|
|
|
|
Q_EMIT onConnectionReceived(*receivedPackage, deviceLink);
|
|
|
|
|
2015-07-13 15:25:22 +01:00
|
|
|
}
|