Skip to content

Commit

Permalink
Merge pull request #90 from ejvr/emqtt
Browse files Browse the repository at this point in the history
Use QSslConfiguration to setup an ssl connection
  • Loading branch information
mwallnoefer authored Feb 20, 2017
2 parents a658139 + ea08f26 commit b0eece3
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 37 deletions.
13 changes: 13 additions & 0 deletions src/mqtt/qmqtt_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ QMQTT::Client::Client(const QHostAddress& host,
d->init(host, port);
}

#ifndef QT_NO_SSL
QMQTT::Client::Client(const QString &hostName,
const quint16 port,
const QSslConfiguration &config,
const bool ignoreSelfSigned, QObject *parent)
: QObject(parent)
, d_ptr(new ClientPrivate(this))
{
Q_D(Client);
d->init(hostName, port, config, ignoreSelfSigned);
}
#endif // QT_NO_SSL

QMQTT::Client::Client(const QString &hostName,
const quint16 port,
const bool ssl,
Expand Down
16 changes: 16 additions & 0 deletions src/mqtt/qmqtt_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
#include <QScopedPointer>
#include <QHostAddress>

#ifndef QT_NO_SSL
QT_FORWARD_DECLARE_CLASS(QSslConfiguration)
#endif // QT_NO_SSL

namespace QMQTT {

static const quint8 LIBRARY_VERSION_MAJOR = 0;
Expand Down Expand Up @@ -116,6 +120,18 @@ class Q_MQTT_EXPORT Client : public QObject
const quint16 port = 1883,
QObject* parent = NULL);

#ifndef QT_NO_SSL
Client(const QString& hostName,
const quint16 port,
const QSslConfiguration& config,
const bool ignoreSelfSigned=false,
QObject* parent = NULL);
#endif // QT_NO_SSL

// This function is provided for backward compatibility with older versions of QMQTT.
// If the ssl parameter is true, this function will load a private key ('cert.key') and a local
// certificate ('cert.crt') from the current working directory. It will also set PeerVerifyMode
// to None. This may not be the safest way to set up a SSL connection.
Client(const QString& hostName,
const quint16 port,
const bool ssl,
Expand Down
56 changes: 36 additions & 20 deletions src/mqtt/qmqtt_client_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
#include "qmqtt_message.h"
#include <QLoggingCategory>
#include <QUuid>
#ifndef QT_NO_SSL
#include <QFile>
#include <QSslConfiguration>
#include <QSslKey>
#endif // QT_NO_SSL

Q_LOGGING_CATEGORY(client, "qmqtt.client")

Expand Down Expand Up @@ -61,51 +66,62 @@ QMQTT::ClientPrivate::~ClientPrivate()

void QMQTT::ClientPrivate::init(const QHostAddress& host, const quint16 port, NetworkInterface* network)
{
Q_Q(Client);

_host = host;
_port = port;
if(network == NULL)
{
_network.reset(new Network);
init(new Network);
}
else
{
_network.reset(network);
init(network);
}

initializeErrorHash();

QObject::connect(&_timer, &QTimer::timeout, q, &Client::onTimerPingReq);
QObject::connect(_network.data(), &Network::connected,
q, &Client::onNetworkConnected);
QObject::connect(_network.data(), &Network::disconnected,
q, &Client::onNetworkDisconnected);
QObject::connect(_network.data(), &Network::received,
q, &Client::onNetworkReceived);
QObject::connect(_network.data(), &Network::error,
q, &Client::onNetworkError);
}

void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port, const bool ssl, const bool ignoreSelfSigned)
#ifndef QT_NO_SSL
void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port,
const QSslConfiguration &config, const bool ignoreSelfSigned)
{
Q_Q(Client);
_hostName = hostName;
_port = port;
init(new SslNetwork(config, ignoreSelfSigned));
}
#endif // QT_NO_SSL

void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port, const bool ssl,
const bool ignoreSelfSigned)
{
_hostName = hostName;
_port = port;
if (ssl)
{
#ifndef QT_NO_SSL
_network.reset(new SslNetwork(ignoreSelfSigned));
QSslConfiguration sslConf = QSslConfiguration::defaultConfiguration();
QList<QSslCertificate> certs = QSslCertificate::fromPath(QStringLiteral("./cert.crt"));
if (!certs.isEmpty())
sslConf.setLocalCertificate(certs.first());
QFile file(QStringLiteral("./cert.key"));
if (file.open(QIODevice::ReadOnly)) {
sslConf.setPrivateKey(QSslKey(file.readAll(), QSsl::Rsa));
}
sslConf.setPeerVerifyMode(QSslSocket::VerifyNone);
init(hostName, port, sslConf, ignoreSelfSigned);
#else
Q_UNUSED(ignoreSelfSigned)
qCritical() << "SSL not supported in this QT build";
#endif // QT_NO_SSL
}
else
{
_network.reset(new Network);
init(new Network);
}
}

