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