Skip to content

Commit

Permalink
allow external app or adb shell to connect or disconnect vpn. issue: d…
Browse files Browse the repository at this point in the history
  • Loading branch information
yaoxinghuo committed Jun 10, 2019
1 parent 6d66975 commit 63d3e32
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 34 deletions.
13 changes: 11 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,24 @@
</intent-filter>
</service>

<activity android:name=".RemoteControlActivity" />
<activity-alias
android:exported="true"
android:name=".api.DisconnectVPN"
android:targetActivity=".RemoteControlActivity" />

<activity-alias
android:exported="true"
android:name=".api.ConnectVPN"
android:targetActivity=".RemoteControlActivity" />

<activity
android:permission="app.openconnect.REMOTE_API"
android:name=".api.GrantPermissionsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity
android:permission="app.openconnect.REMOTE_API"
android:name=".api.ConfirmDialog" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
100 changes: 100 additions & 0 deletions app/src/main/java/app/openconnect/RemoteControlActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2019.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package app.openconnect;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.widget.Toast;
import app.openconnect.api.ExternalAppDatabase;
import app.openconnect.api.GrantPermissionsActivity;
import app.openconnect.core.OpenConnectManagementThread;
import app.openconnect.core.OpenVpnService;
import app.openconnect.core.ProfileManager;
import app.openconnect.core.VPNConnector;

/**
* @author Terry E-mail: yaoxinghuo at 126 dot com
* @date 2019-06-10 08:23
* @description
*/
public class RemoteControlActivity extends Activity {

public static final String EXTRA_NAME = "app.openconnect.api.profileName";

private ExternalAppDatabase mExtAppDb;
private VPNConnector mConn;

@Override
protected void onResume() {
super.onResume();

mExtAppDb = new ExternalAppDatabase(this);

mConn = new VPNConnector(this, true) {
@Override
public void onUpdate(OpenVpnService service) {
performAction(service);
}
};
}

private void performAction(OpenVpnService service) {

if (!mExtAppDb.checkRemoteActionPermission(this, getCallingPackage())) {
finish();
return;
}

Intent intent = getIntent();
if (intent == null) { // avoid crash

finish();
return;
}
setIntent(null);
ComponentName component = intent.getComponent();
if (component.getShortClassName().equals(".api.DisconnectVPN")) {
service.stopVPN();
} else if (component.getShortClassName().equals(".api.ConnectVPN")) {
String vpnName = intent.getStringExtra(EXTRA_NAME);
VpnProfile profile = ProfileManager.getProfileByName(vpnName);
if (profile == null) {
Toast.makeText(this, String.format("Vpn profile %s from API call not found", vpnName),
Toast.LENGTH_LONG).show();
} else {
if (service.getConnectionState() != OpenConnectManagementThread.STATE_DISCONNECTED) {
mConn.service.stopVPN();
}
startVPN(profile);
}
}
finish();
}

@Override
protected void onPause() {
super.onPause();

mConn.stopActiveDialog();
mConn.unbind();
}

private void startVPN(VpnProfile profile) {
Intent intent = new Intent(this, GrantPermissionsActivity.class);
String pkg = this.getPackageName();

intent.putExtra(pkg + GrantPermissionsActivity.EXTRA_UUID, profile.getUUID().toString());
intent.setAction(Intent.ACTION_MAIN);
startActivity(intent);
}
}
40 changes: 26 additions & 14 deletions app/src/main/java/app/openconnect/api/ConfirmDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand All @@ -35,6 +36,8 @@
public class ConfirmDialog extends Activity implements
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 = "app.openconnect.ANONYMOUS_PACKAGE";

private String mPackage;

Expand All @@ -46,20 +49,29 @@ public class ConfirmDialog extends Activity implements
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)));
Intent intent = getIntent();
if (intent.getStringExtra(EXTRA_PACKAGE_NAME) != null) {
mPackage = intent.getStringExtra(EXTRA_PACKAGE_NAME);
} else {
mPackage = getCallingPackage();
if (mPackage==null) {
finish();
return;
}
}

