Ignore other IKE options if IkeTunnelConnectionParams is set
Stop parsing the IKE options from the input IkeTunnelConnectionParams
if exists. The caller shuould get the relevant infortation the
params.
The field is also stored in the VpnProfile if it built from an
Ikev2VpnProfile.
Bug: 184750836
Test: atest FrameworksNetTests HostsideVpnTests
Test: build ; flash ; connect VPN successfully
Change-Id: Id05c17285915462c7a6cd51d5fb4ee5da7f465ba
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 3abe83b..1b503b1 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -25,12 +25,6 @@
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
-import static android.net.eap.EapSessionConfig.EapMsChapV2Config;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig;
-import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
@@ -40,6 +34,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.content.pm.PackageManager;
+import android.net.ipsec.ike.IkeDerAsn1DnIdentification;
import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeIdentification;
import android.net.ipsec.ike.IkeIpv4AddrIdentification;
@@ -119,8 +114,8 @@
DEFAULT_ALGORITHMS = Collections.unmodifiableList(algorithms);
}
- @NonNull private final String mServerAddr;
- @NonNull private final String mUserIdentity;
+ @Nullable private final String mServerAddr;
+ @Nullable private final String mUserIdentity;
// PSK authentication
@Nullable private final byte[] mPresharedKey;
@@ -146,8 +141,8 @@
private Ikev2VpnProfile(
int type,
- @NonNull String serverAddr,
- @NonNull String userIdentity,
+ @Nullable String serverAddr,
+ @Nullable String userIdentity,
@Nullable byte[] presharedKey,
@Nullable X509Certificate serverRootCaCert,
@Nullable String username,
@@ -165,8 +160,6 @@
@Nullable IkeTunnelConnectionParams ikeTunConnParams) {
super(type, excludeLocalRoutes, requiresInternetValidation);
- checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
- checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
checkNotNull(allowedAlgorithms, MISSING_PARAM_MSG_TMPL, "Allowed Algorithms");
mServerAddr = serverAddr;
@@ -191,18 +184,12 @@
mIsMetered = isMetered;
mMaxMtu = maxMtu;
mIsRestrictedToTestNetworks = restrictToTestNetworks;
-
mIkeTunConnParams = ikeTunConnParams;
validate();
}
private void validate() {
- // Server Address not validated except to check an address was provided. This allows for
- // dual-stack servers and hostname based addresses.
- checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address");
- checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
-
// 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
// (at least that of the IPv6 MTU).
@@ -210,6 +197,15 @@
throw new IllegalArgumentException("Max MTU must be at least" + IPV6_MIN_MTU);
}
+ // Skip validating the other fields if mIkeTunConnParams is set because the required
+ // information should all come from the mIkeTunConnParams.
+ if (mIkeTunConnParams != null) return;
+
+ // Server Address not validated except to check an address was provided. This allows for
+ // dual-stack servers and hostname based addresses.
+ checkStringNotEmpty(mServerAddr, MISSING_PARAM_MSG_TMPL, "Server Address");
+ checkStringNotEmpty(mUserIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
+
switch (mType) {
case TYPE_IKEV2_IPSEC_USER_PASS:
checkNotNull(mUsername, MISSING_PARAM_MSG_TMPL, "Username");
@@ -286,22 +282,31 @@
/** Retrieves the server address string. */
@NonNull
public String getServerAddr() {
- return mServerAddr;
+ if (mIkeTunConnParams == null) return mServerAddr;
+
+ final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+ return ikeSessionParams.getServerHostname();
}
/** Retrieves the user identity. */
@NonNull
public String getUserIdentity() {
- return mUserIdentity;
+ if (mIkeTunConnParams == null) return mUserIdentity;
+
+ final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+ return getUserIdentityFromIkeSession(ikeSessionParams);
}
/**
* Retrieves the pre-shared key.
*
- * <p>May be null if the profile is not using Pre-shared key authentication.
+ * <p>May be null if the profile is not using Pre-shared key authentication, or the profile is
+ * built from an {@link IkeTunnelConnectionParams}.
*/
@Nullable
public byte[] getPresharedKey() {
+ if (mIkeTunConnParams != null) return null;
+
return mPresharedKey == null ? null : Arrays.copyOf(mPresharedKey, mPresharedKey.length);
}
@@ -309,46 +314,62 @@
* Retrieves the certificate for the server's root CA.
*
* <p>May be null if the profile is not using RSA Digital Signature Authentication or
- * Username/Password authentication
+ * Username/Password authentication, or the profile is built from an
+ * {@link IkeTunnelConnectionParams}.
*/
@Nullable
public X509Certificate getServerRootCaCert() {
+ if (mIkeTunConnParams != null) return null;
+
return mServerRootCaCert;
}
-
/**
* Retrieves the username.
*
- * <p>May be null if the profile is not using Username/Password authentication
+ * <p>May be null if the profile is not using Username/Password authentication, or the profile
+ * is built from an {@link IkeTunnelConnectionParams}.
*/
@Nullable
public String getUsername() {
+ if (mIkeTunConnParams != null) return null;
+
return mUsername;
}
/**
* Retrieves the password.
*
- * <p>May be null if the profile is not using Username/Password authentication
+ * <p>May be null if the profile is not using Username/Password authentication, or the profile
+ * is built from an {@link IkeTunnelConnectionParams}.
*/
@Nullable
public String getPassword() {
+ if (mIkeTunConnParams != null) return null;
+
return mPassword;
}
/**
* Retrieves the RSA private key.
*
- * <p>May be null if the profile is not using RSA Digital Signature authentication
+ * <p>May be null if the profile is not using RSA Digital Signature authentication, or the
+ * profile is built from an {@link IkeTunnelConnectionParams}.
*/
@Nullable
public PrivateKey getRsaPrivateKey() {
+ if (mIkeTunConnParams != null) return null;
+
return mRsaPrivateKey;
}
- /** Retrieves the user certificate, if any was set. */
+ /** Retrieves the user certificate, if any was set.
+ *
+ * <p>May be null if the profile is built from an {@link IkeTunnelConnectionParams}.
+ */
@Nullable
public X509Certificate getUserCert() {
+ if (mIkeTunConnParams != null) return null;
+
return mUserCert;
}
@@ -358,9 +379,14 @@
return mProxyInfo;
}
- /** Returns all the algorithms allowed by this VPN profile. */
+ /** Returns all the algorithms allowed by this VPN profile.
+ *
+ * <p>May be an empty list if the profile is built from an {@link IkeTunnelConnectionParams}.
+ */
@NonNull
public List<String> getAllowedAlgorithms() {
+ if (mIkeTunConnParams != null) return new ArrayList<>();
+
return mAllowedAlgorithms;
}
@@ -455,18 +481,25 @@
@NonNull
public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
- mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
- profile.type = mType;
- profile.server = mServerAddr;
- profile.ipsecIdentifier = mUserIdentity;
+ mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation,
+ mIkeTunConnParams);
+
+ profile.server = getServerAddr();
+ profile.ipsecIdentifier = getUserIdentity();
profile.proxy = mProxyInfo;
- profile.setAllowedAlgorithms(mAllowedAlgorithms);
profile.isBypassable = mIsBypassable;
profile.isMetered = mIsMetered;
profile.maxMtu = mMaxMtu;
profile.areAuthParamsInline = true;
profile.saveLogin = true;
+ // The other fields should come from mIkeTunConnParams if it's available.
+ if (mIkeTunConnParams != null) {
+ profile.type = VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS;
+ return profile;
+ }
+ profile.type = mType;
+ profile.setAllowedAlgorithms(mAllowedAlgorithms);
switch (mType) {
case TYPE_IKEV2_IPSEC_USER_PASS:
profile.username = mUsername;
@@ -516,10 +549,47 @@
@NonNull
public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
throws GeneralSecurityException {
- // TODO: Build the VpnProfile from mIkeTunConnParams if it exists.
- final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
+ final Builder builder;
+ if (profile.ikeTunConnParams == null) {
+ builder = new Builder(profile.server, profile.ipsecIdentifier);
+ builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
+
+ switch (profile.type) {
+ case TYPE_IKEV2_IPSEC_USER_PASS:
+ builder.setAuthUsernamePassword(
+ profile.username,
+ profile.password,
+ certificateFromPemString(profile.ipsecCaCert));
+ break;
+ case TYPE_IKEV2_IPSEC_PSK:
+ builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
+ break;
+ case TYPE_IKEV2_IPSEC_RSA:
+ final PrivateKey key;
+ if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) {
+ final String alias =
+ profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length());
+ key = getPrivateKeyFromAndroidKeystore(alias);
+ } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) {
+ key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length()));
+ } else {
+ throw new IllegalArgumentException("Invalid RSA private key prefix");
+ }
+
+ final X509Certificate userCert =
+ certificateFromPemString(profile.ipsecUserCert);
+ final X509Certificate serverRootCa =
+ certificateFromPemString(profile.ipsecCaCert);
+ builder.setAuthDigitalSignature(userCert, key, serverRootCa);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid auth method set");
+ }
+ } else {
+ builder = new Builder(profile.ikeTunConnParams);
+ }
+
builder.setProxy(profile.proxy);
- builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
builder.setBypassable(profile.isBypassable);
builder.setMetered(profile.isMetered);
builder.setMaxMtu(profile.maxMtu);
@@ -527,36 +597,6 @@
builder.restrictToTestNetworks();
}
- switch (profile.type) {
- case TYPE_IKEV2_IPSEC_USER_PASS:
- builder.setAuthUsernamePassword(
- profile.username,
- profile.password,
- certificateFromPemString(profile.ipsecCaCert));
- break;
- case TYPE_IKEV2_IPSEC_PSK:
- builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
- break;
- case TYPE_IKEV2_IPSEC_RSA:
- final PrivateKey key;
- if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) {
- final String alias =
- profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length());
- key = getPrivateKeyFromAndroidKeystore(alias);
- } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) {
- key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length()));
- } else {
- throw new IllegalArgumentException("Invalid RSA private key prefix");
- }
-
- final X509Certificate userCert = certificateFromPemString(profile.ipsecUserCert);
- final X509Certificate serverRootCa = certificateFromPemString(profile.ipsecCaCert);
- builder.setAuthDigitalSignature(userCert, key, serverRootCa);
- break;
- default:
- throw new IllegalArgumentException("Invalid auth method set");
- }
-
if (profile.excludeLocalRoutes && !profile.isBypassable) {
Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
}
@@ -678,82 +718,13 @@
}
private static void checkBuilderSetter(boolean constructedFromIkeTunConParams,
- @NonNull String message) {
+ @NonNull String field) {
if (constructedFromIkeTunConParams) {
- throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams "
- + "should not set " + message);
+ throw new IllegalArgumentException(
+ field + " can't be set with IkeTunnelConnectionParams builder");
}
}
- private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) {
- final IkeAuthConfig config = params.getLocalAuthConfig();
- if (config instanceof IkeAuthDigitalSignLocalConfig) {
- return TYPE_IKEV2_IPSEC_RSA;
- } else if (config instanceof IkeAuthEapConfig) {
- return TYPE_IKEV2_IPSEC_USER_PASS;
- } else if (config instanceof IkeAuthPskConfig) {
- return TYPE_IKEV2_IPSEC_PSK;
- } else {
- throw new IllegalStateException("Invalid local IkeAuthConfig");
- }
- }
-
- @Nullable
- private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) {
- if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
-
- final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
- final EapMsChapV2Config eapMsChapV2Config =
- ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
- return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null;
- }
-
- @Nullable
- private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) {
- if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
-
- final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
- final EapMsChapV2Config eapMsChapV2Config =
- ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
- return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null;
- }
-
- @Nullable
- private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) {
- if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
-
- final IkeAuthDigitalSignLocalConfig config =
- (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
- return config.getClientEndCertificate();
- }
-
- @Nullable
- private static X509Certificate getServerRootCaCertFromIkeSession(
- @NonNull IkeSessionParams params) {
- if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null;
-
- final IkeAuthDigitalSignRemoteConfig config =
- (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig();
- return config.getRemoteCaCert();
- }
-
- @Nullable
- private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) {
- if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
-
- final IkeAuthDigitalSignLocalConfig config =
- (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
- return config.getPrivateKey();
- }
-
- @Nullable
- private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) {
- if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null;
-
- final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig();
- return config.getPsk();
- }
-
@NonNull
private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) {
final IkeIdentification ident = params.getLocalIdentification();
@@ -768,6 +739,8 @@
return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress();
} else if (ident instanceof IkeIpv6AddrIdentification) {
return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress();
+ } else if (ident instanceof IkeDerAsn1DnIdentification) {
+ throw new IllegalArgumentException("Unspported ASN.1 encoded identities");
} else {
throw new IllegalArgumentException("Unknown IkeIdentification to get user identity");
}
@@ -776,8 +749,8 @@
/** A incremental builder for IKEv2 VPN profiles */
public static final class Builder {
private int mType = -1;
- @NonNull private final String mServerAddr;
- @NonNull private final String mUserIdentity;
+ @Nullable private final String mServerAddr;
+ @Nullable private final String mUserIdentity;
// PSK authentication
@Nullable private byte[] mPresharedKey;
@@ -831,19 +804,8 @@
checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams");
mIkeTunConnParams = ikeTunConnParams;
-
- final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
- mServerAddr = ikeSessionParams.getServerHostname();
-
- mType = getTypeFromIkeSession(ikeSessionParams);
- mUserCert = getUserCertFromIkeSession(ikeSessionParams);
- mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
- mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams);
- mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
- mUsername = getUsernameFromIkeSession(ikeSessionParams);
- mPassword = getPasswordFromIkeSession(ikeSessionParams);
- mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams);
- mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams);
+ mServerAddr = null;
+ mUserIdentity = null;
}
private void resetAuthParams() {
@@ -862,6 +824,10 @@
* authentication method may be set. This method will overwrite any previously set
* authentication method.
*
+ * <p>It's not allowed to set this if this {@link Builder} is constructed from an
+ * {@link IkeTunnelConnectionParams}. This information should be retrieved from
+ * {@link IkeTunnelConnectionParams}
+ *
* @param user the username to be used for EAP-MSCHAPv2 authentication
* @param pass the password to be used for EAP-MSCHAPv2 authentication
* @param serverRootCa the root certificate to be used for verifying the identity of the
@@ -898,6 +864,10 @@
* Only one authentication method may be set. This method will overwrite any previously set
* authentication method.
*
+ * <p>It's not allowed to set this if this {@link Builder} is constructed from an
+ * {@link IkeTunnelConnectionParams}. This information should be retrieved from
+ * {@link IkeTunnelConnectionParams}
+ *
* @param userCert the username to be used for RSA Digital signiture authentication
* @param key the PrivateKey instance associated with the user ceritificate, used for
* constructing the signature
@@ -936,6 +906,10 @@
* authentication method may be set. This method will overwrite any previously set
* authentication method.
*
+ * <p>It's not allowed to set this if this {@link Builder} is constructed from an
+ * {@link IkeTunnelConnectionParams}. This information should be retrieved from
+ * {@link IkeTunnelConnectionParams}
+ *
* @param psk the key to be used for Pre-Shared Key authentication
* @return this {@link Builder} object to facilitate chaining of method calls
*/
@@ -1068,6 +1042,10 @@
* Authentication, and one that provides Encryption. Authenticated Encryption with
* Associated Data (AEAD) algorithms provide both Authentication and Encryption.
*
+ * <p>It's not allowed to set this if this {@link Builder} is constructed from an
+ * {@link IkeTunnelConnectionParams}. This information should be retrieved from
+ * {@link IkeTunnelConnectionParams}
+ *
* <p>By default, this profile will use any algorithm defined in {@link IpSecAlgorithm},
* with the exception of those considered insecure (as described above).
*
@@ -1079,6 +1057,7 @@
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
public Builder setAllowedAlgorithms(@NonNull List<String> algorithmNames) {
checkNotNull(algorithmNames, MISSING_PARAM_MSG_TMPL, "algorithmNames");
+ checkBuilderSetter(mIkeTunConnParams != null, "algorithmNames");
validateAllowedAlgorithms(algorithmNames);
mAllowedAlgorithms = algorithmNames;
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index bd3e898..8797381 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -22,12 +22,17 @@
import android.net.PlatformVpnProfile;
import android.net.ProxyInfo;
import android.net.Uri;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.text.TextUtils;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.HexDump;
import com.android.net.module.util.ProxyUtils;
import java.io.UnsupportedEncodingException;
@@ -69,7 +74,8 @@
public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6;
public static final int TYPE_IKEV2_IPSEC_PSK = 7;
public static final int TYPE_IKEV2_IPSEC_RSA = 8;
- public static final int TYPE_MAX = 8;
+ public static final int TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS = 9;
+ public static final int TYPE_MAX = 9;
// Match these constants with R.array.vpn_proxy_settings.
public static final int PROXY_NONE = 0;
@@ -145,25 +151,27 @@
public final boolean excludeLocalRoutes; // 25
public final boolean requiresInternetValidation; // 26
+ public final IkeTunnelConnectionParams ikeTunConnParams; // 27
// Helper fields.
@UnsupportedAppUsage
public transient boolean saveLogin = false;
public VpnProfile(String key) {
- this(key, false, false, false);
+ this(key, false, false, false, null);
}
public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
- this(key, isRestrictedToTestNetworks, false, false);
+ this(key, isRestrictedToTestNetworks, false, false, null);
}
public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
- boolean requiresInternetValidation) {
+ boolean requiresInternetValidation, IkeTunnelConnectionParams ikeTunConnParams) {
this.key = key;
this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
this.excludeLocalRoutes = excludeLocalRoutes;
this.requiresInternetValidation = requiresInternetValidation;
+ this.ikeTunConnParams = ikeTunConnParams;
}
@UnsupportedAppUsage
@@ -195,6 +203,10 @@
isRestrictedToTestNetworks = in.readBoolean();
excludeLocalRoutes = in.readBoolean();
requiresInternetValidation = in.readBoolean();
+ final PersistableBundle bundle =
+ in.readParcelable(PersistableBundle.class.getClassLoader());
+ ikeTunConnParams = (bundle == null) ? null
+ : TunnelConnectionParamsUtils.fromPersistableBundle(bundle);
}
/**
@@ -244,6 +256,8 @@
out.writeBoolean(isRestrictedToTestNetworks);
out.writeBoolean(excludeLocalRoutes);
out.writeBoolean(requiresInternetValidation);
+ out.writeParcelable(ikeTunConnParams == null ? null
+ : TunnelConnectionParamsUtils.toPersistableBundle(ikeTunConnParams), flags);
}
/**
@@ -259,15 +273,17 @@
}
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
// 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
// 26: ...and excludeLocalRoutes
- // (26 can only be found on dogfood devices)
// 27: ...and requiresInternetValidation
+ // (26,27 can only be found on dogfood devices)
+ // 28: ...and ikeTunConnParams
if ((values.length < 14 || (values.length > 19 && values.length < 24)
- || values.length > 27)) {
+ || values.length > 28)) {
return null;
}
@@ -292,8 +308,22 @@
requiresInternetValidation = false;
}
+ final IkeTunnelConnectionParams tempIkeTunConnParams;
+ // Assign null directly if the ikeTunConParams field is empty.
+ if (values.length >= 28 && values[27].length() != 0) {
+ final Parcel parcel = Parcel.obtain();
+ final byte[] bytes = HexDump.hexStringToByteArray(values[27]);
+ parcel.unmarshall(bytes, 0, bytes.length);
+ parcel.setDataPosition(0);
+ final PersistableBundle bundle = (PersistableBundle) parcel.readValue(
+ PersistableBundle.class.getClassLoader());
+ tempIkeTunConnParams = TunnelConnectionParamsUtils.fromPersistableBundle(bundle);
+ } else {
+ tempIkeTunConnParams = null;
+ }
+
VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
- excludeLocalRoutes, requiresInternetValidation);
+ excludeLocalRoutes, requiresInternetValidation, tempIkeTunConnParams);
profile.name = values[0];
profile.type = Integer.parseInt(values[1]);
if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -345,6 +375,7 @@
profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
return profile;
} catch (Exception e) {
+ Log.d(TAG, "Got exception in decode.", e);
// ignore
}
return null;
@@ -406,6 +437,17 @@
builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
+ if (ikeTunConnParams != null) {
+ final PersistableBundle bundle =
+ TunnelConnectionParamsUtils.toPersistableBundle(ikeTunConnParams);
+ final Parcel parcel = Parcel.obtain();
+ parcel.writeValue(bundle);
+ final byte[] bytes = parcel.marshall();
+ builder.append(VALUE_DELIMITER).append(HexDump.toHexString(bytes));
+ } else {
+ builder.append(VALUE_DELIMITER).append("");
+ }
+
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
@@ -486,7 +528,8 @@
key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
- isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
+ isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation,
+ ikeTunConnParams);
}
/** Checks VPN profiles for interior equality. */
@@ -521,7 +564,8 @@
&& areAuthParamsInline == other.areAuthParamsInline
&& isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
&& excludeLocalRoutes == other.excludeLocalRoutes
- && requiresInternetValidation == other.requiresInternetValidation;
+ && requiresInternetValidation == other.requiresInternetValidation
+ && Objects.equals(ikeTunConnParams, other.ikeTunConnParams);
}
@NonNull