aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java270
1 files changed, 136 insertions, 134 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index c6431bfaf..e71349880 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -17,16 +17,18 @@
package org.sufficientlysecure.keychain.ui;
+
import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import android.text.InputType;
import android.text.method.PasswordTransformationMethod;
import android.view.ContextThemeWrapper;
@@ -43,20 +45,21 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
-import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.remote.CryptoInputParcelCacheService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
+import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -64,6 +67,8 @@ import org.sufficientlysecure.keychain.util.Preferences;
/**
* We can not directly create a dialog on the application context.
* This activity encapsulates a DialogFragment to emulate a dialog.
+ * NOTE: If no CryptoInputParcel is passed via EXTRA_CRYPTO_INPUT, the CryptoInputParcel is created
+ * internally and is NOT meant to be used by signing operations before adding a signature time
*/
public class PassphraseDialogActivity extends FragmentActivity {
@@ -71,11 +76,13 @@ public class PassphraseDialogActivity extends FragmentActivity {
public static final String EXTRA_REQUIRED_INPUT = "required_input";
public static final String EXTRA_SUBKEY_ID = "secret_key_id";
+ public static final String EXTRA_CRYPTO_INPUT = "crypto_input";
// special extra for OpenPgpService
public static final String EXTRA_SERVICE_INTENT = "data";
+ private long mSubKeyId;
- private static final int REQUEST_CODE_ENTER_PATTERN = 2;
+ private CryptoInputParcel mCryptoInputParcel;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -90,20 +97,52 @@ public class PassphraseDialogActivity extends FragmentActivity {
);
}
+ mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
+
+ if (mCryptoInputParcel == null) {
+ // not all usages of PassphraseActivity are from CryptoInputOperation
+ // NOTE: This CryptoInputParcel cannot be used for signing operations without setting
+ // signature time
+ mCryptoInputParcel = new CryptoInputParcel();
+ }
+
// this activity itself has no content view (see manifest)
- long keyId;
if (getIntent().hasExtra(EXTRA_SUBKEY_ID)) {
- keyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0);
+ mSubKeyId = getIntent().getLongExtra(EXTRA_SUBKEY_ID, 0);
} else {
RequiredInputParcel requiredInput = getIntent().getParcelableExtra(EXTRA_REQUIRED_INPUT);
switch (requiredInput.mType) {
case PASSPHRASE_SYMMETRIC: {
- keyId = Constants.key.symmetric;
+ mSubKeyId = Constants.key.symmetric;
break;
}
case PASSPHRASE: {
- keyId = requiredInput.getSubKeyId();
+
+ // handle empty passphrases by directly returning an empty crypto input parcel
+ try {
+ CanonicalizedSecretKeyRing pubRing =
+ new ProviderHelper(this).getCanonicalizedSecretKeyRing(
+ requiredInput.getMasterKeyId());
+ // use empty passphrase for empty passphrase
+ if (pubRing.getSecretKey(requiredInput.getSubKeyId()).getSecretKeyType() ==
+ SecretKeyType.PASSPHRASE_EMPTY) {
+ // also return passphrase back to activity
+ Intent returnIntent = new Intent();
+ mCryptoInputParcel.mPassphrase = new Passphrase("");
+ returnIntent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
+ setResult(RESULT_OK, returnIntent);
+ finish();
+ return;
+ }
+ } catch (NotFoundException e) {
+ Log.e(Constants.TAG, "Key not found?!", e);
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+ }
+
+ mSubKeyId = requiredInput.getSubKeyId();
break;
}
default: {
@@ -112,64 +151,35 @@ public class PassphraseDialogActivity extends FragmentActivity {
}
}
- Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_SERVICE_INTENT);
-
- show(this, keyId, serviceIntent);
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_ENTER_PATTERN: {
- /*
- * NOTE that there are 4 possible result codes!!!
- */
- switch (resultCode) {
- case RESULT_OK:
- // The user passed
- break;
- case RESULT_CANCELED:
- // The user cancelled the task
- break;
-// case LockPatternActivity.RESULT_FAILED:
-// // The user failed to enter the pattern
-// break;
-// case LockPatternActivity.RESULT_FORGOT_PATTERN:
-// // The user forgot the pattern and invoked your recovery Activity.
-// break;
- }
+ protected void onResumeFragments() {
+ super.onResumeFragments();
- /*
- * In any case, there's always a key EXTRA_RETRY_COUNT, which holds
- * the number of tries that the user did.
- */
-// int retryCount = data.getIntExtra(
-// LockPatternActivity.EXTRA_RETRY_COUNT, 0);
+ /* Show passphrase dialog to cache a new passphrase the user enters for using it later for
+ * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
+ * for a symmetric passphrase
+ */
- break;
- }
- }
+ Intent serviceIntent = getIntent().getParcelableExtra(EXTRA_SERVICE_INTENT);
+
+ PassphraseDialogFragment frag = new PassphraseDialogFragment();
+ Bundle args = new Bundle();
+ args.putLong(EXTRA_SUBKEY_ID, mSubKeyId);
+ args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent);
+ frag.setArguments(args);
+ frag.show(getSupportFragmentManager(), "passphraseDialog");
}
- /**
- * Shows passphrase dialog to cache a new passphrase the user enters for using it later for
- * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks
- * for a symmetric passphrase
- */
- public static void show(final FragmentActivity context, final long keyId, final Intent serviceIntent) {
- DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
- public void run() {
- // do NOT check if the key even needs a passphrase. that's not our job here.
- PassphraseDialogFragment frag = new PassphraseDialogFragment();
- Bundle args = new Bundle();
- args.putLong(EXTRA_SUBKEY_ID, keyId);
- args.putParcelable(EXTRA_SERVICE_INTENT, serviceIntent);
-
- frag.setArguments(args);
-
- frag.show(context.getSupportFragmentManager(), "passphraseDialog");
- }
- });
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ DialogFragment dialog = (DialogFragment) getSupportFragmentManager().findFragmentByTag("passphraseDialog");
+ if (dialog != null) {
+ dialog.dismiss();
+ }
}
public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
@@ -183,17 +193,12 @@ public class PassphraseDialogActivity extends FragmentActivity {
private Intent mServiceIntent;
- /**
- * Creates dialog
- */
+ @NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity();
- // if the dialog is displayed from the application class, design is missing
- // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
- ContextThemeWrapper theme = new ContextThemeWrapper(activity,
- R.style.Theme_AppCompat_Light_Dialog);
+ ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(activity);
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
mServiceIntent = getArguments().getParcelable(EXTRA_SERVICE_INTENT);
@@ -246,12 +251,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
userId = null;
}
- /* Get key type for message */
- // find a master key id for our key
- long masterKeyId = new ProviderHelper(activity).getMasterKeyId(mSubKeyId);
- CachedPublicKeyRing keyRing = new ProviderHelper(activity).getCachedPublicKeyRing(masterKeyId);
- // get the type of key (from the database)
- keyType = keyRing.getSecretKeyType(mSubKeyId);
+ keyType = mSecretRing.getSecretKey(mSubKeyId).getSecretKeyType();
switch (keyType) {
case PASSPHRASE:
message = getString(R.string.passphrase_for, userId);
@@ -284,51 +284,42 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseText.setText(message);
- if (keyType == CanonicalizedSecretKey.SecretKeyType.PATTERN) {
- // start pattern dialog and show progress circle here...
-// Intent patternActivity = new Intent(getActivity(), LockPatternActivity.class);
-// patternActivity.putExtra(LockPatternActivity.EXTRA_PATTERN, "123");
-// startActivityForResult(patternActivity, REQUEST_CODE_ENTER_PATTERN);
- mInput.setVisibility(View.INVISIBLE);
- mProgress.setVisibility(View.VISIBLE);
- } else {
- // Hack to open keyboard.
- // This is the only method that I found to work across all Android versions
- // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
- // Notes: * onCreateView can't be used because we want to add buttons to the dialog
- // * opening in onActivityCreated does not work on Android 4.4
- mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPassphraseEditText.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || mPassphraseEditText == null) {
- return;
- }
- InputMethodManager imm = (InputMethodManager) getActivity()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
+ // Hack to open keyboard.
+ // This is the only method that I found to work across all Android versions
+ // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
+ // Notes: * onCreateView can't be used because we want to add buttons to the dialog
+ // * opening in onActivityCreated does not work on Android 4.4
+ mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mPassphraseEditText.post(new Runnable() {
+ @Override
+ public void run() {
+ if (getActivity() == null || mPassphraseEditText == null) {
+ return;
}
- });
- }
- });
- mPassphraseEditText.requestFocus();
-
- mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
- mPassphraseEditText.setOnEditorActionListener(this);
-
- if (keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin()) {
- mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- } else if (keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
- mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- } else {
- mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
}
+ });
+ mPassphraseEditText.requestFocus();
+
+ mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
+ mPassphraseEditText.setOnEditorActionListener(this);
+ if ((keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin())
+ || keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
+ mPassphraseEditText.setInputType(InputType.TYPE_CLASS_NUMBER);
mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
+ } else {
+ mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
+ mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
+
AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null);
@@ -347,11 +338,16 @@ public class PassphraseDialogActivity extends FragmentActivity {
public void onClick(View v) {
final Passphrase passphrase = new Passphrase(mPassphraseEditText);
+ CryptoInputParcel cryptoInputParcel =
+ ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel;
+
// Early breakout if we are dealing with a symmetric key
if (mSecretRing == null) {
- PassphraseCacheService.addCachedPassphrase(getActivity(),
- Constants.key.symmetric, Constants.key.symmetric, passphrase,
- getString(R.string.passp_cache_notif_pwd));
+ if (cryptoInputParcel.mCachePassphrase) {
+ PassphraseCacheService.addCachedPassphrase(getActivity(),
+ Constants.key.symmetric, Constants.key.symmetric, passphrase,
+ getString(R.string.passp_cache_notif_pwd));
+ }
finishCaching(passphrase);
return;
@@ -404,15 +400,24 @@ public class PassphraseDialogActivity extends FragmentActivity {
return;
}
- // cache the new passphrase
- Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
+ // cache the new passphrase as specified in CryptoInputParcel
+ Log.d(Constants.TAG, "Everything okay!");
- try {
- PassphraseCacheService.addCachedPassphrase(getActivity(),
- mSecretRing.getMasterKeyId(), mSubKeyId, passphrase,
- mSecretRing.getPrimaryUserIdWithFallback());
- } catch (PgpKeyNotFoundException e) {
- Log.e(Constants.TAG, "adding of a passphrase failed", e);
+ CryptoInputParcel cryptoInputParcel
+ = ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel;
+
+ if (cryptoInputParcel.mCachePassphrase) {
+ Log.d(Constants.TAG, "Caching entered passphrase");
+
+ try {
+ PassphraseCacheService.addCachedPassphrase(getActivity(),
+ mSecretRing.getMasterKeyId(), mSubKeyId, passphrase,
+ mSecretRing.getPrimaryUserIdWithFallback());
+ } catch (PgpKeyNotFoundException e) {
+ Log.e(Constants.TAG, "adding of a passphrase failed", e);
+ }
+ } else {
+ Log.d(Constants.TAG, "Not caching entered passphrase!");
}
finishCaching(passphrase);
@@ -428,9 +433,12 @@ public class PassphraseDialogActivity extends FragmentActivity {
return;
}
- CryptoInputParcel inputParcel = new CryptoInputParcel(null, passphrase);
+ CryptoInputParcel inputParcel =
+ ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel;
+ inputParcel.mPassphrase = passphrase;
if (mServiceIntent != null) {
- CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent, inputParcel);
+ CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent,
+ inputParcel);
getActivity().setResult(RESULT_OK, mServiceIntent);
} else {
// also return passphrase back to activity
@@ -449,20 +457,16 @@ public class PassphraseDialogActivity extends FragmentActivity {
// note we need no synchronization here, this variable is only accessed in the ui thread
mIsCancelled = true;
+
+ getActivity().setResult(RESULT_CANCELED);
+ getActivity().finish();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
- if (getActivity() == null) {
- return;
- }
-
hideKeyboard();
-
- getActivity().setResult(RESULT_CANCELED);
- getActivity().finish();
}
private void hideKeyboard() {
@@ -476,11 +480,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
- /**
- * Associate the "done" button on the soft keyboard with the okay button in the view
- */
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Associate the "done" button on the soft keyboard with the okay button in the view
if (EditorInfo.IME_ACTION_DONE == actionId) {
AlertDialog dialog = ((AlertDialog) getDialog());
Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);