Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72c10a25 authored by Christopher Tate's avatar Christopher Tate
Browse files

Clean up app-link verification policy

If an app claims to be the official auto-verified app for any domain
and thus the automatic handler for ACTION_VIEW / {http,https}://...
intents naming that domain, then we require that it verify as the
official app for *all* domains it purports to handle, even if the
other domains are not flagged for verify.

Bug 21335460

Change-Id: I3fdd8620defa31aea36ce738fa63ac94fc53c5f7
parent 9f6d39f8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -731,6 +731,10 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
            if (filter.getAutoVerify()) {
                if (localVerificationLOGV || debug) {
                    Slog.v(TAG, "  Filter verified: " + isFilterVerified(filter));
                    int authorities = filter.countDataAuthorities();
                    for (int z = 0; z < authorities; z++) {
                        Slog.v(TAG, "   " + filter.getDataAuthority(z).getHost());
                    }
                }
            }

+27 −32
Original line number Diff line number Diff line
@@ -268,6 +268,7 @@ public class PackageManagerService extends IPackageManager.Stub {
    static final boolean DEBUG_SETTINGS = false;
    static final boolean DEBUG_PREFERRED = false;
    static final boolean DEBUG_UPGRADE = false;
    static final boolean DEBUG_DOMAIN_VERIFICATION = false;
    private static final boolean DEBUG_BACKUP = true;
    private static final boolean DEBUG_INSTALL = false;
    private static final boolean DEBUG_REMOVE = false;
@@ -279,7 +280,6 @@ public class PackageManagerService extends IPackageManager.Stub {
    private static final boolean DEBUG_VERIFY = false;
    private static final boolean DEBUG_DEXOPT = false;
    private static final boolean DEBUG_ABI_SELECTION = false;
    private static final boolean DEBUG_DOMAIN_VERIFICATION = false;
    private static final int RADIO_UID = Process.PHONE_UID;
    private static final int LOG_UID = Process.LOG_UID;
@@ -11818,50 +11818,45 @@ public class PackageManagerService extends IPackageManager.Stub {
        final int verificationId = mIntentFilterVerificationToken++;
        int count = 0;
        final String packageName = pkg.packageName;
        ArrayList<String> allHosts = new ArrayList<>();
        boolean needToVerify = false;
        synchronized (mPackages) {
            // If any filters need to be verified, then all need to be.
            for (PackageParser.Activity a : pkg.activities) {
                for (ActivityIntentInfo filter : a.intents) {
                    boolean needsFilterVerification = filter.needsVerification();
                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                        if (DEBUG_DOMAIN_VERIFICATION) {
                            Slog.d(TAG, "Intent filter needs verification, so processing all filters");
                        }
                        needToVerify = true;
                        break;
                    }
                }
            }
            if (needToVerify) {
                for (PackageParser.Activity a : pkg.activities) {
                    for (ActivityIntentInfo filter : a.intents) {
                        boolean needsFilterVerification = filter.hasWebDataURI();
                        if (needsFilterVerification && needsNetworkVerificationLPr(filter)) {
                            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                    "Verification needed for IntentFilter:" + filter.toString());
                            mIntentFilterVerifier.addOneIntentFilterVerification(
                                    verifierUid, userId, verificationId, filter, packageName);
                            count++;
                    } else if (!needsFilterVerification) {
                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                "No verification needed for IntentFilter:" + filter.toString());
                        if (hasValidDomains(filter)) {
                            ArrayList<String> hosts = filter.getHostsList();
                            if (hosts.size() > 0) {
                                allHosts.addAll(hosts);
                            } else {
                                if (allHosts.isEmpty()) {
                                    allHosts.add("*");
                                }
                            }
                        }
                    } else {
                        if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                "Verification already done for IntentFilter:" + filter.toString());
                    }
                }
            }
        }
        if (count > 0) {
            mIntentFilterVerifier.startVerifications(userId);
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Started " + count
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                    + " IntentFilter verification" + (count > 1 ? "s" : "")
                    +  " for userId:" + userId + "!");
                    +  " for userId:" + userId);
            mIntentFilterVerifier.startVerifications(userId);
        } else {
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                    "No need to start any IntentFilter verification!");
            if (allHosts.size() > 0 && mSettings.createIntentFilterVerificationIfNeededLPw(
                    packageName, allHosts) != null) {
                scheduleWriteSettingsLocked();
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
            }
        }
    }
+33 −14
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;

import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -977,7 +978,9 @@ final class Settings {
    IntentFilterVerificationInfo getIntentFilterVerificationLPr(String packageName) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
            }
            return null;
        }
        return ps.getIntentFilterVerificationInfo();
@@ -988,28 +991,36 @@ final class Settings {
            ArrayList<String> domains) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
            }
            return null;
        }
        IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
        if (ivi == null) {
            ivi = new IntentFilterVerificationInfo(packageName, domains);
            ps.setIntentFilterVerificationInfo(ivi);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(PackageManagerService.TAG,
                    "Creating new IntentFilterVerificationInfo for packageName: " + packageName);
                        "Creating new IntentFilterVerificationInfo for pkg: " + packageName);
            }
        } else {
            ivi.setDomains(domains);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(PackageManagerService.TAG,
                    "Setting domains to existing IntentFilterVerificationInfo for packageName: " +
                        "Setting domains to existing IntentFilterVerificationInfo for pkg: " +
                                packageName + " and with domains: " + ivi.getDomainsString());
            }
        }
        return ivi;
    }

    int getIntentFilterVerificationStatusLPr(String packageName, int userId) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
            }
            return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
        }
        int status = ps.getDomainVerificationStatusForUser(userId);
@@ -1025,14 +1036,18 @@ final class Settings {
        // Update the status for the current package
        PackageSetting current = mPackages.get(packageName);
        if (current == null) {
            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
            }
            return false;
        }
        current.setDomainVerificationStatusForUser(status, userId);

        if (current.getIntentFilterVerificationInfo() == null) {
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG,
                    "No IntentFilterVerificationInfo known for name: " + packageName);
                        "No IntentFilterVerificationInfo known: " + packageName);
            }
            return false;
        }

@@ -1080,7 +1095,9 @@ final class Settings {
    boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.w(PackageManagerService.TAG, "No package known: " + packageName);
            }
            return false;
        }
        ps.clearDomainVerificationStatusForUser(userId);
@@ -1549,8 +1566,10 @@ final class Settings {
        if (verificationInfo != null && verificationInfo.getPackageName() != null) {
            serializer.startTag(null, TAG_DOMAIN_VERIFICATION);
            verificationInfo.writeToXml(serializer);
            Log.d(TAG, "Wrote domain verification for package: "
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "Wrote domain verification for package: "
                        + verificationInfo.getPackageName());
            }
            serializer.endTag(null, TAG_DOMAIN_VERIFICATION);
        }
    }