1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-07 16:06:08 +00:00

Merge pull request #40 from owncloud/fix_https_access_via_proxy

Fix access to HTTPS servers via proxy
This commit is contained in:
jabarros 2014-10-30 14:24:23 +01:00
commit 4f315c7e06

View File

@ -43,6 +43,7 @@ import javax.net.ssl.SSLSocket;
import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.conn.ssl.X509HostnameVerifier;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
@ -56,7 +57,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
* @author David A. Velasco * @author David A. Velasco
*/ */
public class AdvancedSslSocketFactory implements ProtocolSocketFactory { public class AdvancedSslSocketFactory implements SecureProtocolSocketFactory {
private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName(); private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
@ -71,7 +72,10 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/** /**
* Constructor for AdvancedSSLProtocolSocketFactory. * Constructor for AdvancedSSLProtocolSocketFactory.
*/ */
public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) { public AdvancedSslSocketFactory(
SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier
) {
if (sslContext == null) if (sslContext == null)
throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext"); throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
if (trustManager == null) if (trustManager == null)
@ -84,7 +88,9 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/** /**
* @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) * @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
*/ */
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException { public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
throws IOException, UnknownHostException {
Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort); Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
verifyPeerIdentity(host, port, socket); verifyPeerIdentity(host, port, socket);
return socket; return socket;
@ -150,7 +156,8 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
final InetAddress localAddress, final int localPort, final InetAddress localAddress, final int localPort,
final HttpConnectionParams params) throws IOException, final HttpConnectionParams params) throws IOException,
UnknownHostException, ConnectTimeoutException { UnknownHostException, ConnectTimeoutException {
Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params); Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" +
localPort + ", params: " + params);
if (params == null) { if (params == null) {
throw new IllegalArgumentException("Parameters may not be null"); throw new IllegalArgumentException("Parameters may not be null");
} }
@ -206,13 +213,15 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
* *
* The server certificate is verified first. * The server certificate is verified first.
* *
* Then, the host name is compared with the content of the server certificate using the current host name verifier, if any. * Then, the host name is compared with the content of the server certificate using the current host name verifier,
* if any.
* @param socket * @param socket
*/ */
private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException { private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
try { try {
CertificateCombinedException failInHandshake = null; CertificateCombinedException failInHandshake = null;
/// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an instance of AdvancedX509TrustManager) /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager
/// (that should be an instance of AdvancedX509TrustManager)
try { try {
SSLSocket sock = (SSLSocket) socket; // a new SSLSession instance is created as a "side effect" SSLSocket sock = (SSLSocket) socket; // a new SSLSession instance is created as a "side effect"
sock.startHandshake(); sock.startHandshake();
@ -224,7 +233,9 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
} else { } else {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
Throwable previousCause = null; Throwable previousCause = null;
while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) { while ( cause != null &&
cause != previousCause &&
!(cause instanceof CertificateCombinedException)) {
previousCause = cause; previousCause = cause;
cause = cause.getCause(); cause = cause.getCause();
} }
@ -263,9 +274,13 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/// 3. Combine the exceptions to throw, if any /// 3. Combine the exceptions to throw, if any
if (!verifiedHostname) { if (!verifiedHostname) {
SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException("Names in the server certificate do not match to " + host + " in the URL"); SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException(
"Names in the server certificate do not match to " + host + " in the URL"
);
if (failInHandshake == null) { if (failInHandshake == null) {
failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]); failInHandshake = new CertificateCombinedException(
(X509Certificate) newSession.getPeerCertificates()[0]
);
failInHandshake.setHostInUrl(host); failInHandshake.setHostInUrl(host);
} }
failInHandshake.setSslPeerUnverifiedException(pue); failInHandshake.setSslPeerUnverifiedException(pue);
@ -287,5 +302,12 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
throw io; throw io;
} }
} }
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException {
Socket sslSocket = mSslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
verifyPeerIdentity(host, port, sslSocket);
return sslSocket;
}
} }