Browse Source

Merge branch 'add_ssl_warning_dialog_for_devices_without_access_to_X509Certificte_in_WebView_SSL_errors' into check_server_certificates_in_SSO_webview

masensio 11 years ago
parent
commit
9cac3b60a5

+ 8 - 2
res/layout/ssl_untrusted_cert_layout.xml

@@ -27,6 +27,7 @@
 		android:id="@+id/header"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
+		android:layout_weight="0"
 		android:text="@string/ssl_validator_header"
 		android:padding="5dp"
 		android:textAppearance="?android:attr/textAppearanceMedium"
@@ -36,6 +37,7 @@
 		android:id="@+id/reason_cert_not_trusted"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
+		android:layout_weight="0"
 		android:layout_gravity="left"
 		android:paddingLeft="20dp"
 		android:text="@string/ssl_validator_reason_cert_not_trusted"
@@ -77,8 +79,10 @@
         android:id="@+id/details_scroll"
         android:visibility="gone" 
     	android:padding="20dp"
-        android:layout_width="wrap_content"
-        android:layout_height="180dp">
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        >
         
 		<LinearLayout 
     		android:id="@+id/details_view"
@@ -407,6 +411,7 @@
         android:id="@+id/question"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+		android:layout_weight="0"
 		android:padding="5dp"
         android:text="@string/ssl_validator_question"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -416,6 +421,7 @@
 	<LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+		android:layout_weight="0"
         android:gravity="center" >
 
         <Button

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

@@ -173,7 +173,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     
     private boolean mResumed; // Control if activity is resumed
 
-    private String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT";
+    public static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT";
 
 
     /**

+ 18 - 8
src/com/owncloud/android/authentication/SsoWebViewClient.java

@@ -25,6 +25,11 @@ import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 
 import com.owncloud.android.lib.common.network.NetworkUtils;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.owncloud.android.R;
+import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
+import com.owncloud.android.ui.dialog.SslUntrustedCertDialogABSTRACT;
+import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener;
 import com.owncloud.android.utils.Log_OC;
 
 import android.content.Context;
@@ -34,6 +39,8 @@ import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
 import android.view.KeyEvent;
 import android.view.View;
 import android.webkit.CookieManager;
@@ -150,28 +157,31 @@ public class SsoWebViewClient extends WebViewClient {
         Log_OC.d(TAG, "onReceivedSslError : " + error);
         // Test 1
         X509Certificate x509Certificate = getX509CertificateFromError(error);
-        boolean isKnowServer = false;
+        boolean isKnownServer = false;
         
         if (x509Certificate != null) {
             Log_OC.d(TAG, "------>>>>> x509Certificate " + x509Certificate.toString());
             
             try {
-                isKnowServer = NetworkUtils.isCertInKnownServersStore((Certificate) x509Certificate, mContext);
+                isKnownServer = NetworkUtils.isCertInKnownServersStore((Certificate) x509Certificate, mContext);
             } catch (Exception e) {
                 Log_OC.e(TAG, "Exception: " + e.getMessage());
             }
         }
         
-         if (isKnowServer) {
+         if (isKnownServer) {
              handler.proceed();
-         } else {
+         } else if (x509Certificate != null) {
              // Show a dialog with the certificate info
              ((AuthenticatorActivity)mContext).showUntrustedCertDialog(x509Certificate, error);
-//             SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstance(mContext, x509Certificate, error);
-//             FragmentManager fm = ((FragmentActivity)mContext).getSupportFragmentManager();
-//             FragmentTransaction ft = fm.beginTransaction();
-//             dialog.show(ft, DIALOG_UNTRUSTED_CERT);
              handler.cancel();
+         } else {
+             // Show a dialog with the certificate information available in SslError (not full)
+             SslUntrustedCertDialogABSTRACT dialog = SslUntrustedCertDialogABSTRACT.newInstanceForEmptySslError(error, handler);
+             FragmentManager fm = ((SherlockFragmentActivity)mContext).getSupportFragmentManager();
+             FragmentTransaction ft = fm.beginTransaction();
+             dialog.show(ft, AuthenticatorActivity.DIALOG_UNTRUSTED_CERT);
+             // let's forward the handler, and see what happens...
          }
     }
     

+ 2 - 9
src/com/owncloud/android/ui/dialog/SslUntrustedCertDialog.java

@@ -29,7 +29,6 @@ import java.util.Map;
 import javax.security.auth.x500.X500Principal;
 
 import com.actionbarsherlock.app.SherlockActivity;
-import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.network.CertificateCombinedException;
 import com.owncloud.android.lib.common.network.NetworkUtils;
@@ -55,7 +54,7 @@ import android.widget.TextView;
  * @author David A. Velasco
  *
  */
-public class SslUntrustedCertDialog extends SherlockDialogFragment{
+public class SslUntrustedCertDialog extends SslUntrustedCertDialogABSTRACT {
     
     private final static String TAG = SslUntrustedCertDialog.class.getSimpleName();
     
@@ -121,8 +120,7 @@ public class SslUntrustedCertDialog extends SherlockDialogFragment{
             return null;
         }
     }
-    
-    
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -421,14 +419,9 @@ public class SslUntrustedCertDialog extends SherlockDialogFragment{
         }
     }
 
-    
     public interface OnSslUntrustedCertListener {
         public void onSavedCertificate();
         public void onCancelCertificate();
         public void onFailedSavingCertificate();
     }
-
-
-   
-
 }

+ 64 - 0
src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogABSTRACT.java

@@ -0,0 +1,64 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.dialog;
+
+import android.net.http.SslError;
+import android.webkit.SslErrorHandler;
+
+import com.actionbarsherlock.app.SherlockDialogFragment;
+
+/**
+ * Dialog to show information about an untrusted certificate and allow the user
+ * to decide trust on it or not.
+ * 
+ * Abstract implementation of common functionality for different dialogs that
+ * get the information about the error and the certificate from different classes. 
+ * 
+ * @author masensio
+ * @author David A. Velasco
+ */
+public abstract class SslUntrustedCertDialogABSTRACT extends SherlockDialogFragment {
+    
+    //private final static String TAG = SslUntrustedCertDialogABSTRACT.class.getSimpleName();
+    
+    public static SslUntrustedCertDialogABSTRACT newInstanceForEmptySslError(SslError error, SslErrorHandler handler) {
+        if (error == null) {
+            throw new IllegalArgumentException("Trying to create instance with a parameter error == null");
+        }
+        return SslUntrustedCertDialogForEmptySslError.newInstance(error, handler);
+    }
+    
+    // TODO - complete when merged
+    /*
+    public static SslUntrustedCertDialogABSTRACT newInstanceForFullSslError(X509Certificate cert, SslError error, OnSslUntrustedCertListener listener, SslErrorHandler handler) {
+        if (cert == null) {
+            throw new IllegalArgumentException("Trying to create instance with a parameter error == null");
+        }
+        if (error == null) {
+            throw new IllegalArgumentException("Trying to create instance with a parameter error == null");
+        }
+        return new SslUntrustedCertDialog(cert, listener, handler);
+    }
+    */
+    
+    
+    public interface OnSslUntrustedCertListener {
+        public void onSavedCertificate();
+        public void onFailedSavingCertificate();
+    }
+
+}

+ 250 - 0
src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogForEmptySslError.java

