@Test public void testPreventNone() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventServiceInBackgroundPackages(false).preventBroadcastToBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); //noinspection deprecation, intentional test for deprecated method condom.preventWakingUpStoppedPackages(false); //noinspection deprecation dry_condom.preventWakingUpStoppedPackages(false); for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) with(ALL_SORT_OF_INTENTS, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
runInSeparateProcess(new TestService.Procedure() { @Override public void run(final Context context) { try { installCondomProcess(context, new CondomOptions().addKit(new NullDeviceIdKit())); fail("CondomKit is incompatible with CondomProcess"); } catch (final IllegalArgumentException ignored) {} }}); }
@Test public void testContentProviderOutboundJudge() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().setOutboundJudge(new OutboundJudge() { @Override public boolean shouldAllow(final OutboundType type, final @Nullable Intent intent, final String target_pkg) { final String settings_pkg = InstrumentationRegistry.getTargetContext().getPackageManager().resolveContentProvider(Settings.System.CONTENT_URI.getAuthority(), 0).packageName; return ! settings_pkg.equals(target_pkg); }}); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) { assertNull(context2test.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNull(context2test.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); } for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) { assertNotNull(context2test.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(context2test.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); } }
runInSeparateProcess(new TestService.Procedure() { @Override public void run(final Context context) { installCondomProcess(context, new CondomOptions().setOutboundJudge(sBlockAllJudge)); final ContentResolver resolver = context.getContentResolver(); withFakeSelfPackageName(new Runnable() { @Override public void run() { assertNull("Block access to provider", resolver.acquireContentProviderClient("com.oasisfeng.condom.test")); }}); }}); }
@Test public void testContentProvider() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Regular provider access final String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); assertNotNull(android_id); for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) { final String condom_android_id = Settings.Secure.getString(context2test.getContentResolver(), Settings.Secure.ANDROID_ID); assertEquals(android_id, condom_android_id); } context.mTestingStoppedProvider = true; for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) { // Prevent stopped packages, assertNull(context2test.getPackageManager().resolveContentProvider(TEST_AUTHORITY, 0)); assertNull(context2test.getContentResolver().acquireContentProviderClient(TEST_CONTENT_URI)); // Providers in system package should not be blocked. assertNotNull(context2test.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(context2test.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); } for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) { assertNotNull(context2test.getPackageManager().resolveContentProvider(TEST_AUTHORITY, 0)); assertNotNull(context2test.getContentResolver().acquireContentProviderClient(TEST_CONTENT_URI)); } context.mTestingStoppedProvider = false; } private static final String TEST_AUTHORITY = "com.oasisfeng.condom.test";
@Test public void testPreventBroadcastToBackgroundPackages() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventBroadcastToBackgroundPackages(true); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); final int extra_flag = SDK_INT >= N ? CondomCore.FLAG_RECEIVER_EXCLUDE_BACKGROUND : FLAG_RECEIVER_REGISTERED_ONLY; for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) with(ALL_SORT_OF_INTENTS, allBroadcastApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(FLAG_EXCLUDE_STOPPED_PACKAGES | extra_flag)); for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) with(ALL_SORT_OF_INTENTS, allBroadcastApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
/** * Install the condom protection for current process if it is not the default process. * * <p>This method must be called in {@link Application#onCreate()} to eliminate potential leakage. */ public static void installExceptDefaultProcess(final Application app) { installExceptDefaultProcess(app, new CondomOptions()); }
runInSeparateProcess(new TestService.Procedure() { @Override public void run(final Context context) { testOrderedBroadcast(context, new Intent(ACTION_TEST).setPackage(context.getPackageName()), true); installCondomProcess(context, new CondomOptions().setOutboundJudge(sBlockAllJudge)); context.sendBroadcast(new Intent(ACTION_TEST).setPackage(context.getPackageName())); // Ensure no exception testOrderedBroadcast(context, new Intent(ACTION_TEST), true); testOrderedBroadcast(context, new Intent(ACTION_TEST).setPackage(context.getPackageName()), true); // Self targeted should always be allowed. withFakeSelfPackageName(new Runnable() { @Override public void run() { testOrderedBroadcast(context, new Intent(ACTION_TEST).setPackage(context.getPackageName()), false); }}); }}); }
@Test public void testSelfTargeted() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Self-targeting test final String self_pkg = condom.getPackageName(); final Intent[] self_targeted_intents = new Intent[] { intent().setPackage(self_pkg), intent().setComponent(new ComponentName(self_pkg, "X")) }; for (final Context context2test : new Context[] {condom, condom.getApplicationContext(), dry_condom, dry_condom.getApplicationContext()}) with(self_targeted_intents, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
@Test public void testPreventBroadcastToBackgroundPackages() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventBroadcastToBackgroundPackages(true); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); final int extra_flag = SDK_INT >= N ? CondomCore.FLAG_RECEIVER_EXCLUDE_BACKGROUND : FLAG_RECEIVER_REGISTERED_ONLY; with(ALL_SORT_OF_INTENTS, allBroadcastApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(FLAG_EXCLUDE_STOPPED_PACKAGES | extra_flag)); with(ALL_SORT_OF_INTENTS, allBroadcastApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
public static @CheckResult CondomContext wrap(final Context base, final @Nullable @Size(max=13) String tag) { return wrap(base, tag, new CondomOptions()); }
@Test public void testPreventWakingUpStoppedPackages_IncludingDryRun() { final Intent[] intents_with_inc_stop = ALL_SORT_OF_INTENTS.clone(); for (int i = 0; i < intents_with_inc_stop.length; i++) intents_with_inc_stop[i] = new Intent(intents_with_inc_stop[i]).addFlags(FLAG_INCLUDE_STOPPED_PACKAGES); final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().preventBroadcastToBackgroundPackages(false).preventServiceInBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) with(intents_with_inc_stop, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(FLAG_EXCLUDE_STOPPED_PACKAGES)); for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) with(intents_with_inc_stop, allBroadcastAndServiceApis(context2test), context.EXPECT_BASE_CALLED, context.expectFlags(FLAG_INCLUDE_STOPPED_PACKAGES)); }
@Test public void testOutboundJudge() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().setOutboundJudge(new OutboundJudge() { @Override public boolean shouldAllow(final OutboundType type, final @Nullable Intent intent, final String target_pkg) { mNumOutboundJudgeCalled.incrementAndGet(); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true));
@Test @SuppressLint("HardwareIds") public void testNullDeviceIdKit() throws NameNotFoundException { final CondomContext condom = CondomContext.wrap(new ContextWrapper(context), "NullDeviceId", new CondomOptions().addKit(new NullDeviceIdKit())); final TelephonyManager tm = (TelephonyManager) condom.getSystemService(Context.TELEPHONY_SERVICE); assertNotNull(tm); assertTrue(tm.getClass().getName().startsWith(NullDeviceIdKit.class.getName())); final TelephonyManager app_tm = (TelephonyManager) condom.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); assertNotNull(app_tm); assertTrue(app_tm.getClass().getName().startsWith(NullDeviceIdKit.class.getName())); assertPermission(condom, READ_PHONE_STATE, true); assertNull(tm.getDeviceId()); if (SDK_INT >= LOLLIPOP) { if (SDK_INT >= M) assertNull(tm.getDeviceId(0)); assertNull(tm.getImei()); assertNull(tm.getImei(0)); if (SDK_INT >= O) assertNull(tm.getMeid()); if (SDK_INT >= O) assertNull(tm.getMeid(0)); } assertNull(tm.getSimSerialNumber()); assertNull(tm.getLine1Number()); assertNull(tm.getSubscriberId()); }
runInSeparateProcess(new TestService.Procedure() { @Override public void run(final Context context) { final Intent intent = new Intent(context, TestService.class); assertNotNull("Test service is not properly setup.", context.startService(intent)); assertTrue(context.stopService(intent)); installCondomProcess(context, new CondomOptions().setOutboundJudge(sBlockAllJudge)); withFakeSelfPackageName(new Runnable() { @Override public void run() { assertNull(context.startService(intent)); }}); // Block by outbound judge assertTrue(context.stopService(intent)); }}); // TODO: More cases
@Test public void testSelfTargeted() { final TestContext context = new TestContext(); final CondomContext condom = CondomContext.wrap(context, TAG), dry_condom = CondomContext.wrap(context, TAG, new CondomOptions().setDryRun(true)); // Self-targeting test final String self_pkg = condom.getPackageName(); final Intent[] self_targeted_intents = new Intent[] { intent().setPackage(self_pkg), intent().setComponent(new ComponentName(self_pkg, "X")) }; with(self_targeted_intents, allBroadcastApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allServiceApis(condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allBroadcastApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); with(self_targeted_intents, allServiceApis(dry_condom), context.EXPECT_BASE_CALLED, context.expectFlags(0)); }
runInSeparateProcess(new TestService.Procedure() { @Override public void run(final Context context) { installCondomProcess(context, new CondomOptions()); final ContentResolver resolver = context.getContentResolver(); // Regular provider access final String android_id = Settings.Secure.getString(resolver, Settings.Secure.ANDROID_ID); assertNotNull("Regular access to ANDROID_ID", android_id); final ContentProviderClient client = resolver.acquireContentProviderClient(Settings.AUTHORITY); assertNotNull("Regular access to Settings provider", client); client.release(); withFakeSelfPackageName(new Runnable() { @Override public void run() { assertNotNull("Regular access to content provider", resolver.acquireContentProviderClient("com.oasisfeng.condom.test")); }}); }});
@Test public void testPreventServiceInBackgroundPackages() { Assume.assumeTrue(SDK_INT < O); final TestContext context = new TestContext(); context.mTestingBackgroundUid = true; final CondomOptions options = new CondomOptions().preventServiceInBackgroundPackages(true).preventBroadcastToBackgroundPackages(false); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); for (final Context context2test : new Context[] {condom, condom.getApplicationContext()}) { final List<ResolveInfo> services = context2test.getPackageManager().queryIntentServices(intent(), 0); assertEquals(3, services.size()); context.assertBaseCalled(); final ResolveInfo resolve = context2test.getPackageManager().resolveService(intent(), 0); assertEquals("non.bg.service", resolve.serviceInfo.packageName); context.assertBaseCalled(); } for (final Context context2test : new Context[] {dry_condom, dry_condom.getApplicationContext()}) { final List<ResolveInfo> services = context2test.getPackageManager().queryIntentServices(intent(), 0); assertEquals(4, services.size()); context.assertBaseCalled(); assertEquals(7777777, context2test.getPackageManager().resolveService(intent(), 0).serviceInfo.applicationInfo.uid); context.assertBaseCalled(); } }
@Test public void testContentProviderOutboundJudge() { final TestContext context = new TestContext(); final CondomOptions options = new CondomOptions().setOutboundJudge(new OutboundJudge() { @Override public boolean shouldAllow(final OutboundType type, final @Nullable Intent intent, final String target_pkg) { final String settings_pkg = InstrumentationRegistry.getTargetContext().getPackageManager().resolveContentProvider(Settings.System.CONTENT_URI.getAuthority(), 0).packageName; return ! settings_pkg.equals(target_pkg); }}); final CondomContext condom = CondomContext.wrap(context, TAG, options), dry_condom = CondomContext.wrap(context, TAG, options.setDryRun(true)); assertNull(condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNotNull(dry_condom.getPackageManager().resolveContentProvider(Settings.AUTHORITY, 0)); assertNull(condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); assertNotNull(dry_condom.getContentResolver().acquireContentProviderClient(Settings.System.CONTENT_URI)); }
@Test public void testBasicKit() throws ReflectiveOperationException, NameNotFoundException { final ActivityManager am = createActivityManager(context); final CondomOptions option = new CondomOptions().addKit(new CondomKit() { @Override public void onRegister(final CondomKitRegistry registry) { registry.registerSystemService(Context.ACTIVITY_SERVICE, new SystemServiceSupplier() { @Override public Object getSystemService(final Context context, final String name) { return am; }}); registry.addPermissionSpoof(WRITE_SETTINGS); registry.addPermissionSpoof(ACCESS_COARSE_LOCATION); }}); final CondomContext condom = CondomContext.wrap(new ContextWrapper(context), "KitTest", option); assertEquals(am, condom.getSystemService(Context.ACTIVITY_SERVICE)); assertEquals(am, condom.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE)); Assert.assertNotNull(condom.getSystemService(Context.NOTIFICATION_SERVICE)); // Service not registered in kit assertPermission(condom, WRITE_SETTINGS, true); assertPermission(condom.getApplicationContext(), WRITE_SETTINGS, true); assertPermission(condom, ACCESS_COARSE_LOCATION, true); assertPermission(condom.getApplicationContext(), ACCESS_COARSE_LOCATION, true); assertPermission(condom, WRITE_SECURE_SETTINGS, false); // Permission not registered to spoof in kit assertPermission(condom.getApplicationContext(), WRITE_SECURE_SETTINGS, false); }