diff --git a/source/org/jivesoftware/smack/SASLAuthentication.java b/source/org/jivesoftware/smack/SASLAuthentication.java index df840fe7a..1715409ce 100644 --- a/source/org/jivesoftware/smack/SASLAuthentication.java +++ b/source/org/jivesoftware/smack/SASLAuthentication.java @@ -24,6 +24,7 @@ import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.packet.Bind; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Session; +import org.jivesoftware.smack.sasl.SASLAnonymous; import org.jivesoftware.smack.sasl.SASLMechanism; import org.jivesoftware.smack.sasl.SASLPlainMechanism; @@ -68,6 +69,7 @@ public class SASLAuthentication implements UserAuthentication { * Boolean indicating if SASL negotiation has finished and was successful. */ private boolean saslNegotiated = false; + private boolean resourceBinded = false; private boolean sessionSupported = false; static { @@ -121,6 +123,45 @@ public class SASLAuthentication implements UserAuthentication { this.connection = connection; } + /** + * Returns true if the server offered ANONYMOUS SASL as a way to authenticate users. + * + * @return true if the server offered ANONYMOUS SASL as a way to authenticate users. + */ + public boolean hasAnonymousAuthentication() { + return serverMechanisms.contains("ANONYMOUS"); + } + + /** + * Returns true if the server offered SASL authentication besides ANONYMOUS SASL. + * + * @return true if the server offered SASL authentication besides ANONYMOUS SASL. + */ + public boolean hasNonAnonymousAuthentication() { + if (!serverMechanisms.isEmpty()) { + // Check that anonymous sasl is not the only supported mechanism + if (serverMechanisms.size() == 1) { + return !hasAnonymousAuthentication(); + } + return true; + } + return false; + } + + /** + * Performs SASL authentication of the specified user. If SASL authentication was successful + * then resource binding and session establishment will be performed. This method will return + * the full JID provided by the server while binding a resource to the connection.
+ * + * The server may assign a full JID with a username or resource different than the requested + * by this method. + * + * @param username the username that is authenticating with the server. + * @param password the password to send to the server. + * @param resource the desired resource. + * @return the full JID provided by the server while binding a resource to the connection. + * @throws XMPPException if an error occures while authenticating. + */ public String authenticate(String username, String password, String resource) throws XMPPException { // Locate the SASLMechanism to use @@ -221,6 +262,98 @@ public class SASLAuthentication implements UserAuthentication { } } + /** + * Performs ANONYMOUS SASL authentication. If SASL authentication was successful + * then resource binding and session establishment will be performed. This method will return + * the full JID provided by the server while binding a resource to the connection.
+ *
+ * The server will assign a full JID with a randomly generated resource and possibly with
+ * no username.
+ *
+ * @return the full JID provided by the server while binding a resource to the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ public String authenticateAnonymously() throws XMPPException {
+ try {
+ currentMechanism = new SASLAnonymous(this);
+ currentMechanism.authenticate(null, null, null);
+
+ // Wait until SASL negotiation finishes
+ synchronized (this) {
+ if (!saslNegotiated) {
+ try {
+ wait(5000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ if (saslNegotiated) {
+ // Bind a resource for this connection and
+ return bindResourceAndEstablishSession(null);
+ }
+ else {
+ return new NonSASLAuthentication(connection).authenticateAnonymously();
+ }
+ } catch (IOException e) {
+ return new NonSASLAuthentication(connection).authenticateAnonymously();
+ }
+ }
+
+ private String bindResourceAndEstablishSession(String resource) throws IOException,
+ XMPPException {
+ // We now need to bind a resource for the connection
+ // Open a new stream and wait for the response
+ connection.packetWriter.openStream();
+
+ // Wait until server sends response containing the