diff --git a/src/mqtt/qmqtt_client.cpp b/src/mqtt/qmqtt_client.cpp index dc83743..53284fd 100644 --- a/src/mqtt/qmqtt_client.cpp +++ b/src/mqtt/qmqtt_client.cpp @@ -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, diff --git a/src/mqtt/qmqtt_client.h b/src/mqtt/qmqtt_client.h index cb0f95d..de730d1 100644 --- a/src/mqtt/qmqtt_client.h +++ b/src/mqtt/qmqtt_client.h @@ -39,6 +39,10 @@ #include #include +#ifndef QT_NO_SSL +QT_FORWARD_DECLARE_CLASS(QSslConfiguration) +#endif // QT_NO_SSL + namespace QMQTT { static const quint8 LIBRARY_VERSION_MAJOR = 0; @@ -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, diff --git a/src/mqtt/qmqtt_client_p.cpp b/src/mqtt/qmqtt_client_p.cpp index 3af3ede..4a386b7 100644 --- a/src/mqtt/qmqtt_client_p.cpp +++ b/src/mqtt/qmqtt_client_p.cpp @@ -34,6 +34,11 @@ #include "qmqtt_message.h" #include #include +#ifndef QT_NO_SSL +#include +#include +#include +#endif // QT_NO_SSL Q_LOGGING_CATEGORY(client, "qmqtt.client") @@ -61,42 +66,46 @@ 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 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"; @@ -104,8 +113,15 @@ void QMQTT::ClientPrivate::init(const QString& hostName, const quint16 port, con } else { - _network.reset(new Network); + init(new Network); } +} + +void QMQTT::ClientPrivate::init(NetworkInterface* network) +{ + Q_Q(Client); + + _network.reset(network); initializeErrorHash(); diff --git a/src/mqtt/qmqtt_client_p.h b/src/mqtt/qmqtt_client_p.h index 55ddd59..1fd92f2 100644 --- a/src/mqtt/qmqtt_client_p.h +++ b/src/mqtt/qmqtt_client_p.h @@ -38,6 +38,10 @@ #include "qmqtt_ssl_network_p.h" #include +#ifndef QT_NO_SSL +QT_FORWARD_DECLARE_CLASS(QSslConfiguration) +#endif // QT_NO_SSL + namespace QMQTT { class ClientPrivate @@ -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; diff --git a/src/mqtt/qmqtt_ssl_network.cpp b/src/mqtt/qmqtt_ssl_network.cpp index 4775383..29943f1 100644 --- a/src/mqtt/qmqtt_ssl_network.cpp +++ b/src/mqtt/qmqtt_ssl_network.cpp @@ -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(); diff --git a/src/mqtt/qmqtt_ssl_network_p.h b/src/mqtt/qmqtt_ssl_network_p.h index 555cb65..02ddb50 100644 --- a/src/mqtt/qmqtt_ssl_network_p.h +++ b/src/mqtt/qmqtt_ssl_network_p.h @@ -44,6 +44,8 @@ #ifndef QT_NO_SSL +QT_FORWARD_DECLARE_CLASS(QSslConfiguration) + namespace QMQTT { class SocketInterface; @@ -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(); diff --git a/src/mqtt/qmqtt_ssl_socket.cpp b/src/mqtt/qmqtt_ssl_socket.cpp index e9c7049..8c3cbca 100644 --- a/src/mqtt/qmqtt_ssl_socket.cpp +++ b/src/mqtt/qmqtt_ssl_socket.cpp @@ -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(), @@ -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()) { diff --git a/src/mqtt/qmqtt_ssl_socket_p.h b/src/mqtt/qmqtt_ssl_socket_p.h index a5cc147..9b6a7c0 100644 --- a/src/mqtt/qmqtt_ssl_socket_p.h +++ b/src/mqtt/qmqtt_ssl_socket_p.h @@ -41,6 +41,7 @@ QT_FORWARD_DECLARE_CLASS(QSslSocket) QT_FORWARD_DECLARE_CLASS(QSslError) +QT_FORWARD_DECLARE_CLASS(QSslConfiguration) namespace QMQTT { @@ -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();