abort on 'continue' - no client support

This commit is contained in:
Daniel Gultsch 2022-08-29 18:53:34 +02:00
parent 6202cbe26b
commit 928a16d31d
4 changed files with 75 additions and 23 deletions

View file

@ -640,6 +640,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
TLS_ERROR,
TLS_ERROR_DOMAIN,
INCOMPATIBLE_SERVER,
INCOMPATIBLE_CLIENT,
TOR_NOT_AVAILABLE,
DOWNGRADE_ATTACK,
SESSION_FAILURE,
@ -709,6 +710,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable
return R.string.account_status_tls_error_domain;
case INCOMPATIBLE_SERVER:
return R.string.account_status_incompatible_server;
case INCOMPATIBLE_CLIENT:
return R.string.account_status_incompatible_client;
case TOR_NOT_AVAILABLE:
return R.string.account_status_tor_unavailable;
case BIND_FAILURE:

View file

@ -56,11 +56,17 @@ public class Tag {
this.attributes = attributes;
}
public boolean isStart(String needle) {
if (needle == null) return false;
public boolean isStart(final String needle) {
if (needle == null) {
return false;
}
return (this.type == START) && (needle.equals(this.name));
}
public boolean isStart(final String name, final String namespace) {
return isStart(name) && namespace != null && namespace.equals(this.getAttribute("xmlns"));
}
public boolean isEnd(String needle) {
if (needle == null) return false;
return (this.type == END) && (needle.equals(this.name));

View file

@ -466,7 +466,7 @@ public class XmppConnection implements Runnable {
processStreamError(nextTag);
} else if (nextTag.isStart("features")) {
processStreamFeatures(nextTag);
} else if (nextTag.isStart("proceed")) {
} else if (nextTag.isStart("proceed", Namespace.TLS)) {
switchOverToTls();
} else if (nextTag.isStart("success")) {
final Element success = tagReader.readElement(nextTag);
@ -499,8 +499,13 @@ public class XmppConnection implements Runnable {
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 String authorizationIdentifier =
success.findChildContent("authorization-identifier");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": SASL 2.0 authorization identifier was "
+ authorizationIdentifier);
}
if (version == SaslMechanism.Version.SASL) {
tagReader.reset();
@ -513,11 +518,10 @@ public class XmppConnection implements Runnable {
}
break;
}
} else if (nextTag.isStart("failure", Namespace.TLS)) {
throw new StateChangingException(Account.State.TLS_ERROR);
} else if (nextTag.isStart("failure")) {
final Element failure = tagReader.readElement(nextTag);
if (Namespace.TLS.equals(failure.getNamespace())) {
throw new StateChangingException(Account.State.TLS_ERROR);
}
final SaslMechanism.Version version;
try {
version = SaslMechanism.Version.of(failure);
@ -547,6 +551,8 @@ public class XmppConnection implements Runnable {
}
}
throw new StateChangingException(Account.State.UNAUTHORIZED);
} else if (nextTag.isStart("continue", Namespace.SASL_2)) {
throw new StateChangingException(Account.State.INCOMPATIBLE_CLIENT);
} else if (nextTag.isStart("challenge")) {
final Element challenge = tagReader.readElement(nextTag);
final SaslMechanism.Version version;
@ -575,12 +581,19 @@ public class XmppConnection implements Runnable {
final Element enabled = tagReader.readElement(nextTag);
if ("true".equals(enabled.getAttribute("resume"))) {
this.streamId = enabled.getAttribute("id");
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
+ ": stream management(" + smVersion
+ ") enabled (resumable)");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid().toString()
+ ": stream management("
+ smVersion
+ ") enabled (resumable)");
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
+ ": stream management(" + smVersion + ") enabled");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid().toString()
+ ": stream management("
+ smVersion
+ ") enabled");
}
this.stanzasReceived = 0;
this.inSmacksSession = true;
@ -599,11 +612,15 @@ public class XmppConnection implements Runnable {
synchronized (this.mStanzaQueue) {
final int serverCount = Integer.parseInt(h);
if (serverCount < stanzasSent) {
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
+ ": session resumed with lost packages");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid().toString()
+ ": session resumed with lost packages");
stanzasSent = serverCount;
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": session resumed");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid().toString() + ": session resumed");
}
acknowledgedMessages = acknowledgeStanzaUpTo(serverCount);
for (int i = 0; i < this.mStanzaQueue.size(); ++i) {
@ -618,7 +635,8 @@ public class XmppConnection implements Runnable {
for (AbstractAcknowledgeableStanza packet : failedStanzas) {
if (packet instanceof MessagePacket) {
MessagePacket message = (MessagePacket) packet;
mXmppConnectionService.markMessage(account,
mXmppConnectionService.markMessage(
account,
message.getTo().asBareJid(),
message.getId(),
Message.STATUS_UNSEND);
@ -627,12 +645,20 @@ public class XmppConnection implements Runnable {
}
} catch (final NumberFormatException ignored) {
}
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": online with resource " + account.getResource());
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": online with resource "
+ account.getResource());
changeStatus(Account.State.ONLINE);
} else if (nextTag.isStart("r")) {
tagReader.readElement(nextTag);
if (Config.EXTENDED_SM_LOGGING) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": acknowledging stanza #" + this.stanzasReceived);
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": acknowledging stanza #"
+ this.stanzasReceived);
}
final AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
tagWriter.writeStanzaAsync(ack);
@ -642,10 +668,19 @@ public class XmppConnection implements Runnable {
if (mWaitingForSmCatchup.compareAndSet(true, false)) {
final int messageCount = mSmCatchupMessageCounter.get();
final int pendingIQs = packetCallbacks.size();
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": SM catchup complete (messages=" + messageCount + ", pending IQs=" + pendingIQs + ")");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": SM catchup complete (messages="
+ messageCount
+ ", pending IQs="
+ pendingIQs
+ ")");
accountUiNeedsRefresh = true;
if (messageCount > 0) {
mXmppConnectionService.getNotificationService().finishBacklog(true, account);
mXmppConnectionService
.getNotificationService()
.finishBacklog(true, account);
}
}
}
@ -664,13 +699,20 @@ public class XmppConnection implements Runnable {
mXmppConnectionService.updateConversationUi();
}
} catch (NumberFormatException | NullPointerException e) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server send ack without sequence number");
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": server send ack without sequence number");
}
} else if (nextTag.isStart("failed")) {
Element failed = tagReader.readElement(nextTag);
try {
final int serverCount = Integer.parseInt(failed.getAttribute("h"));
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": resumption failed but server acknowledged stanza #" + serverCount);
Log.d(
Config.LOGTAG,
account.getJid().asBareJid()
+ ": resumption failed but server acknowledged stanza #"
+ serverCount);
final boolean acknowledgedMessages;
synchronized (this.mStanzaQueue) {
acknowledgedMessages = acknowledgeStanzaUpTo(serverCount);

View file

@ -168,6 +168,7 @@
<string name="account_status_tls_error_domain">Domain not verifiable</string>
<string name="account_status_policy_violation">Policy violation</string>
<string name="account_status_incompatible_server">Incompatible server</string>
<string name="account_status_incompatible_client">Incompatible client</string>
<string name="account_status_stream_error">Stream error</string>
<string name="account_status_stream_opening_error">Stream opening error</string>
<string name="encryption_choice_unencrypted">Unencrypted</string>