refactor sasl 2 authentication code

This commit is contained in:
Daniel Gultsch 2022-09-24 14:58:49 +02:00
parent 9f5da67539
commit 126e8ef08c

View file

@ -1290,43 +1290,10 @@ public class XmppConnection implements Runnable {
authenticate.setContent(firstMessage); authenticate.setContent(firstMessage);
} }
} else if (version == SaslMechanism.Version.SASL_2) { } else if (version == SaslMechanism.Version.SASL_2) {
authenticate = new Element("authenticate", Namespace.SASL_2);
if (!Strings.isNullOrEmpty(firstMessage)) {
authenticate.addChild("initial-response").setContent(firstMessage);
}
final Element userAgent = authenticate.addChild("user-agent");
userAgent.setAttribute("id", account.getUuid());
userAgent
.addChild("software")
.setContent(mXmppConnectionService.getString(R.string.app_name));
if (!PhoneHelper.isEmulator()) {
userAgent
.addChild("device")
.setContent(String.format("%s %s", Build.MANUFACTURER, Build.MODEL));
}
final Element inline = authElement.findChild("inline", Namespace.SASL_2); final Element inline = authElement.findChild("inline", Namespace.SASL_2);
final boolean inlineStreamManagement = final boolean sm = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
inline != null && inline.hasChild("sm", "urn:xmpp:sm:3"); final Collection<String> bindFeatures = bindFeatures(inline);
final Element inlineBind2 = authenticate = generateAuthenticationRequest(firstMessage, bindFeatures, sm);
inline != null ? inline.findChild("bind", Namespace.BIND2) : null;
final Element inlineBind2Inline =
inlineBind2 != null ? inlineBind2.findChild("inline", Namespace.BIND2) : null;
if (inlineBind2 != null) {
final Element bind =
generateBindRequest(
inlineBind2Inline == null
? Collections.emptyList()
: Collections2.transform(
inlineBind2Inline.getChildren(),
c -> c == null ? null : c.getAttribute("var")));
authenticate.addChild(bind);
}
if (inlineStreamManagement && streamId != null) {
final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived);
this.mSmCatchupMessageCounter.set(0);
this.mWaitingForSmCatchup.set(true);
authenticate.addChild(resume);
}
} else { } else {
throw new AssertionError("Missing implementation for " + version); throw new AssertionError("Missing implementation for " + version);
} }
@ -1342,6 +1309,51 @@ public class XmppConnection implements Runnable {
tagWriter.writeElement(authenticate); tagWriter.writeElement(authenticate);
} }
private static Collection<String> bindFeatures(final Element inline) {
final Element inlineBind2 =
inline != null ? inline.findChild("bind", Namespace.BIND2) : null;
final Element inlineBind2Inline =
inlineBind2 != null ? inlineBind2.findChild("inline", Namespace.BIND2) : null;
if (inlineBind2 == null) {
return null;
}
if (inlineBind2Inline == null) {
return Collections.emptyList();
}
return Collections2.transform(
inlineBind2Inline.getChildren(), c -> c == null ? null : c.getAttribute("var"));
}
private Element generateAuthenticationRequest(
final String firstMessage,
final Collection<String> bind,
final boolean inlineStreamManagement) {
final Element authenticate = new Element("authenticate", Namespace.SASL_2);
if (!Strings.isNullOrEmpty(firstMessage)) {
authenticate.addChild("initial-response").setContent(firstMessage);
}
final Element userAgent = authenticate.addChild("user-agent");
userAgent.setAttribute("id", account.getUuid());
userAgent
.addChild("software")
.setContent(mXmppConnectionService.getString(R.string.app_name));
if (!PhoneHelper.isEmulator()) {
userAgent
.addChild("device")
.setContent(String.format("%s %s", Build.MANUFACTURER, Build.MODEL));
}
if (bind != null) {
authenticate.addChild(generateBindRequest(bind));
}
if (inlineStreamManagement && streamId != null) {
final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived);
this.mSmCatchupMessageCounter.set(0);
this.mWaitingForSmCatchup.set(true);
authenticate.addChild(resume);
}
return authenticate;
}
private Element generateBindRequest(final Collection<String> bindFeatures) { private Element generateBindRequest(final Collection<String> bindFeatures) {
Log.d(Config.LOGTAG, "inline bind features: " + bindFeatures); Log.d(Config.LOGTAG, "inline bind features: " + bindFeatures);
final Element bind = new Element("bind", Namespace.BIND2); final Element bind = new Element("bind", Namespace.BIND2);