void tst_QXmppSasl::testResponse() { QFETCH(QByteArray, xml); QFETCH(QByteArray, value); // no condition QXmppSaslResponse response; parsePacket(response, xml); QCOMPARE(response.value(), value); serializePacket(response, xml); }
void QXmppIncomingClient::handleStanza (const QDomElement &nodeRecv) { const QString ns = nodeRecv.namespaceURI(); if (d->idleTimer->interval()) d->idleTimer->start(); if (ns == ns_tls && nodeRecv.tagName() == QLatin1String ("starttls")) { sendData ("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); socket()->flush(); socket()->startServerEncryption(); return; } else if (ns == ns_sasl) { if (!d->passwordChecker) { warning ("Cannot perform authentication, no password checker"); sendPacket (QXmppSaslFailure ("temporary-auth-failure")); disconnectFromHost(); return; } if (nodeRecv.tagName() == QLatin1String ("auth")) { QXmppSaslAuth auth; auth.parse (nodeRecv); d->saslServer = QXmppSaslServer::create (auth.mechanism(), this); if (!d->saslServer) { sendPacket (QXmppSaslFailure ("invalid-mechanism")); disconnectFromHost(); return; } d->saslServer->setRealm (d->domain.toUtf8()); QByteArray challenge; QXmppSaslServer::Response result = d->saslServer->respond (auth.value(), challenge); if (result == QXmppSaslServer::InputNeeded) { // check credentials d->checkCredentials (auth.value()); } else if (result == QXmppSaslServer::Challenge) sendPacket (QXmppSaslChallenge (challenge)); else { // FIXME: what condition? sendPacket (QXmppSaslFailure()); disconnectFromHost(); return; } } else if (nodeRecv.tagName() == QLatin1String ("response")) { QXmppSaslResponse response; response.parse (nodeRecv); if (!d->saslServer) { warning ("SASL response received, but no mechanism selected"); sendPacket (QXmppSaslFailure()); disconnectFromHost(); return; } QByteArray challenge; QXmppSaslServer::Response result = d->saslServer->respond (response.value(), challenge); if (result == QXmppSaslServer::InputNeeded) { // check credentials d->checkCredentials (response.value()); } else if (result == QXmppSaslServer::Succeeded) { // authentication succeeded d->jid = QString ("%1@%2").arg (d->saslServer->username(), d->domain); info (QString ("Authentication succeeded for '%1' from %2").arg (d->jid, d->origin())); updateCounter ("incoming-client.auth.success"); sendPacket (QXmppSaslSuccess()); handleStart(); } else { // FIXME: what condition? sendPacket (QXmppSaslFailure()); disconnectFromHost(); } } } else if (ns == ns_client) { if (nodeRecv.tagName() == QLatin1String ("iq")) { const QString type = nodeRecv.attribute ("type"); if (QXmppBindIq::isBindIq (nodeRecv) && type == QLatin1String ("set")) { QXmppBindIq bindSet; bindSet.parse (nodeRecv); d->resource = bindSet.resource().trimmed(); if (d->resource.isEmpty()) d->resource = QXmppUtils::generateStanzaHash(); d->jid = QString ("%1/%2").arg (QXmppUtils::jidToBareJid (d->jid), d->resource); QXmppBindIq bindResult; bindResult.setType (QXmppIq::Result); bindResult.setId (bindSet.id()); bindResult.setJid (d->jid); sendPacket (bindResult); // bound emit connected(); return; } else if (QXmppSessionIq::isSessionIq (nodeRecv) && type == QLatin1String ("set")) { QXmppSessionIq sessionSet; sessionSet.parse (nodeRecv); QXmppIq sessionResult; sessionResult.setType (QXmppIq::Result); sessionResult.setId (sessionSet.id()); sessionResult.setTo (d->jid); sendPacket (sessionResult); return; } } // check the sender is legitimate const QString from = nodeRecv.attribute ("from"); if (!from.isEmpty() && from != d->jid && from != QXmppUtils::jidToBareJid (d->jid)) { warning (QString ("Received a stanza from unexpected JID %1").arg (from)); return; } // process unhandled stanzas if (nodeRecv.tagName() == QLatin1String ("iq") || nodeRecv.tagName() == QLatin1String ("message") || nodeRecv.tagName() == QLatin1String ("presence")) { QDomElement nodeFull (nodeRecv); // if the sender is empty, set it to the appropriate JID if (nodeFull.attribute ("from").isEmpty()) { if (nodeFull.tagName() == QLatin1String ("presence") && (nodeFull.attribute ("type") == QLatin1String ("subscribe") || nodeFull.attribute ("type") == QLatin1String ("subscribed"))) nodeFull.setAttribute ("from", QXmppUtils::jidToBareJid (d->jid)); else nodeFull.setAttribute ("from", d->jid); } // if the recipient is empty, set it to the local domain if (nodeFull.attribute ("to").isEmpty()) nodeFull.setAttribute ("to", d->domain); // emit stanza for processing by server emit elementReceived (nodeFull); } } }