Merge changes I7a017026,I76a5c940 into main am: 520d7c6758 am: 6d96b61bfa am: 0a173b2618

Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/2819338

Change-Id: I60593753806b8804b2647bd9251f630b6203a764
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hansen Kurli
2023-11-15 08:32:47 +00:00
committed by Automerger Merge Worker
4 changed files with 37 additions and 260 deletions

View File

@@ -66,25 +66,6 @@
<EditText style="@style/vpn_value" <EditText style="@style/vpn_value"
android:id="@+id/server"/> android:id="@+id/server"/>
<CheckBox style="@style/vpn_value"
android:id="@+id/mppe"
android:text="@string/vpn_mppe"
android:visibility="gone"/>
<LinearLayout android:id="@+id/l2tp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView style="@style/vpn_label"
android:text="@string/vpn_l2tp_secret"
android:labelFor="@+id/l2tp_secret"/>
<EditText style="@style/vpn_value"
android:id="@+id/l2tp_secret"
android:password="true"
android:hint="@string/vpn_not_used"/>
</LinearLayout>
<LinearLayout android:id="@+id/options_ipsec_identity" <LinearLayout android:id="@+id/options_ipsec_identity"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -154,31 +135,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
<LinearLayout android:id="@+id/network_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView style="@style/vpn_label"
android:text="@string/vpn_search_domains"
android:labelFor="@+id/search_domains"/>
<EditText style="@style/vpn_value"
android:id="@+id/search_domains"
android:hint="@string/vpn_not_used"/>
<TextView style="@style/vpn_label"
android:text="@string/vpn_dns_servers"
android:labelFor="@+id/dns_servers"/>
<EditText style="@style/vpn_value"
android:id="@+id/dns_servers"
android:hint="@string/vpn_not_used"/>
<TextView style="@style/vpn_label"
android:text="@string/vpn_routes"
android:labelFor="@+id/routes"/>
<EditText style="@style/vpn_value"
android:id="@+id/routes"
android:hint="@string/vpn_not_used"/>
</LinearLayout>
<TextView android:id="@+id/vpn_proxy_settings_title" <TextView android:id="@+id/vpn_proxy_settings_title"
style="@style/vpn_label" style="@style/vpn_label"

View File

@@ -872,15 +872,9 @@
<item>1</item> <item>1</item>
</string-array> </string-array>
<!-- Match this with the constants in VpnProfile. --> <skip /> <!-- Match this with the array VPN_TYPES in ConfigDialog. --> <skip />
<!-- Short names for each VPN type, not really translatable. [CHAR LIMIT=20] --> <!-- Short names for each VPN type, not really translatable. [CHAR LIMIT=20] -->
<string-array name="vpn_types" translatable="false"> <string-array name="vpn_types" translatable="false">
<item>PPTP</item>
<item>L2TP/IPSec PSK</item>
<item>L2TP/IPSec RSA</item>
<item>IPSec Xauth PSK</item>
<item>IPSec Xauth RSA</item>
<item>IPSec Hybrid RSA</item>
<item>IKEv2/IPSec MSCHAPv2</item> <item>IKEv2/IPSec MSCHAPv2</item>
<item>IKEv2/IPSec PSK</item> <item>IKEv2/IPSec PSK</item>
<item>IKEv2/IPSec RSA</item> <item>IKEv2/IPSec RSA</item>

View File

