Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SecurityPolicy factory method for apps signed with the platform certificate #11239

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
21 changes: 21 additions & 0 deletions binder/src/main/java/io/grpc/binder/SecurityPolicies.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,27 @@ public static SecurityPolicy hasSignature(
packageManager, packageName, ImmutableList.of(requiredSignature));
}

/**
* Creates a {@link SecurityPolicy} which checks if the given package is signed with the same
* certificate that the current Android platform was signed with.
*
* @param packageName the package name of the allowed package.
* @throws NullPointerException if any of the inputs are {@code null}.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/11238")
public static SecurityPolicy hasSameSignatureAsPlatform(
mateusazis marked this conversation as resolved.
Show resolved Hide resolved
PackageManager packageManager, String packageName) {
PackageInfo platformPackageInfo;
try {
platformPackageInfo =
packageManager.getPackageInfo("android", PackageManager.GET_SIGNING_CERTIFICATES);
} catch (PackageManager.NameNotFoundException e) {
throw new AssertionError(e); // impossible; the platform package is always available.
}
Signature platformSignature = platformPackageInfo.signatures[0];
mateusazis marked this conversation as resolved.
Show resolved Hide resolved
return hasSignature(packageManager, packageName, platformSignature);
}

/**
* Creates {@link SecurityPolicy} which checks if the SHA-256 hash of the package signature
* matches {@code requiredSignatureSha256Hash}.
Expand Down
60 changes: 60 additions & 0 deletions binder/src/test/java/io/grpc/binder/SecurityPoliciesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ private void installPackages(int uid, PackageInfo... packageInfo) {
shadowOf(packageManager).setPackagesForUid(uid, packageNames);
}

private void setupPlatformSignature(Signature signature) {
PackageInfo platformPackageInfo =
newBuilder().setPackageName("android").setSignatures(signature).build();
installPackages(Process.SYSTEM_UID, platformPackageInfo);
}

@Test
public void testInternalOnly() throws Exception {
policy = SecurityPolicies.internalOnly();
Expand Down Expand Up @@ -151,6 +157,60 @@ public void testHasSignature_failsIfSignatureDoesNotMatch() throws Exception {
.isEqualTo(Status.PERMISSION_DENIED.getCode());
}

@Test
public void testHasSameSignatureAsPlatform_succeedsIfSignaturesMatch() {
setupPlatformSignature(SIG1);
PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG1).build();
installPackages(OTHER_UID, info);

policy = SecurityPolicies.hasSameSignatureAsPlatform(packageManager, OTHER_UID_PACKAGE_NAME);

assertThat(policy.checkAuthorization(OTHER_UID).getCode()).isEqualTo(Status.OK.getCode());
}

@Test
public void testHasSameSignatureAsPlatform_failsIfPackageNameDoesNotMatch() {
setupPlatformSignature(SIG1);
PackageInfo info =
newBuilder()
.setPackageName(OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME)
.setSignatures(SIG1)
.build();
installPackages(OTHER_UID_SAME_SIGNATURE, info);

policy =
SecurityPolicies.hasSameSignatureAsPlatform(packageManager, appContext.getPackageName());

assertThat(policy.checkAuthorization(OTHER_UID_SAME_SIGNATURE).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
}

@Test
public void testHasSameSignatureAsPlatform_failsIfSignatureDoesNotMatch() {
setupPlatformSignature(SIG1);
PackageInfo info =
newBuilder().setPackageName(OTHER_UID_PACKAGE_NAME).setSignatures(SIG2).build();
installPackages(OTHER_UID, info);

policy = SecurityPolicies.hasSameSignatureAsPlatform(packageManager, OTHER_UID_PACKAGE_NAME);

assertThat(policy.checkAuthorization(OTHER_UID).getCode())
.isEqualTo(Status.PERMISSION_DENIED.getCode());
}

@Test
public void testHasSameSignatureAsPlatform_failsIfUidUnknown() {
setupPlatformSignature(SIG1);
policy =
SecurityPolicies.hasSameSignatureAsPlatform(
packageManager,
appContext.getPackageName());

assertThat(policy.checkAuthorization(OTHER_UID_UNKNOWN).getCode())
.isEqualTo(Status.UNAUTHENTICATED.getCode());
}

@Test
public void testOneOfSignatures_succeedsIfPackageNameAndSignaturesMatch()
throws Exception {
Expand Down
Loading