Skip to content

Commit

Permalink
Add SCRAM-SHA1 support
Browse files Browse the repository at this point in the history
Thanks to Stefan Karlsson for helping with the implementation.

Also add SASLMechanism.checkIfSuccessfulOrThrow(), to increase the
security by verifying the mechanisms state at the end of SASL
authentication.

SASLMechanism now has a SASLPrep StringTransformer.

Refactor SHA1 functions out of StringUtils into SHA1 utility class.

Add MAC utility class.

Make DummyConnection getSentpacket() methods use generics to make unit
testing SCRAM-SHA1 easier.

Fixes SMACK-398
  • Loading branch information
Flowdalic committed Oct 21, 2014
1 parent 6a2bc0c commit 403ecff
Show file tree
Hide file tree
Showing 18 changed files with 704 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ public void authenticated(Success success) throws SmackException {
if (success.getData() != null) {
challengeReceived(success.getData(), true);
}
currentMechanism.checkIfSuccessfulOrThrow();
authenticationSuccessful = true;
// Wake up the thread that is waiting in the #authenticate method
synchronized (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import org.jivesoftware.smack.compression.Java7ZlibInputOutputStream;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism;
import org.jivesoftware.smack.util.FileUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
Expand Down Expand Up @@ -130,6 +131,8 @@ public final class SmackInitialization {
// Ignore.
}

SASLAuthentication.registerSASLMechanism(new SCRAMSHA1Mechanism());

SmackConfiguration.smackInitialized = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,9 @@ public SASLAnonymous newInstance() {
return new SASLAnonymous();
}

@Override
public void checkIfSuccessfulOrThrow() throws SmackException {
// SASL Anonymous is always successful :)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.AuthMechanism;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Response;
import org.jivesoftware.smack.util.StringTransformer;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.stringencoder.Base64;

Expand Down Expand Up @@ -71,6 +72,22 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
public static final String GSSAPI = "GSSAPI";
public static final String PLAIN = "PLAIN";

// TODO Remove once Smack's min Android API is 9, where java.text.Normalizer is available
private static StringTransformer saslPrepTransformer;

/**
* Set the SASLPrep StringTransformer.
* <p>
* A simple SASLPrep StringTransformer would be for example: <code>java.text.Normalizer.normalize(string, Form.NFKC);</code>
* </p>
*
* @param stringTransformer set StringTransformer to use for SASLPrep.
* @see <a href="http://tools.ietf.org/html/rfc4013">RFC 4013 - SASLprep: Stringprep Profile for User Names and Passwords</a>
*/
public static void setSaslPrepTransformer(StringTransformer stringTransformer) {
saslPrepTransformer = stringTransformer;
}

protected XMPPConnection connection;

/**
Expand Down Expand Up @@ -238,6 +255,8 @@ public final int compareTo(SASLMechanism other) {

public abstract int getPriority();

public abstract void checkIfSuccessfulOrThrow() throws SmackException;

public SASLMechanism instanceForAuthentication(XMPPConnection connection) {
SASLMechanism saslMechansim = newInstance();
saslMechansim.connection = connection;
Expand All @@ -249,4 +268,19 @@ public SASLMechanism instanceForAuthentication(XMPPConnection connection) {
protected static byte[] toBytes(String string) {
return StringUtils.toBytes(string);
}

/**
* SASLprep the given String.
*
* @param string the String to sasl prep.
* @return the given String SASL preped
* @see <a href="http://tools.ietf.org/html/rfc4013">RFC 4013 - SASLprep: Stringprep Profile for User Names and Passwords</a>
*/
protected static String saslPrep(String string) {
StringTransformer stringTransformer = saslPrepTransformer;
if (stringTransformer != null) {
return stringTransformer.transform(string);
}
return string;
}
}
Loading

0 comments on commit 403ecff

Please sign in to comment.