Просмотр исходного кода

Handle TLS client certificates in NextCloudWebViewClient

All interaction with the nextcloud server is handled by the `NextCloudWebViewClient`, so TLS client certificate handling should be done by that class. Since `AuthenticatorActivity` only extends `NextCloudWebViewClient` with some additional methods, it is enough to have the certificate handling in one place.

Signed-off-by: Elv1zz <elv1zz.git@gmail.com>
Elv1zz 2 лет назад
Родитель
Сommit
692cee7255

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

@@ -66,7 +66,6 @@ import android.util.AndroidRuntimeException;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
-import android.webkit.ClientCertRequest;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
 import android.webkit.WebResourceRequest;
@@ -103,7 +102,6 @@ import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
 import com.owncloud.android.lib.common.UserInfo;
 import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
-import com.owncloud.android.lib.common.network.AdvancedX509KeyManager;
 import com.owncloud.android.lib.common.network.CertificateCombinedException;
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
@@ -134,8 +132,6 @@ import com.owncloud.android.utils.theme.CapabilityUtils;
 import com.owncloud.android.utils.theme.ViewThemeUtils;
 
 import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.net.URLDecoder;
 import java.util.HashMap;
 import java.util.Locale;
@@ -487,24 +483,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                 if (!customError.isEmpty()) {
                     accountSetupWebviewBinding.loginWebview.loadData(customError, "text/html; charset=UTF-8", null);
                 }
-
-                if (errorCode >= 400 && errorCode < 500) {
-                    Log_OC.w(TAG, "WebView failed with error code " + errorCode + "; remove key chain aliases");
-                    // chosen client certificate alias does not seem to work -> discard it
-                    try {
-                        URL url = new URL(failingUrl);
-                        new AdvancedX509KeyManager(getApplicationContext()).removeKeys(url.getHost(), url.getPort());
-                    } catch (MalformedURLException e) {
-                        Log_OC.e(TAG, "Malformed URL: " + failingUrl);
-                    }
-                }
             }
-
-            @Override
-            public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
-                new AdvancedX509KeyManager(getApplicationContext()).handleWebViewClientCertRequest(request);
-            }
-
         });
     }
 

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

@@ -3,15 +3,20 @@ 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 java.io.ByteArrayInputStream
+import java.net.MalformedURLException
 import java.security.cert.CertificateException
 import java.security.cert.CertificateFactory
 import java.security.cert.X509Certificate
@@ -78,4 +83,36 @@ 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 == 400) {
+            Log_OC.w(tag, "WebView failed with error code $errorCode; remove key chain aliases")
+            // chosen client certificate alias does not seem to work -> discard it
+            val failingUrl = request?.url ?: return
+            val context = view?.context ?: return
+            AdvancedX509KeyManager(context).removeKeys(failingUrl.host, failingUrl.port)
+        }
+    }
 }