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
This commit is contained in:
Christopher Tate
2015-06-12 18:31:24 -07:00
parent 9f6d39f844
commit 72c10a25f0
3 changed files with 64 additions and 46 deletions

View File

@@ -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());
}
}
}

View File

@@ -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 (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("*");
}
}
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 (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);
}
}
}

View File

@@ -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,20 +991,26 @@ 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);
Slog.d(PackageManagerService.TAG,
"Creating new IntentFilterVerificationInfo for packageName: " + packageName);
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.d(PackageManagerService.TAG,
"Creating new IntentFilterVerificationInfo for pkg: " + packageName);
}
} else {
ivi.setDomains(domains);
Slog.d(PackageManagerService.TAG,
"Setting domains to existing IntentFilterVerificationInfo for packageName: " +
packageName + " and with domains: " + ivi.getDomainsString());
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.d(PackageManagerService.TAG,
"Setting domains to existing IntentFilterVerificationInfo for pkg: " +
packageName + " and with domains: " + ivi.getDomainsString());
}
}
return ivi;
}
@@ -1009,7 +1018,9 @@ final class Settings {
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) {
Slog.w(PackageManagerService.TAG,
"No IntentFilterVerificationInfo known for name: " + packageName);
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.w(PackageManagerService.TAG,
"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: "
+ verificationInfo.getPackageName());
if (DEBUG_DOMAIN_VERIFICATION) {
Slog.d(TAG, "Wrote domain verification for package: "
+ verificationInfo.getPackageName());
}
serializer.endTag(null, TAG_DOMAIN_VERIFICATION);
}
}