diff -ur psi-0.9.3/iris/include/im.h psi-0.9.3-sasl/iris/include/im.h --- psi-0.9.3/iris/include/im.h 2004-10-14 20:14:40.000000000 +0100 +++ psi-0.9.3-sasl/iris/include/im.h 2005-07-03 20:30:45.000000000 +0100 @@ -605,6 +605,7 @@ void groupChatLeft(const Jid &); void groupChatPresence(const Jid &, const Status &); void groupChatError(const Jid &, int, const QString &); + void sessionStarted(); void incomingJidLink(); @@ -620,6 +621,7 @@ void streamOutgoingXml(const QString &); void slotRosterRequestFinished(); + void slotSessionStarted(); // basic daemons void ppSubscription(const Jid &, const QString &); diff -ur psi-0.9.3/iris/xmpp-core/protocol.cpp psi-0.9.3-sasl/iris/xmpp-core/protocol.cpp --- psi-0.9.3/iris/xmpp-core/protocol.cpp 2004-03-04 20:49:55.000000000 +0000 +++ psi-0.9.3-sasl/iris/xmpp-core/protocol.cpp 2005-07-12 23:25:09.000000000 +0100 @@ -1055,9 +1055,14 @@ if(!sasl_authed) { if(!features.sasl_supported) { // SASL MUST be supported - event = EError; - errorCode = ErrProtocol; - return true; + if(doAuth) { + step = HandleAuthGet; + return processStep(); + } else + return loginComplete(); + // event = EError; + // errorCode = ErrProtocol; + // return true; } #ifdef XMPP_TEST diff -ur psi-0.9.3/iris/xmpp-core/stream.cpp psi-0.9.3-sasl/iris/xmpp-core/stream.cpp --- psi-0.9.3/iris/xmpp-core/stream.cpp 2005-07-13 09:33:23.943893864 +0100 +++ psi-0.9.3-sasl/iris/xmpp-core/stream.cpp 2005-07-13 00:37:23.000000000 +0100 @@ -749,13 +749,9 @@ void ClientStream::setPassword(const QString &s) { - if(d->client.old) { - d->client.setPassword(s); - } - else { - if(d->sasl) - d->sasl->setPassword(s); - } + d->client.setPassword(s); + if(d->sasl) + d->sasl->setPassword(s); } void ClientStream::setRealm(const QString &s) @@ -768,7 +764,7 @@ { if(d->state == NeedParams) { d->state = Connecting; - if(d->client.old) { + if(d->client.old || d->sasl==NULL) { processNext(); } else { @@ -1067,10 +1063,8 @@ #ifdef XMPP_DEBUG printf("need params: %d,%d,%d,%d\n", user, authzid, pass, realm); #endif - if(authzid && !user) { + if(authzid) d->sasl->setAuthzid(d->jid.bare()); - //d->sasl->setAuthzid("infiniti.homelesshackers.org"); - } if(user || pass || realm) { d->state = NeedParams; needAuthParams(user, pass, realm); @@ -1111,10 +1105,27 @@ // printf("sasl error: %d\n", c); //#endif // has to be auth error - int x = convertedSASLCond(); - reset(); - d->errCond = x; - error(ErrAuth); + + // The more correct version of this test is that + // * If we've already sent data to the server, send an + // * Find out the mechanism that's failed (current QCA can't tell + // us this, unfortunately.) + // * Remove the failed mechanism from the list + // * If there's still mechs left, try again to start the SASL + // exchange. Otherwise, throw the last error that we received + // + // However, because qca will only tell us the mechanism when the + // first SASL exchange succeeds, we just remove the common failure + // cause (GSSAPI) on the first time round. + + if (d->sasl_mechlist.remove("GSSAPI")>0) { + d->sasl->startClient("xmpp", d->server, d->sasl_mechlist, true); + } else { + int x = convertedSASLCond(); + reset(); + d->errCond = x; + error(ErrAuth); + } } void ClientStream::srvProcessNext() @@ -1482,6 +1493,8 @@ else ml = d->client.features.sasl_mechs; + d->sasl_mechlist = ml; + if(!d->sasl->startClient("xmpp", d->server, ml, true)) { int x = convertedSASLCond(); reset(); diff -ur psi-0.9.3/iris/xmpp-im/client.cpp psi-0.9.3-sasl/iris/xmpp-im/client.cpp --- psi-0.9.3/iris/xmpp-im/client.cpp 2004-12-28 20:19:45.000000000 +0000 +++ psi-0.9.3-sasl/iris/xmpp-im/client.cpp 2005-07-13 00:16:36.000000000 +0100 @@ -202,6 +202,17 @@ d->pass = pass; d->resource = _resource; + if (!d->stream->old()) { + JT_Session *s = new JT_Session(rootTask()); + connect(s, SIGNAL(finished()), SLOT(slotSessionStarted())); + s->go(true); + } else { + slotSessionStarted(); + } +} + +void Client::slotSessionStarted() +{ Status stat; stat.setIsAvailable(false); d->resourceList += Resource(resource(), stat); @@ -219,6 +230,9 @@ new JT_ServInfo(rootTask()); d->active = true; + + if (!d->stream->old()) + sessionStarted(); } void Client::setFileTransferEnabled(bool b) diff -ur psi-0.9.3/iris/xmpp-im/xmpp_tasks.cpp psi-0.9.3-sasl/iris/xmpp-im/xmpp_tasks.cpp --- psi-0.9.3/iris/xmpp-im/xmpp_tasks.cpp 2004-12-06 09:46:15.000000000 +0000 +++ psi-0.9.3-sasl/iris/xmpp-im/xmpp_tasks.cpp 2005-07-04 19:10:37.000000000 +0100 @@ -295,6 +295,41 @@ } //---------------------------------------------------------------------------- +// JT_Session +//---------------------------------------------------------------------------- + +JT_Session::JT_Session(Task *parent) +: Task(parent) +{ +} + +JT_Session::~JT_Session() +{ +} + +void JT_Session::onGo() +{ + QDomElement iq = createIQ(doc(), "set", client()->host(), id()); + QDomElement session = doc()->createElement("session"); + session.setAttribute("xmlns","urn:ietf:params:xml:ns:xmpp-session"); + iq.appendChild(session); + send(iq); +} + +bool JT_Session::take(const QDomElement &x) +{ + if(!iqVerify(x, client()->host(), id())) + return false; + + if (x.attribute("type") == "result") + setSuccess(); + else + setError(x); + + return true; +} + +//---------------------------------------------------------------------------- // JT_Roster //---------------------------------------------------------------------------- class JT_Roster::Private diff -ur psi-0.9.3/iris/xmpp-im/xmpp_tasks.h psi-0.9.3-sasl/iris/xmpp-im/xmpp_tasks.h --- psi-0.9.3/iris/xmpp-im/xmpp_tasks.h 2003-10-22 13:07:48.000000000 +0100 +++ psi-0.9.3-sasl/iris/xmpp-im/xmpp_tasks.h 2005-07-03 20:44:37.000000000 +0100 @@ -78,6 +78,16 @@ Private *d; }; + class JT_Session : public Task + { Q_OBJECT + public: + JT_Session(Task *parent); + ~JT_Session(); + + void onGo(); + bool take(const QDomElement &); + }; + class JT_Roster : public Task { Q_OBJECT diff -ur psi-0.9.3/src/psiaccount.cpp psi-0.9.3-sasl/src/psiaccount.cpp --- psi-0.9.3/src/psiaccount.cpp 2005-07-04 14:57:39.000000000 +0100 +++ psi-0.9.3-sasl/src/psiaccount.cpp 2005-07-04 19:01:21.000000000 +0100 @@ -417,6 +417,7 @@ //connect(d->client, SIGNAL(sslCertReady(const QSSLCert &)), SLOT(client_sslCertReady(const QSSLCert &))); //connect(d->client, SIGNAL(closeFinished()), SLOT(client_closeFinished())); //connect(d->client, SIGNAL(authFinished(bool, int, const QString &)), SLOT(client_authFinished(bool, int, const QString &))); + connect(d->client, SIGNAL(sessionStarted()), SLOT(client_sessionStarted())); connect(d->client, SIGNAL(rosterRequestFinished(bool, int, const QString &)), SLOT(client_rosterRequestFinished(bool, int, const QString &))); connect(d->client, SIGNAL(rosterItemAdded(const RosterItem &)), SLOT(client_rosterItemUpdated(const RosterItem &))); connect(d->client, SIGNAL(rosterItemUpdated(const RosterItem &)), SLOT(client_rosterItemUpdated(const RosterItem &))); @@ -531,14 +532,16 @@ void PsiAccount::cleanupStream() { - delete d->stream; + if (d->stream) + d->stream->deleteLater(); d->stream = 0; delete d->tls; d->tls = 0; d->tlsHandler = 0; - delete d->conn; + if (d->conn) + d->conn->deleteLater(); d->conn = 0; d->certList.clear(); @@ -853,12 +856,13 @@ d->conn->setOptSSL(d->acc.opt_ssl); d->stream = new ClientStream(d->conn, d->tlsHandler); - d->stream->setOldOnly(true); + d->stream->setOldOnly(false); d->stream->setAllowPlain(d->acc.opt_plain); if(d->acc.opt_keepAlive) d->stream->setNoopTime(55000); // prevent NAT timeouts every minute else d->stream->setNoopTime(0); + d->stream->setSSFRange(0,256); connect(d->stream, SIGNAL(connected()), SLOT(cs_connected())); connect(d->stream, SIGNAL(securityLayerActivated(int)), SLOT(cs_securityLayerActivated())); connect(d->stream, SIGNAL(needAuthParams(bool, bool, bool)), SLOT(cs_needAuthParams(bool, bool, bool))); @@ -970,10 +974,14 @@ stateChanged(); } -void PsiAccount::cs_needAuthParams(bool, bool pass, bool) +void PsiAccount::cs_needAuthParams(bool user, bool pass, bool realm) { + if(user) + d->stream->setUsername(d->jid.user()); if(pass) d->stream->setPassword(d->acc.pass); + if(realm) + d->stream->setRealm(d->jid.domain()); d->stream->continueAfterParams(); } @@ -982,18 +990,6 @@ d->conn->changePollInterval(10); // for http poll, slow down after login d->client->start(d->jid.host(), d->jid.user(), d->acc.pass, d->acc.resource); - - //printf("PsiAccount: [%s] authenticated\n", name().latin1()); - - // flag roster for delete - UserListIt it(d->userList); - for(UserListItem *u; (u = it.current()); ++it) { - if(u->inList()) - u->setFlagForDelete(true); - } - - // ask for roster - d->client->rosterRequest(); } void PsiAccount::cs_connectionClosed() @@ -1150,9 +1146,6 @@ getErrorInfo(err, d->conn, d->stream, d->tlsHandler, &str, &reconn); - d->client->close(); - cleanupStream(); - //printf("Error: [%s]\n", str.latin1()); isDisconnecting = true; @@ -1173,10 +1166,28 @@ } v_isActive = false; + + QMessageBox::critical(0, tr("%1: Server Error").arg(name()), tr("There was an error communicating with the Jabber server.\nDetails: %1").arg(str)); + + d->client->close(); + cleanupStream(); + stateChanged(); disconnected(); +} - QMessageBox::critical(0, tr("%1: Server Error").arg(name()), tr("There was an error communicating with the Jabber server.\nDetails: %1").arg(str)); +void PsiAccount::client_sessionStarted() { + //printf("PsiAccount: [%s] authenticated\n", name().latin1()); + + // flag roster for delete + UserListIt it(d->userList); + for(UserListItem *u; (u = it.current()); ++it) { + if(u->inList()) + u->setFlagForDelete(true); + } + + // ask for roster + d->client->rosterRequest(); } void PsiAccount::client_rosterRequestFinished(bool success, int, const QString &) @@ -1645,7 +1656,7 @@ tr("Need Password"), tr("Please enter the password for %1:").arg(j.full()), QLineEdit::Password, QString::null, &ok, 0); - if(ok && !text.isEmpty()) + if(ok) d->acc.pass = text; else return; diff -ur psi-0.9.3/src/psiaccount.h psi-0.9.3-sasl/src/psiaccount.h --- psi-0.9.3/src/psiaccount.h 2004-08-18 02:35:35.000000000 +0100 +++ psi-0.9.3-sasl/src/psiaccount.h 2005-07-03 20:31:18.000000000 +0100 @@ -298,6 +298,7 @@ void client_groupChatError(const Jid &, int, const QString &); void client_incomingJidLink(); void client_incomingFileTransfer(); + void client_sessionStarted(); void reconnect(); void disconnect();