aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2019-12-14 22:47:28 +0100
committerLNJ <lnj@kaidan.im>2020-01-20 17:14:49 +0100
commit28411b5995553eb3a50c826c55517b4c610959c2 (patch)
treec22ea3b5bd5c1de2831cb3141940038180ce878e /src/client
parent55966be2e3e80bd5ab2cc86da2492963dd8127ee (diff)
downloadqxmpp-28411b5995553eb3a50c826c55517b4c610959c2.tar.gz
Move TLS negotiation into new QXmppTlsManager
Diffstat (limited to 'src/client')
-rw-r--r--src/client/QXmppClient.cpp45
-rw-r--r--src/client/QXmppClient.h5
-rw-r--r--src/client/QXmppOutgoingClient.cpp42
-rw-r--r--src/client/QXmppTlsManager.cpp74
-rw-r--r--src/client/QXmppTlsManager.h45
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