1 /*
2  * Copyright (C) 2011 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 android.content.pm.PackageManager;
20 import android.util.SparseBooleanArray;
21 
22 import com.android.server.pm.PackageManagerService.VerificationParams;
23 
24 /**
25  * Tracks the package verification state for a particular package. Each package verification has a
26  * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list
27  * must return affirmative to allow the package to be considered verified. If there are zero
28  * sufficient verifiers, then package verification is considered complete.
29  */
30 class PackageVerificationState {
31     private final VerificationParams mParams;
32 
33     private final SparseBooleanArray mSufficientVerifierUids;
34 
35     private int mRequiredVerifierUid;
36 
37     private boolean mSufficientVerificationComplete;
38 
39     private boolean mSufficientVerificationPassed;
40 
41     private boolean mRequiredVerificationComplete;
42 
43     private boolean mRequiredVerificationPassed;
44 
45     private boolean mExtendedTimeout;
46 
47     private boolean mIntegrityVerificationComplete;
48 
49     /**
50      * Create a new package verification state where {@code requiredVerifierUid} is the user ID for
51      * the package that must reply affirmative before things can continue.
52      */
PackageVerificationState(VerificationParams params)53     PackageVerificationState(VerificationParams params) {
54         mParams = params;
55         mSufficientVerifierUids = new SparseBooleanArray();
56         mExtendedTimeout = false;
57     }
58 
getVerificationParams()59     VerificationParams getVerificationParams() {
60         return mParams;
61     }
62 
63     /** Sets the user ID of the required package verifier. */
setRequiredVerifierUid(int uid)64     void setRequiredVerifierUid(int uid) {
65         mRequiredVerifierUid = uid;
66     }
67 
68     /**
69      * Add a verifier which is added to our sufficient list.
70      *
71      * @param uid user ID of sufficient verifier
72      */
addSufficientVerifier(int uid)73     void addSufficientVerifier(int uid) {
74         mSufficientVerifierUids.put(uid, true);
75     }
76 
77     /**
78      * Should be called when a verification is received from an agent so the state of the package
79      * verification can be tracked.
80      *
81      * @param uid user ID of the verifying agent
82      * @return {@code true} if the verifying agent actually exists in our list
83      */
setVerifierResponse(int uid, int code)84     boolean setVerifierResponse(int uid, int code) {
85         if (uid == mRequiredVerifierUid) {
86             mRequiredVerificationComplete = true;
87             switch (code) {
88                 case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT:
89                     mSufficientVerifierUids.clear();
90                     // fall through
91                 case PackageManager.VERIFICATION_ALLOW:
92                     mRequiredVerificationPassed = true;
93                     break;
94                 default:
95                     mRequiredVerificationPassed = false;
96             }
97             return true;
98         } else {
99             if (mSufficientVerifierUids.get(uid)) {
100                 if (code == PackageManager.VERIFICATION_ALLOW) {
101                     mSufficientVerificationComplete = true;
102                     mSufficientVerificationPassed = true;
103                 }
104 
105                 mSufficientVerifierUids.delete(uid);
106                 if (mSufficientVerifierUids.size() == 0) {
107                     mSufficientVerificationComplete = true;
108                 }
109 
110                 return true;
111             }
112         }
113 
114         return false;
115     }
116 
117     /**
118      * Returns whether verification is considered complete. This means that the required verifier
119      * and at least one of the sufficient verifiers has returned a positive verification.
120      *
121      * @return {@code true} when verification is considered complete
122      */
isVerificationComplete()123     boolean isVerificationComplete() {
124         if (!mRequiredVerificationComplete) {
125             return false;
126         }
127 
128         if (mSufficientVerifierUids.size() == 0) {
129             return true;
130         }
131 
132         return mSufficientVerificationComplete;
133     }
134 
135     /**
136      * Returns whether installation should be allowed. This should only be called after {@link
137      * #isVerificationComplete()} returns {@code true}.
138      *
139      * @return {@code true} if installation should be allowed
140      */
isInstallAllowed()141     boolean isInstallAllowed() {
142         if (!mRequiredVerificationPassed) {
143             return false;
144         }
145 
146         if (mSufficientVerificationComplete) {
147             return mSufficientVerificationPassed;
148         }
149 
150         return true;
151     }
152 
153     /** Extend the timeout for this Package to be verified. */
extendTimeout()154     void extendTimeout() {
155         if (!mExtendedTimeout) {
156             mExtendedTimeout = true;
157         }
158     }
159 
160     /**
161      * Returns whether the timeout was extended for verification.
162      *
163      * @return {@code true} if a timeout was already extended.
164      */
timeoutExtended()165     boolean timeoutExtended() {
166         return mExtendedTimeout;
167     }
168 
setIntegrityVerificationResult(int code)169     void setIntegrityVerificationResult(int code) {
170         mIntegrityVerificationComplete = true;
171     }
172 
isIntegrityVerificationComplete()173     boolean isIntegrityVerificationComplete() {
174         return mIntegrityVerificationComplete;
175     }
176 
areAllVerificationsComplete()177     boolean areAllVerificationsComplete() {
178         return mIntegrityVerificationComplete && isVerificationComplete();
179     }
180 }
181