Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a036e4d2 authored by cketti's avatar cketti
Browse files

Merge branch 'tls-hardening'

parents f7562e1b a97705ff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2449,7 +2449,7 @@ public class ImapStore extends Store {
                            sslContext.init(null, new TrustManager[] {
                                                TrustManagerFactory.get(mSettings.getHost(), secure)
                                            }, new SecureRandom());
                            mSocket = sslContext.getSocketFactory().createSocket();
                            mSocket = TrustedSocketFactory.createSocket(sslContext);
                        } else {
                            mSocket = new Socket();
                        }
+1 −1
Original line number Diff line number Diff line
@@ -330,7 +330,7 @@ public class Pop3Store extends Store {
                    sslContext.init(null, new TrustManager[] {
                                        TrustManagerFactory.get(mHost, secure)
                                    }, new SecureRandom());
                    mSocket = sslContext.getSocketFactory().createSocket();
                    mSocket = TrustedSocketFactory.createSocket(sslContext);
                } else {
                    mSocket = new Socket();
                }
+96 −0
Original line number Diff line number Diff line
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);
        }
    }
}
+27 −22
Original line number Diff line number Diff line
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.scheme.LayeredSocketFactory;
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.net.InetAddress;
import java.net.Socket;
@@ -17,11 +12,21 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
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 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.init(null, new TrustManager[] {
                TrustManagerFactory.get(host, secure)
+1 −2
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ import com.fsck.k9.mail.*;

import com.fsck.k9.mail.filter.EOLConvertingOutputStream;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.transport.TrustedSocketFactory;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.client.CookieStore;
@@ -1080,7 +1079,7 @@ public class WebDavStore extends Store {

            SchemeRegistry reg = mHttpClient.getConnectionManager().getSchemeRegistry();
            try {
                Scheme s = new Scheme("https", new TrustedSocketFactory(mHost, mSecure), 443);
                Scheme s = new Scheme("https", new WebDavSocketFactory(mHost, mSecure), 443);
                reg.register(s);
            } catch (NoSuchAlgorithmException nsa) {
                Log.e(K9.LOG_TAG, "NoSuchAlgorithmException in getHttpClient: " + nsa);
Loading