mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-15 05:55:06 -05:00
124 lines
4.1 KiB
Java
124 lines
4.1 KiB
Java
|
|
package com.fsck.k9.net.ssl;
|
|
|
|
import android.util.Log;
|
|
|
|
import com.fsck.k9.helper.DomainNameChecker;
|
|
import com.fsck.k9.mail.CertificateChainException;
|
|
import com.fsck.k9.security.LocalKeyStore;
|
|
|
|
import javax.net.ssl.TrustManager;
|
|
import javax.net.ssl.X509TrustManager;
|
|
import java.security.KeyStore;
|
|
import java.security.KeyStoreException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.cert.CertificateException;
|
|
import java.security.cert.X509Certificate;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
public final class TrustManagerFactory {
|
|
private static final String LOG_TAG = "TrustManagerFactory";
|
|
|
|
private static X509TrustManager defaultTrustManager;
|
|
|
|
private static LocalKeyStore keyStore;
|
|
|
|
|
|
private static class SecureX509TrustManager implements X509TrustManager {
|
|
private static final Map<String, SecureX509TrustManager> mTrustManager =
|
|
new HashMap<String, SecureX509TrustManager>();
|
|
|
|
private final String mHost;
|
|
private final int mPort;
|
|
|
|
private SecureX509TrustManager(String host, int port) {
|
|
mHost = host;
|
|
mPort = port;
|
|
}
|
|
|
|
public synchronized static X509TrustManager getInstance(String host, int port) {
|
|
String key = host + ":" + port;
|
|
SecureX509TrustManager trustManager;
|
|
if (mTrustManager.containsKey(key)) {
|
|
trustManager = mTrustManager.get(key);
|
|
} else {
|
|
trustManager = new SecureX509TrustManager(host, port);
|
|
mTrustManager.put(key, trustManager);
|
|
}
|
|
|
|
return trustManager;
|
|
}
|
|
|
|
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
|
throws CertificateException {
|
|
defaultTrustManager.checkClientTrusted(chain, authType);
|
|
}
|
|
|
|
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
|
throws CertificateException {
|
|
String message = null;
|
|
boolean foundInGlobalKeyStore = false;
|
|
try {
|
|
defaultTrustManager.checkServerTrusted(chain, authType);
|
|
foundInGlobalKeyStore = true;
|
|
} catch (CertificateException e) {
|
|
message = e.getMessage();
|
|
}
|
|
|
|
X509Certificate certificate = chain[0];
|
|
|
|
// Check the local key store if we couldn't verify the certificate using the global
|
|
// key store or if the host name doesn't match the certificate name
|
|
if (foundInGlobalKeyStore
|
|
&& DomainNameChecker.match(certificate, mHost)
|
|
|| keyStore.isValidCertificate(certificate, mHost, mPort)) {
|
|
return;
|
|
}
|
|
|
|
if (message == null) {
|
|
message = (foundInGlobalKeyStore) ?
|
|
"Certificate domain name does not match " + mHost :
|
|
"Couldn't find certificate in local key store";
|
|
}
|
|
|
|
throw new CertificateChainException(message, chain);
|
|
}
|
|
|
|
public X509Certificate[] getAcceptedIssuers() {
|
|
return defaultTrustManager.getAcceptedIssuers();
|
|
}
|
|
|
|
}
|
|
|
|
static {
|
|
try {
|
|
keyStore = LocalKeyStore.getInstance();
|
|
|
|
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
|
|
tmf.init((KeyStore) null);
|
|
|
|
TrustManager[] tms = tmf.getTrustManagers();
|
|
if (tms != null) {
|
|
for (TrustManager tm : tms) {
|
|
if (tm instanceof X509TrustManager) {
|
|
defaultTrustManager = (X509TrustManager) tm;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch (NoSuchAlgorithmException e) {
|
|
Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
|
|
} catch (KeyStoreException e) {
|
|
Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
|
|
}
|
|
}
|
|
|
|
private TrustManagerFactory() {
|
|
}
|
|
|
|
public static X509TrustManager get(String host, int port) {
|
|
return SecureX509TrustManager.getInstance(host, port);
|
|
}
|
|
}
|