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 /** 23 * Tracks the package verification state for a particular package. Each package verification has a 24 * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list 25 * must return affirmative to allow the package to be considered verified. If there are zero 26 * sufficient verifiers, then package verification is considered complete. 27 */ 28 class PackageVerificationState { 29 private final VerifyingSession mVerifyingSession; 30 31 private final SparseBooleanArray mSufficientVerifierUids; 32 33 private final SparseBooleanArray mRequiredVerifierUids; 34 private final SparseBooleanArray mUnrespondedRequiredVerifierUids; 35 36 private final SparseBooleanArray mExtendedTimeoutUids; 37 38 private boolean mSufficientVerificationComplete; 39 40 private boolean mSufficientVerificationPassed; 41 42 private boolean mRequiredVerificationComplete; 43 44 private boolean mRequiredVerificationPassed; 45 46 /** 47 * Create a new package verification state where {@code requiredVerifierUid} is the user ID for 48 * the package that must reply affirmative before things can continue. 49 */ PackageVerificationState(VerifyingSession verifyingSession)50 PackageVerificationState(VerifyingSession verifyingSession) { 51 mVerifyingSession = verifyingSession; 52 mSufficientVerifierUids = new SparseBooleanArray(); 53 mRequiredVerifierUids = new SparseBooleanArray(); 54 mUnrespondedRequiredVerifierUids = new SparseBooleanArray(); 55 mExtendedTimeoutUids = new SparseBooleanArray(); 56 mRequiredVerificationComplete = false; 57 mRequiredVerificationPassed = true; 58 } 59 getVerifyingSession()60 VerifyingSession getVerifyingSession() { 61 return mVerifyingSession; 62 } 63 64 /** Add the user ID of the required package verifier. */ addRequiredVerifierUid(int uid)65 void addRequiredVerifierUid(int uid) { 66 mRequiredVerifierUids.put(uid, true); 67 mUnrespondedRequiredVerifierUids.put(uid, true); 68 } 69 70 /** Returns true if the uid a required verifier. */ checkRequiredVerifierUid(int uid)71 boolean checkRequiredVerifierUid(int uid) { 72 return mRequiredVerifierUids.get(uid, false); 73 } 74 75 /** 76 * Add a verifier which is added to our sufficient list. 77 * 78 * @param uid user ID of sufficient verifier 79 */ addSufficientVerifier(int uid)80 void addSufficientVerifier(int uid) { 81 mSufficientVerifierUids.put(uid, true); 82 } 83 84 /** Returns true if the uid a sufficient verifier. */ checkSufficientVerifierUid(int uid)85 boolean checkSufficientVerifierUid(int uid) { 86 return mSufficientVerifierUids.get(uid, false); 87 } 88 setVerifierResponseOnTimeout(int uid, int code)89 void setVerifierResponseOnTimeout(int uid, int code) { 90 if (!checkRequiredVerifierUid(uid)) { 91 return; 92 } 93 94 // Timeout, not waiting for the sufficient verifiers anymore. 95 mSufficientVerifierUids.clear(); 96 97 // Only if unresponded. 98 if (mUnrespondedRequiredVerifierUids.get(uid, false)) { 99 setVerifierResponse(uid, code); 100 } 101 } 102 103 /** 104 * Should be called when a verification is received from an agent so the state of the package 105 * verification can be tracked. 106 * 107 * @param uid user ID of the verifying agent 108 */ setVerifierResponse(int uid, int code)109 void setVerifierResponse(int uid, int code) { 110 if (mRequiredVerifierUids.get(uid)) { 111 switch (code) { 112 case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT: 113 mSufficientVerifierUids.clear(); 114 // fall through 115 case PackageManager.VERIFICATION_ALLOW: 116 // Two possible options: 117 // - verification result is true, 118 // - another verifier set it to false. 119 // In both cases we don't need to assign anything, just exit. 120 break; 121 default: 122 mRequiredVerificationPassed = false; 123 // Required verifier rejected, no need to wait for the rest. 124 mUnrespondedRequiredVerifierUids.clear(); 125 mSufficientVerifierUids.clear(); 126 mExtendedTimeoutUids.clear(); 127 } 128 129 // Responded, no need to extend timeout. 130 mExtendedTimeoutUids.delete(uid); 131 132 mUnrespondedRequiredVerifierUids.delete(uid); 133 if (mUnrespondedRequiredVerifierUids.size() == 0) { 134 mRequiredVerificationComplete = true; 135 } 136 } else if (mSufficientVerifierUids.get(uid)) { 137 if (code == PackageManager.VERIFICATION_ALLOW) { 138 mSufficientVerificationPassed = true; 139 mSufficientVerificationComplete = true; 140 } 141 142 mSufficientVerifierUids.delete(uid); 143 if (mSufficientVerifierUids.size() == 0) { 144 mSufficientVerificationComplete = true; 145 } 146 } 147 } 148 149 /** 150 * Mark the session as passed required verification. 151 */ passRequiredVerification()152 void passRequiredVerification() { 153 if (mUnrespondedRequiredVerifierUids.size() > 0) { 154 throw new RuntimeException("Required verifiers still present."); 155 } 156 mRequiredVerificationPassed = true; 157 mRequiredVerificationComplete = true; 158 } 159 160 /** 161 * Returns whether verification is considered complete. This means that the required verifier 162 * and at least one of the sufficient verifiers has returned a positive verification. 163 * 164 * @return {@code true} when verification is considered complete 165 */ isVerificationComplete()166 boolean isVerificationComplete() { 167 if (!mRequiredVerificationComplete) { 168 return false; 169 } 170 171 if (mSufficientVerifierUids.size() == 0) { 172 return true; 173 } 174 175 return mSufficientVerificationComplete; 176 } 177 178 /** 179 * Returns whether installation should be allowed. This should only be called after {@link 180 * #isVerificationComplete()} returns {@code true}. 181 * 182 * @return {@code true} if installation should be allowed 183 */ isInstallAllowed()184 boolean isInstallAllowed() { 185 if (!mRequiredVerificationComplete || !mRequiredVerificationPassed) { 186 return false; 187 } 188 189 if (mSufficientVerificationComplete) { 190 return mSufficientVerificationPassed; 191 } 192 193 return true; 194 } 195 196 /** Extend the timeout for this Package to be verified. */ extendTimeout(int uid)197 boolean extendTimeout(int uid) { 198 if (!checkRequiredVerifierUid(uid) || timeoutExtended(uid)) { 199 return false; 200 } 201 mExtendedTimeoutUids.append(uid, true); 202 return true; 203 } 204 205 /** 206 * Returns whether the timeout was extended for verification. 207 * 208 * @return {@code true} if a timeout was already extended. 209 */ timeoutExtended(int uid)210 boolean timeoutExtended(int uid) { 211 return mExtendedTimeoutUids.get(uid, false); 212 } 213 areAllVerificationsComplete()214 boolean areAllVerificationsComplete() { 215 return isVerificationComplete(); 216 } 217 } 218