文章目录
开发平台基本信息
芯片: MT8766
版本: Android 12
kernel: msm-4.19
问题描述
在项目开发的时候,经常有一些客户,要求系统安装应用的时候需要进行验签;也就是系统默认不允许任何应用安装,应用安装的时候,会读取系统目录下存放的公钥,然后拿着公钥去解析需要安装的应用,只有匹配上签名的应用才能正常安装。
解决方法
- 应用验签的算法各种各样,也比较隐私,这里就不做展示了;这里仅提供应用安装拦截的方法;可以在安装的地方,读取设定的白名单,只有白名单内的应用才允许安装;或者读取设定的黑名单,除了黑名单内的应用禁止安装,其他的应用正常安装。具体怎么使用,就看具体需求。
java
--- a/frameworks/base/core/api/system-current.txt
+++ b/frameworks/base/core/api/system-current.txt
@@ -8892,6 +8892,7 @@ package android.permission {
method public int checkDeviceIdentifierAccess(@Nullable String, @Nullable String, @Nullable String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public java.util.Set<java.lang.String> getAutoRevokeExemptionGrantedPackages();
method @NonNull @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public java.util.Set<java.lang.String> getAutoRevokeExemptionRequestedPackages();
+ method public android.content.Context getPermissionContext();
method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public int getRuntimePermissionsVersion();
method @NonNull public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
--- a/frameworks/base/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/frameworks/base/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -132,6 +132,17 @@ import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.content.Context;
+import android.util.Log;
+
@@ -275,7 +288,7 @@ public class ParsingPackageUtils {
return new ParsingPackageImpl(packageName, baseApkPath, path,
manifestArray);
}
- });
+ },mContext);
try {
result = parser.parsePackage(input, file, parseFlags);
if (result.isError()) {
@@ -309,16 +322,19 @@ public class ParsingPackageUtils {
@NonNull
private List<PermissionManager.SplitPermissionInfo> mSplitPermissionInfos;
private Callback mCallback;
+ private static Context mContext;
public ParsingPackageUtils(boolean onlyCoreApps, String[] separateProcesses,
DisplayMetrics displayMetrics,
@NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
- @NonNull Callback callback) {
+ @NonNull Callback callback,
+ @NonNull Context context) {
mOnlyCoreApps = onlyCoreApps;
mSeparateProcesses = separateProcesses;
mDisplayMetrics = displayMetrics;
mSplitPermissionInfos = splitPermissions;
mCallback = callback;
+ mContext = context;
}
@@ -3043,6 +3059,11 @@ public class ParsingPackageUtils {
@NonNull SigningDetails existingSigningDetails, int targetSdk) {
int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
targetSdk);
+ boolean isAllow = false;
+
if (isStaticSharedLibrary) {
// must use v2 signing scheme
minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
@@ -3056,7 +3077,71 @@ public class ParsingPackageUtils {
verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
baseCodePath, SigningDetails.SignatureSchemeVersion.JAR);
} else {
- verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme);
+ String whiteListValue = null;
+ String[] whiteListArray = null;
+ if(mContext != null){
+ if(mContext.getContentResolver()!=null){
+ whiteListValue = Settings.System.getString(mContext.getContentResolver(), Settings.System.KEY_CERT_WHITE_LIST_ACTION);
+ }
+
+ if (whiteListValue != null){
+ int count = 0;
+ String packageName = null;
+ PackageManager pm = mContext.getPackageManager();
+ PackageInfo info = pm.getPackageArchiveInfo(baseCodePath, PackageManager.GET_ACTIVITIES);
+ if(info!=null){
+ ApplicationInfo appInfo = info.applicationInfo;
+ packageName = appInfo.packageName; //得到安装包名称
+ Log.d(TAG, "packageName : " + packageName);
+
+ whiteListArray = whiteListValue.split(";");
+ for(count=0; count < whiteListArray.length; count++){
+ if(packageName.equals(whiteListArray[count])){
+ isAllow = true;
+ break;
+ }else{
+ isAllow = false;
+ }
+ }
+ }
+ }else{
+ Log.d(TAG, "whiteList is null");
+ }
+ }
+ if (isAllow){
+ verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme);
+ }else {
+ throw new PackageParserException(
+ INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
+ baseCodePath + " has mismatched certificates");
+ }
}
} catch (PackageParserException e) {
return input.error(PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES,
--- a/frameworks/base/core/java/android/permission/PermissionManager.java
+++ b/frameworks/base/core/java/android/permission/PermissionManager.java
@@ -161,6 +161,10 @@ public final class PermissionManager {
mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
}
+ public Context getPermissionContext(){
+ return mContext;
+ }
+
--- a/frameworks/base/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/frameworks/base/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -129,7 +129,7 @@ public class PackageParser2 implements AutoCloseable {
mCacher = cacheDir == null ? null : new PackageCacher(cacheDir);
parsingUtils = new ParsingPackageUtils(onlyCoreApps, separateProcesses, displayMetrics,
- splitPermissions, callback);
+ splitPermissions, callback,permissionManager.getPermissionContext());
ParseInput.Callback enforcementCallback = (changeId, packageName, targetSdkVersion) -> {
ApplicationInfo appInfo = mSharedAppInfo.get();
主要就是在应用安装的那个类里面拿不到上下文,所以,只能通过构造类的时候,从上一层拿到上下文之后,再传进来。拿到上下文之后就可以获取Setting数据库,读出黑白名单列表,再跟当前安装的包名做对比,判断当前应用是否安装。