summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChiachang Wang <chiachangwang@google.com>2022-01-27 17:03:14 +0800
committerChalard Jean <jchalard@google.com>2022-02-09 02:19:15 +0900
commit3fc98d5ebdeb0fbe34d071dbf0930fef3d7a3eb7 (patch)
tree1d1931ace5f2484dddefda1d8f014743751eb974
parent1962b10531814b4079e2c2af55cd43ad58a89000 (diff)
downloadbase-3fc98d5ebdeb0fbe34d071dbf0930fef3d7a3eb7.tar.gz
Allow VPN apps to ask for running the validation checks
Expose an API to allow VPNs app to ask for running the validation check on the VPN network built from Ikev2VpnProfile. Bug: 184750836 Test: New test in Ikev2VpnTest Also FrameworksNetTests Change-Id: I385bb887b6c697d8f5d87af750dbd2aab44afca6 CTS-Coverage-Bug: 184750836 (but CTS is in the same topic, just not detected by the tool)
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java47
-rw-r--r--core/java/android/net/PlatformVpnProfile.java30
-rw-r--r--core/java/com/android/internal/net/VpnConfig.java6
-rw-r--r--core/java/com/android/internal/net/VpnProfile.java36
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
6 files changed, 98 insertions, 25 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 6a72017c9610..c61dd379de64 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25227,6 +25227,7 @@ package android.net {
method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int);
method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean);
method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
+ method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean);
}
public final class IpSecAlgorithm implements android.os.Parcelable {
@@ -25370,6 +25371,7 @@ package android.net {
public abstract class PlatformVpnProfile {
method public final boolean getExcludeLocalRoutes();
+ method public final boolean getRequiresInternetValidation();
method public final int getType();
method @NonNull public final String getTypeString();
field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 036607be2b5d..ec752fdbf45f 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -159,8 +159,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
boolean isMetered,
int maxMtu,
boolean restrictToTestNetworks,
- boolean excludeLocalRoutes) {
- super(type, excludeLocalRoutes);
+ boolean excludeLocalRoutes,
+ boolean requiresInternetValidation) {
+ super(type, excludeLocalRoutes, requiresInternetValidation);
checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
@@ -181,7 +182,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
if (excludeLocalRoutes && !isBypassable) {
throw new IllegalArgumentException(
- "Vpn should be byassable if excludeLocalRoutes is set");
+ "Vpn must be bypassable if excludeLocalRoutes is set");
}
mIsBypassable = isBypassable;
@@ -238,7 +239,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
* that provides Authentication, and one that provides Encryption. Authenticated Encryption with
* Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption.
*
- * @param allowedAlgorithms The list to be validated
+ * @param algorithmNames The list to be validated
*/
private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
// First, make sure no insecure algorithms were proposed.
@@ -400,7 +401,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mIsBypassable,
mIsMetered,
mMaxMtu,
- mIsRestrictedToTestNetworks);
+ mIsRestrictedToTestNetworks,
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
@Override
@@ -425,7 +428,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
&& mIsMetered == other.mIsMetered
&& mMaxMtu == other.mMaxMtu
&& mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
- && mExcludeLocalRoutes == other.mExcludeLocalRoutes;
+ && mExcludeLocalRoutes == other.mExcludeLocalRoutes
+ && mRequiresInternetValidation == other.mRequiresInternetValidation;
}
/**
@@ -439,7 +443,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
@NonNull
public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
- mIsRestrictedToTestNetworks, mExcludeLocalRoutes);
+ mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
profile.type = mType;
profile.server = mServerAddr;
profile.ipsecIdentifier = mUserIdentity;
@@ -544,6 +548,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
}
builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
+ builder.setRequiresInternetValidation(profile.requiresInternetValidation);
return builder.build();
}
@@ -776,6 +781,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
@Nullable private ProxyInfo mProxyInfo;
@NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS;
+ private boolean mRequiresInternetValidation = false;
private boolean mIsBypassable = false;
private boolean mIsMetered = true;
private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
@@ -988,6 +994,30 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
}
/**
+ * Request that this VPN undergoes Internet validation.
+ *
+ * If this is true, the platform will perform basic validation checks for Internet
+ * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+ * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+ * capability.
+ *
+ * If this is false, the platform assumes the VPN either is always capable of reaching the
+ * Internet or intends not to. In this case, the VPN network capabilities will
+ * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+ * immediately after it connects, whether it can reach public Internet destinations or not.
+ *
+ * @param requiresInternetValidation {@code true} if the framework should attempt to
+ * validate this VPN for Internet connectivity. Defaults
+ * to {@code false}.
+ */
+ @NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+ public Builder setRequiresInternetValidation(boolean requiresInternetValidation) {
+ mRequiresInternetValidation = requiresInternetValidation;
+ return this;
+ }
+
+ /**
* Marks the VPN network as metered.
*
* <p>A VPN network is classified as metered when the user is sensitive to heavy data usage
@@ -1103,7 +1133,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mIsMetered,
mMaxMtu,
mIsRestrictedToTestNetworks,
- mExcludeLocalRoutes);
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
}
}
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
index 3c45799e10f2..8bd1c8d07017 100644
--- a/core/java/android/net/PlatformVpnProfile.java
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -16,10 +16,6 @@
package android.net;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -67,11 +63,15 @@ public abstract class PlatformVpnProfile {
/** @hide */
protected final boolean mExcludeLocalRoutes;
+ /** @hide */
+ protected final boolean mRequiresInternetValidation;
/** @hide */
- PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes) {
+ PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes,
+ boolean requiresValidation) {
mType = type;
mExcludeLocalRoutes = excludeLocalRoutes;
+ mRequiresInternetValidation = requiresValidation;
}
/** Returns the profile integer type. */
@@ -80,14 +80,30 @@ public abstract class PlatformVpnProfile {
return mType;
}
-
/**
- * Returns if the local traffic is exempted from the VPN.
+ * Returns whether the local traffic is exempted from the VPN.
*/
public final boolean getExcludeLocalRoutes() {
return mExcludeLocalRoutes;
}
+ /**
+ * Returns whether this VPN should undergo Internet validation.
+ *
+ * If this is true, the platform will perform basic validation checks for Internet
+ * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+ * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+ * capability.
+ *
+ * If this is false, the platform assumes the VPN either is always capable of reaching the
+ * Internet or intends not to. In this case, the VPN network capabilities will
+ * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+ * immediately after it connects, whether it can reach public Internet destinations or not.
+ */
+ public final boolean getRequiresInternetValidation() {
+ return mRequiresInternetValidation;
+ }
+
/** Returns a type string describing the VPN profile type */
@NonNull
public final String getTypeString() {
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2ae56f808972..f174498c0d0d 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -105,6 +105,7 @@ public class VpnConfig implements Parcelable {
public boolean allowIPv4;
public boolean allowIPv6;
public boolean isMetered = true;
+ public boolean requiresInternetValidation = false;
public Network[] underlyingNetworks;
public ProxyInfo proxyInfo;
@@ -131,6 +132,7 @@ public class VpnConfig implements Parcelable {
allowIPv4 = other.allowIPv4;
allowIPv6 = other.allowIPv6;
isMetered = other.isMetered;
+ requiresInternetValidation = other.requiresInternetValidation;
underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
other.underlyingNetworks, other.underlyingNetworks.length) : null;
proxyInfo = other.proxyInfo;
@@ -189,6 +191,7 @@ public class VpnConfig implements Parcelable {
out.writeInt(allowIPv4 ? 1 : 0);
out.writeInt(allowIPv6 ? 1 : 0);
out.writeInt(isMetered ? 1 : 0);
+ out.writeInt(requiresInternetValidation ? 1 : 0);
out.writeTypedArray(underlyingNetworks, flags);
out.writeParcelable(proxyInfo, flags);
}
@@ -216,6 +219,7 @@ public class VpnConfig implements Parcelable {
config.allowIPv4 = in.readInt() != 0;
config.allowIPv6 = in.readInt() != 0;
config.isMetered = in.readInt() != 0;
+ config.requiresInternetValidation = in.readInt() != 0;
config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
config.proxyInfo = in.readParcelable(null);
return config;
@@ -248,6 +252,8 @@ public class VpnConfig implements Parcelable {
.append(", allowBypass=").append(allowBypass)
.append(", allowIPv4=").append(allowIPv4)
.append(", allowIPv6=").append(allowIPv6)
+ .append(", isMetered=").append(isMetered)
+ .append(", requiresInternetValidation").append(requiresInternetValidation)
.append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
.append(", proxyInfo=").append(proxyInfo)
.append("}")
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index d8dc1436128e..bd3e898a631c 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -144,23 +144,26 @@ public final class VpnProfile implements Cloneable, Parcelable {
public final boolean isRestrictedToTestNetworks; // 24
public final boolean excludeLocalRoutes; // 25
+ public final boolean requiresInternetValidation; // 26
// Helper fields.
@UnsupportedAppUsage
public transient boolean saveLogin = false;
public VpnProfile(String key) {
- this(key, false, false);
+ this(key, false, false, false);
}
public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
- this(key, isRestrictedToTestNetworks, false);
+ this(key, isRestrictedToTestNetworks, false, false);
}
- public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes) {
+ public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
+ boolean requiresInternetValidation) {
this.key = key;
this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
this.excludeLocalRoutes = excludeLocalRoutes;
+ this.requiresInternetValidation = requiresInternetValidation;
}
@UnsupportedAppUsage
@@ -191,6 +194,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
areAuthParamsInline = in.readBoolean();
isRestrictedToTestNetworks = in.readBoolean();
excludeLocalRoutes = in.readBoolean();
+ requiresInternetValidation = in.readBoolean();
}
/**
@@ -239,6 +243,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
out.writeBoolean(areAuthParamsInline);
out.writeBoolean(isRestrictedToTestNetworks);
out.writeBoolean(excludeLocalRoutes);
+ out.writeBoolean(requiresInternetValidation);
}
/**
@@ -258,9 +263,11 @@ public final class VpnProfile implements Cloneable, Parcelable {
// 14-19: Standard profile, with option for serverCert, proxy
// 24: Standard profile with serverCert, proxy and platform-VPN parameters
// 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
- // 26: Standard profile with platform-VPN parameters and excludeLocalRoutes
- if ((values.length < 14 || values.length > 19)
- && values.length != 24 && values.length != 25 && values.length != 26) {
+ // 26: ...and excludeLocalRoutes
+ // (26 can only be found on dogfood devices)
+ // 27: ...and requiresInternetValidation
+ if ((values.length < 14 || (values.length > 19 && values.length < 24)
+ || values.length > 27)) {
return null;
}
@@ -278,8 +285,15 @@ public final class VpnProfile implements Cloneable, Parcelable {
excludeLocalRoutes = false;
}
+ final boolean requiresInternetValidation;
+ if (values.length >= 27) {
+ requiresInternetValidation = Boolean.parseBoolean(values[26]);
+ } else {
+ requiresInternetValidation = false;
+ }
+
VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
- excludeLocalRoutes);
+ excludeLocalRoutes, requiresInternetValidation);
profile.name = values[0];
profile.type = Integer.parseInt(values[1]);
if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -390,6 +404,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
+ builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
@@ -471,7 +486,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
- isRestrictedToTestNetworks, excludeLocalRoutes);
+ isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
}
/** Checks VPN profiles for interior equality. */
@@ -505,11 +520,12 @@ public final class VpnProfile implements Cloneable, Parcelable {
&& maxMtu == other.maxMtu
&& areAuthParamsInline == other.areAuthParamsInline
&& isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
- && excludeLocalRoutes == other.excludeLocalRoutes;
+ && excludeLocalRoutes == other.excludeLocalRoutes
+ && requiresInternetValidation == other.requiresInternetValidation;
}
@NonNull
- public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+ public static final Creator<VpnProfile> CREATOR = new Creator<>() {
@Override
public VpnProfile createFromParcel(Parcel in) {
return new VpnProfile(in);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9a9c3ea05d19..bbef6b0d848f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1302,6 +1302,7 @@ public class Vpn {
.setLegacyType(ConnectivityManager.TYPE_VPN)
.setLegacyTypeName("VPN")
.setBypassableVpn(mConfig.allowBypass && !mLockdown)
+ .setVpnRequiresValidation(mConfig.requiresInternetValidation)
.build();
capsBuilder.setOwnerUid(mOwnerUID);
@@ -3363,6 +3364,7 @@ public class Vpn {
}
mConfig.startTime = SystemClock.elapsedRealtime();
mConfig.proxyInfo = profile.proxy;
+ mConfig.requiresInternetValidation = profile.requiresInternetValidation;
switch (profile.type) {
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: