diff options
| author | Linus Jahn <lnj@kaidan.im> | 2019-12-14 22:47:28 +0100 |
|---|---|---|
| committer | LNJ <lnj@kaidan.im> | 2020-01-20 17:14:49 +0100 |
| commit | 28411b5995553eb3a50c826c55517b4c610959c2 (patch) | |
| tree | c22ea3b5bd5c1de2831cb3141940038180ce878e /src/client | |
| parent | 55966be2e3e80bd5ab2cc86da2492963dd8127ee (diff) | |
| download | qxmpp-28411b5995553eb3a50c826c55517b4c610959c2.tar.gz | |
Move TLS negotiation into new QXmppTlsManager
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/QXmppClient.cpp | 45 | ||||
| -rw-r--r-- | src/client/QXmppClient.h | 5 | ||||
| -rw-r--r-- | src/client/QXmppOutgoingClient.cpp | 42 | ||||
| -rw-r--r-- | src/client/QXmppTlsManager.cpp | 74 | ||||
| -rw-r--r-- | src/client/QXmppTlsManager.h | 45 |
5 files changed, 168 insertions, 43 deletions
diff --git a/src/client/QXmppClient.cpp b/src/client/QXmppClient.cpp index 523a9e79..db56776a 100644 --- a/src/client/QXmppClient.cpp +++ b/src/client/QXmppClient.cpp @@ -32,6 +32,7 @@ #include "QXmppMessage.h" #include "QXmppUtils.h" +#include "QXmppTlsManager.h" #include "QXmppRosterManager.h" #include "QXmppVCardManager.h" #include "QXmppVersionManager.h" @@ -146,6 +147,7 @@ QXmppClient::QXmppClient(QObject *parent) // logging setLogger(QXmppLogger::getLogger()); + addExtension(new QXmppTlsManager); addExtension(new QXmppRosterManager(this)); addExtension(new QXmppVCardManager); addExtension(new QXmppVersionManager); @@ -447,15 +449,54 @@ QAbstractSocket::SocketError QXmppClient::socketError() } /// Returns the human-readable description of the last socket error if error() is QXmppClient::SocketError. -/// QString QXmppClient::socketErrorString() const { return d->stream->socket()->errorString(); } -/// Returns the XMPP stream error if QXmppClient::Error is QXmppClient::XmppStreamError. +/// Returns true, if the used socket supports SSL / TLS encryption. +/// +/// This is useful for checking whether TLS can be enabled. It is used by the +/// \c QXmppTlsManager. /// +/// \since QXmpp 1.2 + +bool QXmppClient::socketSupportsSsl() const +{ + return d->stream->socket()->supportsSsl(); +} + +/// Returns true, if the socket used for connection to the XMPP server +/// currently uses SSL / TLS encryption. +/// +/// When using STARTTLS, this is false at first and becomes true later. +/// +/// \since QXmpp 1.2 + +bool QXmppClient::isSocketEncrypted() const +{ + return d->stream->socket()->isEncrypted(); +} + +/// If the socket supports SSL / TLS encryption, this method can be used to +/// enable it. +/// +/// This is used by the \c QXmppTlsManager to enable SSL / TLS encryption for +/// STARTTLS. +/// +/// \note You should usually not use this method manually. If you want to +/// enable or disable TLS encryption, you can set this in the +/// \c QXmppConfiguration provided to \c connectToServer(). +/// +/// \since QXmpp 1.2 + +void QXmppClient::startSocketEncryption() +{ + d->stream->socket()->startClientEncryption(); +} + +/// Returns the XMPP stream error if QXmppClient::Error is QXmppClient::XmppStreamError. QXmppStanza::Error::Condition QXmppClient::xmppStreamError() { diff --git a/src/client/QXmppClient.h b/src/client/QXmppClient.h index 2ad60d05..7d2dd61b 100644 --- a/src/client/QXmppClient.h +++ b/src/client/QXmppClient.h @@ -175,6 +175,11 @@ public: QAbstractSocket::SocketError socketError(); QString socketErrorString() const; + + bool socketSupportsSsl() const; + bool isSocketEncrypted() const; + void startSocketEncryption(); + State state() const; QXmppStanza::Error::Condition xmppStreamError(); diff --git a/src/client/QXmppOutgoingClient.cpp b/src/client/QXmppOutgoingClient.cpp index 1b73542e..8cbde9e2 100644 --- a/src/client/QXmppOutgoingClient.cpp +++ b/src/client/QXmppOutgoingClient.cpp @@ -392,40 +392,9 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv) QXmppStreamFeatures features; features.parse(nodeRecv); - if(features.clientStateIndicationMode() == QXmppStreamFeatures::Enabled) + if (features.clientStateIndicationMode() == QXmppStreamFeatures::Enabled) d->clientStateIndicationEnabled = true; - if (!socket()->isEncrypted()) - { - // determine TLS mode to use - const QXmppConfiguration::StreamSecurityMode localSecurity = configuration().streamSecurityMode(); - const QXmppStreamFeatures::Mode remoteSecurity = features.tlsMode(); - if (!socket()->supportsSsl() && - (localSecurity == QXmppConfiguration::TLSRequired || - remoteSecurity == QXmppStreamFeatures::Required)) - { - warning("Disconnecting as TLS is required, but SSL support is not available"); - disconnectFromHost(); - return; - } - if (localSecurity == QXmppConfiguration::TLSRequired && - remoteSecurity == QXmppStreamFeatures::Disabled) - { - warning("Disconnecting as TLS is required, but not supported by the server"); - disconnectFromHost(); - return; - } - - if (socket()->supportsSsl() && - localSecurity != QXmppConfiguration::TLSDisabled && - remoteSecurity != QXmppStreamFeatures::Disabled) - { - // enable TLS as it is support by both parties - sendData("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); - return; - } - } - // handle authentication const bool nonSaslAvailable = features.nonSaslAuthMode() != QXmppStreamFeatures::Disabled; const bool saslAvailable = !features.authMechanisms().isEmpty(); @@ -548,15 +517,6 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv) d->xmppStreamError = QXmppStanza::Error::UndefinedCondition; emit error(QXmppClient::XmppStreamError); } - else if(ns == ns_tls) - { - if(nodeRecv.tagName() == "proceed") - { - debug("Starting encryption"); - socket()->startClientEncryption(); - return; - } - } else if(ns == ns_sasl) { if (!d->saslClient) { diff --git a/src/client/QXmppTlsManager.cpp b/src/client/QXmppTlsManager.cpp new file mode 100644 index 00000000..0301e20c --- /dev/null +++ b/src/client/QXmppTlsManager.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Authors: + * Linus Jahn + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + +#include "QXmppTlsManager.h" + +#include "QXmppConstants_p.h" +#include "QXmppClient.h" +#include "QXmppStreamFeatures.h" +#include "QXmppStartTlsPacket.h" + +#include <QDomElement> + +QXmppTlsManager::QXmppTlsManager() = default; + +bool QXmppTlsManager::handleStanza(const QDomElement &stanza) +{ + if (QXmppStreamFeatures::isStreamFeatures(stanza) && !client()->isSocketEncrypted()) { + QXmppStreamFeatures features; + features.parse(stanza); + + // determine TLS mode to use + const QXmppConfiguration::StreamSecurityMode localSecurity = client()->configuration().streamSecurityMode(); + const QXmppStreamFeatures::Mode remoteSecurity = features.tlsMode(); + if (!client()->socketSupportsSsl() && + (localSecurity == QXmppConfiguration::TLSRequired || + remoteSecurity == QXmppStreamFeatures::Required)) { + warning("Disconnecting since TLS is required, but SSL support is not available"); + client()->disconnectFromServer(); + return true; + } + if (localSecurity == QXmppConfiguration::TLSRequired && + remoteSecurity == QXmppStreamFeatures::Disabled) { + warning("Disconnecting since TLS is required, but not supported by the server"); + client()->disconnectFromServer(); + return true; + } + + if (client()->socketSupportsSsl() && + localSecurity != QXmppConfiguration::TLSDisabled && + remoteSecurity != QXmppStreamFeatures::Disabled) { + // enable TLS since it is supported by both parties + client()->sendPacket(QXmppStartTlsPacket()); + return true; + } + } + + if (QXmppStartTlsPacket::isStartTlsPacket(stanza, QXmppStartTlsPacket::Proceed)) { + debug("Starting encryption"); + client()->startSocketEncryption(); + return true; + } + + return false; +} diff --git a/src/client/QXmppTlsManager.h b/src/client/QXmppTlsManager.h new file mode 100644 index 00000000..ac811cfd --- /dev/null +++ b/src/client/QXmppTlsManager.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008-2019 The QXmpp developers + * + * Authors: + * Linus Jahn + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPTLSMANAGER_H +#define QXMPPTLSMANAGER_H + +#include "QXmppClientExtension.h" + +/// \brief The QXmppTlsManager enables the QXmppClient to use STARTTLS. It is +/// added to the client by default and can be configured using the +/// \c QXmppConfiguration class. +/// +/// \ingroup Managers + +class QXMPP_EXPORT QXmppTlsManager : public QXmppClientExtension +{ + Q_OBJECT + +public: + QXmppTlsManager(); + + bool handleStanza(const QDomElement &stanza) override; +}; + +#endif // QXMPPTLSMANAGER_H |
