1 /*
2  * Copyright (C) 2021 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.server.pm;
18 
19 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
20 
21 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
22 import static com.android.server.pm.PackageManagerService.PACKAGE_MIME_TYPE;
23 import static com.android.server.pm.PackageManagerService.TAG;
24 
25 import android.annotation.Nullable;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageInstaller;
29 import android.content.pm.PackageManager;
30 import android.net.Uri;
31 import android.os.Trace;
32 import android.os.UserHandle;
33 import android.provider.Settings;
34 import android.util.Slog;
35 
36 import com.android.internal.annotations.VisibleForTesting;
37 
38 final class VerificationUtils {
39     /**
40      * The default maximum time to wait for the verification agent to return in
41      * milliseconds.
42      */
43     private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
44 
45     /**
46      * The default maximum time to wait for the verification agent to return in
47      * milliseconds.
48      */
49     private static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT = 3 * 1000;
50 
getVerificationTimeout(Context context, boolean streaming)51     public static long getVerificationTimeout(Context context, boolean streaming) {
52         if (streaming) {
53             return getDefaultStreamingVerificationTimeout(context);
54         }
55         return getDefaultVerificationTimeout(context);
56     }
57 
58     /**
59      * Get the default verification agent timeout. Used for both the APK verifier and the
60      * intent filter verifier.
61      *
62      * @return verification timeout in milliseconds
63      */
getDefaultVerificationTimeout(Context context)64     public static long getDefaultVerificationTimeout(Context context) {
65         long timeout = Settings.Global.getLong(context.getContentResolver(),
66                 Settings.Global.PACKAGE_VERIFIER_TIMEOUT, DEFAULT_VERIFICATION_TIMEOUT);
67         // The setting can be used to increase the timeout but not decrease it, since that is
68         // equivalent to disabling the verifier.
69         return Math.max(timeout, DEFAULT_VERIFICATION_TIMEOUT);
70     }
71 
72     /**
73      * Get the default verification agent timeout for streaming installations.
74      *
75      * @return verification timeout in milliseconds
76      */
getDefaultStreamingVerificationTimeout(Context context)77     public static long getDefaultStreamingVerificationTimeout(Context context) {
78         long timeout = Settings.Global.getLong(context.getContentResolver(),
79                 Settings.Global.PACKAGE_STREAMING_VERIFIER_TIMEOUT,
80                 DEFAULT_STREAMING_VERIFICATION_TIMEOUT);
81         // The setting can be used to increase the timeout but not decrease it, since that is
82         // equivalent to disabling the verifier.
83         return Math.max(timeout, DEFAULT_STREAMING_VERIFICATION_TIMEOUT);
84     }
85 
broadcastPackageVerified(int verificationId, Uri packageUri, int verificationCode, @Nullable String rootHashString, int dataLoaderType, UserHandle user, Context context)86     public static void broadcastPackageVerified(int verificationId, Uri packageUri,
87             int verificationCode, @Nullable String rootHashString, int dataLoaderType,
88             UserHandle user, Context context) {
89         final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
90         intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
91         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
92         intent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
93         intent.putExtra(PackageManager.EXTRA_VERIFICATION_RESULT, verificationCode);
94         if (rootHashString != null) {
95             intent.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
96         }
97         intent.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
98 
99         context.sendBroadcastAsUser(intent, user,
100                 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
101     }
102 
103     @VisibleForTesting(visibility = PACKAGE)
processVerificationResponseOnTimeout(int verificationId, PackageVerificationState state, PackageVerificationResponse response, PackageManagerService pms)104     static void processVerificationResponseOnTimeout(int verificationId,
105             PackageVerificationState state, PackageVerificationResponse response,
106             PackageManagerService pms) {
107         state.setVerifierResponseOnTimeout(response.callerUid, response.code);
108         processVerificationResponse(verificationId, state, response.code, "Verification timed out",
109                 pms);
110     }
111 
112     @VisibleForTesting(visibility = PACKAGE)
processVerificationResponse(int verificationId, PackageVerificationState state, PackageVerificationResponse response, PackageManagerService pms)113     static void processVerificationResponse(int verificationId, PackageVerificationState state,
114             PackageVerificationResponse response, PackageManagerService pms) {
115         state.setVerifierResponse(response.callerUid, response.code);
116         processVerificationResponse(verificationId, state, response.code, "Install not allowed",
117                 pms);
118     }
119 
processVerificationResponse(int verificationId, PackageVerificationState state, int verificationResult, String failureReason, PackageManagerService pms)120     private static void processVerificationResponse(int verificationId,
121             PackageVerificationState state, int verificationResult, String failureReason,
122             PackageManagerService pms) {
123         if (!state.isVerificationComplete()) {
124             return;
125         }
126 
127         final VerifyingSession verifyingSession = state.getVerifyingSession();
128         final Uri originUri = verifyingSession != null ? Uri.fromFile(
129                 verifyingSession.mOriginInfo.mResolvedFile) : null;
130 
131         final int verificationCode =
132                 state.isInstallAllowed() ? verificationResult : PackageManager.VERIFICATION_REJECT;
133 
134         if (pms != null && verifyingSession != null) {
135             VerificationUtils.broadcastPackageVerified(verificationId, originUri,
136                     verificationCode, null,
137                     verifyingSession.getDataLoaderType(), verifyingSession.getUser(),
138                     pms.mContext);
139         }
140 
141         if (state.isInstallAllowed()) {
142             Slog.i(TAG, "Continuing with installation of " + originUri);
143         } else {
144             String errorMsg = failureReason + " for " + originUri;
145             Slog.i(TAG, errorMsg);
146             if (verifyingSession != null) {
147                 verifyingSession.setReturnCode(
148                         PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
149             }
150         }
151 
152         if (pms != null && state.areAllVerificationsComplete()) {
153             pms.mPendingVerification.remove(verificationId);
154         }
155 
156         Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
157 
158         if (verifyingSession != null) {
159             verifyingSession.handleVerificationFinished();
160         }
161     }
162 }
163