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.PackageSettingsSnapshotProvider; 29 import android.content.pm.ResolveInfo; 30 import android.content.pm.verify.domain.DomainVerificationInfo; 31 import android.content.pm.verify.domain.DomainVerificationManager; 32 import android.content.pm.verify.domain.DomainVerificationState; 33 import android.os.Binder; 34 import android.os.UserHandle; 35 import android.util.IndentingPrintWriter; 36 import android.util.Pair; 37 import android.util.TypedXmlPullParser; 38 import android.util.TypedXmlSerializer; 39 40 import com.android.server.pm.PackageManagerService; 41 import com.android.server.pm.PackageSetting; 42 import com.android.server.pm.Settings; 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(PackageSetting, Intent, List, 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(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(TypedXmlSerializer, boolean, int)}. That must be 237 * handled by the caller. 238 */ addPackage(@onNull PackageSetting newPkgSetting)239 void addPackage(@NonNull PackageSetting newPkgSetting); 240 241 /** 242 * Migrates verification state from a previous install to a new one. It is expected that the 243 * {@link PackageSetting#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(TypedXmlSerializer, boolean, int)}. That must be 252 * handled by the caller. 253 */ migrateState(@onNull PackageSetting oldPkgSetting, @NonNull PackageSetting newPkgSetting)254 void migrateState(@NonNull PackageSetting oldPkgSetting, @NonNull PackageSetting newPkgSetting); 255 256 /** 257 * Serializes the entire internal state. This is equivalent to a full backup of the existing 258 * verification state. This write includes legacy state, as a sibling tag the modern state. 259 * 260 * @param includeSignatures Whether to include the package signatures in the output, mainly 261 * used for backing up the user settings and ensuring they're 262 * re-attached to the same package. 263 * @param userId The user to write out. Supports {@link UserHandle#USER_ALL} if all users 264 * should be written. 265 */ writeSettings(@onNull TypedXmlSerializer serializer, boolean includeSignatures, @UserIdInt int userId)266 void writeSettings(@NonNull TypedXmlSerializer serializer, boolean includeSignatures, 267 @UserIdInt int userId) throws IOException; 268 269 /** 270 * Read back a list of {@link DomainVerificationPkgState}s previously written by {@link 271 * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the 272 * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} tag has already been entered. 273 * <p> 274 * This is expected to only be used to re-attach states for packages already known to be on the 275 * device. If restoring from a backup, use {@link #restoreSettings(TypedXmlPullParser)}. 276 */ readSettings(@onNull TypedXmlPullParser parser)277 void readSettings(@NonNull TypedXmlPullParser parser) 278 throws IOException, XmlPullParserException; 279 280 /** 281 * Read back data from 282 * {@link DomainVerificationLegacySettings#writeSettings(TypedXmlSerializer)}. Assumes that the 283 * {@link DomainVerificationLegacySettings#TAG_DOMAIN_VERIFICATIONS_LEGACY} tag has already 284 * been entered. 285 */ readLegacySettings(@onNull TypedXmlPullParser parser)286 void readLegacySettings(@NonNull TypedXmlPullParser parser) 287 throws IOException, XmlPullParserException; 288 289 /** 290 * Remove all state for the given package. 291 */ clearPackage(@onNull String packageName)292 void clearPackage(@NonNull String packageName); 293 294 /** 295 * Remove all state for the given package for the given user. 296 */ clearPackageForUser(@onNull String packageName, @UserIdInt int userId)297 void clearPackageForUser(@NonNull String packageName, @UserIdInt int userId); 298 299 /** 300 * Delete all the state for a user. This can be because the user has been removed from the 301 * device, or simply that the state for a user should be deleted. 302 */ clearUser(@serIdInt int userId)303 void clearUser(@UserIdInt int userId); 304 305 /** 306 * Restore a list of {@link DomainVerificationPkgState}s previously written by {@link 307 * #writeSettings(TypedXmlSerializer, boolean, int)}. Assumes that the 308 * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} 309 * tag has already been entered. 310 * <p> 311 * This is <b>only</b> for restore, and will override package states, ignoring if their {@link 312 * DomainVerificationInfo#getIdentifier()}s match. It's expected that any restored domains 313 * marked 314 * as success verify against the server correctly, although the verification agent may decide 315 * to 316 * re-verify them when it gets the chance. 317 */ 318 /* 319 * TODO(b/170746586): Figure out how to verify that package signatures match at snapshot time 320 * and restore time. 321 */ restoreSettings(@onNull TypedXmlPullParser parser)322 void restoreSettings(@NonNull TypedXmlPullParser parser) 323 throws IOException, XmlPullParserException; 324 325 /** 326 * Set aside a legacy {@link IntentFilterVerificationInfo} that will be restored to a pending 327 * {@link DomainVerificationPkgState} once it's added through 328 * {@link #addPackage(PackageSetting)}. 329 */ addLegacySetting(@onNull String packageName, @NonNull IntentFilterVerificationInfo info)330 void addLegacySetting(@NonNull String packageName, @NonNull IntentFilterVerificationInfo info); 331 332 /** 333 * Set aside a legacy user selection that will be restored to a pending 334 * {@link DomainVerificationPkgState} once it's added through 335 * {@link #addPackage(PackageSetting)}. 336 * 337 * @return true if state changed successfully 338 */ setLegacyUserState(@onNull String packageName, @UserIdInt int userId, int state)339 boolean setLegacyUserState(@NonNull String packageName, @UserIdInt int userId, int state); 340 341 /** 342 * Until the legacy APIs are entirely removed, returns the legacy state from the previously 343 * written info stored in {@link Settings}. 344 */ getLegacyState(@onNull String packageName, @UserIdInt int userId)345 int getLegacyState(@NonNull String packageName, @UserIdInt int userId); 346 347 /** 348 * Print the verification state and user selection state of a package. 349 * 350 * @param packageName the package whose state to change, or all packages if none is 351 * specified 352 * @param userId the specific user to print, or null to skip printing user selection 353 * states, supports {@link android.os.UserHandle#USER_ALL} 354 * @param pkgSettingFunction the method by which to retrieve package data; if this is called 355 * from {@link PackageManagerService}, it is 356 * expected to pass in the snapshot of {@link PackageSetting} objects 357 */ printState(@onNull IndentingPrintWriter writer, @Nullable String packageName, @Nullable @UserIdInt Integer userId, @NonNull Function<String, PackageSetting> pkgSettingFunction)358 void printState(@NonNull IndentingPrintWriter writer, @Nullable String packageName, 359 @Nullable @UserIdInt Integer userId, 360 @NonNull Function<String, PackageSetting> pkgSettingFunction) 361 throws NameNotFoundException; 362 363 @NonNull getShell()364 DomainVerificationShell getShell(); 365 366 @NonNull getCollector()367 DomainVerificationCollector getCollector(); 368 369 /** 370 * Filters the provided list down to the {@link ResolveInfo} objects that should be allowed 371 * to open the domain inside the {@link Intent}. It is possible for no packages represented in 372 * the list to be approved, in which case an empty list will be returned. 373 * 374 * @return the filtered list and the corresponding approval level 375 */ 376 @NonNull filterToApprovedApp(@onNull Intent intent, @NonNull List<ResolveInfo> infos, @UserIdInt int userId, @NonNull Function<String, PackageSetting> pkgSettingFunction)377 Pair<List<ResolveInfo>, Integer> filterToApprovedApp(@NonNull Intent intent, 378 @NonNull List<ResolveInfo> infos, @UserIdInt int userId, 379 @NonNull Function<String, PackageSetting> pkgSettingFunction); 380 381 /** 382 * Check at what precedence a package resolving a URI is approved to takeover the domain. 383 * This can be because the domain was auto-verified for the package, or if the user manually 384 * chose to enable the domain for the package. If an app is auto-verified, it will be 385 * preferred over apps that were manually selected. 386 * 387 * NOTE: This should not be used for filtering intent resolution. See 388 * {@link #filterToApprovedApp(Intent, List, int, Function)} for that. 389 */ 390 @ApprovalLevel approvalLevelForDomain(@onNull PackageSetting pkgSetting, @NonNull Intent intent, @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId)391 int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent, 392 @PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId); 393 394 /** 395 * @return the domain verification set ID for the given package, or null if the ID is 396 * unavailable 397 */ 398 @Nullable getDomainVerificationInfoId(@onNull String packageName)399 UUID getDomainVerificationInfoId(@NonNull String packageName); 400 401 @DomainVerificationManager.Error 402 @RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT) setDomainVerificationStatusInternal(int callingUid, @NonNull UUID domainSetId, @NonNull Set<String> domains, int state)403 int setDomainVerificationStatusInternal(int callingUid, @NonNull UUID domainSetId, 404 @NonNull Set<String> domains, int state) throws NameNotFoundException; 405 406 407 interface Connection extends DomainVerificationEnforcer.Callback, 408 PackageSettingsSnapshotProvider { 409 410 /** 411 * Notify that a settings change has been made and that eventually 412 * {@link #writeSettings(TypedXmlSerializer, boolean, int)} should be invoked by the parent. 413 */ scheduleWriteSettings()414 void scheduleWriteSettings(); 415 416 /** 417 * Delegate to {@link Binder#getCallingUid()} to allow mocking in tests. 418 */ getCallingUid()419 int getCallingUid(); 420 421 /** 422 * Delegate to {@link UserHandle#getCallingUserId()} to allow mocking in tests. 423 */ 424 @UserIdInt getCallingUserId()425 int getCallingUserId(); 426 427 /** 428 * @see DomainVerificationProxy.BaseConnection#schedule(int, java.lang.Object) 429 */ schedule(int code, @Nullable Object object)430 void schedule(int code, @Nullable Object object); 431 432 @UserIdInt getAllUserIds()433 int[] getAllUserIds(); 434 } 435 } 436