diff options
author | Arne Schwabe <arne@rfc2549.org> | 2021-08-24 19:25:59 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2021-08-24 19:25:59 +0200 |
commit | 09c5cb0a0d33c58897026b7b4b1901c1ddc088f1 (patch) | |
tree | 2a881c94bd517b145178a1bd08f71d69914115d4 /main/src/ui/java/de/blinkt/openvpn/fragments | |
parent | d1eb15b8dd6b4cb599ea7a084e61e24dfdbc74f4 (diff) |
Implement support of openvpn://import-profile/ support
For details about the protocol see
https://github.com/OpenVPN/openvpn3/blob/master/doc/webauth.md
Diffstat (limited to 'main/src/ui/java/de/blinkt/openvpn/fragments')
-rw-r--r-- | main/src/ui/java/de/blinkt/openvpn/fragments/ImportRemoteConfig.kt (renamed from main/src/ui/java/de/blinkt/openvpn/fragments/ImportASConfig.kt) | 82 | ||||
-rw-r--r-- | main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java | 14 |
2 files changed, 67 insertions, 29 deletions
diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/ImportASConfig.kt b/main/src/ui/java/de/blinkt/openvpn/fragments/ImportRemoteConfig.kt index 71d1ee7c..6cd322ca 100644 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/ImportASConfig.kt +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/ImportRemoteConfig.kt @@ -19,9 +19,7 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.CheckBox -import android.widget.EditText -import android.widget.Toast +import android.widget.* import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import de.blinkt.openvpn.R @@ -86,13 +84,16 @@ fun getCompositeSSLSocketFactory(certPin: CertificatePinner, hostname: String): } -class ImportASConfig : DialogFragment() { - private lateinit var asUseAutlogin: CheckBox +class ImportRemoteConfig : DialogFragment() { + private lateinit var asUseAutologin: CheckBox private lateinit var asServername: EditText private lateinit var asUsername: EditText private lateinit var asPassword: EditText private lateinit var dialogView: View + private lateinit var importChoiceGroup: RadioGroup + private lateinit var importChoiceAS: RadioButton + internal fun getHostNameVerifier(prefs: SharedPreferences): HostnameVerifier { @@ -131,8 +132,10 @@ class ImportASConfig : DialogFragment() { val pinnedHosts: Set<String> = prefs.getStringSet("pinnedHosts", emptySet())!! val okHttpClient = OkHttpClient.Builder() - .addInterceptor(BasicAuthInterceptor(user, password)) - .connectTimeout(15, TimeUnit.SECONDS) + if (user.isNotBlank() && password.isNotBlank()) { + okHttpClient.addInterceptor(BasicAuthInterceptor(user, password)) + } + okHttpClient.connectTimeout(15, TimeUnit.SECONDS) /* Rely on system certificates if we do not have the host pinned */ if (pinnedHosts.contains(hostname)) { @@ -164,6 +167,7 @@ class ImportASConfig : DialogFragment() { val prefs = c.getSharedPreferences("pinnedCerts", Context.MODE_PRIVATE) val pedit = prefs.edit() val pinnedHosts: MutableSet<String> = prefs.getStringSet("pinnedHosts", mutableSetOf<String>())!! + .toMutableSet() pinnedHosts.add(host) @@ -177,7 +181,7 @@ class ImportASConfig : DialogFragment() { internal fun removedPinnedCert(c: Context, host: String) { val prefs = c.getSharedPreferences("pinnedCerts", Context.MODE_PRIVATE) val pedit = prefs.edit() - val pinnedHosts: MutableSet<String> = prefs.getStringSet("pinnedHosts", mutableSetOf<String>())!! + val pinnedHosts: MutableSet<String> = prefs.getStringSet("pinnedHosts", mutableSetOf<String>())!!.toMutableSet() pinnedHosts.remove(host) @@ -223,7 +227,7 @@ class ImportASConfig : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val inflater = requireActivity().layoutInflater - dialogView = inflater.inflate(R.layout.import_as_config, null); + dialogView = inflater.inflate(R.layout.import_remote_config, null); val builder = AlertDialog.Builder(requireContext()) @@ -233,11 +237,27 @@ class ImportASConfig : DialogFragment() { asServername = dialogView.findViewById(R.id.as_servername) asUsername = dialogView.findViewById(R.id.username) asPassword = dialogView.findViewById(R.id.password) - asUseAutlogin = dialogView.findViewById(R.id.request_autologin) + asUseAutologin = dialogView.findViewById(R.id.request_autologin) + + importChoiceGroup = dialogView.findViewById(R.id.import_source_group) + importChoiceAS = dialogView.findViewById(R.id.import_choice_as) + + importChoiceGroup.setOnCheckedChangeListener { group, checkedId -> + if (checkedId == R.id.import_choice_as) + asServername.setHint(R.string.as_servername) + else + asServername.setHint(R.string.server_url) + } builder.setPositiveButton(R.string.import_config, null) builder.setNegativeButton(android.R.string.cancel) { _, _ -> } + if (arguments?.getString("url") != null) + { + asServername.setText(arguments?.getString("url")) + importChoiceGroup.check(R.id.import_choice_url) + } + val dialog = builder.create() return dialog @@ -276,8 +296,11 @@ class ImportASConfig : DialogFragment() { Toast.makeText(context, "Downloading profile", Toast.LENGTH_LONG).show() } - - val asProfileUri = getAsUrl(asServername.text.toString(), asUseAutlogin.isChecked) + val asProfileUri:HttpUrl + if (importChoiceAS.isChecked) + asProfileUri = getAsUrl(asServername.text.toString(), asUseAutologin.isChecked) + else + asProfileUri = HttpUrl.parse(asServername.text.toString()) var e: Exception? = null try { @@ -400,22 +423,43 @@ class ImportASConfig : DialogFragment() { override fun onResume() { super.onResume() - asServername.setText(Preferences.getDefaultSharedPreferences(activity).getString("as-hostname", "")) - asUsername.setText(Preferences.getDefaultSharedPreferences(activity).getString("as-username", "")) + if (arguments == null) { + asServername.setText( + Preferences.getDefaultSharedPreferences(activity).getString("as-hostname", "") + ) + asUsername.setText( + Preferences.getDefaultSharedPreferences(activity).getString("as-username", "") + ) + if (Preferences.getDefaultSharedPreferences(activity).getBoolean("as-selected", true)) { + importChoiceGroup.check(R.id.import_choice_as) + } else { + importChoiceGroup.check(R.id.import_choice_url) + } + + } } override fun onPause() { super.onPause() val prefs = Preferences.getDefaultSharedPreferences(activity) - prefs.edit().putString("as-hostname", asServername.text.toString()).apply() - prefs.edit().putString("as-username", asUsername.text.toString()).apply() + val editor = prefs.edit() + editor.putString("as-hostname", asServername.text.toString()) + editor.putString("as-username", asUsername.text.toString()) + editor.putBoolean("as-selected", importChoiceAS.isChecked) + editor.apply() } companion object { @JvmStatic - fun newInstance(): ImportASConfig { - return ImportASConfig(); + fun newInstance(url:String? = null): ImportRemoteConfig { + val frag = ImportRemoteConfig() + if (url != null) + { + val extras = Bundle() + extras.putString("url", url) + frag.arguments = extras + } + return frag } } - } 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 3804926f..ce6fa7f1 100644 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java @@ -21,7 +21,6 @@ import android.os.Bundle; import android.os.PersistableBundle; import androidx.annotation.RequiresApi; -import androidx.fragment.app.DialogFragment; import androidx.fragment.app.ListFragment; import android.text.Html; @@ -95,7 +94,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn private boolean showUserRequestDialogIfNeeded(ConnectionStatus level, Intent intent) { if (level == LEVEL_WAITING_FOR_USER_INPUT) { - if (intent.getStringExtra(EXTRA_CHALLENGE_TXT) != null) { + if (intent != null && intent.getStringExtra(EXTRA_CHALLENGE_TXT) != null) { PasswordDialogFragment pwInputFrag = PasswordDialogFragment.Companion.newInstance(intent, false); pwInputFrag.show(getParentFragmentManager(), "dialog"); @@ -126,6 +125,7 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + setListAdapter(); } @RequiresApi(api = Build.VERSION_CODES.N_MR1) @@ -277,12 +277,6 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setListAdapter(); - } - private void setListAdapter() { if (mArrayadapter == null) { mArrayadapter = new VPNArrayAdapter(getActivity(), R.layout.vpn_list_item, R.id.vpn_item_title); @@ -354,8 +348,8 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn } private boolean startASProfileImport() { - ImportASConfig asImportFrag = ImportASConfig.newInstance(); - asImportFrag.show(requireFragmentManager(), "dialog"); + ImportRemoteConfig asImportFrag = ImportRemoteConfig.newInstance(null); + asImportFrag.show(getParentFragmentManager(), "dialog"); return true; } |