@@ -0,0 +1,250 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.dialog;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AuthenticatorActivity;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.net.http.SslCertificate;
+import android.net.http.SslError;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Dialog to show an Untrusted Certificate
+ * 
+ * @author masensio
+ * @author David A. Velasco
+ */
+public class SslUntrustedCertDialogForEmptySslError extends SslUntrustedCertDialogABSTRACT {
+    
+    //private final static String TAG = SslUntrustedCertDialogForEmptySslError.class.getSimpleName();
+    
+    private SslError mError;
+    private SslErrorHandler mHandler;
+    private View mView;
+
+    
+    /**
+     * Factory method.
+     * 
+     * @param error     Error occurred; details about it will be shown in the dialog.
+     * @param handler   Handler to indicate to the {@link WebView} where the error was found what to do next.
+     * @return          New dialog.
+     */
+    public static SslUntrustedCertDialogForEmptySslError newInstance(SslError error, SslErrorHandler handler) {
+        return new SslUntrustedCertDialogForEmptySslError(error, handler);
+    }
+    
+    
+    /**
+     * Empty constructor.
+     * 
+     * Required by Android framework. Never used, since the state is retained; see {@link #onCreate(Bundle)}  
+     */
+    public SslUntrustedCertDialogForEmptySslError() {}
+    
+
+    /**
+     * Private constructor.
+     * 
+     * Used by the factory method {@link #newInstance(SslError, SslErrorHandler)}.
+     * 
+     * @param error     Error occurred; details about it will be shown in the dialog.
+     * @param handler   Handler to indicate to the {@link WebView} where the error was found what to do next.
+     */
+    private SslUntrustedCertDialogForEmptySslError(SslError error, SslErrorHandler handler) {
+        mError = error;
+        mHandler = handler;
+    }
+
+    
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        /*if (!(activity instanceof OnSslUntrustedCertListener)) {
+            throw new IllegalArgumentException("Trying to attach to an Activity not implementing " + OnSslUntrustedCertListener.class.getCanonicalName());
+        }*/
+    }
+    
+    
+    // TODO try to move to the parent class ?
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setRetainInstance(true);    // force to keep the state of the fragment on configuration changes (such as device rotations)
+        setCancelable(false);
+        mView = null;
+    }
+    
+    // try to move to the parent class ?
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        // Create a view by inflating desired layout
+        if (mView == null) {
+            mView = inflater.inflate(R.layout.ssl_untrusted_cert_layout, container,  false);
+        } else {
+            ((ViewGroup)mView.getParent()).removeView(mView);
+        }
+        
+        Button ok = (Button) mView.findViewById(R.id.ok);
+        ok.setOnClickListener(new OnClickListener() {
+            
+            @Override
+            public void onClick(View v) {
+                //AuthenticatorActivity act = ((AuthenticatorActivity)getSherlockActivity());
+                mHandler.proceed();
+                dismiss();
+            }
+        });
+        
+        Button cancel = (Button) mView.findViewById(R.id.cancel);
+        cancel.setOnClickListener(new OnClickListener() {
+            
+            @Override
+            public void onClick(View v) {
+                AuthenticatorActivity act = ((AuthenticatorActivity)getSherlockActivity());
+                getDialog().cancel();
+                mHandler.cancel();
+                act.cancelWebView();
+            }
+        });
+        
+        Button details = (Button) mView.findViewById(R.id.details_btn);
+        details.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                View detailsScroll = mView.findViewById(R.id.details_scroll);
+                if (detailsScroll.getVisibility() == View.VISIBLE) {
+                    detailsScroll.setVisibility(View.GONE);
+                    ((Button) v).setText(R.string.ssl_validator_btn_details_see);
+
+                } else {
+                    detailsScroll.setVisibility(View.VISIBLE);
+                    ((Button) v).setText(R.string.ssl_validator_btn_details_hide);
+                    showCertificateData();
+                }
+            }
+        });
+        
+        return mView;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Dialog dialog = super.onCreateDialog(savedInstanceState);
+        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        return dialog;
+    }
+
+    @Override
+    public void onDestroyView() {
+        if (getDialog() != null && getRetainInstance())
+            getDialog().setDismissMessage(null);
+        super.onDestroyView();
+    }
+    
+    private void showCertificateData() {
+        TextView nullCerView = (TextView) mView.findViewById(R.id.null_cert);
+        SslCertificate cert = mError.getCertificate();
+        if (cert != null) {
+            nullCerView.setVisibility(View.GONE);
+            showSubject(cert.getIssuedTo());
+            showIssuer(cert.getIssuedBy());
+            showValidity(cert.getValidNotBeforeDate(), cert.getValidNotAfterDate());
+            hideSignature();
+            
+        } else {
+            nullCerView.setVisibility(View.VISIBLE);
+        }
+    }
+    
+    private void showValidity(Date notBefore, Date notAfter) {
+        TextView fromView = ((TextView)mView.findViewById(R.id.value_validity_from));
+        TextView toView = ((TextView)mView.findViewById(R.id.value_validity_to));
+        DateFormat dateFormat = DateFormat.getDateInstance();
+        fromView.setText(dateFormat.format(notBefore));
+        toView.setText(dateFormat.format(notAfter));
+    }
+
+    
+    private void showSubject(SslCertificate.DName subject) {
+        TextView cnView = ((TextView)mView.findViewById(R.id.value_subject_CN));
+        cnView.setText(subject.getCName());
+        cnView.setVisibility(View.VISIBLE);
+        
+        TextView oView = ((TextView)mView.findViewById(R.id.value_subject_O));
+        oView.setText(subject.getOName());
+        oView.setVisibility(View.VISIBLE);
+        
+        TextView ouView = ((TextView)mView.findViewById(R.id.value_subject_OU));
+        ouView.setText(subject.getUName());
+        ouView.setVisibility(View.VISIBLE);
+
+        // SslCertificates don't offer this information
+        ((TextView)mView.findViewById(R.id.value_subject_C)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_subject_ST)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_subject_L)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_subject_C)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_subject_ST)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_subject_L)).setVisibility(View.GONE);
+    }
+    
+    
+    private void showIssuer(SslCertificate.DName issuer) {
+        TextView cnView = ((TextView)mView.findViewById(R.id.value_issuer_CN));
+        cnView.setText(issuer.getCName());
+        cnView.setVisibility(View.VISIBLE);
+        
+        TextView oView = ((TextView)mView.findViewById(R.id.value_issuer_O));
+        oView.setText(issuer.getOName());
+        oView.setVisibility(View.VISIBLE);
+
+        TextView ouView = ((TextView)mView.findViewById(R.id.value_issuer_OU));
+        ouView.setText(issuer.getUName());
+        ouView.setVisibility(View.VISIBLE);
+        
+        // SslCertificates don't offer this information
+        ((TextView)mView.findViewById(R.id.value_issuer_C)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_issuer_ST)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_issuer_L)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_issuer_C)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_issuer_ST)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_issuer_L)).setVisibility(View.GONE);
+    }
+    
+    private void hideSignature() {
+        ((TextView)mView.findViewById(R.id.label_signature)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.label_signature_algorithm)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_signature_algorithm)).setVisibility(View.GONE);
+        ((TextView)mView.findViewById(R.id.value_signature)).setVisibility(View.GONE);
+    }
+
+}