diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java index 8a0600159..88334e9af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java @@ -209,7 +209,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation skippedDisallowedKeys = new HashSet<>(); + HashSet skippedDisallowedEncryptionKeys = new HashSet<>(); boolean insecureEncryptionKey = false; // convenience method to return with error @@ -608,7 +608,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation 0) { - long masterKeyId = skippedDisallowedKeys[0]; - + long[] skippedDisallowedEncryptionKeys = pgpResult.getSkippedDisallowedKeys(); + if (pgpResult.isKeysDisallowed() && + skippedDisallowedEncryptionKeys != null && skippedDisallowedEncryptionKeys.length > 0) { // allow user to select allowed keys Intent result = new Intent(); String packageName = mApiPermissionHelper.getCurrentCallingPackage(); result.putExtra(OpenPgpApi.RESULT_INTENT, mApiPendingIntentFactory.createRequestKeyPermissionPendingIntent( - data, packageName, masterKeyId)); + data, packageName, skippedDisallowedEncryptionKeys)); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionActivity.java index 6b4782d97..0296e9b48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionActivity.java @@ -37,7 +37,6 @@ import android.widget.ImageView; import android.widget.TextView; import org.openintents.openpgp.util.OpenPgpUtils.UserId; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.remote.ui.RequestKeyPermissionPresenter.RequestKeyPermissionMvpView; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; @@ -46,7 +45,7 @@ import org.sufficientlysecure.keychain.ui.util.ThemeChanger; public class RequestKeyPermissionActivity extends FragmentActivity { public static final String EXTRA_PACKAGE_NAME = "package_name"; - public static final String EXTRA_REQUESTED_KEY_ID = "requested_key_id"; + public static final String EXTRA_REQUESTED_KEY_IDS = "requested_key_ids"; private RequestKeyPermissionPresenter presenter; @@ -70,9 +69,9 @@ public class RequestKeyPermissionActivity extends FragmentActivity { Intent intent = getIntent(); String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); - long masterKeyId = intent.getLongExtra(EXTRA_REQUESTED_KEY_ID, Constants.key.none); + long masterKeyIds[] = intent.getLongArrayExtra(EXTRA_REQUESTED_KEY_IDS); - presenter.setupFromIntentData(packageName, masterKeyId); + presenter.setupFromIntentData(packageName, masterKeyIds); } public static class RequestKeyPermissionFragment extends DialogFragment { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionPresenter.java index 82b7cdb64..b4de0fe7d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionPresenter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RequestKeyPermissionPresenter.java @@ -6,14 +6,18 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; import org.openintents.openpgp.util.OpenPgpUtils.UserId; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.ApiDataAccessObject; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.remote.ApiPermissionHelper; import org.sufficientlysecure.keychain.remote.ApiPermissionHelper.WrongPackageCertificateException; import org.sufficientlysecure.keychain.util.Log; @@ -29,29 +33,33 @@ class RequestKeyPermissionPresenter { private String packageName; private long masterKeyId; + private ProviderHelper providerHelper; static RequestKeyPermissionPresenter createRequestKeyPermissionPresenter(Context context) { PackageManager packageManager = context.getPackageManager(); ApiDataAccessObject apiDataAccessObject = new ApiDataAccessObject(context); ApiPermissionHelper apiPermissionHelper = new ApiPermissionHelper(context, apiDataAccessObject); + ProviderHelper providerHelper = new ProviderHelper(context); - return new RequestKeyPermissionPresenter(context, apiDataAccessObject, apiPermissionHelper, packageManager); + return new RequestKeyPermissionPresenter(context, apiDataAccessObject, apiPermissionHelper, packageManager, + providerHelper); } private RequestKeyPermissionPresenter(Context context, ApiDataAccessObject apiDataAccessObject, - ApiPermissionHelper apiPermissionHelper, PackageManager packageManager) { + ApiPermissionHelper apiPermissionHelper, PackageManager packageManager, ProviderHelper providerHelper) { this.context = context; this.apiDataAccessObject = apiDataAccessObject; this.apiPermissionHelper = apiPermissionHelper; this.packageManager = packageManager; + this.providerHelper = providerHelper; } void setView(RequestKeyPermissionMvpView view) { this.view = view; } - void setupFromIntentData(String packageName, long masterKeyId) { + void setupFromIntentData(String packageName, long[] masterKeyIds) { checkPackageAllowed(packageName); try { @@ -62,25 +70,58 @@ class RequestKeyPermissionPresenter { return; } - this.packageName = packageName; - this.masterKeyId = masterKeyId; try { - CachedPublicKeyRing cachedPublicKeyRing = new ProviderHelper(context).getCachedPublicKeyRing(masterKeyId); - - UserId userId = cachedPublicKeyRing.getSplitPrimaryUserIdWithFallback(); - view.displayKeyInfo(userId); - - if (cachedPublicKeyRing.hasAnySecret()) { - view.switchToLayoutRequestKeyChoice(); - } else { - view.switchToLayoutNoSecret(); - } + setRequestedMasterKeyId(masterKeyIds); } catch (PgpKeyNotFoundException e) { view.finishAsCancelled(); } } + private void setRequestedMasterKeyId(long[] subKeyIds) throws PgpKeyNotFoundException { + CachedPublicKeyRing secretKeyRingOrPublicFallback = findSecretKeyRingOrPublicFallback(subKeyIds); + + if (secretKeyRingOrPublicFallback == null) { + throw new PgpKeyNotFoundException("No key found among requested!"); + } + + this.masterKeyId = secretKeyRingOrPublicFallback.getMasterKeyId(); + + UserId userId = secretKeyRingOrPublicFallback.getSplitPrimaryUserIdWithFallback(); + view.displayKeyInfo(userId); + + if (secretKeyRingOrPublicFallback.hasAnySecret()) { + view.switchToLayoutRequestKeyChoice(); + } else { + view.switchToLayoutNoSecret(); + } + } + + @Nullable + private CachedPublicKeyRing findSecretKeyRingOrPublicFallback(long[] subKeyIds) { + CachedPublicKeyRing publicFallbackRing = null; + for (long candidateSubKeyId : subKeyIds) { + try { + CachedPublicKeyRing cachedPublicKeyRing = providerHelper.getCachedPublicKeyRing( + KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(candidateSubKeyId) + ); + + SecretKeyType secretKeyType = cachedPublicKeyRing.getSecretKeyType(candidateSubKeyId); + if (secretKeyType.isUsable()) { + return cachedPublicKeyRing; + } + if (publicFallbackRing == null) { + publicFallbackRing = cachedPublicKeyRing; + } + } catch (PgpKeyNotFoundException | NotFoundException e) { + // no matter + } + } + return publicFallbackRing; + } + private void setPackageInfo(String packageName) throws NameNotFoundException { + this.packageName = packageName; + ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0); Drawable appIcon = packageManager.getApplicationIcon(applicationInfo); CharSequence appName = packageManager.getApplicationLabel(applicationInfo);