Merge pull request #1686 from fidesmo/feature-handle-not-installed-nfc-applet
Handle not installed PGP applet
This commit is contained in:
@@ -29,6 +29,7 @@ import android.app.Activity;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
import android.nfc.Tag;
|
import android.nfc.Tag;
|
||||||
import android.nfc.TagLostException;
|
import android.nfc.TagLostException;
|
||||||
@@ -36,6 +37,7 @@ import android.nfc.tech.IsoDep;
|
|||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import nordpol.Apdu;
|
||||||
import nordpol.android.TagDispatcher;
|
import nordpol.android.TagDispatcher;
|
||||||
import nordpol.android.AndroidCard;
|
import nordpol.android.AndroidCard;
|
||||||
import nordpol.android.OnDiscoveredTagListener;
|
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.CreateKeyActivity;
|
||||||
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
|
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
|
||||||
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
|
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.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
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";
|
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 mPin;
|
||||||
protected Passphrase mAdminPin;
|
protected Passphrase mAdminPin;
|
||||||
protected boolean mPw1ValidForMultipleSignatures;
|
protected boolean mPw1ValidForMultipleSignatures;
|
||||||
@@ -309,6 +317,20 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
|
|||||||
onNfcError(getString(R.string.security_token_error_unknown));
|
onNfcError(getString(R.string.security_token_error_unknown));
|
||||||
break;
|
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: {
|
default: {
|
||||||
onNfcError(getString(R.string.security_token_error, e.getMessage()));
|
onNfcError(getString(R.string.security_token_error, e.getMessage()));
|
||||||
break;
|
break;
|
||||||
@@ -372,7 +394,6 @@ public abstract class BaseSecurityTokenNfcActivity extends BaseActivity implemen
|
|||||||
mPin = input.getPassphrase();
|
mPin = input.getPassphrase();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1720,5 +1720,14 @@
|
|||||||
<string name="settings_cache_ttl_at_least_one">"At least one item must be selected!"</string>
|
<string name="settings_cache_ttl_at_least_one">"At least one item must be selected!"</string>
|
||||||
<string name="settings_cache_ttl_max_three">"Can\'t select more than three items!"</string>
|
<string name="settings_cache_ttl_max_three">"Can\'t select more than three items!"</string>
|
||||||
<string name="remember">"Remember"</string>
|
<string name="remember">"Remember"</string>
|
||||||
|
<string name="security_token_error_pgp_app_not_installed">"No PGP app was found on the security token"</string>
|
||||||
|
<string name="prompt_fidesmo_pgp_install_title">"Install PGP?"</string>
|
||||||
|
<string name="prompt_fidesmo_pgp_install_message">"There was no PGP app available on your Fidesmo device."</string>
|
||||||
|
<string name="prompt_fidesmo_pgp_install_button_positive">"Install"</string>
|
||||||
|
<string name="prompt_fidesmo_pgp_install_button_negative">"Cancel"</string>
|
||||||
|
<string name="prompt_fidesmo_app_install_title">"Install Fidesmo?"</string>
|
||||||
|
<string name="prompt_fidesmo_app_install_message">"To install PGP you need the Fidesmo Android app."</string>
|
||||||
|
<string name="prompt_fidesmo_app_install_button_positive">"Install"</string>
|
||||||
|
<string name="prompt_fidesmo_app_install_button_negative">"Cancel"</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user