|
|
|
@ -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
|
|
|
|
|