Merge "Include knownCerts in Parcels for PermissionInfo and ParsedPermission" into sc-dev

This commit is contained in:
Michael Groover
2021-02-12 17:31:45 +00:00
committed by Android (Google) Code Review
4 changed files with 92 additions and 11 deletions

View File

@@ -28,6 +28,9 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Set;
@@ -477,6 +480,8 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
*/
public @Nullable CharSequence nonLocalizedDescription;
private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);
/**
* A {@link Set} of trusted signing certificate digests. If this permission has the {@link
* #PROTECTION_FLAG_KNOWN_SIGNER} flag set the permission will be granted to a requesting app
@@ -688,6 +693,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(descriptionRes);
dest.writeInt(requestRes);
TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
sForStringSet.parcel(knownCerts, dest, parcelableFlags);
}
/** @hide */
@@ -753,5 +759,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
descriptionRes = source.readInt();
requestRes = source.readInt();
nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
knownCerts = sForStringSet.unparcel(source);
}
}

View File

@@ -21,16 +21,22 @@ import android.content.pm.PermissionInfo;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;
import java.util.Locale;
import java.util.Set;
/** @hide */
public class ParsedPermission extends ParsedComponent {
private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);
@Nullable
String backgroundPermission;
@Nullable
@@ -89,6 +95,19 @@ public class ParsedPermission extends ParsedComponent {
return knownCerts;
}
protected void setKnownCert(String knownCert) {
// Convert the provided digest to upper case for consistent Set membership
// checks when verifying the signing certificate digests of requesting apps.
this.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
}
protected void setKnownCerts(String[] knownCerts) {
this.knownCerts = new ArraySet<>();
for (String knownCert : knownCerts) {
this.knownCerts.add(knownCert.toUpperCase(Locale.US));
}
}
public int calculateFootprint() {
int size = getName().length();
if (getNonLocalizedLabel() != null) {
@@ -117,6 +136,7 @@ public class ParsedPermission extends ParsedComponent {
dest.writeInt(this.protectionLevel);
dest.writeBoolean(this.tree);
dest.writeParcelable(this.parsedPermissionGroup, flags);
sForStringSet.parcel(knownCerts, dest, flags);
}
protected ParsedPermission(Parcel in) {
@@ -129,6 +149,7 @@ public class ParsedPermission extends ParsedComponent {
this.protectionLevel = in.readInt();
this.tree = in.readBoolean();
this.parsedPermissionGroup = in.readParcelable(boot);
this.knownCerts = sForStringSet.unparcel(in);
}
public static final Parcelable.Creator<ParsedPermission> CREATOR =

View File

@@ -25,7 +25,6 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.R;
@@ -33,8 +32,6 @@ import com.android.internal.R;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Locale;
import java.util.Set;
/** @hide */
public class ParsedPermissionUtils {
@@ -103,17 +100,12 @@ public class ParsedPermissionUtils {
if (resourceType.equals("array")) {
final String[] knownCerts = res.getStringArray(knownCertsResource);
if (knownCerts != null) {
// Convert the provided digest to upper case for consistent Set membership
// checks when verifying the signing certificate digests of requesting apps.
permission.knownCerts = new ArraySet<>();
for (String knownCert : knownCerts) {
permission.knownCerts.add(knownCert.toUpperCase(Locale.US));
}
permission.setKnownCerts(knownCerts);
}
} else {
final String knownCert = res.getString(knownCertsResource);
if (knownCert != null) {
permission.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
permission.setKnownCert(knownCert);
}
}
if (permission.knownCerts == null) {
@@ -126,7 +118,7 @@ public class ParsedPermissionUtils {
final String knownCert = sa.getString(
R.styleable.AndroidManifestPermission_knownCerts);
if (knownCert != null) {
permission.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
permission.setKnownCert(knownCert);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
import android.util.ArraySet;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public final class PermissionInfoTest {
private static final String KNOWN_CERT_DIGEST_1 =
"6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599";
private static final String KNOWN_CERT_DIGEST_2 =
"9369370ffcfdc1e92dae777252c05c483b8cbb55fa9d5fd9f6317f623ae6d8c6";
@Test
public void createFromParcel_returnsKnownCerts() {
// The platform supports a knownSigner permission protection flag that allows one or more
// trusted signing certificates to be specified with the permission declaration; if a
// requesting app is signed by any of these trusted certificates the permission is granted.
// This test verifies the Set of knownCerts is properly parceled / unparceled.
PermissionInfo permissionInfo = new PermissionInfo();
permissionInfo.protectionLevel =
PermissionInfo.PROTECTION_SIGNATURE | PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER;
permissionInfo.knownCerts = new ArraySet<>(2);
permissionInfo.knownCerts.add(KNOWN_CERT_DIGEST_1);
permissionInfo.knownCerts.add(KNOWN_CERT_DIGEST_2);
Parcel parcel = Parcel.obtain();
permissionInfo.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
PermissionInfo unparceledPermissionInfo = PermissionInfo.CREATOR.createFromParcel(parcel);
assertNotNull(unparceledPermissionInfo.knownCerts);
assertEquals(2, unparceledPermissionInfo.knownCerts.size());
assertTrue(unparceledPermissionInfo.knownCerts.contains(KNOWN_CERT_DIGEST_1));
assertTrue(unparceledPermissionInfo.knownCerts.contains(KNOWN_CERT_DIGEST_2));
}
}