Use app name and version when bluetoothing to peer.
Previously, it would either send "base.apk" (in earlier versions of F-Droid when bluetoothing an apk from the /data/app/... dirs), or "install-[random].apk" (if recent F-Droid when copying file to a safe place to expose via a FileProvider. This now writes the file to, e.g. "F-Droid-0.103.1.apk" before sending. Note that this means files are more likely to be overridden when being sent, if the same apk from two different repositories is either: * Sent via bluetooth * Prompted to install via the system package manager However this should still never let malicious people write to that folder.
This commit is contained in:
parent
6002a97a03
commit
91eb408280
@ -27,7 +27,7 @@ import android.bluetooth.BluetoothAdapter;
|
|||||||
import android.bluetooth.BluetoothManager;
|
import android.bluetooth.BluetoothManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
@ -377,12 +377,12 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
PackageManager pm = getPackageManager();
|
PackageManager pm = getPackageManager();
|
||||||
ApplicationInfo appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
|
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
||||||
sendBt = new Intent(Intent.ACTION_SEND);
|
sendBt = new Intent(Intent.ACTION_SEND);
|
||||||
|
|
||||||
// The APK type ("application/vnd.android.package-archive") is blocked by stock Android, so use zip
|
// The APK type ("application/vnd.android.package-archive") is blocked by stock Android, so use zip
|
||||||
sendBt.setType("application/zip");
|
sendBt.setType("application/zip");
|
||||||
sendBt.putExtra(Intent.EXTRA_STREAM, ApkFileProvider.getSafeUri(this, appInfo));
|
sendBt.putExtra(Intent.EXTRA_STREAM, ApkFileProvider.getSafeUri(this, packageInfo));
|
||||||
|
|
||||||
// not all devices have the same Bluetooth Activities, so
|
// not all devices have the same Bluetooth Activities, so
|
||||||
// let's find it
|
// let's find it
|
||||||
|
@ -79,9 +79,13 @@ public class AppProvider extends FDroidProvider {
|
|||||||
return apps;
|
return apps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static App findHighestPriorityMetadata(ContentResolver resolver, String packageName) {
|
public static App findHighestPriorityMetadata(ContentResolver resolver, String packageName, String[] cols) {
|
||||||
final Uri uri = getHighestPriorityMetadataUri(packageName);
|
final Uri uri = getHighestPriorityMetadataUri(packageName);
|
||||||
return cursorToApp(resolver.query(uri, Cols.ALL, null, null, null));
|
return cursorToApp(resolver.query(uri, cols, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static App findHighestPriorityMetadata(ContentResolver resolver, String packageName) {
|
||||||
|
return findHighestPriorityMetadata(resolver, packageName, Cols.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,6 +21,7 @@ package org.fdroid.fdroid.installer;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||||
@ -28,6 +29,8 @@ import com.nostra13.universalimageloader.utils.StorageUtils;
|
|||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.fdroid.fdroid.Hasher;
|
import org.fdroid.fdroid.Hasher;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
|
import org.fdroid.fdroid.data.App;
|
||||||
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
import org.fdroid.fdroid.data.SanitizedFile;
|
import org.fdroid.fdroid.data.SanitizedFile;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -42,8 +45,11 @@ public class ApkCache {
|
|||||||
* verify the hash after copying. This is because we are copying from an installed apk, which
|
* verify the hash after copying. This is because we are copying from an installed apk, which
|
||||||
* other apps do not have permission to modify.
|
* other apps do not have permission to modify.
|
||||||
*/
|
*/
|
||||||
public static SanitizedFile copyInstalledApkToFiles(Context context, ApplicationInfo appInfo) throws IOException {
|
public static SanitizedFile copyInstalledApkToFiles(Context context, PackageInfo packageInfo) throws IOException {
|
||||||
return copyApkToFiles(context, new File(appInfo.publicSourceDir), false, null, null);
|
ApplicationInfo appInfo = packageInfo.applicationInfo;
|
||||||
|
CharSequence name = context.getPackageManager().getApplicationLabel(appInfo);
|
||||||
|
String apkFileName = name + "-" + packageInfo.versionName + ".apk";
|
||||||
|
return copyApkToFiles(context, new File(appInfo.publicSourceDir), apkFileName, false, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +60,10 @@ public class ApkCache {
|
|||||||
*/
|
*/
|
||||||
public static SanitizedFile copyApkFromCacheToFiles(Context context, File apkFile, Apk expectedApk)
|
public static SanitizedFile copyApkFromCacheToFiles(Context context, File apkFile, Apk expectedApk)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return copyApkToFiles(context, apkFile, true, expectedApk.hash, expectedApk.hashType);
|
App app = AppProvider.Helper.findHighestPriorityMetadata(context.getContentResolver(), expectedApk.packageName);
|
||||||
|
String name = app == null ? expectedApk.packageName : app.name;
|
||||||
|
String apkFileName = name + "-" + expectedApk.versionName + ".apk";
|
||||||
|
return copyApkToFiles(context, apkFile, apkFileName, true, expectedApk.hash, expectedApk.hashType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,10 +73,17 @@ public class ApkCache {
|
|||||||
* if the app was installed from part of the system where it can't be tampered
|
* if the app was installed from part of the system where it can't be tampered
|
||||||
* with (e.g. installed apks on disk) then
|
* with (e.g. installed apks on disk) then
|
||||||
*/
|
*/
|
||||||
private static SanitizedFile copyApkToFiles(Context context, File apkFile, boolean verifyHash, String hash, String hashType)
|
private static SanitizedFile copyApkToFiles(Context context, File apkFile, String destinationName, boolean verifyHash, String hash, String hashType)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SanitizedFile sanitizedApkFile = SanitizedFile.knownSanitized(
|
SanitizedFile sanitizedApkFile = new SanitizedFile(context.getFilesDir(), destinationName);
|
||||||
File.createTempFile("install-", ".apk", context.getFilesDir()));
|
|
||||||
|
// Don't think this is necessary, but the docs for FileUtils#copyFile() are not clear
|
||||||
|
// on whether it overwrites destination files (pretty confident it does, as per the docs
|
||||||
|
// in FileUtils#copyFileToDirectory() - which delegates to copyFile()).
|
||||||
|
if (sanitizedApkFile.exists()) {
|
||||||
|
sanitizedApkFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
FileUtils.copyFile(apkFile, sanitizedApkFile);
|
FileUtils.copyFile(apkFile, sanitizedApkFile);
|
||||||
|
|
||||||
// verify copied file's hash with expected hash from Apk class
|
// verify copied file's hash with expected hash from Apk class
|
||||||
|
@ -21,7 +21,7 @@ package org.fdroid.fdroid.installer;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.v4.content.FileProvider;
|
import android.support.v4.content.FileProvider;
|
||||||
@ -49,8 +49,8 @@ public class ApkFileProvider extends FileProvider {
|
|||||||
|
|
||||||
private static final String AUTHORITY = "org.fdroid.fdroid.installer.ApkFileProvider";
|
private static final String AUTHORITY = "org.fdroid.fdroid.installer.ApkFileProvider";
|
||||||
|
|
||||||
public static Uri getSafeUri(Context context, ApplicationInfo appInfo) throws IOException {
|
public static Uri getSafeUri(Context context, PackageInfo packageInfo) throws IOException {
|
||||||
SanitizedFile tempApkFile = ApkCache.copyInstalledApkToFiles(context, appInfo);
|
SanitizedFile tempApkFile = ApkCache.copyInstalledApkToFiles(context, packageInfo);
|
||||||
return getSafeUri(context, tempApkFile, Build.VERSION.SDK_INT >= 24);
|
return getSafeUri(context, tempApkFile, Build.VERSION.SDK_INT >= 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user