1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.uri; 18 19 import static com.android.server.uri.UriGrantsMockContext.FLAG_PERSISTABLE; 20 import static com.android.server.uri.UriGrantsMockContext.FLAG_PREFIX; 21 import static com.android.server.uri.UriGrantsMockContext.FLAG_READ; 22 import static com.android.server.uri.UriGrantsMockContext.PKG_CAMERA; 23 import static com.android.server.uri.UriGrantsMockContext.PKG_COMPLEX; 24 import static com.android.server.uri.UriGrantsMockContext.PKG_FORCE; 25 import static com.android.server.uri.UriGrantsMockContext.PKG_SOCIAL; 26 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_CAMERA; 27 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_COMPLEX; 28 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_FORCE; 29 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_PRIVATE; 30 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_PUBLIC; 31 import static com.android.server.uri.UriGrantsMockContext.UID_PRIMARY_SOCIAL; 32 import static com.android.server.uri.UriGrantsMockContext.UID_SECONDARY_CAMERA; 33 import static com.android.server.uri.UriGrantsMockContext.UID_SECONDARY_SOCIAL; 34 import static com.android.server.uri.UriGrantsMockContext.URI_FORCE; 35 import static com.android.server.uri.UriGrantsMockContext.URI_PHOTO_1; 36 import static com.android.server.uri.UriGrantsMockContext.URI_PRIVATE; 37 import static com.android.server.uri.UriGrantsMockContext.URI_PUBLIC; 38 import static com.android.server.uri.UriGrantsMockContext.USER_PRIMARY; 39 import static com.android.server.uri.UriGrantsMockContext.USER_SECONDARY; 40 41 import static org.junit.Assert.assertEquals; 42 import static org.junit.Assert.assertFalse; 43 import static org.junit.Assert.assertNull; 44 import static org.junit.Assert.assertTrue; 45 import static org.junit.Assert.fail; 46 import static org.mockito.ArgumentMatchers.any; 47 import static org.mockito.ArgumentMatchers.anyBoolean; 48 import static org.mockito.ArgumentMatchers.anyInt; 49 import static org.mockito.ArgumentMatchers.eq; 50 import static org.mockito.ArgumentMatchers.isNull; 51 import static org.mockito.Mockito.never; 52 import static org.mockito.Mockito.verify; 53 54 import android.content.ClipData; 55 import android.content.Intent; 56 import android.content.pm.ProviderInfo; 57 import android.net.Uri; 58 import android.os.Process; 59 import android.os.UserHandle; 60 import android.util.ArraySet; 61 62 import androidx.test.InstrumentationRegistry; 63 64 import org.junit.Before; 65 import org.junit.Test; 66 67 import java.util.Arrays; 68 import java.util.Set; 69 70 public class UriGrantsManagerServiceTest { 71 private UriGrantsMockContext mContext; 72 private UriGrantsManagerInternal mService; 73 74 // we expect the following only during grant if a grant is expected verifyNoVisibilityGrant()75 private void verifyNoVisibilityGrant() { 76 verify(mContext.mPmInternal, never()).grantImplicitAccess( 77 anyInt(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean()); 78 } 79 80 @Before setUp()81 public void setUp() throws Exception { 82 mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext()); 83 mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService(); 84 } 85 86 /** 87 * Verify that a camera sharing a normally-private photo with a social media 88 * app in the same user issues a grant. 89 */ 90 @Test testNeeded_normal_sameUser()91 public void testNeeded_normal_sameUser() { 92 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); 93 final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ); 94 95 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 96 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY); 97 assertEquals(PKG_SOCIAL, needed.targetPkg); 98 assertEquals(UID_PRIMARY_SOCIAL, needed.targetUid); 99 assertEquals(FLAG_READ, needed.flags); 100 assertEquals(asSet(expectedGrant), needed.uris); 101 verifyNoVisibilityGrant(); 102 } 103 104 /** 105 * Verify that a camera sharing a normally-private photo with a social media 106 * app in a different user issues a grant. 107 */ 108 @Test testNeeded_normal_differentUser()109 public void testNeeded_normal_differentUser() { 110 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); 111 final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ); 112 113 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 114 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY); 115 assertEquals(PKG_SOCIAL, needed.targetPkg); 116 assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid); 117 assertEquals(FLAG_READ, needed.flags); 118 assertEquals(asSet(expectedGrant), needed.uris); 119 verifyNoVisibilityGrant(); 120 } 121 122 /** 123 * No need to issue grants for public authorities. 124 */ 125 @Test testNeeded_public()126 public void testNeeded_public() { 127 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PUBLIC).addFlags(FLAG_READ); 128 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 129 intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_PRIMARY); 130 assertNull(needed); 131 verify(mContext.mPmInternal).grantImplicitAccess(eq(USER_PRIMARY), isNull(), eq( 132 UserHandle.getAppId(UID_PRIMARY_SOCIAL)), eq(UID_PRIMARY_PUBLIC), eq(false)); 133 } 134 135 /** 136 * But we're willing to issue grants to public authorities when crossing 137 * user boundaries. 138 */ 139 @Test testNeeded_public_differentUser()140 public void testNeeded_public_differentUser() { 141 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PUBLIC).addFlags(FLAG_READ); 142 final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PUBLIC, FLAG_READ); 143 144 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 145 intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_SECONDARY); 146 assertEquals(PKG_SOCIAL, needed.targetPkg); 147 assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid); 148 assertEquals(FLAG_READ, needed.flags); 149 assertEquals(asSet(expectedGrant), needed.uris); 150 verifyNoVisibilityGrant(); 151 } 152 153 /** 154 * Refuse to issue grants for private authorities. 155 */ 156 @Test testNeeded_private()157 public void testNeeded_private() { 158 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PRIVATE).addFlags(FLAG_READ); 159 try { 160 mService.checkGrantUriPermissionFromIntent( 161 intent, UID_PRIMARY_PRIVATE, PKG_SOCIAL, USER_PRIMARY); 162 fail(); 163 } catch (SecurityException expected) { 164 } 165 } 166 167 /** 168 * Verify that {@link ProviderInfo#forceUriPermissions} forces permission 169 * grants, even when receiver already holds permission. 170 */ 171 @Test testNeeded_force()172 public void testNeeded_force() { 173 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_FORCE) 174 .addFlags(FLAG_READ); 175 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 176 intent, UID_PRIMARY_FORCE, PKG_FORCE, USER_PRIMARY); 177 assertEquals(asSet(new GrantUri(USER_PRIMARY, URI_FORCE, 0)), needed.uris); 178 } 179 180 /** 181 * Verify that we can't grant permissions to top level of a provider with 182 * complex permission model. 183 */ 184 @Test testNeeded_complex_top()185 public void testNeeded_complex_top() { 186 final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/"); 187 { 188 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 189 .addFlags(FLAG_READ | Intent.FLAG_ACTIVITY_CLEAR_TASK); 190 assertNull(mService.checkGrantUriPermissionFromIntent( 191 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY)); 192 } 193 { 194 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 195 .addFlags(FLAG_READ | FLAG_PREFIX); 196 try { 197 mService.checkGrantUriPermissionFromIntent( 198 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY); 199 fail(); 200 } catch (SecurityException expected) { 201 } 202 } 203 { 204 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 205 .addFlags(FLAG_READ | FLAG_PERSISTABLE); 206 try { 207 mService.checkGrantUriPermissionFromIntent( 208 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY); 209 fail(); 210 } catch (SecurityException expected) { 211 } 212 } 213 } 214 215 /** 216 * Verify that we allow special cross-user grants to top level of a provider 217 * that normally wouldn't allow it. Only basic permission modes are allowed; 218 * advanced modes throw. 219 */ 220 @Test testNeeded_complex_top_differentUser()221 public void testNeeded_complex_top_differentUser() { 222 final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/"); 223 { 224 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 225 .addFlags(FLAG_READ); 226 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 227 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY); 228 assertEquals(FLAG_READ, needed.flags); 229 } 230 { 231 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 232 .addFlags(FLAG_READ | FLAG_PREFIX); 233 try { 234 mService.checkGrantUriPermissionFromIntent( 235 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY); 236 fail(); 237 } catch (SecurityException expected) { 238 } 239 } 240 { 241 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 242 .addFlags(FLAG_READ | FLAG_PERSISTABLE); 243 try { 244 mService.checkGrantUriPermissionFromIntent( 245 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY); 246 fail(); 247 } catch (SecurityException expected) { 248 } 249 } 250 } 251 252 /** 253 * Verify that we can grant permissions to middle level of a provider with 254 * complex permission model. 255 */ 256 @Test testNeeded_complex_middle()257 public void testNeeded_complex_middle() { 258 final Uri uri = Uri.parse("content://" + PKG_COMPLEX + "/secure/12"); 259 { 260 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 261 .addFlags(FLAG_READ); 262 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 263 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY); 264 assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris); 265 } 266 { 267 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 268 .addFlags(FLAG_READ | FLAG_PREFIX); 269 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 270 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY); 271 assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, FLAG_PREFIX)), needed.uris); 272 } 273 { 274 final Intent intent = new Intent(Intent.ACTION_VIEW, uri) 275 .addFlags(FLAG_READ | FLAG_PERSISTABLE); 276 final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent( 277 intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY); 278 assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris); 279 } 280 } 281 282 /** 283 * Verify that when we try sending a list of mixed items that the actual 284 * grants are verified based on the capabilities of the caller. 285 */ 286 @Test testNeeded_mixedPersistable()287 public void testNeeded_mixedPersistable() { 288 final ClipData clip = ClipData.newRawUri("test", URI_PHOTO_1); 289 clip.addItem(new ClipData.Item(URI_PUBLIC)); 290 291 final Intent intent = new Intent(Intent.ACTION_VIEW); 292 intent.addFlags(FLAG_READ | FLAG_PERSISTABLE); 293 intent.setClipData(clip); 294 295 { 296 // The camera package shouldn't be able to see other packages or their providers, 297 // so make sure the grant only succeeds for the camera's URIs. 298 final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent( 299 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY); 300 if (nug != null && nug.uris != null) { 301 for (GrantUri gu : nug.uris) { 302 if (!gu.uri.getAuthority().equals(PKG_CAMERA)) { 303 fail(); 304 } 305 } 306 } 307 } 308 { 309 // The camera package shouldn't be able to see other packages or their providers, 310 // so make sure the grant only succeeds for the camera's URIs. 311 final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent( 312 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY); 313 if (nug != null && nug.uris != null) { 314 for (GrantUri gu : nug.uris) { 315 if (!gu.uri.getAuthority().equals(PKG_CAMERA)) { 316 fail(); 317 } 318 } 319 } 320 } 321 } 322 323 /** 324 * Verify that two overlapping owners require separate grants and that they 325 * don't interfere with each other. 326 */ 327 @Test testGrant_overlap()328 public void testGrant_overlap() { 329 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); 330 331 final UriPermissionOwner activity = new UriPermissionOwner(mService, "activity"); 332 final UriPermissionOwner service = new UriPermissionOwner(mService, "service"); 333 334 final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ); 335 336 // Grant read via activity and write via service 337 mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent( 338 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), activity); 339 mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent( 340 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), service); 341 342 // Verify that everything is good with the world 343 assertTrue(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ)); 344 345 // Finish activity; service should hold permission 346 activity.removeUriPermissions(); 347 assertTrue(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ)); 348 349 // And finishing service should wrap things up 350 service.removeUriPermissions(); 351 assertFalse(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ)); 352 } 353 354 @Test testCheckAuthorityGrants()355 public void testCheckAuthorityGrants() { 356 final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ); 357 final UriPermissionOwner owner = new UriPermissionOwner(mService, "primary"); 358 359 final ProviderInfo cameraInfo = mContext.mPmInternal.resolveContentProvider( 360 PKG_CAMERA, 0, USER_PRIMARY, Process.SYSTEM_UID); 361 362 // By default no social can see any camera 363 assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 364 cameraInfo, USER_PRIMARY, true)); 365 assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 366 cameraInfo, USER_SECONDARY, true)); 367 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 368 cameraInfo, USER_PRIMARY, true)); 369 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 370 cameraInfo, USER_SECONDARY, true)); 371 372 // Granting primary camera to primary social 373 mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent( 374 intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner); 375 assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 376 cameraInfo, USER_PRIMARY, true)); 377 assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 378 cameraInfo, USER_SECONDARY, true)); 379 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 380 cameraInfo, USER_PRIMARY, true)); 381 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 382 cameraInfo, USER_SECONDARY, true)); 383 384 // Granting secondary camera to primary social 385 mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent( 386 intent, UID_SECONDARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner); 387 assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 388 cameraInfo, USER_PRIMARY, true)); 389 assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 390 cameraInfo, USER_SECONDARY, true)); 391 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 392 cameraInfo, USER_PRIMARY, true)); 393 assertFalse(mService.checkAuthorityGrants(UID_SECONDARY_SOCIAL, 394 cameraInfo, USER_SECONDARY, true)); 395 396 // And releasing the grant means we lose access 397 owner.removeUriPermissions(); 398 assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 399 cameraInfo, USER_PRIMARY, true)); 400 assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL, 401 cameraInfo, USER_SECONDARY, true)); 402 } 403 asSet(T... values)404 private static <T> Set<T> asSet(T... values) { 405 return new ArraySet<T>(Arrays.asList(values)); 406 } 407 } 408