• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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