Browse Source

Merge pull request #12408 from nextcloud/clientCert

Client cert
Tobias Kaminsky 1 year ago
parent
commit
aa780ca2ad

+ 1 - 0
app/src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -472,6 +472,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                 }
             }
 
+            @Override
             public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                 accountSetupWebviewBinding.loginWebviewProgressBar.setVisibility(View.GONE);
                 accountSetupWebviewBinding.loginWebview.setVisibility(View.VISIBLE);

+ 40 - 0
app/src/main/java/com/owncloud/android/ui/NextcloudWebViewClient.kt

@@ -3,14 +3,19 @@ package com.owncloud.android.ui
 import android.annotation.SuppressLint
 import android.net.http.SslCertificate
 import android.net.http.SslError
+import android.webkit.ClientCertRequest
 import android.webkit.SslErrorHandler
+import android.webkit.WebResourceRequest
+import android.webkit.WebResourceResponse
 import android.webkit.WebView
 import android.webkit.WebViewClient
 import androidx.fragment.app.FragmentManager
 import com.owncloud.android.authentication.AuthenticatorActivity
+import com.owncloud.android.lib.common.network.AdvancedX509KeyManager
 import com.owncloud.android.lib.common.network.NetworkUtils
 import com.owncloud.android.lib.common.utils.Log_OC
 import com.owncloud.android.ui.dialog.SslUntrustedCertDialog
+import org.apache.commons.httpclient.HttpStatus
 import java.io.ByteArrayInputStream
 import java.security.cert.CertificateException
 import java.security.cert.CertificateFactory
@@ -78,4 +83,39 @@ open class NextcloudWebViewClient(val supportFragmentManager: FragmentManager) :
         ft.addToBackStack(null)
         dialog.show(ft, AuthenticatorActivity.UNTRUSTED_CERT_DIALOG_TAG)
     }
+
+    /**
+     * Handle request for a TLS client certificate.
+     */
+    override fun onReceivedClientCertRequest(view: WebView?, request: ClientCertRequest?) {
+        if (view == null || request == null) {
+            return
+        }
+        AdvancedX509KeyManager(view.context).handleWebViewClientCertRequest(request)
+    }
+
+    /**
+     * Handle HTTP errors.
+     *
+     * We might receive an HTTP status code 400 (bad request), which probably tells us that our certificate
+     * is not valid (anymore), e.g. because it expired. In that case we forget the selected client certificate,
+     * so it can be re-selected.
+     */
+    override fun onReceivedHttpError(
+        view: WebView?,
+        request: WebResourceRequest?,
+        errorResponse: WebResourceResponse?
+    ) {
+        val errorCode = errorResponse?.statusCode ?: return
+        if (errorCode == HttpStatus.SC_BAD_REQUEST) {
+            // chosen client certificate alias does not seem to work -> discard it
+            val failingUrl = request?.url
+            val context = view?.context
+            if (failingUrl == null || context == null) {
+                return
+            }
+            Log_OC.w(tag, "WebView failed with error code $errorCode; remove key chain aliases")
+            AdvancedX509KeyManager(context).removeKeys(failingUrl)
+        }
+    }
 }