1
0
mirror of https://github.com/owncloud/android-library.git synced 2026-08-13 17:32:56 +00:00

Merge branch 'develop' of github.com:owncloud/android-library into buildsystem/gradle_develop

Conflicts:
	.travis.yml
This commit is contained in:
Marcello Steiner
2014-11-21 12:44:23 +01:00
committed by MMMarcy
25 changed files with 468 additions and 337 deletions
@@ -30,6 +30,7 @@ import java.io.InputStream;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
@@ -92,11 +93,33 @@ public class OwnCloudClient extends HttpClient {
PARAM_SINGLE_COOKIE_HEADER, // to avoid problems with some web servers
PARAM_SINGLE_COOKIE_HEADER_VALUE);
applyProxySettings();
clearCredentials();
}
public void setCredentials(OwnCloudCredentials credentials) {
private void applyProxySettings() {
String proxyHost = System.getProperty("http.proxyHost");
String proxyPortSt = System.getProperty("http.proxyPort");
int proxyPort = 0;
try {
if (proxyPortSt != null && proxyPortSt.length() > 0) {
proxyPort = Integer.parseInt(proxyPortSt);
}
} catch (Exception e) {
// nothing to do here
}
if (proxyHost != null && proxyHost.length() > 0) {
HostConfiguration hostCfg = getHostConfiguration();
hostCfg.setProxy(proxyHost, proxyPort);
Log_OC.d(TAG, "Proxy settings: " + proxyHost + ":" + proxyPort);
}
}
public void setCredentials(OwnCloudCredentials credentials) {
if (credentials != null) {
mCredentials = credentials;
mCredentials.applyTo(this);
@@ -36,6 +36,7 @@ import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
@@ -43,6 +44,7 @@ import javax.net.ssl.SSLSocket;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import com.owncloud.android.lib.common.utils.Log_OC;
@@ -56,7 +58,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
* @author David A. Velasco
*/
public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
public class AdvancedSslSocketFactory implements SecureProtocolSocketFactory {
private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
@@ -71,11 +73,17 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/**
* Constructor for AdvancedSSLProtocolSocketFactory.
*/
public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) {
public AdvancedSslSocketFactory(
SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier
) {
if (sslContext == null)
throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
if (trustManager == null)
throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null Trust Manager");
if (trustManager == null && mHostnameVerifier != null)
throw new IllegalArgumentException(
"AdvancedSslSocketFactory can not be created with a null Trust Manager and a " +
"not null Hostname Verifier"
);
mSslContext = sslContext;
mTrustManager = trustManager;
mHostnameVerifier = hostnameVerifier;
@@ -84,8 +92,11 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/**
* @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);
enableSecureProtocols(socket);
verifyPeerIdentity(host, port, socket);
return socket;
}
@@ -150,7 +161,8 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
final InetAddress localAddress, final int localPort,
final HttpConnectionParams params) throws IOException,
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) {
throw new IllegalArgumentException("Parameters may not be null");
}
@@ -161,6 +173,7 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
SocketFactory socketfactory = mSslContext.getSocketFactory();
Log_OC.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
Socket socket = socketfactory.createSocket();
enableSecureProtocols(socket);
SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.setSoTimeout(params.getSoTimeout());
@@ -178,10 +191,22 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
UnknownHostException {
Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
enableSecureProtocols(socket);
verifyPeerIdentity(host, port, socket);
return socket;
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException {
Socket sslSocket = mSslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
enableSecureProtocols(sslSocket);
verifyPeerIdentity(host, port, sslSocket);
return sslSocket;
}
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(
AdvancedSslSocketFactory.class));
@@ -206,13 +231,15 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
*
* 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
*/
private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
try {
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 {
SSLSocket sock = (SSLSocket) socket; // a new SSLSession instance is created as a "side effect"
sock.startHandshake();
@@ -224,7 +251,9 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
} else {
Throwable cause = e.getCause();
Throwable previousCause = null;
while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
while ( cause != null &&
cause != previousCause &&
!(cause instanceof CertificateCombinedException)) {
previousCause = cause;
cause = cause.getCause();
}
@@ -263,9 +292,13 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
/// 3. Combine the exceptions to throw, if any
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) {
failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]);
failInHandshake = new CertificateCombinedException(
(X509Certificate) newSession.getPeerCertificates()[0]
);
failInHandshake.setHostInUrl(host);
}
failInHandshake.setSslPeerUnverifiedException(pue);
@@ -287,5 +320,23 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
throw io;
}
}
/**
* Grants that all protocols supported by the Security Provider in mSslContext are enabled in socket.
*
* Grants also that no unsupported protocol is tried to be enabled. That would trigger an exception, breaking
* the connection process although some protocols are supported.
*
* This is not cosmetic: not all the supported protocols are enabled by default. Too see an overview of
* supported and enabled protocols in the stock Security Provider in Android see the tables in
* http://developer.android.com/reference/javax/net/ssl/SSLSocket.html.
*
* @param socket
*/
private void enableSecureProtocols(Socket socket) {
SSLParameters params = mSslContext.getSupportedSSLParameters();
String [] supportedProtocols = params.getProtocols();
((SSLSocket) socket).setEnabledProtocols(supportedProtocols);
}
}
@@ -57,6 +57,12 @@ public class NetworkUtils {
/** Default timeout for establishing a connection */
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
/** Standard name for protocol TLS version 1.2 in Java Secure Socket Extension (JSSE) API */
public static final String PROTOCOL_TLSv1_2 = "TLSv1.2";
/** Standard name for protocol TLS version 1.0 in JSSE API */
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
/** Connection manager for all the OwnCloudClients */
private static MultiThreadedHttpConnectionManager mConnManager = null;
@@ -72,7 +78,9 @@ public class NetworkUtils {
* Registers or unregisters the proper components for advanced SSL handling.
* @throws IOException
*/
public static void registerAdvancedSslContext(boolean register, Context context) throws GeneralSecurityException, IOException {
@SuppressWarnings("deprecation")
public static void registerAdvancedSslContext(boolean register, Context context)
throws GeneralSecurityException, IOException {
Protocol pr = null;
try {
pr = Protocol.getProtocol("https");
@@ -93,13 +101,22 @@ public class NetworkUtils {
}
}
public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context)
throws GeneralSecurityException, IOException {
if (mAdvancedSslSocketFactory == null) {
KeyStore trustStore = getKnownServersStore(context);
AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
TrustManager[] tms = new TrustManager[] { trustMgr };
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException e) {
Log_OC.w(TAG, "TLSv1.2 is not supported in this device; falling through TLSv1.0");
sslContext = SSLContext.getInstance("TLSv1");
// should be available in any device; see reference of supported protocols in
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
}
sslContext.init(null, tms, null);
mHostnameVerifier = new BrowserCompatHostnameVerifier();
@@ -127,9 +144,11 @@ public class NetworkUtils {
* @throws KeyStoreException When the KeyStore instance could not be created.
* @throws IOException When an existing local trust store could not be loaded.
* @throws NoSuchAlgorithmException When the existing local trust store was saved with an unsupported algorithm.
* @throws CertificateException When an exception occurred while loading the certificates from the local trust store.
* @throws CertificateException When an exception occurred while loading the certificates from the local
* trust store.
*/
private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
private static KeyStore getKnownServersStore(Context context)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
if (mKnownServersStore == null) {
//mKnownServersStore = KeyStore.getInstance("BKS");
mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -143,15 +162,17 @@ public class NetworkUtils {
in.close();
}
} else {
mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
// next is necessary to initialize an empty KeyStore instance
mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
}
}
return mKnownServersStore;
}
public static void addCertToKnownServersStore(Certificate cert, Context context) throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException {
public static void addCertToKnownServersStore(Certificate cert, Context context)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore knownServers = getKnownServersStore(context);
knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
FileOutputStream fos = null;
@@ -173,7 +194,8 @@ public class NetworkUtils {
return mConnManager;
}
public static boolean isCertInKnownServersStore(Certificate cert, Context context) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
public static boolean isCertInKnownServersStore(Certificate cert, Context context)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore knownServers = getKnownServersStore(context);
Log_OC.d(TAG, "Certificate - HashCode: " + cert.hashCode() + " "
@@ -175,5 +175,4 @@ public class Log_OC {
public static String[] getLogFileNames() {
return mLogFileNames;
}
}
@@ -48,7 +48,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
public class ReadRemoteFileOperation extends RemoteOperation {
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
private static final int SYNC_READ_TIMEOUT = 10000;
private static final int SYNC_READ_TIMEOUT = 40000;
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
private String mRemotePath;