aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2011-01-17 13:31:32 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2011-01-17 13:31:32 +0000
commit8000f0b96e7b7cfbe4cf631bc243671fa8d5f7fd (patch)
tree76819bbb6a6910e61e862b9ba6a38c6a93278b0b /src
parentbae979bf028adb8c6b72102a97dbc9a3eee4984f (diff)
downloadqxmpp-8000f0b96e7b7cfbe4cf631bc243671fa8d5f7fd.tar.gz
* do not hardcoded QXmppIncomingClient inactivity timeout
* make QXmppPasswordChecker return more informative codes
Diffstat (limited to 'src')
-rw-r--r--src/QXmppIncomingClient.cpp51
-rw-r--r--src/QXmppIncomingClient.h10
2 files changed, 51 insertions, 10 deletions
diff --git a/src/QXmppIncomingClient.cpp b/src/QXmppIncomingClient.cpp
index 71c3b664..47abb244 100644
--- a/src/QXmppIncomingClient.cpp
+++ b/src/QXmppIncomingClient.cpp
@@ -64,12 +64,15 @@ QXmppIncomingClient::QXmppIncomingClient(QSslSocket *socket, const QString &doma
d->domain = domain;
d->saslStep = 0;
- setObjectName("C2S-in");
- setSocket(socket);
+ if (socket) {
+ info(QString("Incoming client connection from %1 %2").arg(
+ socket->peerAddress().toString(),
+ QString::number(socket->peerPort())));
+ setSocket(socket);
+ }
// create inactivity timer
d->idleTimer = new QTimer(this);
- d->idleTimer->setInterval(70000);
d->idleTimer->setSingleShot(true);
bool check = connect(d->idleTimer, SIGNAL(timeout()),
this, SLOT(slotTimeout()));
@@ -109,6 +112,17 @@ QString QXmppIncomingClient::jid() const
return jid;
}
+/// Sets the number of seconds after which a client will be disconnected
+/// for inactivity.
+
+void QXmppIncomingClient::setInactivityTimeout(int secs)
+{
+ d->idleTimer->stop();
+ d->idleTimer->setInterval(secs * 1000);
+ if (d->idleTimer->interval())
+ d->idleTimer->start();
+}
+
/// Sets the password checker used to verify client credentials.
///
/// \param checker
@@ -121,7 +135,8 @@ void QXmppIncomingClient::setPasswordChecker(QXmppPasswordChecker *checker)
void QXmppIncomingClient::handleStream(const QDomElement &streamElement)
{
- d->idleTimer->start();
+ if (d->idleTimer->interval())
+ d->idleTimer->start();
d->saslStep = 0;
// start stream
@@ -151,7 +166,7 @@ void QXmppIncomingClient::handleStream(const QDomElement &streamElement)
// send stream features
QXmppStreamFeatures features;
- if (!socket()->isEncrypted() && !socket()->localCertificate().isNull() && !socket()->privateKey().isNull())
+ if (socket() && !socket()->isEncrypted() && !socket()->localCertificate().isNull() && !socket()->privateKey().isNull())
features.setTlsMode(QXmppStreamFeatures::Enabled);
if (!d->username.isEmpty())
{
@@ -173,7 +188,8 @@ void QXmppIncomingClient::handleStanza(const QDomElement &nodeRecv)
{
const QString ns = nodeRecv.namespaceURI();
- d->idleTimer->start();
+ if (d->idleTimer->interval())
+ d->idleTimer->start();
if (ns == ns_tls && nodeRecv.tagName() == "starttls")
{
@@ -192,21 +208,37 @@ void QXmppIncomingClient::handleStanza(const QDomElement &nodeRecv)
QList<QByteArray> auth = QByteArray::fromBase64(nodeRecv.text().toAscii()).split('\0');
if (auth.size() != 3)
{
- sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
+ sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><incorrect-encoding/></failure>");
disconnectFromHost();
return;
}
const QString username = QString::fromUtf8(auth[1]);
const QString password = QString::fromUtf8(auth[2]);
- if (d->passwordChecker && d->passwordChecker->checkPassword(username, password))
+ if (!d->passwordChecker) {
+ // FIXME: what type of failure?
+ warning(QString("Cannot authenticate '%1', no password checker").arg(username));
+ sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
+ disconnectFromHost();
+ return;
+ }
+
+ QXmppPasswordChecker::Error error = d->passwordChecker->checkPassword(username, password);
+ if (error == QXmppPasswordChecker::NoError)
{
d->username = username;
+ info(QString("Authentication succeeded for '%1'").arg(d->username));
sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
- } else {
+ } else if (error == QXmppPasswordChecker::AuthorizationError) {
+ warning(QString("Authentication failed for '%1'").arg(username));
sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>");
disconnectFromHost();
return;
+ } else {
+ warning(QString("Temporary authentication failure for '%1'").arg(username));
+ sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><temporary-auth-failure/></failure>");
+ disconnectFromHost();
+ return;
}
}
else if (mechanism == "DIGEST-MD5")
@@ -277,6 +309,7 @@ void QXmppIncomingClient::handleStanza(const QDomElement &nodeRecv)
{
// authentication succeeded
d->saslStep = 3;
+ info(QString("Authentication succeeded for '%1'").arg(d->username));
sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
}
}
diff --git a/src/QXmppIncomingClient.h b/src/QXmppIncomingClient.h
index 384cac82..22b05c48 100644
--- a/src/QXmppIncomingClient.h
+++ b/src/QXmppIncomingClient.h
@@ -34,11 +34,18 @@ class QXmppIncomingClientPrivate;
class QXmppPasswordChecker
{
public:
+ /// This enum is used to describe authentication errors.
+ enum Error {
+ NoError = 0,
+ AuthorizationError,
+ TemporaryError,
+ };
+
/// Checks that the given credentials are valid.
///
/// \param username
/// \param password
- virtual bool checkPassword(const QString &username, const QString &password) = 0;
+ virtual Error checkPassword(const QString &username, const QString &password) = 0;
virtual bool getPassword(const QString &username, QString &password);
virtual bool hasGetPassword() const;
};
@@ -58,6 +65,7 @@ public:
bool isConnected() const;
QString jid() const;
+ void setInactivityTimeout(int secs);
void setPasswordChecker(QXmppPasswordChecker *checker);
signals: