Use AOSP Installer if permission check fails

If the old repo index is used and the
permission check fails in ApkVerifier
fallback to the AOSP DefaultInstaller
to show all permissions.
This commit is contained in:
Dominik Schürmann 2016-07-29 18:00:05 +02:00
parent 19a033db32
commit bfcc706167
2 changed files with 35 additions and 7 deletions

View File

@ -51,7 +51,7 @@ class ApkVerifier {
this.pm = context.getPackageManager();
}
public void verifyApk() throws ApkVerificationException {
public void verifyApk() throws ApkVerificationException, ApkPermissionUnequalException {
// parse downloaded apk file locally
PackageInfo localApkInfo = pm.getPackageArchiveInfo(
localApkUri.getPath(), PackageManager.GET_PERMISSIONS);
@ -78,9 +78,9 @@ class ApkVerifier {
// Thus, containsAll() instead of equals() is used!
// See also https://gitlab.com/fdroid/fdroidclient/issues/703
if (!expectedPermissions.containsAll(localPermissions)) {
throw new ApkVerificationException(
throw new ApkPermissionUnequalException(
"Permissions of the apk file are not a true subset of the permissions listed by the repo," +
" i.e., some permissions have not been shown to the user!");
" i.e., some permissions have not been shown to the user!");
}
int localTargetSdkVersion = localApkInfo.applicationInfo.targetSdkVersion;
@ -93,7 +93,6 @@ class ApkVerifier {
} else if (localTargetSdkVersion != expectedTargetSdkVersion) {
throw new ApkVerificationException("TargetSdkVersion of apk file is not the expected targetSdkVersion!");
}
}
private HashSet<String> getLocalPermissionsSet(PackageInfo localApkInfo) {
@ -116,4 +115,15 @@ class ApkVerifier {
}
}
public static class ApkPermissionUnequalException extends Exception {
ApkPermissionUnequalException(String message) {
super(message);
}
ApkPermissionUnequalException(Throwable cause) {
super(cause);
}
}
}

View File

@ -226,17 +226,35 @@ public abstract class Installer {
* @param apk apk object of the app that should be installed
*/
public void installPackage(Uri localApkUri, Uri downloadUri, Apk apk) {
Uri sanitizedUri;
try {
// verify that permissions of the apk file match the ones from the apk object
ApkVerifier apkVerifier = new ApkVerifier(context, localApkUri, apk);
apkVerifier.verifyApk();
} catch (ApkVerifier.ApkVerificationException e) {
Log.e(TAG, e.getMessage(), e);
sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED,
e.getMessage());
return;
} catch (ApkVerifier.ApkPermissionUnequalException e) {
// if permissions of apk are not the ones listed in the repo
// and an unattended installer is used, a wrong permission screen
// has been shown, thus fallback to AOSP DefaultInstaller!
if (isUnattended()) {
Log.e(TAG, e.getMessage(), e);
Log.e(TAG, "Falling back to AOSP DefaultInstaller!");
DefaultInstaller defaultInstaller = new DefaultInstaller(context);
defaultInstaller.installPackageInternal(localApkUri, downloadUri, apk);
return;
}
}
Uri sanitizedUri;
try {
// move apk file to private directory for installation and check hash
sanitizedUri = ApkFileProvider.getSafeUri(
context, localApkUri, apk, supportsContentUri());
} catch (ApkVerifier.ApkVerificationException | IOException e) {
Log.e(TAG, "ApkVerifier / ApkFileProvider failed", e);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_INTERRUPTED,
e.getMessage());
return;