summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2017-12-24 01:39:53 +0100
committerArne Schwabe <arne@rfc2549.org>2017-12-24 01:39:53 +0100
commitf014940abd99c372004e227f2e68f31820162731 (patch)
treec301a10b01b6935221e83d9343147cca5ee143de
parent5d9b51c42e4077d5975c2b74262e9ca78a6ed5a7 (diff)
Implement remote actions
-rw-r--r--build.gradle2
-rw-r--r--gradle/wrapper/gradle-wrapper.properties4
-rw-r--r--main/build.gradle6
m---------main/openssl0
-rw-r--r--main/src/main/AndroidManifest.xml7
-rw-r--r--main/src/main/java/de/blinkt/openvpn/LaunchVPN.java9
-rw-r--r--main/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java191
-rw-r--r--main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java41
-rw-r--r--main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java43
-rw-r--r--main/src/main/java/de/blinkt/openvpn/api/RemoteAction.java73
-rwxr-xr-xmain/src/main/res/values/strings.xml1
11 files changed, 252 insertions, 125 deletions
diff --git a/build.gradle b/build.gradle
index c482d85a..14cf5e15 100644
--- a/build.gradle
+++ b/build.gradle
@@ -11,7 +11,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.0-alpha04'
+ classpath 'com.android.tools.build:gradle:3.1.0-alpha06'
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c188c8b0..d7e494a9 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Nov 24 12:34:12 EST 2017
+#Sun Dec 24 00:32:39 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-4.4-20171031235950+0000-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-rc-3-all.zip
diff --git a/main/build.gradle b/main/build.gradle
index 6b49c36d..02384425 100644
--- a/main/build.gradle
+++ b/main/build.gradle
@@ -20,9 +20,9 @@ repositories {
dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
- compile 'com.android.support:support-annotations:27.0.1'
- compile 'com.android.support:cardview-v7:27.0.1'
- compile 'com.android.support:recyclerview-v7:27.0.1'
+ compile 'com.android.support:support-annotations:27.0.2'
+ compile 'com.android.support:cardview-v7:27.0.2'
+ compile 'com.android.support:recyclerview-v7:27.0.2'
// compile 'ch.acra:acra:4.5.0'
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
diff --git a/main/openssl b/main/openssl
-Subproject e6d693e846f38eb43a06b1c464d534bf39be80d
+Subproject 2b0fd26192c4014eabe8cbacbc87e0a2aec2d04
diff --git a/main/src/main/AndroidManifest.xml b/main/src/main/AndroidManifest.xml
index e57cf096..efee02f7 100644
--- a/main/src/main/AndroidManifest.xml
+++ b/main/src/main/AndroidManifest.xml
@@ -224,6 +224,13 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="de.blinkt.openvpn.activities.MainActivity" />
</activity>
+ <activity
+ android:name=".api.RemoteAction"
+ />
+ <activity-alias
+ android:exported="true"
+ android:name=".api.DisconnectVPN"
+ android:targetActivity=".api.RemoteAction" />
</application>
</manifest> \ No newline at end of file
diff --git a/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
index 44e355ff..7b5d4e28 100644
--- a/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
+++ b/main/src/main/java/de/blinkt/openvpn/LaunchVPN.java
@@ -34,6 +34,7 @@ import android.widget.EditText;
import java.io.IOException;
import de.blinkt.openvpn.activities.LogWindow;
+import de.blinkt.openvpn.api.ExternalAppDatabase;
import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.IServiceStatus;
import de.blinkt.openvpn.core.OpenVPNStatusService;
@@ -139,8 +140,14 @@ public class LaunchVPN extends Activity {
mhideLog = intent.getBooleanExtra(EXTRA_HIDELOG, false);
VpnProfile profileToConnect = ProfileManager.get(this, shortcutUUID);
- if (shortcutName != null && profileToConnect == null)
+ if (shortcutName != null && profileToConnect == null) {
profileToConnect = ProfileManager.getInstance(this).getProfileByName(shortcutName);
+ if (!(new ExternalAppDatabase(this).checkRemoteActionPermission(this))) {
+ finish();
+ return;
+ }
+ }
+
if (profileToConnect == null) {
VpnStatus.logError(R.string.shortcut_profile_notfound);
diff --git a/main/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java b/main/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java
index 4124b7d4..2355f83b 100644
--- a/main/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java
+++ b/main/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java
@@ -21,6 +21,7 @@ import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log;
@@ -29,97 +30,113 @@ import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
+
import de.blinkt.openvpn.R;
public class ConfirmDialog extends Activity implements
-CompoundButton.OnCheckedChangeListener, DialogInterface.OnClickListener {
- private static final String TAG = "OpenVPNVpnConfirm";
-
- private String mPackage;
-
- private Button mButton;
-
- private AlertDialog mAlert;
-
- @Override
- protected void onResume() {
- super.onResume();
- try {
- mPackage = getCallingPackage();
- if (mPackage==null) {
- finish();
- return;
- }
-
-
- PackageManager pm = getPackageManager();
- ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
-
- View view = View.inflate(this, R.layout.api_confirm, null);
- ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.loadIcon(pm));
- ((TextView) view.findViewById(R.id.prompt)).setText(
- getString(R.string.prompt, app.loadLabel(pm), getString(R.string.app)));
- ((CompoundButton) view.findViewById(R.id.check)).setOnCheckedChangeListener(this);
-
-
- Builder builder = new AlertDialog.Builder(this);
-
- builder.setView(view);
-
- builder.setIconAttribute(android.R.attr.alertDialogIcon);
- builder.setTitle(android.R.string.dialog_alert_title);
- builder.setPositiveButton(android.R.string.ok,this);
- builder.setNegativeButton(android.R.string.cancel,this);
-
- mAlert = builder.create();
- mAlert.setCanceledOnTouchOutside(false);
-
- mAlert.setOnShowListener (new OnShowListener() {
- @Override
- public void onShow(DialogInterface dialog) {
- mButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
- mButton.setEnabled(false);
-
- }
- });
-
- //setCloseOnTouchOutside(false);
-
- mAlert.show();
-
- } catch (Exception e) {
- Log.e(TAG, "onResume", e);
- finish();
- }
- }
-
- @Override
- public void onBackPressed() {
- setResult(RESULT_CANCELED);
- finish();
- }
-
- @Override
- public void onCheckedChanged(CompoundButton button, boolean checked) {
- mButton.setEnabled(checked);
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == DialogInterface.BUTTON_POSITIVE) {
- ExternalAppDatabase extapps = new ExternalAppDatabase(this);
- extapps.addApp(mPackage);
- setResult(RESULT_OK);
- finish();
- }
-
- if (which == DialogInterface.BUTTON_NEGATIVE) {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
+ CompoundButton.OnCheckedChangeListener, DialogInterface.OnClickListener {
+ private static final String TAG = "OpenVPNVpnConfirm";
+
+ public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
+
+ public static final String ANONYMOUS_PACKAGE = "de.blinkt.openvpn.ANYPACKAGE";
+
+ private String mPackage;
+
+ private Button mButton;
+
+ private AlertDialog mAlert;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ Intent intent = getIntent();
+ if (intent.getStringExtra(EXTRA_PACKAGE_NAME) != null) {
+ mPackage = intent.getStringExtra(EXTRA_PACKAGE_NAME);
+ } else {
+ mPackage = getCallingPackage();
+ if (mPackage == null) {
+ finish();
+ return;
+ }
+ }
+
+ try {
+ View view = View.inflate(this, R.layout.api_confirm, null);
+ CharSequence appString;
+ if (mPackage.equals(ANONYMOUS_PACKAGE)) {
+ appString = getString(R.string.all_app_prompt, getString(R.string.app));
+ } else {
+ PackageManager pm = getPackageManager();
+ ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
+ appString = getString(R.string.prompt, app.loadLabel(pm) , getString(R.string.app));
+ ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.loadIcon(pm));
+ }
+
+
+ ((TextView) view.findViewById(R.id.prompt)).setText(appString);
+ ((CompoundButton) view.findViewById(R.id.check)).setOnCheckedChangeListener(this);
+
+
+ Builder builder = new AlertDialog.Builder(this);
+
+ builder.setView(view);
+
+ builder.setIconAttribute(android.R.attr.alertDialogIcon);
+ builder.setTitle(android.R.string.dialog_alert_title);
+ builder.setPositiveButton(android.R.string.ok, this);
+ builder.setNegativeButton(android.R.string.cancel, this);
+
+ mAlert = builder.create();
+ mAlert.setCanceledOnTouchOutside(false);
+
+ mAlert.setOnShowListener(new OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialog) {
+ mButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
+ mButton.setEnabled(false);
+
+ }
+ });
+
+ //setCloseOnTouchOutside(false);
+
+ mAlert.show();
+
+ } catch (Exception e) {
+ Log.e(TAG, "onResume", e);
+ finish();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean checked) {
+ mButton.setEnabled(checked);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ ExternalAppDatabase extapps = new ExternalAppDatabase(this);
+ extapps.addApp(mPackage);
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ if (which == DialogInterface.BUTTON_NEGATIVE) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java b/main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java
index 967d7728..e87b4c3a 100644
--- a/main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java
+++ b/main/src/main/java/de/blinkt/openvpn/api/ExternalAppDatabase.java
@@ -5,9 +5,14 @@
package de.blinkt.openvpn.api;
+import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Binder;
import java.util.HashSet;
import java.util.Set;
@@ -64,4 +69,40 @@ public class ExternalAppDatabase {
saveExtAppList(allowedapps);
}
+
+ public String checkOpenVPNPermission(PackageManager pm) throws SecurityRemoteException {
+
+ for (String appPackage : getExtAppList()) {
+ ApplicationInfo app;
+ try {
+ app = pm.getApplicationInfo(appPackage, 0);
+ if (Binder.getCallingUid() == app.uid) {
+ return appPackage;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // App not found. Remove it from the list
+ removeApp(appPackage);
+ }
+
+ }
+ throw new SecurityException("Unauthorized OpenVPN API Caller");
+ }
+
+
+ public boolean checkRemoteActionPermission(Activity a) {
+
+ String callingPackage = a.getCallingPackage();
+
+ if (callingPackage == null)
+ callingPackage = ConfirmDialog.ANONYMOUS_PACKAGE;
+
+ if (isAllowed(callingPackage)) {
+ return true;
+ } else {
+ Intent confirmDialog = new Intent(a, ConfirmDialog.class);
+ confirmDialog.putExtra(ConfirmDialog.EXTRA_PACKAGE_NAME, callingPackage);
+ a.startActivity(confirmDialog);
+ return false;
+ }
+ }
}
diff --git a/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java
index 6b549ed1..e5c50a6c 100644
--- a/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java
@@ -111,28 +111,9 @@ public class ExternalOpenVPNService extends Service implements StateListener {
private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() {
- private String checkOpenVPNPermission() throws SecurityRemoteException {
- PackageManager pm = getPackageManager();
-
- for (String appPackage : mExtAppDb.getExtAppList()) {
- ApplicationInfo app;
- try {
- app = pm.getApplicationInfo(appPackage, 0);
- if (Binder.getCallingUid() == app.uid) {
- return appPackage;
- }
- } catch (NameNotFoundException e) {
- // App not found. Remove it from the list
- mExtAppDb.removeApp(appPackage);
- }
-
- }
- throw new SecurityException("Unauthorized OpenVPN API Caller");
- }
-
@Override
public List<APIVpnProfile> getProfiles() throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
ProfileManager pm = ProfileManager.getInstance(getBaseContext());
@@ -170,7 +151,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public void startProfile(String profileUUID) throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
VpnProfile vp = ProfileManager.get(getBaseContext(), profileUUID);
if (vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
@@ -180,7 +161,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
}
public void startVPN(String inlineConfig) throws RemoteException {
- String callingApp = checkOpenVPNPermission();
+ String callingApp = mExtAppDb.checkOpenVPNPermission(getPackageManager());
ConfigParser cp = new ConfigParser();
try {
@@ -216,7 +197,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public APIVpnProfile addNewVPNProfile(String name, boolean userEditable, String config) throws RemoteException {
- String callingPackage = checkOpenVPNPermission();
+ String callingPackage = mExtAppDb.checkOpenVPNPermission(getPackageManager());
ConfigParser cp = new ConfigParser();
try {
@@ -241,7 +222,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public void removeProfile(String profileUUID) throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
ProfileManager pm = ProfileManager.getInstance(getBaseContext());
VpnProfile vp = ProfileManager.get(getBaseContext(), profileUUID);
pm.removeProfile(ExternalOpenVPNService.this, vp);
@@ -249,7 +230,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public boolean protectSocket(ParcelFileDescriptor pfd) throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
try {
boolean success= mService.protect(pfd.getFd());
pfd.close();
@@ -272,7 +253,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public Intent prepareVPNService() throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (VpnService.prepare(ExternalOpenVPNService.this) == null)
return null;
@@ -284,7 +265,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public void registerStatusCallback(IOpenVPNStatusCallback cb)
throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (cb != null) {
cb.newStatus(mMostRecentState.vpnUUID, mMostRecentState.state,
@@ -298,7 +279,7 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public void unregisterStatusCallback(IOpenVPNStatusCallback cb)
throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (cb != null)
mCallbacks.unregister(cb);
@@ -306,21 +287,21 @@ public class ExternalOpenVPNService extends Service implements StateListener {
@Override
public void disconnect() throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (mService != null)
mService.stopVPN(false);
}
@Override
public void pause() throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (mService != null)
mService.userPause(true);
}
@Override
public void resume() throws RemoteException {
- checkOpenVPNPermission();
+ mExtAppDb.checkOpenVPNPermission(getPackageManager());
if (mService != null)
mService.userPause(false);
diff --git a/main/src/main/java/de/blinkt/openvpn/api/RemoteAction.java b/main/src/main/java/de/blinkt/openvpn/api/RemoteAction.java
new file mode 100644
index 00000000..cac8efcb
--- /dev/null
+++ b/main/src/main/java/de/blinkt/openvpn/api/RemoteAction.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012-2017 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.api;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import de.blinkt.openvpn.core.IOpenVPNServiceInternal;
+import de.blinkt.openvpn.core.OpenVPNService;
+
+public class RemoteAction extends Activity {
+
+ private ExternalAppDatabase mExtAppDb;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mExtAppDb = new ExternalAppDatabase(this);
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className,
+ IBinder service) {
+
+ IOpenVPNServiceInternal myservice = IOpenVPNServiceInternal.Stub.asInterface(service);
+ try {
+ myservice.stopVPN(false);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ //mService = null;
+ }
+
+ };
+
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mExtAppDb.checkRemoteActionPermission(this))
+ performAction();
+
+ finish();
+
+ }
+
+ private void performAction() {
+ Intent intent = new Intent(this, OpenVPNService.class);
+ intent.setAction(OpenVPNService.START_SERVICE);
+
+ ComponentName component = getIntent().getComponent();
+ if (component.getShortClassName().equals(".api.DisconnectVPN")) {
+ boolean mDoDisconnect = true;
+ }
+ getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+
+
+ }
+}
diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml
index 67248dae..c814afc6 100755
--- a/main/src/main/res/values/strings.xml
+++ b/main/src/main/res/values/strings.xml
@@ -454,5 +454,6 @@
<string name="openssl_error">OpenSSL returned an error</string>
<string name="running_test">Running test…</string>
<string name="test_algoirhtms">Test selected algorithms</string>
+ <string name="all_app_prompt">An external app tries to control %s. The app cannot be determined allowing now grants ALL apps access.</string>
</resources>