enable SASL EXTERNAL (certificate login
This commit is contained in:
parent
7be331bbb2
commit
b519411d34
|
@ -0,0 +1,29 @@
|
||||||
|
package eu.siacs.conversations.crypto.sasl;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
|
|
||||||
|
public class External extends SaslMechanism {
|
||||||
|
|
||||||
|
public External(TagWriter tagWriter, Account account, SecureRandom rng) {
|
||||||
|
super(tagWriter, account, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 25;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMechanism() {
|
||||||
|
return "EXTERNAL";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientFirstMessage() {
|
||||||
|
return Base64.encodeToString(account.getJid().toBareJid().toString().getBytes(),Base64.NO_WRAP);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,8 @@ import android.os.Parcelable;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.security.KeyChain;
|
||||||
|
import android.security.KeyChainException;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
@ -33,7 +35,12 @@ import java.net.UnknownHostException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -45,14 +52,17 @@ import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.KeyManager;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import javax.net.ssl.X509KeyManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
import de.duenndns.ssl.MemorizingTrustManager;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.sasl.DigestMd5;
|
import eu.siacs.conversations.crypto.sasl.DigestMd5;
|
||||||
|
import eu.siacs.conversations.crypto.sasl.External;
|
||||||
import eu.siacs.conversations.crypto.sasl.Plain;
|
import eu.siacs.conversations.crypto.sasl.Plain;
|
||||||
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
|
import eu.siacs.conversations.crypto.sasl.SaslMechanism;
|
||||||
import eu.siacs.conversations.crypto.sasl.ScramSha1;
|
import eu.siacs.conversations.crypto.sasl.ScramSha1;
|
||||||
|
@ -126,6 +136,46 @@ public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
private SaslMechanism saslMechanism;
|
private SaslMechanism saslMechanism;
|
||||||
|
|
||||||
|
private X509KeyManager mKeyManager = new X509KeyManager() {
|
||||||
|
@Override
|
||||||
|
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
|
||||||
|
return account.getPrivateKeyAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getCertificateChain(String alias) {
|
||||||
|
try {
|
||||||
|
return KeyChain.getCertificateChain(mXmppConnectionService, alias);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new X509Certificate[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getClientAliases(String s, Principal[] principals) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getServerAliases(String s, Principal[] principals) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrivateKey getPrivateKey(String alias) {
|
||||||
|
try {
|
||||||
|
return KeyChain.getPrivateKey(mXmppConnectionService, alias);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private OnIqPacketReceived createPacketReceiveHandler() {
|
private OnIqPacketReceived createPacketReceiveHandler() {
|
||||||
OnIqPacketReceived receiver = new OnIqPacketReceived() {
|
OnIqPacketReceived receiver = new OnIqPacketReceived() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -551,7 +601,13 @@ public class XmppConnection implements Runnable {
|
||||||
try {
|
try {
|
||||||
final SSLContext sc = SSLContext.getInstance("TLS");
|
final SSLContext sc = SSLContext.getInstance("TLS");
|
||||||
MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
|
MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
|
||||||
sc.init(null,new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()},mXmppConnectionService.getRNG());
|
KeyManager[] keyManager;
|
||||||
|
if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) {
|
||||||
|
keyManager = new KeyManager[]{ mKeyManager };
|
||||||
|
} else {
|
||||||
|
keyManager = null;
|
||||||
|
}
|
||||||
|
sc.init(keyManager,new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()},mXmppConnectionService.getRNG());
|
||||||
final SSLSocketFactory factory = sc.getSocketFactory();
|
final SSLSocketFactory factory = sc.getSocketFactory();
|
||||||
final HostnameVerifier verifier;
|
final HostnameVerifier verifier;
|
||||||
if (mInteractive) {
|
if (mInteractive) {
|
||||||
|
@ -598,7 +654,7 @@ public class XmppConnection implements Runnable {
|
||||||
processStream(tagReader.readTag());
|
processStream(tagReader.readTag());
|
||||||
sslSocket.close();
|
sslSocket.close();
|
||||||
} catch (final NoSuchAlgorithmException | KeyManagementException e1) {
|
} catch (final NoSuchAlgorithmException | KeyManagementException e1) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
|
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
|
||||||
throw new SecurityException();
|
throw new SecurityException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -622,7 +678,9 @@ public class XmppConnection implements Runnable {
|
||||||
.findChild("mechanisms"));
|
.findChild("mechanisms"));
|
||||||
final Element auth = new Element("auth");
|
final Element auth = new Element("auth");
|
||||||
auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
|
auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
|
||||||
if (mechanisms.contains("SCRAM-SHA-1")) {
|
if (mechanisms.contains("EXTERNAL")) {
|
||||||
|
saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
|
} else if (mechanisms.contains("SCRAM-SHA-1")) {
|
||||||
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
|
||||||
} else if (mechanisms.contains("PLAIN")) {
|
} else if (mechanisms.contains("PLAIN")) {
|
||||||
saslMechanism = new Plain(tagWriter, account);
|
saslMechanism = new Plain(tagWriter, account);
|
||||||
|
|
Loading…
Reference in a new issue