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