From 9e082d930b483ad6008f4ee973f8b5383d489c17 Mon Sep 17 00:00:00 2001 From: R Hirner Date: Sun, 18 Jan 2015 17:04:32 +0100 Subject: [PATCH] Use Apache HttpClient-Android SSLConnectionSocketFactory * SSLConnectionSocketFactory is now SNI-capable, so there's no need to manage SNI in DAVdroid * keep secure protocol/cipher suite definitions * use a patched jar until https://issues.apache.org/jira/browse/HTTPCLIENT-1591 is fixed --- app/build.gradle | 9 +- ... httpclient-android-4.3.5.2-davdroid1.jar} | Bin 506619 -> 516127 bytes .../webdav/TlsSniSocketFactoryTest.java | 39 ++- .../davdroid/webdav/DavHttpClient.java | 2 +- .../davdroid/webdav/TlsSniSocketFactory.java | 239 +++++------------- 5 files changed, 92 insertions(+), 197 deletions(-) rename app/lib/{httpclient-android-4.3.5.davdroid1.jar => httpclient-android-4.3.5.2-davdroid1.jar} (84%) diff --git a/app/build.gradle b/app/build.gradle index 6a6caa8e..9951fbaf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,7 +35,7 @@ configurations.all { dependencies { // Apache Commons compile 'commons-lang:commons-lang:2.6' - compile 'org.apache.commons:commons-io:1.3.2' + compile 'commons-io:commons-io:2.4' // Lombok for useful @helpers provided 'org.projectlombok:lombok:1.14.8' @@ -56,9 +56,10 @@ dependencies { compile 'dnsjava:dnsjava:2.1.6' // HttpClient 4.3, Android flavour for WebDAV operations - // we have to use our patched version of 4.3.5 to avoid https://issues.apache.org/jira/browse/HTTPCLIENT-1566 - compile files('lib/httpclient-android-4.3.5.davdroid1.jar') - // compile 'org.apache.httpcomponents:httpclient-android:4.3.5' + // we have to use our own patched build of 4.3.5.2-SNAPSHOT to avoid + // https://issues.apache.org/jira/browse/HTTPCLIENT-1591 + compile files('lib/httpclient-android-4.3.5.2-davdroid1.jar') + // compile 'org.apache.httpcomponents:httpclient-android:4.3.5.2-SNAPSHOT' // SimpleXML for parsing and generating WebDAV messages compile('org.simpleframework:simple-xml:2.7.1') { diff --git a/app/lib/httpclient-android-4.3.5.davdroid1.jar b/app/lib/httpclient-android-4.3.5.2-davdroid1.jar similarity index 84% rename from app/lib/httpclient-android-4.3.5.davdroid1.jar rename to app/lib/httpclient-android-4.3.5.2-davdroid1.jar index 50bdf3dc750f7d427238171fde3f3d97eee27fa7..1586e9cc3cb1bab11312f0d79cce92f314ddf809 100644 GIT binary patch delta 50850 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 Y$gUnDBeHF=t=EcjL(U(j7~8h;%3+(hZLwp@hJ< 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 diff --git a/app/src/androidTest/java/at/bitfire/davdroid/webdav/TlsSniSocketFactoryTest.java b/app/src/androidTest/java/at/bitfire/davdroid/webdav/TlsSniSocketFactoryTest.java index f7a3d571..54afcace 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/webdav/TlsSniSocketFactoryTest.java +++ b/app/src/androidTest/java/at/bitfire/davdroid/webdav/TlsSniSocketFactoryTest.java @@ -14,6 +14,8 @@ import java.net.Socket; import java.net.SocketAddress; import java.security.cert.CertPathValidatorException; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSocket; @@ -29,7 +31,7 @@ import lombok.Cleanup; public class TlsSniSocketFactoryTest extends TestCase { private static final String TAG = "davdroid.TlsSniSocketFactoryTest"; - TlsSniSocketFactory factory = TlsSniSocketFactory.INSTANCE; + TlsSniSocketFactory factory = TlsSniSocketFactory.getSocketFactory(); private InetSocketAddress sampleTlsEndpoint; @@ -41,7 +43,7 @@ public class TlsSniSocketFactoryTest extends TestCase { public void testCreateSocket() { try { - @Cleanup SSLSocket socket = factory.createSocket(null); + @Cleanup Socket socket = factory.createSocket(null); assertFalse(socket.isConnected()); } catch (IOException e) { fail(); @@ -50,9 +52,7 @@ public class TlsSniSocketFactoryTest extends TestCase { public void testConnectSocket() { try { - @Cleanup SSLSocket socket = factory.createSocket(null); - - factory.connectSocket(1000, socket, new HttpHost(sampleTlsEndpoint.getHostName()), sampleTlsEndpoint, null, null); + factory.connectSocket(1000, null, new HttpHost(sampleTlsEndpoint.getHostName()), sampleTlsEndpoint, null, null); } catch (IOException e) { Log.e(TAG, "I/O exception", e); fail(); @@ -67,7 +67,7 @@ public class TlsSniSocketFactoryTest extends TestCase { assertTrue(plain.isConnected()); // then create TLS socket on top of it and establish TLS Connection - @Cleanup SSLSocket socket = factory.createLayeredSocket(plain, sampleTlsEndpoint.getHostName(), sampleTlsEndpoint.getPort(), null); + @Cleanup Socket socket = factory.createLayeredSocket(plain, sampleTlsEndpoint.getHostName(), sampleTlsEndpoint.getPort(), null); assertTrue(socket.isConnected()); } catch (IOException e) { @@ -76,11 +76,8 @@ public class TlsSniSocketFactoryTest extends TestCase { } } - public void testSetTlsParameters() throws IOException { - @Cleanup SSLSocket socket = factory.createSocket(null); - factory.setTlsParameters(socket); - - String enabledProtocols[] = socket.getEnabledProtocols(); + public void testProtocolVersions() throws IOException { + String enabledProtocols[] = factory.protocols; // SSL (all versions) should be disabled for (String protocol : enabledProtocols) assertFalse(protocol.contains("SSL")); @@ -91,27 +88,29 @@ public class TlsSniSocketFactoryTest extends TestCase { } - public void testHostnameNotInCertificate() { + public void testHostnameNotInCertificate() throws IOException { try { // host with certificate that doesn't match host name // use the IP address as host name because IP addresses are usually not in the certificate subject - InetSocketAddress host = new InetSocketAddress(sampleTlsEndpoint.getAddress().getHostAddress(), 443); - - @Cleanup SSLSocket socket = factory.connectSocket(0, null, new HttpHost(host.getHostName()), host, null, null); + final String ipHostname = sampleTlsEndpoint.getAddress().getHostAddress(); + InetSocketAddress host = new InetSocketAddress(ipHostname, 443); + @Cleanup Socket socket = factory.connectSocket(0, null, new HttpHost(ipHostname), host, null, null); fail(); - } catch (IOException e) { - assertFalse(ExceptionUtils.indexOfType(e, SSLPeerUnverifiedException.class) == -1); + } catch (SSLException e) { + Log.i(TAG, "Expected exception", e); + assertFalse(ExceptionUtils.indexOfType(e, SSLException.class) == -1); } } - public void testUntrustedCertificate() { + public void testUntrustedCertificate() throws IOException { try { // host with certificate that is not trusted by default InetSocketAddress host = new InetSocketAddress("cacert.org", 443); - @Cleanup SSLSocket socket = factory.connectSocket(0, null, new HttpHost(host.getHostName()), host, null, null); + @Cleanup Socket socket = factory.connectSocket(0, null, new HttpHost(host.getHostName()), host, null, null); fail(); - } catch (IOException e) { + } catch (SSLHandshakeException e) { + Log.i(TAG, "Expected exception", e); assertFalse(ExceptionUtils.indexOfType(e, CertPathValidatorException.class) == -1); } } diff --git a/app/src/main/java/at/bitfire/davdroid/webdav/DavHttpClient.java b/app/src/main/java/at/bitfire/davdroid/webdav/DavHttpClient.java index 55baf356..e3c3f9a3 100644 --- a/app/src/main/java/at/bitfire/davdroid/webdav/DavHttpClient.java +++ b/app/src/main/java/at/bitfire/davdroid/webdav/DavHttpClient.java @@ -31,7 +31,7 @@ public class DavHttpClient { static { socketFactoryRegistry = RegistryBuilder. create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) - .register("https", TlsSniSocketFactory.INSTANCE) + .register("https", TlsSniSocketFactory.getSocketFactory()) .build(); // use request defaults from AndroidHttpClient diff --git a/app/src/main/java/at/bitfire/davdroid/webdav/TlsSniSocketFactory.java b/app/src/main/java/at/bitfire/davdroid/webdav/TlsSniSocketFactory.java index 1aa749e3..ceadc3b7 100644 --- a/app/src/main/java/at/bitfire/davdroid/webdav/TlsSniSocketFactory.java +++ b/app/src/main/java/at/bitfire/davdroid/webdav/TlsSniSocketFactory.java @@ -7,204 +7,99 @@ */ package at.bitfire.davdroid.webdav; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.net.SSLCertificateSocketFactory; import android.os.Build; import android.util.Log; import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.ssl.BrowserCompatHostnameVerifierHC4; -import org.apache.http.protocol.HttpContext; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -public class TlsSniSocketFactory implements LayeredConnectionSocketFactory { +import lombok.Cleanup; + +public class TlsSniSocketFactory extends SSLConnectionSocketFactory { private static final String TAG = "davdroid.TlsSniSocketFactory"; - - public final static TlsSniSocketFactory INSTANCE = new TlsSniSocketFactory(); - private final static SSLSocketFactory sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault(); - - // use BrowserCompatHostnameVerifier to allow IP addresses in the Common Name - private final static HostnameVerifier hostnameVerifier = new BrowserCompatHostnameVerifierHC4(); - - - /* - For TLS connections without HTTPS (CONNECT) proxy: - 1) socket = createSocket() is called - 2) connectSocket(socket) is called which creates a new TLS connection (but no handshake yet) - 3) reasonable encryption settings are applied to socket - 4) SNI is set up for socket - 5) handshake and certificate/host name verification - - Layered sockets are used with HTTPS (CONNECT) proxies: - 1) plain = createSocket() is called - 2) the plain socket is connected to http://proxy:8080 - 3) a CONNECT request is sent to the proxy and the response is parsed - 4) socket = createLayeredSocket(plain) is called to "upgrade" the plain connection to a TLS connection (but no handshake yet) - 5) reasonable encryption settings are applied to socket - 6) SNI is set up for socket - 7) handshake and certificate/host name verification - */ - - @Override - public SSLSocket createSocket(HttpContext context) throws IOException { - return (SSLSocket)sslSocketFactory.createSocket(); + public static TlsSniSocketFactory getSocketFactory() { + return new TlsSniSocketFactory( + (SSLSocketFactory) SSLSocketFactory.getDefault(), + new BrowserCompatHostnameVerifierHC4() // use BrowserCompatHostnameVerifier to allow IP addresses in the Common Name + ); } - @Override - public SSLSocket connectSocket(int timeout, Socket sock, HttpHost host, InetSocketAddress remoteAddr, InetSocketAddress localAddr, HttpContext context) throws IOException { - Log.d(TAG, "Establishing direct TLS connection to " + host); - final SSLSocket socket = (sock != null) ? (SSLSocket)sock : createSocket(context); + // Android 5.0+ (API level21) provides reasonable default settings + // but it still allows SSLv3 + // https://developer.android.com/about/versions/android-5.0-changes.html#ssl + static String protocols[] = null, cipherSuites[] = null; + static { + try { + @Cleanup SSLSocket socket = (SSLSocket)SSLSocketFactory.getDefault().createSocket(); - if (localAddr != null) - socket.bind(localAddr); + /* set reasonable protocol versions */ + // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) + // - remove all SSL versions (especially SSLv3) because they're insecure now + List protocols = new LinkedList(); + for (String protocol : socket.getSupportedProtocols()) + if (!protocol.toUpperCase().contains("SSL")) + protocols.add(protocol); + Log.v(TAG, "Setting allowed TLS protocols: " + StringUtils.join(protocols, ", ")); + TlsSniSocketFactory.protocols = protocols.toArray(new String[0]); - // connect the socket on TCP level - socket.connect(remoteAddr, timeout); + /* set reasonable cipher suites */ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + // choose secure cipher suites + List allowedCiphers = Arrays.asList(new String[]{ + // allowed secure ciphers according to NIST.SP.800-52r1.pdf Section 3.3.1 (see docs directory) + // TLS 1.2 + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", + // maximum interoperability + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + // additionally + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + }); - // establish and verify TLS connection - establishAndVerify(socket, host.getHostName()); - return socket; - } + List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); - @Override - public SSLSocket createLayeredSocket(Socket plain, String host, int port, HttpContext context) throws IOException { - Log.d(TAG, "Establishing layered TLS connection to " + host); + // preferred ciphers = allowed Ciphers \ availableCiphers + HashSet preferredCiphers = new HashSet(allowedCiphers); + preferredCiphers.retainAll(availableCiphers); - // create new socket for TLS connection on top of existing socket - final SSLSocket socket = (SSLSocket)sslSocketFactory.createSocket(plain, host, port, true); + // add preferred ciphers to enabled ciphers + // for maximum security, preferred ciphers should *replace* enabled ciphers, + // but I guess for the security level of DAVdroid, disabling of insecure + // ciphers should be a server-side task + HashSet enabledCiphers = preferredCiphers; + enabledCiphers.addAll(new HashSet(Arrays.asList(socket.getEnabledCipherSuites()))); - // establish and verify TLS connection - establishAndVerify(socket, host); - return socket; - } - - - /** - * Establishes and verifies a TLS connection to a (TCP-)connected SSLSocket: - * - set TLS parameters like allowed protocols and ciphers - * - set SNI host name - * - verify host name - * - verify certificate - * @param socket unconnected SSLSocket - * @param host host name for SNI - * @throws SSLPeerUnverifiedException - */ - private void establishAndVerify(SSLSocket socket, String host) throws IOException, SSLPeerUnverifiedException { - setTlsParameters(socket); - setSniHostname(socket, host); - - // TLS handshake, throws an exception for untrusted certificates - socket.startHandshake(); - - // verify hostname and certificate - SSLSession session = socket.getSession(); - if (!hostnameVerifier.verify(host, session)) - // throw exception for inavlid host names - throw new SSLPeerUnverifiedException(host); - - Log.d(TAG, "Established " + session.getProtocol() + " connection with " + session.getPeerHost() + - " using " + session.getCipherSuite()); - } - - - /** - * Prepares a TLS/SSL connection socket by: - * - setting the default TrustManager (as we have created an "insecure" connection to avoid handshake problems before) - * - setting reasonable TLS protocol versions - * - setting reasonable cipher suites (if required) - * @param socket unconnected SSLSocket to prepare - */ - @SuppressLint("DefaultLocale") - void setTlsParameters(SSLSocket socket) { - // Android 5.0+ (API level21) provides reasonable default settings - // but it still allows SSLv3 - // https://developer.android.com/about/versions/android-5.0-changes.html#ssl - - /* set reasonable protocol versions */ - // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) - // - remove all SSL versions (especially SSLv3) because they're insecure now - List protocols = new LinkedList(); - for (String protocol : socket.getSupportedProtocols()) - if (!protocol.toUpperCase().contains("SSL")) - protocols.add(protocol); - Log.v(TAG, "Setting allowed TLS protocols: " + StringUtils.join(protocols, ", ")); - socket.setEnabledProtocols(protocols.toArray(new String[0])); - - /* set reasonable cipher suites */ - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - // choose secure cipher suites - List allowedCiphers = Arrays.asList(new String[] { - // allowed secure ciphers according to NIST.SP.800-52r1.pdf Section 3.3.1 (see docs directory) - // TLS 1.2 - "TLS_RSA_WITH_AES_256_GCM_SHA384", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", - // maximum interoperability - "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", - // additionally - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - }); - - List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); - - // preferred ciphers = allowed Ciphers \ availableCiphers - HashSet preferredCiphers = new HashSet(allowedCiphers); - preferredCiphers.retainAll(availableCiphers); - - // add preferred ciphers to enabled ciphers - // for maximum security, preferred ciphers should *replace* enabled ciphers, - // but I guess for the security level of DAVdroid, disabling of insecure - // ciphers should be a server-side task - HashSet enabledCiphers = preferredCiphers; - enabledCiphers.addAll(new HashSet(Arrays.asList(socket.getEnabledCipherSuites()))); - - Log.v(TAG, "Setting allowed TLS ciphers: " + StringUtils.join(enabledCiphers, ", ")); - socket.setEnabledCipherSuites(enabledCiphers.toArray(new String[0])); - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) - private void setSniHostname(SSLSocket socket, String hostName) { - // set SNI host name - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && sslSocketFactory instanceof SSLCertificateSocketFactory) { - Log.d(TAG, "Using documented SNI with host name " + hostName); - ((SSLCertificateSocketFactory)sslSocketFactory).setHostname(socket, hostName); - } else { - Log.d(TAG, "No documented SNI support on Android <4.2, trying reflection method with host name " + hostName); - try { - java.lang.reflect.Method setHostnameMethod = socket.getClass().getMethod("setHostname", String.class); - setHostnameMethod.invoke(socket, hostName); - } catch (Exception e) { - Log.w(TAG, "SNI not useable", e); + Log.v(TAG, "Setting allowed TLS ciphers: " + StringUtils.join(enabledCiphers, ", ")); + TlsSniSocketFactory.cipherSuites = enabledCiphers.toArray(new String[0]); } + } catch (IOException e) { } } - + + public TlsSniSocketFactory(SSLSocketFactory socketfactory, X509HostnameVerifier hostnameVerifier) { + super(socketfactory, protocols, cipherSuites, hostnameVerifier); + } + }