Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use QSslConfiguration to setup an ssl connection #90

Merged
merged 2 commits into from
Feb 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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