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

Commit 29d64121 authored by Benedict Wong's avatar Benedict Wong
Browse files

Add RequiresFeature annotations for IKEv2 VPN profiles

This change adds the @RequiresFeature annotation to Ikev2VpnProfile
Builder methods, and checks before provisioning VPN profiles.

Bug: 156681625
Test: New tests added, passing.
Change-Id: I125d8fbe5d67fb877ad7d0636c007cb3e1a9f59b
Merged-In: I125d8fbe5d67fb877ad7d0636c007cb3e1a9f59b
(cherry picked from commit e84a17dd)
parent cc56e255
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import static com.android.internal.util.Preconditions.checkStringNotEmpty;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.content.pm.PackageManager;
import android.os.Process;
import android.security.Credentials;
import android.security.KeyStore;
@@ -647,6 +649,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @param serverAddr the server that the VPN should connect to
         * @param identity the identity string to be used for IKEv2 authentication
         */
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder(@NonNull String serverAddr, @NonNull String identity) {
            checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "serverAddr");
            checkNotNull(identity, MISSING_PARAM_MSG_TMPL, "identity");
@@ -680,6 +683,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         *     unrecognized format
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setAuthUsernamePassword(
                @NonNull String user,
                @NonNull String pass,
@@ -715,6 +719,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         *     unrecognized format
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setAuthDigitalSignature(
                @NonNull X509Certificate userCert,
                @NonNull PrivateKey key,
@@ -745,6 +750,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @return this {@link Builder} object to facilitate chaining of method calls
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setAuthPsk(@NonNull byte[] psk) {
            checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk");

@@ -768,6 +774,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @return this {@link Builder} object to facilitate chaining of method calls
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setBypassable(boolean isBypassable) {
            mIsBypassable = isBypassable;
            return this;
@@ -782,6 +789,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @return this {@link Builder} object to facilitate chaining of method calls
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setProxy(@Nullable ProxyInfo proxy) {
            mProxyInfo = proxy;
            return this;
@@ -798,6 +806,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @throws IllegalArgumentException if the value is not at least the minimum IPv6 MTU (1280)
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setMaxMtu(int mtu) {
            // IPv6 MTU is greater; since profiles may be started by the system on IPv4 and IPv6
            // networks, the VPN must provide a link fulfilling the stricter of the two conditions
@@ -825,6 +834,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setMetered(boolean isMetered) {
            mIsMetered = isMetered;
            return this;
@@ -852,6 +862,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @see IpSecAlgorithm
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) {
            checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames");
            validateAllowedAlgorithms(algorithmNames);
@@ -870,6 +881,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @hide
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Builder restrictToTestNetworks() {
            mIsRestrictedToTestNetworks = true;
            return this;
@@ -881,6 +893,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
         * @throws IllegalArgumentException if any of the required keys or values were invalid
         */
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        public Ikev2VpnProfile build() {
            return new Ikev2VpnProfile(
                    mType,
+18 −0
Original line number Diff line number Diff line
@@ -2867,6 +2867,23 @@ public class Vpn {
        return Credentials.PLATFORM_VPN + mUserHandle + "_" + packageName;
    }

    @VisibleForTesting
    void validateRequiredFeatures(VpnProfile profile) {
        switch (profile.type) {
            case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
            case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
            case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
                if (!mContext.getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_IPSEC_TUNNELS)) {
                    throw new UnsupportedOperationException(
                            "Ikev2VpnProfile(s) requires PackageManager.FEATURE_IPSEC_TUNNELS");
                }
                break;
            default:
                return;
        }
    }

    /**
     * Stores an app-provisioned VPN profile and returns whether the app is already prepared.
     *
@@ -2883,6 +2900,7 @@ public class Vpn {

        verifyCallingUidAndPackage(packageName);
        enforceNotRestrictedUser();
        validateRequiredFeatures(profile);

        if (profile.isRestrictedToTestNetworks) {
            mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS,
+16 −0
Original line number Diff line number Diff line
@@ -199,6 +199,8 @@ public class VpnTest {
        when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
                .thenReturn(Resources.getSystem().getString(
                        R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
                .thenReturn(true);
        when(mSystemServices.isCallerSystem()).thenReturn(true);

        // Used by {@link Notification.Builder}
@@ -730,6 +732,20 @@ public class VpnTest {
        }
    }

    @Test
    public void testProvisionVpnProfileNoIpsecTunnels() throws Exception {
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
                .thenReturn(false);
        final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);

        try {
            checkProvisionVpnProfile(
                    vpn, true /* expectedResult */, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);
            fail("Expected exception due to missing feature");
        } catch (UnsupportedOperationException expected) {
        }
    }

    @Test
    public void testProvisionVpnProfilePreconsented() throws Exception {
        final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);