Merge "Add and implement API for VpnManagers to request validation"
This commit is contained in:
@@ -124,6 +124,7 @@ package android.net {
|
||||
|
||||
public final class NetworkAgentConfig implements android.os.Parcelable {
|
||||
method @Nullable public String getSubscriberId();
|
||||
method public boolean getVpnRequiresValidation();
|
||||
method public boolean isBypassableVpn();
|
||||
}
|
||||
|
||||
@@ -131,6 +132,7 @@ package android.net {
|
||||
method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean);
|
||||
method @NonNull public android.net.NetworkAgentConfig.Builder setExcludeLocalRoutesVpn(boolean);
|
||||
method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
|
||||
method @NonNull public android.net.NetworkAgentConfig.Builder setVpnRequiresValidation(boolean);
|
||||
}
|
||||
|
||||
public final class NetworkCapabilities implements android.os.Parcelable {
|
||||
|
||||
@@ -34,6 +34,8 @@ import java.util.Objects;
|
||||
*/
|
||||
@SystemApi
|
||||
public final class NetworkAgentConfig implements Parcelable {
|
||||
// TODO : make this object immutable. The fields that should stay mutable should likely
|
||||
// migrate to NetworkAgentInfo.
|
||||
|
||||
/**
|
||||
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
|
||||
@@ -246,6 +248,27 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
return excludeLocalRouteVpn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether network validation should be performed for this VPN network.
|
||||
* {@see #getVpnRequiresValidation}
|
||||
* @hide
|
||||
*/
|
||||
private boolean mVpnRequiresValidation = false;
|
||||
|
||||
/**
|
||||
* Whether network validation should be performed for this VPN network.
|
||||
*
|
||||
* If this network isn't a VPN this should always be {@code false}, and will be ignored
|
||||
* if set.
|
||||
* If this network is a VPN, false means this network should always be considered validated;
|
||||
* true means it follows the same validation semantics as general internet networks.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public boolean getVpnRequiresValidation() {
|
||||
return mVpnRequiresValidation;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public NetworkAgentConfig() {
|
||||
}
|
||||
@@ -266,6 +289,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
legacySubTypeName = nac.legacySubTypeName;
|
||||
mLegacyExtraInfo = nac.mLegacyExtraInfo;
|
||||
excludeLocalRouteVpn = nac.excludeLocalRouteVpn;
|
||||
mVpnRequiresValidation = nac.mVpnRequiresValidation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +432,25 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether network validation should be performed for this VPN network.
|
||||
*
|
||||
* Only agents registering a VPN network should use this setter. On other network
|
||||
* types it will be ignored.
|
||||
* False means this network should always be considered validated;
|
||||
* true means it follows the same validation semantics as general internet.
|
||||
*
|
||||
* @param vpnRequiresValidation whether this VPN requires validation.
|
||||
* Default is {@code false}.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@SystemApi(client = MODULE_LIBRARIES)
|
||||
public Builder setVpnRequiresValidation(boolean vpnRequiresValidation) {
|
||||
mConfig.mVpnRequiresValidation = vpnRequiresValidation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the apps can bypass the VPN connection.
|
||||
*
|
||||
@@ -458,14 +501,16 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
&& Objects.equals(subscriberId, that.subscriberId)
|
||||
&& Objects.equals(legacyTypeName, that.legacyTypeName)
|
||||
&& Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo)
|
||||
&& excludeLocalRouteVpn == that.excludeLocalRouteVpn;
|
||||
&& excludeLocalRouteVpn == that.excludeLocalRouteVpn
|
||||
&& mVpnRequiresValidation == that.mVpnRequiresValidation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
|
||||
acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
|
||||
skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn);
|
||||
skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn,
|
||||
mVpnRequiresValidation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -483,6 +528,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
+ ", legacyTypeName = '" + legacyTypeName + '\''
|
||||
+ ", legacyExtraInfo = '" + mLegacyExtraInfo + '\''
|
||||
+ ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\''
|
||||
+ ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\''
|
||||
+ "}";
|
||||
}
|
||||
|
||||
@@ -506,6 +552,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
out.writeString(legacySubTypeName);
|
||||
out.writeString(mLegacyExtraInfo);
|
||||
out.writeInt(excludeLocalRouteVpn ? 1 : 0);
|
||||
out.writeInt(mVpnRequiresValidation ? 1 : 0);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
|
||||
@@ -526,6 +573,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
||||
networkAgentConfig.legacySubTypeName = in.readString();
|
||||
networkAgentConfig.mLegacyExtraInfo = in.readString();
|
||||
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
|
||||
networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0;
|
||||
return networkAgentConfig;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.os.Build
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.modules.utils.build.SdkLevel.isAtLeastS
|
||||
import com.android.modules.utils.build.SdkLevel.isAtLeastT
|
||||
import com.android.testutils.ConnectivityModuleTest
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
@@ -49,6 +50,10 @@ class NetworkAgentConfigTest {
|
||||
if (isAtLeastS()) {
|
||||
setBypassableVpn(true)
|
||||
}
|
||||
if (isAtLeastT()) {
|
||||
setExcludeLocalRoutesVpn(true)
|
||||
setVpnRequiresValidation(true)
|
||||
}
|
||||
}.build()
|
||||
assertParcelingIsLossless(config)
|
||||
}
|
||||
@@ -69,6 +74,10 @@ class NetworkAgentConfigTest {
|
||||
setProvisioningNotificationEnabled(false)
|
||||
setBypassableVpn(true)
|
||||
}
|
||||
if (isAtLeastT()) {
|
||||
setExcludeLocalRoutesVpn(true)
|
||||
setVpnRequiresValidation(true)
|
||||
}
|
||||
}.build()
|
||||
|
||||
assertTrue(config.isExplicitlySelected())
|
||||
@@ -77,6 +86,10 @@ class NetworkAgentConfigTest {
|
||||
assertFalse(config.isPartialConnectivityAcceptable())
|
||||
assertTrue(config.isUnvalidatedConnectivityAcceptable())
|
||||
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
|
||||
if (isAtLeastT()) {
|
||||
assertTrue(config.getExcludeLocalRouteVpn())
|
||||
assertTrue(config.getVpnRequiresValidation())
|
||||
}
|
||||
if (isAtLeastS()) {
|
||||
assertEquals(testExtraInfo, config.getLegacyExtraInfo())
|
||||
assertFalse(config.isNat64DetectionEnabled())
|
||||
|
||||
@@ -50,6 +50,7 @@ public class VpnProfileTest {
|
||||
private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
|
||||
private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
|
||||
private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
|
||||
private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
|
||||
|
||||
@Test
|
||||
public void testDefaults() throws Exception {
|
||||
@@ -78,10 +79,13 @@ public class VpnProfileTest {
|
||||
assertEquals(1360, p.maxMtu);
|
||||
assertFalse(p.areAuthParamsInline);
|
||||
assertFalse(p.isRestrictedToTestNetworks);
|
||||
assertFalse(p.excludeLocalRoutes);
|
||||
assertFalse(p.requiresInternetValidation);
|
||||
}
|
||||
|
||||
private VpnProfile getSampleIkev2Profile(String key) {
|
||||
final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */);
|
||||
final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
|
||||
false /* excludesLocalRoutes */, true /* requiresPlatformValidation */);
|
||||
|
||||
p.name = "foo";
|
||||
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
|
||||
@@ -129,8 +133,8 @@ public class VpnProfileTest {
|
||||
@Test
|
||||
public void testParcelUnparcel() {
|
||||
if (isAtLeastT()) {
|
||||
// excludeLocalRoutes is added in T.
|
||||
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 24);
|
||||
// excludeLocalRoutes, requiresPlatformValidation were added in T.
|
||||
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 25);
|
||||
} else {
|
||||
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
|
||||
}
|
||||
@@ -174,7 +178,8 @@ public class VpnProfileTest {
|
||||
getEncodedDecodedIkev2ProfileMissingValues(
|
||||
ENCODED_INDEX_AUTH_PARAMS_INLINE,
|
||||
ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
|
||||
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
|
||||
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
|
||||
ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
|
||||
|
||||
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
|
||||
}
|
||||
@@ -194,13 +199,25 @@ public class VpnProfileTest {
|
||||
public void testEncodeDecodeMissingExcludeLocalRoutes() {
|
||||
final String tooFewValues =
|
||||
getEncodedDecodedIkev2ProfileMissingValues(
|
||||
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
|
||||
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
|
||||
ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
|
||||
|
||||
// Verify decoding without isRestrictedToTestNetworks defaults to false
|
||||
// Verify decoding without excludeLocalRoutes defaults to false
|
||||
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
|
||||
assertFalse(decoded.excludeLocalRoutes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecodeMissingRequiresValidation() {
|
||||
final String tooFewValues =
|
||||
getEncodedDecodedIkev2ProfileMissingValues(
|
||||
ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
|
||||
|
||||
// Verify decoding without requiresValidation defaults to false
|
||||
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
|
||||
assertFalse(decoded.requiresInternetValidation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeDecodeLoginsNotSaved() {
|
||||
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
|
||||
|
||||
Reference in New Issue
Block a user