summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2021-10-08 02:22:07 +0200
committerArne Schwabe <arne@rfc2549.org>2021-10-08 02:22:07 +0200
commit9ca2ff6f0688ae6c987f0fa6fe50f1b2fc2425d7 (patch)
treea7195b5a82f7d829c5671fb379046a774d882c86
parent34be3fa975cc7693e8f0203e7dbe5a60df8525a2 (diff)
Add red warnings if a profile uses deprecated/insecure options
-rw-r--r--main/src/testui/java/de/blinkt/openvpn/core/TestUiUtils.kt13
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt56
-rw-r--r--main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java36
3 files changed, 93 insertions, 12 deletions
diff --git a/main/src/testui/java/de/blinkt/openvpn/core/TestUiUtils.kt b/main/src/testui/java/de/blinkt/openvpn/core/TestUiUtils.kt
index 8bc2e4fa..040606cf 100644
--- a/main/src/testui/java/de/blinkt/openvpn/core/TestUiUtils.kt
+++ b/main/src/testui/java/de/blinkt/openvpn/core/TestUiUtils.kt
@@ -1,3 +1,4 @@
+import de.blinkt.openvpn.VpnProfile
import de.blinkt.openvpn.fragments.Utils
import org.junit.Assert
import org.junit.Test
@@ -9,4 +10,16 @@ class TestUiUtils {
Assert.assertEquals(0, Utils.mapCompatVer(20707))
Assert.assertEquals(3, Utils.mapCompatVer(11723))
}
+
+ @Test
+ fun testWarnings() {
+ val vp = VpnProfile("unittest")
+ vp.mUseCustomConfig = true;
+ vp.mCustomConfigOptions = "\ntls-cipher DEFAULT:@SECLEVEL=0\n"
+
+ val warnings = mutableListOf<String>()
+ Utils.addSoftWarnings(warnings, vp)
+ Assert.assertTrue(warnings.size >= 1)
+
+ }
} \ No newline at end of file
diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt b/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt
index 64a8d3ba..f4cc446f 100644
--- a/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt
+++ b/main/src/ui/java/de/blinkt/openvpn/fragments/Utils.kt
@@ -8,10 +8,16 @@ import android.annotation.TargetApi
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.graphics.Color
import android.os.Build
import android.provider.OpenableColumns
+import android.text.SpannableString
+import android.text.SpannableStringBuilder
+import android.text.TextUtils
+import android.text.style.ForegroundColorSpan
import android.util.Base64
import android.webkit.MimeTypeMap
+import de.blinkt.openvpn.R
import kotlin.Throws
import de.blinkt.openvpn.VpnProfile
import de.blinkt.openvpn.core.Preferences
@@ -258,4 +264,54 @@ object Utils {
else -> return 0
}
}
+
+ val seclevleregex = Regex("tls-cipher.*@SECLEVEL=0")
+
+ @JvmStatic
+ fun getWarningText(c:Context, vp:VpnProfile): SpannableStringBuilder {
+ val warnings = mutableListOf<String>()
+
+ val errorId = vp.checkProfile(c)
+ if (errorId != R.string.no_error_found)
+ {
+ warnings.add(c.resources.getString(errorId))
+ }
+
+ addSoftWarnings(warnings, vp)
+ val builder = SpannableStringBuilder()
+ if (warnings.size > 0) {
+ val warnSpan = SpannableString( warnings.joinToString(separator = ", "))
+ warnSpan.setSpan(ForegroundColorSpan(Color.RED), 0, warnSpan.length, 0)
+ builder.append(warnSpan)
+ }
+
+ return builder
+ }
+
+ val weakCiphers = listOf<String>("BF-CBC", "DES-CBC", "NONE")
+
+ @JvmStatic
+ fun addSoftWarnings(warnings:MutableList<String>, vp:VpnProfile) {
+ if (vp.mUseLegacyProvider)
+ warnings.add("legacy Provider enabled")
+ if (vp.mAuthenticationType == VpnProfile.TYPE_STATICKEYS)
+ warnings.add("deprecated static key (--secret) mode")
+ if (vp.mUseCustomConfig && vp.mCustomConfigOptions.contains(seclevleregex))
+ warnings.add("low security (@SECLEVEL=0)")
+ if (vp.mCompatMode > 0 )
+ warnings.add("compat mode enabled")
+
+ var cipher= vp.mCipher.toUpperCase(Locale.ROOT)
+ if (TextUtils.isEmpty(cipher))
+ cipher = "BF-CBC";
+
+ for (weakCipher in weakCiphers) {
+ if ((vp.mDataCiphers != null && vp.mDataCiphers.toUpperCase(Locale.ROOT)
+ .contains(weakCipher))
+ || (vp.mCompatMode in 1..20399 && (cipher == weakCipher))
+ )
+ warnings.add("weak cipher (${weakCipher})")
+ }
+ }
+
} \ No newline at end of file
diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
index ce6fa7f1..cf48cc48 100644
--- a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
+++ b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java
@@ -20,11 +20,14 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
+import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.ListFragment;
import android.text.Html;
import android.text.Html.ImageGetter;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -81,6 +84,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
private String mLastStatusMessage;
private ArrayAdapter<VpnProfile> mArrayadapter;
private Intent mLastIntent;
+ private VpnProfile defaultVPN;
@Override
public void updateState(String state, String logmessage, final int localizedResId, ConnectionStatus level, Intent intent) {
@@ -246,6 +250,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
updateDynamicShortcuts();
}
VpnStatus.addStateListener(this);
+ defaultVPN = ProfileManager.getAlwaysOnVPN(requireContext());
}
@Override
@@ -286,7 +291,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
}
private void populateVpnList() {
- boolean sortByLRU = Preferences.getDefaultSharedPreferences(getActivity()).getBoolean(PREF_SORT_BY_LRU, false);
+ boolean sortByLRU = Preferences.getDefaultSharedPreferences(requireActivity()).getBoolean(PREF_SORT_BY_LRU, false);
Collection<VpnProfile> allvpn = getPM().getProfiles();
TreeSet<VpnProfile> sortedset;
if (sortByLRU)
@@ -303,7 +308,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(Menu menu, @NonNull MenuInflater inflater) {
menu.add(0, MENU_ADD_PROFILE, 0, R.string.menu_add_profile)
.setIcon(R.drawable.ic_menu_add)
.setAlphabeticShortcut('a')
@@ -589,30 +594,37 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn
super(context, resource, textViewResourceId);
}
+ @NonNull
@Override
- public View getView(final int position, View convertView, ViewGroup parent) {
+ public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
View v = super.getView(position, convertView, parent);
final VpnProfile profile = (VpnProfile) getListAdapter().getItem(position);
View titleview = v.findViewById(R.id.vpn_list_item_left);
- titleview.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- startOrStopVPN(profile);
- }
- });
+ titleview.setOnClickListener(v1 -> startOrStopVPN(profile));
View settingsview = v.findViewById(R.id.quickedit_settings);
settingsview.setOnClickListener(view -> editVPN(profile));
- TextView subtitle = (TextView) v.findViewById(R.id.vpn_item_subtitle);
+ TextView subtitle = v.findViewById(R.id.vpn_item_subtitle);
+ SpannableStringBuilder warningText = Utils.getWarningText(requireContext(), profile);
+
+ if (profile == defaultVPN) {
+ if (warningText.length() > 0)
+ warningText.append(" ");
+ warningText.append(new SpannableString("Default VPN"));
+ }
+
if (profile.getUUIDString().equals(VpnStatus.getLastConnectedVPNProfile())) {
subtitle.setText(mLastStatusMessage);
subtitle.setVisibility(View.VISIBLE);
} else {
- subtitle.setText("");
- subtitle.setVisibility(View.GONE);
+ subtitle.setText(warningText);
+ if (warningText.length() > 0)
+ subtitle.setVisibility(View.VISIBLE);
+ else
+ subtitle.setVisibility(View.GONE);
}