From b5e0eee4b798d3e2bfef3b87500b8625b77a16b4 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Wed, 11 Dec 2019 11:20:45 +0100 Subject: Modernise 2FA challenge input, use activity alias for non implemented activities --- .../de/blinkt/openvpn/fragments/LogFragment.java | 3 +- .../openvpn/fragments/PasswordDialogFragment.kt | 99 ++++++++++++++++++++++ .../blinkt/openvpn/fragments/VPNProfileList.java | 14 ++- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 main/src/ui/java/de/blinkt/openvpn/fragments/PasswordDialogFragment.kt (limited to 'main/src/ui/java/de/blinkt/openvpn/fragments') diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/LogFragment.java b/main/src/ui/java/de/blinkt/openvpn/fragments/LogFragment.java index 994d6e95..64eb720d 100644 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -9,6 +9,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.app.Activity; +import android.app.PendingIntent; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -650,7 +651,7 @@ public class LogFragment extends ListFragment implements StateListener, SeekBar. @Override - public void updateState(final String status, final String logMessage, final int resId, final ConnectionStatus level) { + public void updateState(final String status, final String logMessage, final int resId, final ConnectionStatus level, Intent intent) { if (isAdded()) { final String cleanLogMessage = VpnStatus.getLastCleanLogMessage(getActivity()); diff --git a/main/src/ui/java/de/blinkt/openvpn/fragments/PasswordDialogFragment.kt b/main/src/ui/java/de/blinkt/openvpn/fragments/PasswordDialogFragment.kt new file mode 100644 index 00000000..eedb2e59 --- /dev/null +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/PasswordDialogFragment.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012-2019 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ +package de.blinkt.openvpn.core + +import android.app.AlertDialog +import android.app.Dialog +import android.content.ComponentName +import android.content.DialogInterface +import android.content.Intent +import android.content.ServiceConnection +import android.os.Bundle +import android.os.IBinder +import android.os.RemoteException +import android.text.InputType +import android.widget.EditText +import androidx.fragment.app.DialogFragment +import de.blinkt.openvpn.R +import de.blinkt.openvpn.core.OpenVPNService.EXTRA_CHALLENGE_TXT + +class PasswordDialogFragment : DialogFragment() { + private var mService: IOpenVPNServiceInternal? = null + private val mConnection: ServiceConnection = object : ServiceConnection { + override fun onServiceConnected(className: ComponentName, + service: IBinder) { + mService = IOpenVPNServiceInternal.Stub.asInterface(service) + } + + override fun onServiceDisconnected(arg0: ComponentName) { + mService = null + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val intent = Intent(activity, OpenVPNService::class.java) + intent.action = OpenVPNService.START_SERVICE + requireActivity().bindService(intent, mConnection, 0) + } + + override fun onDestroy() { + super.onDestroy() + requireActivity().unbindService(mConnection) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val title = requireArguments().getString("title") + val echo = requireArguments().getBoolean("echo") + val finish = requireArguments().getBoolean("finish") + val input = EditText(activity) + if (!echo) + input.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + + return AlertDialog.Builder(activity) + .setTitle("Challenge/Response Authentification") + .setMessage(title) + .setView(input) + .setPositiveButton(android.R.string.ok) { _, _ -> + try { + mService?.challengeResponse(input.text.toString()) + if (finish) requireActivity().finish() + } catch (e: RemoteException) { + VpnStatus.logException(e) + e.printStackTrace() + } + } + .setNegativeButton(R.string.cancel + ) { _, _ -> if (finish) requireActivity().finish() } + .create() + } + + companion object { + fun newInstance(intent: Intent, finish: Boolean): PasswordDialogFragment? { + val extras = intent.extras ?: return null + val challenge = extras.getString(EXTRA_CHALLENGE_TXT, "R,E:(empty challenge text)") + val message = challenge.split(":", limit = 2)[1] + val flagsStr = challenge.split(":", limit = 2)[0] + val flags = flagsStr.split(",") + var echo = false + var response = false + for (flag in flags) { + if (flag == "R") response = true + else if (flag == "E") echo = true + } + if (!response) { + VpnStatus.logError("Error unrecognised challenge from Server: $challenge") + return null + } + val frag = PasswordDialogFragment() + val args = Bundle() + args.putString("title", message) + args.putBoolean("echo", echo) + args.putBoolean("finish", finish) + frag.arguments = args + return frag + } + } +} \ 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 eb81e62e..f3164bd3 100644 --- a/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java +++ b/main/src/ui/java/de/blinkt/openvpn/fragments/VPNProfileList.java @@ -53,10 +53,12 @@ import de.blinkt.openvpn.activities.DisconnectVPN; import de.blinkt.openvpn.activities.FileSelect; import de.blinkt.openvpn.activities.VPNPreferences; import de.blinkt.openvpn.core.ConnectionStatus; +import de.blinkt.openvpn.core.PasswordDialogFragment; import de.blinkt.openvpn.core.Preferences; import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.core.VpnStatus; +import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static de.blinkt.openvpn.core.OpenVPNService.DISCONNECT_VPN; @@ -80,13 +82,23 @@ public class VPNProfileList extends ListFragment implements OnClickListener, Vpn private ArrayAdapter mArrayadapter; @Override - public void updateState(String state, String logmessage, final int localizedResId, ConnectionStatus level) { + public void updateState(String state, String logmessage, final int localizedResId, ConnectionStatus level, Intent intent) { requireActivity().runOnUiThread(() -> { mLastStatusMessage = VpnStatus.getLastCleanLogMessage(getActivity()); mArrayadapter.notifyDataSetChanged(); + showUserRequestDialogIfNeeded(level, intent); }); } + private void showUserRequestDialogIfNeeded(ConnectionStatus level, Intent intent) { + if (level == LEVEL_WAITING_FOR_USER_INPUT) { + PasswordDialogFragment pwInputFrag = PasswordDialogFragment.Companion.newInstance(intent, false); + + pwInputFrag.show(requireFragmentManager(), "dialog"); + + } + } + @Override public void setConnectedVPN(String uuid) { } -- cgit v1.2.3