From 25afe7bc86a92a0d5664efa4c254dbf11cb2964e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20Franz=C3=A9n?= Date: Thu, 14 Jan 2016 13:32:00 +0100 Subject: Handle not installed PGP applet --- .../ui/base/BaseSecurityTokenNfcActivity.java | 72 +++++++++++++++++++++- .../keychain/ui/dialog/FidesmoInstallDialog.java | 59 ++++++++++++++++++ .../ui/dialog/FidesmoPgpInstallDialog.java | 63 +++++++++++++++++++ OpenKeychain/src/main/res/values/strings.xml | 9 +++ 4 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoInstallDialog.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoPgpInstallDialog.java (limited to 'OpenKeychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java index 1a04bcf43..52b439a0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenNfcActivity.java @@ -29,6 +29,7 @@ import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.TagLostException; @@ -36,6 +37,7 @@ import android.nfc.tech.IsoDep; import android.os.AsyncTask; import android.os.Bundle; +import nordpol.Apdu; import nordpol.android.TagDispatcher; import nordpol.android.AndroidCard; import nordpol.android.OnDiscoveredTagListener; @@ -59,6 +61,8 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.CreateKeyActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity; +import org.sufficientlysecure.keychain.ui.dialog.FidesmoInstallDialog; +import org.sufficientlysecure.keychain.ui.dialog.FidesmoPgpInstallDialog; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; @@ -71,6 +75,10 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen public static final String EXTRA_TAG_HANDLING_ENABLED = "tag_handling_enabled"; + // Fidesmo constants + private static final String FIDESMO_APPS_AID_PREFIX = "A000000617"; + private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android"; + protected Passphrase mPin; protected Passphrase mAdminPin; protected boolean mPw1ValidForMultipleSignatures; @@ -309,6 +317,20 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen onNfcError(getString(R.string.security_token_error_unknown)); break; } + // 6A82 app not installed on security token! + case 0x6A82: { + if (isFidesmoDevice()) { + // Check if the Fidesmo app is installed + if (isAndroidAppInstalled(FIDESMO_APP_PACKAGE)) { + promptFidesmoPgpInstall(); + } else { + promptFidesmoAppInstall(); + } + } else { // Other (possibly) compatible hardware + onNfcError(getString(R.string.security_token_error_pgp_app_not_installed)); + } + break; + } default: { onNfcError(getString(R.string.security_token_error, e.getMessage())); break; @@ -372,7 +394,6 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen mPin = input.getPassphrase(); break; } - default: super.onActivityResult(requestCode, resultCode, data); } @@ -984,4 +1005,53 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen } + private boolean isFidesmoDevice() { + if (isNfcConnected()) { // Check if we can still talk to the card + try { + // By trying to select any apps that have the Fidesmo AID prefix we can + // see if it is a Fidesmo device or not + byte[] mSelectResponse = mIsoCard.transceive(Apdu.select(FIDESMO_APPS_AID_PREFIX)); + // Compare the status returned by our select with the OK status code + return Apdu.hasStatus(mSelectResponse, Apdu.OK_APDU); + } catch (IOException e) { + Log.e(Constants.TAG, "Card communication failed!", e); + } + } + return false; + } + + /** + * Ask user if she wants to install PGP onto her Fidesmo device + */ + private void promptFidesmoPgpInstall() { + FidesmoPgpInstallDialog mFidesmoPgpInstallDialog = new FidesmoPgpInstallDialog(); + mFidesmoPgpInstallDialog.show(getSupportFragmentManager(), "mFidesmoPgpInstallDialog"); + } + + /** + * Show a Dialog to the user informing that Fidesmo App must be installed and with option + * to launch the Google Play store. + */ + private void promptFidesmoAppInstall() { + FidesmoInstallDialog mFidesmoInstallDialog = new FidesmoInstallDialog(); + mFidesmoInstallDialog.show(getSupportFragmentManager(), "mFidesmoInstallDialog"); + } + + /** + * Use the package manager to detect if an application is installed on the phone + * @param uri an URI identifying the application's package + * @return 'true' if the app is installed + */ + private boolean isAndroidAppInstalled(String uri) { + PackageManager mPackageManager = getPackageManager(); + boolean mAppInstalled = false; + try { + mPackageManager.getPackageInfo(uri, PackageManager.GET_ACTIVITIES); + mAppInstalled = true; + } catch (PackageManager.NameNotFoundException e) { + Log.e(Constants.TAG, "App not installed on Android device"); + mAppInstalled = false; + } + return mAppInstalled; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoInstallDialog.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoInstallDialog.java new file mode 100644 index 000000000..76934c5d4 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoInstallDialog.java @@ -0,0 +1,59 @@ +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; + +import org.sufficientlysecure.keychain.R; + +public class FidesmoInstallDialog extends DialogFragment { + + // URLs for Google Play app and to install apps via browser + private final static String PLAY_STORE_URI = "market://details?id="; + private final static String PLAY_STORE_VIA_BROWSER_URI = "http://play.google.com/store/apps/details?id="; + + // Fidesmo constants + private static final String FIDESMO_APP_PACKAGE = "com.fidesmo.sec.android"; + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + CustomAlertDialogBuilder mCustomAlertDialogBuilder = new CustomAlertDialogBuilder(getActivity()); + mCustomAlertDialogBuilder.setTitle(getString(R.string.prompt_fidesmo_app_install_title)); + mCustomAlertDialogBuilder.setMessage(getString(R.string.prompt_fidesmo_app_install_message)); + mCustomAlertDialogBuilder.setPositiveButton( + getString(R.string.prompt_fidesmo_app_install_button_positive), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismiss(); + startPlayStoreFidesmoAppActivity(); + } + }); + mCustomAlertDialogBuilder.setNegativeButton( + getString(R.string.prompt_fidesmo_app_install_button_negative), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismiss(); + } + }); + + return mCustomAlertDialogBuilder.show(); + } + + private void startPlayStoreFidesmoAppActivity() { + try { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(PLAY_STORE_URI + + FIDESMO_APP_PACKAGE))); + } catch (android.content.ActivityNotFoundException exception) { + // if the Google Play app is not installed, call the browser + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(PLAY_STORE_VIA_BROWSER_URI + + FIDESMO_APP_PACKAGE))); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoPgpInstallDialog.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoPgpInstallDialog.java new file mode 100644 index 000000000..cdf6e5c7c --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FidesmoPgpInstallDialog.java @@ -0,0 +1,63 @@ +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +public class FidesmoPgpInstallDialog extends DialogFragment { + + // Fidesmo constants + private static final String FIDESMO_SERVICE_DELIVERY_CARD_ACTION = "com.fidesmo.sec.DELIVER_SERVICE"; + private static final String FIDESMO_SERVICE_URI = "https://api.fidesmo.com/service/"; + private static final String FIDESMO_PGP_APPLICATION_ID = "0cdc651e"; + private static final String FIDESMO_PGP_SERVICE_ID = "OKC-install"; + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + CustomAlertDialogBuilder mCustomAlertDialogBuilder = new CustomAlertDialogBuilder(getActivity()); + mCustomAlertDialogBuilder.setTitle(getString(R.string.prompt_fidesmo_pgp_install_title)); + mCustomAlertDialogBuilder.setMessage(getString(R.string.prompt_fidesmo_pgp_install_message)); + mCustomAlertDialogBuilder.setPositiveButton( + getString(R.string.prompt_fidesmo_pgp_install_button_positive), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismiss(); + startFidesmoPgpAppletActivity(); + } + }); + mCustomAlertDialogBuilder.setNegativeButton( + getString(R.string.prompt_fidesmo_pgp_install_button_negative), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismiss(); + } + }); + + return mCustomAlertDialogBuilder.show(); + } + + private void startFidesmoPgpAppletActivity() { + try { + // Call the Fidesmo app with the PGP applet as parameter to + // send the user straight to it + final String mPgpInstallServiceUrl = FIDESMO_SERVICE_URI + FIDESMO_PGP_APPLICATION_ID + + "/" + FIDESMO_PGP_SERVICE_ID; + Intent mPgpServiceIntent = new Intent(FIDESMO_SERVICE_DELIVERY_CARD_ACTION, + Uri.parse(mPgpInstallServiceUrl)); + startActivity(mPgpServiceIntent); + } catch (IllegalArgumentException e) { + Log.e(Constants.TAG, "Error when parsing URI"); + } + } +} diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 7525c199d..d15f66bd0 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1720,5 +1720,14 @@ "At least one item must be selected!" "Can\'t select more than three items!" "Remember" + "No PGP app was found on the security token" + "Install PGP?" + "There was no PGP app available on your Fidesmo device." + "Install" + "Cancel" + "Install Fidesmo?" + "To install PGP you need the Fidesmo Android app." + "Install" + "Cancel" -- cgit v1.2.3