Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bedbd28 authored by Alex Johnston's avatar Alex Johnston
Browse files

DPM Check for unaffiliated secondary users

* Add authorization check in DPMS for API
  methods to set the private DNS mode and
  the recommended global proxy.
* When there is a unaffiliated user, it is
  assumed that it is managed separately.
* These are device-wide policies that affect
  all users, so should only be set when it is
  the same managing entity and all users on
  the device are affiliated.

Bug: 177926343
Test: atest com.android.server.devicepolicy.DevicePolicyManagerTest
      atest com.android.cts.devicepolicy.DeviceOwnerTest#testProxyPacProxyTest
      atest com.android.cts.devicepolicy.DeviceOwnerTest#testProxyStaticProxyTest
Change-Id: I119a84988ad3cda42b709dbc6d63acf76b0031d6
parent eb54ad9b
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -5504,6 +5504,10 @@ public class DevicePolicyManager {
     * This method requires the caller to be the device owner.
     * <p>
     * This proxy is only a recommendation and it is possible that some apps will ignore it.
     * <p>
     * Note: The device owner won't be able to set a global HTTP proxy if there are unaffiliated
     * secondary users or profiles on the device. It's recommended that affiliation ids are set for
     * new users as soon as possible after provisioning via {@link #setAffiliationIds}.
     *
     * @see ProxyInfo
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -12770,6 +12774,11 @@ public class DevicePolicyManager {
     * <p>In this mode, the DNS subsystem will attempt a TLS handshake to the network-supplied
     * resolver prior to attempting name resolution in cleartext.
     *
     * <p>Note: The device owner won't be able to set the global private DNS mode if there are
     * unaffiliated secondary users or profiles on the device. It's recommended that affiliation
     * ids are set for new users as soon as possible after provisioning via
     * {@link #setAffiliationIds}.
     *
     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
     *
     * @return {@code PRIVATE_DNS_SET_NO_ERROR} if the mode was set successfully, or
@@ -12805,6 +12814,11 @@ public class DevicePolicyManager {
     * the ability to resolve hostnames as system traffic to the resolver may not go through the
     * VPN.
     *
     * <p>Note: The device owner won't be able to set the global private DNS mode if there are
     * unaffiliated secondary users or profiles on the device. It's recommended that affiliation
     * ids are set for new users as soon as possible after provisioning via
     * {@link #setAffiliationIds}.
     *
     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
     * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858).
     *
+2 −0
Original line number Diff line number Diff line
@@ -7232,6 +7232,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        Preconditions.checkCallAuthorization(isDeviceOwner(caller));
        checkAllUsersAreAffiliatedWithDevice();
        mInjector.binderWithCleanCallingIdentity(
                () -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo));
    }
@@ -15709,6 +15710,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        Preconditions.checkCallAuthorization(isDeviceOwner(caller));
        checkAllUsersAreAffiliatedWithDevice();
        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_GLOBAL_PRIVATE_DNS);
        switch (mode) {
+43 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.PasswordMetrics.computeForPasswordOrPin;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
@@ -7333,6 +7334,48 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assertThat(dpm.getPolicyExemptApps()).containsExactly("4", "8", "15", "16", "23", "42");
    }

    @Test
    public void testSetGlobalPrivateDnsModeOpportunistic_asDeviceOwner() throws Exception {
        setDeviceOwner();
        // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the
        // feature is disabled because there are non-affiliated secondary users.
        getServices().removeUser(CALLER_USER_HANDLE);
        clearInvocations(getServices().settings);

        int result = dpm.setGlobalPrivateDnsModeOpportunistic(admin1);

        assertThat(result).isEqualTo(PRIVATE_DNS_SET_NO_ERROR);
    }

    @Test
    public void testSetGlobalPrivateDnsModeOpportunistic_hasUnaffiliatedUsers() throws Exception {
        setDeviceOwner();
        setAsProfileOwner(admin2);

        assertThrows(SecurityException.class,
                () -> dpm.setGlobalPrivateDnsModeOpportunistic(admin1));
    }

    @Test
    public void testSetRecommendedGlobalProxy_asDeviceOwner() throws Exception {
        setDeviceOwner();
        // setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the
        // feature is disabled because there are non-affiliated secondary users.
        getServices().removeUser(CALLER_USER_HANDLE);

        dpm.setRecommendedGlobalProxy(admin1, null);

        verify(getServices().connectivityManager).setGlobalProxy(null);
    }

    @Test
    public void testSetRecommendedGlobalProxy_hasUnaffiliatedUsers() throws Exception {
        setDeviceOwner();
        setAsProfileOwner(admin2);

        assertThrows(SecurityException.class, () -> dpm.setRecommendedGlobalProxy(admin1, null));
    }

    private void setUserUnlocked(int userHandle, boolean unlocked) {
        when(getServices().userManager.isUserUnlocked(eq(userHandle))).thenReturn(unlocked);
    }