diff options
8 files changed, 132 insertions, 43 deletions
| diff --git a/main/build.gradle b/main/build.gradle index 78f29204..0ddd3590 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -126,7 +126,6 @@ android {          normal {              dimension "implementation"              buildConfigField 'boolean', 'openvpn3', 'true' -          }      } diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java index 4e391e2e..74c0b595 100644 --- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -311,13 +311,14 @@ public class VpnProfile implements Serializable, Cloneable {          } -        cfg.append("machine-readable-output\n"); -        if (!mIsOpenVPN22) -            cfg.append("allow-recursive-routing\n"); - -        // Users are confused by warnings that are misleading... -        cfg.append("ifconfig-nowarn\n"); +        if (!configForOvpn3) { +            cfg.append("machine-readable-output\n"); +            if (!mIsOpenVPN22) +                cfg.append("allow-recursive-routing\n"); +            // Users are confused by warnings that are misleading... +            cfg.append("ifconfig-nowarn\n"); +        }          boolean useTLSClient = (mAuthenticationType != TYPE_STATICKEYS); diff --git a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java index 53847cbf..1cbd99ef 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java +++ b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java @@ -66,5 +66,15 @@ public class ICSOpenVPNApplication extends Application {          mChannel.setLightColor(Color.BLUE);          mNotificationManager.createNotificationChannel(mChannel); + + +        // Urgent requests, e.g. two factor auth +        name = getString(R.string.channel_name_userreq); +        mChannel = new NotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_USERREQ_ID, +                name, NotificationManager.IMPORTANCE_HIGH); +        mChannel.setDescription(getString(R.string.channel_description_userreq)); +        mChannel.enableVibration(true); +        mChannel.setLightColor(Color.CYAN); +        mNotificationManager.createNotificationChannel(mChannel);      }  } diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index 5e0016f4..b5afbb0e 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -20,6 +20,7 @@ import android.content.pm.ShortcutManager;  import android.content.res.Configuration;  import android.content.res.Resources;  import android.net.ConnectivityManager; +import android.net.Uri;  import android.net.VpnService;  import android.os.Build;  import android.os.Bundle; @@ -66,6 +67,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      public static final String DISCONNECT_VPN = "de.blinkt.openvpn.DISCONNECT_VPN";      public static final String NOTIFICATION_CHANNEL_BG_ID = "openvpn_bg";      public static final String NOTIFICATION_CHANNEL_NEWSTATUS_ID = "openvpn_newstat"; +    public static final String NOTIFICATION_CHANNEL_USERREQ_ID = "openvpn_userreq"; +      public static final String VPNSERVICE_TUN = "vpnservice-tun";      public final static String ORBOT_PACKAGE_NAME = "org.torproject.android";      private static final String PAUSE_VPN = "de.blinkt.openvpn.PAUSE_VPN"; @@ -235,6 +238,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          int priority;          if (channel.equals(NOTIFICATION_CHANNEL_BG_ID))              priority = PRIORITY_MIN; +        else if (channel.equals(NOTIFICATION_CHANNEL_USERREQ_ID)) +            priority = PRIORITY_MAX;          else              priority = PRIORITY_DEFAULT; @@ -258,12 +263,13 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          // Try to set the priority available since API 16 (Jellybean) -        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {              jbNotificationExtras(priority, nbuilder); +            addVpnActionsToNotification(nbuilder); +        }          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) -            lpNotificationExtras(nbuilder); +            lpNotificationExtras(nbuilder, Notification.CATEGORY_SERVICE);          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {              //noinspection NewApi @@ -308,8 +314,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      }      @TargetApi(Build.VERSION_CODES.LOLLIPOP) -    private void lpNotificationExtras(Notification.Builder nbuilder) { -        nbuilder.setCategory(Notification.CATEGORY_SERVICE); +    private void lpNotificationExtras(Notification.Builder nbuilder, String category) { +        nbuilder.setCategory(category);          nbuilder.setLocalOnly(true);      } @@ -354,28 +360,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac              } -            Intent disconnectVPN = new Intent(this, DisconnectVPN.class); -            disconnectVPN.setAction(DISCONNECT_VPN); -            PendingIntent disconnectPendingIntent = PendingIntent.getActivity(this, 0, disconnectVPN, 0); - -            nbuilder.addAction(R.drawable.ic_menu_close_clear_cancel, -                    getString(R.string.cancel_connection), disconnectPendingIntent); - -            Intent pauseVPN = new Intent(this, OpenVPNService.class); -            if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) { -                pauseVPN.setAction(PAUSE_VPN); -                PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); -                nbuilder.addAction(R.drawable.ic_menu_pause, -                        getString(R.string.pauseVPN), pauseVPNPending); - -            } else { -                pauseVPN.setAction(RESUME_VPN); -                PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); -                nbuilder.addAction(R.drawable.ic_menu_play, -                        getString(R.string.resumevpn), resumeVPNPending); -            } - -              //ignore exception          } catch (NoSuchMethodException | IllegalArgumentException |                  InvocationTargetException | IllegalAccessException e) { @@ -384,6 +368,30 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac      } +    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) +    private void addVpnActionsToNotification(Notification.Builder nbuilder) { +        Intent disconnectVPN = new Intent(this, DisconnectVPN.class); +        disconnectVPN.setAction(DISCONNECT_VPN); +        PendingIntent disconnectPendingIntent = PendingIntent.getActivity(this, 0, disconnectVPN, 0); + +        nbuilder.addAction(R.drawable.ic_menu_close_clear_cancel, +                getString(R.string.cancel_connection), disconnectPendingIntent); + +        Intent pauseVPN = new Intent(this, OpenVPNService.class); +        if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) { +            pauseVPN.setAction(PAUSE_VPN); +            PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); +            nbuilder.addAction(R.drawable.ic_menu_pause, +                    getString(R.string.pauseVPN), pauseVPNPending); + +        } else { +            pauseVPN.setAction(RESUME_VPN); +            PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); +            nbuilder.addAction(R.drawable.ic_menu_play, +                    getString(R.string.resumevpn), resumeVPNPending); +        } +    } +      PendingIntent getUserInputIntent(String needed) {          Intent intent = new Intent(getApplicationContext(), LaunchVPN.class);          intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); @@ -1106,11 +1114,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          // Display byte count only after being connected          { -            if (level == LEVEL_WAITING_FOR_USER_INPUT) { -                // The user is presented a dialog of some kind, no need to inform the user -                // with a notifcation -                return; -            } else if (level == LEVEL_CONNECTED) { +            if (level == LEVEL_CONNECTED) {                  mDisplayBytecount = true;                  mConnecttime = System.currentTimeMillis();                  if (!runningOnAndroidTV()) @@ -1190,4 +1194,47 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac          VpnStatus.updateStateString("NEED", "need " + needed, resid, LEVEL_WAITING_FOR_USER_INPUT);          showNotification(getString(resid), getString(resid), NOTIFICATION_CHANNEL_NEWSTATUS_ID, 0, LEVEL_WAITING_FOR_USER_INPUT);      } + +    public void trigger_url_open(String info) { +        String channel = NOTIFICATION_CHANNEL_USERREQ_ID; +        String url = info.split(":",2)[1]; + +        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + +        Notification.Builder nbuilder = new Notification.Builder(this); +        nbuilder.setContentTitle(getString(R.string.openurl_requested)); + +        nbuilder.setContentText(url); +        nbuilder.setAutoCancel(true); + +        int icon = android.R.drawable.ic_dialog_info; + +        nbuilder.setSmallIcon(icon); + +        Intent openUrlIntent = new Intent(Intent.ACTION_VIEW); +        openUrlIntent.setData(Uri.parse(url)); +        openUrlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + +        nbuilder.setContentIntent(PendingIntent.getActivity(this,0, openUrlIntent, 0)); + + +        // Try to set the priority available since API 16 (Jellybean) +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) +            jbNotificationExtras(PRIORITY_MAX, nbuilder); + +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) +            lpNotificationExtras(nbuilder, Notification.CATEGORY_STATUS); + +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +            //noinspection NewApi +            nbuilder.setChannelId(channel); +        } + +        @SuppressWarnings("deprecation") +        Notification notification = nbuilder.getNotification(); + +        int notificationId = channel.hashCode(); + +        mNotificationManager.notify(notificationId, notification); +    }  } diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index e711d8ff..74a2ad05 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -312,6 +312,9 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {                  case "PK_SIGN":
                      processSignCommand(argument);
                      break;
 +                case "INFOMSG":
 +                    processInfoMessage(argument);
 +                    break;
                  default:
                      VpnStatus.logWarning("MGMT: Got unrecognized command" + command);
                      Log.i(TAG, "Got unrecognized command" + command);
 @@ -330,6 +333,14 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {          }
      }
 +    private void processInfoMessage(String info)
 +    {
 +        if (info.startsWith("OPEN_URL:"))
 +        {
 +            mOpenVPNService.trigger_url_open(info);
 +        }
 +    }
 +
      private void processLogMessage(String argument) {
          String[] args = argument.split(",", 4);
          // 0 unix time stamp
 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 3adf7c88..b87c8864 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -300,6 +300,8 @@ public class VpnStatus {                  return R.string.state_resolve;              case "TCP_CONNECT":                  return R.string.state_tcp_connect; +            case "AUTH_PENDING": +                return R.string.state_auth_pending;              default:                  return R.string.unknown_state;          } @@ -323,7 +325,7 @@ public class VpnStatus {      private static ConnectionStatus getLevel(String state) {          String[] noreplyet = {"CONNECTING", "WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"}; -        String[] reply = {"AUTH", "GET_CONFIG", "ASSIGN_IP", "ADD_ROUTES"}; +        String[] reply = {"AUTH", "GET_CONFIG", "ASSIGN_IP", "ADD_ROUTES", "AUTH_PENDING"};          String[] connected = {"CONNECTED"};          String[] notconnected = {"DISCONNECTED", "EXITING"}; @@ -385,7 +387,7 @@ public class VpnStatus {          for (StateListener sl : stateListener) {              sl.updateState(state, msg, resid, level);          } -        newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg))); +        //newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg)));      }      public static void logInfo(String message) { diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml index a7cd6a61..5590acf3 100755 --- a/main/src/main/res/values/strings.xml +++ b/main/src/main/res/values/strings.xml @@ -475,4 +475,11 @@      <string name="faq_remote_api">OpenVPN for Android supports two remote APIs, a sophisticated API using AIDL (remoteEXample in the git repository) and a simple one using Intents. <p>Examples using adb shell and the intents. Replace profilname with your profile name<p><p> adb shell am start-activity -a android.intent.action.MAIN de.blinkt.openvpn/.api.DisconnectVPN<p> adb shell am start-activity -a android.intent.action.MAIN -e de.blinkt.openvpn.api.profileName Blinkt de.blinkt.openvpn/.api.ConnectVPN</string>      <string name ="enableproxyauth">Enable Proxy Authentication</string>      <string name="error_orbot_and_proxy_options">Cannot use extra http-proxy-option statement and Orbot integration at the same timeO</string> +    <string name="info_from_server">Info from server: \'%s\'</string> +    <string name="channel_name_userreq">User interaction required</string> +    <string name="channel_description_userreq">OpenVPN connection requires a user input, e.g. two factor +        authentification +    </string> +    <string name="openurl_requested">Open URL to continue VPN authentication</string> +    <string name="state_auth_pending">Authentication pending</string>  </resources> diff --git a/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java b/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java index b2e8714f..08c84558 100644 --- a/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java +++ b/main/src/ovpn3/java/de/blinkt/openvpn/core/OpenVPNThreadv3.java @@ -1,5 +1,6 @@  package de.blinkt.openvpn.core; +import de.blinkt.openvpn.R;  import net.openvpn.ovpn3.ClientAPI_Config;  import net.openvpn.ovpn3.ClientAPI_EvalConfig;  import net.openvpn.ovpn3.ClientAPI_Event; @@ -189,6 +190,7 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable          //config.setPlatformVersion(mVp.getPlatformVersionEnvString());  		config.setExternalPkiAlias("extpki");  		config.setCompressionMode("yes"); +		config.setInfo(true);  		ClientAPI_EvalConfig ec = eval_config(config);  		if(ec.getExternalPki()) { @@ -278,9 +280,19 @@ public class OpenVPNThreadv3 extends ClientAPI_OpenVPNClient implements Runnable  	@Override  	public void event(ClientAPI_Event event) { -		VpnStatus.updateStateString(event.getName(), event.getInfo()); +		String name = event.getName(); +		String info = event.getInfo(); +		if (name.equals("INFO")) { +			VpnStatus.logInfo(R.string.info_from_server, info); +			if (info.startsWith("OPEN_URL:")) +			{ +				mService.trigger_url_open(info); +			} +		} else{ +			VpnStatus.updateStateString(name, info); +		}  		if(event.getError()) -            VpnStatus.logError(String.format("EVENT(Error): %s: %s",event.getName(),event.getInfo())); +            VpnStatus.logError(String.format("EVENT(Error): %s: %s", name, info));  	} | 
