1 /* 2 * Copyright (C) 2019 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.cts.usespermissiondiffcertapp; 18 19 import static com.android.cts.usespermissiondiffcertapp.AccessPermissionWithDiffSigTest.PERM_URI_GRANTING; 20 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertNoPersistedUriPermission; 21 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertPersistedUriPermission; 22 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertReadingClipAllowed; 23 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertReadingClipNotAllowed; 24 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertWritingClipAllowed; 25 import static com.android.cts.usespermissiondiffcertapp.Asserts.assertWritingClipNotAllowed; 26 import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaActivity; 27 import static com.android.cts.usespermissiondiffcertapp.Utils.grantClipUriPermissionViaContext; 28 import static com.android.cts.usespermissiondiffcertapp.Utils.revokeClipUriPermissionViaContext; 29 30 import static junit.framework.Assert.fail; 31 32 import android.content.ClipData; 33 import android.content.ContentResolver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.net.Uri; 37 38 import androidx.test.InstrumentationRegistry; 39 import androidx.test.runner.AndroidJUnit4; 40 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 @RunWith(AndroidJUnit4.class) 45 public class UriGrantsTest { 46 static final String TAG = "UriGrantsTest"; 47 getContext()48 private static Context getContext() { 49 return InstrumentationRegistry.getTargetContext(); 50 } 51 makeSingleClipData(Uri uri)52 static ClipData makeSingleClipData(Uri uri) { 53 return new ClipData("foo", new String[] { "foo/bar" }, 54 new ClipData.Item(uri)); 55 } 56 makeMultiClipData(Uri uri)57 static ClipData makeMultiClipData(Uri uri) { 58 Uri grantClip1Uri = uri; 59 Uri grantClip2Uri = Uri.withAppendedPath(uri, "clip2"); 60 Uri grantClip3Uri = Uri.withAppendedPath(uri, "clip3"); 61 Uri grantClip4Uri = Uri.withAppendedPath(uri, "clip4"); 62 Uri grantClip5Uri = Uri.withAppendedPath(uri, "clip5"); 63 ClipData clip = new ClipData("foo", new String[] { "foo/bar" }, 64 new ClipData.Item(grantClip1Uri)); 65 clip.addItem(new ClipData.Item(grantClip2Uri)); 66 // Intents in the ClipData should allow their data: and clip URIs 67 // to be granted, but only respect the grant flags of the top-level 68 // Intent. 69 clip.addItem(new ClipData.Item(new Intent(Intent.ACTION_VIEW, grantClip3Uri))); 70 Intent intent = new Intent(Intent.ACTION_VIEW, grantClip4Uri); 71 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 72 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 73 clip.addItem(new ClipData.Item(intent)); 74 intent = new Intent(Intent.ACTION_VIEW); 75 intent.setClipData(new ClipData("foo", new String[] { "foo/bar" }, 76 new ClipData.Item(grantClip5Uri))); 77 clip.addItem(new ClipData.Item(intent)); 78 return clip; 79 } 80 81 /** 82 * Validate behavior of persistable permission grants. 83 */ 84 @Test testGrantPersistableUriPermission()85 public void testGrantPersistableUriPermission() { 86 final ContentResolver resolver = getContext().getContentResolver(); 87 88 final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo"); 89 final ClipData clip = makeSingleClipData(target); 90 91 // Make sure we can't see the target 92 assertReadingClipNotAllowed(clip, "reading should have failed"); 93 assertWritingClipNotAllowed(clip, "writing should have failed"); 94 95 // Make sure we can't take a grant we don't have 96 try { 97 resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 98 fail("taking read should have failed"); 99 } catch (SecurityException expected) { 100 } 101 102 // And since we were just installed, no persisted grants yet 103 assertNoPersistedUriPermission(); 104 105 // Now, let's grant ourselves some access 106 ReceiveUriActivity.clearStarted(); 107 grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION 108 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); 109 ReceiveUriActivity.waitForStart(); 110 111 // We should now have reading access, even before taking the persistable 112 // grant. Persisted grants should still be empty. 113 assertReadingClipAllowed(clip); 114 assertWritingClipNotAllowed(clip, "writing should have failed"); 115 assertNoPersistedUriPermission(); 116 117 // Take the read grant and verify we have it! 118 long before = System.currentTimeMillis(); 119 resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 120 long after = System.currentTimeMillis(); 121 assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after); 122 123 // Make sure we can't take a grant we don't have 124 try { 125 resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 126 fail("taking write should have failed"); 127 } catch (SecurityException expected) { 128 } 129 130 // Launch again giving ourselves persistable read and write access 131 ReceiveUriActivity.clearNewIntent(); 132 grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION 133 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION 134 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); 135 ReceiveUriActivity.waitForNewIntent(); 136 137 // Previous persisted grant should be unchanged 138 assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after); 139 140 // We should have both read and write; read is persisted, and write 141 // isn't persisted yet. 142 assertReadingClipAllowed(clip); 143 assertWritingClipAllowed(clip); 144 145 // Take again, but still only read; should just update timestamp 146 before = System.currentTimeMillis(); 147 resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 148 after = System.currentTimeMillis(); 149 assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after); 150 151 // And take yet again, both read and write 152 before = System.currentTimeMillis(); 153 resolver.takePersistableUriPermission(target, 154 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 155 after = System.currentTimeMillis(); 156 assertPersistedUriPermission(target, 157 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 158 before, after); 159 160 // Now drop the persisted grant; write first, then read 161 resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 162 assertPersistedUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after); 163 resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 164 assertNoPersistedUriPermission(); 165 166 // And even though we dropped the persistable grants, our activity is 167 // still running with the global grants (until reboot). 168 assertReadingClipAllowed(clip); 169 assertWritingClipAllowed(clip); 170 171 ReceiveUriActivity.finishCurInstanceSync(); 172 } 173 174 /** 175 * Validate behavior of prefix permission grants. 176 */ 177 @Test testGrantPrefixUriPermission()178 public void testGrantPrefixUriPermission() throws Exception { 179 final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo1"); 180 final Uri targetMeow = Uri.withAppendedPath(target, "meow"); 181 final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat"); 182 183 final ClipData clip = makeSingleClipData(target); 184 final ClipData clipMeow = makeSingleClipData(targetMeow); 185 final ClipData clipMeowCat = makeSingleClipData(targetMeowCat); 186 187 // Make sure we can't see the target 188 assertReadingClipNotAllowed(clip, "reading should have failed"); 189 assertWritingClipNotAllowed(clip, "writing should have failed"); 190 191 // Give ourselves prefix read access 192 ReceiveUriActivity.clearStarted(); 193 grantClipUriPermissionViaActivity(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION 194 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 195 ReceiveUriActivity.waitForStart(); 196 197 // Verify prefix read access 198 assertReadingClipNotAllowed(clip, "reading should have failed"); 199 assertReadingClipAllowed(clipMeow); 200 assertReadingClipAllowed(clipMeowCat); 201 assertWritingClipNotAllowed(clip, "writing should have failed"); 202 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 203 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 204 205 // Now give ourselves exact write access 206 ReceiveUriActivity.clearNewIntent(); 207 grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 208 ReceiveUriActivity.waitForNewIntent(); 209 210 // Verify we have exact write access, but not prefix write 211 assertReadingClipNotAllowed(clip, "reading should have failed"); 212 assertReadingClipAllowed(clipMeow); 213 assertReadingClipAllowed(clipMeowCat); 214 assertWritingClipAllowed(clip); 215 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 216 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 217 218 ReceiveUriActivity.finishCurInstanceSync(); 219 } 220 221 @Test testGrantPersistablePrefixUriPermission()222 public void testGrantPersistablePrefixUriPermission() { 223 final ContentResolver resolver = getContext().getContentResolver(); 224 225 final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo2"); 226 final Uri targetMeow = Uri.withAppendedPath(target, "meow"); 227 228 final ClipData clip = makeSingleClipData(target); 229 final ClipData clipMeow = makeSingleClipData(targetMeow); 230 231 // Make sure we can't see the target 232 assertReadingClipNotAllowed(clip, "reading should have failed"); 233 234 // Give ourselves prefix read access 235 ReceiveUriActivity.clearStarted(); 236 grantClipUriPermissionViaActivity(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION 237 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION 238 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 239 ReceiveUriActivity.waitForStart(); 240 241 // Verify prefix read access 242 assertReadingClipAllowed(clip); 243 assertReadingClipAllowed(clipMeow); 244 245 // Verify we can persist direct grant 246 long before = System.currentTimeMillis(); 247 resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 248 long after = System.currentTimeMillis(); 249 assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after); 250 251 // But we can't take anywhere under the prefix 252 try { 253 resolver.takePersistableUriPermission(targetMeow, 254 Intent.FLAG_GRANT_READ_URI_PERMISSION); 255 fail("taking under prefix should have failed"); 256 } catch (SecurityException expected) { 257 } 258 259 // Should still have access regardless of taking 260 assertReadingClipAllowed(clip); 261 assertReadingClipAllowed(clipMeow); 262 263 // And clean up our grants 264 resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 265 assertNoPersistedUriPermission(); 266 267 ReceiveUriActivity.finishCurInstanceSync(); 268 } 269 270 /** 271 * Validate behavior of directly granting/revoking permission grants. 272 */ 273 @Test testDirectGrantRevokeUriPermission()274 public void testDirectGrantRevokeUriPermission() throws Exception { 275 final ContentResolver resolver = getContext().getContentResolver(); 276 277 final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3"); 278 final Uri targetMeow = Uri.withAppendedPath(target, "meow"); 279 final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat"); 280 281 final ClipData clip = makeSingleClipData(target); 282 final ClipData clipMeow = makeSingleClipData(targetMeow); 283 final ClipData clipMeowCat = makeSingleClipData(targetMeowCat); 284 285 // Make sure we can't see the target 286 assertReadingClipNotAllowed(clipMeow, "reading should have failed"); 287 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 288 289 // Give ourselves some grants: 290 // /meow/cat WRITE|PERSISTABLE 291 // /meow READ|PREFIX 292 // /meow WRITE 293 grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION 294 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); 295 grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION 296 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 297 grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 298 299 long before = System.currentTimeMillis(); 300 resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 301 long after = System.currentTimeMillis(); 302 assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after); 303 304 // Verify they look good 305 assertReadingClipNotAllowed(clip, "reading should have failed"); 306 assertReadingClipAllowed(clipMeow); 307 assertReadingClipAllowed(clipMeowCat); 308 assertWritingClipNotAllowed(clip, "writing should have failed"); 309 assertWritingClipAllowed(clipMeow); 310 assertWritingClipAllowed(clipMeowCat); 311 312 // Revoke anyone with write under meow 313 revokeClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 314 315 // This should have nuked persisted permission at lower level, but it 316 // shoulnd't have touched our prefix read. 317 assertReadingClipNotAllowed(clip, "reading should have failed"); 318 assertReadingClipAllowed(clipMeow); 319 assertReadingClipAllowed(clipMeowCat); 320 assertWritingClipNotAllowed(clip, "writing should have failed"); 321 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 322 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 323 assertNoPersistedUriPermission(); 324 325 // Revoking read at top of tree should nuke everything else 326 revokeClipUriPermissionViaContext(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 327 assertReadingClipNotAllowed(clip, "reading should have failed"); 328 assertReadingClipNotAllowed(clipMeow, "reading should have failed"); 329 assertReadingClipNotAllowed(clipMeowCat, "reading should have failed"); 330 assertWritingClipNotAllowed(clip, "writing should have failed"); 331 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 332 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 333 assertNoPersistedUriPermission(); 334 } 335 336 /** 337 * Validate behavior of a direct permission grant, where the receiver of 338 * that permission revokes it. 339 */ 340 @Test testDirectGrantReceiverRevokeUriPermission()341 public void testDirectGrantReceiverRevokeUriPermission() throws Exception { 342 final ContentResolver resolver = getContext().getContentResolver(); 343 344 final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3"); 345 final Uri targetMeow = Uri.withAppendedPath(target, "meow"); 346 final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat"); 347 348 final ClipData clip = makeSingleClipData(target); 349 final ClipData clipMeow = makeSingleClipData(targetMeow); 350 final ClipData clipMeowCat = makeSingleClipData(targetMeowCat); 351 352 // Make sure we can't see the target 353 assertReadingClipNotAllowed(clipMeow, "reading should have failed"); 354 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 355 356 // Give ourselves some grants: 357 // /meow/cat WRITE|PERSISTABLE 358 // /meow READ|PREFIX 359 // /meow WRITE 360 grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION 361 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); 362 grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION 363 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 364 grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 365 366 long before = System.currentTimeMillis(); 367 resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 368 long after = System.currentTimeMillis(); 369 assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after); 370 371 // Verify they look good 372 assertReadingClipNotAllowed(clip, "reading should have failed"); 373 assertReadingClipAllowed(clipMeow); 374 assertReadingClipAllowed(clipMeowCat); 375 assertWritingClipNotAllowed(clip, "writing should have failed"); 376 assertWritingClipAllowed(clipMeow); 377 assertWritingClipAllowed(clipMeowCat); 378 379 // Revoke anyone with write under meow 380 getContext().revokeUriPermission(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 381 382 // This should have nuked persisted permission at lower level, but it 383 // shoulnd't have touched our prefix read. 384 assertReadingClipNotAllowed(clip, "reading should have failed"); 385 assertReadingClipAllowed(clipMeow); 386 assertReadingClipAllowed(clipMeowCat); 387 assertWritingClipNotAllowed(clip, "writing should have failed"); 388 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 389 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 390 assertNoPersistedUriPermission(); 391 392 // Revoking read at top of tree should nuke everything else 393 getContext().revokeUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION); 394 assertReadingClipNotAllowed(clip, "reading should have failed"); 395 assertReadingClipNotAllowed(clipMeow, "reading should have failed"); 396 assertReadingClipNotAllowed(clipMeowCat, "reading should have failed"); 397 assertWritingClipNotAllowed(clip, "writing should have failed"); 398 assertWritingClipNotAllowed(clipMeow, "writing should have failed"); 399 assertWritingClipNotAllowed(clipMeowCat, "writing should have failed"); 400 assertNoPersistedUriPermission(); 401 } 402 } 403