From df219b61c6416b56e52b32d58d828e5b347512cb Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Fri, 27 Nov 2015 23:40:04 +0100 Subject: move custm api permission methods into helper class (composition over inheritance) --- .../keychain/remote/ApiPermissionHelper.java | 280 ++++++++++++++++++++ .../keychain/remote/OpenPgpService.java | 33 ++- .../keychain/remote/RemoteService.java | 283 --------------------- 3 files changed, 302 insertions(+), 294 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java new file mode 100644 index 000000000..2d65e5b80 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ApiPermissionHelper.java @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.remote; + + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; + +import android.annotation.SuppressLint; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.Signature; +import android.net.Uri; +import android.os.Binder; + +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.util.OpenPgpApi; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity; +import org.sufficientlysecure.keychain.util.Log; + + +/** + * Abstract service class for remote APIs that handle app registration and user input. + */ +public class ApiPermissionHelper { + + private final Context mContext; + private final ProviderHelper mProviderHelper; + private PackageManager mPackageManager; + + public ApiPermissionHelper(Context context) { + mContext = context; + mPackageManager = context.getPackageManager(); + mProviderHelper = new ProviderHelper(context); + } + + public static class WrongPackageCertificateException extends Exception { + private static final long serialVersionUID = -8294642703122196028L; + + public WrongPackageCertificateException(String message) { + super(message); + } + } + + /** + * Checks if caller is allowed to access the API + * + * @return null if caller is allowed, or a Bundle with a PendingIntent + */ + protected Intent isAllowed(Intent data) { + try { + if (isCallerAllowed()) { + return null; + } else { + String packageName = getCurrentCallingPackage(); + Log.d(Constants.TAG, "isAllowed packageName: " + packageName); + + byte[] packageCertificate; + try { + packageCertificate = getPackageCertificate(packageName); + } catch (NameNotFoundException e) { + Log.e(Constants.TAG, "Should not happen, returning!", e); + // return error + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERROR, + new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); + return result; + } + Log.e(Constants.TAG, "Not allowed to use service! return PendingIntent for registration!"); + + Intent intent = new Intent(mContext, RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_REGISTER); + intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); + intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageCertificate); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); + + PendingIntent pi = PendingIntent.getActivity(mContext, 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + + return result; + } + } catch (WrongPackageCertificateException e) { + Log.e(Constants.TAG, "wrong signature!", e); + + Intent intent = new Intent(mContext, RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE); + intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, + mContext.getString(R.string.api_error_wrong_signature)); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); + + PendingIntent pi = PendingIntent.getActivity(mContext, 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + + return result; + } + } + + 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); + // NOTE: Silly Android API naming: Signatures are actually certificates + Signature[] certificates = pkgInfo.signatures; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (Signature cert : certificates) { + try { + outputStream.write(cert.toByteArray()); + } catch (IOException e) { + throw new RuntimeException("Should not happen! Writing ByteArrayOutputStream to concat certificates failed"); + } + } + + // Even if an apk has several certificates, these certificates should never change + // Google Play does not allow the introduction of new certificates into an existing apk + // Also see this attack: http://stackoverflow.com/a/10567852 + return outputStream.toByteArray(); + } + + /** + * Returns package name associated with the UID, which is assigned to the process that sent you the + * current transaction that is being processed :) + * + * @return package name + */ + protected String getCurrentCallingPackage() { + String[] callingPackages = mPackageManager.getPackagesForUid(Binder.getCallingUid()); + + // NOTE: No support for sharedUserIds + // callingPackages contains more than one entry when sharedUserId has been used + // No plans to support sharedUserIds due to many bugs connected to them: + // http://java-hamster.blogspot.de/2010/05/androids-shareduserid.html + String currentPkg = callingPackages[0]; + Log.d(Constants.TAG, "currentPkg: " + currentPkg); + + return currentPkg; + } + + /** + * DEPRECATED API + *

+ * Retrieves AccountSettings from database for the application calling this remote service + */ + protected AccountSettings getAccSettings(String accountName) { + String currentPkg = getCurrentCallingPackage(); + Log.d(Constants.TAG, "getAccSettings accountName: " + accountName); + + Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(currentPkg, accountName); + + return mProviderHelper.getApiAccountSettings(uri); // can be null! + } + + /** + * Deprecated API + */ + protected Intent getCreateAccountIntent(Intent data, String accountName) { + String packageName = getCurrentCallingPackage(); + Log.d(Constants.TAG, "getCreateAccountIntent accountName: " + accountName); + + Intent intent = new Intent(mContext, RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_CREATE_ACCOUNT); + intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); + intent.putExtra(RemoteServiceActivity.EXTRA_ACC_NAME, accountName); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); + + PendingIntent pi = PendingIntent.getActivity(mContext, 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + + return result; + } + + /** + * Checks if process that binds to this service (i.e. the package name corresponding to the + * process) is in the list of allowed package names. + * + * @return true if process is allowed to use this service + * @throws WrongPackageCertificateException + */ + private boolean isCallerAllowed() throws WrongPackageCertificateException { + return isUidAllowed(Binder.getCallingUid()); + } + + private boolean isUidAllowed(int uid) + throws WrongPackageCertificateException { + + String[] callingPackages = mPackageManager.getPackagesForUid(uid); + + // is calling package allowed to use this service? + for (String currentPkg : callingPackages) { + if (isPackageAllowed(currentPkg)) { + return true; + } + } + + Log.e(Constants.TAG, "Uid is NOT allowed!"); + return false; + } + + /** + * Checks if packageName is a registered app for the API. Does not return true for own package! + * + * @throws WrongPackageCertificateException + */ + private boolean isPackageAllowed(String packageName) throws WrongPackageCertificateException { + Log.d(Constants.TAG, "isPackageAllowed packageName: " + packageName); + + ArrayList allowedPkgs = mProviderHelper.getRegisteredApiApps(); + Log.d(Constants.TAG, "allowed: " + allowedPkgs); + + // check if package is allowed to use our service + if (allowedPkgs.contains(packageName)) { + Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); + + // check package signature + byte[] currentCert; + try { + currentCert = getPackageCertificate(packageName); + } catch (NameNotFoundException e) { + throw new WrongPackageCertificateException(e.getMessage()); + } + + byte[] storedCert = mProviderHelper.getApiAppCertificate(packageName); + if (Arrays.equals(currentCert, storedCert)) { + Log.d(Constants.TAG, + "Package certificate is correct! (equals certificate from database)"); + return true; + } else { + throw new WrongPackageCertificateException( + "PACKAGE NOT ALLOWED! Certificate wrong! (Certificate not " + + "equals certificate from database)"); + } + } + + Log.d(Constants.TAG, "Package is NOT allowed! packageName: " + packageName); + return false; + } + +} 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 9501226cd..5f48e44bd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.remote; import android.app.PendingIntent; +import android.app.Service; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -74,7 +75,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; -public class OpenPgpService extends RemoteService { +public class OpenPgpService extends Service { static final String[] EMAIL_SEARCH_PROJECTION = new String[]{ KeyRings._ID, @@ -87,6 +88,16 @@ public class OpenPgpService extends RemoteService { static final String EMAIL_SEARCH_WHERE = Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " + KeychainContract.KeyRings.IS_EXPIRED + " = 0"; + private ApiPermissionHelper mApiPermissionHelper; + private ProviderHelper mProviderHelper; + + @Override + public void onCreate() { + super.onCreate(); + mApiPermissionHelper = new ApiPermissionHelper(this); + mProviderHelper = new ProviderHelper(this); + } + /** * Search database for key ids based on emails. */ @@ -225,7 +236,7 @@ public class OpenPgpService extends RemoteService { // to retrieve the missing key Intent intent = new Intent(getBaseContext(), SelectAllowedKeysActivity.class); intent.putExtra(SelectAllowedKeysActivity.EXTRA_SERVICE_INTENT, data); - intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(getCurrentCallingPackage())); + intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(mApiPermissionHelper.getCurrentCallingPackage())); return PendingIntent.getActivity(getBaseContext(), 0, intent, @@ -297,7 +308,7 @@ public class OpenPgpService extends RemoteService { } // execute PGP operation! - PgpSignEncryptOperation pse = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null); + PgpSignEncryptOperation pse = new PgpSignEncryptOperation(this, new ProviderHelper(this), null); PgpSignEncryptResult pgpResult = pse.execute(pseInput, inputParcel, inputData, outputStream); if (pgpResult.isPending()) { @@ -414,9 +425,9 @@ public class OpenPgpService extends RemoteService { if (TextUtils.isEmpty(accName)) { accName = "default"; } - final AccountSettings accSettings = getAccSettings(accName); + final AccountSettings accSettings = mApiPermissionHelper.getAccSettings(accName); if (accSettings == null || (accSettings.getKeyId() == Constants.key.none)) { - return getCreateAccountIntent(data, accName); + return mApiPermissionHelper.getCreateAccountIntent(data, accName); } pseInput.setAdditionalEncryptId(accSettings.getKeyId()); } @@ -431,7 +442,7 @@ public class OpenPgpService extends RemoteService { new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); } - PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null); + PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, mProviderHelper, null); // execute PGP operation! PgpSignEncryptResult pgpResult = op.execute(pseInput, inputParcel, inputData, outputStream); @@ -472,7 +483,7 @@ public class OpenPgpService extends RemoteService { outputStream = null; } - String currentPkg = getCurrentCallingPackage(); + String currentPkg = mApiPermissionHelper.getCurrentCallingPackage(); HashSet allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp( KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); @@ -695,7 +706,7 @@ public class OpenPgpService extends RemoteService { String preferredUserId = data.getStringExtra(OpenPgpApi.EXTRA_USER_ID); Intent intent = new Intent(getBaseContext(), SelectSignKeyIdActivity.class); - String currentPkg = getCurrentCallingPackage(); + String currentPkg = mApiPermissionHelper.getCurrentCallingPackage(); intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(currentPkg)); intent.putExtra(SelectSignKeyIdActivity.EXTRA_USER_ID, preferredUserId); intent.putExtra(SelectSignKeyIdActivity.EXTRA_DATA, data); @@ -740,9 +751,9 @@ public class OpenPgpService extends RemoteService { } Log.d(Constants.TAG, "accName: " + accName); // fallback to old API - final AccountSettings accSettings = getAccSettings(accName); + final AccountSettings accSettings = mApiPermissionHelper.getAccSettings(accName); if (accSettings == null || (accSettings.getKeyId() == Constants.key.none)) { - return getCreateAccountIntent(data, accName); + return mApiPermissionHelper.getCreateAccountIntent(data, accName); } // NOTE: just wrapping the key id @@ -792,7 +803,7 @@ public class OpenPgpService extends RemoteService { } // check if caller is allowed to access OpenKeychain - Intent result = isAllowed(data); + Intent result = mApiPermissionHelper.isAllowed(data); if (result != null) { return result; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java deleted file mode 100644 index 792a4d253..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2013-2015 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.remote; - -import android.annotation.SuppressLint; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature; -import android.net.Uri; -import android.os.Binder; - -import org.openintents.openpgp.OpenPgpError; -import org.openintents.openpgp.util.OpenPgpApi; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity; -import org.sufficientlysecure.keychain.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Abstract service class for remote APIs that handle app registration and user input. - */ -public abstract class RemoteService extends Service { - - public static class WrongPackageCertificateException extends Exception { - private static final long serialVersionUID = -8294642703122196028L; - - public WrongPackageCertificateException(String message) { - super(message); - } - } - - Context mContext; - ProviderHelper mProviderHelper; - - public Context getContext() { - return mContext; - } - - /** - * Checks if caller is allowed to access the API - * - * @return null if caller is allowed, or a Bundle with a PendingIntent - */ - protected Intent isAllowed(Intent data) { - try { - if (isCallerAllowed()) { - return null; - } else { - String packageName = getCurrentCallingPackage(); - Log.d(Constants.TAG, "isAllowed packageName: " + packageName); - - byte[] packageCertificate; - try { - packageCertificate = getPackageCertificate(packageName); - } catch (NameNotFoundException e) { - Log.e(Constants.TAG, "Should not happen, returning!", e); - // return error - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); - result.putExtra(OpenPgpApi.RESULT_ERROR, - new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); - return result; - } - Log.e(Constants.TAG, "Not allowed to use service! return PendingIntent for registration!"); - - Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); - intent.setAction(RemoteServiceActivity.ACTION_REGISTER); - intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageCertificate); - intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - - return result; - } - } catch (WrongPackageCertificateException e) { - Log.e(Constants.TAG, "wrong signature!", e); - - Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); - intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE); - intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, - getString(R.string.api_error_wrong_signature)); - intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - - return result; - } - } - - private byte[] getPackageCertificate(String packageName) throws NameNotFoundException { - @SuppressLint("PackageManagerGetSignatures") // we do check the byte array of *all* signatures - PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES); - // NOTE: Silly Android API naming: Signatures are actually certificates - Signature[] certificates = pkgInfo.signatures; - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - for (Signature cert : certificates) { - try { - outputStream.write(cert.toByteArray()); - } catch (IOException e) { - throw new RuntimeException("Should not happen! Writing ByteArrayOutputStream to concat certificates failed"); - } - } - - // Even if an apk has several certificates, these certificates should never change - // Google Play does not allow the introduction of new certificates into an existing apk - // Also see this attack: http://stackoverflow.com/a/10567852 - return outputStream.toByteArray(); - } - - /** - * Returns package name associated with the UID, which is assigned to the process that sent you the - * current transaction that is being processed :) - * - * @return package name - */ - protected String getCurrentCallingPackage() { - String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid()); - - // NOTE: No support for sharedUserIds - // callingPackages contains more than one entry when sharedUserId has been used - // No plans to support sharedUserIds due to many bugs connected to them: - // http://java-hamster.blogspot.de/2010/05/androids-shareduserid.html - String currentPkg = callingPackages[0]; - Log.d(Constants.TAG, "currentPkg: " + currentPkg); - - return currentPkg; - } - - /** - * DEPRECATED API - *

- * Retrieves AccountSettings from database for the application calling this remote service - */ - protected AccountSettings getAccSettings(String accountName) { - String currentPkg = getCurrentCallingPackage(); - Log.d(Constants.TAG, "getAccSettings accountName: " + accountName); - - Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(currentPkg, accountName); - - return mProviderHelper.getApiAccountSettings(uri); // can be null! - } - - /** - * Deprecated API - */ - protected Intent getCreateAccountIntent(Intent data, String accountName) { - String packageName = getCurrentCallingPackage(); - Log.d(Constants.TAG, "getCreateAccountIntent accountName: " + accountName); - - Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); - intent.setAction(RemoteServiceActivity.ACTION_CREATE_ACCOUNT); - intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); - intent.putExtra(RemoteServiceActivity.EXTRA_ACC_NAME, accountName); - intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - - return result; - } - - /** - * Checks if process that binds to this service (i.e. the package name corresponding to the - * process) is in the list of allowed package names. - * - * @return true if process is allowed to use this service - * @throws WrongPackageCertificateException - */ - private boolean isCallerAllowed() throws WrongPackageCertificateException { - return isUidAllowed(Binder.getCallingUid()); - } - - private boolean isUidAllowed(int uid) - throws WrongPackageCertificateException { - - String[] callingPackages = getPackageManager().getPackagesForUid(uid); - - // is calling package allowed to use this service? - for (String currentPkg : callingPackages) { - if (isPackageAllowed(currentPkg)) { - return true; - } - } - - Log.e(Constants.TAG, "Uid is NOT allowed!"); - return false; - } - - /** - * Checks if packageName is a registered app for the API. Does not return true for own package! - * - * @throws WrongPackageCertificateException - */ - private boolean isPackageAllowed(String packageName) throws WrongPackageCertificateException { - Log.d(Constants.TAG, "isPackageAllowed packageName: " + packageName); - - ArrayList allowedPkgs = mProviderHelper.getRegisteredApiApps(); - Log.d(Constants.TAG, "allowed: " + allowedPkgs); - - // check if package is allowed to use our service - if (allowedPkgs.contains(packageName)) { - Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName); - - // check package signature - byte[] currentCert; - try { - currentCert = getPackageCertificate(packageName); - } catch (NameNotFoundException e) { - throw new WrongPackageCertificateException(e.getMessage()); - } - - byte[] storedCert = mProviderHelper.getApiAppCertificate(packageName); - if (Arrays.equals(currentCert, storedCert)) { - Log.d(Constants.TAG, - "Package certificate is correct! (equals certificate from database)"); - return true; - } else { - throw new WrongPackageCertificateException( - "PACKAGE NOT ALLOWED! Certificate wrong! (Certificate not " + - "equals certificate from database)"); - } - } - - Log.d(Constants.TAG, "Package is NOT allowed! packageName: " + packageName); - return false; - } - - @Override - public void onCreate() { - super.onCreate(); - mContext = this; - mProviderHelper = new ProviderHelper(this); - } - -} -- cgit v1.2.3