From bd7cfb950450fcc889a23e795a3ed56e5b208ff5 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 3 Apr 2018 01:28:45 +0200 Subject: [PATCH] Key selection implies permission to OpenKeychain access --- .../remote/ApiPendingIntentFactory.java | 17 ++++------------- .../keychain/remote/ApiPermissionHelper.java | 8 ++++++++ .../keychain/remote/OpenPgpService.java | 9 ++++++++- .../ui/dialog/RemoteSelectIdKeyActivity.java | 4 +++- .../RemoteSelectIdentityKeyPresenter.java | 17 ++++++++++++++--- 5 files changed, 37 insertions(+), 18 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java index 364f053ab..98e64ad00 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPendingIntentFactory.java @@ -90,16 +90,6 @@ public class ApiPendingIntentFactory { return createInternal(data, intent); } - PendingIntent createSelectIdentityKeyPendingIntent( - String packageName, String apiIdentity, Long currentMasterKeyId) { - Intent intent = new Intent(mContext, RemoteSelectIdKeyActivity.class); - intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_USER_ID, apiIdentity); - intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_CURRENT_MASTER_KEY_ID, currentMasterKeyId); - - return createInternal(null, intent); - } - PendingIntent createSelectPublicKeyPendingIntent(Intent data, long[] keyIdsArray, ArrayList missingEmails, ArrayList duplicateEmails, boolean noUserIdsCheck) { Intent intent = new Intent(mContext, RemoteSelectPubKeyActivity.class); @@ -147,16 +137,17 @@ public class ApiPendingIntentFactory { PendingIntent createSelectSignKeyIdLegacyPendingIntent(Intent data, String packageName, String preferredUserId) { Intent intent = new Intent(mContext, SelectSignKeyIdActivity.class); intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(packageName)); - intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_USER_ID, preferredUserId); + intent.putExtra(SelectSignKeyIdActivity.EXTRA_USER_ID, preferredUserId); return createInternal(data, intent); } - PendingIntent createSelectSignKeyIdPendingIntent(Intent data, String packageName, String preferredUserId) { + PendingIntent createSelectSignKeyIdPendingIntent(Intent data, String packageName, + byte[] packageSignature, String preferredUserId) { Intent intent = new Intent(mContext, RemoteSelectIdKeyActivity.class); intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(packageName)); intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_PACKAGE_NAME, packageName); + intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature); intent.putExtra(RemoteSelectIdKeyActivity.EXTRA_USER_ID, preferredUserId); return createInternal(data, intent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java index 445886892..fa6d04bbd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java @@ -124,6 +124,14 @@ public class ApiPermissionHelper { } } + byte[] getPackageCertificateOrError(String packageName) { + try { + return getPackageCertificate(packageName); + } catch (NameNotFoundException e) { + throw new AssertionError("Package signature must be retrievable"); + } + } + private byte[] getPackageCertificate(String packageName) throws NameNotFoundException { @SuppressLint("PackageManagerGetSignatures") // we do check the byte array of *all* signatures PackageInfo pkgInfo = mContext.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index e6a375c3f..0e653e6fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -722,7 +722,9 @@ public class OpenPgpService extends Service { if (preferredUserId == null) { pi = mApiPendingIntentFactory.createSelectSignKeyIdLegacyPendingIntent(data, currentPkg, null); } else { - pi = mApiPendingIntentFactory.createSelectSignKeyIdPendingIntent(data, currentPkg, preferredUserId); + byte[] packageSignature = mApiPermissionHelper.getPackageCertificateOrError(currentPkg); + pi = mApiPendingIntentFactory.createSelectSignKeyIdPendingIntent( + data, currentPkg, packageSignature, preferredUserId); } result.putExtra(OpenPgpApi.RESULT_INTENT, pi); } @@ -899,6 +901,11 @@ public class OpenPgpService extends Service { return result; } + // special exception: getting a sign key id will also register the app + if (OpenPgpApi.ACTION_GET_SIGN_KEY_ID.equals(data.getAction())) { + return null; + } + // check if caller is allowed to access OpenKeychain Intent result = mApiPermissionHelper.isAllowedOrReturnIntent(data); if (result != null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java index 53c335696..5acd94a12 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdKeyActivity.java @@ -74,6 +74,7 @@ import timber.log.Timber; public class RemoteSelectIdKeyActivity extends FragmentActivity { public static final String EXTRA_PACKAGE_NAME = "package_name"; + public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature"; public static final String EXTRA_USER_ID = "user_id"; public static final String EXTRA_CURRENT_MASTER_KEY_ID = "current_master_key_id"; @@ -106,8 +107,9 @@ public class RemoteSelectIdKeyActivity extends FragmentActivity { Intent intent = getIntent(); String userId = intent.getStringExtra(EXTRA_USER_ID); String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); + byte[] packageSignature = intent.getByteArrayExtra(EXTRA_PACKAGE_SIGNATURE); - presenter.setupFromIntentData(packageName, userId); + presenter.setupFromIntentData(packageName, packageSignature, userId); } public static class RemoteSelectIdentityKeyDialogFragment extends DialogFragment { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java index e60b3bdfa..59d5de589 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/dialog/RemoteSelectIdentityKeyPresenter.java @@ -37,7 +37,9 @@ import org.sufficientlysecure.keychain.livedata.KeyInfoInteractor.KeySelector; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.provider.ApiDataAccessObject; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import timber.log.Timber; @@ -55,11 +57,14 @@ class RemoteSelectIdentityKeyPresenter { private UserId userId; private long selectedMasterKeyId; private byte[] generatedKeyData; + private ApiDataAccessObject apiDao; + private AppSettings appSettings; RemoteSelectIdentityKeyPresenter(Context context, RemoteSelectIdViewModel viewModel, LifecycleOwner lifecycleOwner) { this.context = context; this.viewModel = viewModel; + this.apiDao = new ApiDataAccessObject(context); packageManager = context.getPackageManager(); @@ -71,9 +76,9 @@ class RemoteSelectIdentityKeyPresenter { this.view = view; } - void setupFromIntentData(String packageName, String rawUserId) { + void setupFromIntentData(String packageName, byte[] packageSignature, String rawUserId) { try { - setPackageInfo(packageName); + setPackageInfo(packageName, packageSignature); } catch (NameNotFoundException e) { Timber.e(e, "Unable to find info of calling app!"); view.finishAsCancelled(); @@ -92,11 +97,13 @@ class RemoteSelectIdentityKeyPresenter { viewModel.getKeyInfo(context).setKeySelector(KeySelector.createOnlySecret(listedKeyRingUri, null)); } - private void setPackageInfo(String packageName) throws NameNotFoundException { + private void setPackageInfo(String packageName, byte[] packageSignature) throws NameNotFoundException { ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0); Drawable appIcon = packageManager.getApplicationIcon(applicationInfo); CharSequence appLabel = packageManager.getApplicationLabel(applicationInfo); + appSettings = new AppSettings(packageName, packageSignature); + view.setTitleClientIconAndName(appIcon, appLabel); } @@ -192,11 +199,15 @@ class RemoteSelectIdentityKeyPresenter { } void onHighlightFinished() { + apiDao.insertApiApp(appSettings); + apiDao.addAllowedKeyIdForApp(appSettings.getPackageName(), selectedMasterKeyId); view.finishAndReturn(selectedMasterKeyId); } void onImportOpSuccess(ImportKeyResult result) { long importedMasterKeyId = result.getImportedMasterKeyIds()[0]; + apiDao.insertApiApp(appSettings); + apiDao.addAllowedKeyIdForApp(appSettings.getPackageName(), selectedMasterKeyId); view.finishAndReturn(importedMasterKeyId); }