1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-01-30 23:00:09 -05:00

Merge branch 'tls-hardening'

This commit is contained in:
cketti 2013-10-29 04:40:06 +01:00
commit a036e4d2f9
6 changed files with 128 additions and 27 deletions

View File

@ -2449,7 +2449,7 @@ public class ImapStore extends Store {
sslContext.init(null, new TrustManager[] { sslContext.init(null, new TrustManager[] {
TrustManagerFactory.get(mSettings.getHost(), secure) TrustManagerFactory.get(mSettings.getHost(), secure)
}, new SecureRandom()); }, new SecureRandom());
mSocket = sslContext.getSocketFactory().createSocket(); mSocket = TrustedSocketFactory.createSocket(sslContext);
} else { } else {
mSocket = new Socket(); mSocket = new Socket();
} }

View File

@ -330,7 +330,7 @@ public class Pop3Store extends Store {
sslContext.init(null, new TrustManager[] { sslContext.init(null, new TrustManager[] {
TrustManagerFactory.get(mHost, secure) TrustManagerFactory.get(mHost, secure)
}, new SecureRandom()); }, new SecureRandom());
mSocket = sslContext.getSocketFactory().createSocket(); mSocket = TrustedSocketFactory.createSocket(sslContext);
} else { } else {
mSocket = new Socket(); mSocket = new Socket();
} }

View File

@ -0,0 +1,96 @@
package com.fsck.k9.mail.store;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.*;
/**
* Filter and reorder list of cipher suites and TLS versions.
*
* <p>
* See: <a href="http://op-co.de/blog/posts/android_ssl_downgrade/">http://op-co.de/blog/posts/android_ssl_downgrade/</a>
* </p>
*/
public class TrustedSocketFactory {
protected static final String ENABLED_CIPHERS[];
protected static final String ENABLED_PROTOCOLS[];
static {
String preferredCiphers[] = {
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_RC4_128_SHA",
"SSL_RSA_WITH_RC4_128_MD5",
};
String preferredProtocols[] = {
"TLSv1.2", "TLSv1.1", "TLSv1"
};
String[] supportedCiphers = null;
String[] supportedProtocols = null;
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, new SecureRandom());
SSLSocketFactory sf = sslContext.getSocketFactory();
supportedCiphers = sf.getSupportedCipherSuites();
SSLSocket sock = (SSLSocket)sf.createSocket();
supportedProtocols = sock.getSupportedProtocols();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (KeyManagementException kme) {
kme.printStackTrace();
} catch (NoSuchAlgorithmException nsae) {
nsae.printStackTrace();
}
ENABLED_CIPHERS = supportedCiphers == null ? null :
filterBySupport(preferredCiphers, supportedCiphers);
ENABLED_PROTOCOLS = supportedProtocols == null ? null :
filterBySupport(preferredProtocols, supportedProtocols);
}
protected static String[] filterBySupport(String[] preferred, String[] supported) {
List<String> enabled = new ArrayList<String>();
Set<String> available = new HashSet<String>();
Collections.addAll(available, supported);
for (String item : preferred) {
if (available.contains(item)) enabled.add(item);
}
return enabled.toArray(new String[enabled.size()]);
}
public static Socket createSocket(SSLContext sslContext) throws IOException {
SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket();
hardenSocket(socket);
return socket;
}
private static void hardenSocket(SSLSocket sock) {
if (ENABLED_CIPHERS != null) {
sock.setEnabledCipherSuites(ENABLED_CIPHERS);
}
if (ENABLED_PROTOCOLS != null) {
sock.setEnabledProtocols(ENABLED_PROTOCOLS);
}
}
}

View File

@ -1,14 +1,9 @@
package com.fsck.k9.mail.transport; package com.fsck.k9.mail.store;
import com.fsck.k9.mail.store.TrustManagerFactory;
import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.LayeredSocketFactory; import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.Socket; import java.net.Socket;
@ -17,11 +12,21 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
public class TrustedSocketFactory implements LayeredSocketFactory { import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
/*
* TODO: find out what's going on here and document it.
* Using two socket factories looks suspicious.
*/
public class WebDavSocketFactory implements LayeredSocketFactory {
private SSLSocketFactory mSocketFactory; private SSLSocketFactory mSocketFactory;
private org.apache.http.conn.ssl.SSLSocketFactory mSchemeSocketFactory; private org.apache.http.conn.ssl.SSLSocketFactory mSchemeSocketFactory;
public TrustedSocketFactory(String host, boolean secure) throws NoSuchAlgorithmException, KeyManagementException { public WebDavSocketFactory(String host, boolean secure) throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("TLS"); SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { sslContext.init(null, new TrustManager[] {
TrustManagerFactory.get(host, secure) TrustManagerFactory.get(host, secure)

View File

@ -10,7 +10,6 @@ import com.fsck.k9.mail.*;
import com.fsck.k9.mail.filter.EOLConvertingOutputStream; import com.fsck.k9.mail.filter.EOLConvertingOutputStream;
import com.fsck.k9.mail.internet.MimeMessage; import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.transport.TrustedSocketFactory;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.http.*; import org.apache.http.*;
import org.apache.http.client.CookieStore; import org.apache.http.client.CookieStore;
@ -1080,7 +1079,7 @@ public class WebDavStore extends Store {
SchemeRegistry reg = mHttpClient.getConnectionManager().getSchemeRegistry(); SchemeRegistry reg = mHttpClient.getConnectionManager().getSchemeRegistry();
try { try {
Scheme s = new Scheme("https", new TrustedSocketFactory(mHost, mSecure), 443); Scheme s = new Scheme("https", new WebDavSocketFactory(mHost, mSecure), 443);
reg.register(s); reg.register(s);
} catch (NoSuchAlgorithmException nsa) { } catch (NoSuchAlgorithmException nsa) {
Log.e(K9.LOG_TAG, "NoSuchAlgorithmException in getHttpClient: " + nsa); Log.e(K9.LOG_TAG, "NoSuchAlgorithmException in getHttpClient: " + nsa);

View File

@ -14,6 +14,7 @@ import com.fsck.k9.mail.filter.SmtpDataStuffing;
import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mail.internet.MimeUtility;
import com.fsck.k9.mail.store.TrustManagerFactory; import com.fsck.k9.mail.store.TrustManagerFactory;
import com.fsck.k9.mail.store.LocalStore.LocalMessage; import com.fsck.k9.mail.store.LocalStore.LocalMessage;
import com.fsck.k9.mail.store.TrustedSocketFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
@ -244,7 +245,7 @@ public class SmtpTransport extends Transport {
sslContext.init(null, new TrustManager[] { sslContext.init(null, new TrustManager[] {
TrustManagerFactory.get(mHost, secure) TrustManagerFactory.get(mHost, secure)
}, new SecureRandom()); }, new SecureRandom());
mSocket = sslContext.getSocketFactory().createSocket(); mSocket = TrustedSocketFactory.createSocket(sslContext);
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT); mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
} else { } else {
mSocket = new Socket(); mSocket = new Socket();