diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index ce3731536..01c7cb3b3 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -831,17 +831,17 @@ public class XmppConnection implements Runnable { } } - private void processFailure(final Element failure) throws StateChangingException { + private void processFailure(final Element failure) throws IOException { final SaslMechanism.Version version; try { version = SaslMechanism.Version.of(failure); } catch (final IllegalArgumentException e) { throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); } - Log.d(Config.LOGTAG,failure.toString()); + Log.d(Config.LOGTAG, failure.toString()); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": login failure " + version); if (SaslMechanism.hashedToken(this.saslMechanism)) { - Log.d(Config.LOGTAG,account.getJid().asBareJid() + ": resetting token"); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": resetting token"); account.resetFastToken(); mXmppConnectionService.databaseBackend.updateAccount(account); } @@ -866,7 +866,15 @@ public class XmppConnection implements Runnable { } } } - throw new StateChangingException(Account.State.UNAUTHORIZED); + if (SaslMechanism.hashedToken(this.saslMechanism)) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": fast authentication failed. falling back to regular authentication"); + authenticate(); + } else { + throw new StateChangingException(Account.State.UNAUTHORIZED); + } } private static SSLSocket sslSocketOrNull(final Socket socket) { @@ -1332,6 +1340,17 @@ public class XmppConnection implements Runnable { } } + private void authenticate() throws IOException { + final boolean isSecure = + features.encryptionEnabled || Config.ALLOW_NON_TLS_CONNECTIONS || account.isOnion(); + if (isSecure && this.streamFeatures.hasChild("authentication", Namespace.SASL_2)) {authenticate(SaslMechanism.Version.SASL_2); + } else if (isSecure && this.streamFeatures.hasChild("mechanisms", Namespace.SASL)) { + authenticate(SaslMechanism.Version.SASL); + } else { + throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); + } + } + private void authenticate(final SaslMechanism.Version version) throws IOException { final Element authElement; if (version == SaslMechanism.Version.SASL) {