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 --- .../java/de/blinkt/openvpn/OpenVPNTileService.java | 3 +- .../blinkt/openvpn/activities/CredentialsPopup.kt | 29 +++++++ .../de/blinkt/openvpn/fragments/LogFragment.java | 3 +- .../openvpn/fragments/PasswordDialogFragment.kt | 99 ++++++++++++++++++++++ .../blinkt/openvpn/fragments/VPNProfileList.java | 14 ++- 5 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt create mode 100644 main/src/ui/java/de/blinkt/openvpn/fragments/PasswordDialogFragment.kt (limited to 'main/src/ui') diff --git a/main/src/ui/java/de/blinkt/openvpn/OpenVPNTileService.java b/main/src/ui/java/de/blinkt/openvpn/OpenVPNTileService.java index ce14cc98..c9ce9745 100644 --- a/main/src/ui/java/de/blinkt/openvpn/OpenVPNTileService.java +++ b/main/src/ui/java/de/blinkt/openvpn/OpenVPNTileService.java @@ -7,6 +7,7 @@ package de.blinkt.openvpn; import android.annotation.SuppressLint; import android.annotation.TargetApi; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -111,7 +112,7 @@ public class OpenVPNTileService extends TileService implements VpnStatus.StateLi } @Override - public void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level) { + public void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level, Intent intent) { VpnProfile vpn; Tile t = getQsTile(); if (level == ConnectionStatus.LEVEL_AUTH_FAILED || level == ConnectionStatus.LEVEL_NOTCONNECTED) { diff --git a/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt b/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt new file mode 100644 index 00000000..f5d836b9 --- /dev/null +++ b/main/src/ui/java/de/blinkt/openvpn/activities/CredentialsPopup.kt @@ -0,0 +1,29 @@ +/* + * 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.activities + +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.DialogFragment +import de.blinkt.openvpn.core.PasswordDialogFragment.Companion.newInstance + +class CredentialsPopup : AppCompatActivity() { + public override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // Get the alarm ID from the intent extra data + val intent = intent + showPwDialog(intent) + } + + private fun showPwDialog(intent: Intent) { + val frag: DialogFragment? = newInstance(intent, true) + if (frag == null) { + finish() + return + } + frag.show(supportFragmentManager, "dialog") + } +} \ No newline at end of file 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