Refactoring

pull/214/head
M66B 1 year ago
parent e013adf7f3
commit 77fce9735e

@ -1,16 +1,23 @@
package eu.faircode.email;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.X509TrustManager;
public class SSLHelper {
static X509TrustManager getTrustManager(X509TrustManager rtm,
String server,
boolean secure, boolean cert_strict,
String trustedFingerprint,
ITrust intf) {
@ -53,6 +60,41 @@ public class SSLHelper {
} else
throw new CertificateException(principal.getName(), ex);
}
// Check host name
List<String> names = EntityCertificate.getDnsNames(chain[0]);
if (EntityCertificate.matches(server, names))
return;
// Fallback: check server/certificate IP address
if (!cert_strict)
try {
InetAddress ip = InetAddress.getByName(server);
Log.i("Checking server ip=" + ip);
for (String name : names) {
if (name.startsWith("*."))
name = name.substring(2);
Log.i("Checking cert name=" + name);
try {
for (InetAddress addr : InetAddress.getAllByName(name))
if (Arrays.equals(ip.getAddress(), addr.getAddress())) {
Log.i("Accepted " + name + " for " + server);
return;
}
} catch (UnknownHostException ex) {
Log.w(ex);
}
}
} catch (UnknownHostException ex) {
Log.w(ex);
} catch (Throwable ex) {
Log.e(ex);
}
String error = server + " not in certificate: " + TextUtils.join(",", names);
Log.i(error);
throw new CertificateException(error);
}
}

@ -1,16 +1,23 @@
package eu.faircode.email;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.X509TrustManager;
public class SSLHelper {
static X509TrustManager getTrustManager(X509TrustManager rtm,
String server,
boolean secure, boolean cert_strict,
String trustedFingerprint,
ITrust intf) {
@ -53,6 +60,41 @@ public class SSLHelper {
} else
throw new CertificateException(principal.getName(), ex);
}
// Check host name
List<String> names = EntityCertificate.getDnsNames(chain[0]);
if (EntityCertificate.matches(server, names))
return;
// Fallback: check server/certificate IP address
if (!cert_strict)
try {
InetAddress ip = InetAddress.getByName(server);
Log.i("Checking server ip=" + ip);
for (String name : names) {
if (name.startsWith("*."))
name = name.substring(2);
Log.i("Checking cert name=" + name);
try {
for (InetAddress addr : InetAddress.getAllByName(name))
if (Arrays.equals(ip.getAddress(), addr.getAddress())) {
Log.i("Accepted " + name + " for " + server);
return;
}
} catch (UnknownHostException ex) {
Log.w(ex);
}
}
} catch (UnknownHostException ex) {
Log.w(ex);
} catch (Throwable ex) {
Log.e(ex);
}
String error = server + " not in certificate: " + TextUtils.join(",", names);
Log.i(error);
throw new CertificateException(error);
}
}

@ -62,7 +62,6 @@ import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@ -90,7 +89,6 @@ import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
@ -1076,7 +1074,7 @@ public class EmailService implements AutoCloseable {
for (TrustManager tm : tms)
Log.e("Trust manager " + tm.getClass());
X509TrustManager tm = SSLHelper.getTrustManager(rtm, secure, cert_strict, trustedFingerprint,
X509TrustManager tm = SSLHelper.getTrustManager(rtm, server, secure, cert_strict, trustedFingerprint,
new SSLHelper.ITrust() {
@Override
public void checkServerTrusted(X509Certificate[] chain) {
@ -1123,62 +1121,7 @@ public class EmailService implements AutoCloseable {
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
configureSocketOptions(s);
ApplicationSecure.waitProviderInstalled();
Socket socket = configure(factory.createSocket(s, server, port, autoClose));
if (!secure || !(socket instanceof SSLSocket))
return socket;
List<String> names = new ArrayList<>();
SSLSession session = ((SSLSocket) socket).getSession();
Certificate[] certs = (session == null ? null : session.getPeerCertificates());
if (certs != null && certs.length > 0 && certs[0] instanceof X509Certificate)
try {
names = EntityCertificate.getDnsNames((X509Certificate) certs[0]);
} catch (Throwable ex) {
Log.w(ex);
}
Log.i("SSL session" +
" server=" + server +
" host=" + host + ":" + port +
" host=" + session.getPeerHost() +
" protocol=" + session.getProtocol() +
" cipher=" + session.getCipherSuite() +
" names=" + TextUtils.join(", ", names));
// Check host name
if (EntityCertificate.matches(server, names))
return socket;
// Fallback: check server/certificate IP address
if (!cert_strict)
try {
InetAddress ip = InetAddress.getByName(server);
Log.i("Checking server ip=" + ip);
for (String name : names) {
if (name.startsWith("*."))
name = name.substring(2);
Log.i("Checking cert name=" + name);
try {
for (InetAddress addr : InetAddress.getAllByName(name))
if (Arrays.equals(ip.getAddress(), addr.getAddress())) {
Log.i("Accepted " + name + " for " + server);
return socket;
}
} catch (UnknownHostException ex) {
Log.w(ex);
}
}
} catch (UnknownHostException ex) {
Log.w(ex);
} catch (Throwable ex) {
Log.e(ex);
}
String error = server + " not in certificate: " + TextUtils.join(",", names);
Log.i(error);
throw new ConnectException(error);
return configure(factory.createSocket(s, server, port, autoClose));
}
@Override

Loading…
Cancel
Save