feat: #420 implement blacklist to disable unsafe SSL/TLS protocol versions on Android

This commit is contained in:
Sefa Ilkimen
2021-07-15 04:00:35 +02:00
parent 9d6005af29
commit bda4eedfb9
8 changed files with 69 additions and 22 deletions
@@ -47,6 +47,13 @@ public class CordovaHttpPlugin extends CordovaPlugin implements Observer {
this.tlsConfiguration.setHostnameVerifier(null);
this.tlsConfiguration.setTrustManagers(tmf.getTrustManagers());
if (this.preferences.contains("androidblacklisttlsprotocols")) {
this.tlsConfiguration.setBlacklistedProtocols(
this.preferences.getString("androidblacklisttlsprotocols", "").split(",")
);
}
} catch (Exception e) {
Log.e(TAG, "An error occured while loading system's CA certificates", e);
}
@@ -13,9 +13,10 @@ import javax.net.ssl.TrustManager;
import com.silkimen.http.TLSSocketFactory;
public class TLSConfiguration {
private TrustManager[] trustManagers;
private KeyManager[] keyManagers;
private HostnameVerifier hostnameVerifier;
private TrustManager[] trustManagers = null;
private KeyManager[] keyManagers = null;
private HostnameVerifier hostnameVerifier = null;
private String[] blacklistedProtocols = {};
private SSLSocketFactory socketFactory;
@@ -33,6 +34,11 @@ public class TLSConfiguration {
this.socketFactory = null;
}
public void setBlacklistedProtocols(String[] protocols) {
this.blacklistedProtocols = protocols;
this.socketFactory = null;
}
public HostnameVerifier getHostnameVerifier() {
return this.hostnameVerifier;
}
@@ -46,12 +52,7 @@ public class TLSConfiguration {
SSLContext context = SSLContext.getInstance("TLS");
context.init(this.keyManagers, this.trustManagers, new SecureRandom());
if (android.os.Build.VERSION.SDK_INT < 20) {
this.socketFactory = new TLSSocketFactory(context);
} else {
this.socketFactory = context.getSocketFactory();
}
this.socketFactory = new TLSSocketFactory(context, this.blacklistedProtocols);
return this.socketFactory;
} catch (GeneralSecurityException e) {
@@ -5,6 +5,9 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
@@ -12,9 +15,11 @@ import javax.net.ssl.SSLSocketFactory;
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory delegate;
private String[] blacklistedProtocols;
public TLSSocketFactory(SSLContext context) {
delegate = context.getSocketFactory();
public TLSSocketFactory(SSLContext context, String[] blacklistedProtocols) {
this.delegate = context.getSocketFactory();
this.blacklistedProtocols = Arrays.stream(blacklistedProtocols).map(String::trim).toArray(String[]::new);
}
@Override
@@ -55,9 +60,18 @@ public class TLSSocketFactory extends SSLSocketFactory {
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" });
if (socket == null || !(socket instanceof SSLSocket)) {
return socket;
}
String[] supported = ((SSLSocket) socket).getSupportedProtocols();
String[] filtered = Arrays.stream(supported).filter(
val -> Arrays.stream(this.blacklistedProtocols).noneMatch(val::equals)
).toArray(String[]::new);
((SSLSocket) socket).setEnabledProtocols(filtered);
return socket;
}
}