From 4f92ba880bcd6fd94798b2370abd42e341a33181 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 30 Aug 2022 09:31:06 +0200 Subject: [PATCH] process authorization id in case full jid changes --- .../java/eu/siacs/conversations/xmpp/Jid.java | 3 +- .../conversations/xmpp/XmppConnection.java | 133 +++++++++++------- 2 files changed, 81 insertions(+), 55 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/Jid.java index 622a132fbab1a0fc968276b4a12b4751b96fd048..299c872b3c665bdcf20aa06fc5be1107a7a46999 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/Jid.java +++ b/src/main/java/eu/siacs/conversations/xmpp/Jid.java @@ -118,8 +118,7 @@ public interface Jid extends Comparable, Serializable, CharSequence { static Jid ofEscaped(CharSequence jid) { try { return new WrappedJid(JidCreate.from(jid)); - } catch (XmppStringprepException e) { - e.printStackTrace(); + } catch (final XmppStringprepException e) { throw new IllegalArgumentException(e); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index c49cb989cd0aba34a835bffa67dac778f7ad4c32..48a9f02815e7ec158f00ff0a984d455f1b2d825f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -470,61 +470,10 @@ public class XmppConnection implements Runnable { switchOverToTls(); } else if (nextTag.isStart("success")) { final Element success = tagReader.readElement(nextTag); - final SaslMechanism.Version version; - try { - version = SaslMechanism.Version.of(success); - } catch (final IllegalArgumentException e) { - throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); - } - final String challenge; - if (version == SaslMechanism.Version.SASL) { - challenge = success.getContent(); - } else if (version == SaslMechanism.Version.SASL_2) { - challenge = success.findChildContent("additional-data"); - } else { - throw new AssertionError("Missing implementation for " + version); - } - try { - saslMechanism.getResponse(challenge); - } catch (final SaslMechanism.AuthenticationException e) { - Log.e(Config.LOGTAG, String.valueOf(e)); - throw new StateChangingException(Account.State.UNAUTHORIZED); - } - Log.d( - Config.LOGTAG, - account.getJid().asBareJid().toString() - + ": logged in (using " - + version - + ")"); - account.setKey( - Account.PINNED_MECHANISM_KEY, String.valueOf(saslMechanism.getPriority())); - if (version == SaslMechanism.Version.SASL_2) { - final String authorizationIdentifier = - success.findChildContent("authorization-identifier"); - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() - + ": SASL 2.0 authorization identifier was " - + authorizationIdentifier); - final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3"); - final Element failed = success.findChild("failed", "urn:xmpp:sm:3"); - if (resumed != null && streamId != null) { - processResumed(resumed); - } else if (failed != null) { - processFailed(failed, false); // wait for new stream features - } - } - if (version == SaslMechanism.Version.SASL) { - tagReader.reset(); - sendStartStream(); - final Tag tag = tagReader.readTag(); - if (tag != null && tag.isStart("stream")) { - processStream(); - } else { - throw new StateChangingException(Account.State.STREAM_OPENING_ERROR); - } + if (processSuccess(success)) { break; } + } else if (nextTag.isStart("failure", Namespace.TLS)) { throw new StateChangingException(Account.State.TLS_ERROR); } else if (nextTag.isStart("failure")) { @@ -679,6 +628,84 @@ public class XmppConnection implements Runnable { } } + private boolean processSuccess(final Element success) throws IOException, XmlPullParserException { + final SaslMechanism.Version version; + try { + version = SaslMechanism.Version.of(success); + } catch (final IllegalArgumentException e) { + throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); + } + final String challenge; + if (version == SaslMechanism.Version.SASL) { + challenge = success.getContent(); + } else if (version == SaslMechanism.Version.SASL_2) { + challenge = success.findChildContent("additional-data"); + } else { + throw new AssertionError("Missing implementation for " + version); + } + try { + saslMechanism.getResponse(challenge); + } catch (final SaslMechanism.AuthenticationException e) { + Log.e(Config.LOGTAG, String.valueOf(e)); + throw new StateChangingException(Account.State.UNAUTHORIZED); + } + Log.d( + Config.LOGTAG, + account.getJid().asBareJid().toString() + + ": logged in (using " + + version + + ")"); + account.setKey( + Account.PINNED_MECHANISM_KEY, String.valueOf(saslMechanism.getPriority())); + if (version == SaslMechanism.Version.SASL_2) { + final String authorizationIdentifier = + success.findChildContent("authorization-identifier"); + final Jid authorizationJid; + try { + authorizationJid = Strings.isNullOrEmpty(authorizationIdentifier) ? null : Jid.ofEscaped(authorizationIdentifier); + } catch (final IllegalArgumentException e) { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": SASL 2.0 authorization identifier was not a valid jid"); + throw new StateChangingException(Account.State.BIND_FAILURE); + } + if (authorizationJid == null) { + throw new StateChangingException(Account.State.BIND_FAILURE); + } + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": SASL 2.0 authorization identifier was " + + authorizationJid); + if (!account.getJid().getDomain().equals(authorizationJid.getDomain())) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server tried to re-assign domain to " + authorizationJid.getDomain()); + throw new StateChangingError(Account.State.BIND_FAILURE); + } + if (authorizationJid.isFullJid() && account.setJid(authorizationJid)) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": jid changed during SASL 2.0. updating database"); + mXmppConnectionService.databaseBackend.updateAccount(account); + } + final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3"); + final Element failed = success.findChild("failed", "urn:xmpp:sm:3"); + if (resumed != null && streamId != null) { + processResumed(resumed); + } else if (failed != null) { + processFailed(failed, false); // wait for new stream features + } + } + if (version == SaslMechanism.Version.SASL) { + tagReader.reset(); + sendStartStream(); + final Tag tag = tagReader.readTag(); + if (tag != null && tag.isStart("stream")) { + processStream(); + return true; + } else { + throw new StateChangingException(Account.State.STREAM_OPENING_ERROR); + } + } else { + return false; + } + } + private void processResumed(final Element resumed) throws StateChangingException { this.inSmacksSession = true; this.isBound = true;