1 /* 2 * Copyright (C) 2020 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.verify.domain; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.UserIdInt; 24 import android.content.Intent; 25 import android.content.pm.IntentFilterVerificationInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.PackageManager.NameNotFoundException; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.verify.domain.DomainVerificationInfo; 30 import android.content.pm.verify.domain.DomainVerificationManager; 31 import android.content.pm.verify.domain.DomainVerificationState; 32 import android.os.Binder; 33 import android.os.UserHandle; 34 import android.util.IndentingPrintWriter; 35 import android.util.Pair; 36 37 import com.android.modules.utils.TypedXmlPullParser; 38 import com.android.modules.utils.TypedXmlSerializer; 39 import com.android.server.pm.Computer; 40 import com.android.server.pm.PackageSetting; 41 import com.android.server.pm.Settings; 42 import com.android.server.pm.pkg.PackageStateInternal; 43 import com.android.server.pm.verify.domain.models.DomainVerificationPkgState; 44 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy; 45 46 import org.xmlpull.v1.XmlPullParserException; 47 48 import java.io.IOException; 49 import java.util.List; 50 import java.util.Set; 51 import java.util.UUID; 52 import java.util.function.Function; 53 54 public interface DomainVerificationManagerInternal { 55 56 UUID DISABLED_ID = new UUID(0, 0); 57 58 /** 59 * The app was not installed for the user. 60 */ 61 int APPROVAL_LEVEL_NOT_INSTALLED = -4; 62 63 /** 64 * The app was not enabled for the user. 65 */ 66 int APPROVAL_LEVEL_DISABLED = -3; 67 68 /** 69 * The app has not declared this domain in a valid web intent-filter in their manifest, and so 70 * would never be able to be approved for this domain. 71 */ 72 int APPROVAL_LEVEL_UNDECLARED = -2; 73 74 /** 75 * The app has declared this domain as a valid autoVerify domain, but it failed or has not 76 * succeeded verification. 77 */ 78 int APPROVAL_LEVEL_UNVERIFIED = -1; 79 80 /** 81 * The app has not been approved for this domain and should never be able to open it through 82 * an implicit web intent. 83 */ 84 int APPROVAL_LEVEL_NONE = 0; 85 86 /** 87 * The app has been approved through the legacy 88 * {@link PackageManager#updateIntentVerificationStatusAsUser(String, int, int)} API, which has 89 * been preserved for migration purposes, but is otherwise ignored. Corresponds to 90 * {@link PackageManager#INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK} and 91 * {@link PackageManager#INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK}. 92 * 93 * This should be used as the cutoff for showing a picker if no better approved app exists 94 * during the legacy transition period. 95 * 96 * TODO(b/177923646): The legacy values can be removed once the Settings API changes are 97 * shipped. These values are not stable, so just deleting the constant and shifting others is 98 * fine. 99 */ 100 int APPROVAL_LEVEL_LEGACY_ASK = 1; 101 102 /** 103 * The app has been approved through the legacy 104 * {@link PackageManager#updateIntentVerificationStatusAsUser(String, int, int)} API, which has 105 * been preserved for migration purposes, but is otherwise ignored. Corresponds to 106 * {@link PackageManager#INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS}. 107 */ 108 int APPROVAL_LEVEL_LEGACY_ALWAYS = 2; 109 110 /** 111 * The app has been chosen by the user through 112 * {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set, boolean)}, 113 * indicating an explicit choice to use this app to open an unverified domain. 114 */ 115 int APPROVAL_LEVEL_SELECTION = 3; 116 117 /** 118 * The app is approved through the digital asset link statement being hosted at the domain 119 * it is capturing. This is set through 120 * {@link DomainVerificationManager#setDomainVerificationStatus(UUID, Set, int)} by 121 * the domain verification agent on device. 122 */ 123 int APPROVAL_LEVEL_VERIFIED = 4; 124 125 /** 126 * The app has been installed as an instant app, which grants it total authority on the domains 127 * that it declares. It is expected that the package installer validate the domains the app 128 * declares against the digital asset link statements before allowing it to be installed. 129 * 130 * The user is still able to disable instant app link handling through 131 * {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String, boolean)}. 132 */ 133 int APPROVAL_LEVEL_INSTANT_APP = 5; 134 135 /** 136 * Defines the possible values for 137 * {@link #approvalLevelForDomain(PackageStateInternal, Intent, int, int)} which sorts packages 138 * by approval priority. A higher numerical value means the package should override all lower 139 * values. This means that comparison using less/greater than IS valid. 140 * 141 * Negative values are possible, used for tracking specific reasons for why an app doesn't have 142 * approval. 143 */ 144 @IntDef({ 145 APPROVAL_LEVEL_NOT_INSTALLED, 146 APPROVAL_LEVEL_DISABLED, 147 APPROVAL_LEVEL_UNDECLARED, 148 APPROVAL_LEVEL_UNVERIFIED, 149 APPROVAL_LEVEL_NONE, 150 APPROVAL_LEVEL_LEGACY_ASK, 151 APPROVAL_LEVEL_LEGACY_ALWAYS, 152 APPROVAL_LEVEL_SELECTION, 153 APPROVAL_LEVEL_VERIFIED, 154 APPROVAL_LEVEL_INSTANT_APP 155 }) 156 @interface ApprovalLevel { 157 } 158 approvalLevelToDebugString(@pprovalLevel int level)159 static String approvalLevelToDebugString(@ApprovalLevel int level) { 160 switch (level) { 161 case APPROVAL_LEVEL_NOT_INSTALLED: 162 return "NOT_INSTALLED"; 163 case APPROVAL_LEVEL_DISABLED: 164 return "DISABLED"; 165 case APPROVAL_LEVEL_UNDECLARED: 166 return "UNDECLARED"; 167 case APPROVAL_LEVEL_UNVERIFIED: 168 return "UNVERIFIED"; 169 case APPROVAL_LEVEL_NONE: 170 return "NONE"; 171 case APPROVAL_LEVEL_LEGACY_ASK: 172 return "LEGACY_ASK"; 173 case APPROVAL_LEVEL_LEGACY_ALWAYS: 174 return "LEGACY_ALWAYS"; 175 case APPROVAL_LEVEL_SELECTION: 176 return "USER_SELECTION"; 177 case APPROVAL_LEVEL_VERIFIED: 178 return "VERIFIED"; 179 case APPROVAL_LEVEL_INSTANT_APP: 180 return "INSTANT_APP"; 181 default: 182 return "UNKNOWN"; 183 } 184 } 185 186 /** @see DomainVerificationManager#getDomainVerificationInfo(String) */ 187 @Nullable 188 @RequiresPermission(anyOf = { 189 android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, 190 android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION 191 }) getDomainVerificationInfo(@onNull String packageName)192 DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName) 193 throws NameNotFoundException; 194 195 /** 196 * Generate a new domain set ID to be used for attaching new packages. 197 */ 198 @NonNull generateNewId()199 UUID generateNewId(); 200 setConnection(@onNull Connection connection)201 void setConnection(@NonNull Connection connection); 202 203 @NonNull getProxy()204 DomainVerificationProxy getProxy(); 205 206 /** 207 * Update the proxy implementation that talks to the domain verification agent on device. The 208 * default proxy is a stub that does nothing, and broadcast functionality will only work once a 209 * real implementation is attached. 210 */ setProxy(@onNull DomainVerificationProxy proxy)211 void setProxy(@NonNull DomainVerificationProxy proxy); 212 213 /** 214 * @see DomainVerificationProxy.BaseConnection#runMessage(int, Object) 215 */ runMessage(int messageCode, Object object)216 boolean runMessage(int messageCode, Object object); 217 218 /** 219 * Restores or creates internal state for the new package. This can either be from scanning a 220 * package at boot, or a truly new installation on the device. It is expected that the {@link 221 * PackageSetting#getDomainSetId()} already be set to the correct value. 222 * <p> 223 * If this is from scan, there should be a pending state that was previous read using {@link 224 * #readSettings(TypedXmlPullParser)}, which will be attached as-is to the package. In this 225 * case, a broadcast will not be sent to the domain verification agent on device, as it is 226 * assumed nothing has changed since the device rebooted. 227 * <p> 228 * If this is a new install, state will be restored from a previous call to {@link 229 * #restoreSettings(Computer, TypedXmlPullParser)}, or a new one will be generated. In either case, a 230 * broadcast will be sent to the domain verification agent so it may re-run any verification 231 * logic for the newly associated domains. 232 * <p> 233 * This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal 234 * lock. This should never be called from within the domain verification classes themselves. 235 * <p> 236 * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be 237 * handled by the caller. 238 */ addPackage(@onNull PackageStateInternal newPkgSetting)239 void addPackage(@NonNull PackageStateInternal newPkgSetting); 240 241 /** 242 * Migrates verification state from a previous install to a new one. It is expected that the 243 * {@link PackageStateInternal#getDomainSetId()} already be set to the correct value, usually from 244 * {@link #generateNewId()}. This will preserve {@link DomainVerificationState#STATE_SUCCESS} 245 * domains under the assumption that the new package will pass the same server side config as 246 * the previous package, as they have matching signatures. 247 * <p> 248 * This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal 249 * lock. This should never be called from within the domain verification classes themselves. 250 * <p> 251 * This will NOT call {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. That must be 252 * handled by the caller. 253 */ migrateState(@onNull PackageStateInternal oldPkgSetting, @NonNull PackageStateInternal newPkgSetting)254 void migrateState(@NonNull PackageStateInternal oldPkgSetting, 255 @NonNull PackageStateInternal newPkgSetting); 256 257 /** 258 * Serializes the entire internal state. This is equivalent to a full backup of the existing 259 * verification state. This write includes legacy state, as a sibling tag the modern state. 260 * 261 * @param snapshot 262 * @param includeSignatures Whether to include the package signatures in the output, mainly 263 * used for backing up the user settings and ensuring they're 264 * re-attached to the same package. 265 * @param userId The user to write out. Supports {@link UserHandle#USER_ALL} if all users 266 */ writeSettings(@onNull Computer snapshot, @NonNull TypedXmlSerializer serializer, boolean includeSignatures, @UserIdInt int userId)267 void writeSettings(@NonNull Computer snapshot, @NonNull TypedXmlSerializer serializer, 268 boolean includeSignatures, @UserIdInt int userId) throws IOException; 269 270 /** 271 * Read back a list of {@link DomainVerificationPkgState}s previously written by {@link 272 * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the 273 * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} tag has already been entered. 274 * <p> 275 * This is expected to only be used to re-attach states for packages already known to be on the 276 * device. If restoring from a backup, use {@link #restoreSettings(Computer, TypedXmlPullParser)}. 277 */ readSettings(@onNull Computer snapshot, @NonNull TypedXmlPullParser parser)278 void readSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser) 279 throws IOException, XmlPullParserException; 280 281 /** 282 * Read back data from 283 * {@link DomainVerificationLegacySettings#writeSettings(TypedXmlSerializer)}. Assumes that the 284 * {@link DomainVerificationLegacySettings#TAG_DOMAIN_VERIFICATIONS_LEGACY} tag has already 285 * been entered. 286 */ readLegacySettings(@onNull TypedXmlPullParser parser)287 void readLegacySettings(@NonNull TypedXmlPullParser parser) 288 throws IOException, XmlPullParserException; 289 290 /** 291 * Remove all state for the given package. 292 */ clearPackage(@onNull String packageName)293 void clearPackage(@NonNull String packageName); 294 295 /** 296 * Remove all state for the given package for the given user. 297 */ clearPackageForUser(@onNull String packageName, @UserIdInt int userId)298 void clearPackageForUser(@NonNull String packageName, @UserIdInt int userId); 299 300 /** 301 * Delete all the state for a user. This can be because the user has been removed from the 302 * device, or simply that the state for a user should be deleted. 303 */ clearUser(@serIdInt int userId)304 void clearUser(@UserIdInt int userId); 305 306 /** 307 * Restore a list of {@link DomainVerificationPkgState}s previously written by {@link 308 * #writeSettings(Computer, TypedXmlSerializer, boolean, int)}. Assumes that the 309 * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} 310 * tag has already been entered. 311 * <p> 312 * This is <b>only</b> for restore, and will override package states, ignoring if their {@link 313 * DomainVerificationInfo#getIdentifier()}s match. It's expected that any restored domains 314 * marked 315 * as success verify against the server correctly, although the verification agent may decide 316 * to 317 * re-verify them when it gets the chance. 318 */ 319 /* 320 * TODO(b/170746586): Figure out how to verify that package signatures match at snapshot time 321 * and restore time. 322 */ restoreSettings(@onNull Computer snapshot, @NonNull TypedXmlPullParser parser)323 void restoreSettings(@NonNull Computer snapshot, @NonNull TypedXmlPullParser parser) 324 throws IOException, XmlPullParserException; 325 326 /** 327 * Set aside a legacy {@link IntentFilterVerificationInfo} that will be restored to a pending 328 * {@link DomainVerificationPkgState} once it's added through 329 * {@link #addPackage(PackageSetting)}. 330 */ addLegacySetting(@onNull String packageName, @NonNull IntentFilterVerificationInfo info)331 void addLegacySetting(@NonNull String packageName, @NonNull IntentFilterVerificationInfo info); 332 333 /** 334 * Set aside a legacy user selection that will be restored to a pending 335 * {@link DomainVerificationPkgState} once it's added through 336 * {@link #addPackage(PackageSetting)}. 337 * 338 * @return true if state changed successfully 339 */ setLegacyUserState(@onNull String packageName, @UserIdInt int userId, int state)340 boolean setLegacyUserState(@NonNull String packageName, @UserIdInt int userId, int state); 341 342 /** 343 * Until the legacy APIs are entirely removed, returns the legacy state from the previously 344 * written info stored in {@link Settings}. 345 */ getLegacyState(@onNull String packageName, @UserIdInt int userId)346 int getLegacyState(@NonNull String packageName, @UserIdInt int userId); 347 348 /** 349 * Print the verification state and user selection state of a package. 350 * 351 * @param snapshot 352 * @param packageName the package whose state to change, or all packages if none is 353 * specified 354 * @param userId the specific user to print, or null to skip printing user selection 355 * states, supports {@link UserHandle#USER_ALL} 356 */ printState(@onNull Computer snapshot, @NonNull IndentingPrintWriter writer, @Nullable String packageName, @Nullable @UserIdInt Integer userId)357 void printState(@NonNull Computer snapshot, @NonNull IndentingPrintWriter writer, 358 @Nullable String packageName, @Nullable @UserIdInt Integer userId) 359 throws NameNotFoundException; 360 361 @NonNull getShell()362 DomainVerificationShell getShell(); 363 364 @NonNull getCollector()365 DomainVerificationCollector getCollector(); 366 367 /** 368 * Filters the provided list down to the {@link ResolveInfo} objects that should be allowed 369 * to open the domain inside the {@link Intent}. It is possible for no packages represented in 370 * the list to be approved, in which case an empty list will be returned. 371 * 372 * @return the filtered list and the corresponding approval level 373 */ 374 @NonNull filterToApprovedApp(@onNull Intent intent, @NonNull List<ResolveInfo> infos, @UserIdInt int userId, @NonNull Function<String, PackageStateInternal> pkgSettingFunction)375 Pair<List<ResolveInfo>, Integer> filterToApprovedApp(@NonNull Intent intent, 376 @NonNull List<ResolveInfo> infos, @UserIdInt int userId, 377 @NonNull Function<String, PackageStateInternal> pkgSettingFunction); 378 379 /** 380 * Check at what precedence a package resolving a URI is approved to takeover the domain. 381 * This can be because the domain was auto-verified for the package, or if the user manually 382 * chose to enable the domain for the package. If an app is auto-verified, it will be 383 * preferred over apps that were manually selected. 384 * 385 * NOTE: This should not be used for filtering intent resolution. See 386 * {@link #filterToApprovedApp(Intent, List, int, Function)} for that. 387 */ 388 @ApprovalLevel approvalLevelForDomain(@onNull PackageStateInternal pkgSetting, @NonNull Intent intent, @PackageManager.ResolveInfoFlagsBits long resolveInfoFlags, @UserIdInt int userId)389 int approvalLevelForDomain(@NonNull PackageStateInternal pkgSetting, @NonNull Intent intent, 390 @PackageManager.ResolveInfoFlagsBits long resolveInfoFlags, @UserIdInt int userId); 391 392 /** 393 * @return the domain verification set ID for the given package, or null if the ID is 394 * unavailable 395 */ 396 @Nullable getDomainVerificationInfoId(@onNull String packageName)397 UUID getDomainVerificationInfoId(@NonNull String packageName); 398 399 @DomainVerificationManager.Error 400 @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) setDomainVerificationStatusInternal(int callingUid, @NonNull UUID domainSetId, @NonNull Set<String> domains, int state)401 int setDomainVerificationStatusInternal(int callingUid, @NonNull UUID domainSetId, 402 @NonNull Set<String> domains, int state) throws NameNotFoundException; 403 404 405 interface Connection extends DomainVerificationEnforcer.Callback { 406 407 /** 408 * Notify that a settings change has been made and that eventually 409 * {@link #writeSettings(Computer, TypedXmlSerializer, boolean, int)} should be invoked by the parent. 410 */ scheduleWriteSettings()411 void scheduleWriteSettings(); 412 413 /** 414 * Delegate to {@link Binder#getCallingUid()} to allow mocking in tests. 415 */ getCallingUid()416 int getCallingUid(); 417 418 /** 419 * Delegate to {@link UserHandle#getCallingUserId()} to allow mocking in tests. 420 */ 421 @UserIdInt getCallingUserId()422 int getCallingUserId(); 423 424 /** 425 * @see DomainVerificationProxy.BaseConnection#schedule(int, java.lang.Object) 426 */ schedule(int code, @Nullable Object object)427 void schedule(int code, @Nullable Object object); 428 429 @UserIdInt getAllUserIds()430 int[] getAllUserIds(); 431 432 @NonNull snapshot()433 Computer snapshot(); 434 } 435 } 436