Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 1da23362 authored by Tobias Kaminsky's avatar Tobias Kaminsky Committed by GitHub
Browse files

Merge pull request #1308 from nextcloud/clientCert

Client cert
parents 30bcf05d fe5b7b41
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -39,10 +39,18 @@
        android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- used by AdvancedX509KeyManager to ask user via a notification to select a
         TLS client certificate when context is not able to start an Activity. -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

    <application
        android:usesCleartextTraffic="true"
        tools:targetApi="m" />
        tools:targetApi="m">

        <activity
            android:name=".common.network.SelectClientCertificateHelperActivity"
            android:exported="false" />
    </application>

</manifest>
+32 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.owncloud.android.lib.common.OwnCloudClientFactory.DEFAULT_CONNECTION_
import com.owncloud.android.lib.common.OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT_LONG
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.accounts.AccountUtils
import com.owncloud.android.lib.common.network.AdvancedX509KeyManager
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager
import com.owncloud.android.lib.common.network.NetworkUtils
import com.owncloud.android.lib.common.network.RedirectionPath
@@ -56,7 +57,8 @@ import javax.net.ssl.TrustManager
class NextcloudClient private constructor(
    val delegate: NextcloudUriDelegate,
    var credentials: String,
    val client: OkHttpClient
    val client: OkHttpClient,
    val context: Context
) : NextcloudUriProvider by delegate {
    var followRedirects = true

@@ -64,8 +66,9 @@ class NextcloudClient private constructor(
        baseUri: Uri,
        userId: String,
        credentials: String,
        client: OkHttpClient
    ) : this(NextcloudUriDelegate(baseUri, userId), credentials, client)
        client: OkHttpClient,
        context: Context
    ) : this(NextcloudUriDelegate(baseUri, userId), credentials, client, context)

    var userId: String
        get() = delegate.userId!!
@@ -79,10 +82,11 @@ class NextcloudClient private constructor(

        private fun createDefaultClient(context: Context): OkHttpClient {
            val trustManager = AdvancedX509TrustManager(NetworkUtils.getKnownServersStore(context))
            val keyManager = AdvancedX509KeyManager(context)

            val sslContext = NetworkUtils.getSSLContext()

            sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
            sslContext.init(arrayOf(keyManager), arrayOf<TrustManager>(trustManager), null)
            val sslSocketFactory = sslContext.socketFactory

            var proxy: Proxy? = null
@@ -116,25 +120,43 @@ class NextcloudClient private constructor(
        userId: String,
        credentials: String,
        context: Context
    ) : this(baseUri, userId, credentials, createDefaultClient(context))
    ) : this(baseUri, userId, credentials, createDefaultClient(context), context)

    @Suppress("TooGenericExceptionCaught")
    fun <T> execute(remoteOperation: RemoteOperation<T>): RemoteOperationResult<T> {
        return try {
        val result =
            try {
                remoteOperation.run(this)
            } catch (ex: Exception) {
                RemoteOperationResult(ex)
            }
        if (result.httpCode == HttpStatus.SC_BAD_REQUEST) {
            val url = remoteOperation.client.hostConfiguration.hostURL
            Log_OC.e(TAG, "Received http status 400 for $url -> removing client certificate")
            AdvancedX509KeyManager(context).removeKeys(url)
        }
        return result
    }

    @Throws(IOException::class)
    fun execute(method: OkHttpMethodBase): Int {
        return method.execute(this)
        val httpStatus = method.execute(this)
        if (httpStatus == HttpStatus.SC_BAD_REQUEST) {
            val uri = method.uri
            Log_OC.e(TAG, "Received http status 400 for $uri -> removing client certificate")
            AdvancedX509KeyManager(context).removeKeys(uri)
        }
        return httpStatus
    }

    internal fun execute(request: Request): ResponseOrError {
        return try {
            val response = client.newCall(request).execute()
            if (response.code == HttpStatus.SC_BAD_REQUEST) {
                val url = request.url
                Log_OC.e(TAG, "Received http status 400 for $url -> removing client certificate")
                AdvancedX509KeyManager(context).removeKeys(url)
            }
            ResponseOrError(response)
        } catch (ex: IOException) {
            ResponseOrError(ex)
+3 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.content.Context
import android.text.TextUtils
import com.owncloud.android.lib.common.OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT_LONG
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.network.AdvancedX509KeyManager
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager
import com.owncloud.android.lib.common.network.NetworkUtils
import com.owncloud.android.lib.common.utils.Log_OC
@@ -55,10 +56,11 @@ class PlainClient(context: Context) {

        private fun createDefaultClient(context: Context): OkHttpClient {
            val trustManager = AdvancedX509TrustManager(NetworkUtils.getKnownServersStore(context))
            val keyManager = AdvancedX509KeyManager(context)

            val sslContext = NetworkUtils.getSSLContext()

            sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
            sslContext.init(arrayOf(keyManager), arrayOf<TrustManager>(trustManager), null)
            val sslSocketFactory = sslContext.socketFactory

            var proxy: Proxy? = null
+17 −2
Original line number Diff line number Diff line
@@ -25,12 +25,14 @@

package com.owncloud.android.lib.common;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;

import com.nextcloud.common.DNSCache;
import com.nextcloud.common.NextcloudUriDelegate;
import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.network.AdvancedX509KeyManager;
import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.utils.Log_OC;

@@ -72,15 +74,18 @@ public class OwnCloudClient extends HttpClient {
    private OwnCloudCredentials credentials = null;
    private int mInstanceNumber;

    private AdvancedX509KeyManager keyManager;

    /**
     * Constructor
     */
    public OwnCloudClient(Uri baseUri, HttpConnectionManager connectionMgr) {
    public OwnCloudClient(Uri baseUri, HttpConnectionManager connectionMgr, Context context) {
        super(connectionMgr);

        if (baseUri == null) {
        	throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
        }
        this.keyManager = new AdvancedX509KeyManager(context);
        nextcloudUriDelegate = new NextcloudUriDelegate(baseUri);

        mInstanceNumber = sInstanceCounter++;
@@ -156,7 +161,13 @@ public class OwnCloudClient extends HttpClient {
            if (connectionTimeout >= 0) {
                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
            }
            return executeMethod(method);
            int httpStatus = executeMethod(method);
            if (httpStatus == HttpStatus.SC_BAD_REQUEST) {
                URI uri = method.getURI();
                Log_OC.e(TAG, "Received http status 400 for " + uri + " -> removing client certificate");
                keyManager.removeKeys(uri);
            }
            return httpStatus;
        } finally {
            getParams().setSoTimeout(oldSoTimeout);
            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
@@ -191,6 +202,10 @@ public class OwnCloudClient extends HttpClient {

            if (status >= 500 && status < 600 && DNSCache.isIPV6First(hostname)) {
                return retryMethodWithIPv4(method, hostname);
            } else if (status == HttpStatus.SC_BAD_REQUEST) {
                URI uri = method.getURI();
                Log_OC.e(TAG, "Received http status 400 for " + uri + " -> removing client certificate");
                keyManager.removeKeys(uri);
            }

            if (followRedirects) {
+1 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ public class OwnCloudClientFactory {
            Log_OC.e(TAG, "The local server truststore could not be read. Default SSL management" +
                    " in the system will be used for HTTPS connections", e);
        }
        OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager());
        OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager(), context);
        client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
        client.setFollowRedirects(followRedirects);

Loading