diff --git a/source/org/jivesoftware/smack/PacketReader.java b/source/org/jivesoftware/smack/PacketReader.java index ee9d36449..ca075e991 100644 --- a/source/org/jivesoftware/smack/PacketReader.java +++ b/source/org/jivesoftware/smack/PacketReader.java @@ -22,6 +22,9 @@ package org.jivesoftware.smack; import org.jivesoftware.smack.Connection.ListenerWrapper; import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.sasl.SASLMechanism.Challenge; +import org.jivesoftware.smack.sasl.SASLMechanism.Failure; +import org.jivesoftware.smack.sasl.SASLMechanism.Success; import org.jivesoftware.smack.util.PacketParserUtils; import org.xmlpull.mxp1.MXParser; import org.xmlpull.v1.XmlPullParser; @@ -281,14 +284,28 @@ class PacketReader { else { // SASL authentication has failed. The server may close the connection // depending on the number of retries + final Failure failure = PacketParserUtils.parseSASLFailure(parser); + processPacket(failure); connection.getSASLAuthentication().authenticationFailed(); } } else if (parser.getName().equals("challenge")) { // The server is challenging the SASL authentication made by the client - connection.getSASLAuthentication().challengeReceived(parser.nextText()); + String challengeData = parser.nextText(); + processPacket(new Challenge(challengeData)); + connection.getSASLAuthentication().challengeReceived(challengeData); } else if (parser.getName().equals("success")) { + processPacket(new Success(parser.nextText())); + // We now need to bind a resource for the connection + // Open a new stream and wait for the response + connection.packetWriter.openStream(); + // Reset the state of the parser since a new stream element is going + // to be sent by the server + resetParser(); + // The SASL authentication with the server was successful. The next step + // will be to bind the resource + connection.getSASLAuthentication().authenticated(); } else if (parser.getName().equals("compressed")) { // Server confirmed that it's possible to use stream compression. Start @@ -304,17 +321,6 @@ class PacketReader { // Disconnect the connection connection.disconnect(); } - else if (parser.getName().equals("success")) { - // We now need to bind a resource for the connection - // Open a new stream and wait for the response - connection.packetWriter.openStream(); - // Reset the state of the parser since a new stream element is going - // to be sent by the server - resetParser(); - // The SASL authentication with the server was successful. The next step - // will be to bind the resource - connection.getSASLAuthentication().authenticated(); - } } eventType = parser.next(); } while (!done && eventType != XmlPullParser.END_DOCUMENT && thread == readerThread); diff --git a/source/org/jivesoftware/smack/sasl/SASLMechanism.java b/source/org/jivesoftware/smack/sasl/SASLMechanism.java index 42b2670f0..8a5767740 100644 --- a/source/org/jivesoftware/smack/sasl/SASLMechanism.java +++ b/source/org/jivesoftware/smack/sasl/SASLMechanism.java @@ -216,6 +216,28 @@ public abstract class SASLMechanism implements CallbackHandler { } } + /** + * A SASL challenge stanza. + */ + public static class Challenge extends Packet { + final private String data; + + public Challenge(String data) { + this.data = data; + } + + public String toXML() { + StringBuilder stanza = new StringBuilder(); + stanza.append(""); + if (data != null && + data.trim().length() > 0) { + stanza.append(data); + } + stanza.append(""); + return stanza.toString(); + } + } + /** * A SASL response stanza. */ @@ -248,4 +270,57 @@ public abstract class SASLMechanism implements CallbackHandler { return stanza.toString(); } } + + /** + * A SASL success stanza. + */ + public static class Success extends Packet { + final private String data; + + public Success(String data) { + this.data = data; + } + + public String toXML() { + StringBuilder stanza = new StringBuilder(); + stanza.append(""); + if (data != null && + data.trim().length() > 0) { + stanza.append(data); + } + stanza.append(""); + return stanza.toString(); + } + } + + /** + * A SASL failure stanza. + */ + public static class Failure extends Packet { + final private String condition; + + public Failure(String condition) { + this.condition = condition; + } + + /** + * Get the SASL related error condition. + * + * @return the SASL related error condition. + */ + public String getCondition() { + return condition; + } + + public String toXML() { + StringBuilder stanza = new StringBuilder(); + stanza.append(""); + if (condition != null && + condition.trim().length() > 0) { + stanza.append("<").append(condition).append("/>"); + } + stanza.append(""); + return stanza.toString(); + } + } } diff --git a/source/org/jivesoftware/smack/util/PacketParserUtils.java b/source/org/jivesoftware/smack/util/PacketParserUtils.java index d76b60417..83cffb7ba 100644 --- a/source/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/source/org/jivesoftware/smack/util/PacketParserUtils.java @@ -25,6 +25,7 @@ import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.provider.PacketExtensionProvider; import org.jivesoftware.smack.provider.ProviderManager; +import org.jivesoftware.smack.sasl.SASLMechanism.Failure; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -590,6 +591,33 @@ public class PacketParserUtils { return properties; } + /** + * Parses SASL authentication error packets. + * + * @param parser the XML parser. + * @return a SASL Failure packet. + * @throws Exception if an exception occurs while parsing the packet. + */ + public static Failure parseSASLFailure(XmlPullParser parser) throws Exception { + String condition = null; + boolean done = false; + while (!done) { + int eventType = parser.next(); + + if (eventType == XmlPullParser.START_TAG) { + if (!parser.getName().equals("failure")) { + condition = parser.getName(); + } + } + else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("failure")) { + done = true; + } + } + } + return new Failure(condition); + } + /** * Parses stream error packets. *