aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2012-07-18 14:52:24 +0200
committerJeremy Lainé <jeremy.laine@m4x.org>2012-07-18 14:52:24 +0200
commit89a558dfbbbde668666e7d8af8f52c23fa61530b (patch)
treed04f4a29641a5a35d308623fedf0a0306b49746f /src
parent088c9cdd984a08d044064a24a4f898d290297b02 (diff)
downloadqxmpp-89a558dfbbbde668666e7d8af8f52c23fa61530b.tar.gz
make QXmppStreamFeatures string-based to allow pluggable SASL
Diffstat (limited to 'src')
-rw-r--r--src/base/QXmppStreamFeatures.cpp58
-rw-r--r--src/base/QXmppStreamFeatures.h13
-rw-r--r--src/client/QXmppConfiguration.h6
-rw-r--r--src/client/QXmppOutgoingClient.cpp87
-rw-r--r--src/server/QXmppIncomingClient.cpp6
5 files changed, 64 insertions, 106 deletions
diff --git a/src/base/QXmppStreamFeatures.cpp b/src/base/QXmppStreamFeatures.cpp
index 75ae559d..e3918cc6 100644
--- a/src/base/QXmppStreamFeatures.cpp
+++ b/src/base/QXmppStreamFeatures.cpp
@@ -64,22 +64,22 @@ void QXmppStreamFeatures::setNonSaslAuthMode(QXmppStreamFeatures::Mode mode)
m_nonSaslAuthMode = mode;
}
-QList<QXmppConfiguration::SASLAuthMechanism> QXmppStreamFeatures::authMechanisms() const
+QStringList QXmppStreamFeatures::authMechanisms() const
{
return m_authMechanisms;
}
-void QXmppStreamFeatures::setAuthMechanisms(QList<QXmppConfiguration::SASLAuthMechanism> &mechanisms)
+void QXmppStreamFeatures::setAuthMechanisms(const QStringList &mechanisms)
{
m_authMechanisms = mechanisms;
}
-QList<QXmppConfiguration::CompressionMethod> QXmppStreamFeatures::compressionMethods() const
+QStringList QXmppStreamFeatures::compressionMethods() const
{
return m_compressionMethods;
}
-void QXmppStreamFeatures::setCompressionMethods(QList<QXmppConfiguration::CompressionMethod> &methods)
+void QXmppStreamFeatures::setCompressionMethods(const QStringList &methods)
{
m_compressionMethods = methods;
}
@@ -128,8 +128,7 @@ void QXmppStreamFeatures::parse(const QDomElement &element)
QDomElement subElement = compression.firstChildElement("method");
while(!subElement.isNull())
{
- if (subElement.text() == QLatin1String("zlib"))
- m_compressionMethods << QXmppConfiguration::ZlibCompression;
+ m_compressionMethods << subElement.text();
subElement = subElement.nextSiblingElement("method");
}
}
@@ -139,16 +138,8 @@ void QXmppStreamFeatures::parse(const QDomElement &element)
if (mechs.namespaceURI() == ns_sasl)
{
QDomElement subElement = mechs.firstChildElement("mechanism");
- while(!subElement.isNull())
- {
- if (subElement.text() == QLatin1String("PLAIN"))
- m_authMechanisms << QXmppConfiguration::SASLPlain;
- else if (subElement.text() == QLatin1String("DIGEST-MD5"))
- m_authMechanisms << QXmppConfiguration::SASLDigestMD5;
- else if (subElement.text() == QLatin1String("ANONYMOUS"))
- m_authMechanisms << QXmppConfiguration::SASLAnonymous;
- else if (subElement.text() == QLatin1String("X-FACEBOOK-PLATFORM"))
- m_authMechanisms << QXmppConfiguration::SASLXFacebookPlatform;
+ while(!subElement.isNull()) {
+ m_authMechanisms << subElement.text();
subElement = subElement.nextSiblingElement("mechanism");
}
}
@@ -178,43 +169,16 @@ void QXmppStreamFeatures::toXml(QXmlStreamWriter *writer) const
{
writer->writeStartElement("compression");
writer->writeAttribute("xmlns", ns_compressFeature);
- for (int i = 0; i < m_compressionMethods.size(); i++)
- {
- writer->writeStartElement("method");
- switch (m_compressionMethods[i])
- {
- case QXmppConfiguration::ZlibCompression:
- writer->writeCharacters("zlib");
- break;
- }
- writer->writeEndElement();
- }
+ foreach (const QString &method, m_compressionMethods)
+ writer->writeTextElement("method", method);
writer->writeEndElement();
}
if (!m_authMechanisms.isEmpty())
{
writer->writeStartElement("mechanisms");
writer->writeAttribute("xmlns", ns_sasl);
- for (int i = 0; i < m_authMechanisms.size(); i++)
- {
- writer->writeStartElement("mechanism");
- switch (m_authMechanisms[i])
- {
- case QXmppConfiguration::SASLPlain:
- writer->writeCharacters("PLAIN");
- break;
- case QXmppConfiguration::SASLDigestMD5:
- writer->writeCharacters("DIGEST-MD5");
- break;
- case QXmppConfiguration::SASLAnonymous:
- writer->writeCharacters("ANONYMOUS");
- break;
- case QXmppConfiguration::SASLXFacebookPlatform:
- writer->writeCharacters("X-FACEBOOK-PLATFORM");
- break;
- }
- writer->writeEndElement();
- }
+ foreach (const QString &mechanism, m_authMechanisms)
+ writer->writeTextElement("mechanism", mechanism);
writer->writeEndElement();
}
writer->writeEndElement();
diff --git a/src/base/QXmppStreamFeatures.h b/src/base/QXmppStreamFeatures.h
index 2aa191ea..93176318 100644
--- a/src/base/QXmppStreamFeatures.h
+++ b/src/base/QXmppStreamFeatures.h
@@ -24,7 +24,6 @@
#ifndef QXMPPSTREAMFEATURES_H
#define QXMPPSTREAMFEATURES_H
-#include "QXmppConfiguration.h"
#include "QXmppStanza.h"
class QXMPP_EXPORT QXmppStreamFeatures : public QXmppStanza
@@ -48,11 +47,11 @@ public:
Mode nonSaslAuthMode() const;
void setNonSaslAuthMode(Mode mode);
- QList<QXmppConfiguration::SASLAuthMechanism> authMechanisms() const;
- void setAuthMechanisms(QList<QXmppConfiguration::SASLAuthMechanism> &mecanisms);
+ QStringList authMechanisms() const;
+ void setAuthMechanisms(const QStringList &mechanisms);
- QList<QXmppConfiguration::CompressionMethod> compressionMethods() const;
- void setCompressionMethods(QList<QXmppConfiguration::CompressionMethod> &methods);
+ QStringList compressionMethods() const;
+ void setCompressionMethods(const QStringList &methods);
Mode tlsMode() const;
void setTlsMode(Mode mode);
@@ -69,8 +68,8 @@ private:
Mode m_sessionMode;
Mode m_nonSaslAuthMode;
Mode m_tlsMode;
- QList<QXmppConfiguration::SASLAuthMechanism> m_authMechanisms;
- QList<QXmppConfiguration::CompressionMethod> m_compressionMethods;
+ QStringList m_authMechanisms;
+ QStringList m_compressionMethods;
};
#endif
diff --git a/src/client/QXmppConfiguration.h b/src/client/QXmppConfiguration.h
index d6423fb5..9d6ce65f 100644
--- a/src/client/QXmppConfiguration.h
+++ b/src/client/QXmppConfiguration.h
@@ -80,12 +80,6 @@ public:
SASLXFacebookPlatform, ///< Facebook Platform
};
- /// An enumeration for stream compression methods.
- enum CompressionMethod
- {
- ZlibCompression = 0 ///< zlib compression
- };
-
QXmppConfiguration();
QXmppConfiguration(const QXmppConfiguration &other);
~QXmppConfiguration();
diff --git a/src/client/QXmppOutgoingClient.cpp b/src/client/QXmppOutgoingClient.cpp
index 4afee079..10f82ad0 100644
--- a/src/client/QXmppOutgoingClient.cpp
+++ b/src/client/QXmppOutgoingClient.cpp
@@ -82,7 +82,7 @@ public:
QString nonSASLAuthId;
QXmppSaslDigestMd5 saslDigest;
int saslDigestStep;
- int saslMechanism;
+ QString saslMechanism;
// Timers
QTimer *pingTimer;
@@ -90,9 +90,8 @@ public:
};
QXmppOutgoingClientPrivate::QXmppOutgoingClientPrivate()
- : sessionAvailable(false),
- saslDigestStep(0),
- saslMechanism(-1)
+ : sessionAvailable(false)
+ , saslDigestStep(0)
{
}
@@ -246,7 +245,7 @@ void QXmppOutgoingClient::handleStart()
// reset authentication step
d->saslDigestStep = 0;
- d->saslMechanism = -1;
+ d->saslMechanism = QString();
// reset session information
d->bindId.clear();
@@ -338,45 +337,52 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv)
}
else if(saslAvailable)
{
- // determine SASL Authentication mechanism to use
- const QList<QXmppConfiguration::SASLAuthMechanism> mechanisms = features.authMechanisms();
- if (mechanisms.isEmpty())
- {
- warning("No supported SASL Authentication mechanism available");
- disconnectFromHost();
- return;
- }
- else if (!mechanisms.contains(configuration().sASLAuthMechanism()))
- {
- info("Desired SASL Auth mechanism is not available, selecting first available one");
- d->saslMechanism = mechanisms.first();
- } else {
- d->saslMechanism = configuration().sASLAuthMechanism();
- }
-
- // send SASL Authentication request
- switch(d->saslMechanism)
- {
+ // supported and preferred SASL auth mechanisms
+ const QStringList supportedMechanisms = QStringList() << "PLAIN" << "DIGEST-MD5" << "ANONYMOUS" << "X-FACEBOOK-PLATFORM";
+ QString preferredMechanism;
+ switch (configuration().sASLAuthMechanism()) {
case QXmppConfiguration::SASLPlain:
- {
- QString userPass('\0' + configuration().user() +
- '\0' + configuration().password());
- QByteArray data = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>";
- data += userPass.toUtf8().toBase64();
- data += "</auth>";
- sendData(data);
- }
+ preferredMechanism = "PLAIN";
break;
case QXmppConfiguration::SASLDigestMD5:
- sendData("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>");
+ preferredMechanism = "DIGEST-MD5";
break;
case QXmppConfiguration::SASLAnonymous:
- sendData("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
+ preferredMechanism = "ANONYMOUS";
break;
case QXmppConfiguration::SASLXFacebookPlatform:
- sendData("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-FACEBOOK-PLATFORM'/>");
+ preferredMechanism = "X-FACEBOOK-PLATFORM";
break;
}
+
+ // determine SASL Authentication mechanism to use
+ QStringList commonMechanisms;
+ foreach (const QString &mechanism, features.authMechanisms()) {
+ if (supportedMechanisms.contains(mechanism))
+ commonMechanisms << mechanism;
+ }
+ if (commonMechanisms.isEmpty()) {
+ warning("No supported SASL Authentication mechanism available");
+ disconnectFromHost();
+ return;
+ } else if (!commonMechanisms.contains(preferredMechanism)) {
+ info(QString("Desired SASL Auth mechanism '%1' is not available, selecting first available one").arg(preferredMechanism));
+ d->saslMechanism = commonMechanisms.first();
+ } else {
+ d->saslMechanism = preferredMechanism;
+ }
+
+ // send SASL Authentication request
+ if (d->saslMechanism == "PLAIN") {
+ QString userPass('\0' + configuration().user() +
+ '\0' + configuration().password());
+ QByteArray data = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>";
+ data += userPass.toUtf8().toBase64();
+ data += "</auth>";
+ sendData(data);
+ } else {
+ sendData("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='" + d->saslMechanism.toLatin1() + "'/>");
+ }
}
// check whether bind is available
@@ -419,9 +425,7 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv)
}
else if(nodeRecv.tagName() == "challenge")
{
- switch(d->saslMechanism)
- {
- case QXmppConfiguration::SASLDigestMD5:
+ if (d->saslMechanism == "DIGEST-MD5") {
d->saslDigestStep++;
switch (d->saslDigestStep)
{
@@ -436,14 +440,11 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv)
disconnectFromHost();
break;
}
- break;
- case QXmppConfiguration::SASLXFacebookPlatform:
+ } else if (d->saslMechanism == "X-FACEBOOK-PLATFORM") {
sendAuthXFacebookResponse(nodeRecv.text());
- break;
- default:
+ } else {
warning("Unexpected SASL challenge");
disconnectFromHost();
- break;
}
}
else if(nodeRecv.tagName() == "failure")
diff --git a/src/server/QXmppIncomingClient.cpp b/src/server/QXmppIncomingClient.cpp
index 721f7e47..c81c20be 100644
--- a/src/server/QXmppIncomingClient.cpp
+++ b/src/server/QXmppIncomingClient.cpp
@@ -200,10 +200,10 @@ void QXmppIncomingClient::handleStream(const QDomElement &streamElement)
}
else if (d->passwordChecker)
{
- QList<QXmppConfiguration::SASLAuthMechanism> mechanisms;
- mechanisms << QXmppConfiguration::SASLPlain;
+ QStringList mechanisms;
+ mechanisms << "PLAIN";
if (d->passwordChecker->hasGetPassword())
- mechanisms << QXmppConfiguration::SASLDigestMD5;
+ mechanisms << "DIGEST-MD5";
features.setAuthMechanisms(mechanisms);
}
sendPacket(features);