request fast token

This commit is contained in:
Daniel Gultsch 2022-10-15 12:27:38 +02:00
parent 3378447f60
commit c13787873c
3 changed files with 49 additions and 5 deletions

View file

@ -18,7 +18,9 @@ import eu.siacs.conversations.utils.SSLSockets;
public abstract class HashedToken extends SaslMechanism { public abstract class HashedToken extends SaslMechanism {
private static List<String> HASH_FUNCTIONS = Arrays.asList("SHA-512", "SHA-256"); private static final String PREFIX = "HT";
private static final List<String> HASH_FUNCTIONS = Arrays.asList("SHA-512", "SHA-256");
protected final ChannelBinding channelBinding; protected final ChannelBinding channelBinding;
@ -61,7 +63,7 @@ public abstract class HashedToken extends SaslMechanism {
if (last <= first || mechanism.length() <= last) { if (last <= first || mechanism.length() <= last) {
throw new IllegalArgumentException("Not a valid HashedToken name"); throw new IllegalArgumentException("Not a valid HashedToken name");
} }
if (mechanism.substring(0, first).equals("HT")) { if (mechanism.substring(0, first).equals(PREFIX)) {
final String hashFunction = mechanism.substring(first + 1, last); final String hashFunction = mechanism.substring(first + 1, last);
final String cbShortName = mechanism.substring(last + 1); final String cbShortName = mechanism.substring(last + 1);
final ChannelBinding channelBinding = final ChannelBinding channelBinding =
@ -110,5 +112,11 @@ public abstract class HashedToken extends SaslMechanism {
.add("channelBinding", channelBinding) .add("channelBinding", channelBinding)
.toString(); .toString();
} }
public String name() {
return String.format(
"%s-%s-%s",
PREFIX, hashFunction, ChannelBinding.SHORT_NAMES.get(channelBinding));
}
} }
} }

View file

@ -0,0 +1,24 @@
package eu.siacs.conversations.crypto.sasl;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import eu.siacs.conversations.entities.Account;
public class HashedTokenSha512 extends HashedToken {
public HashedTokenSha512(final Account account, final ChannelBinding channelBinding) {
super(account, channelBinding);
}
@Override
protected HashFunction getHashFunction(final byte[] key) {
return Hashing.hmacSha512(key);
}
@Override
public String getMechanism() {
final String cbShortName = ChannelBinding.SHORT_NAMES.get(this.channelBinding);
return String.format("HT-SHA-512-%s", cbShortName);
}
}

View file

@ -181,6 +181,7 @@ public class XmppConnection implements Runnable {
private OnBindListener bindListener = null; private OnBindListener bindListener = null;
private OnMessageAcknowledged acknowledgedListener = null; private OnMessageAcknowledged acknowledgedListener = null;
private SaslMechanism saslMechanism; private SaslMechanism saslMechanism;
private HashedToken.Mechanism hashTokenRequest;
private HttpUrl redirectionUrl = null; private HttpUrl redirectionUrl = null;
private String verifiedHostname = null; private String verifiedHostname = null;
private volatile Thread mThread; private volatile Thread mThread;
@ -761,6 +762,8 @@ public class XmppConnection implements Runnable {
final Element bound = success.findChild("bound", Namespace.BIND2); final Element bound = success.findChild("bound", Namespace.BIND2);
final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3"); final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3");
final Element failed = success.findChild("failed", "urn:xmpp:sm:3"); final Element failed = success.findChild("failed", "urn:xmpp:sm:3");
final Element tokenWrapper = success.findChild("token", Namespace.FAST);
final String token = tokenWrapper == null ? null : tokenWrapper.getAttribute("token");
if (bound != null && resumed != null) { if (bound != null && resumed != null) {
Log.d( Log.d(
Config.LOGTAG, Config.LOGTAG,
@ -795,6 +798,10 @@ public class XmppConnection implements Runnable {
} }
sendPostBindInitialization(waitForDisco, carbonsEnabled != null); sendPostBindInitialization(waitForDisco, carbonsEnabled != null);
} }
//TODO figure out name either by the existence of hashTokenRequest or if scramMechanism is of instance HashedToken
if (this.hashTokenRequest != null && !Strings.isNullOrEmpty(token)) {
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": storing hashed token "+this.hashTokenRequest.name()+ " "+token);
}
} }
this.quickStartInProgress = false; this.quickStartInProgress = false;
if (version == SaslMechanism.Version.SASL) { if (version == SaslMechanism.Version.SASL) {
@ -1345,7 +1352,7 @@ public class XmppConnection implements Runnable {
final boolean sm = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3"); final boolean sm = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
final Element fast = inline == null ? null : inline.findChild("fast", Namespace.FAST); final Element fast = inline == null ? null : inline.findChild("fast", Namespace.FAST);
final Collection<String> fastMechanisms = SaslMechanism.mechanisms(fast); final Collection<String> fastMechanisms = SaslMechanism.mechanisms(fast);
Log.d(Config.LOGTAG,"fast mechanism: "+ HashedToken.Mechanism.best(fastMechanisms, SSLSockets.version(this.socket))); final HashedToken.Mechanism hashTokenRequest = HashedToken.Mechanism.best(fastMechanisms, SSLSockets.version(this.socket));
final Collection<String> bindFeatures = Bind2.features(inline); final Collection<String> bindFeatures = Bind2.features(inline);
quickStartAvailable = quickStartAvailable =
sm sm
@ -1362,7 +1369,8 @@ public class XmppConnection implements Runnable {
return; return;
} }
} }
authenticate = generateAuthenticationRequest(firstMessage, bindFeatures, sm); this.hashTokenRequest = hashTokenRequest;
authenticate = generateAuthenticationRequest(firstMessage, hashTokenRequest, bindFeatures, sm);
} else { } else {
throw new AssertionError("Missing implementation for " + version); throw new AssertionError("Missing implementation for " + version);
} }
@ -1383,11 +1391,12 @@ public class XmppConnection implements Runnable {
} }
private Element generateAuthenticationRequest(final String firstMessage) { private Element generateAuthenticationRequest(final String firstMessage) {
return generateAuthenticationRequest(firstMessage, Bind2.QUICKSTART_FEATURES, true); return generateAuthenticationRequest(firstMessage, null, Bind2.QUICKSTART_FEATURES, true);
} }
private Element generateAuthenticationRequest( private Element generateAuthenticationRequest(
final String firstMessage, final String firstMessage,
final HashedToken.Mechanism hashedTokenRequest,
final Collection<String> bind, final Collection<String> bind,
final boolean inlineStreamManagement) { final boolean inlineStreamManagement) {
final Element authenticate = new Element("authenticate", Namespace.SASL_2); final Element authenticate = new Element("authenticate", Namespace.SASL_2);
@ -1413,6 +1422,9 @@ public class XmppConnection implements Runnable {
this.mWaitingForSmCatchup.set(true); this.mWaitingForSmCatchup.set(true);
authenticate.addChild(resume); authenticate.addChild(resume);
} }
if (hashedTokenRequest != null) {
authenticate.addChild("request-token", Namespace.FAST).setAttribute("mechanism", hashedTokenRequest.name());
}
return authenticate; return authenticate;
} }