From 4a238bf243da0eae57ebe148b98a2294a177bb65 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 7 Aug 2024 12:07:51 +0200 Subject: [PATCH] reset quick start after invalid mechanism --- .../conversations/xmpp/XmppConnection.java | 31 +++++-- .../xmpp/model/AuthenticationFailure.java | 18 ++++ .../android/xmpp/model/sasl/Failure.java | 11 +++ .../android/xmpp/model/sasl/SaslError.java | 89 +++++++++++++++++++ .../xmpp/model/sasl2/Authenticate.java | 3 +- .../android/xmpp/model/sasl2/Failure.java | 12 +++ 6 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 src/main/java/im/conversations/android/xmpp/model/AuthenticationFailure.java create mode 100644 src/main/java/im/conversations/android/xmpp/model/sasl/Failure.java create mode 100644 src/main/java/im/conversations/android/xmpp/model/sasl/SaslError.java create mode 100644 src/main/java/im/conversations/android/xmpp/model/sasl2/Failure.java diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 1b5269b274d4e842182425ddb555146f35382e36..31f4ac32a371038e3773bbbfb6c8c488900af14d 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -63,6 +63,7 @@ import eu.siacs.conversations.xmpp.bind.Bind2; import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; +import im.conversations.android.xmpp.model.AuthenticationFailure; import im.conversations.android.xmpp.model.AuthenticationRequest; import im.conversations.android.xmpp.model.AuthenticationStreamFeature; import im.conversations.android.xmpp.model.StreamElement; @@ -75,8 +76,10 @@ import im.conversations.android.xmpp.model.fast.Fast; import im.conversations.android.xmpp.model.fast.RequestToken; import im.conversations.android.xmpp.model.jingle.Jingle; import im.conversations.android.xmpp.model.sasl.Auth; +import im.conversations.android.xmpp.model.sasl.Failure; import im.conversations.android.xmpp.model.sasl.Mechanisms; import im.conversations.android.xmpp.model.sasl.Response; +import im.conversations.android.xmpp.model.sasl.SaslError; import im.conversations.android.xmpp.model.sasl.Success; import im.conversations.android.xmpp.model.sasl2.Authenticate; import im.conversations.android.xmpp.model.sasl2.Authentication; @@ -616,8 +619,13 @@ public class XmppConnection implements Runnable { if (processSuccess(success)) { break; } - } else if (nextTag.isStart("failure")) { - final Element failure = tagReader.readElement(nextTag); + } else if (nextTag.isStart("failure", Namespace.SASL)) { + final var failure = tagReader.readElement(nextTag, Failure.class); + processFailure(failure); + } else if (nextTag.isStart("failure", Namespace.SASL_2)) { + final var failure = + tagReader.readElement( + nextTag, im.conversations.android.xmpp.model.sasl2.Failure.class); processFailure(failure); } else if (nextTag.isStart("continue", Namespace.SASL_2)) { // two step sasl2 - we don’t support this yet @@ -962,7 +970,7 @@ public class XmppConnection implements Runnable { } } - private void processFailure(final Element failure) throws IOException { + private void processFailure(final AuthenticationFailure failure) throws IOException { final SaslMechanism.Version version; try { version = SaslMechanism.Version.of(failure); @@ -976,10 +984,21 @@ public class XmppConnection implements Runnable { account.resetFastToken(); mXmppConnectionService.databaseBackend.updateAccount(account); } - if (failure.hasChild("temporary-auth-failure")) { + final var errorCondition = failure.getErrorCondition(); + if (errorCondition instanceof SaslError.InvalidMechanism + || errorCondition instanceof SaslError.MechanismTooWeak) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": invalid or too weak mechanism. resetting quick start"); + if (account.setOption(Account.OPTION_QUICKSTART_AVAILABLE, false)) { + mXmppConnectionService.databaseBackend.updateAccount(account); + } + throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); + } else if (errorCondition instanceof SaslError.TemporaryAuthFailure) { throw new StateChangingException(Account.State.TEMPORARY_AUTH_FAILURE); - } else if (failure.hasChild("account-disabled")) { - final String text = failure.findChildContent("text"); + } else if (errorCondition instanceof SaslError.AccountDisabled) { + final String text = failure.getText(); if (Strings.isNullOrEmpty(text)) { throw new StateChangingException(Account.State.UNAUTHORIZED); } diff --git a/src/main/java/im/conversations/android/xmpp/model/AuthenticationFailure.java b/src/main/java/im/conversations/android/xmpp/model/AuthenticationFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..7d6790a6449d08e579f36197ce021f9be3eda54b --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/AuthenticationFailure.java @@ -0,0 +1,18 @@ +package im.conversations.android.xmpp.model; + +import im.conversations.android.xmpp.model.sasl.SaslError; + +public abstract class AuthenticationFailure extends StreamElement { + + protected AuthenticationFailure(Class clazz) { + super(clazz); + } + + public SaslError getErrorCondition() { + return this.getExtension(SaslError.class); + } + + public String getText() { + return this.findChildContent("text"); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/sasl/Failure.java b/src/main/java/im/conversations/android/xmpp/model/sasl/Failure.java new file mode 100644 index 0000000000000000000000000000000000000000..1db7029b502ed50541e4fabd8b5fb0424f4f2f32 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/sasl/Failure.java @@ -0,0 +1,11 @@ +package im.conversations.android.xmpp.model.sasl; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.AuthenticationFailure; + +@XmlElement +public class Failure extends AuthenticationFailure { + public Failure() { + super(Failure.class); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/sasl/SaslError.java b/src/main/java/im/conversations/android/xmpp/model/sasl/SaslError.java new file mode 100644 index 0000000000000000000000000000000000000000..54a26709bc37b03c15cd6c8076ce7d982f96a74d --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/sasl/SaslError.java @@ -0,0 +1,89 @@ +package im.conversations.android.xmpp.model.sasl; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.Extension; + +public class SaslError extends Extension { + + private SaslError(final Class clazz) { + super(clazz); + } + + @XmlElement + public static class Aborted extends SaslError { + public Aborted() { + super(Aborted.class); + } + } + + @XmlElement + public static class AccountDisabled extends SaslError { + public AccountDisabled() { + super(AccountDisabled.class); + } + } + + @XmlElement + public static class CredentialsExpired extends SaslError { + public CredentialsExpired() { + super(CredentialsExpired.class); + } + } + + @XmlElement + public static class EncryptionRequired extends SaslError { + public EncryptionRequired() { + super(EncryptionRequired.class); + } + } + + @XmlElement + public static class IncorrectEncoding extends SaslError { + public IncorrectEncoding() { + super(IncorrectEncoding.class); + } + } + + @XmlElement + public static class InvalidAuthzid extends SaslError { + public InvalidAuthzid() { + super(InvalidAuthzid.class); + } + } + + @XmlElement + public static class InvalidMechanism extends SaslError { + public InvalidMechanism() { + super(InvalidMechanism.class); + } + } + + @XmlElement + public static class MalformedRequest extends SaslError { + public MalformedRequest() { + super(MalformedRequest.class); + } + } + + @XmlElement + public static class MechanismTooWeak extends SaslError { + public MechanismTooWeak() { + super(MechanismTooWeak.class); + } + } + + @XmlElement + public static class NotAuthorized extends SaslError { + + public NotAuthorized() { + super(NotAuthorized.class); + } + } + + @XmlElement + public static class TemporaryAuthFailure extends SaslError { + public TemporaryAuthFailure() { + super(TemporaryAuthFailure.class); + } + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/sasl2/Authenticate.java b/src/main/java/im/conversations/android/xmpp/model/sasl2/Authenticate.java index c709a779dd4614b9ec0f5e5dc2e6adf549004819..ac99ed346d49d0c15f3601b772f28c5be07431fb 100644 --- a/src/main/java/im/conversations/android/xmpp/model/sasl2/Authenticate.java +++ b/src/main/java/im/conversations/android/xmpp/model/sasl2/Authenticate.java @@ -1,10 +1,9 @@ package im.conversations.android.xmpp.model.sasl2; import eu.siacs.conversations.crypto.sasl.SaslMechanism; -import eu.siacs.conversations.xmpp.XmppConnection; + import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.AuthenticationRequest; -import im.conversations.android.xmpp.model.StreamElement; @XmlElement public class Authenticate extends AuthenticationRequest { diff --git a/src/main/java/im/conversations/android/xmpp/model/sasl2/Failure.java b/src/main/java/im/conversations/android/xmpp/model/sasl2/Failure.java new file mode 100644 index 0000000000000000000000000000000000000000..bb0e327d9b28e624bbaa6ec6863c6dc8e2672fc5 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/sasl2/Failure.java @@ -0,0 +1,12 @@ +package im.conversations.android.xmpp.model.sasl2; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.AuthenticationFailure; + +@XmlElement +public class Failure extends AuthenticationFailure { + + public Failure() { + super(Failure.class); + } +}