1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.managedprovisioning.task; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import static java.util.Objects.requireNonNull; 22 23 import android.content.Context; 24 import android.content.pm.PackageInfo; 25 import android.content.pm.PackageManager; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.managedprovisioning.analytics.MetricsWriterFactory; 29 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 30 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 31 import com.android.managedprovisioning.common.ProvisionLogger; 32 import com.android.managedprovisioning.common.SettingsFacade; 33 import com.android.managedprovisioning.common.Utils; 34 import com.android.managedprovisioning.model.PackageDownloadInfo; 35 import com.android.managedprovisioning.model.ProvisioningParams; 36 37 import java.io.File; 38 39 /** 40 * Verifies the management app apk downloaded previously in {@link DownloadPackageTask}. 41 * 42 * <p>The first check verifies that a {@link android.app.admin.DeviceAdminReceiver} is present in 43 * the apk and that it corresponds to the one provided via 44 * {@link ProvisioningParams#deviceAdminComponentName}.</p> 45 * 46 * <p>The second check verifies that the package or signature checksum matches the ones given via 47 * {@link PackageDownloadInfo#packageChecksum} or {@link PackageDownloadInfo#signatureChecksum} 48 * respectively. The package checksum takes priority in case both are present.</p> 49 */ 50 public class VerifyAdminPackageTask extends AbstractProvisioningTask { 51 public static final int ERROR_HASH_MISMATCH = 0; 52 public static final int ERROR_DEVICE_ADMIN_MISSING = 1; 53 54 private final Utils mUtils; 55 private final PackageLocationProvider mDownloadLocationProvider; 56 private final PackageManager mPackageManager; 57 private final PackageDownloadInfo mPackageDownloadInfo; 58 private final ChecksumUtils mChecksumUtils; 59 VerifyAdminPackageTask( PackageLocationProvider downloadLocationProvider, Context context, ProvisioningParams params, PackageDownloadInfo packageDownloadInfo, Callback callback)60 public VerifyAdminPackageTask( 61 PackageLocationProvider downloadLocationProvider, 62 Context context, 63 ProvisioningParams params, 64 PackageDownloadInfo packageDownloadInfo, 65 Callback callback) { 66 this(new Utils(), downloadLocationProvider, context, params, packageDownloadInfo, callback, 67 new ProvisioningAnalyticsTracker( 68 MetricsWriterFactory.getMetricsWriter(context, new SettingsFacade()), 69 new ManagedProvisioningSharedPreferences(context)), 70 new ChecksumUtils(new Utils())); 71 } 72 73 @VisibleForTesting VerifyAdminPackageTask( Utils utils, PackageLocationProvider downloadLocationProvider, Context context, ProvisioningParams params, PackageDownloadInfo packageDownloadInfo, Callback callback, ProvisioningAnalyticsTracker provisioningAnalyticsTracker, ChecksumUtils checksumUtils)74 VerifyAdminPackageTask( 75 Utils utils, 76 PackageLocationProvider downloadLocationProvider, 77 Context context, 78 ProvisioningParams params, 79 PackageDownloadInfo packageDownloadInfo, 80 Callback callback, 81 ProvisioningAnalyticsTracker provisioningAnalyticsTracker, 82 ChecksumUtils checksumUtils) { 83 super(context, params, callback, provisioningAnalyticsTracker); 84 85 mUtils = checkNotNull(utils); 86 mDownloadLocationProvider = checkNotNull(downloadLocationProvider); 87 mPackageManager = mContext.getPackageManager(); 88 mPackageDownloadInfo = checkNotNull(packageDownloadInfo); 89 mChecksumUtils = requireNonNull(checksumUtils); 90 } 91 92 @Override run(int userId)93 public void run(int userId) { 94 final File packageLocation = mDownloadLocationProvider.getPackageLocation(); 95 if (packageLocation == null) { 96 ProvisionLogger.logw("VerifyPackageTask invoked, but package is null"); 97 success(); 98 return; 99 } 100 ProvisionLogger.logi("Verifying package from location " + packageLocation.getAbsolutePath() 101 + " for user " + userId); 102 103 PackageInfo packageInfo = mPackageManager.getPackageArchiveInfo( 104 packageLocation.getAbsolutePath(), 105 PackageManager.GET_SIGNATURES | PackageManager.GET_RECEIVERS); 106 String packageName = mProvisioningParams.inferDeviceAdminPackageName(); 107 // Device admin package name can't be null 108 if (packageInfo == null || packageName == null) { 109 ProvisionLogger.loge("Device admin package info or name is null"); 110 error(ERROR_DEVICE_ADMIN_MISSING); 111 return; 112 } 113 114 if (mUtils.findDeviceAdminInPackageInfo(packageName, 115 mProvisioningParams.deviceAdminComponentName, packageInfo) == null) { 116 error(ERROR_DEVICE_ADMIN_MISSING); 117 return; 118 } 119 120 if (mPackageDownloadInfo.packageChecksum.length > 0) { 121 if (!mChecksumUtils.doesPackageHashMatch( 122 packageLocation.getAbsolutePath(), mPackageDownloadInfo.packageChecksum)) { 123 error(ERROR_HASH_MISMATCH); 124 return; 125 } 126 } else { 127 if (!mChecksumUtils.doesASignatureHashMatch( 128 packageInfo, mPackageDownloadInfo.signatureChecksum)) { 129 error(ERROR_HASH_MISMATCH); 130 return; 131 } 132 } 133 134 success(); 135 } 136 } 137