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