1616
1717package io .grpc .binder ;
1818
19+ import static android .Manifest .permission .ACCESS_COARSE_LOCATION ;
20+ import static android .Manifest .permission .ACCESS_FINE_LOCATION ;
21+ import static android .Manifest .permission .WRITE_EXTERNAL_STORAGE ;
22+ import static android .content .pm .PackageInfo .REQUESTED_PERMISSION_GRANTED ;
23+ import static com .google .common .base .Preconditions .checkState ;
1924import static com .google .common .truth .Truth .assertThat ;
2025import static org .robolectric .Shadows .shadowOf ;
2126
2631import android .os .Process ;
2732import androidx .test .core .app .ApplicationProvider ;
2833import com .google .common .collect .ImmutableList ;
34+ import com .google .common .collect .ImmutableSet ;
2935import io .grpc .Status ;
30- import io . grpc . binder . SecurityPolicy ;
36+ import java . util . HashMap ;
3137import org .junit .Before ;
3238import org .junit .Test ;
3339import org .junit .runner .RunWith ;
@@ -39,7 +45,6 @@ public final class SecurityPoliciesTest {
3945 private static final int MY_UID = Process .myUid ();
4046 private static final int OTHER_UID = MY_UID + 1 ;
4147 private static final int OTHER_UID_SAME_SIGNATURE = MY_UID + 2 ;
42- private static final int OTHER_UID_NO_SIGNATURE = MY_UID + 3 ;
4348 private static final int OTHER_UID_UNKNOWN = MY_UID + 4 ;
4449
4550 private static final String PERMISSION_DENIED_REASONS = "some reasons" ;
@@ -49,7 +54,6 @@ public final class SecurityPoliciesTest {
4954
5055 private static final String OTHER_UID_PACKAGE_NAME = "other.package" ;
5156 private static final String OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME = "other.package.samesignature" ;
52- private static final String OTHER_UID_NO_SIGNATURE_PACKAGE_NAME = "other.package.nosignature" ;
5357
5458 private Context appContext ;
5559 private PackageManager packageManager ;
@@ -60,24 +64,22 @@ public final class SecurityPoliciesTest {
6064 public void setUp () {
6165 appContext = ApplicationProvider .getApplicationContext ();
6266 packageManager = appContext .getPackageManager ();
63- installPackage (MY_UID , appContext .getPackageName (), SIG1 );
64- installPackage (OTHER_UID , OTHER_UID_PACKAGE_NAME , SIG2 );
65- installPackage (OTHER_UID_SAME_SIGNATURE , OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME , SIG1 );
66- installPackage (OTHER_UID_NO_SIGNATURE , OTHER_UID_NO_SIGNATURE_PACKAGE_NAME );
6767 }
6868
6969 @ SuppressWarnings ("deprecation" )
70- private void installPackage (int uid , String packageName , Signature ... signatures ) {
71- PackageInfo info = new PackageInfo ();
72- info .packageName = packageName ;
73- info .signatures = signatures ;
74- shadowOf (packageManager ).installPackage (info );
75- shadowOf (packageManager ).setPackagesForUid (uid , packageName );
70+ private void installPackages (int uid , PackageInfo ... packageInfo ) {
71+ String [] packageNames = new String [packageInfo .length ];
72+ for (int i = 0 ; i < packageInfo .length ; i ++) {
73+ shadowOf (packageManager ).installPackage (packageInfo [i ]);
74+ packageNames [i ] = packageInfo [i ].packageName ;
75+ }
76+ shadowOf (packageManager ).setPackagesForUid (uid , packageNames );
7677 }
7778
7879 @ Test
7980 public void testInternalOnly () throws Exception {
8081 policy = SecurityPolicies .internalOnly ();
82+
8183 assertThat (policy .checkAuthorization (MY_UID ).getCode ()).isEqualTo (Status .OK .getCode ());
8284 assertThat (policy .checkAuthorization (OTHER_UID ).getCode ())
8385 .isEqualTo (Status .PERMISSION_DENIED .getCode ());
@@ -99,6 +101,11 @@ public void testPermissionDenied() throws Exception {
99101 @ Test
100102 public void testHasSignature_succeedsIfPackageNameAndSignaturesMatch ()
101103 throws Exception {
104+ PackageInfo info =
105+ newBuilder ().setPackageName (OTHER_UID_PACKAGE_NAME ).setSignatures (SIG2 ).build ();
106+
107+ installPackages (OTHER_UID , info );
108+
102109 policy = SecurityPolicies .hasSignature (packageManager , OTHER_UID_PACKAGE_NAME , SIG2 );
103110
104111 // THEN UID for package that has SIG2 will be authorized
@@ -107,6 +114,14 @@ public void testHasSignature_succeedsIfPackageNameAndSignaturesMatch()
107114
108115 @ Test
109116 public void testHasSignature_failsIfPackageNameDoesNotMatch () throws Exception {
117+ PackageInfo info =
118+ newBuilder ()
119+ .setPackageName (OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME )
120+ .setSignatures (SIG1 )
121+ .build ();
122+
123+ installPackages (OTHER_UID_SAME_SIGNATURE , info );
124+
110125 policy = SecurityPolicies .hasSignature (packageManager , appContext .getPackageName (), SIG1 );
111126
112127 // THEN UID for package that has SIG1 but different package name will not be authorized
@@ -116,6 +131,11 @@ public void testHasSignature_failsIfPackageNameDoesNotMatch() throws Exception {
116131
117132 @ Test
118133 public void testHasSignature_failsIfSignatureDoesNotMatch () throws Exception {
134+ PackageInfo info =
135+ newBuilder ().setPackageName (OTHER_UID_PACKAGE_NAME ).setSignatures (SIG2 ).build ();
136+
137+ installPackages (OTHER_UID , info );
138+
119139 policy = SecurityPolicies .hasSignature (packageManager , OTHER_UID_PACKAGE_NAME , SIG1 );
120140
121141 // THEN UID for package that doesn't have SIG1 will not be authorized
@@ -126,6 +146,11 @@ public void testHasSignature_failsIfSignatureDoesNotMatch() throws Exception {
126146 @ Test
127147 public void testOneOfSignatures_succeedsIfPackageNameAndSignaturesMatch ()
128148 throws Exception {
149+ PackageInfo info =
150+ newBuilder ().setPackageName (OTHER_UID_PACKAGE_NAME ).setSignatures (SIG2 ).build ();
151+
152+ installPackages (OTHER_UID , info );
153+
129154 policy =
130155 SecurityPolicies .oneOfSignatures (
131156 packageManager , OTHER_UID_PACKAGE_NAME , ImmutableList .of (SIG2 ));
@@ -136,6 +161,14 @@ public void testOneOfSignatures_succeedsIfPackageNameAndSignaturesMatch()
136161
137162 @ Test
138163 public void testOneOfSignature_failsIfAllSignaturesDoNotMatch () throws Exception {
164+ PackageInfo info =
165+ newBuilder ()
166+ .setPackageName (OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME )
167+ .setSignatures (SIG1 )
168+ .build ();
169+
170+ installPackages (OTHER_UID_SAME_SIGNATURE , info );
171+
139172 policy =
140173 SecurityPolicies .oneOfSignatures (
141174 packageManager ,
@@ -150,11 +183,14 @@ public void testOneOfSignature_failsIfAllSignaturesDoNotMatch() throws Exception
150183 @ Test
151184 public void testOneOfSignature_succeedsIfPackageNameAndOneOfSignaturesMatch ()
152185 throws Exception {
186+ PackageInfo info =
187+ newBuilder ().setPackageName (OTHER_UID_PACKAGE_NAME ).setSignatures (SIG2 ).build ();
188+
189+ installPackages (OTHER_UID , info );
190+
153191 policy =
154192 SecurityPolicies .oneOfSignatures (
155- packageManager ,
156- OTHER_UID_PACKAGE_NAME ,
157- ImmutableList .of (SIG1 , SIG2 ));
193+ packageManager , OTHER_UID_PACKAGE_NAME , ImmutableList .of (SIG1 , SIG2 ));
158194
159195 // THEN UID for package that has SIG2 will be authorized
160196 assertThat (policy .checkAuthorization (OTHER_UID ).getCode ()).isEqualTo (Status .OK .getCode ());
@@ -164,11 +200,170 @@ public void testOneOfSignature_succeedsIfPackageNameAndOneOfSignaturesMatch()
164200 public void testHasSignature_failsIfUidUnknown () throws Exception {
165201 policy =
166202 SecurityPolicies .hasSignature (
167- packageManager ,
168- appContext .getPackageName (),
169- SIG1 );
203+ packageManager ,
204+ appContext .getPackageName (),
205+ SIG1 );
170206
171207 assertThat (policy .checkAuthorization (OTHER_UID_UNKNOWN ).getCode ())
172- .isEqualTo (Status .UNAUTHENTICATED .getCode ());
208+ .isEqualTo (Status .UNAUTHENTICATED .getCode ());
209+ }
210+
211+ @ Test
212+ public void testHasPermissions_sharedUserId_succeedsIfAllPackageHavePermissions ()
213+ throws Exception {
214+ PackageInfo info =
215+ newBuilder ()
216+ .setPackageName (OTHER_UID_PACKAGE_NAME )
217+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
218+ .setPermission (ACCESS_COARSE_LOCATION , REQUESTED_PERMISSION_GRANTED )
219+ .build ();
220+
221+ PackageInfo infoSamePerms =
222+ newBuilder ()
223+ .setPackageName (OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME )
224+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
225+ .setPermission (ACCESS_COARSE_LOCATION , REQUESTED_PERMISSION_GRANTED )
226+ .build ();
227+
228+ installPackages (OTHER_UID , info , infoSamePerms );
229+
230+ policy =
231+ SecurityPolicies .hasPermissions (
232+ packageManager , ImmutableSet .of (ACCESS_FINE_LOCATION , ACCESS_COARSE_LOCATION ));
233+ assertThat (policy .checkAuthorization (OTHER_UID ).getCode ()).isEqualTo (Status .OK .getCode ());
234+ }
235+
236+ @ Test
237+ public void testHasPermissions_sharedUserId_failsIfOnePackageHasNoPermissions () throws Exception {
238+ PackageInfo info =
239+ newBuilder ()
240+ .setPackageName (OTHER_UID_PACKAGE_NAME )
241+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
242+ .build ();
243+
244+ PackageInfo infoNoPerms =
245+ newBuilder ()
246+ .setPackageName (OTHER_UID_SAME_SIGNATURE_PACKAGE_NAME )
247+ .setPermission (ACCESS_FINE_LOCATION , 0 )
248+ .build ();
249+
250+ installPackages (OTHER_UID , info , infoNoPerms );
251+
252+ policy = SecurityPolicies .hasPermissions (packageManager , ImmutableSet .of (ACCESS_FINE_LOCATION ));
253+ assertThat (policy .checkAuthorization (OTHER_UID ).getCode ())
254+ .isEqualTo (Status .PERMISSION_DENIED .getCode ());
255+ assertThat (policy .checkAuthorization (OTHER_UID ).getDescription ())
256+ .contains ("does not have permission" );
257+ }
258+
259+ @ Test
260+ public void testHasPermissions_succeedsIfPackageHasPermissions () throws Exception {
261+ PackageInfo info =
262+ newBuilder ()
263+ .setPackageName (OTHER_UID_PACKAGE_NAME )
264+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
265+ .setPermission (ACCESS_COARSE_LOCATION , REQUESTED_PERMISSION_GRANTED )
266+ .setPermission (WRITE_EXTERNAL_STORAGE , 0 )
267+ .build ();
268+
269+ installPackages (OTHER_UID , info );
270+
271+ policy =
272+ SecurityPolicies .hasPermissions (
273+ packageManager , ImmutableSet .of (ACCESS_FINE_LOCATION , ACCESS_COARSE_LOCATION ));
274+ assertThat (policy .checkAuthorization (OTHER_UID ).getCode ()).isEqualTo (Status .OK .getCode ());
275+ }
276+
277+ @ Test
278+ public void testHasPermissions_failsIfPackageDoesNotHaveOnePermission () throws Exception {
279+ PackageInfo info =
280+ newBuilder ()
281+ .setPackageName (OTHER_UID_PACKAGE_NAME )
282+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
283+ .setPermission (ACCESS_COARSE_LOCATION , REQUESTED_PERMISSION_GRANTED )
284+ .setPermission (WRITE_EXTERNAL_STORAGE , 0 )
285+ .build ();
286+
287+ installPackages (OTHER_UID , info );
288+
289+ policy =
290+ SecurityPolicies .hasPermissions (
291+ packageManager , ImmutableSet .of (ACCESS_FINE_LOCATION , WRITE_EXTERNAL_STORAGE ));
292+ assertThat (policy .checkAuthorization (OTHER_UID ).getCode ())
293+ .isEqualTo (Status .PERMISSION_DENIED .getCode ());
294+ assertThat (policy .checkAuthorization (OTHER_UID ).getDescription ())
295+ .contains ("does not have permission" );
296+ }
297+
298+ @ Test
299+ public void testHasPermissions_failsIfPackageDoesNotHavePermissions () throws Exception {
300+ PackageInfo info =
301+ newBuilder ()
302+ .setPackageName (OTHER_UID_PACKAGE_NAME )
303+ .setPermission (ACCESS_FINE_LOCATION , REQUESTED_PERMISSION_GRANTED )
304+ .setPermission (ACCESS_COARSE_LOCATION , REQUESTED_PERMISSION_GRANTED )
305+ .setPermission (WRITE_EXTERNAL_STORAGE , 0 )
306+ .build ();
307+
308+ installPackages (OTHER_UID , info );
309+
310+ policy =
311+ SecurityPolicies .hasPermissions (packageManager , ImmutableSet .of (WRITE_EXTERNAL_STORAGE ));
312+ assertThat (policy .checkAuthorization (OTHER_UID ).getCode ())
313+ .isEqualTo (Status .PERMISSION_DENIED .getCode ());
314+ assertThat (policy .checkAuthorization (OTHER_UID ).getDescription ())
315+ .contains ("does not have permission" );
316+ }
317+
318+ private static PackageInfoBuilder newBuilder () {
319+ return new PackageInfoBuilder ();
320+ }
321+
322+ private static class PackageInfoBuilder {
323+ private String packageName ;
324+ private Signature [] signatures ;
325+ private final HashMap <String , Integer > permissions = new HashMap <>();
326+
327+ public PackageInfoBuilder setPackageName (String packageName ) {
328+ this .packageName = packageName ;
329+ return this ;
330+ }
331+
332+ public PackageInfoBuilder setPermission (String permissionName , int permissionFlag ) {
333+ this .permissions .put (permissionName , permissionFlag );
334+ return this ;
335+ }
336+
337+ public PackageInfoBuilder setSignatures (Signature ... signatures ) {
338+ this .signatures = signatures ;
339+ return this ;
340+ }
341+
342+ public PackageInfo build () {
343+ checkState (this .packageName != null , "packageName is a mandatory field" );
344+
345+ PackageInfo packageInfo = new PackageInfo ();
346+
347+ packageInfo .packageName = this .packageName ;
348+
349+ if (this .signatures != null ) {
350+ packageInfo .signatures = this .signatures ;
351+ }
352+
353+ if (!this .permissions .isEmpty ()) {
354+ String [] requestedPermissions =
355+ this .permissions .keySet ().toArray (new String [this .permissions .size ()]);
356+ int [] requestedPermissionsFlags = new int [requestedPermissions .length ];
357+
358+ for (int i = 0 ; i < requestedPermissions .length ; i ++) {
359+ requestedPermissionsFlags [i ] = this .permissions .get (requestedPermissions [i ]);
360+ }
361+
362+ packageInfo .requestedPermissions = requestedPermissions ;
363+ packageInfo .requestedPermissionsFlags = requestedPermissionsFlags ;
364+ }
365+
366+ return packageInfo ;
367+ }
173368 }
174369}
0 commit comments