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:
commit
a036e4d2f9
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
96
src/com/fsck/k9/mail/store/TrustedSocketFactory.java
Normal file
96
src/com/fsck/k9/mail/store/TrustedSocketFactory.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user