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 --- main/src/main/AndroidManifest.xml | 4 +- .../de/blinkt/openvpn/core/IStatusCallbacks.aidl | 2 +- .../src/main/java/de/blinkt/openvpn/LaunchVPN.java | 4 +- .../blinkt/openvpn/api/ExternalOpenVPNService.java | 3 +- .../de/blinkt/openvpn/core/CredentialsPopup.java | 47 ---------- .../de/blinkt/openvpn/core/OpenVPNService.java | 52 ++++++------ .../blinkt/openvpn/core/OpenVPNStatusService.java | 11 ++- .../openvpn/core/PasswordDialogFragment.java | 91 -------------------- .../de/blinkt/openvpn/core/StatusListener.java | 5 +- .../java/de/blinkt/openvpn/core/VpnStatus.java | 28 ++++-- main/src/skeleton/AndroidManifest.xml | 13 ++- .../de/blinkt/openvpn/activities/LogWindow.java | 14 --- .../de/blinkt/openvpn/activities/MainActivity.java | 14 --- .../blinkt/openvpn/activities/NotImplemented.java | 14 +++ .../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 ++- 19 files changed, 235 insertions(+), 215 deletions(-) delete mode 100644 main/src/main/java/de/blinkt/openvpn/core/CredentialsPopup.java delete mode 100644 main/src/main/java/de/blinkt/openvpn/core/PasswordDialogFragment.java delete mode 100644 main/src/skeleton/java/de/blinkt/openvpn/activities/LogWindow.java delete mode 100644 main/src/skeleton/java/de/blinkt/openvpn/activities/MainActivity.java create mode 100644 main/src/skeleton/java/de/blinkt/openvpn/activities/NotImplemented.java 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') diff --git a/main/src/main/AndroidManifest.xml b/main/src/main/AndroidManifest.xml index 8df4ed79..cfa99452 100644 --- a/main/src/main/AndroidManifest.xml +++ b/main/src/main/AndroidManifest.xml @@ -19,7 +19,9 @@ android:supportsRtl="true" android:theme="@style/blinkt" tools:ignore="UnusedAttribute"> - + { - if (mService != null) { - try { - mService.challengeResponse(input.getText().toString()); - getActivity().finish(); - } catch (RemoteException e) { - VpnStatus.logException(e); - e.printStackTrace(); - } - } - }) - .setNegativeButton(android.R.string.cancel, - (dialog, whichButton) -> getActivity().finish() - ) - .create(); - } -} \ No newline at end of file diff --git a/main/src/main/java/de/blinkt/openvpn/core/StatusListener.java b/main/src/main/java/de/blinkt/openvpn/core/StatusListener.java index bb8572c9..2a1166ce 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/StatusListener.java +++ b/main/src/main/java/de/blinkt/openvpn/core/StatusListener.java @@ -5,6 +5,7 @@ package de.blinkt.openvpn.core; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -35,8 +36,8 @@ public class StatusListener implements VpnStatus.LogListener { @Override public void updateStateString(String state, String msg, int resid, ConnectionStatus - level) throws RemoteException { - VpnStatus.updateStateString(state, msg, resid, level); + level, Intent intent) throws RemoteException { + VpnStatus.updateStateString(state, msg, resid, level, intent); } @Override diff --git a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index c8e98b6d..4d286b81 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -5,7 +5,9 @@ package de.blinkt.openvpn.core; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.os.Build; import android.os.HandlerThread; import android.os.Message; @@ -15,14 +17,9 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.LinkedList; import java.util.Locale; -import java.util.Queue; import java.util.Vector; -import java.util.concurrent.ConcurrentLinkedQueue; -import android.util.Log; -import de.blinkt.openvpn.BuildConfig; import de.blinkt.openvpn.R; -import de.blinkt.openvpn.VpnProfile; public class VpnStatus { @@ -39,6 +36,8 @@ public class VpnStatus { private static int mLastStateresid = R.string.state_noprocess; + private static Intent mLastIntent = null; + private static HandlerThread mHandlerThread; private static String mLastConnectedVPNUUID; @@ -48,6 +47,7 @@ public class VpnStatus { public static TrafficHistory trafficHistory; + public static void logException(LogLevel ll, String context, Exception e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); @@ -216,7 +216,7 @@ public class VpnStatus { } public interface StateListener { - void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level); + void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level, Intent Intent); void setConnectedVPN(String uuid); } @@ -272,7 +272,7 @@ public class VpnStatus { if (!stateListener.contains(sl)) { stateListener.add(sl); if (mLaststate != null) - sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel); + sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel, mLastIntent); } } @@ -366,12 +366,21 @@ public class VpnStatus { } static void updateStateString(String state, String msg) { + // We want to skip announcing that we are trying to get the configuration since + // this is just polling until the user input has finished.be + if (mLastLevel == ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT && state.equals("GET_CONFIG")) + return; int rid = getLocalizedState(state); ConnectionStatus level = getLevel(state); updateStateString(state, msg, rid, level); } - public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) { + public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) + { + updateStateString(state, msg, resid, level, null); + } + + public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level, Intent intent) { // Workound for OpenVPN doing AUTH and wait and being connected // Simply ignore these state if (mLastLevel == ConnectionStatus.LEVEL_CONNECTED && @@ -384,10 +393,11 @@ public class VpnStatus { mLaststatemsg = msg; mLastStateresid = resid; mLastLevel = level; + mLastIntent = intent; for (StateListener sl : stateListener) { - sl.updateState(state, msg, resid, level); + sl.updateState(state, msg, resid, level, intent); } //newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg))); } diff --git a/main/src/skeleton/AndroidManifest.xml b/main/src/skeleton/AndroidManifest.xml index 916da0e2..054d61e7 100644 --- a/main/src/skeleton/AndroidManifest.xml +++ b/main/src/skeleton/AndroidManifest.xml @@ -9,8 +9,19 @@ + + + + + diff --git a/main/src/skeleton/java/de/blinkt/openvpn/activities/LogWindow.java b/main/src/skeleton/java/de/blinkt/openvpn/activities/LogWindow.java deleted file mode 100644 index 9fd3ba49..00000000 --- a/main/src/skeleton/java/de/blinkt/openvpn/activities/LogWindow.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.blinkt.openvpn.activities; - -import android.app.Activity; -import android.os.Bundle; -import android.widget.Toast; - -public class LogWindow extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Toast.makeText(this, "Not implemented", Toast.LENGTH_LONG).show(); - finish(); - } -} \ No newline at end of file diff --git a/main/src/skeleton/java/de/blinkt/openvpn/activities/MainActivity.java b/main/src/skeleton/java/de/blinkt/openvpn/activities/MainActivity.java deleted file mode 100644 index d3c79d51..00000000 --- a/main/src/skeleton/java/de/blinkt/openvpn/activities/MainActivity.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.blinkt.openvpn.activities; - -import android.app.Activity; -import android.os.Bundle; -import android.widget.Toast; - -public class MainActivity extends Activity { - @Override - protected void onCreate( Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Toast.makeText(this, "Not implemented", Toast.LENGTH_LONG).show(); - finish(); - } -} \ No newline at end of file diff --git a/main/src/skeleton/java/de/blinkt/openvpn/activities/NotImplemented.java b/main/src/skeleton/java/de/blinkt/openvpn/activities/NotImplemented.java new file mode 100644 index 00000000..3abe826f --- /dev/null +++ b/main/src/skeleton/java/de/blinkt/openvpn/activities/NotImplemented.java @@ -0,0 +1,14 @@ +package de.blinkt.openvpn.activities; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.Toast; + +public class NotImplemented extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Toast.makeText(this, "Not implemented", Toast.LENGTH_LONG).show(); + finish(); + } +} \ No newline at end of file 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