diff --git a/Privileged-F-Droid/src/main/AndroidManifest.xml b/Privileged-F-Droid/src/main/AndroidManifest.xml index 63bf561ed..e919ee606 100644 --- a/Privileged-F-Droid/src/main/AndroidManifest.xml +++ b/Privileged-F-Droid/src/main/AndroidManifest.xml @@ -11,6 +11,14 @@ android:name="android.permission.DELETE_PACKAGES" tools:ignore="ProtectedPermissions" /> + + + + android:permission="org.fdroid.fdroid.privileged.USE_SERVICE"> diff --git a/Privileged-F-Droid/src/main/java/org/fdroid/fdroid/privileged/PrivilegedService.java b/Privileged-F-Droid/src/main/java/org/fdroid/fdroid/privileged/PrivilegedService.java index b727e7408..d717d4b8d 100644 --- a/Privileged-F-Droid/src/main/java/org/fdroid/fdroid/privileged/PrivilegedService.java +++ b/Privileged-F-Droid/src/main/java/org/fdroid/fdroid/privileged/PrivilegedService.java @@ -19,40 +19,25 @@ package org.fdroid.fdroid.privileged; -import android.annotation.SuppressLint; import android.app.Service; import android.content.Intent; import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageInstallObserver; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.Signature; import android.net.Uri; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.lang.reflect.Method; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; /** * This service provides an API via AIDL IPC for the main F-Droid app to install/delete packages. - *

- * Security: - * Binding only works when,... - * - packageName is "org.fdroid.fdroid" - * - signature is equal or BuildConfig.DEBUG */ public class PrivilegedService extends Service { public static final String TAG = "PrivilegedFDroid"; - private static final String F_DROID_PACKAGE = "org.fdroid.fdroid"; - private Method mInstallMethod; private Method mDeleteMethod; @@ -119,16 +104,12 @@ public class PrivilegedService extends Service { @Override public void installPackage(Uri packageURI, int flags, String installerPackageName, IPrivilegedCallback callback) { - if (isAllowed()) { - installPackageImpl(packageURI, flags, installerPackageName, callback); - } + installPackageImpl(packageURI, flags, installerPackageName, callback); } @Override public void deletePackage(String packageName, int flags, IPrivilegedCallback callback) { - if (isAllowed()) { - deletePackageImpl(packageName, flags, callback); - } + deletePackageImpl(packageName, flags, callback); } }; @@ -137,111 +118,6 @@ public class PrivilegedService extends Service { return mBinder; } - private boolean isAllowed() { - // Check that binding app is allowed to use this API - try { - - barrierPackageName(); - barrierPackageCertificate(); - - } catch (WrongPackageCertificateException e) { - Log.e(TAG, "package certificate is not allowed!", e); - return false; - } catch (WrongPackageNameException e) { - Log.e(TAG, "package name is not allowed!", e); - return false; - } - - return true; - } - - /** - * Checks if process that binds to this service (i.e. the package name corresponding to the - * process) is allowed. Only returns when package name is allowed! - * - * @throws WrongPackageNameException - */ - private void barrierPackageName() throws WrongPackageNameException { - int uid = Binder.getCallingUid(); - String[] callingPackages = getPackageManager().getPackagesForUid(uid); - - // is calling package allowed to use this service? - for (String currentPkg : callingPackages) { - if (F_DROID_PACKAGE.equals(currentPkg)) { - return; - } - } - - throw new WrongPackageNameException("package name is not allowed"); - } - - private void barrierPackageCertificate() throws WrongPackageCertificateException { - String packageName = getCurrentCallingPackage(); - - byte[] packageCertificate; - try { - packageCertificate = getPackageCertificate(packageName); - } catch (PackageManager.NameNotFoundException e) { - throw new WrongPackageCertificateException(e.getMessage()); - } - - MessageDigest md; - try { - md = MessageDigest.getInstance("SHA-512"); - } catch (NoSuchAlgorithmException e) { - throw new WrongPackageCertificateException("SHA-512 not available!"); - } - byte[] hash = md.digest(packageCertificate); - - Log.d(TAG, "hash:" + getHex(hash)); - Log.d(TAG, "F_DROID_CERT_SHA512:" + BuildConfig.F_DROID_CERT_SHA512); - - if (getHex(hash).equals(BuildConfig.F_DROID_CERT_SHA512) - || BuildConfig.DEBUG) { - return; - } - - throw new WrongPackageCertificateException("certificate not allowed!"); - } - - private byte[] getPackageCertificate(String packageName) throws PackageManager.NameNotFoundException { - // we do check the byte array of *all* signatures - @SuppressLint("PackageManagerGetSignatures") - 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 - return callingPackages[0]; - } - @Override public void onCreate() { super.onCreate(); @@ -266,40 +142,4 @@ public class PrivilegedService extends Service { } } - private String getHex(byte[] byteData) { - StringBuilder hexString = new StringBuilder(); - for (byte aByteData : byteData) { - String hex = Integer.toHexString(0xff & aByteData); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - - return hexString.toString(); - } - - public static class WrongPackageCertificateException extends Exception { - private static final long serialVersionUID = -1294642703122196028L; - - public WrongPackageCertificateException(String message) { - super(message); - } - } - - public static class WrongPackageNameException extends Exception { - private static final long serialVersionUID = -2294642703111196028L; - - public WrongPackageNameException(String message) { - super(message); - } - } - - public static class AndroidNotCompatibleException extends Exception { - private static final long serialVersionUID = -3294642703111196028L; - - public AndroidNotCompatibleException(String message) { - super(message); - } - } }