X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/a5fc7533aa7bcbe033c543aa6d8f0b9b06cacbae..eda6ddd98f723053e8c65c7cac4065ddde1e401e:/src/com/owncloud/android/authentication/AuthenticatorActivity.java diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index e604a954..73bbaecb 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -18,6 +18,8 @@ package com.owncloud.android.authentication; +import java.security.cert.X509Certificate; + import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlertDialog; @@ -29,10 +31,13 @@ import android.content.SharedPreferences; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.net.http.SslError; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@ -43,6 +48,7 @@ import android.view.View.OnFocusChangeListener; import android.view.View.OnTouchListener; import android.view.Window; import android.view.inputmethod.EditorInfo; +import android.webkit.SslErrorHandler; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; @@ -59,6 +65,7 @@ import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.operations.OAuth2GetAccessToken; +import com.owncloud.android.lib.common.network.CertificateCombinedException; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -68,8 +75,8 @@ import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; import com.owncloud.android.ui.dialog.SamlWebViewDialog; -import com.owncloud.android.ui.dialog.SslValidatorDialog; -import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener; +import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; +import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; import com.owncloud.android.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; @@ -80,7 +87,8 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion; * @author David A. Velasco */ public class AuthenticatorActivity extends AccountAuthenticatorActivity -implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeListener, OnEditorActionListener, SsoWebViewClientListener{ + implements OnRemoteOperationListener, OnFocusChangeListener, OnEditorActionListener, + SsoWebViewClientListener, OnSslUntrustedCertListener { private static final String TAG = AuthenticatorActivity.class.getSimpleName(); @@ -113,9 +121,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private static final String AUTH_OPTIONAL = "optional"; private static final int DIALOG_LOGIN_PROGRESS = 0; - private static final int DIALOG_SSL_VALIDATOR = 1; - private static final int DIALOG_CERT_NOT_SAVED = 2; - private static final int DIALOG_OAUTH2_LOGIN_PROGRESS = 3; + private static final int DIALOG_CERT_NOT_SAVED = 1; + private static final int DIALOG_OAUTH2_LOGIN_PROGRESS = 2; public static final byte ACTION_CREATE = 0; public static final byte ACTION_UPDATE_TOKEN = 1; @@ -135,7 +142,6 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private Thread mOperationThread; private GetRemoteStatusOperation mOcServerChkOperation; private ExistenceCheckRemoteOperation mAuthCheckOperation; - private RemoteOperationResult mLastSslUntrustedServerResult; private Uri mNewCapturedUriFromOAuth2Redirection; @@ -168,6 +174,10 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private boolean mResumed; // Control if activity is resumed + public static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; + + private boolean mTryEmptyAuthorization = false; + /** * {@inheritDoc} @@ -885,6 +895,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList /// update status icon and text if (mServerIsValid) { hideRefreshButton(); + // Try to create an account with user and pass "", to know if it is a regular server + tryEmptyAuthorization(); } else { showRefreshButton(); } @@ -893,22 +905,47 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList /// very special case (TODO: move to a common place for all the remote operations) if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) { - mLastSslUntrustedServerResult = result; - showDialog(DIALOG_SSL_VALIDATOR); + showUntrustedCertDialog(result); } /// retrieve discovered version and normalize server URL mDiscoveredVersion = operation.getDiscoveredVersion(); mHostBaseUrl = normalizeUrl(mHostUrlInput.getText().toString()); - /// allow or not the user try to access the server - mOkButton.setEnabled(mServerIsValid); +// /// allow or not the user try to access the server +// mOkButton.setEnabled(mServerIsValid); } // else nothing ; only the last check operation is considered; // multiple can be triggered if the user amends a URL before a previous check can be triggered } + /** + * Try to access with user/pass ""/"", to know if it is a regular server + */ + private void tryEmptyAuthorization() { + mTryEmptyAuthorization = true; + + Log_OC.d(TAG, "Trying empty authorization to detect authentication method"); + + /// be gentle with the user + showDialog(DIALOG_LOGIN_PROGRESS); + + /// get the path to the root folder through WebDAV from the version server + String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, mAuthTokenType); + + /// get basic credentials entered by user + String username = ""; + String password = ""; + + /// test credentials + mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false); + OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true); + client.setBasicCredentials(username, password); + mOperationThread = mAuthCheckOperation.execute(client, this, mHandler); + } + + private String normalizeUrl(String url) { if (url != null && url.length() > 0) { url = url.trim(); @@ -1159,21 +1196,29 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } catch (IllegalArgumentException e) { // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens } - + if (result.isSuccess()) { - Log_OC.d(TAG, "Successful access - time to save the account"); + + if (mTryEmptyAuthorization) { + //allow or not the user try to access the server + mOkButton.setEnabled(mServerIsValid); + mTryEmptyAuthorization = false; + + } else { + Log_OC.d(TAG, "Successful access - time to save the account"); - boolean success = false; - if (mAction == ACTION_CREATE) { - success = createAccount(); + boolean success = false; + if (mAction == ACTION_CREATE) { + success = createAccount(); - } else { - updateToken(); - success = true; - } + } else { + updateToken(); + success = true; + } - if (success) { - finish(); + if (success) { + finish(); + } } } else if (result.isServerFail() || result.isException()) { @@ -1198,8 +1243,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList // very special case (TODO: move to a common place for all the remote operations) (dangerous here?) if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) { - mLastSslUntrustedServerResult = result; - showDialog(DIALOG_SSL_VALIDATOR); + showUntrustedCertDialog(result); } } else { // authorization fail due to client side - probably wrong credentials @@ -1331,10 +1375,6 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList case DIALOG_CERT_NOT_SAVED: case DIALOG_OAUTH2_LOGIN_PROGRESS: break; - case DIALOG_SSL_VALIDATOR: { - ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult); - break; - } default: Log_OC.e(TAG, "Incorrect dialog called with id = " + id); } @@ -1385,11 +1425,6 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList dialog = working_dialog; break; } - case DIALOG_SSL_VALIDATOR: { - /// TODO start to use new dialog interface, at least for this (it is a FragmentDialog already) - dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this); - break; - } case DIALOG_CERT_NOT_SAVED: { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved)); @@ -1540,23 +1575,6 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } /** - * Called from SslValidatorDialog when a new server certificate was correctly saved. - */ - public void onSavedCertificate() { - checkOcServer(); - } - - /** - * Called from SslValidatorDialog when a new server certificate could not be saved - * when the user requested it. - */ - @Override - public void onFailedSavingCertificate() { - showDialog(DIALOG_CERT_NOT_SAVED); - } - - - /** * Called when the 'action' button in an IME is pressed ('enter' in software keyboard). * * Used to trigger the authentication check when the user presses 'enter' after writing the password, @@ -1670,5 +1688,86 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } return super.onTouchEvent(event); } + + + /** + * Show untrusted cert dialog + */ + public void showUntrustedCertDialog(X509Certificate x509Certificate, SslError error, SslErrorHandler handler) { + // Show a dialog with the certificate info + SslUntrustedCertDialog dialog = null; + if (x509Certificate == null) { + dialog = SslUntrustedCertDialog.newInstanceForEmptySslError(error, handler); + } else { + dialog = SslUntrustedCertDialog.newInstanceForFullSslError(x509Certificate, error, handler); + } + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + ft.addToBackStack(null); + dialog.show(ft, DIALOG_UNTRUSTED_CERT); + } + + /** + * Show untrusted cert dialog + */ + public void showUntrustedCertDialog(RemoteOperationResult result) { + // Show a dialog with the certificate info + SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException)result.getException()); + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + ft.addToBackStack(null); + dialog.show(ft, DIALOG_UNTRUSTED_CERT); + + } + + /** + * Dismiss untrusted cert dialog + */ + public void dismissUntrustedCertDialog(){ + /*Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_UNTRUSTED_CERT); + if (frag != null) { + SslErrorViewAdapter dialog = (SslErrorViewAdapter) frag; + dialog.dismiss(); + } + */ + } + + /** + * Called from SslValidatorDialog when a new server certificate was correctly saved. + */ + public void onSavedCertificate() { + Fragment fd = getSupportFragmentManager().findFragmentByTag(TAG_SAML_DIALOG); + if (fd == null) { + // if SAML dialog is not shown, the SslDialog was shown due to an SSL error in the server check + checkOcServer(); + } + } + + /** + * Called from SslValidatorDialog when a new server certificate could not be saved + * when the user requested it. + */ + @Override + public void onFailedSavingCertificate() { + showDialog(DIALOG_CERT_NOT_SAVED); + cancelWebView(); + } + + @Override + public void onCancelCertificate() { + cancelWebView(); + } + + public void cancelWebView() { + Fragment fd = getSupportFragmentManager().findFragmentByTag(TAG_SAML_DIALOG); + if (fd != null && fd instanceof SherlockDialogFragment) { + Dialog d = ((SherlockDialogFragment)fd).getDialog(); + if (d != null && d.isShowing()) { + d.dismiss(); + } + } + + } + }