Loading core/java/android/net/Ikev2VpnProfile.java +40 −5 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private final boolean mIsBypassable; // Defaults in builder private final boolean mIsMetered; // Defaults in builder private final int mMaxMtu; // Defaults in builder private final boolean mIsRestrictedToTestNetworks; private Ikev2VpnProfile( int type, Loading @@ -116,7 +117,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @NonNull List<String> allowedAlgorithms, boolean isBypassable, boolean isMetered, int maxMtu) { int maxMtu, boolean restrictToTestNetworks) { super(type); checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address"); Loading @@ -140,6 +142,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mIsBypassable = isBypassable; mIsMetered = isMetered; mMaxMtu = maxMtu; mIsRestrictedToTestNetworks = restrictToTestNetworks; validate(); } Loading Loading @@ -329,6 +332,15 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return mMaxMtu; } /** * Returns whether or not this VPN profile is restricted to test networks. * * @hide */ public boolean isRestrictedToTestNetworks() { return mIsRestrictedToTestNetworks; } @Override public int hashCode() { return Objects.hash( Loading @@ -345,7 +357,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, mMaxMtu); mMaxMtu, mIsRestrictedToTestNetworks); } @Override Loading @@ -368,7 +381,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms) && mIsBypassable == other.mIsBypassable && mIsMetered == other.mIsMetered && mMaxMtu == other.mMaxMtu; && mMaxMtu == other.mMaxMtu && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks; } /** Loading @@ -381,7 +395,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { */ @NonNull public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException { final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */); final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */, mIsRestrictedToTestNetworks); profile.type = mType; profile.server = mServerAddr; profile.ipsecIdentifier = mUserIdentity; Loading Loading @@ -449,6 +464,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { builder.setBypassable(profile.isBypassable); builder.setMetered(profile.isMetered); builder.setMaxMtu(profile.maxMtu); if (profile.isRestrictedToTestNetworks) { builder.restrictToTestNetworks(); } switch (profile.type) { case TYPE_IKEV2_IPSEC_USER_PASS: Loading Loading @@ -621,6 +639,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private boolean mIsBypassable = false; private boolean mIsMetered = true; private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; private boolean mIsRestrictedToTestNetworks = false; /** * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. Loading Loading @@ -841,6 +860,21 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return this; } /** * Restricts this profile to use test networks (only). * * <p>This method is for testing only, and must not be used by apps. Calling * provisionVpnProfile() with a profile where test-network usage is enabled will require the * MANAGE_TEST_NETWORKS permission. * * @hide */ @NonNull public Builder restrictToTestNetworks() { mIsRestrictedToTestNetworks = true; return this; } /** * Validates, builds and provisions the VpnProfile. * Loading @@ -862,7 +896,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, mMaxMtu); mMaxMtu, mIsRestrictedToTestNetworks); } } } core/java/com/android/internal/net/VpnProfile.java +27 −5 Original line number Diff line number Diff line Loading @@ -136,13 +136,19 @@ public final class VpnProfile implements Cloneable, Parcelable { public boolean isMetered = false; // 21 public int maxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; // 22 public boolean areAuthParamsInline = false; // 23 public final boolean isRestrictedToTestNetworks; // 24 // Helper fields. @UnsupportedAppUsage public transient boolean saveLogin = false; public VpnProfile(String key) { this(key, false); } public VpnProfile(String key, boolean isRestrictedToTestNetworks) { this.key = key; this.isRestrictedToTestNetworks = isRestrictedToTestNetworks; } @UnsupportedAppUsage Loading Loading @@ -171,6 +177,7 @@ public final class VpnProfile implements Cloneable, Parcelable { isMetered = in.readBoolean(); maxMtu = in.readInt(); areAuthParamsInline = in.readBoolean(); isRestrictedToTestNetworks = in.readBoolean(); } /** Loading Loading @@ -220,6 +227,7 @@ public final class VpnProfile implements Cloneable, Parcelable { out.writeBoolean(isMetered); out.writeInt(maxMtu); out.writeBoolean(areAuthParamsInline); out.writeBoolean(isRestrictedToTestNetworks); } /** Loading @@ -237,12 +245,21 @@ public final class VpnProfile implements Cloneable, Parcelable { String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1); // Acceptable numbers of values are: // 14-19: Standard profile, with option for serverCert, proxy // 24: Standard profile with serverCert, proxy and platform-VPN parameters. if ((values.length < 14 || values.length > 19) && values.length != 24) { // 24: Standard profile with serverCert, proxy and platform-VPN parameters // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks if ((values.length < 14 || values.length > 19) && values.length != 24 && values.length != 25) { return null; } VpnProfile profile = new VpnProfile(key); final boolean isRestrictedToTestNetworks; if (values.length >= 25) { isRestrictedToTestNetworks = Boolean.parseBoolean(values[24]); } else { isRestrictedToTestNetworks = false; } VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks); profile.name = values[0]; profile.type = Integer.parseInt(values[1]); if (profile.type < 0 || profile.type > TYPE_MAX) { Loading Loading @@ -283,6 +300,8 @@ public final class VpnProfile implements Cloneable, Parcelable { profile.areAuthParamsInline = Boolean.parseBoolean(values[23]); } // isRestrictedToTestNetworks (values[24]) assigned as part of the constructor profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty(); return profile; } catch (Exception e) { Loading Loading @@ -330,6 +349,7 @@ public final class VpnProfile implements Cloneable, Parcelable { builder.append(VALUE_DELIMITER).append(isMetered); builder.append(VALUE_DELIMITER).append(maxMtu); builder.append(VALUE_DELIMITER).append(areAuthParamsInline); builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks); return builder.toString().getBytes(StandardCharsets.UTF_8); } Loading Loading @@ -421,7 +441,8 @@ public final class VpnProfile implements Cloneable, Parcelable { return Objects.hash( key, type, server, username, password, dnsServers, searchDomains, routes, mppe, l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert, proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline); proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline, isRestrictedToTestNetworks); } /** Checks VPN profiles for interior equality. */ Loading Loading @@ -453,7 +474,8 @@ public final class VpnProfile implements Cloneable, Parcelable { && isBypassable == other.isBypassable && isMetered == other.isMetered && maxMtu == other.maxMtu && areAuthParamsInline == other.areAuthParamsInline; && areAuthParamsInline == other.areAuthParamsInline && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks; } @NonNull Loading services/core/java/com/android/server/connectivity/Vpn.java +26 −5 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.RouteInfo; import android.net.UidRange; import android.net.VpnManager; Loading Loading @@ -2225,12 +2226,27 @@ public class Vpn { @Override public void run() { // Explicitly use only the network that ConnectivityService thinks is the "best." In // other words, only ever use the currently selected default network. This does mean // that in both onLost() and onConnected(), any old sessions MUST be torn down. This // does NOT include VPNs. // Unless the profile is restricted to test networks, explicitly use only the network // that ConnectivityService thinks is the "best." In other words, only ever use the // currently selected default network. This does mean that in both onLost() and // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs. // // When restricted to test networks, select any network with TRANSPORT_TEST. Since the // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, // this is considered safe. final ConnectivityManager cm = ConnectivityManager.from(mContext); cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback); final NetworkRequest req; if (mProfile.isRestrictedToTestNetworks()) { req = new NetworkRequest.Builder() .clearCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_TEST) .build(); } else { req = cm.getDefaultRequest(); } cm.requestNetwork(req, mNetworkCallback); } private boolean isActiveNetwork(@Nullable Network network) { Loading Loading @@ -2868,6 +2884,11 @@ public class Vpn { verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); if (profile.isRestrictedToTestNetworks) { mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS, "Test-mode profiles require the MANAGE_TEST_NETWORKS permission"); } final byte[] encodedProfile = profile.encode(); if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) { throw new IllegalArgumentException("Profile too big"); Loading tests/net/java/com/android/internal/net/VpnProfileTest.java +40 −7 Original line number Diff line number Diff line Loading @@ -33,7 +33,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** Unit tests for {@link VpnProfile}. */ @SmallTest Loading @@ -41,6 +43,9 @@ import java.util.Arrays; public class VpnProfileTest { private static final String DUMMY_PROFILE_KEY = "Test"; private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; @Test public void testDefaults() throws Exception { final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); Loading @@ -67,10 +72,11 @@ public class VpnProfileTest { assertFalse(p.isMetered); assertEquals(1360, p.maxMtu); assertFalse(p.areAuthParamsInline); assertFalse(p.isRestrictedToTestNetworks); } private VpnProfile getSampleIkev2Profile(String key) { final VpnProfile p = new VpnProfile(key); final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */); p.name = "foo"; p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; Loading Loading @@ -116,7 +122,7 @@ public class VpnProfileTest { @Test public void testParcelUnparcel() { assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22); assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); } @Test Loading Loading @@ -159,14 +165,41 @@ public class VpnProfileTest { assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); } private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { // Sort to ensure when we remove, we can do it from greatest first. Arrays.sort(missingIndices); final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); final List<String> parts = new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); // Remove from back first to ensure indexing is consistent. for (int i = missingIndices.length - 1; i >= 0; i--) { parts.remove(missingIndices[i]); } return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); } @Test public void testEncodeDecodeInvalidNumberOfValues() { final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); final String encoded = new String(profile.encode()); final byte[] tooFewValues = encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes(); final String tooFewValues = getEncodedDecodedIkev2ProfileMissingValues( ENCODED_INDEX_AUTH_PARAMS_INLINE, ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues)); assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); } @Test public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { final String tooFewValues = getEncodedDecodedIkev2ProfileMissingValues( ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); // Verify decoding without isRestrictedToTestNetworks defaults to false final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); assertFalse(decoded.isRestrictedToTestNetworks); } @Test Loading Loading
core/java/android/net/Ikev2VpnProfile.java +40 −5 Original line number Diff line number Diff line Loading @@ -101,6 +101,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private final boolean mIsBypassable; // Defaults in builder private final boolean mIsMetered; // Defaults in builder private final int mMaxMtu; // Defaults in builder private final boolean mIsRestrictedToTestNetworks; private Ikev2VpnProfile( int type, Loading @@ -116,7 +117,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { @NonNull List<String> allowedAlgorithms, boolean isBypassable, boolean isMetered, int maxMtu) { int maxMtu, boolean restrictToTestNetworks) { super(type); checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address"); Loading @@ -140,6 +142,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mIsBypassable = isBypassable; mIsMetered = isMetered; mMaxMtu = maxMtu; mIsRestrictedToTestNetworks = restrictToTestNetworks; validate(); } Loading Loading @@ -329,6 +332,15 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return mMaxMtu; } /** * Returns whether or not this VPN profile is restricted to test networks. * * @hide */ public boolean isRestrictedToTestNetworks() { return mIsRestrictedToTestNetworks; } @Override public int hashCode() { return Objects.hash( Loading @@ -345,7 +357,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, mMaxMtu); mMaxMtu, mIsRestrictedToTestNetworks); } @Override Loading @@ -368,7 +381,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms) && mIsBypassable == other.mIsBypassable && mIsMetered == other.mIsMetered && mMaxMtu == other.mMaxMtu; && mMaxMtu == other.mMaxMtu && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks; } /** Loading @@ -381,7 +395,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { */ @NonNull public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException { final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */); final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */, mIsRestrictedToTestNetworks); profile.type = mType; profile.server = mServerAddr; profile.ipsecIdentifier = mUserIdentity; Loading Loading @@ -449,6 +464,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { builder.setBypassable(profile.isBypassable); builder.setMetered(profile.isMetered); builder.setMaxMtu(profile.maxMtu); if (profile.isRestrictedToTestNetworks) { builder.restrictToTestNetworks(); } switch (profile.type) { case TYPE_IKEV2_IPSEC_USER_PASS: Loading Loading @@ -621,6 +639,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { private boolean mIsBypassable = false; private boolean mIsMetered = true; private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; private boolean mIsRestrictedToTestNetworks = false; /** * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN. Loading Loading @@ -841,6 +860,21 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { return this; } /** * Restricts this profile to use test networks (only). * * <p>This method is for testing only, and must not be used by apps. Calling * provisionVpnProfile() with a profile where test-network usage is enabled will require the * MANAGE_TEST_NETWORKS permission. * * @hide */ @NonNull public Builder restrictToTestNetworks() { mIsRestrictedToTestNetworks = true; return this; } /** * Validates, builds and provisions the VpnProfile. * Loading @@ -862,7 +896,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile { mAllowedAlgorithms, mIsBypassable, mIsMetered, mMaxMtu); mMaxMtu, mIsRestrictedToTestNetworks); } } }
core/java/com/android/internal/net/VpnProfile.java +27 −5 Original line number Diff line number Diff line Loading @@ -136,13 +136,19 @@ public final class VpnProfile implements Cloneable, Parcelable { public boolean isMetered = false; // 21 public int maxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; // 22 public boolean areAuthParamsInline = false; // 23 public final boolean isRestrictedToTestNetworks; // 24 // Helper fields. @UnsupportedAppUsage public transient boolean saveLogin = false; public VpnProfile(String key) { this(key, false); } public VpnProfile(String key, boolean isRestrictedToTestNetworks) { this.key = key; this.isRestrictedToTestNetworks = isRestrictedToTestNetworks; } @UnsupportedAppUsage Loading Loading @@ -171,6 +177,7 @@ public final class VpnProfile implements Cloneable, Parcelable { isMetered = in.readBoolean(); maxMtu = in.readInt(); areAuthParamsInline = in.readBoolean(); isRestrictedToTestNetworks = in.readBoolean(); } /** Loading Loading @@ -220,6 +227,7 @@ public final class VpnProfile implements Cloneable, Parcelable { out.writeBoolean(isMetered); out.writeInt(maxMtu); out.writeBoolean(areAuthParamsInline); out.writeBoolean(isRestrictedToTestNetworks); } /** Loading @@ -237,12 +245,21 @@ public final class VpnProfile implements Cloneable, Parcelable { String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1); // Acceptable numbers of values are: // 14-19: Standard profile, with option for serverCert, proxy // 24: Standard profile with serverCert, proxy and platform-VPN parameters. if ((values.length < 14 || values.length > 19) && values.length != 24) { // 24: Standard profile with serverCert, proxy and platform-VPN parameters // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks if ((values.length < 14 || values.length > 19) && values.length != 24 && values.length != 25) { return null; } VpnProfile profile = new VpnProfile(key); final boolean isRestrictedToTestNetworks; if (values.length >= 25) { isRestrictedToTestNetworks = Boolean.parseBoolean(values[24]); } else { isRestrictedToTestNetworks = false; } VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks); profile.name = values[0]; profile.type = Integer.parseInt(values[1]); if (profile.type < 0 || profile.type > TYPE_MAX) { Loading Loading @@ -283,6 +300,8 @@ public final class VpnProfile implements Cloneable, Parcelable { profile.areAuthParamsInline = Boolean.parseBoolean(values[23]); } // isRestrictedToTestNetworks (values[24]) assigned as part of the constructor profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty(); return profile; } catch (Exception e) { Loading Loading @@ -330,6 +349,7 @@ public final class VpnProfile implements Cloneable, Parcelable { builder.append(VALUE_DELIMITER).append(isMetered); builder.append(VALUE_DELIMITER).append(maxMtu); builder.append(VALUE_DELIMITER).append(areAuthParamsInline); builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks); return builder.toString().getBytes(StandardCharsets.UTF_8); } Loading Loading @@ -421,7 +441,8 @@ public final class VpnProfile implements Cloneable, Parcelable { return Objects.hash( key, type, server, username, password, dnsServers, searchDomains, routes, mppe, l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert, proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline); proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline, isRestrictedToTestNetworks); } /** Checks VPN profiles for interior equality. */ Loading Loading @@ -453,7 +474,8 @@ public final class VpnProfile implements Cloneable, Parcelable { && isBypassable == other.isBypassable && isMetered == other.isMetered && maxMtu == other.maxMtu && areAuthParamsInline == other.areAuthParamsInline; && areAuthParamsInline == other.areAuthParamsInline && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks; } @NonNull Loading
services/core/java/com/android/server/connectivity/Vpn.java +26 −5 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.RouteInfo; import android.net.UidRange; import android.net.VpnManager; Loading Loading @@ -2225,12 +2226,27 @@ public class Vpn { @Override public void run() { // Explicitly use only the network that ConnectivityService thinks is the "best." In // other words, only ever use the currently selected default network. This does mean // that in both onLost() and onConnected(), any old sessions MUST be torn down. This // does NOT include VPNs. // Unless the profile is restricted to test networks, explicitly use only the network // that ConnectivityService thinks is the "best." In other words, only ever use the // currently selected default network. This does mean that in both onLost() and // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs. // // When restricted to test networks, select any network with TRANSPORT_TEST. Since the // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, // this is considered safe. final ConnectivityManager cm = ConnectivityManager.from(mContext); cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback); final NetworkRequest req; if (mProfile.isRestrictedToTestNetworks()) { req = new NetworkRequest.Builder() .clearCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_TEST) .build(); } else { req = cm.getDefaultRequest(); } cm.requestNetwork(req, mNetworkCallback); } private boolean isActiveNetwork(@Nullable Network network) { Loading Loading @@ -2868,6 +2884,11 @@ public class Vpn { verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); if (profile.isRestrictedToTestNetworks) { mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS, "Test-mode profiles require the MANAGE_TEST_NETWORKS permission"); } final byte[] encodedProfile = profile.encode(); if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) { throw new IllegalArgumentException("Profile too big"); Loading
tests/net/java/com/android/internal/net/VpnProfileTest.java +40 −7 Original line number Diff line number Diff line Loading @@ -33,7 +33,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** Unit tests for {@link VpnProfile}. */ @SmallTest Loading @@ -41,6 +43,9 @@ import java.util.Arrays; public class VpnProfileTest { private static final String DUMMY_PROFILE_KEY = "Test"; private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; @Test public void testDefaults() throws Exception { final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); Loading @@ -67,10 +72,11 @@ public class VpnProfileTest { assertFalse(p.isMetered); assertEquals(1360, p.maxMtu); assertFalse(p.areAuthParamsInline); assertFalse(p.isRestrictedToTestNetworks); } private VpnProfile getSampleIkev2Profile(String key) { final VpnProfile p = new VpnProfile(key); final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */); p.name = "foo"; p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; Loading Loading @@ -116,7 +122,7 @@ public class VpnProfileTest { @Test public void testParcelUnparcel() { assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22); assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); } @Test Loading Loading @@ -159,14 +165,41 @@ public class VpnProfileTest { assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); } private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { // Sort to ensure when we remove, we can do it from greatest first. Arrays.sort(missingIndices); final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); final List<String> parts = new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); // Remove from back first to ensure indexing is consistent. for (int i = missingIndices.length - 1; i >= 0; i--) { parts.remove(missingIndices[i]); } return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); } @Test public void testEncodeDecodeInvalidNumberOfValues() { final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); final String encoded = new String(profile.encode()); final byte[] tooFewValues = encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes(); final String tooFewValues = getEncodedDecodedIkev2ProfileMissingValues( ENCODED_INDEX_AUTH_PARAMS_INLINE, ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues)); assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); } @Test public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { final String tooFewValues = getEncodedDecodedIkev2ProfileMissingValues( ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); // Verify decoding without isRestrictedToTestNetworks defaults to false final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); assertFalse(decoded.isRestrictedToTestNetworks); } @Test Loading