From c3189b7b465dd0a3aaf985ee868639d24f624c8a Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 22 Sep 2020 16:38:28 +0200 Subject: [PATCH] replace old cookies but don't delete them --- .../lib/common/OwnCloudClientFactory.java | 8 ++ .../android/lib/common/http/CookieJarImpl.kt | 40 +++++++ .../android/lib/common/http/HttpClient.java | 107 ++++++++---------- .../status/GetRemoteStatusOperation.kt | 2 +- .../implementation/OCServerInfoService.kt | 6 + 5 files changed, 103 insertions(+), 60 deletions(-) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/CookieJarImpl.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClientFactory.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClientFactory.java index d78e4d6a..f5c64bfa 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClientFactory.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/OwnCloudClientFactory.java @@ -27,6 +27,8 @@ package com.owncloud.android.lib.common; import android.content.Context; import android.net.Uri; +import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation; + public class OwnCloudClientFactory { /** @@ -43,7 +45,13 @@ public class OwnCloudClientFactory { client.setFollowRedirects(followRedirects); client.setContext(context); + retriveCookisFromMiddleware(client); return client; } + + public static void retriveCookisFromMiddleware(OwnCloudClient client) { + final GetRemoteStatusOperation statusOperation = new GetRemoteStatusOperation(); + statusOperation.run(client); + } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/CookieJarImpl.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/CookieJarImpl.kt new file mode 100644 index 00000000..9070c812 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/CookieJarImpl.kt @@ -0,0 +1,40 @@ +package com.owncloud.android.lib.common.http + +import okhttp3.Cookie +import okhttp3.CookieJar +import okhttp3.HttpUrl + +class CookieJarImpl( + private val sCookieStore: HashMap> +) : CookieJar { + + private fun containsCookieWithName(cookies: List, name: String): Boolean { + for (cookie: Cookie in cookies) { + if (cookie.name == name) { + return true; + } + } + return false; + } + + private fun getUpdatedCookies(oldCookies: List, newCookies: List): List { + val updatedList = ArrayList(newCookies); + for (oldCookie: Cookie in oldCookies) { + if (!containsCookieWithName(updatedList, oldCookie.name)) { + updatedList.add(oldCookie); + } + } + return updatedList; + } + + override fun saveFromResponse(url: HttpUrl, newCookies: List) { + // Avoid duplicated cookies but update + val currentCookies: List = sCookieStore[url.host] ?: ArrayList() + val updatedCookies: List = getUpdatedCookies(currentCookies, newCookies); + sCookieStore.put(url.host, updatedCookies); + } + + override fun loadForRequest(url: HttpUrl) = + sCookieStore[url.host] ?: ArrayList() + +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 06e8056d..8762954a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -39,13 +39,11 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -53,6 +51,7 @@ import java.util.concurrent.TimeUnit; * * @author David González Verdugo */ + public class HttpClient { private static OkHttpClient sOkHttpClient; private static Context sContext; @@ -64,66 +63,13 @@ public class HttpClient { try { final X509TrustManager trustManager = new AdvancedX509TrustManager( NetworkUtils.getKnownServersStore(sContext)); - - SSLContext sslContext; - - try { - sslContext = SSLContext.getInstance("TLSv1.3"); - } catch (NoSuchAlgorithmException tlsv13Exception) { - try { - Timber.w("TLSv1.3 is not supported in this device; falling through TLSv1.2"); - sslContext = SSLContext.getInstance("TLSv1.2"); - } catch (NoSuchAlgorithmException tlsv12Exception) { - try { - Timber.w("TLSv1.2 is not supported in this device; falling through TLSv1.1"); - sslContext = SSLContext.getInstance("TLSv1.1"); - } catch (NoSuchAlgorithmException tlsv11Exception) { - Timber.w("TLSv1.1 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, new TrustManager[]{trustManager}, null); - - SSLSocketFactory sslSocketFactory; - - sslSocketFactory = sslContext.getSocketFactory(); - + final SSLSocketFactory sslSocketFactory = getNewSslSocketFactory(trustManager); // Automatic cookie handling, NOT PERSISTENT - CookieJar cookieJar = new CookieJar() { - @Override - public void saveFromResponse(HttpUrl url, List cookies) { - // Avoid duplicated cookies - Set nonDuplicatedCookiesSet = new HashSet<>(cookies); - List nonDuplicatedCookiesList = new ArrayList<>(nonDuplicatedCookiesSet); + final CookieJar cookieJar = new CookieJarImpl(sCookieStore); - sCookieStore.put(url.host(), nonDuplicatedCookiesList); - } - - @Override - public List loadForRequest(HttpUrl url) { - List cookies = sCookieStore.get(url.host()); - return cookies != null ? cookies : new ArrayList<>(); - } - }; - - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() - .addNetworkInterceptor(getLogInterceptor()) - .protocols(Arrays.asList(Protocol.HTTP_1_1)) - .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) - .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) - .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .followRedirects(false) - .sslSocketFactory(sslSocketFactory, trustManager) - .hostnameVerifier((asdf, usdf) -> true) - .cookieJar(cookieJar); // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); - - sOkHttpClient = clientBuilder.build(); + sOkHttpClient = buildNewOkHttpClient(sslSocketFactory, trustManager, cookieJar); } catch (Exception e) { Timber.e(e, "Could not setup SSL system."); @@ -132,6 +78,49 @@ public class HttpClient { return sOkHttpClient; } + private static SSLContext getSslContext() throws NoSuchAlgorithmException { + try { + return SSLContext.getInstance("TLSv1.3"); + } catch (NoSuchAlgorithmException tlsv13Exception) { + try { + Timber.w("TLSv1.3 is not supported in this device; falling through TLSv1.2"); + return SSLContext.getInstance("TLSv1.2"); + } catch (NoSuchAlgorithmException tlsv12Exception) { + try { + Timber.w("TLSv1.2 is not supported in this device; falling through TLSv1.1"); + return SSLContext.getInstance("TLSv1.1"); + } catch (NoSuchAlgorithmException tlsv11Exception) { + Timber.w("TLSv1.1 is not supported in this device; falling through TLSv1.0"); + return 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 + } + } + } + } + + private static SSLSocketFactory getNewSslSocketFactory(X509TrustManager trustManager) + throws NoSuchAlgorithmException, KeyManagementException { + final SSLContext sslContext = getSslContext(); + sslContext.init(null, new TrustManager[]{trustManager}, null); + return sslContext.getSocketFactory(); + } + + private static OkHttpClient buildNewOkHttpClient(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager, + CookieJar cookieJar) { + return new OkHttpClient.Builder() + .addNetworkInterceptor(getLogInterceptor()) + .protocols(Arrays.asList(Protocol.HTTP_1_1)) + .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) + .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) + .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) + .followRedirects(false) + .sslSocketFactory(sslSocketFactory, trustManager) + .hostnameVerifier((asdf, usdf) -> true) + .cookieJar(cookieJar) + .build(); + } + public Context getContext() { return sContext; } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt index 5c16b844..ecace174 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/GetRemoteStatusOperation.kt @@ -45,7 +45,7 @@ import timber.log.Timber */ class GetRemoteStatusOperation : RemoteOperation() { - override fun run(client: OwnCloudClient): RemoteOperationResult { + public override fun run(client: OwnCloudClient): RemoteOperationResult { client.baseUri = buildFullHttpsUrl(client.baseUri) var result = tryToConnect(client) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt index 65b85479..e1250d84 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/status/services/implementation/OCServerInfoService.kt @@ -43,4 +43,10 @@ class OCServerInfoService : ServerInfoService { client: OwnCloudClient ): RemoteOperationResult = GetRemoteStatusOperation().execute(client) + + private fun createClientFromPath(path: String): OwnCloudClient { + val client = OwnCloudClient(Uri.parse(path)).apply { credentials = getAnonymousCredentials() } + OwnCloudClientFactory.retriveCookisFromMiddleware(client) + return client + } }