diff --git a/app/src/dummy/java/eu/faircode/email/SSLHelper.java b/app/src/dummy/java/eu/faircode/email/SSLHelper.java index b53f5f779d..e9cbd713b3 100644 --- a/app/src/dummy/java/eu/faircode/email/SSLHelper.java +++ b/app/src/dummy/java/eu/faircode/email/SSLHelper.java @@ -1,17 +1,24 @@ package eu.faircode.email; +import java.security.KeyStore; import java.security.cert.X509Certificate; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; public class SSLHelper { - static X509TrustManager getTrustManager(X509TrustManager rtm, - String server, - boolean secure, boolean cert_strict, - String trustedFingerprint, - ITrust intf) { - // https://support.google.com/faqs/answer/6346016 - return null; + // https://support.google.com/faqs/answer/6346016 + + static TrustManager[] getTrustManagers(String server, boolean secure, boolean cert_strict, String trustedFingerprint, ITrust intf) { + TrustManagerFactory tmf; + try { + tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init((KeyStore) null); + return tmf.getTrustManagers(); + } catch (Throwable ex) { + Log.e(ex); + return null; + } } static boolean customTrustManager() { diff --git a/app/src/extra/java/eu/faircode/email/SSLHelper.java b/app/src/extra/java/eu/faircode/email/SSLHelper.java index c3fb5f7a01..ee9c1b1992 100644 --- a/app/src/extra/java/eu/faircode/email/SSLHelper.java +++ b/app/src/extra/java/eu/faircode/email/SSLHelper.java @@ -6,22 +6,45 @@ import androidx.annotation.NonNull; import java.net.InetAddress; import java.net.UnknownHostException; +import java.security.KeyStore; import java.security.Principal; import java.security.cert.CertPathValidatorException; import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; public class SSLHelper { - static X509TrustManager getTrustManager(X509TrustManager rtm, - String server, - boolean secure, boolean cert_strict, - String trustedFingerprint, - ITrust intf) { - return new X509TrustManager() { + static TrustManager[] getTrustManagers(String server, boolean secure, boolean cert_strict, String trustedFingerprint, ITrust intf) { + TrustManagerFactory tmf; + try { + tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init((KeyStore) null); + } catch (Throwable ex) { + Log.e(ex); + tmf = null; + } + + TrustManager[] tms = (tmf == null ? null : tmf.getTrustManagers()); + Log.i("Trust managers=" + (tms == null ? null : tms.length)); + + if (tms == null || tms.length == 0 || !(tms[0] instanceof X509TrustManager)) { + Log.e("Missing root trust manager"); + return tms; + } + + if (tms.length > 1) + for (TrustManager tm : tms) + Log.e("Trust manager " + tm.getClass()); + + final X509TrustManager rtm = (X509TrustManager) tms[0]; + + return new TrustManager[]{new X509TrustManager() { // openssl s_client -connect @Override @@ -105,9 +128,7 @@ public class SSLHelper { private boolean noAnchor(Throwable ex) { while (ex != null) { - if (ex instanceof CertPathValidatorException && - "Trust anchor for certification path not found." - .equals(ex.getMessage())) + if (ex instanceof CertPathValidatorException) return true; ex = ex.getCause(); } @@ -116,16 +137,13 @@ public class SSLHelper { private boolean isExpired(Throwable ex) { while (ex != null) { - if (ex instanceof CertPathValidatorException && - "timestamp check failed" - .equals(ex.getMessage())) + if (ex instanceof CertificateExpiredException) return true; - ex = ex.getCause(); } return false; } - }; + }}; } static boolean customTrustManager() { diff --git a/app/src/main/java/eu/faircode/email/EmailService.java b/app/src/main/java/eu/faircode/email/EmailService.java index 5b8092cd37..259d95e4cb 100644 --- a/app/src/main/java/eu/faircode/email/EmailService.java +++ b/app/src/main/java/eu/faircode/email/EmailService.java @@ -1047,6 +1047,32 @@ public class EmailService implements AutoCloseable { this.cert_strict = cert_strict; this.trustedFingerprint = fingerprint; + TrustManager[] tms = SSLHelper.getTrustManagers(server, secure, cert_strict, trustedFingerprint, + new SSLHelper.ITrust() { + @Override + public void checkServerTrusted(X509Certificate[] chain) { + certificate = chain[0]; + } + }); + + KeyManager[] km = null; + if (key != null && chain != null) + try { + Log.i("Client certificate init"); + + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(null, new char[0]); + ks.setKeyEntry(server, key, new char[0], chain); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, new char[0]); + km = kmf.getKeyManagers(); + + Log.i("Client certificate initialized"); + } catch (Throwable ex) { + Log.e(ex); + } + // https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext // https://stackoverflow.com/questions/69571364/sslcontext-getinstancetls-vulnerability // https://developer.android.com/about/versions/oreo/android-8.0-changes.html#security-all @@ -1057,50 +1083,7 @@ public class EmailService implements AutoCloseable { else sslContext = SSLContext.getInstance(protocol); Log.i("Using protocol=" + protocol + " bc=" + bc + " FIPS=" + fips); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init((KeyStore) null); - - TrustManager[] tms = tmf.getTrustManagers(); - Log.i("Trust managers=" + (tms == null ? null : tms.length)); - - if (tms == null || tms.length == 0 || !(tms[0] instanceof X509TrustManager)) { - Log.e("Missing root trust manager"); - sslContext.init(null, tms, null); - } else { - final X509TrustManager rtm = (X509TrustManager) tms[0]; - - if (tms.length > 1) - for (TrustManager tm : tms) - Log.e("Trust manager " + tm.getClass()); - - X509TrustManager tm = SSLHelper.getTrustManager(rtm, server, secure, cert_strict, trustedFingerprint, - new SSLHelper.ITrust() { - @Override - public void checkServerTrusted(X509Certificate[] chain) { - certificate = chain[0]; - } - }); - - KeyManager[] km = null; - if (key != null && chain != null) - try { - Log.i("Client certificate init"); - - KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(null, new char[0]); - ks.setKeyEntry(server, key, new char[0], chain); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, new char[0]); - km = kmf.getKeyManagers(); - - Log.i("Client certificate initialized"); - } catch (Throwable ex) { - Log.e(ex); - } - sslContext.init(km, new TrustManager[]{tm == null ? rtm : tm}, null); - } + sslContext.init(km, tms, null); factory = sslContext.getSocketFactory(); }