aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2012-07-20 10:59:53 +0200
committerJeremy Lainé <jeremy.laine@m4x.org>2012-07-20 10:59:53 +0200
commit15cab790071aabfc62977d590b89f54a5fa6e92d (patch)
tree4b75e1269ab983d06130340325a4ee97baf901e7 /src
parenta609100c2a0eb19ef4b9c7a571366281ca722ac8 (diff)
downloadqxmpp-15cab790071aabfc62977d590b89f54a5fa6e92d.tar.gz
first stab at factoring out server-side SASL
Diffstat (limited to 'src')
-rw-r--r--src/base/QXmppSaslAuth.cpp149
-rw-r--r--src/base/QXmppSaslAuth.h28
-rw-r--r--src/base/QXmppSaslAuth_p.h49
3 files changed, 225 insertions, 1 deletions
diff --git a/src/base/QXmppSaslAuth.cpp b/src/base/QXmppSaslAuth.cpp
index 0ae3b1df..ead1188f 100644
--- a/src/base/QXmppSaslAuth.cpp
+++ b/src/base/QXmppSaslAuth.cpp
@@ -104,7 +104,7 @@ void QXmppSaslClient::setServiceType(const QString &serviceType)
d->serviceType = serviceType;
}
-/// Returns the host.
+/// Returns the username.
QString QXmppSaslClient::username() const
{
@@ -308,6 +308,153 @@ bool QXmppSaslClientPlain::respond(const QByteArray &challenge, QByteArray &resp
}
}
+class QXmppSaslServerPrivate
+{
+public:
+ QString username;
+ QString password;
+};
+
+QXmppSaslServer::QXmppSaslServer(QObject *parent)
+ : QXmppLoggable(parent)
+ , d(new QXmppSaslServerPrivate)
+{
+}
+
+QXmppSaslServer::~QXmppSaslServer()
+{
+ delete d;
+}
+
+/// Creates an SASL server for the given mechanism.
+
+QXmppSaslServer* QXmppSaslServer::create(const QString &mechanism, QObject *parent)
+{
+ if (mechanism == "PLAIN") {
+ return new QXmppSaslServerPlain(parent);
+ } else if (mechanism == "DIGEST-MD5") {
+ return new QXmppSaslServerDigestMd5(parent);
+ } else if (mechanism == "ANONYMOUS") {
+ return new QXmppSaslServerAnonymous(parent);
+ }
+}
+
+/// Returns the username.
+
+QString QXmppSaslServer::username() const
+{
+ return d->username;
+}
+
+/// Sets the username.
+
+void QXmppSaslServer::setUsername(const QString &username)
+{
+ d->username = username;
+}
+
+/// Returns the password.
+
+QString QXmppSaslServer::password() const
+{
+ return d->password;
+}
+
+/// Sets the password.
+
+void QXmppSaslServer::setPassword(const QString &password)
+{
+ d->password = password;
+}
+
+QXmppSaslServerAnonymous::QXmppSaslServerAnonymous(QObject *parent)
+ : QXmppSaslServer(parent)
+ , m_step(0)
+{
+}
+
+QString QXmppSaslServerAnonymous::mechanism() const
+{
+ return "ANONYMOUS";
+}
+
+QXmppSaslServer::Response QXmppSaslServerAnonymous::respond(const QByteArray &request, QByteArray &response)
+{
+ Q_UNUSED(request);
+ if (m_step == 0) {
+ m_step++;
+ response = QByteArray();
+ return Succeeded;
+ } else {
+ warning("QXmppSaslServerAnonymous : Invalid step");
+ return Failed;
+ }
+}
+
+QXmppSaslServerDigestMd5::QXmppSaslServerDigestMd5(QObject *parent)
+ : QXmppSaslServer(parent)
+ , m_step(0)
+{
+}
+
+QString QXmppSaslServerDigestMd5::mechanism() const
+{
+ return "DIGEST-MD5";
+}
+
+QXmppSaslServer::Response QXmppSaslServerDigestMd5::respond(const QByteArray &request, QByteArray &response)
+{
+ if (m_step == 0) {
+ // generate nonce
+ m_saslDigest.setNonce(QXmppSaslDigestMd5::generateNonce());
+ //m_saslDigest.setQop("auth");
+
+ QMap<QByteArray, QByteArray> challenge;
+ challenge["nonce"] = m_saslDigest.nonce();
+ //challenge["realm"] = m_domain.toUtf8();
+ challenge["qop"] = "auth";
+ challenge["charset"] = "utf-8";
+ challenge["algorithm"] = "md5-sess";
+
+ m_step++;
+ response = QXmppSaslDigestMd5::serializeMessage(challenge);
+ return Challenge;
+ } else {
+ return Failed;
+ }
+}
+
+QXmppSaslServerPlain::QXmppSaslServerPlain(QObject *parent)
+ : QXmppSaslServer(parent)
+ , m_step(0)
+{
+}
+
+QString QXmppSaslServerPlain::mechanism() const
+{
+ return "PLAIN";
+}
+
+QXmppSaslServer::Response QXmppSaslServerPlain::respond(const QByteArray &request, QByteArray &response)
+{
+ if (m_step == 0) {
+ QList<QByteArray> auth = request.split('\0');
+ if (auth.size() != 3) {
+ warning("QXmppSaslServerPlain : Invalid input");
+ return Failed;
+ }
+ setUsername(QString::fromUtf8(auth[1]));
+ setPassword(QString::fromUtf8(auth[2]));
+
+ m_step++;
+ response = QByteArray();
+ return Succeeded;
+ } else {
+ warning("QXmppSaslServerPlain : Invalid step");
+ return Failed;
+ }
+}
+
QByteArray QXmppSaslDigestMd5::authzid() const
{
return m_authzid;
diff --git a/src/base/QXmppSaslAuth.h b/src/base/QXmppSaslAuth.h
index b6428eb8..9026d757 100644
--- a/src/base/QXmppSaslAuth.h
+++ b/src/base/QXmppSaslAuth.h
@@ -32,6 +32,7 @@
#include "QXmppLogger.h"
class QXmppSaslClientPrivate;
+class QXmppSaslServerPrivate;
class QXMPP_EXPORT QXmppSaslDigestMd5
{
@@ -105,4 +106,31 @@ private:
QXmppSaslClientPrivate *d;
};
+class QXMPP_EXPORT QXmppSaslServer : public QXmppLoggable
+{
+public:
+ enum Response {
+ Challenge = 0,
+ Succeeded = 1,
+ Failed = 2
+ };
+
+ QXmppSaslServer(QObject *parent = 0);
+ virtual ~QXmppSaslServer();
+
+ QString username() const;
+ void setUsername(const QString &username);
+
+ QString password() const;
+ void setPassword(const QString &password);
+
+ virtual QString mechanism() const = 0;
+ virtual Response respond(const QByteArray &challenge, QByteArray &response) = 0;
+
+ static QXmppSaslServer* create(const QString &mechanism, QObject *parent = 0);
+
+private:
+ QXmppSaslServerPrivate *d;
+};
+
#endif
diff --git a/src/base/QXmppSaslAuth_p.h b/src/base/QXmppSaslAuth_p.h
index 18c1829e..10a20cfb 100644
--- a/src/base/QXmppSaslAuth_p.h
+++ b/src/base/QXmppSaslAuth_p.h
@@ -81,4 +81,53 @@ private:
int m_step;
};
+class QXmppSaslServerAnonymous : public QXmppSaslServer
+{
+public:
+ QXmppSaslServerAnonymous(QObject *parent = 0);
+ QString mechanism() const;
+
+ Response respond(const QByteArray &challenge, QByteArray &response);
+
+private:
+ int m_step;
+};
+
+class QXmppSaslServerDigestMd5 : public QXmppSaslServer
+{
+public:
+ QXmppSaslServerDigestMd5(QObject *parent = 0);
+ QString mechanism() const;
+
+ Response respond(const QByteArray &challenge, QByteArray &response);
+
+private:
+ QXmppSaslDigestMd5 m_saslDigest;
+ int m_step;
+};
+
+class QXmppSaslServerFacebook : public QXmppSaslServer
+{
+public:
+ QXmppSaslServerFacebook(QObject *parent = 0);
+ QString mechanism() const;
+
+ Response respond(const QByteArray &challenge, QByteArray &response);
+
+private:
+ int m_step;
+};
+
+class QXmppSaslServerPlain : public QXmppSaslServer
+{
+public:
+ QXmppSaslServerPlain(QObject *parent = 0);
+ QString mechanism() const;
+
+ Response respond(const QByteArray &challenge, QByteArray &response);
+
+private:
+ int m_step;
+};
+
#endif