Loading services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java +28 −7 Original line number Diff line number Diff line Loading @@ -21,11 +21,8 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedIntentInfo; import android.os.Binder; import android.os.Build; import android.util.ArraySet; import android.util.Patterns; Loading @@ -36,19 +33,31 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DomainVerificationCollector { // The default domain name matcher doesn't account for wildcards, so prefix with *. private static final Pattern DOMAIN_NAME_WITH_WILDCARD = Pattern.compile("(\\*\\.)?" + Patterns.DOMAIN_NAME.pattern()); @NonNull private final PlatformCompat mPlatformCompat; @NonNull private final SystemConfig mSystemConfig; @NonNull private final Matcher mDomainMatcher; public DomainVerificationCollector(@NonNull PlatformCompat platformCompat, @NonNull SystemConfig systemConfig) { mPlatformCompat = platformCompat; mSystemConfig = systemConfig; // Cache the matcher to avoid calling into native on each check mDomainMatcher = DOMAIN_NAME_WITH_WILDCARD.matcher(""); } /** Loading Loading @@ -144,7 +153,10 @@ public class DomainVerificationCollector { if (intent.handlesWebUris(false)) { int authorityCount = intent.countDataAuthorities(); for (int index = 0; index < authorityCount; index++) { domains.add(intent.getDataAuthority(index).getHost()); String host = intent.getDataAuthority(index).getHost(); if (isValidHost(host)) { domains.add(host); } } } } Loading Loading @@ -188,13 +200,22 @@ public class DomainVerificationCollector { int authorityCount = intent.countDataAuthorities(); for (int index = 0; index < authorityCount; index++) { String host = intent.getDataAuthority(index).getHost(); // It's easy to misconfigure autoVerify intent filters, so to avoid // adding unintended hosts, check if the host is an HTTP domain. if (Patterns.DOMAIN_NAME.matcher(host).matches()) { if (isValidHost(host)) { domains.add(host); } } } } } /** * It's easy to mis-configure autoVerify intent filters, so to avoid adding unintended hosts, * check if the host is an HTTP domain. This applies for both legacy and modern versions of * the API, which will strip invalid hosts from the legacy parsing result. This is done to * improve the reliability of any legacy verifiers. */ private boolean isValidHost(String host) { mDomainMatcher.reset(host); return mDomainMatcher.matches(); } } services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java +65 −15 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationState; import android.os.Process; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; Loading @@ -45,6 +44,7 @@ import com.android.server.pm.verify.domain.DomainVerificationMessageCodes; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; Loading Loading @@ -168,22 +168,58 @@ public class DomainVerificationProxyV1 implements DomainVerificationProxy { return true; } Set<String> successfulDomains = new ArraySet<>(info.getHostToStateMap().keySet()); successfulDomains.removeAll(response.failedDomains); AndroidPackage pkg = mConnection.getPackage(packageName); if (pkg == null) { return true; } ArraySet<String> failedDomains = new ArraySet<>(response.failedDomains); Map<String, Integer> hostToStateMap = info.getHostToStateMap(); Set<String> hostKeySet = hostToStateMap.keySet(); ArraySet<String> successfulDomains = new ArraySet<>(hostKeySet); successfulDomains.removeAll(failedDomains); // v1 doesn't handle wildcard domains, so check them here for the verifier int size = successfulDomains.size(); for (int index = size - 1; index >= 0; index--) { String domain = successfulDomains.valueAt(index); if (domain.startsWith("*.")) { String nonWildcardDomain = domain.substring(2); if (failedDomains.contains(nonWildcardDomain)) { failedDomains.add(domain); successfulDomains.removeAt(index); // It's possible to declare a wildcard without declaring its // non-wildcard equivalent, so if it wasn't originally declared, // remove the transformed domain from the failed set. Otherwise the // manager will not accept the failed set as it contains an undeclared // domain. if (!hostKeySet.contains(nonWildcardDomain)) { failedDomains.remove(nonWildcardDomain); } } } } int callingUid = response.callingUid; if (!successfulDomains.isEmpty()) { try { mManager.setDomainVerificationStatusInternal(callingUid, domainSetId, successfulDomains, DomainVerificationState.STATE_SUCCESS); } catch (DomainVerificationManager.InvalidDomainSetException | PackageManager.NameNotFoundException ignored) { | PackageManager.NameNotFoundException e) { Slog.e(TAG, "Failure reporting successful domains for " + packageName, e); } } if (!failedDomains.isEmpty()) { try { mManager.setDomainVerificationStatusInternal(callingUid, domainSetId, new ArraySet<>(response.failedDomains), DomainVerificationState.STATE_LEGACY_FAILURE); failedDomains, DomainVerificationState.STATE_LEGACY_FAILURE); } catch (DomainVerificationManager.InvalidDomainSetException | PackageManager.NameNotFoundException ignored) { | PackageManager.NameNotFoundException e) { Slog.e(TAG, "Failure reporting failed domains for " + packageName, e); } } return true; Loading Loading @@ -235,7 +271,21 @@ public class DomainVerificationProxyV1 implements DomainVerificationProxy { // The collector itself handles the v1 vs v2 behavior, which is based on targetSdkVersion, // not the version of the verification agent on device. ArraySet<String> domains = mCollector.collectAutoVerifyDomains(pkg); return TextUtils.join(" ", domains); // v1 doesn't handle wildcard domains, so transform them here to the root StringBuilder builder = new StringBuilder(); int size = domains.size(); for (int index = 0; index < size; index++) { if (index > 0) { builder.append(" "); } String domain = domains.valueAt(index); if (domain.startsWith("*.")) { domain = domain.substring(2); } builder.append(domain); } return builder.toString(); } private static class Response { Loading Loading
services/core/java/com/android/server/pm/verify/domain/DomainVerificationCollector.java +28 −7 Original line number Diff line number Diff line Loading @@ -21,11 +21,8 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedIntentInfo; import android.os.Binder; import android.os.Build; import android.util.ArraySet; import android.util.Patterns; Loading @@ -36,19 +33,31 @@ import com.android.server.pm.parsing.pkg.AndroidPackage; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DomainVerificationCollector { // The default domain name matcher doesn't account for wildcards, so prefix with *. private static final Pattern DOMAIN_NAME_WITH_WILDCARD = Pattern.compile("(\\*\\.)?" + Patterns.DOMAIN_NAME.pattern()); @NonNull private final PlatformCompat mPlatformCompat; @NonNull private final SystemConfig mSystemConfig; @NonNull private final Matcher mDomainMatcher; public DomainVerificationCollector(@NonNull PlatformCompat platformCompat, @NonNull SystemConfig systemConfig) { mPlatformCompat = platformCompat; mSystemConfig = systemConfig; // Cache the matcher to avoid calling into native on each check mDomainMatcher = DOMAIN_NAME_WITH_WILDCARD.matcher(""); } /** Loading Loading @@ -144,7 +153,10 @@ public class DomainVerificationCollector { if (intent.handlesWebUris(false)) { int authorityCount = intent.countDataAuthorities(); for (int index = 0; index < authorityCount; index++) { domains.add(intent.getDataAuthority(index).getHost()); String host = intent.getDataAuthority(index).getHost(); if (isValidHost(host)) { domains.add(host); } } } } Loading Loading @@ -188,13 +200,22 @@ public class DomainVerificationCollector { int authorityCount = intent.countDataAuthorities(); for (int index = 0; index < authorityCount; index++) { String host = intent.getDataAuthority(index).getHost(); // It's easy to misconfigure autoVerify intent filters, so to avoid // adding unintended hosts, check if the host is an HTTP domain. if (Patterns.DOMAIN_NAME.matcher(host).matches()) { if (isValidHost(host)) { domains.add(host); } } } } } /** * It's easy to mis-configure autoVerify intent filters, so to avoid adding unintended hosts, * check if the host is an HTTP domain. This applies for both legacy and modern versions of * the API, which will strip invalid hosts from the legacy parsing result. This is done to * improve the reliability of any legacy verifiers. */ private boolean isValidHost(String host) { mDomainMatcher.reset(host); return mDomainMatcher.matches(); } }
services/core/java/com/android/server/pm/verify/domain/proxy/DomainVerificationProxyV1.java +65 −15 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationState; import android.os.Process; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Pair; Loading @@ -45,6 +44,7 @@ import com.android.server.pm.verify.domain.DomainVerificationMessageCodes; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; Loading Loading @@ -168,22 +168,58 @@ public class DomainVerificationProxyV1 implements DomainVerificationProxy { return true; } Set<String> successfulDomains = new ArraySet<>(info.getHostToStateMap().keySet()); successfulDomains.removeAll(response.failedDomains); AndroidPackage pkg = mConnection.getPackage(packageName); if (pkg == null) { return true; } ArraySet<String> failedDomains = new ArraySet<>(response.failedDomains); Map<String, Integer> hostToStateMap = info.getHostToStateMap(); Set<String> hostKeySet = hostToStateMap.keySet(); ArraySet<String> successfulDomains = new ArraySet<>(hostKeySet); successfulDomains.removeAll(failedDomains); // v1 doesn't handle wildcard domains, so check them here for the verifier int size = successfulDomains.size(); for (int index = size - 1; index >= 0; index--) { String domain = successfulDomains.valueAt(index); if (domain.startsWith("*.")) { String nonWildcardDomain = domain.substring(2); if (failedDomains.contains(nonWildcardDomain)) { failedDomains.add(domain); successfulDomains.removeAt(index); // It's possible to declare a wildcard without declaring its // non-wildcard equivalent, so if it wasn't originally declared, // remove the transformed domain from the failed set. Otherwise the // manager will not accept the failed set as it contains an undeclared // domain. if (!hostKeySet.contains(nonWildcardDomain)) { failedDomains.remove(nonWildcardDomain); } } } } int callingUid = response.callingUid; if (!successfulDomains.isEmpty()) { try { mManager.setDomainVerificationStatusInternal(callingUid, domainSetId, successfulDomains, DomainVerificationState.STATE_SUCCESS); } catch (DomainVerificationManager.InvalidDomainSetException | PackageManager.NameNotFoundException ignored) { | PackageManager.NameNotFoundException e) { Slog.e(TAG, "Failure reporting successful domains for " + packageName, e); } } if (!failedDomains.isEmpty()) { try { mManager.setDomainVerificationStatusInternal(callingUid, domainSetId, new ArraySet<>(response.failedDomains), DomainVerificationState.STATE_LEGACY_FAILURE); failedDomains, DomainVerificationState.STATE_LEGACY_FAILURE); } catch (DomainVerificationManager.InvalidDomainSetException | PackageManager.NameNotFoundException ignored) { | PackageManager.NameNotFoundException e) { Slog.e(TAG, "Failure reporting failed domains for " + packageName, e); } } return true; Loading Loading @@ -235,7 +271,21 @@ public class DomainVerificationProxyV1 implements DomainVerificationProxy { // The collector itself handles the v1 vs v2 behavior, which is based on targetSdkVersion, // not the version of the verification agent on device. ArraySet<String> domains = mCollector.collectAutoVerifyDomains(pkg); return TextUtils.join(" ", domains); // v1 doesn't handle wildcard domains, so transform them here to the root StringBuilder builder = new StringBuilder(); int size = domains.size(); for (int index = 0; index < size; index++) { if (index > 0) { builder.append(" "); } String domain = domains.valueAt(index); if (domain.startsWith("*.")) { domain = domain.substring(2); } builder.append(domain); } return builder.toString(); } private static class Response { Loading