diff options
author | Arne Schwabe <arne@rfc2549.org> | 2021-10-16 04:22:31 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2021-10-16 04:22:31 +0200 |
commit | 9296124d0b89b4bb8534216c935ecb05f0cd620b (patch) | |
tree | 99ee912f415c7c1ea9812a68b95df79be1208ff5 | |
parent | e0b23dfaedf15d2ab7753189c02c3cb29748a644 (diff) |
Add TLS Profile to config converter and remove AsyncTask
-rw-r--r-- | main/src/main/res/values/arrays.xml | 2 | ||||
-rw-r--r-- | main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt | 232 | ||||
-rw-r--r-- | main/src/ui/res/layout/config_converter.xml | 165 |
3 files changed, 237 insertions, 162 deletions
diff --git a/main/src/main/res/values/arrays.xml b/main/src/main/res/values/arrays.xml index d5e21f3a..3d6512c1 100644 --- a/main/src/main/res/values/arrays.xml +++ b/main/src/main/res/values/arrays.xml @@ -46,6 +46,6 @@ <item>insecure (not recommend, allows insecure crypto)</item> <item>legacy (default)</item> <item>preferred (recommended but limited compabbility)</item> - <item>Suite B</item> + <item>Suite B (only NIST approved elliptic curves)</item> </string-array> </resources> diff --git a/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt b/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt index 13538aa4..fa786dcb 100644 --- a/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt +++ b/main/src/ui/java/de/blinkt/openvpn/activities/ConfigConverter.kt @@ -14,7 +14,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.database.Cursor import android.net.Uri -import android.os.AsyncTask import android.os.Build import android.os.Bundle import android.os.Environment @@ -28,6 +27,7 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.* +import androidx.lifecycle.lifecycleScope import de.blinkt.openvpn.R import de.blinkt.openvpn.VpnProfile import de.blinkt.openvpn.core.ConfigParser @@ -36,6 +36,9 @@ import de.blinkt.openvpn.core.ProfileManager import de.blinkt.openvpn.fragments.Utils import de.blinkt.openvpn.views.FileSelectLayout import de.blinkt.openvpn.views.FileSelectLayout.FileSelectCallback +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.* import java.net.URLDecoder import java.util.* @@ -57,7 +60,8 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener private lateinit var mProfilename: EditText private lateinit var mCompatmode: Spinner private lateinit var mCompatmodeLabel: TextView - private var mImportTask: AsyncTask<Void, Void, Int>? = null + private lateinit var mTLSProfile: Spinner + private lateinit var mTLSProfileLabel: TextView private lateinit var mLogLayout: LinearLayout private lateinit var mProfilenameLabel: TextView @@ -74,7 +78,11 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), requestCode) } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array<String>, + grantResults: IntArray + ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // Permission declined, do nothing if (grantResults.size == 0 || grantResults[0] == PackageManager.PERMISSION_DENIED) @@ -127,10 +135,15 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener } mResult!!.mCompatMode = Utils.mapCompatMode(mCompatmode.selectedItemPosition) - /* If you need compability with such an old version there is a high chance that - the legacy provider is needed as well - */ - if (mResult!!.mCompatMode in 1..20400) + + val selectedTLSProfile = translSelectionToProfileName(mTLSProfile.selectedItemPosition) + if (selectedTLSProfile != "legacy" || !mResult!!.mTlSCertProfile.isNullOrEmpty()) { + mResult!!.mTlSCertProfile = selectedTLSProfile + } + + /* If you need compability with such an old version or such a low security profile + * there is a high chance that the legacy provider is needed as well */ + if (mResult!!.mCompatMode in 1..20400 || selectedTLSProfile == "insecure") mResult!!.mUseLegacyProvider = true; val intent = installPKCS12() @@ -212,16 +225,18 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener fun showCertDialog() { try { - KeyChain.choosePrivateKeyAlias(this, - { alias -> - // Credential alias selected. Remember the alias selection for future use. - mResult!!.mAlias = alias - saveProfile() - }, - arrayOf("RSA", "EC"), null, // issuer, null for any - mResult!!.mServerName, // host name of server requesting the cert, null if unavailable - -1, // port of server requesting the cert, -1 if unavailable - mAliasName)// List of acceptable key types. null for any + KeyChain.choosePrivateKeyAlias( + this, + { alias -> + // Credential alias selected. Remember the alias selection for future use. + mResult!!.mAlias = alias + saveProfile() + }, + arrayOf("RSA", "EC"), null, // issuer, null for any + mResult!!.mServerName, // host name of server requesting the cert, null if unavailable + -1, // port of server requesting the cert, -1 if unavailable + mAliasName + )// List of acceptable key types. null for any // alias to preselect, null if unavailable } catch (anf: ActivityNotFoundException) { val ab = AlertDialog.Builder(this) @@ -307,7 +322,11 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener return true } - private fun embedFile(filename: String?, type: Utils.FileType, onlyFindFileAndNullonNotFound: Boolean): String? { + private fun embedFile( + filename: String?, + type: Utils.FileType, + onlyFindFileAndNullonNotFound: Boolean + ): String? { if (filename == null) return null @@ -400,10 +419,14 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener val fileDialogInfo = getFileDialogInfo(type!!) - val isCert = type == Utils.FileType.CA_CERTIFICATE || type == Utils.FileType.CLIENT_CERTIFICATE + val isCert = + type == Utils.FileType.CA_CERTIFICATE || type == Utils.FileType.CLIENT_CERTIFICATE val fl = FileSelectLayout(this, getString(fileDialogInfo.first), isCert, false) fileSelectMap[type] = fl - fl.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + fl.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) (findViewById<View>(R.id.config_convert_root) as LinearLayout).addView(fl, 2) findViewById<View>(R.id.files_missing_hint).visibility = View.VISIBLE @@ -549,11 +572,16 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener } - mResult!!.mCaFilename = embedFile(mResult!!.mCaFilename, Utils.FileType.CA_CERTIFICATE, false) - mResult!!.mClientCertFilename = embedFile(mResult!!.mClientCertFilename, Utils.FileType.CLIENT_CERTIFICATE, false) - mResult!!.mClientKeyFilename = embedFile(mResult!!.mClientKeyFilename, Utils.FileType.KEYFILE, false) - mResult!!.mTLSAuthFilename = embedFile(mResult!!.mTLSAuthFilename, Utils.FileType.TLS_AUTH_FILE, false) - mResult!!.mPKCS12Filename = embedFile(mResult!!.mPKCS12Filename, Utils.FileType.PKCS12, false) + mResult!!.mCaFilename = + embedFile(mResult!!.mCaFilename, Utils.FileType.CA_CERTIFICATE, false) + mResult!!.mClientCertFilename = + embedFile(mResult!!.mClientCertFilename, Utils.FileType.CLIENT_CERTIFICATE, false) + mResult!!.mClientKeyFilename = + embedFile(mResult!!.mClientKeyFilename, Utils.FileType.KEYFILE, false) + mResult!!.mTLSAuthFilename = + embedFile(mResult!!.mTLSAuthFilename, Utils.FileType.TLS_AUTH_FILE, false) + mResult!!.mPKCS12Filename = + embedFile(mResult!!.mPKCS12Filename, Utils.FileType.PKCS12, false) mResult!!.mCrlFilename = embedFile(mResult!!.mCrlFilename, Utils.FileType.CRL_FILE, true) if (cp != null) { mEmbeddedPwFile = cp.authUserPassFile @@ -568,6 +596,25 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener } } + private fun translateTLSProfileToSelection(tlsprofile: String?): Int { + return when (tlsprofile) { + "insecure" -> 0 + "legacy" -> 1 + "preferred" -> 2 + "suiteb" -> 3 + else -> 1 + } + } + + private fun translSelectionToProfileName(selection: Int): String { + return when (selection) { + 0 -> "insecure" + 1 -> "legacy" + 2 -> "preferred" + 3 -> "suiteb" + else -> "legacy" + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -588,6 +635,8 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener mCompatmode = findViewById(R.id.compatmode) as Spinner mCompatmodeLabel = findViewById(R.id.compatmode_label) as TextView + mTLSProfile = findViewById(R.id.tls_profile) as Spinner + mTLSProfileLabel = findViewById(R.id.tls_profile_label) as TextView if (savedInstanceState != null && savedInstanceState.containsKey(VPNPROFILE)) { mResult = savedInstanceState.getSerializable(VPNPROFILE) as VpnProfile? @@ -596,6 +645,7 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener mSourceUri = savedInstanceState.getParcelable("mSourceUri") mProfilename.setText(mResult!!.mName) mCompatmode.setSelection(Utils.mapCompatVer(mResult!!.mCompatMode)) + mTLSProfile.setSelection(translateTLSProfileToSelection(mResult?.mTlSCertProfile)) if (savedInstanceState.containsKey("logentries")) { @@ -625,8 +675,11 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener val data = intent.getStringExtra(Intent.EXTRA_TEXT) if (data != null) { - startImportTask(Uri.fromParts("inline", "inlinetext", null), - "imported profiles from AS", data); + lifecycleScope.launch { + startImportTask( + Uri.fromParts("inline", "inlinetext", null), + "imported profiles from AS", data) + } } } else if (intent.action.equals(IMPORT_PROFILE) || intent.action.equals(Intent.ACTION_VIEW)) { val data = intent.data @@ -642,7 +695,10 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener //log(R.string.import_experimental); log(R.string.importing_config, data.toString()) var possibleName: String? = null - if (data.scheme != null && data.scheme == "file" || data.lastPathSegment != null && (data.lastPathSegment!!.endsWith(".ovpn") || data.lastPathSegment!!.endsWith(".conf"))) { + if (data.scheme != null && data.scheme == "file" || data.lastPathSegment != null && (data.lastPathSegment!!.endsWith( + ".ovpn" + ) || data.lastPathSegment!!.endsWith(".conf")) + ) { possibleName = data.lastPathSegment if (possibleName!!.lastIndexOf('/') != -1) possibleName = possibleName.substring(possibleName.lastIndexOf('/') + 1) @@ -651,7 +707,7 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener mPathsegments = data.pathSegments - var cursor:Cursor? = null + var cursor: Cursor? = null try { cursor = contentResolver.query(data, null, null, null, null) @@ -668,8 +724,7 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener log("Mime type: " + cursor.getString(columnIndex)) } } - } - catch (se:SecurityException) { + } catch (se: SecurityException) { log("Importing failed: ${se.localizedMessage}") } finally { cursor?.close() @@ -679,69 +734,72 @@ class ConfigConverter : BaseActivity(), FileSelectCallback, View.OnClickListener possibleName = possibleName.replace(".conf", "") } - startImportTask(data, possibleName, "") - - + lifecycleScope.launch { + startImportTask(data, possibleName, "") + } } - private fun startImportTask(data: Uri, possibleName: String?, inlineData: String) { - mImportTask = object : AsyncTask<Void, Void, Int>() { - private var mProgress: ProgressBar? = null - - override fun onPreExecute() { - mProgress = ProgressBar(this@ConfigConverter) - addViewToLog(mProgress) - } + private suspend fun startImportTask(data: Uri, possibleName: String?, inlineData: String) { + val mProgress: ProgressBar + withContext(Dispatchers.Main) + { + mProgress = ProgressBar(this@ConfigConverter) + addViewToLog(mProgress) + } + var errorCode = 0 + withContext(Dispatchers.IO) + { - override fun doInBackground(vararg params: Void): Int? { - try { - var inputStream: InputStream? - if (data.scheme.equals("inline")) { - inputStream = inlineData.byteInputStream() - } else { - inputStream = contentResolver.openInputStream(data) - } - - if (inputStream != null) { - doImport(inputStream) - } - if (mResult == null) - return -3 - } catch (se: IOException) { - log(R.string.import_content_resolve_error.toString() + ":" + se.localizedMessage) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - checkMarschmallowFileImportError(data) - return -2 - } catch (se: SecurityException) { - log(R.string.import_content_resolve_error.toString() + ":" + se.localizedMessage) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - checkMarschmallowFileImportError(data) - return -2 + try { + val inputStream: InputStream? + if (data.scheme.equals("inline")) { + inputStream = inlineData.byteInputStream() + } else { + inputStream = contentResolver.openInputStream(data) } - return 0 - } - - override fun onPostExecute(errorCode: Int?) { - mLogLayout.removeView(mProgress) - addMissingFileDialogs() - updateFileSelectDialogs() - - if (errorCode == 0) { - displayWarnings() - mResult!!.mName = getUniqueProfileName(possibleName) - mProfilename.visibility = View.VISIBLE - mProfilenameLabel.visibility = View.VISIBLE - mProfilename.setText(mResult!!.name) - - mCompatmode.visibility = View.VISIBLE - mCompatmodeLabel.visibility = View.VISIBLE - mCompatmode.setSelection(Utils.mapCompatVer(mResult!!.mCompatMode)) - - log(R.string.import_done) + if (inputStream != null) { + doImport(inputStream) } + if (mResult == null) + errorCode = -3 + } catch (se: IOException) { + log(R.string.import_content_resolve_error.toString() + ":" + se.localizedMessage) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + checkMarschmallowFileImportError(data) + errorCode = -2 + } catch (se: SecurityException) { + log(R.string.import_content_resolve_error.toString() + ":" + se.localizedMessage) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + checkMarschmallowFileImportError(data) + errorCode = -2 } - }.execute() + } + withContext(Dispatchers.Main) + { + mLogLayout.removeView(mProgress) + addMissingFileDialogs() + updateFileSelectDialogs() + + if (errorCode == 0) { + displayWarnings() + val result = mResult!! + result.mName = getUniqueProfileName(possibleName) + mProfilename.visibility = View.VISIBLE + mProfilenameLabel.visibility = View.VISIBLE + mProfilename.setText(result.name) + + mCompatmode.visibility = View.VISIBLE + mCompatmodeLabel.visibility = View.VISIBLE + mCompatmode.setSelection(Utils.mapCompatVer(result.mCompatMode)) + + mTLSProfile.visibility = View.VISIBLE + mTLSProfileLabel.visibility = View.VISIBLE + mTLSProfile.setSelection(translateTLSProfileToSelection(result.mTlSCertProfile)) + + log(R.string.import_done) + } + } } diff --git a/main/src/ui/res/layout/config_converter.xml b/main/src/ui/res/layout/config_converter.xml index b980dc59..d4e1f820 100644 --- a/main/src/ui/res/layout/config_converter.xml +++ b/main/src/ui/res/layout/config_converter.xml @@ -1,95 +1,112 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (c) 2012-2016 Arne Schwabe ~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> -<ScrollView android:layout_width="match_parent" + <ScrollView + android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/stdpadding" android:orientation="vertical"> - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:id="@+id/config_convert_root" - android:layout_height="wrap_content"> + <LinearLayout + android:id="@+id/config_convert_root" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> - <TextView - android:visibility="gone" - android:id="@+id/profilename_label" - style="@style/item" - android:labelFor="@id/profilename" - android:text="@string/profilename" - android:textAppearance="?android:attr/textAppearanceSmall" - /> + <TextView + android:id="@+id/profilename_label" + style="@style/item" + android:labelFor="@id/profilename" + android:text="@string/profilename" + android:textAppearance="?android:attr/textAppearanceSmall" + android:visibility="gone" /> - <EditText - android:visibility="gone" - android:id="@+id/profilename" - style="@style/item" - android:inputType="text" /> + <EditText + android:id="@+id/profilename" + style="@style/item" + android:inputType="text" + android:visibility="gone" /> - <TextView - style="@style/item" - android:id="@+id/compatmode_label" - android:text="@string/compat_mode_label" - android:visibility="gone" - android:textAppearance="?android:attr/textAppearanceSmall" /> - <Spinner - android:id="@+id/compatmode" - style="@style/item" - android:visibility="gone" - android:prompt="@string/compatmode" - android:entries="@array/compat_mode" - /> + <TextView + android:id="@+id/compatmode_label" + style="@style/item" + android:text="@string/compat_mode_label" + android:textAppearance="?android:attr/textAppearanceSmall" + android:visibility="gone" + tools:visibility="visible" /> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/files_missing_hint" - android:visibility="gone" - android:id="@+id/files_missing_hint" - tools:visibilty="visible"/> + <Spinner + android:id="@+id/compatmode" + style="@style/item" + android:entries="@array/compat_mode" + android:prompt="@string/compatmode" + android:visibility="gone" + tools:visibility="visible" /> - <TextView - android:text="@string/query_permissions_sdcard" - android:layout_width="match_parent" - android:layout_height="wrap_content" - tools:visibility="visible" - android:visibility="gone" - android:id="@+id/permssion_hint" - android:padding="5dp" - android:textStyle="bold" /> + <TextView + android:id="@+id/tls_profile_label" + style="@style/item" + android:text="@string/tls_profile" + android:textAppearance="?android:attr/textAppearanceSmall" + android:visibility="gone" + tools:visibility="visible" /> + <Spinner + android:id="@+id/tls_profile" + style="@style/item" + android:entries="@array/tls_profile_entries" + android:prompt="@string/compatmode" + android:visibility="gone" + tools:visibility="visible" /> + <TextView + android:id="@+id/files_missing_hint" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/files_missing_hint" + android:visibility="gone" + tools:visibilty="visible" /> - <CheckBox - android:id="@+id/importpkcs12" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:checked="true" - tools:visibilty="visible" - android:text="@string/importpkcs12fromconfig" - android:visibility="gone"/> + <TextView + android:id="@+id/permssion_hint" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/query_permissions_sdcard" + android:textStyle="bold" + android:visibility="gone" + tools:visibility="visible" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="10dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/import_log" - android:id="@+id/textView"/> - <Space - android:id="@+id/fab_footerspace" - android:visibility="gone" - android:layout_width="40dp" - android:layout_height="@dimen/round_button_diameter" /> - </LinearLayout> + <CheckBox + android:id="@+id/importpkcs12" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:checked="true" + android:text="@string/importpkcs12fromconfig" + android:visibility="gone" + tools:visibilty="visible" /> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:text="@string/import_log" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <Space + android:id="@+id/fab_footerspace" + android:layout_width="40dp" + android:layout_height="@dimen/round_button_diameter" + android:visibility="gone" /> + </LinearLayout> </ScrollView> + <include layout="@layout/save_fab" /> </RelativeLayout> |