void QMQTT::ClientPrivate::init(NetworkInterface* network)
{
Q_Q(Client);

_network.reset(network);

initializeErrorHash();

Expand Down
9 changes: 9 additions & 0 deletions src/mqtt/qmqtt_client_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#include "qmqtt_ssl_network_p.h"
#include <QTimer>

#ifndef QT_NO_SSL
QT_FORWARD_DECLARE_CLASS(QSslConfiguration)
#endif // QT_NO_SSL

namespace QMQTT {

class ClientPrivate
Expand All @@ -47,7 +51,12 @@ class ClientPrivate
~ClientPrivate();

void init(const QHostAddress& host, const quint16 port, NetworkInterface* network = NULL);
#ifndef QT_NO_SSL
void init(const QString& hostName, const quint16 port, const QSslConfiguration& config,
const bool ignoreSelfSigned=false);
#endif // QT_NO_SSL
void init(const QString& hostName, const quint16 port, const bool ssl, const bool ignoreSelfSigned);
void init(NetworkInterface* network);

QHostAddress _host;
QString _hostName;
Expand Down
4 changes: 2 additions & 2 deletions src/mqtt/qmqtt_ssl_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ const quint16 DEFAULT_PORT = 8883;
const bool DEFAULT_AUTORECONNECT = false;
const int DEFAULT_AUTORECONNECT_INTERVAL_MS = 5000;

QMQTT::SslNetwork::SslNetwork(bool ignoreSelfSigned, QObject* parent)
QMQTT::SslNetwork::SslNetwork(const QSslConfiguration &config, bool ignoreSelfSigned, QObject* parent)
: NetworkInterface(parent)
, _port(DEFAULT_PORT)
, _hostName(DEFAULT_HOST_NAME)
, _autoReconnect(DEFAULT_AUTORECONNECT)
, _autoReconnectInterval(DEFAULT_AUTORECONNECT_INTERVAL_MS)
, _bytesRemaining(0)
, _socket(new QMQTT::SslSocket(ignoreSelfSigned))
, _socket(new QMQTT::SslSocket(config, ignoreSelfSigned))
, _autoReconnectTimer(new QMQTT::Timer)
{
initialize();
Expand Down
4 changes: 3 additions & 1 deletion src/mqtt/qmqtt_ssl_network_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

#ifndef QT_NO_SSL

QT_FORWARD_DECLARE_CLASS(QSslConfiguration)

namespace QMQTT {

class SocketInterface;
Expand All @@ -54,7 +56,7 @@ class SslNetwork : public NetworkInterface
Q_OBJECT

public:
SslNetwork(bool ignoreSelfSigned, QObject* parent = NULL);
SslNetwork(const QSslConfiguration& config, bool ignoreSelfSigned, QObject* parent = NULL);
SslNetwork(SocketInterface* socketInterface, TimerInterface* timerInterface,
QObject* parent = NULL);
~SslNetwork();
Expand Down
24 changes: 11 additions & 13 deletions src/mqtt/qmqtt_ssl_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@

#ifndef QT_NO_SSL

QMQTT::SslSocket::SslSocket(bool ignoreSelfSigned, QObject* parent)
QMQTT::SslSocket::SslSocket(const QSslConfiguration &config, bool ignoreSelfSigned, QObject* parent)
: SocketInterface(parent)
, _socket(new QSslSocket)
, _ignoreSelfSigned(ignoreSelfSigned)
{
_socket->setSslConfiguration(config);
connect(_socket.data(), &QSslSocket::encrypted, this, &SocketInterface::connected);
connect(_socket.data(), &QSslSocket::disconnected, this, &SocketInterface::disconnected);
connect(_socket.data(),
Expand Down Expand Up @@ -73,16 +74,9 @@ void QMQTT::SslSocket::connectToHost(const QHostAddress& address, quint16 port)
emit _socket->error(QAbstractSocket::ConnectionRefusedError);
}

//put the crt and key file into application running directory
//todo:set file path on instance if necessary
void QMQTT::SslSocket::connectToHost(const QString& hostName, quint16 port)
{
QSslConfiguration sslConf = _socket.data()->sslConfiguration();
sslConf.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral("./cert.crt")).first()); //LocalCertificate
_socket.data()->setSslConfiguration(sslConf);
_socket.data()->setPrivateKey(QStringLiteral("./cert.key")); //LocalPrivateKey
_socket->connectToHostEncrypted(hostName, port);
_socket.data()->setPeerVerifyMode(QSslSocket::VerifyNone); //important

if (!_socket->waitForEncrypted())
{
Expand All @@ -107,13 +101,17 @@ QAbstractSocket::SocketError QMQTT::SslSocket::error() const

void QMQTT::SslSocket::sslErrors(const QList<QSslError> &errors)
{
Q_UNUSED(errors);

if (_ignoreSelfSigned)
if (!_ignoreSelfSigned)
return;
for (QSslError error: errors)
{
// allow self-signed certificates
_socket->ignoreSslErrors();
if (error.error() != QSslError::SelfSignedCertificate ||
error.error() != QSslError::SelfSignedCertificateInChain)
{
return;
}
}
_socket->ignoreSslErrors();
}

#endif // QT_NO_SSL
3 changes: 2 additions & 1 deletion src/mqtt/qmqtt_ssl_socket_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

QT_FORWARD_DECLARE_CLASS(QSslSocket)
QT_FORWARD_DECLARE_CLASS(QSslError)
QT_FORWARD_DECLARE_CLASS(QSslConfiguration)

namespace QMQTT
{
Expand All @@ -49,7 +50,7 @@ class SslSocket : public SocketInterface
{
Q_OBJECT
public:
explicit SslSocket(bool ignoreSelfSigned, QObject* parent = NULL);
explicit SslSocket(const QSslConfiguration &config, bool ignoreSelfSigned, QObject* parent = NULL);
virtual ~SslSocket();

virtual QIODevice *ioDevice();
Expand Down

0 comments on commit b0eece3

Please sign in to comment.