View view = View.inflate(this, R.layout.api_confirm, null);
CharSequence appString;
if (mPackage.equals(ANONYMOUS_PACKAGE)) {
appString = getString(R.string.anonymous_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);


Expand Down
22 changes: 19 additions & 3 deletions app/src/main/java/app/openconnect/api/ExternalAppDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@

package app.openconnect.api;

import java.util.HashSet;
import java.util.Set;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;

import java.util.HashSet;
import java.util.Set;

public class ExternalAppDatabase {

Context mContext;
Expand Down Expand Up @@ -79,4 +80,19 @@ public void removeApp(String packagename) {
saveExtAppList(allowedapps);
}

public boolean checkRemoteActionPermission(Context c, String callingPackage) {
if (callingPackage == null)
callingPackage = ConfirmDialog.ANONYMOUS_PACKAGE;

if (isAllowed(callingPackage)) {
return true;
} else {
Intent confirmDialog = new Intent(c, ConfirmDialog.class);
confirmDialog.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
confirmDialog.putExtra(ConfirmDialog.EXTRA_PACKAGE_NAME, callingPackage);
c.startActivity(confirmDialog);
return false;
}
}

}
29 changes: 16 additions & 13 deletions app/src/main/java/app/openconnect/fragments/GeneralSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,33 @@
*/

package app.openconnect.fragments;
import java.io.File;
import java.util.Map;

import android.Manifest.permission;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import app.openconnect.R;
import app.openconnect.api.ConfirmDialog;
import app.openconnect.api.ExternalAppDatabase;
import app.openconnect.core.DeviceStateReceiver;

import java.io.File;
import java.util.Map;

public class GeneralSettings extends PreferenceFragment
implements OnPreferenceClickListener, OnClickListener, OnSharedPreferenceChangeListener {

Expand Down Expand Up @@ -87,11 +88,9 @@ public boolean onPreferenceChange(Preference arg0, Object arg1) {
this.onSharedPreferenceChanged(sp, entry.getKey());
}

/*
Preference clearapi = findPreference("clearapi");
clearapi.setOnPreferenceClickListener(this);
setClearApiSummary();
*/
}

@Override
Expand Down Expand Up @@ -137,12 +136,16 @@ private String getExtAppList(String delim) {
String applist=null;
for (String packagename : mExtapp.getExtAppList()) {
try {
app = pm.getApplicationInfo(packagename, 0);
if (applist==null)
applist = "";
else
applist += delim;
applist+=app.loadLabel(pm);
if (applist==null)
applist = "";
else
applist += delim;
if(ConfirmDialog.ANONYMOUS_PACKAGE.equals(packagename)) {
applist+=getString(R.string.anonymous_app);
}else{
app = pm.getApplicationInfo(packagename, 0);
applist+=app.loadLabel(pm);
}

} catch (NameNotFoundException e) {
// App not found. Remove it from the list
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,15 @@
<string name="remote_trust">I trust this application.</string>
<string name="no_external_app_allowed">No app allowed to use external API</string>
<string name="allowed_apps">Allowed apps: %s</string>
<string name="anonymous_app">Anonymous App</string>
<string name="clearappsdialog">Clear list of allowed external apps?\nCurrent list of allowed apps:\n\n%s</string>
<string name="screenoff_summary">Pause the connection when the screen is off, to save battery life.</string>
<string name="screenoff_title">Pause when asleep</string>
<string name="save_password">Save Password</string>
<string name="device_specific">Device-specific Hacks</string>
<string name="cannotparsecert">Cannot display certificate information</string>
<string name="appbehaviour">APP behavior</string>
<string name="anonymous_app_prompt">An external app tries to control %s. The app requesting access cannot be determined. Allowing this app grants ANONYMOUS app access.</string>
<string name="vpnbehaviour">VPN behavior</string>
<string name="allow_vpn_changes">Allow changes to VPN Profiles</string>
<!-- OpenConnect preference strings -->
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/res/xml/general_settings.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!--

<PreferenceCategory android:title="@string/appbehaviour">

<!--
<CheckBoxPreference
android:defaultValue="false"
android:key="restartvpnonboot"
android:summary="@string/onbootrestartsummary"
android:title="@string/onbootrestart"/>
-->

<Preference
android:key="clearapi"
android:persistent="false"
android:title="Clear allowed external apps"/>
</PreferenceCategory>
-->

<PreferenceCategory android:title="@string/vpnbehaviour">
<!--
Expand Down

0 comments on commit 63d3e32

Please sign in to comment.