From 57d61730b0c16e45bce643b20f6a2b489dad904e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 7 Oct 2019 16:42:00 +0200 Subject: [PATCH 01/12] android: Update Gradle plugin --- src/frontends/android/build.gradle | 2 +- .../android/gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontends/android/build.gradle b/src/frontends/android/build.gradle index f5a6850709..5880d16967 100644 --- a/src/frontends/android/build.gradle +++ b/src/frontends/android/build.gradle @@ -4,7 +4,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.2' + classpath 'com.android.tools.build:gradle:3.5.1' } } diff --git a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties index 54bc74adb1..558ba36a3e 100644 --- a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties +++ b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Aug 13 13:47:52 CEST 2019 +#Mon Oct 07 16:41:25 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip From 2ee1c6b1065c15ec0bcfd8576afa10e04f64b668 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 7 Oct 2019 17:00:11 +0200 Subject: [PATCH 02/12] android: Update AndroidX libraries --- src/frontends/android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/app/build.gradle b/src/frontends/android/app/build.gradle index b2d8c0b958..c9ec5bd3da 100644 --- a/src/frontends/android/app/build.gradle +++ b/src/frontends/android/app/build.gradle @@ -46,8 +46,8 @@ android { } dependencies { - implementation 'androidx.appcompat:appcompat:1.0.0' - implementation 'androidx.preference:preference:1.0.0' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.0.0' testImplementation 'junit:junit:4.12' From 54a4a3632d2c5687104e2294825ab7fd382b5e2a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 15:21:00 +0200 Subject: [PATCH 03/12] android: Fix deprecation warning related to FragmentPagerAdapter --- .../org/strongswan/android/ui/TrustedCertificatesActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java index 2953790230..1c13a110f7 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java @@ -169,7 +169,7 @@ public class TrustedCertificatesActivity extends AppCompatActivity implements Tr public TrustedCertificatesPagerAdapter(FragmentManager fm, Context context) { - super(fm); + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); mTabs = new TrustedCertificatesTab[]{ new TrustedCertificatesTab(context.getString(R.string.system_tab), TrustedCertificateSource.SYSTEM), new TrustedCertificatesTab(context.getString(R.string.user_tab), TrustedCertificateSource.USER), From 2e74fc219743754553321d8ceb298397b76f4776 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 14:46:38 +0200 Subject: [PATCH 04/12] android: Add helper to read strings from text boxes --- .../android/ui/VpnProfileDetailActivity.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java index 9674b7d415..53773e6768 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -28,7 +28,6 @@ import android.security.KeyChain; import android.security.KeyChainAliasCallback; import android.security.KeyChainException; import android.text.Editable; -import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; @@ -632,14 +631,14 @@ public class VpnProfileDetailActivity extends AppCompatActivity private boolean verifyInput() { boolean valid = true; - if (mGateway.getText().toString().trim().isEmpty()) + if (getString(mGateway) == null) { mGatewayWrap.setError(getString(R.string.alert_text_no_input_gateway)); valid = false; } if (mVpnType.has(VpnTypeFeature.USER_PASS)) { - if (mUsername.getText().toString().trim().isEmpty()) + if (getString(mUsername) == null) { mUsernameWrap.setError(getString(R.string.alert_text_no_input_username)); valid = false; @@ -705,17 +704,15 @@ public class VpnProfileDetailActivity extends AppCompatActivity private void updateProfileData() { /* the name is optional, we default to the gateway if none is given */ - String name = mName.getText().toString().trim(); - String gateway = mGateway.getText().toString().trim(); - mProfile.setName(name.isEmpty() ? gateway : name); + String name = getString(mName); + String gateway = getString(mGateway); + mProfile.setName(name == null ? gateway : name); mProfile.setGateway(gateway); mProfile.setVpnType(mVpnType); if (mVpnType.has(VpnTypeFeature.USER_PASS)) { - mProfile.setUsername(mUsername.getText().toString().trim()); - String password = mPassword.getText().toString().trim(); - password = password.isEmpty() ? null : password; - mProfile.setPassword(password); + mProfile.setUsername(getString(mUsername)); + mProfile.setPassword(getString(mPassword)); } if (mVpnType.has(VpnTypeFeature.CERTIFICATE)) { @@ -724,8 +721,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity } String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias(); mProfile.setCertificateAlias(certAlias); - String remote_id = mRemoteId.getText().toString().trim(); - mProfile.setRemoteId(remote_id.isEmpty() ? null : remote_id); + mProfile.setRemoteId(getString(mRemoteId)); mProfile.setMTU(getInteger(mMTU)); mProfile.setPort(getInteger(mPort)); mProfile.setNATKeepAlive(getInteger(mNATKeepalive)); @@ -736,22 +732,17 @@ public class VpnProfileDetailActivity extends AppCompatActivity flags |= mStrictRevocation.isChecked() ? VpnProfile.FLAGS_STRICT_REVOCATION : 0; flags |= mRsaPss.isChecked() ? VpnProfile.FLAGS_RSA_PSS : 0; mProfile.setFlags(flags); - String included = mIncludedSubnets.getText().toString().trim(); - mProfile.setIncludedSubnets(included.isEmpty() ? null : included); - String excluded = mExcludedSubnets.getText().toString().trim(); - mProfile.setExcludedSubnets(excluded.isEmpty() ? null : excluded); + mProfile.setIncludedSubnets(getString(mIncludedSubnets)); + mProfile.setExcludedSubnets(getString(mExcludedSubnets)); int st = 0; st |= mBlockIPv4.isChecked() ? VpnProfile.SPLIT_TUNNELING_BLOCK_IPV4 : 0; st |= mBlockIPv6.isChecked() ? VpnProfile.SPLIT_TUNNELING_BLOCK_IPV6 : 0; mProfile.setSplitTunneling(st == 0 ? null : st); mProfile.setSelectedAppsHandling(mSelectedAppsHandling); mProfile.setSelectedApps(mSelectedApps); - String ike = mIkeProposal.getText().toString().trim(); - mProfile.setIkeProposal(ike.isEmpty() ? null : ike); - String esp = mEspProposal.getText().toString().trim(); - mProfile.setEspProposal(esp.isEmpty() ? null : esp); - String dns = mDnsServers.getText().toString().trim(); - mProfile.setDnsServers(dns.isEmpty() ? null : dns); + mProfile.setIkeProposal(getString(mIkeProposal)); + mProfile.setEspProposal(getString(mEspProposal)); + mProfile.setDnsServers(getString(mDnsServers)); } /** @@ -846,6 +837,17 @@ public class VpnProfileDetailActivity extends AppCompatActivity } } + /** + * Get the string value in the given text box or null if empty + * + * @param view text box + */ + private String getString(EditText view) + { + String value = view.getText().toString().trim(); + return value.isEmpty() ? null : value; + } + /** * Get the integer value in the given text box or null if empty * From 999287f679cf5f562c84cd6a356b4aa8e8c032d7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 14:49:16 +0200 Subject: [PATCH 05/12] android: No auto-completion required for DNS server text box --- .../org/strongswan/android/ui/VpnProfileDetailActivity.java | 6 +++--- .../android/app/src/main/res/layout/profile_detail_view.xml | 6 ++---- .../android/app/src/main/res/values-de/strings.xml | 2 +- .../android/app/src/main/res/values-pl/strings.xml | 2 +- .../android/app/src/main/res/values-ru/strings.xml | 2 +- .../android/app/src/main/res/values-ua/strings.xml | 2 +- .../android/app/src/main/res/values-zh-rCN/strings.xml | 2 ++ .../android/app/src/main/res/values-zh-rTW/strings.xml | 2 +- src/frontends/android/app/src/main/res/values/strings.xml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java index 53773e6768..5ba594363c 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -140,7 +140,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity private EditText mEspProposal; private TextView mProfileIdLabel; private TextView mProfileId; - private MultiAutoCompleteTextView mDnsServers; + private EditText mDnsServers; private TextInputLayoutHelper mDnsServersWrap; @Override @@ -180,8 +180,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity mRemoteId = (MultiAutoCompleteTextView)findViewById(R.id.remote_id); mRemoteIdWrap = (TextInputLayoutHelper) findViewById(R.id.remote_id_wrap); - mDnsServers = (MultiAutoCompleteTextView)findViewById(R.id.dns_servers); - mDnsServersWrap = (TextInputLayoutHelper) findViewById(R.id.dns_servers_wrap); + mDnsServers = findViewById(R.id.dns_servers); + mDnsServersWrap = findViewById(R.id.dns_servers_wrap); mMTU = (EditText)findViewById(R.id.mtu); mMTUWrap = (TextInputLayoutHelper) findViewById(R.id.mtu_wrap); mPort = (EditText)findViewById(R.id.port); diff --git a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml index 0bdbc1d687..0adbe6efdb 100644 --- a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml +++ b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml @@ -216,17 +216,15 @@ android:id="@+id/dns_servers_wrap" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="10dp" android:hint="@string/profile_dns_servers_label" app:helper_text="@string/profile_dns_servers_hint" > - + android:inputType="textNoSuggestions" /> diff --git a/src/frontends/android/app/src/main/res/values-de/strings.xml b/src/frontends/android/app/src/main/res/values-de/strings.xml index f7fc36dc89..77542aa182 100644 --- a/src/frontends/android/app/src/main/res/values-de/strings.xml +++ b/src/frontends/android/app/src/main/res/values-de/strings.xml @@ -86,7 +86,7 @@ Standardwert ist der konfigurierte Server. Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen Standardwert ist \"%1$s\". Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen DNS Server - Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\", standardmässig werden die vom VPN Server erhaltenen Server verwendet) + Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\"), standardmässig werden die vom VPN Server erhaltenen Server verwendet MTU des VPN Tunnel-Device Falls der Standardwert in einem bestimmten Netzwerk nicht geeignet ist Server Port diff --git a/src/frontends/android/app/src/main/res/values-pl/strings.xml b/src/frontends/android/app/src/main/res/values-pl/strings.xml index b202b6706e..90523be5a3 100644 --- a/src/frontends/android/app/src/main/res/values-pl/strings.xml +++ b/src/frontends/android/app/src/main/res/values-pl/strings.xml @@ -86,7 +86,7 @@ Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication DNS servers - Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server) + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device In case the default value is unsuitable for a particular network Server port diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml index 1f81587dc8..c6a38de9d6 100644 --- a/src/frontends/android/app/src/main/res/values-ru/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml @@ -83,7 +83,7 @@ Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication DNS servers - Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server) + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device In case the default value is unsuitable for a particular network Server port diff --git a/src/frontends/android/app/src/main/res/values-ua/strings.xml b/src/frontends/android/app/src/main/res/values-ua/strings.xml index 95fdd428af..b133525f65 100644 --- a/src/frontends/android/app/src/main/res/values-ua/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ua/strings.xml @@ -84,7 +84,7 @@ Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication DNS servers - Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server) + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device In case the default value is unsuitable for a particular network Server port diff --git a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml index 006ad53590..3594391511 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml @@ -82,6 +82,8 @@ 服务器ID 默认为已配置的服务器地址。自义定值将在鉴权期间被显式地发送至服务器 默认为 \"%1$s\"。自义定值将在鉴权期间被显式地发送至服务器 + DNS servers + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server VPN隧道设备的MTU值 假如在某一网络下默认值不合适 服务器端口 diff --git a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml index 12666ca55d..2330283c09 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml @@ -83,7 +83,7 @@ 預設為已設定的伺服器位置。自訂值會在授權期間送到伺服器 預設為 \"%1$s\"。自訂值會在授權期間送到伺服器 DNS servers - Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server) + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server VPN通道裝置的MTU值 如果在某個網路下預設值不適合 伺服器Port diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml index e86e84b5a6..243231609d 100644 --- a/src/frontends/android/app/src/main/res/values/strings.xml +++ b/src/frontends/android/app/src/main/res/values/strings.xml @@ -86,7 +86,7 @@ Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication DNS servers - Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\", defaults to those received from the VPN server) + Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device In case the default value is unsuitable for a particular network Server port From df0214baa6d18ff68fec74a7873288ce47e99bae Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 14:51:31 +0200 Subject: [PATCH 06/12] android: Rename adapter for gateway address auto-completion --- .../android/ui/VpnProfileDetailActivity.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java index 5ba594363c..94bb21c383 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -216,9 +216,9 @@ public class VpnProfileDetailActivity extends AppCompatActivity final SpaceTokenizer spaceTokenizer = new SpaceTokenizer(); mName.setTokenizer(spaceTokenizer); mRemoteId.setTokenizer(spaceTokenizer); - final ArrayAdapter completeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line); - mName.setAdapter(completeAdapter); - mRemoteId.setAdapter(completeAdapter); + final ArrayAdapter gatewayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line); + mName.setAdapter(gatewayAdapter); + mRemoteId.setAdapter(gatewayAdapter); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { @@ -237,8 +237,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity @Override public void afterTextChanged(Editable s) { - completeAdapter.clear(); - completeAdapter.add(mGateway.getText().toString()); + gatewayAdapter.clear(); + gatewayAdapter.add(mGateway.getText().toString()); if (TextUtils.isEmpty(mGateway.getText())) { mNameWrap.setHelperText(getString(R.string.profile_name_hint)); From 698a18e7a5a7b1ec3fdf7e9bd746ff3ab7e8c461 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 15:02:30 +0200 Subject: [PATCH 07/12] android: Allow configuration of client identity for all authentication types This replaces the drop-down box to select certificate identities with a text field (in the advanced settings) with auto-completion for SANs contained in the certificate. The field is always shown and allows using an IKE identity different from the username for EAP authentication (e.g. to configure a more complete identity to select a specific config on the server). Fixes #3134. --- .../android/ui/VpnProfileDetailActivity.java | 42 +++++-------------- .../adapter/CertificateIdentitiesAdapter.java | 17 +------- .../android/ui/adapter/VpnProfileAdapter.java | 18 ++++---- .../main/res/layout/profile_detail_view.xml | 32 +++++++------- .../app/src/main/res/values-de/strings.xml | 6 +-- .../app/src/main/res/values-pl/strings.xml | 6 +-- .../app/src/main/res/values-ru/strings.xml | 6 +-- .../app/src/main/res/values-ua/strings.xml | 6 +-- .../src/main/res/values-zh-rCN/strings.xml | 6 +-- .../src/main/res/values-zh-rTW/strings.xml | 6 +-- .../app/src/main/res/values/strings.xml | 6 +-- 11 files changed, 61 insertions(+), 90 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java index 94bb21c383..eaed550111 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -90,7 +90,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity private TrustedCertificateEntry mCertEntry; private String mUserCertLoading; private CertificateIdentitiesAdapter mSelectUserIdAdapter; - private String mSelectedUserId; private TrustedCertificateEntry mUserCertEntry; private VpnType mVpnType = VpnType.IKEV2_EAP; private SelectedAppsHandling mSelectedAppsHandling = SelectedAppsHandling.SELECTED_APPS_DISABLE; @@ -107,7 +106,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity private EditText mPassword; private ViewGroup mUserCertificate; private RelativeLayout mSelectUserCert; - private Spinner mSelectUserId; private CheckBox mCheckAuto; private RelativeLayout mSelectCert; private RelativeLayout mTncNotice; @@ -115,6 +113,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity private ViewGroup mAdvancedSettings; private MultiAutoCompleteTextView mRemoteId; private TextInputLayoutHelper mRemoteIdWrap; + private MultiAutoCompleteTextView mLocalId; + private TextInputLayoutHelper mLocalIdWrap; private EditText mMTU; private TextInputLayoutHelper mMTUWrap; private EditText mPort; @@ -170,7 +170,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity mUserCertificate = (ViewGroup)findViewById(R.id.user_certificate_group); mSelectUserCert = (RelativeLayout)findViewById(R.id.select_user_certificate); - mSelectUserId = (Spinner)findViewById(R.id.select_user_id); mCheckAuto = (CheckBox)findViewById(R.id.ca_auto); mSelectCert = (RelativeLayout)findViewById(R.id.select_certificate); @@ -180,6 +179,8 @@ public class VpnProfileDetailActivity extends AppCompatActivity mRemoteId = (MultiAutoCompleteTextView)findViewById(R.id.remote_id); mRemoteIdWrap = (TextInputLayoutHelper) findViewById(R.id.remote_id_wrap); + mLocalId = findViewById(R.id.local_id); + mLocalIdWrap = findViewById(R.id.local_id_wrap); mDnsServers = findViewById(R.id.dns_servers); mDnsServersWrap = findViewById(R.id.dns_servers_wrap); mMTU = (EditText)findViewById(R.id.mtu); @@ -216,6 +217,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity final SpaceTokenizer spaceTokenizer = new SpaceTokenizer(); mName.setTokenizer(spaceTokenizer); mRemoteId.setTokenizer(spaceTokenizer); + mLocalId.setTokenizer(spaceTokenizer); final ArrayAdapter gatewayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line); mName.setAdapter(gatewayAdapter); mRemoteId.setAdapter(gatewayAdapter); @@ -280,23 +282,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity mSelectUserCert.setOnClickListener(new SelectUserCertOnClickListener()); mSelectUserIdAdapter = new CertificateIdentitiesAdapter(this); - mSelectUserId.setAdapter(mSelectUserIdAdapter); - mSelectUserId.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) - { - if (mUserCertEntry != null) - { /* we don't store the subject DN as it is in the reverse order and the default anyway */ - mSelectedUserId = position == 0 ? null : mSelectUserIdAdapter.getItem(position); - } - } - - @Override - public void onNothingSelected(AdapterView parent) - { - mSelectedUserId = null; - } - }); + mLocalId.setAdapter(mSelectUserIdAdapter); mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override @@ -384,10 +370,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity { outState.putString(VpnProfileDataSource.KEY_USER_CERTIFICATE, mUserCertEntry.getAlias()); } - if (mSelectedUserId != null) - { - outState.putString(VpnProfileDataSource.KEY_LOCAL_ID, mSelectedUserId); - } if (mCertEntry != null) { outState.putString(VpnProfileDataSource.KEY_CERTIFICATE, mCertEntry.getAlias()); @@ -455,10 +437,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity mUsernamePassword.setVisibility(mVpnType.has(VpnTypeFeature.USER_PASS) ? View.VISIBLE : View.GONE); mUserCertificate.setVisibility(mVpnType.has(VpnTypeFeature.CERTIFICATE) ? View.VISIBLE : View.GONE); mTncNotice.setVisibility(mVpnType.has(VpnTypeFeature.BYOD) ? View.VISIBLE : View.GONE); + mLocalIdWrap.setHelperText(getString(R.string.profile_local_id_hint_user)); if (mVpnType.has(VpnTypeFeature.CERTIFICATE)) { - mSelectUserId.setEnabled(false); if (mUserCertLoading != null) { ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertLoading); @@ -470,8 +452,6 @@ public class VpnProfileDetailActivity extends AppCompatActivity ((TextView)mSelectUserCert.findViewById(android.R.id.text1)).setText(mUserCertEntry.getAlias()); ((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(mUserCertEntry.getCertificate().getSubjectDN().toString()); mSelectUserIdAdapter.setCertificate(mUserCertEntry); - mSelectUserId.setSelection(mSelectUserIdAdapter.getPosition(mSelectedUserId)); - mSelectUserId.setEnabled(true); } else { @@ -479,6 +459,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity ((TextView)mSelectUserCert.findViewById(android.R.id.text2)).setText(R.string.profile_user_select_certificate); mSelectUserIdAdapter.setCertificate(null); } + mLocalIdWrap.setHelperText(getString(R.string.profile_local_id_hint_cert)); } } @@ -580,7 +561,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity mProfile.getIncludedSubnets() != null || mProfile.getExcludedSubnets() != null || mProfile.getSelectedAppsHandling() != SelectedAppsHandling.SELECTED_APPS_DISABLE || mProfile.getIkeProposal() != null || mProfile.getEspProposal() != null || - mProfile.getDnsServers() != null; + mProfile.getDnsServers() != null || mProfile.getLocalId() != null; } mShowAdvanced.setVisibility(!show ? View.VISIBLE : View.GONE); mAdvancedSettings.setVisibility(show ? View.VISIBLE : View.GONE); @@ -717,11 +698,11 @@ public class VpnProfileDetailActivity extends AppCompatActivity if (mVpnType.has(VpnTypeFeature.CERTIFICATE)) { mProfile.setUserCertificateAlias(mUserCertEntry.getAlias()); - mProfile.setLocalId(mSelectedUserId); } String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias(); mProfile.setCertificateAlias(certAlias); mProfile.setRemoteId(getString(mRemoteId)); + mProfile.setLocalId(getString(mLocalId)); mProfile.setMTU(getInteger(mMTU)); mProfile.setPort(getInteger(mPort)); mProfile.setNATKeepAlive(getInteger(mNATKeepalive)); @@ -767,6 +748,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity mUsername.setText(mProfile.getUsername()); mPassword.setText(mProfile.getPassword()); mRemoteId.setText(mProfile.getRemoteId()); + mLocalId.setText(mProfile.getLocalId()); mMTU.setText(mProfile.getMTU() != null ? mProfile.getMTU().toString() : null); mPort.setText(mProfile.getPort() != null ? mProfile.getPort().toString() : null); mNATKeepalive.setText(mProfile.getNATKeepAlive() != null ? mProfile.getNATKeepAlive().toString() : null); @@ -803,12 +785,10 @@ public class VpnProfileDetailActivity extends AppCompatActivity /* check if the user selected a user certificate previously */ useralias = savedInstanceState == null ? useralias : savedInstanceState.getString(VpnProfileDataSource.KEY_USER_CERTIFICATE); - local_id = savedInstanceState == null ? local_id : savedInstanceState.getString(VpnProfileDataSource.KEY_LOCAL_ID); if (useralias != null) { UserCertificateLoader loader = new UserCertificateLoader(this, useralias); mUserCertLoading = useralias; - mSelectedUserId = local_id; loader.execute(); } diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/CertificateIdentitiesAdapter.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/CertificateIdentitiesAdapter.java index c8e3df38b4..912f524413 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/CertificateIdentitiesAdapter.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/CertificateIdentitiesAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Tobias Brunner + * Copyright (C) 2016-2019 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -16,17 +16,10 @@ package org.strongswan.android.ui.adapter; import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.TextView; -import org.strongswan.android.R; import org.strongswan.android.security.TrustedCertificateEntry; -import java.util.List; - public class CertificateIdentitiesAdapter extends ArrayAdapter { TrustedCertificateEntry mCertificate; @@ -51,14 +44,8 @@ public class CertificateIdentitiesAdapter extends ArrayAdapter private void extractIdentities() { - if (mCertificate == null) + if (mCertificate != null) { - add(getContext().getString(R.string.profile_user_select_id_init)); - } - else - { - add(String.format(getContext().getString(R.string.profile_user_select_id_default), - mCertificate.getCertificate().getSubjectDN().getName())); addAll(mCertificate.getSubjectAltNames()); } } diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java index f1ff1c6f81..d9201747a3 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java @@ -17,14 +17,6 @@ package org.strongswan.android.ui.adapter; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.strongswan.android.R; -import org.strongswan.android.data.VpnProfile; -import org.strongswan.android.data.VpnType.VpnTypeFeature; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; @@ -32,6 +24,14 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; +import org.strongswan.android.R; +import org.strongswan.android.data.VpnProfile; +import org.strongswan.android.data.VpnType.VpnTypeFeature; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + public class VpnProfileAdapter extends ArrayAdapter { private final int resource; @@ -74,7 +74,7 @@ public class VpnProfileAdapter extends ArrayAdapter profile.getLocalId() != null) { tv.setVisibility(View.VISIBLE); - tv.setText(getContext().getString(R.string.profile_user_select_id_label) + ": " + profile.getLocalId()); + tv.setText(getContext().getString(R.string.profile_local_id_label) + ": " + profile.getLocalId()); } else { diff --git a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml index 0adbe6efdb..acab0b2f1b 100644 --- a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml +++ b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml @@ -73,6 +73,7 @@ android:id="@+id/username_wrap" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginTop="4dp" android:hint="@string/profile_username_label" > - - - - + + + + + + Benutzer-Zertifikat Benutzer-Zertifikat auswählen Wählen Sie ein bestimmtes Benutzer-Zertifikat - Benutzer-Identität - Wählen Sie zuerst ein Benutzer-Zertifikat - Standardwert (%1$s) CA-Zertifikat Automatisch wählen CA-Zertifikat auswählen @@ -85,6 +82,9 @@ Server-Identität Standardwert ist der konfigurierte Server. Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen Standardwert ist \"%1$s\". Eigene Werte werden explizit an den Server gesendet und während der Authentifizierung erzwungen + Client-Identität + Standardwert ist der konfigurierte Benutzername. Eigene Werte können verwendet werden, falls der Server diese erwartet/benötigt + Standardwert ist die Inhaber-Identität des Zertifkats. Eigene Werte können verwendet werden, falls der Server diese erwartet/benötigt. Zu beachten ist, dass diese üblicherweise vom Zertifikat bestätigt werden müssen (für die alternativen Identitäten des Zertifikats, falls vorhanden, wird eine Auto-Vervollständigung angeboten) DNS Server Benutzerdefinierte DNS Server bei Verbindung zum VPN (mit Leerzeichen getrennt, z.B.. \"8.8.8.8 2001:4860:4860::8888\"), standardmässig werden die vom VPN Server erhaltenen Server verwendet MTU des VPN Tunnel-Device diff --git a/src/frontends/android/app/src/main/res/values-pl/strings.xml b/src/frontends/android/app/src/main/res/values-pl/strings.xml index 90523be5a3..6f4716ba84 100644 --- a/src/frontends/android/app/src/main/res/values-pl/strings.xml +++ b/src/frontends/android/app/src/main/res/values-pl/strings.xml @@ -73,9 +73,6 @@ Certyfikat użytkownika Wybierz certyfikat użytkownika >Wybierz określony certyfikat użytkownika - User identity - Select a certificate first - Default (%1$s) Certyfikat CA Wybierz automatycznie Wybierz certyfikat CA @@ -85,6 +82,9 @@ Server identity Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml index c6a38de9d6..5def66df8b 100644 --- a/src/frontends/android/app/src/main/res/values-ru/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml @@ -70,9 +70,6 @@ Сертификат пользователя Выбрать сертификат пользователя Выбрать сертификат пользователя - User identity - Select a certificate first - Default (%1$s) Сертификат CA Выбрать автоматически Выбрать сертификат CA @@ -82,6 +79,9 @@ Server identity Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device diff --git a/src/frontends/android/app/src/main/res/values-ua/strings.xml b/src/frontends/android/app/src/main/res/values-ua/strings.xml index b133525f65..4920aa2385 100644 --- a/src/frontends/android/app/src/main/res/values-ua/strings.xml +++ b/src/frontends/android/app/src/main/res/values-ua/strings.xml @@ -71,9 +71,6 @@ Сертифікат користувача Виберіть сертифікат користувача Вибрати спеціальний сертифікат користувача - User identity - Select a certificate first - Default (%1$s) Сертифікат CA Вибрати автоматично Вибрати сертифікат CA @@ -83,6 +80,9 @@ Server identity Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device diff --git a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml index 3594391511..3408f5f55f 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml @@ -70,9 +70,6 @@ 用户证书 选择用户证书 选择指定的用户证书 - 用户ID - 首先选择一个证书 - 默认(%1$s) CA证书 自动选择 选择CA证书 @@ -82,6 +79,9 @@ 服务器ID 默认为已配置的服务器地址。自义定值将在鉴权期间被显式地发送至服务器 默认为 \"%1$s\"。自义定值将在鉴权期间被显式地发送至服务器 + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server VPN隧道设备的MTU值 diff --git a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml index 2330283c09..e3d7f03616 100644 --- a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml @@ -70,9 +70,6 @@ 用戶憑證 選擇用戶憑證 選擇指定的用戶憑證 - 用戶帳號 - 請先選擇一個憑證 - 預設(%1$s) CA憑證 自動選擇 選擇CA憑證 @@ -82,6 +79,9 @@ 伺服器ID 預設為已設定的伺服器位置。自訂值會在授權期間送到伺服器 預設為 \"%1$s\"。自訂值會在授權期間送到伺服器 + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server VPN通道裝置的MTU值 diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml index 243231609d..4d9fd879f2 100644 --- a/src/frontends/android/app/src/main/res/values/strings.xml +++ b/src/frontends/android/app/src/main/res/values/strings.xml @@ -73,9 +73,6 @@ User certificate Select user certificate Select a specific user certificate - User identity - Select a certificate first - Default (%1$s) CA certificate Select automatically Select CA certificate @@ -85,6 +82,9 @@ Server identity Defaults to the configured server. Custom values are explicitly sent to the server and enforced during authentication Defaults to \"%1$s\". Custom values are explicitly sent to the server and enforced during authentication + Client identity + Defaults to the configured username. Custom values may be used if expected/required by the server + Defaults to the certificate\'s subject identity. Custom values may be used if expected/required by the server. Note that these usually must be confirmed by the certificate (auto-completion is provided for the certificate\'s alternative identities, if any) DNS servers Custom DNS servers to use when connected to the VPN (separated by spaces, e.g. \"8.8.8.8 2001:4860:4860::8888\"), defaults to those received from the VPN server MTU of the VPN tunnel device From a82673346e3a29b530bd1a3edffe322a62cb34a1 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 15:13:55 +0200 Subject: [PATCH 08/12] android: Import local identity for all authentication types --- .../org/strongswan/android/ui/VpnProfileImportActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java index eae7683782..14fa70014f 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java @@ -505,6 +505,8 @@ public class VpnProfileImportActivity extends AppCompatActivity JSONObject local = obj.optJSONObject("local"); if (local != null) { + profile.setLocalId(local.optString("id", null)); + if (type.has(VpnTypeFeature.USER_PASS)) { profile.setUsername(local.optString("eap_id", null)); @@ -512,7 +514,6 @@ public class VpnProfileImportActivity extends AppCompatActivity if (type.has(VpnTypeFeature.CERTIFICATE)) { - profile.setLocalId(local.optString("id", null)); profile.PKCS12 = decodeBase64(local.optString("p12", null)); if (local.optBoolean("rsa-pss", false)) From 1227b43fe4335b185a2c870ddda9da5c3d7cbf76 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 15:51:18 +0200 Subject: [PATCH 09/12] android: Don't use specific key types to select user certificates Android 10 will honor the preselection and could, thus, hide some installed certificates if we only pass "RSA". The dialog will also only be shown if there are actually certificates installed (i.e. users will have to do that manually outside of the app or via profile import). Fixes #3196. --- .../org/strongswan/android/ui/VpnProfileDetailActivity.java | 2 +- .../org/strongswan/android/ui/VpnProfileImportActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java index eaed550111..fac9b34ea8 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java @@ -925,7 +925,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity public void onClick(View v) { String useralias = mUserCertEntry != null ? mUserCertEntry.getAlias() : null; - KeyChain.choosePrivateKeyAlias(VpnProfileDetailActivity.this, this, new String[] { "RSA" }, null, null, -1, useralias); + KeyChain.choosePrivateKeyAlias(VpnProfileDetailActivity.this, this, null, null, null, -1, useralias); } @Override diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java index 14fa70014f..33b396629f 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java @@ -889,7 +889,7 @@ public class VpnProfileImportActivity extends AppCompatActivity { alias = getString(R.string.profile_cert_alias, mProfile.getName()); } - KeyChain.choosePrivateKeyAlias(VpnProfileImportActivity.this, this, new String[] { "RSA" }, null, null, -1, alias); + KeyChain.choosePrivateKeyAlias(VpnProfileImportActivity.this, this, null, null, null, -1, alias); } @Override From 71d143149c926946d33e3ab15397c12697bd188d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 14 Oct 2019 15:03:10 +0200 Subject: [PATCH 10/12] android: Replace deprecated CONNECTIVITY_ACTION on newer Android versions It was deprecated in API level 28, registerNetworkCallback is available since API level 21, but ConnectivityManager got some updates with 24 (e.g. default network handling) so we start using it then. --- .../android/logic/NetworkManager.java | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java index abe6293224..e283cd56d7 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Tobias Brunner + * Copyright (C) 2012-2019 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +20,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.net.Network; import android.net.NetworkInfo; +import android.net.NetworkRequest; +import android.os.Build; import java.util.LinkedList; @@ -28,12 +31,45 @@ public class NetworkManager extends BroadcastReceiver implements Runnable { private final Context mContext; private volatile boolean mRegistered; + private ConnectivityManager.NetworkCallback mCallback; private Thread mEventNotifier; + private int mConnectedNetworks = 0; private LinkedList mEvents = new LinkedList<>(); public NetworkManager(Context context) { mContext = context; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + mCallback = new ConnectivityManager.NetworkCallback() + { + @Override + public void onAvailable(Network network) + { + synchronized (NetworkManager.this) + { + /* we expect this to be called if connected to at least one network during + * callback registration */ + mConnectedNetworks += 1; + mEvents.addLast(true); + NetworkManager.this.notifyAll(); + } + } + + @Override + public void onLost(Network network) + { + synchronized (NetworkManager.this) + { + /* in particular mobile connections are disconnected overlapping with WiFi */ + mConnectedNetworks -= 1; + mEvents.addLast(mConnectedNetworks > 0); + NetworkManager.this.notifyAll(); + } + } + }; + } } public void Register() @@ -42,12 +78,38 @@ public class NetworkManager extends BroadcastReceiver implements Runnable mRegistered = true; mEventNotifier = new Thread(this); mEventNotifier.start(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + /* while we only get events for the VPN network via registerDefaultNetworkCallback, + * the default capabilities in the builder include NetworkCapabilities.NET_CAPABILITY_NOT_VPN */ + NetworkRequest.Builder builder = new NetworkRequest.Builder(); + cm.registerNetworkCallback(builder.build(), mCallback); + } + else + { + registerLegacyReceiver(); + } + } + + @SuppressWarnings("deprecation") + private void registerLegacyReceiver() + { + /* deprecated since API level 28 */ mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); } public void Unregister() { - mContext.unregisterReceiver(this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.unregisterNetworkCallback(mCallback); + } + else + { + mContext.unregisterReceiver(this); + } mRegistered = false; synchronized (this) { From 60457e2aef415e27a05f7f86f0ad7b1c1d06c2d9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 14 Oct 2019 17:24:15 +0200 Subject: [PATCH 11/12] ike-delete: Continue break-before-make reauth if server concurrently deletes SA There seem to be servers around that, upon receiving a delete from the client, instead of responding with an empty INFORMATIONAL, send a delete themselves. --- src/libcharon/sa/ikev2/tasks/ike_delete.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libcharon/sa/ikev2/tasks/ike_delete.c b/src/libcharon/sa/ikev2/tasks/ike_delete.c index fd36b144a2..49cd663708 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_delete.c +++ b/src/libcharon/sa/ikev2/tasks/ike_delete.c @@ -168,6 +168,33 @@ METHOD(task_t, process_r, status_t, return NEED_MORE; } +/** + * Check if we are currently deleting this IKE_SA in a break-before-make reauth. + */ +static bool is_reauthenticating(private_ike_delete_t *this) +{ + enumerator_t *tasks; + task_t *task; + + if (!this->ike_sa->has_condition(this->ike_sa, COND_REAUTHENTICATING)) + { + return FALSE; + } + + tasks = this->ike_sa->create_task_enumerator(this->ike_sa, + TASK_QUEUE_ACTIVE); + while (tasks->enumerate(tasks, &task)) + { + if (task->get_type(task) == TASK_IKE_REAUTH) + { + tasks->destroy(tasks); + return TRUE; + } + } + tasks->destroy(tasks); + return FALSE; +} + METHOD(task_t, build_r, status_t, private_ike_delete_t *this, message_t *message) { @@ -177,6 +204,18 @@ METHOD(task_t, build_r, status_t, { /* invoke ike_down() hook if SA has not been rekeyed */ charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); } + + /* if we are currently deleting this IKE_SA due to a break-before-make + * reauthentication, make sure to not just silently destroy the SA if + * the peer concurrently deletes it */ + if (is_reauthenticating(this)) + { + if (this->ike_sa->reestablish(this->ike_sa) != SUCCESS) + { + DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); + } + } + /* completed, delete IKE_SA by returning DESTROY_ME */ return DESTROY_ME; } From 6e12aa68b3fe81702f15d7e3e525207cc80ec539 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 8 Oct 2019 15:34:00 +0200 Subject: [PATCH 12/12] android: New release after making local identity configurable This also includes a fix for Android 10 and some older fixes for API level 28 compatibility and a crash on Huawei devices. The API used to detect network changes is also replaced on newer Android versions and an issue with DELETES received during break-before-make reauthentication is also fixed. --- src/frontends/android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontends/android/app/build.gradle b/src/frontends/android/app/build.gradle index c9ec5bd3da..b3a17f373b 100644 --- a/src/frontends/android/app/build.gradle +++ b/src/frontends/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "org.strongswan.android" minSdkVersion 15 targetSdkVersion 28 - versionCode 64 - versionName "2.1.1" + versionCode 68 + versionName "2.2.0" } sourceSets.main {