blob: 41cddf582685eb50a749aeaeda3b286f78285644 [file] [log] [blame]
/*
* Copyright (C) 2009 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 com.android.cts.usespermissiondiffcertapp;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.util.Log;
/**
* Tests that signature-enforced permissions cannot be accessed by apps signed
* with different certs than app that declares the permission.
*
* Accesses app cts/tests/appsecurity-tests/test-apps/PermissionDeclareApp/...
*/
public class AccessPermissionWithDiffSigTest extends AndroidTestCase {
static final ComponentName GRANT_URI_PERM_COMP
= new ComponentName("com.android.cts.permissiondeclareapp",
"com.android.cts.permissiondeclareapp.GrantUriPermission");
static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
static final Uri PERM_URI_PATH = Uri.parse("content://ctspermissionwithsignaturepath");
static final Uri PERM_URI_PATH_RESTRICTING = Uri.parse(
"content://ctspermissionwithsignaturepathrestricting");
static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
static final String EXPECTED_MIME_TYPE = "got/theMIME";
public void assertReadingContentUriNotAllowed(Uri uri, String msg) {
try {
getContext().getContentResolver().query(uri, null, null, null, null);
fail("expected SecurityException reading " + uri + ": " + msg);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
}
}
public void assertReadingContentUriAllowed(Uri uri) {
try {
getContext().getContentResolver().query(uri, null, null, null, null);
} catch (SecurityException e) {
fail("unexpected SecurityException reading " + uri);
}
}
public void assertReadingClipNotAllowed(ClipData clip, String msg) {
for (int i=0; i<clip.getItemCount(); i++) {
ClipData.Item item = clip.getItemAt(i);
Uri uri = item.getUri();
if (uri != null) {
assertReadingContentUriNotAllowed(uri, msg);
} else {
Intent intent = item.getIntent();
uri = intent.getData();
if (uri != null) {
assertReadingContentUriNotAllowed(uri, msg);
}
ClipData intentClip = intent.getClipData();
if (intentClip != null) {
assertReadingClipNotAllowed(intentClip, msg);
}
}
}
}
public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
try {
getContext().getContentResolver().insert(uri, new ContentValues());
fail("expected SecurityException writing " + uri + ": " + msg);
} catch (SecurityException expected) {
assertNotNull("security exception's error message.", expected.getMessage());
}
}
public void assertWritingContentUriAllowed(Uri uri) {
try {
getContext().getContentResolver().insert(uri, new ContentValues());
} catch (SecurityException e) {
fail("unexpected SecurityException writing " + uri);
}
}
public void assertWritingClipNotAllowed(ClipData clip, String msg) {
for (int i=0; i<clip.getItemCount(); i++) {
ClipData.Item item = clip.getItemAt(i);
Uri uri = item.getUri();
if (uri != null) {
assertWritingContentUriNotAllowed(uri, msg);
} else {
Intent intent = item.getIntent();
uri = intent.getData();
if (uri != null) {
assertWritingContentUriNotAllowed(uri, msg);
}
ClipData intentClip = intent.getClipData();
if (intentClip != null) {
assertWritingClipNotAllowed(intentClip, msg);
}
}
}
}
/**
* Test that the ctspermissionwithsignature content provider cannot be read,
* since this app lacks the required certs
*/
public void testReadProviderWithDiff() {
assertReadingContentUriRequiresPermission(PERM_URI,
"com.android.cts.permissionWithSignature");
}
/**
* Test that the ctspermissionwithsignature content provider cannot be written,
* since this app lacks the required certs
*/
public void testWriteProviderWithDiff() {
assertWritingContentUriRequiresPermission(PERM_URI,
"com.android.cts.permissionWithSignature");
}
/**
* Test that the ctsprivateprovider content provider cannot be read,
* since it is not exported from its app.
*/
public void testReadProviderWhenPrivate() {
assertReadingContentUriNotAllowed(PRIV_URI,
"shouldn't read private provider");
}
/**
* Test that the ctsprivateprovider content provider cannot be written,
* since it is not exported from its app.
*/
public void testWriteProviderWhenPrivate() {
assertWritingContentUriNotAllowed(PRIV_URI,
"shouldn't write private provider");
}
public static ClipData makeSingleClipData(Uri uri) {
return new ClipData("foo", new String[] { "foo/bar" },
new ClipData.Item(uri));
}
public static ClipData makeMultiClipData(Uri uri) {
Uri grantClip1Uri = Uri.withAppendedPath(uri, "clip1");
Uri grantClip2Uri = Uri.withAppendedPath(uri, "clip2");
Uri grantClip3Uri = Uri.withAppendedPath(uri, "clip3");
Uri grantClip4Uri = Uri.withAppendedPath(uri, "clip4");
Uri grantClip5Uri = Uri.withAppendedPath(uri, "clip5");
ClipData clip = new ClipData("foo", new String[] { "foo/bar" },
new ClipData.Item(grantClip1Uri));
clip.addItem(new ClipData.Item(grantClip2Uri));
// Intents in the ClipData should allow their data: and clip URIs
// to be granted, but only respect the grant flags of the top-level
// Intent.
clip.addItem(new ClipData.Item(new Intent(Intent.ACTION_VIEW, grantClip3Uri)));
Intent intent = new Intent(Intent.ACTION_VIEW, grantClip4Uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
clip.addItem(new ClipData.Item(intent));
intent = new Intent(Intent.ACTION_VIEW);
intent.setClipData(new ClipData("foo", new String[] { "foo/bar" },
new ClipData.Item(grantClip5Uri)));
clip.addItem(new ClipData.Item(intent));
return clip;
}
public static Intent makeClipIntent(ClipData clip, int flags) {
Intent intent = new Intent();
intent.setClipData(clip);
intent.addFlags(flags);
return intent;
}
public static Intent makeClipIntent(Uri uri, int flags) {
return makeClipIntent(makeMultiClipData(uri), flags);
}
public void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
Uri grantDataUri = Uri.withAppendedPath(uri, "data");
Intent grantIntent = new Intent();
grantIntent.setData(grantDataUri);
grantIntent.addFlags(mode | Intent.FLAG_ACTIVITY_NEW_TASK);
grantIntent.setClass(getContext(), ReceiveUriActivity.class);
try {
ReceiveUriActivity.clearStarted();
getContext().startActivity(grantIntent);
ReceiveUriActivity.waitForStart();
fail("expected SecurityException granting " + grantDataUri + " to activity");
} catch (SecurityException e) {
// This is what we want.
}
grantIntent = makeClipIntent(uri, mode | Intent.FLAG_ACTIVITY_NEW_TASK);
grantIntent.setClass(getContext(), ReceiveUriActivity.class);
try {
ReceiveUriActivity.clearStarted();
getContext().startActivity(grantIntent);
ReceiveUriActivity.waitForStart();
fail("expected SecurityException granting " + grantIntent.getClipData() + " to activity");
} catch (SecurityException e) {
// This is what we want.
}
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantReadUriActivityPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantWriteUriActivityPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantReadUriActivityPrivateToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantWriteUriActivityPrivateToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
public void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
Uri grantDataUri = Uri.withAppendedPath(uri, "data");
Intent grantIntent = new Intent();
grantIntent.setData(grantDataUri);
grantIntent.addFlags(mode);
grantIntent.setClass(getContext(), ReceiveUriService.class);
try {
getContext().startService(grantIntent);
fail("expected SecurityException granting " + grantDataUri + " to service");
} catch (SecurityException e) {
// This is what we want.
}
grantIntent = makeClipIntent(uri, mode);
grantIntent.setClass(getContext(), ReceiveUriService.class);
try {
getContext().startService(grantIntent);
fail("expected SecurityException granting " + grantIntent.getClipData() + " to service");
} catch (SecurityException e) {
// This is what we want.
}
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantReadUriServicePermissionToSelf() {
doTryGrantUriServicePermissionToSelf(
Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantWriteUriServicePermissionToSelf() {
doTryGrantUriServicePermissionToSelf(
Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantReadUriServicePrivateToSelf() {
doTryGrantUriServicePermissionToSelf(
Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that we can't grant a permission to ourself.
*/
public void testGrantWriteUriServicePrivateToSelf() {
doTryGrantUriServicePermissionToSelf(
Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
static class GrantResultReceiver extends BroadcastReceiver {
boolean mHaveResult = false;
boolean mGoodResult = false;
boolean mSucceeded = false;
@Override
public void onReceive(Context context, Intent intent) {
synchronized (this) {
mHaveResult = true;
switch (getResultCode()) {
case 100:
mGoodResult = true;
mSucceeded = false;
break;
case 101:
mGoodResult = true;
mSucceeded = true;
break;
default:
mGoodResult = false;
break;
}
notifyAll();
}
}
void assertSuccess(String failureMessage) {
synchronized (this) {
final long startTime = SystemClock.uptimeMillis();
while (!mHaveResult) {
try {
wait(5000);
} catch (InterruptedException e) {
}
if (SystemClock.uptimeMillis() >= (startTime+5000)) {
throw new RuntimeException("Timeout");
}
}
if (!mGoodResult) {
fail("Broadcast receiver did not return good result");
}
if (!mSucceeded) {
fail(failureMessage);
}
}
}
void assertFailure(String failureMessage) {
synchronized (this) {
final long startTime = SystemClock.uptimeMillis();
while (!mHaveResult) {
try {
wait(5000);
} catch (InterruptedException e) {
}
if (SystemClock.uptimeMillis() >= (startTime+5000)) {
throw new RuntimeException("Timeout");
}
}
if (!mGoodResult) {
fail("Broadcast receiver did not return good result");
}
if (mSucceeded) {
fail(failureMessage);
}
}
}
}
void grantUriPermissionFail(Uri uri, int mode, boolean service) {
Uri grantDataUri = Uri.withAppendedPath(uri, "data");
Intent grantIntent = new Intent();
grantIntent.setData(grantDataUri);
grantIntent.addFlags(mode);
grantIntent.setClass(getContext(),
service ? ReceiveUriService.class : ReceiveUriActivity.class);
Intent intent = new Intent();
intent.setComponent(GRANT_URI_PERM_COMP);
intent.putExtra("intent", grantIntent);
intent.putExtra("service", service);
GrantResultReceiver receiver = new GrantResultReceiver();
getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
receiver.assertFailure("Able to grant URI permission to " + grantDataUri + " when should not");
grantIntent = makeClipIntent(uri, mode);
grantIntent.setClass(getContext(),
service ? ReceiveUriService.class : ReceiveUriActivity.class);
intent = new Intent();
intent.setComponent(GRANT_URI_PERM_COMP);
intent.putExtra("intent", grantIntent);
intent.putExtra("service", service);
receiver = new GrantResultReceiver();
getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
receiver.assertFailure("Able to grant URI permission to " + grantIntent.getClipData()
+ " when should not");
}
void doTestGrantUriPermissionFail(Uri uri) {
grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
grantUriPermissionFail(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
grantUriPermissionFail(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
}
/**
* Test that the ctspermissionwithsignature content provider can not grant
* URI permissions to others.
*/
public void testGrantPermissionNonGrantingFail() {
doTestGrantUriPermissionFail(PERM_URI);
}
/**
* Test that the ctspermissionwithsignaturegranting content provider can not grant
* URI permissions to paths outside of the grant tree
*/
public void testGrantPermissionOutsideGrantingFail() {
doTestGrantUriPermissionFail(PERM_URI_GRANTING);
doTestGrantUriPermissionFail(Uri.withAppendedPath(PERM_URI_GRANTING, "invalid"));
}
/**
* Test that the ctsprivateprovider content provider can not grant
* URI permissions to others.
*/
public void testGrantPrivateNonGrantingFail() {
doTestGrantUriPermissionFail(PRIV_URI);
}
/**
* Test that the ctsprivateprovidergranting content provider can not grant
* URI permissions to paths outside of the grant tree
*/
public void testGrantPrivateOutsideGrantingFail() {
doTestGrantUriPermissionFail(PRIV_URI_GRANTING);
doTestGrantUriPermissionFail(Uri.withAppendedPath(PRIV_URI_GRANTING, "invalid"));
}
void grantClipUriPermission(ClipData clip, int mode, boolean service) {
Intent grantIntent = new Intent();
if (clip.getItemCount() == 1) {
grantIntent.setData(clip.getItemAt(0).getUri());
} else {
grantIntent.setClipData(clip);
// Make this Intent unique from the one that started it.
for (int i=0; i<clip.getItemCount(); i++) {
Uri uri = clip.getItemAt(i).getUri();
if (uri != null) {
grantIntent.addCategory(uri.toString());
}
}
}
grantIntent.addFlags(mode);
grantIntent.setClass(getContext(),
service ? ReceiveUriService.class : ReceiveUriActivity.class);
Intent intent = new Intent();
intent.setComponent(GRANT_URI_PERM_COMP);
intent.putExtra("intent", grantIntent);
intent.putExtra("service", service);
getContext().sendBroadcast(intent);
}
void assertReadingClipAllowed(ClipData clip) {
for (int i=0; i<clip.getItemCount(); i++) {
ClipData.Item item = clip.getItemAt(i);
Uri uri = item.getUri();
if (uri != null) {
Cursor c = getContext().getContentResolver().query(uri,
null, null, null, null);
if (c != null) {
c.close();
}
} else {
Intent intent = item.getIntent();
uri = intent.getData();
if (uri != null) {
Cursor c = getContext().getContentResolver().query(uri,
null, null, null, null);
if (c != null) {
c.close();
}
}
ClipData intentClip = intent.getClipData();
if (intentClip != null) {
assertReadingClipAllowed(intentClip);
}
}
}
}
void doTestGrantActivityUriReadPermission(Uri uri, boolean useClip) {
final Uri subUri = Uri.withAppendedPath(uri, "foo");
final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
// Precondition: no current access.
assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
// --------------------------------
ReceiveUriActivity.clearStarted();
grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
ReceiveUriActivity.waitForStart();
// See if we now have access to the provider.
assertReadingClipAllowed(subClip);
// But not writing.
assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");
// And not to the base path.
assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
// And not to a sub path.
assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
// --------------------------------
ReceiveUriActivity.clearNewIntent();
grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
ReceiveUriActivity.waitForNewIntent();
if (false) {
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(10000);
} catch (InterruptedException e) {
}
}
}
// See if we now have access to the provider.
assertReadingClipAllowed(sub2Clip);
// And still have access to the original URI.
assertReadingClipAllowed(subClip);
// But not writing.
assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");
// And not to the base path.
assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
// And not to a sub path.
assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");
// And make sure we can't generate a permission to a running activity.
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(uri, "hah"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(uri, "hah"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// --------------------------------
// Dispose of activity.
ReceiveUriActivity.finishCurInstanceSync();
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(100);
} catch (InterruptedException e) {
}
}
// Ensure reading no longer allowed.
assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
}
void assertWritingClipAllowed(ClipData clip) {
for (int i=0; i<clip.getItemCount(); i++) {
ClipData.Item item = clip.getItemAt(i);
Uri uri = item.getUri();
if (uri != null) {
getContext().getContentResolver().insert(uri, new ContentValues());
} else {
Intent intent = item.getIntent();
uri = intent.getData();
if (uri != null) {
getContext().getContentResolver().insert(uri, new ContentValues());
}
ClipData intentClip = intent.getClipData();
if (intentClip != null) {
assertWritingClipAllowed(intentClip);
}
}
}
}
void doTestGrantActivityUriWritePermission(Uri uri, boolean useClip) {
final Uri subUri = Uri.withAppendedPath(uri, "foo");
final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
// Precondition: no current access.
assertWritingClipNotAllowed(subClip, "shouldn't write when starting test");
assertWritingClipNotAllowed(sub2Clip, "shouldn't write when starting test");
// --------------------------------
ReceiveUriActivity.clearStarted();
grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
ReceiveUriActivity.waitForStart();
// See if we now have access to the provider.
assertWritingClipAllowed(subClip);
// But not reading.
assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");
// And not to the base path.
assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
// And not a sub-path.
assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
// --------------------------------
ReceiveUriActivity.clearNewIntent();
grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
ReceiveUriActivity.waitForNewIntent();
if (false) {
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(10000);
} catch (InterruptedException e) {
}
}
}
// See if we now have access to the provider.
assertWritingClipAllowed(sub2Clip);
// And still have access to the original URI.
assertWritingClipAllowed(subClip);
// But not reading.
assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");
// And not to the base path.
assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
// And not a sub-path.
assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
// And make sure we can't generate a permission to a running activity.
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(uri, "hah"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(uri, "hah"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// --------------------------------
// Dispose of activity.
ReceiveUriActivity.finishCurInstanceSync();
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(100);
} catch (InterruptedException e) {
}
}
// Ensure writing no longer allowed.
assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
}
/**
* Test that the ctspermissionwithsignaturegranting content provider can grant a read
* permission.
*/
public void testGrantReadPermissionFromStartActivity() {
doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, false);
doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, true);
}
/**
* Test that the ctspermissionwithsignaturegranting content provider can grant a write
* permission.
*/
public void testGrantWritePermissionFromStartActivity() {
doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, true);
doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, false);
}
/**
* Test that the ctsprivateprovidergranting content provider can grant a read
* permission.
*/
public void testGrantReadPrivateFromStartActivity() {
doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, false);
doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, true);
}
/**
* Test that the ctsprivateprovidergranting content provider can grant a write
* permission.
*/
public void testGrantWritePrivateFromStartActivity() {
doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, true);
doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, false);
}
void doTestGrantServiceUriReadPermission(Uri uri, boolean useClip) {
final Uri subUri = Uri.withAppendedPath(uri, "foo");
final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
ReceiveUriService.stop(getContext());
final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
// Precondition: no current access.
assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
// --------------------------------
ReceiveUriService.clearStarted();
grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
ReceiveUriService.waitForStart();
int firstStartId = ReceiveUriService.getCurStartId();
// See if we now have access to the provider.
assertReadingClipAllowed(subClip);
// But not writing.
assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");
// And not to the base path.
assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
// And not to a sub path.
assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
// --------------------------------
// Send another Intent to it.
ReceiveUriService.clearStarted();
grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
ReceiveUriService.waitForStart();
if (false) {
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(10000);
} catch (InterruptedException e) {
}
}
}
// See if we now have access to the provider.
assertReadingClipAllowed(sub2Clip);
// And still to the previous URI.
assertReadingClipAllowed(subClip);
// But not writing.
assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");
// And not to the base path.
assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
// And not to a sub path.
assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");
// --------------------------------
// Stop the first command.
ReceiveUriService.stopCurWithId(firstStartId);
// Ensure reading no longer allowed.
assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
// And make sure we can't generate a permission to a running service.
doTryGrantUriActivityPermissionToSelf(subUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
doTryGrantUriActivityPermissionToSelf(subUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// --------------------------------
// Dispose of service.
ReceiveUriService.stopSync(getContext());
// Ensure reading no longer allowed.
assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
}
void doTestGrantServiceUriWritePermission(Uri uri, boolean useClip) {
final Uri subUri = Uri.withAppendedPath(uri, "foo");
final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
ReceiveUriService.stop(getContext());
final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
// Precondition: no current access.
assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
// --------------------------------
ReceiveUriService.clearStarted();
grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
ReceiveUriService.waitForStart();
int firstStartId = ReceiveUriService.getCurStartId();
// See if we now have access to the provider.
assertWritingClipAllowed(subClip);
// But not reading.
assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");
// And not to the base path.
assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
// And not a sub-path.
assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
// --------------------------------
// Send another Intent to it.
ReceiveUriService.clearStarted();
grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
ReceiveUriService.waitForStart();
// See if we now have access to the provider.
assertWritingClipAllowed(sub2Clip);
// And still to the previous URI.
assertWritingClipAllowed(subClip);
// But not reading.
assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");
// And not to the base path.
assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
// And not a sub-path.
assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
if (false) {
synchronized (this) {
Log.i("**", "******************************* WAITING!!!");
try {
wait(10000);
} catch (InterruptedException e) {
}
}
}
// --------------------------------
// Stop the first command.
ReceiveUriService.stopCurWithId(firstStartId);
// Ensure writing no longer allowed.
assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
// And make sure we can't generate a permission to a running service.
doTryGrantUriActivityPermissionToSelf(subUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
doTryGrantUriActivityPermissionToSelf(subUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// --------------------------------
// Dispose of service.
ReceiveUriService.stopSync(getContext());
// Ensure writing no longer allowed.
assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
}
public void testGrantReadPermissionFromStartService() {
doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, false);
doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, true);
}
public void testGrantWritePermissionFromStartService() {
doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, false);
doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, true);
}
public void testGrantReadPrivateFromStartService() {
doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, false);
doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, true);
}
public void testGrantWritePrivateFromStartService() {
doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, false);
doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, true);
}
/**
* Test that ctspermissionwithsignaturepath can't grant read permissions
* on paths it doesn't have permission to.
*/
public void testGrantReadUriActivityPathPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that ctspermissionwithsignaturepath can't grant write permissions
* on paths it doesn't have permission to.
*/
public void testGrantWriteUriActivityPathPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
/**
* Test that ctspermissionwithsignaturepath can't grant read permissions
* on paths it doesn't have permission to.
*/
public void testGrantReadUriActivitySubPathPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PERM_URI_PATH, "foo"),
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
/**
* Test that ctspermissionwithsignaturepath can't grant write permissions
* on paths it doesn't have permission to.
*/
public void testGrantWriteUriActivitySubPathPermissionToSelf() {
doTryGrantUriActivityPermissionToSelf(
Uri.withAppendedPath(PERM_URI_PATH, "foo"),
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
/**
* Test that the ctspermissionwithsignaturepath content provider can grant a read
* permission.
*/
public void testGrantReadPathPermissionFromStartActivity() {
doTestGrantActivityUriReadPermission(PERM_URI_PATH, false);
doTestGrantActivityUriReadPermission(PERM_URI_PATH, true);
}
/**
* Test that the ctspermissionwithsignaturepath content provider can grant a write
* permission.
*/
public void testGrantWritePathPermissionFromStartActivity() {
doTestGrantActivityUriWritePermission(PERM_URI_PATH, false);
doTestGrantActivityUriWritePermission(PERM_URI_PATH, true);
}
/**
* Test that the ctspermissionwithsignaturepath content provider can grant a read
* permission.
*/
public void testGrantReadPathPermissionFromStartService() {
doTestGrantServiceUriReadPermission(PERM_URI_PATH, false);
doTestGrantServiceUriReadPermission(PERM_URI_PATH, true);
}
/**
* Test that the ctspermissionwithsignaturepath content provider can grant a write
* permission.
*/
public void testGrantWritePathPermissionFromStartService() {
doTestGrantServiceUriWritePermission(PERM_URI_PATH, false);
doTestGrantServiceUriWritePermission(PERM_URI_PATH, true);
}
/**
* Verify that we can access paths outside the {@code path-permission}
* protections, which should only rely on {@code provider} permissions.
*/
public void testRestrictingProviderNoMatchingPath() {
assertReadingContentUriAllowed(PERM_URI_PATH_RESTRICTING);
assertWritingContentUriAllowed(PERM_URI_PATH_RESTRICTING);
// allowed by no top-level permission
final Uri test = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("fo").build();
assertReadingContentUriAllowed(test);
assertWritingContentUriAllowed(test);
}
/**
* Verify that paths under {@code path-permission} restriction aren't
* allowed, even though the {@code provider} requires no permissions.
*/
public void testRestrictingProviderMatchingPathDenied() {
// rejected by "foo" prefix
final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("foo").build();
assertReadingContentUriNotAllowed(test1, null);
assertWritingContentUriNotAllowed(test1, null);
// rejected by "foo" prefix
final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
.appendPath("foo").appendPath("ba").build();
assertReadingContentUriNotAllowed(test2, null);
assertWritingContentUriNotAllowed(test2, null);
}
/**
* Verify that at least one {@code path-permission} rule will grant access,
* even if the caller doesn't hold another matching {@code path-permission}.
*/
public void testRestrictingProviderMultipleMatchingPath() {
// allowed by narrow "foo/bar" prefix
final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon()
.appendPath("foo").appendPath("bar").build();
assertReadingContentUriAllowed(test1);
assertWritingContentUriAllowed(test1);
// allowed by narrow "foo/bar" prefix
final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
.appendPath("foo").appendPath("bar2").build();
assertReadingContentUriAllowed(test2);
assertWritingContentUriAllowed(test2);
}
public void testGetMimeTypePermission() {
// Precondition: no current access.
assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
// All apps should be able to get MIME type regardless of permission.
assertEquals(getContext().getContentResolver().getType(PERM_URI), EXPECTED_MIME_TYPE);
}
public void testGetMimeTypePrivate() {
// Precondition: no current access.
assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
// All apps should be able to get MIME type even if provider is private.
assertEquals(getContext().getContentResolver().getType(PRIV_URI), EXPECTED_MIME_TYPE);
}
}