1 /* 2 * Copyright (C) 2021 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 android.devicepolicy.cts; 18 19 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; 20 import static android.content.pm.PackageManager.FEATURE_SECURE_LOCK_SCREEN; 21 22 import static com.android.bedstead.remotedpc.RemoteDpc.DPC_COMPONENT_NAME; 23 24 import static com.google.common.truth.Truth.assertThat; 25 26 import static org.junit.Assert.fail; 27 28 import android.app.admin.RemoteDevicePolicyManager; 29 import android.content.ComponentName; 30 31 import com.android.bedstead.harrier.BedsteadJUnit4; 32 import com.android.bedstead.harrier.DeviceState; 33 import com.android.bedstead.harrier.annotations.Postsubmit; 34 import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature; 35 import com.android.bedstead.harrier.annotations.RequireFeature; 36 import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest; 37 import com.android.bedstead.harrier.policies.LockscreenPolicyWithUnifiedChallenge; 38 import com.android.bedstead.harrier.policies.ScreenCaptureDisabled; 39 import com.android.bedstead.testapp.TestApp; 40 import com.android.bedstead.testapp.TestAppInstance; 41 42 import org.junit.ClassRule; 43 import org.junit.Rule; 44 import org.junit.runner.RunWith; 45 46 import java.util.function.BiConsumer; 47 48 /** 49 * Test that DevicePolicyManager getters that accept "ComponentName who" argument don't allow a 50 * different app to probe for admins when policy is set: those getters should only allow either 51 * calls where "who" is null or "who" is not null and belongs to caller. SecurityExceptions that are 52 * thrown otherwise shouldn't leak that data either. 53 */ 54 // Password policies aren't supported on automotive 55 @RequireDoesNotHaveFeature(FEATURE_AUTOMOTIVE) 56 @RequireFeature(FEATURE_SECURE_LOCK_SCREEN) 57 @RunWith(BedsteadJUnit4.class) 58 public class NoAdminLeakingTest { 59 @ClassRule 60 @Rule 61 public static final DeviceState sDeviceState = new DeviceState(); 62 63 private static final TestApp sTestApp = sDeviceState.testApps().any(); 64 65 @Postsubmit(reason = "new test") 66 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordQuality_adminPolicyNotAvailableToNonAdmin()67 public void passwordQuality_adminPolicyNotAvailableToNonAdmin() { 68 assertOnlyAggregatePolicyAvailableToNonAdmin( 69 (dpm, who) -> dpm.getPasswordQuality(who)); 70 } 71 72 @Postsubmit(reason = "new test") 73 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumLength_adminPolicyNotAvailableToNonAdmin()74 public void passwordMinimumLength_adminPolicyNotAvailableToNonAdmin() { 75 assertOnlyAggregatePolicyAvailableToNonAdmin( 76 (dpm, who) -> dpm.getPasswordMinimumLength(who)); 77 } 78 79 @Postsubmit(reason = "new test") 80 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumLetters_adminPolicyNotAvailableToNonAdmin()81 public void passwordMinimumLetters_adminPolicyNotAvailableToNonAdmin() { 82 assertOnlyAggregatePolicyAvailableToNonAdmin( 83 (dpm, who) -> dpm.getPasswordMinimumLetters(who)); 84 } 85 86 @Postsubmit(reason = "new test") 87 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumNonLetter_adminPolicyNotAvailableToNonAdmin()88 public void passwordMinimumNonLetter_adminPolicyNotAvailableToNonAdmin() { 89 assertOnlyAggregatePolicyAvailableToNonAdmin( 90 (dpm, who) -> dpm.getPasswordMinimumNonLetter(who)); 91 } 92 93 @Postsubmit(reason = "new test") 94 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumLowerCase_adminPolicyNotAvailableToNonAdmin()95 public void passwordMinimumLowerCase_adminPolicyNotAvailableToNonAdmin() { 96 assertOnlyAggregatePolicyAvailableToNonAdmin( 97 (dpm, who) -> dpm.getPasswordMinimumLowerCase(who)); 98 } 99 100 @Postsubmit(reason = "new test") 101 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumUpperCase_adminPolicyNotAvailableToNonAdmin()102 public void passwordMinimumUpperCase_adminPolicyNotAvailableToNonAdmin() { 103 assertOnlyAggregatePolicyAvailableToNonAdmin( 104 (dpm, who) -> dpm.getPasswordMinimumUpperCase(who)); 105 } 106 107 @Postsubmit(reason = "new test") 108 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumNumeric_adminPolicyNotAvailableToNonAdmin()109 public void passwordMinimumNumeric_adminPolicyNotAvailableToNonAdmin() { 110 assertOnlyAggregatePolicyAvailableToNonAdmin( 111 (dpm, who) -> dpm.getPasswordMinimumNumeric(who)); 112 } 113 114 @Postsubmit(reason = "new test") 115 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordMinimumSymbols_adminPolicyNotAvailableToNonAdmin()116 public void passwordMinimumSymbols_adminPolicyNotAvailableToNonAdmin() { 117 assertOnlyAggregatePolicyAvailableToNonAdmin( 118 (dpm, who) -> dpm.getPasswordMinimumSymbols(who)); 119 } 120 121 @Postsubmit(reason = "new test") 122 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordHistoryLength_adminPolicyNotAvailableToNonAdmin()123 public void passwordHistoryLength_adminPolicyNotAvailableToNonAdmin() { 124 assertOnlyAggregatePolicyAvailableToNonAdmin( 125 (dpm, who) -> dpm.getPasswordHistoryLength(who)); 126 } 127 128 @Postsubmit(reason = "new test") 129 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordExpiration_adminPolicyNotAvailableToNonAdmin()130 public void passwordExpiration_adminPolicyNotAvailableToNonAdmin() { 131 assertOnlyAggregatePolicyAvailableToNonAdmin( 132 (dpm, who) -> dpm.getPasswordExpiration(who)); 133 } 134 135 @Postsubmit(reason = "new test") 136 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) passwordExpirationTimeout_adminPolicyNotAvailableToNonAdmin()137 public void passwordExpirationTimeout_adminPolicyNotAvailableToNonAdmin() { 138 assertOnlyAggregatePolicyAvailableToNonAdmin( 139 (dpm, who) -> dpm.getPasswordExpirationTimeout(who)); 140 } 141 142 @Postsubmit(reason = "new test") 143 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) maximumFailedPasswordsForWipe_adminPolicyNotAvailableToNonAdmin()144 public void maximumFailedPasswordsForWipe_adminPolicyNotAvailableToNonAdmin() { 145 assertOnlyAggregatePolicyAvailableToNonAdmin( 146 (dpm, who) -> dpm.getMaximumFailedPasswordsForWipe(who)); 147 } 148 149 @Postsubmit(reason = "new test") 150 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) maximumTimeToLock_adminPolicyNotAvailableToNonAdmin()151 public void maximumTimeToLock_adminPolicyNotAvailableToNonAdmin() { 152 assertOnlyAggregatePolicyAvailableToNonAdmin( 153 (dpm, who) -> dpm.getMaximumTimeToLock(who)); 154 } 155 156 @Postsubmit(reason = "new test") 157 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) requiredStrongAuthTimeout_adminPolicyNotAvailableToNonAdmin()158 public void requiredStrongAuthTimeout_adminPolicyNotAvailableToNonAdmin() { 159 assertOnlyAggregatePolicyAvailableToNonAdmin( 160 (dpm, who) -> dpm.getRequiredStrongAuthTimeout(who)); 161 } 162 163 @Postsubmit(reason = "new test") 164 @CanSetPolicyTest(policy = ScreenCaptureDisabled.class) screenCaptureDisabled_adminPolicyNotAvailableToNonAdmin()165 public void screenCaptureDisabled_adminPolicyNotAvailableToNonAdmin() { 166 assertOnlyAggregatePolicyAvailableToNonAdmin( 167 (dpm, who) -> dpm.getScreenCaptureDisabled(who)); 168 } 169 170 @Postsubmit(reason = "new test") 171 @CanSetPolicyTest(policy = LockscreenPolicyWithUnifiedChallenge.class) trustAgentConfiguration_adminPolicyNotAvailableToNonAdmin()172 public void trustAgentConfiguration_adminPolicyNotAvailableToNonAdmin() { 173 assertOnlyAggregatePolicyAvailableToNonAdmin( 174 (dpm, who) -> dpm.getTrustAgentConfiguration(who, 175 DPC_COMPONENT_NAME /* agent component, need to be non-null */)); 176 } 177 178 // TODO(b/210996030): replace this with test method parametrization and separate "null" case. assertOnlyAggregatePolicyAvailableToNonAdmin( BiConsumer<RemoteDevicePolicyManager, ComponentName> accessor)179 private void assertOnlyAggregatePolicyAvailableToNonAdmin( 180 BiConsumer<RemoteDevicePolicyManager, ComponentName> accessor) { 181 try (TestAppInstance testApp = sTestApp.install()) { 182 // Invoking with null admin should not throw. 183 accessor.accept(testApp.devicePolicyManager(), /* who= */ null); 184 185 SecurityException adminPackageEx = null; 186 try { 187 // Requesting policy for an admin from a different app should throw. 188 accessor.accept(testApp.devicePolicyManager(), DPC_COMPONENT_NAME); 189 fail("Checking particular admin policy shouldn't be allowed for non admin"); 190 } catch (SecurityException e) { 191 adminPackageEx = e; 192 } 193 194 ComponentName nonexistentComponent = new ComponentName("bad_pkg_123", "bad_clz_456"); 195 SecurityException nonexistentPackageEx = null; 196 try { 197 // Requesting policy for a nonexistent admin should throw. 198 accessor.accept(testApp.devicePolicyManager(), nonexistentComponent); 199 fail("Querying policy for non-existent admin should have thrown an exception"); 200 } catch (SecurityException e) { 201 nonexistentPackageEx = e; 202 } 203 204 // Both exceptions should have the same message (except package name) to avoid revealing 205 // admin existence. 206 String adminMessage = adminPackageEx.getMessage() 207 .replace(DPC_COMPONENT_NAME.toString(), ""); 208 String nonexistentMessage = nonexistentPackageEx.getMessage() 209 .replace(nonexistentComponent.toString(), ""); 210 assertThat(adminMessage).isEqualTo(nonexistentMessage); 211 } 212 } 213 } 214