@@ -6440,10 +6440,6 @@
<string name="vpn_type">Type</string> <string name="vpn_type">Type</string>
<!-- Input label for the server address of a VPN profile. [CHAR LIMIT=40] --> <!-- Input label for the server address of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_server">Server address</string> <string name="vpn_server">Server address</string>
<!-- Checkbox label to enable PPP encryption for a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_mppe">PPP encryption (MPPE)</string>
<!-- Input label for the L2TP secret of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_l2tp_secret">L2TP secret</string>
<!-- Input label for the IPSec identifier of a VPN profile. [CHAR LIMIT=40] --> <!-- Input label for the IPSec identifier of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_ipsec_identifier">IPSec identifier</string> <string name="vpn_ipsec_identifier">IPSec identifier</string>
<!-- Input label for the IPSec pre-shared key of a VPN profile. [CHAR LIMIT=40] --> <!-- Input label for the IPSec pre-shared key of a VPN profile. [CHAR LIMIT=40] -->
@@ -6456,12 +6452,6 @@
<string name="vpn_ipsec_server_cert">IPSec server certificate</string> <string name="vpn_ipsec_server_cert">IPSec server certificate</string>
<!-- Checkbox label to show advanced options of a VPN profile. [CHAR LIMIT=40] --> <!-- Checkbox label to show advanced options of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_show_options">Show advanced options</string> <string name="vpn_show_options">Show advanced options</string>
<!-- Input label for the DNS search domains of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_search_domains">DNS search domains</string>
<!-- Input label for the DNS servers of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_dns_servers">DNS servers (e.g. 8.8.8.8)</string>
<!-- Input label for the forwarding routes of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_routes">Forwarding routes (e.g. 10.0.0.0/8)</string>
<!-- Input label for the username of a VPN profile. [CHAR LIMIT=40] --> <!-- Input label for the username of a VPN profile. [CHAR LIMIT=40] -->
<string name="vpn_username">Username</string> <string name="vpn_username">Username</string>
<!-- Input label for the password of a VPN profile. [CHAR LIMIT=40] --> <!-- Input label for the password of a VPN profile. [CHAR LIMIT=40] -->
@@ -6474,22 +6464,6 @@
<string name="vpn_no_ca_cert">(don\u2019t verify server)</string> <string name="vpn_no_ca_cert">(don\u2019t verify server)</string>
<!-- Option to use the server certificate received from the VPN server. [CHAR LIMIT=40] --> <!-- Option to use the server certificate received from the VPN server. [CHAR LIMIT=40] -->
<string name="vpn_no_server_cert">(received from server)</string> <string name="vpn_no_server_cert">(received from server)</string>
<!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
the selected VPN type doesn't support always-on. [CHAR LIMIT=120] -->
<string name="vpn_always_on_invalid_reason_type">This VPN type can\'t stay connected at all
times</string>
<!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
the server address is not in numeric form (e.g. 8.8.8.8). [CHAR LIMIT=120] -->
<string name="vpn_always_on_invalid_reason_server">Always-on VPN only supports numeric server
addresses</string>
<!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
no DNS is found. [CHAR LIMIT=120] -->
<string name="vpn_always_on_invalid_reason_no_dns">A DNS server must be specified for always-on
VPN</string>
<!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
DNS server addresses are not in numeric form (e.g. 8.8.8.8). [CHAR LIMIT=120] -->
<string name="vpn_always_on_invalid_reason_dns">DNS server addresses must be numeric for
always-on VPN</string>
<!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled: <!-- Error message displayed below the always-on VPN checkbox when the checkbox is disabled:
generic error. [CHAR LIMIT=120] --> generic error. [CHAR LIMIT=120] -->
<string name="vpn_always_on_invalid_reason_other">The information entered doesn\'t support <string name="vpn_always_on_invalid_reason_other">The information entered doesn\'t support

View File

