From: David A. Velasco Date: Fri, 7 Mar 2014 12:44:13 +0000 (+0100) Subject: Added new dialog for SSL errors showing information saved in SslCertificate X-Git-Tag: oc-android-1.5.5~15^2~7^2~2 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/6bab28424a71006337d88f4dc3dce6b61483effc?hp=--cc Added new dialog for SSL errors showing information saved in SslCertificate --- 6bab28424a71006337d88f4dc3dce6b61483effc diff --git a/src/com/owncloud/android/authentication/SsoWebViewClient.java b/src/com/owncloud/android/authentication/SsoWebViewClient.java index 587c33e7..27327a96 100644 --- a/src/com/owncloud/android/authentication/SsoWebViewClient.java +++ b/src/com/owncloud/android/authentication/SsoWebViewClient.java @@ -24,9 +24,11 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; import com.owncloud.android.lib.common.network.NetworkUtils; 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; @@ -160,27 +162,34 @@ public class SsoWebViewClient extends WebViewClient implements OnSslUntrustedCer 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 { - // Show a dialog with the certificate info + } else if (x509Certificate != null) { + // Show a dialog with all the certificate info SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstance(mContext, x509Certificate, this, handler); - FragmentManager fm = ((FragmentActivity)mContext).getSupportFragmentManager(); + FragmentManager fm = ((SherlockFragmentActivity)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, DIALOG_UNTRUSTED_CERT); + // let's forward the handler, and see what happens... } } diff --git a/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialog.java b/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialog.java index 85df58a9..5a7d5a85 100644 --- a/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialog.java +++ b/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialog.java @@ -28,12 +28,12 @@ import java.util.Map; import javax.security.auth.x500.X500Principal; -import com.actionbarsherlock.app.SherlockDialogFragment; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.utils.Log_OC; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.os.Bundle; @@ -52,7 +52,7 @@ import android.widget.TextView; * @author masensio * */ -public class SslUntrustedCertDialog extends SherlockDialogFragment{ +public class SslUntrustedCertDialog extends SslUntrustedCertDialogABSTRACT { private final static String TAG = SslUntrustedCertDialog.class.getSimpleName(); @@ -80,8 +80,7 @@ public class SslUntrustedCertDialog extends SherlockDialogFragment{ return null; } } - - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -339,9 +338,8 @@ public class SslUntrustedCertDialog extends SherlockDialogFragment{ } } - public interface OnSslUntrustedCertListener { public void onFailedSavingCertificate(); } - + } diff --git a/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogABSTRACT.java b/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogABSTRACT.java new file mode 100644 index 00000000..26b097cc --- /dev/null +++ b/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 . + * + */ +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(); + } + +} diff --git a/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogForEmptySslError.java b/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogForEmptySslError.java new file mode 100644 index 00000000..7eda6042 --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/SslUntrustedCertDialogForEmptySslError.java @@ -0,0 +1,235 @@ +/* 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 . + * + */ +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.untrusted_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.untrusted_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.untrusted_details_btn); + details.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + View detailsScroll = mView.findViewById(R.id.untrusted_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.untrusted_null_cert); + SslCertificate cert = mError.getCertificate(); + if (cert != null) { + nullCerView.setVisibility(View.GONE); + showSubject(cert.getIssuedTo()); + showIssuer(cert.getIssuedBy()); + showValidity(cert.getValidNotBeforeDate(), cert.getValidNotAfterDate()); + // TODO showSignatureNotAvailabe/Provided + + } else { + nullCerView.setVisibility(View.VISIBLE); + } + } + + private void showValidity(Date notBefore, Date notAfter) { + TextView fromView = ((TextView)mView.findViewById(R.id.untrusted_value_validity_from)); + TextView toView = ((TextView)mView.findViewById(R.id.untrusted_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.untrusted_value_subject_CN)); + cnView.setText(subject.getCName()); + cnView.setVisibility(View.VISIBLE); + + TextView oView = ((TextView)mView.findViewById(R.id.untrusted_value_subject_O)); + oView.setText(subject.getOName()); + oView.setVisibility(View.VISIBLE); + + TextView ouView = ((TextView)mView.findViewById(R.id.untrusted_value_subject_OU)); + ouView.setText(subject.getUName()); + ouView.setVisibility(View.VISIBLE); + + ((TextView)mView.findViewById(R.id.untrusted_value_subject_C)).setVisibility(View.GONE); + ((TextView)mView.findViewById(R.id.untrusted_value_subject_ST)).setVisibility(View.GONE); + ((TextView)mView.findViewById(R.id.untrusted_value_subject_L)).setVisibility(View.GONE); + } + + + private void showIssuer(SslCertificate.DName issuer) { + TextView cnView = ((TextView)mView.findViewById(R.id.untrusted_value_issuer_CN)); + cnView.setText(issuer.getCName()); + cnView.setVisibility(View.VISIBLE); + + TextView oView = ((TextView)mView.findViewById(R.id.untrusted_value_issuer_O)); + oView.setText(issuer.getOName()); + oView.setVisibility(View.VISIBLE); + + TextView ouView = ((TextView)mView.findViewById(R.id.untrusted_value_issuer_OU)); + ouView.setText(issuer.getUName()); + ouView.setVisibility(View.VISIBLE); + + ((TextView)mView.findViewById(R.id.untrusted_value_issuer_C)).setVisibility(View.GONE); + ((TextView)mView.findViewById(R.id.untrusted_value_issuer_ST)).setVisibility(View.GONE); + ((TextView)mView.findViewById(R.id.untrusted_value_issuer_L)).setVisibility(View.GONE); + } + +}