Get SSLSocketFactory from GmsCore
b/15721931 This follows an example pattern from GoogleHttpClient. It tries to get the SSLCertificateSocketFactory from GmsCore using reflection. If that fails, (because GmsCore is not installed on the device) then it will fall back to the platform implementation. MailApplication sets a static object in SSLUtils that allows it to get an externally created SSLCertifcateSocketFactory. If this method is set, then it will use it, otherwise it will fall back to the platform factory. This way there is no reference to GmsCore in the AOSP email. Change-Id: I0890fe4c3d79283fb98a4dc5a62a32efd320e52a
This commit is contained in:
parent
083a013826
commit
601700a61e
@ -21,6 +21,7 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.SSLCertificateSocketFactory;
|
||||
import android.net.SSLSessionCache;
|
||||
import android.security.KeyChain;
|
||||
import android.security.KeyChainException;
|
||||
|
||||
@ -49,7 +50,7 @@ import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class SSLUtils {
|
||||
// All secure factories are the same; all insecure factories are associated with HostAuth's
|
||||
private static SSLCertificateSocketFactory sSecureFactory;
|
||||
private static javax.net.ssl.SSLSocketFactory sSecureFactory;
|
||||
|
||||
private static final boolean LOG_ENABLED = false;
|
||||
private static final String TAG = "Email.Ssl";
|
||||
@ -137,40 +138,73 @@ public class SSLUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ExternalSecureSocketFactoryBuilder {
|
||||
abstract public javax.net.ssl.SSLSocketFactory createSecureSocketFactory(
|
||||
final Context context, final int handshakeTimeoutMillis);
|
||||
}
|
||||
|
||||
private static ExternalSecureSocketFactoryBuilder sExternalSocketFactoryBuilder;
|
||||
|
||||
public static void setExternalSecureSocketFactoryBuilder(
|
||||
ExternalSecureSocketFactoryBuilder builder) {
|
||||
sExternalSocketFactoryBuilder = builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link javax.net.ssl.SSLSocketFactory}.
|
||||
* Optionally bypass all SSL certificate checks.
|
||||
*
|
||||
* @param insecure if true, bypass all SSL certificate checks
|
||||
*/
|
||||
public synchronized static SSLCertificateSocketFactory getSSLSocketFactory(Context context,
|
||||
HostAuth hostAuth, boolean insecure) {
|
||||
public synchronized static javax.net.ssl.SSLSocketFactory getSSLSocketFactory(
|
||||
final Context context, final HostAuth hostAuth, final KeyManager keyManager,
|
||||
final boolean insecure) {
|
||||
if (insecure) {
|
||||
SSLCertificateSocketFactory insecureFactory = (SSLCertificateSocketFactory)
|
||||
final SSLCertificateSocketFactory insecureFactory = (SSLCertificateSocketFactory)
|
||||
SSLCertificateSocketFactory.getInsecure(SSL_HANDSHAKE_TIMEOUT, null);
|
||||
insecureFactory.setTrustManagers(
|
||||
new TrustManager[] {
|
||||
new SameCertificateCheckingTrustManager(context, hostAuth)});
|
||||
if (keyManager != null) {
|
||||
insecureFactory.setKeyManagers(new KeyManager[] { keyManager });
|
||||
}
|
||||
return insecureFactory;
|
||||
} else {
|
||||
if (sSecureFactory == null) {
|
||||
sSecureFactory = (SSLCertificateSocketFactory)
|
||||
SSLCertificateSocketFactory.getDefault(SSL_HANDSHAKE_TIMEOUT, null);
|
||||
// First try to get use an externally supplied, more secure SSLSocketBuilder.
|
||||
// If so we should use that.
|
||||
javax.net.ssl.SSLSocketFactory socketFactory = null;
|
||||
if (sExternalSocketFactoryBuilder != null) {
|
||||
socketFactory = sExternalSocketFactoryBuilder.createSecureSocketFactory(
|
||||
context, SSL_HANDSHAKE_TIMEOUT);
|
||||
}
|
||||
if (socketFactory != null) {
|
||||
sSecureFactory = socketFactory;
|
||||
LogUtils.d(TAG, "Using externally created CertificateSocketFactory");
|
||||
return sSecureFactory;
|
||||
}
|
||||
// Only fall back to the platform one if that fails.
|
||||
LogUtils.d(TAG, "Falling back to platform CertificateSocketFactory");
|
||||
final SSLCertificateSocketFactory certificateSocketFactory =
|
||||
(SSLCertificateSocketFactory)
|
||||
SSLCertificateSocketFactory.getDefault(SSL_HANDSHAKE_TIMEOUT,
|
||||
new SSLSessionCache(context));
|
||||
if (keyManager != null) {
|
||||
certificateSocketFactory.setKeyManagers(new KeyManager[] { keyManager });
|
||||
}
|
||||
sSecureFactory = certificateSocketFactory;
|
||||
}
|
||||
return sSecureFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link org.apache.http.conn.ssl.SSLSocketFactory SSLSocketFactory} for use with the
|
||||
* Apache HTTP stack.
|
||||
* Returns a com.android.emailcommon.utility.SSLSocketFactory
|
||||
*/
|
||||
public static SSLSocketFactory getHttpSocketFactory(Context context, HostAuth hostAuth,
|
||||
KeyManager keyManager, boolean insecure) {
|
||||
SSLCertificateSocketFactory underlying = getSSLSocketFactory(context, hostAuth, insecure);
|
||||
if (keyManager != null) {
|
||||
underlying.setKeyManagers(new KeyManager[] { keyManager });
|
||||
}
|
||||
javax.net.ssl.SSLSocketFactory underlying = getSSLSocketFactory(context, hostAuth,
|
||||
keyManager, insecure);
|
||||
SSLSocketFactory wrapped = new SSLSocketFactory(underlying);
|
||||
if (insecure) {
|
||||
wrapped.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
|
@ -112,7 +112,7 @@ public class MailTransport {
|
||||
SocketAddress socketAddress = new InetSocketAddress(getHost(), getPort());
|
||||
if (canTrySslSecurity()) {
|
||||
mSocket = SSLUtils.getSSLSocketFactory(
|
||||
mContext, mHostAuth, canTrustAllCertificates()).createSocket();
|
||||
mContext, mHostAuth, null, canTrustAllCertificates()).createSocket();
|
||||
} else {
|
||||
mSocket = new Socket();
|
||||
}
|
||||
@ -152,7 +152,8 @@ public class MailTransport {
|
||||
*/
|
||||
public void reopenTls() throws MessagingException {
|
||||
try {
|
||||
mSocket = SSLUtils.getSSLSocketFactory(mContext, mHostAuth, canTrustAllCertificates())
|
||||
mSocket = SSLUtils.getSSLSocketFactory(mContext, mHostAuth, null,
|
||||
canTrustAllCertificates())
|
||||
.createSocket(mSocket, getHost(), getPort(), true);
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
|
||||
|
Loading…
Reference in New Issue
Block a user