@@ -16,8 +16,6 @@
package com.android.settings.vpn2; package com.android.settings.vpn2;
import static com.android.internal.net.VpnProfile.isLegacyType;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@@ -43,9 +41,6 @@ import com.android.net.module.util.ProxyUtils;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.utils.AndroidKeystoreAliasLoader;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -60,13 +55,18 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
View.OnClickListener, AdapterView.OnItemSelectedListener, View.OnClickListener, AdapterView.OnItemSelectedListener,
CompoundButton.OnCheckedChangeListener { CompoundButton.OnCheckedChangeListener {
private static final String TAG = "ConfigDialog"; private static final String TAG = "ConfigDialog";
// Vpn profile constants to match with R.array.vpn_types.
private static final List<Integer> VPN_TYPES = List.of(
VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS,
VpnProfile.TYPE_IKEV2_IPSEC_PSK,
VpnProfile.TYPE_IKEV2_IPSEC_RSA
);
private final DialogInterface.OnClickListener mListener; private final DialogInterface.OnClickListener mListener;
private final VpnProfile mProfile; private final VpnProfile mProfile;
private boolean mEditing; private boolean mEditing;
private boolean mExists; private boolean mExists;
private List<String> mTotalTypes;
private List<String> mAllowedTypes;
private View mView; private View mView;
@@ -75,14 +75,9 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
private TextView mServer; private TextView mServer;
private TextView mUsername; private TextView mUsername;
private TextView mPassword; private TextView mPassword;
private TextView mSearchDomains;
private TextView mDnsServers;
private TextView mRoutes;
private Spinner mProxySettings; private Spinner mProxySettings;
private TextView mProxyHost; private TextView mProxyHost;
private TextView mProxyPort; private TextView mProxyPort;
private CheckBox mMppe;
private TextView mL2tpSecret;
private TextView mIpsecIdentifier; private TextView mIpsecIdentifier;
private TextView mIpsecSecret; private TextView mIpsecSecret;
private Spinner mIpsecUserCert; private Spinner mIpsecUserCert;
@@ -116,14 +111,9 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mServer = (TextView) mView.findViewById(R.id.server); mServer = (TextView) mView.findViewById(R.id.server);
mUsername = (TextView) mView.findViewById(R.id.username); mUsername = (TextView) mView.findViewById(R.id.username);
mPassword = (TextView) mView.findViewById(R.id.password); mPassword = (TextView) mView.findViewById(R.id.password);
mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
mRoutes = (TextView) mView.findViewById(R.id.routes);
mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings); mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings);
mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host); mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host);
mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port); mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port);
mMppe = (CheckBox) mView.findViewById(R.id.mppe);
mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier); mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier);
mIpsecSecret = (TextView) mView.findViewById(R.id.ipsec_secret); mIpsecSecret = (TextView) mView.findViewById(R.id.ipsec_secret);
mIpsecUserCert = (Spinner) mView.findViewById(R.id.ipsec_user_cert); mIpsecUserCert = (Spinner) mView.findViewById(R.id.ipsec_user_cert);
@@ -137,29 +127,17 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// Second, copy values from the profile. // Second, copy values from the profile.
mName.setText(mProfile.name); mName.setText(mProfile.name);
setTypesByFeature(mType); setTypesByFeature(mType);
// Not all types will be available to the user. Find the index corresponding to the mType.setSelection(convertVpnProfileConstantToTypeIndex(mProfile.type));
// string of the profile's type.
if (mAllowedTypes != null && mTotalTypes != null) {
mType.setSelection(mAllowedTypes.indexOf(mTotalTypes.get(mProfile.type)));
} else {
Log.w(TAG, "Allowed or Total vpn types not initialized when setting initial selection");
}
mServer.setText(mProfile.server); mServer.setText(mProfile.server);
if (mProfile.saveLogin) { if (mProfile.saveLogin) {
mUsername.setText(mProfile.username); mUsername.setText(mProfile.username);
mPassword.setText(mProfile.password); mPassword.setText(mProfile.password);
} }
mSearchDomains.setText(mProfile.searchDomains);
mDnsServers.setText(mProfile.dnsServers);
mRoutes.setText(mProfile.routes);
if (mProfile.proxy != null) { if (mProfile.proxy != null) {
mProxyHost.setText(mProfile.proxy.getHost()); mProxyHost.setText(mProfile.proxy.getHost());
int port = mProfile.proxy.getPort(); int port = mProfile.proxy.getPort();
mProxyPort.setText(port == 0 ? "" : Integer.toString(port)); mProxyPort.setText(port == 0 ? "" : Integer.toString(port));
} }
mMppe.setChecked(mProfile.mppe);
mL2tpSecret.setText(mProfile.l2tpSecret);
mL2tpSecret.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium);
mIpsecIdentifier.setText(mProfile.ipsecIdentifier); mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
mIpsecSecret.setText(mProfile.ipsecSecret); mIpsecSecret.setText(mProfile.ipsecSecret);
final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = final AndroidKeystoreAliasLoader androidKeystoreAliasLoader =
@@ -185,8 +163,6 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mServer.addTextChangedListener(this); mServer.addTextChangedListener(this);
mUsername.addTextChangedListener(this); mUsername.addTextChangedListener(this);
mPassword.addTextChangedListener(this); mPassword.addTextChangedListener(this);
mDnsServers.addTextChangedListener(this);
mRoutes.addTextChangedListener(this);
mProxySettings.setOnItemSelectedListener(this); mProxySettings.setOnItemSelectedListener(this);
mProxyHost.addTextChangedListener(this); mProxyHost.addTextChangedListener(this);
mProxyPort.addTextChangedListener(this); mProxyPort.addTextChangedListener(this);
@@ -217,12 +193,6 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// Create a button to forget the profile if it has already been saved.. // Create a button to forget the profile if it has already been saved..
setButton(DialogInterface.BUTTON_NEUTRAL, setButton(DialogInterface.BUTTON_NEUTRAL,
context.getString(R.string.vpn_forget), mListener); context.getString(R.string.vpn_forget), mListener);
// Display warning subtitle if the existing VPN is an insecure type...
if (VpnProfile.isLegacyType(mProfile.type)) {
TextView subtitle = mView.findViewById(R.id.dialog_alert_subtitle);
subtitle.setVisibility(View.VISIBLE);
}
} }
// Create a button to save the profile. // Create a button to save the profile.
@@ -285,10 +255,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == mType) { if (parent == mType) {
// Because the spinner may not display all available types, changeType(VPN_TYPES.get(position));
// convert the selected position into the actual vpn profile type integer.
final int profileType = convertAllowedIndexToProfileType(position);
changeType(profileType);
} else if (parent == mProxySettings) { } else if (parent == mProxySettings) {
updateProxyFieldsVisibility(position); updateProxyFieldsVisibility(position);
} }
@@ -330,17 +297,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} else { } else {
mAlwaysOnVpn.setChecked(false); mAlwaysOnVpn.setChecked(false);
mAlwaysOnVpn.setEnabled(false); mAlwaysOnVpn.setEnabled(false);
if (!profile.isTypeValidForLockdown()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_type);
} else if (isLegacyType(profile.type) && !profile.isServerAddressNumeric()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_server);
} else if (isLegacyType(profile.type) && !profile.hasDns()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_no_dns);
} else if (isLegacyType(profile.type) && !profile.areDnsAddressesNumeric()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_dns);
} else {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_other); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_other);
}
mAlwaysOnInvalidReason.setVisibility(View.VISIBLE); mAlwaysOnInvalidReason.setVisibility(View.VISIBLE);
} }
@@ -370,21 +327,14 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} }
private boolean isAdvancedOptionsEnabled() { private boolean isAdvancedOptionsEnabled() {
return mSearchDomains.getText().length() > 0 || mDnsServers.getText().length() > 0 || return mProxyHost.getText().length() > 0 || mProxyPort.getText().length() > 0;
mRoutes.getText().length() > 0 || mProxyHost.getText().length() > 0
|| mProxyPort.getText().length() > 0;
} }
private void configureAdvancedOptionsVisibility() { private void configureAdvancedOptionsVisibility() {
if (mShowOptions.isChecked() || isAdvancedOptionsEnabled()) { if (mShowOptions.isChecked() || isAdvancedOptionsEnabled()) {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE); mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
mShowOptions.setVisibility(View.GONE); mShowOptions.setVisibility(View.GONE);
// Configure networking option visibility
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes // TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
final int visibility =
isLegacyType(getSelectedVpnType()) ? View.VISIBLE : View.GONE;
mView.findViewById(R.id.network_options).setVisibility(visibility);
} else { } else {
mView.findViewById(R.id.options).setVisibility(View.GONE); mView.findViewById(R.id.options).setVisibility(View.GONE);
mShowOptions.setVisibility(View.VISIBLE); mShowOptions.setVisibility(View.VISIBLE);
@@ -393,8 +343,6 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
private void changeType(int type) { private void changeType(int type) {
// First, hide everything. // First, hide everything.
mMppe.setVisibility(View.GONE);
mView.findViewById(R.id.l2tp).setVisibility(View.GONE);
mView.findViewById(R.id.ipsec_psk).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_psk).setVisibility(View.GONE);
mView.findViewById(R.id.ipsec_user).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_user).setVisibility(View.GONE);
mView.findViewById(R.id.ipsec_peer).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_peer).setVisibility(View.GONE);
@@ -403,34 +351,18 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
setUsernamePasswordVisibility(type); setUsernamePasswordVisibility(type);
// Always enable identity for IKEv2/IPsec profiles. // Always enable identity for IKEv2/IPsec profiles.
if (!isLegacyType(type)) {
mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE); mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE);
}
// Then, unhide type-specific fields. // Then, unhide type-specific fields.
switch (type) { switch (type) {
case VpnProfile.TYPE_PPTP: case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
mMppe.setVisibility(View.VISIBLE);
break;
case VpnProfile.TYPE_L2TP_IPSEC_PSK:
mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE);
// fall through
case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
mView.findViewById(R.id.ipsec_psk).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_psk).setVisibility(View.VISIBLE);
mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE); mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE);
break; break;
case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
case VpnProfile.TYPE_L2TP_IPSEC_RSA:
mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE);
// fall through
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
mView.findViewById(R.id.ipsec_user).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_user).setVisibility(View.VISIBLE);
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
mView.findViewById(R.id.ipsec_peer).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_peer).setVisibility(View.VISIBLE);
break; break;
} }
@@ -443,7 +375,8 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
return false; return false;
} }
final int type = getSelectedVpnType(); final int position = mType.getSelectedItemPosition();
final int type = VPN_TYPES.get(position);
if (!editing && requiresUsernamePassword(type)) { if (!editing && requiresUsernamePassword(type)) {
return mUsername.getText().length() != 0 && mPassword.getText().length() != 0; return mUsername.getText().length() != 0 && mPassword.getText().length() != 0;
} }
@@ -451,15 +384,8 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
return false; return false;
} }
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
if (isLegacyType(mProfile.type)
&& (!validateAddresses(mDnsServers.getText().toString(), false)
|| !validateAddresses(mRoutes.getText().toString(), true))) {
return false;
}
// All IKEv2 methods require an identifier // All IKEv2 methods require an identifier
if (!isLegacyType(mProfile.type) && mIpsecIdentifier.getText().length() == 0) { if (mIpsecIdentifier.getText().length() == 0) {
return false; return false;
} }
@@ -468,56 +394,23 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} }
switch (type) { switch (type) {
case VpnProfile.TYPE_PPTP: // fall through
case VpnProfile.TYPE_IPSEC_HYBRID_RSA: // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
return true; return true;
case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
case VpnProfile.TYPE_L2TP_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
return mIpsecSecret.getText().length() != 0; return mIpsecSecret.getText().length() != 0;
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
case VpnProfile.TYPE_L2TP_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
return mIpsecUserCert.getSelectedItemPosition() != 0; return mIpsecUserCert.getSelectedItemPosition() != 0;
} }
return false; return false;
} }
private boolean validateAddresses(String addresses, boolean cidr) {
try {
for (String address : addresses.split(" ")) {
if (address.isEmpty()) {
continue;
}
// Legacy VPN currently only supports IPv4.
int prefixLength = 32;
if (cidr) {
String[] parts = address.split("/", 2);
address = parts[0];
prefixLength = Integer.parseInt(parts[1]);
}
byte[] bytes = InetAddress.parseNumericAddress(address).getAddress();
int integer = (bytes[3] & 0xFF) | (bytes[2] & 0xFF) << 8 |
(bytes[1] & 0xFF) << 16 | (bytes[0] & 0xFF) << 24;
if (bytes.length != 4 || prefixLength < 0 || prefixLength > 32 ||
(prefixLength < 32 && (integer << prefixLength) != 0)) {
return false;
}
}
} catch (Exception e) {
return false;
}
return true;
}
private void setTypesByFeature(Spinner typeSpinner) { private void setTypesByFeature(Spinner typeSpinner) {
String[] types = getContext().getResources().getStringArray(R.array.vpn_types); String[] types = getContext().getResources().getStringArray(R.array.vpn_types);
mTotalTypes = new ArrayList<>(Arrays.asList(types)); if (types.length != VPN_TYPES.size()) {
mAllowedTypes = new ArrayList<>(Arrays.asList(types)); Log.wtf(TAG, "VPN_TYPES array length does not match string array");
}
// Although FEATURE_IPSEC_TUNNELS should always be present in android S and beyond, // Although FEATURE_IPSEC_TUNNELS should always be present in android S and beyond,
// keep this check here just to be safe. // keep this check here just to be safe.
if (!getContext().getPackageManager().hasSystemFeature( if (!getContext().getPackageManager().hasSystemFeature(
@@ -532,17 +425,6 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mProfile.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; mProfile.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
} }
// Remove all types which are legacy types from the typesList
if (!VpnProfile.isLegacyType(mProfile.type)) {
for (int i = mAllowedTypes.size() - 1; i >= 0; i--) {
// This must be removed from back to front in order to ensure index consistency
if (VpnProfile.isLegacyType(i)) {
mAllowedTypes.remove(i);
}
}
types = mAllowedTypes.toArray(new String[0]);
}
final ArrayAdapter<String> adapter = new ArrayAdapter<String>( final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getContext(), android.R.layout.simple_spinner_item, types); getContext(), android.R.layout.simple_spinner_item, types);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -606,20 +488,14 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// First, save common fields. // First, save common fields.
VpnProfile profile = new VpnProfile(mProfile.key); VpnProfile profile = new VpnProfile(mProfile.key);
profile.name = mName.getText().toString(); profile.name = mName.getText().toString();
profile.type = getSelectedVpnType(); final int position = mType.getSelectedItemPosition();
profile.type = VPN_TYPES.get(position);
profile.server = mServer.getText().toString().trim(); profile.server = mServer.getText().toString().trim();
profile.username = mUsername.getText().toString(); profile.username = mUsername.getText().toString();
profile.password = mPassword.getText().toString(); profile.password = mPassword.getText().toString();
// Save fields based on VPN type. // Save fields based on VPN type.
if (isLegacyType(profile.type)) {
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
profile.searchDomains = mSearchDomains.getText().toString().trim();
profile.dnsServers = mDnsServers.getText().toString().trim();
profile.routes = mRoutes.getText().toString().trim();
} else {
profile.ipsecIdentifier = mIpsecIdentifier.getText().toString(); profile.ipsecIdentifier = mIpsecIdentifier.getText().toString();
}
if (hasProxy()) { if (hasProxy()) {
String proxyHost = mProxyHost.getText().toString().trim(); String proxyHost = mProxyHost.getText().toString().trim();
@@ -640,34 +516,17 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} }
// Then, save type-specific fields. // Then, save type-specific fields.
switch (profile.type) { switch (profile.type) {
case VpnProfile.TYPE_PPTP: case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
profile.mppe = mMppe.isChecked();
break;
case VpnProfile.TYPE_L2TP_IPSEC_PSK:
profile.l2tpSecret = mL2tpSecret.getText().toString();
// fall through
case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
profile.ipsecIdentifier = mIpsecIdentifier.getText().toString();
profile.ipsecSecret = mIpsecSecret.getText().toString(); profile.ipsecSecret = mIpsecSecret.getText().toString();
break; break;
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
if (mIpsecUserCert.getSelectedItemPosition() != 0) {
profile.ipsecSecret = (String) mIpsecUserCert.getSelectedItem();
}
// fall through
case VpnProfile.TYPE_L2TP_IPSEC_RSA:
profile.l2tpSecret = mL2tpSecret.getText().toString();
// fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
if (mIpsecUserCert.getSelectedItemPosition() != 0) { if (mIpsecUserCert.getSelectedItemPosition() != 0) {
profile.ipsecUserCert = (String) mIpsecUserCert.getSelectedItem(); profile.ipsecUserCert = (String) mIpsecUserCert.getSelectedItem();
profile.ipsecSecret = profile.ipsecUserCert;
} }
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
if (mIpsecCaCert.getSelectedItemPosition() != 0) { if (mIpsecCaCert.getSelectedItemPosition() != 0) {
profile.ipsecCaCert = (String) mIpsecCaCert.getSelectedItem(); profile.ipsecCaCert = (String) mIpsecCaCert.getSelectedItem();
} }
@@ -692,19 +551,13 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
return ProxyUtils.validate(host, port, "") == ProxyUtils.PROXY_VALID; return ProxyUtils.validate(host, port, "") == ProxyUtils.PROXY_VALID;
} }
private int getSelectedVpnType() { private int convertVpnProfileConstantToTypeIndex(int vpnType) {
return convertAllowedIndexToProfileType(mType.getSelectedItemPosition()); final int typeIndex = VPN_TYPES.indexOf(vpnType);
if (typeIndex == -1) {
// Existing legacy profile type
Log.wtf(TAG, "Invalid existing profile type");
return 0;
} }
return typeIndex;
private int convertAllowedIndexToProfileType(int allowedSelectedPosition) {
if (mAllowedTypes != null && mTotalTypes != null) {
final String typeString = mAllowedTypes.get(allowedSelectedPosition);
final int profileType = mTotalTypes.indexOf(typeString);
return profileType;
} else {
Log.w(TAG, "Allowed or Total vpn types not initialized when converting protileType");
return allowedSelectedPosition;
} }
} }
}