Key selection implies permission to OpenKeychain access

This commit is contained in:
Vincent Breitmoser
2018-04-03 01:28:45 +02:00
parent 50af8b6889
commit bd7cfb9504
5 changed files with 37 additions and 18 deletions

View File

@@ -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<String> missingEmails,
ArrayList<String> 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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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);
}