From fe6f99ea6a7334f565caa4d6ee5a29d1436b4c4f Mon Sep 17 00:00:00 2001 From: jabarros Date: Mon, 4 Aug 2014 10:18:21 +0200 Subject: [PATCH 1/4] Detect when there is a change bewwen a https connection to a non-secure one and generated a new erro code. --- .../operations/RemoteOperationResult.java | 18 +++++++- .../status/GetRemoteStatusOperation.java | 46 +++++++++++++++---- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index 3b6b99a4..9bb0d4c7 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -100,7 +100,8 @@ public class RemoteOperationResult implements Serializable { SHARE_NOT_FOUND, LOCAL_STORAGE_NOT_REMOVED, FORBIDDEN, - SHARE_FORBIDDEN + SHARE_FORBIDDEN, + OK_REDIRECT_TO_NON_SECURE_CONNECTION } private boolean mSuccess = false; @@ -114,7 +115,7 @@ public class RemoteOperationResult implements Serializable { public RemoteOperationResult(ResultCode code) { mCode = code; - mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL); + mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL || code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION); mData = null; } @@ -250,6 +251,10 @@ public class RemoteOperationResult implements Serializable { return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED; } + public boolean isRedirectToNonSecureConnection() { + return mCode == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION; + } + private CertificateCombinedException getCertificateCombinedException(Exception e) { CertificateCombinedException result = null; if (e instanceof CertificateCombinedException) { @@ -371,6 +376,15 @@ public class RemoteOperationResult implements Serializable { mRedirectedLocation.toLowerCase().contains("wayf"))); } + /** + * Checks if is a non https connection + * + * @return boolean true/false + */ + public boolean isNonSecureRedirection() { + return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://"))); + } + public String getAuthenticateHeader() { return mAuthenticate; } diff --git a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java index 458a91d3..b101aafd 100644 --- a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java @@ -31,16 +31,17 @@ import org.apache.commons.httpclient.methods.GetMethod; import org.json.JSONException; import org.json.JSONObject; -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.accounts.AccountUtils; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; - import android.content.Context; import android.net.ConnectivityManager; import android.net.Uri; import android.util.Log; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.accounts.AccountUtils; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; + /** * Checks if the server is valid and if the server supports the Share API * @@ -93,10 +94,35 @@ public class GetRemoteStatusOperation extends RemoteOperation { RemoteOperationResult.ResultCode.OK_NO_SSL ); - ArrayList data = new ArrayList(); - data.add(ocVersion); - mLatestResult.setData(data); - retval = true; + RemoteOperation operation = new ExistenceCheckRemoteOperation("", mContext, false); + client.setFollowRedirects(false); + boolean isRedirectToNonSecureConnection = false; + + // checks if there are any reconnection to a non secure + // connection + RemoteOperationResult result = operation.execute(client); + String redirectedLocation = result.getRedirectedLocation(); + while (baseUrlSt.startsWith("https://") && redirectedLocation != null + && redirectedLocation.length() > 0 + && result.isNonSecureRedirection()) { + client.setBaseUri(Uri.parse(result.getRedirectedLocation())); + result = operation.execute(client); + redirectedLocation = result.getRedirectedLocation(); + + isRedirectToNonSecureConnection = true; + break; + } + + if (isRedirectToNonSecureConnection) { + mLatestResult = new RemoteOperationResult( + RemoteOperationResult.ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION); + } else { + retval = true; + } + + ArrayList data = new ArrayList(); + data.add(ocVersion); + mLatestResult.setData(data); } } @@ -148,7 +174,7 @@ public class GetRemoteStatusOperation extends RemoteOperation { } else { client.setBaseUri(Uri.parse("https://" + baseUriStr)); boolean httpsSuccess = tryConnection(client); - if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) { + if (!httpsSuccess && !mLatestResult.isSslRecoverableException() && mLatestResult.isNonSecureRedirection()) { Log.d(TAG, "establishing secure connection failed, trying non secure connection"); client.setBaseUri(Uri.parse("http://" + baseUriStr)); tryConnection(client); From 585054092df5ad4c8fe67bd395d6f17cacf3b3c2 Mon Sep 17 00:00:00 2001 From: jabarros Date: Mon, 4 Aug 2014 14:25:31 +0200 Subject: [PATCH 2/4] Fixed bug. It is not possible to connect to a http server --- .../lib/resources/status/GetRemoteStatusOperation.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java index b101aafd..e51f7566 100644 --- a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java @@ -116,13 +116,12 @@ public class GetRemoteStatusOperation extends RemoteOperation { if (isRedirectToNonSecureConnection) { mLatestResult = new RemoteOperationResult( RemoteOperationResult.ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION); - } else { - retval = true; } ArrayList data = new ArrayList(); data.add(ocVersion); mLatestResult.setData(data); + retval = true; } } @@ -174,7 +173,7 @@ public class GetRemoteStatusOperation extends RemoteOperation { } else { client.setBaseUri(Uri.parse("https://" + baseUriStr)); boolean httpsSuccess = tryConnection(client); - if (!httpsSuccess && !mLatestResult.isSslRecoverableException() && mLatestResult.isNonSecureRedirection()) { + if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) { Log.d(TAG, "establishing secure connection failed, trying non secure connection"); client.setBaseUri(Uri.parse("http://" + baseUriStr)); tryConnection(client); From 07f3d9caaebee7469d92f5d12c55e4464cc992cc Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Wed, 6 Aug 2014 10:59:33 +0200 Subject: [PATCH 3/4] Fixed check of HTTPS downgrade so that works with multiple redirections, and done without an extra request --- .../status/GetRemoteStatusOperation.java | 80 +++++++++++-------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java index e51f7566..0bdfa78b 100644 --- a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java @@ -40,7 +40,6 @@ import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; /** * Checks if the server is valid and if the server supports the Share API @@ -52,7 +51,10 @@ import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; public class GetRemoteStatusOperation extends RemoteOperation { - /** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs. */ + /** + * Maximum time to wait for a response from the server when the connection is being tested, + * in MILLISECONDs. + */ public static final int TRY_CONNECTION_TIMEOUT = 5000; private static final String TAG = GetRemoteStatusOperation.class.getSimpleName(); @@ -73,7 +75,36 @@ public class GetRemoteStatusOperation extends RemoteOperation { String baseUrlSt = client.getBaseUri().toString(); try { get = new GetMethod(baseUrlSt + AccountUtils.STATUS_PATH); + + client.setFollowRedirects(false); + boolean isRedirectToNonSecureConnection = false; int status = client.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT); + mLatestResult = new RemoteOperationResult( + (status == HttpStatus.SC_OK), + status, + get.getResponseHeaders() + ); + + if (baseUrlSt.startsWith("https://")) { + String redirectedLocation = mLatestResult.getRedirectedLocation(); + while (redirectedLocation != null && redirectedLocation.length() > 0 + && !mLatestResult.isSuccess()) { + + isRedirectToNonSecureConnection = redirectedLocation.startsWith("http://"); + get.releaseConnection(); + get = new GetMethod(redirectedLocation); + status = client.executeMethod( + get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT + ); + mLatestResult = new RemoteOperationResult( + (status == HttpStatus.SC_OK), + status, + get.getResponseHeaders() + ); + redirectedLocation = mLatestResult.getRedirectedLocation(); + } + } + String response = get.getResponseBodyAsString(); if (status == HttpStatus.SC_OK) { JSONObject json = new JSONObject(response); @@ -88,35 +119,19 @@ public class GetRemoteStatusOperation extends RemoteOperation { RemoteOperationResult.ResultCode.BAD_OC_VERSION); } else { - mLatestResult = new RemoteOperationResult( - baseUrlSt.startsWith("https://") ? - RemoteOperationResult.ResultCode.OK_SSL : - RemoteOperationResult.ResultCode.OK_NO_SSL - ); - - RemoteOperation operation = new ExistenceCheckRemoteOperation("", mContext, false); - client.setFollowRedirects(false); - boolean isRedirectToNonSecureConnection = false; - - // checks if there are any reconnection to a non secure - // connection - RemoteOperationResult result = operation.execute(client); - String redirectedLocation = result.getRedirectedLocation(); - while (baseUrlSt.startsWith("https://") && redirectedLocation != null - && redirectedLocation.length() > 0 - && result.isNonSecureRedirection()) { - client.setBaseUri(Uri.parse(result.getRedirectedLocation())); - result = operation.execute(client); - redirectedLocation = result.getRedirectedLocation(); - - isRedirectToNonSecureConnection = true; - break; - } - - if (isRedirectToNonSecureConnection) { - mLatestResult = new RemoteOperationResult( - RemoteOperationResult.ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION); - } + // success + if (isRedirectToNonSecureConnection) { + mLatestResult = new RemoteOperationResult( + RemoteOperationResult.ResultCode. + OK_REDIRECT_TO_NON_SECURE_CONNECTION + ); + } else { + mLatestResult = new RemoteOperationResult( + baseUrlSt.startsWith("https://") ? + RemoteOperationResult.ResultCode.OK_SSL : + RemoteOperationResult.ResultCode.OK_NO_SSL + ); + } ArrayList data = new ArrayList(); data.add(ocVersion); @@ -145,7 +160,8 @@ public class GetRemoteStatusOperation extends RemoteOperation { Log.i(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); } else if (mLatestResult.getException() != null) { - Log.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(), mLatestResult.getException()); + Log.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage(), + mLatestResult.getException()); } else { Log.e(TAG, "Connection check at " + baseUrlSt + ": " + mLatestResult.getLogMessage()); From e43e43f51a895c591b72aaef8f36ef5595d18dba Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Wed, 6 Aug 2014 11:16:17 +0200 Subject: [PATCH 4/4] Fixed logic of HTTPS downgrade detection for multiple redirections, and grant that redirection if followed for HTTP servers --- .../status/GetRemoteStatusOperation.java | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java index 0bdfa78b..a9a16bde 100644 --- a/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java +++ b/src/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.java @@ -85,25 +85,26 @@ public class GetRemoteStatusOperation extends RemoteOperation { get.getResponseHeaders() ); - if (baseUrlSt.startsWith("https://")) { - String redirectedLocation = mLatestResult.getRedirectedLocation(); - while (redirectedLocation != null && redirectedLocation.length() > 0 - && !mLatestResult.isSuccess()) { - - isRedirectToNonSecureConnection = redirectedLocation.startsWith("http://"); - get.releaseConnection(); - get = new GetMethod(redirectedLocation); - status = client.executeMethod( - get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT - ); - mLatestResult = new RemoteOperationResult( - (status == HttpStatus.SC_OK), - status, - get.getResponseHeaders() - ); - redirectedLocation = mLatestResult.getRedirectedLocation(); - } - } + String redirectedLocation = mLatestResult.getRedirectedLocation(); + while (redirectedLocation != null && redirectedLocation.length() > 0 + && !mLatestResult.isSuccess()) { + + isRedirectToNonSecureConnection |= ( + baseUrlSt.startsWith("https://") && + redirectedLocation.startsWith("http://") + ); + get.releaseConnection(); + get = new GetMethod(redirectedLocation); + status = client.executeMethod( + get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT + ); + mLatestResult = new RemoteOperationResult( + (status == HttpStatus.SC_OK), + status, + get.getResponseHeaders() + ); + redirectedLocation = mLatestResult.getRedirectedLocation(); + } String response = get.getResponseBodyAsString(); if (status == HttpStatus.SC_OK) {