diff options
| -rw-r--r-- | AndroidManifest.xml | 16 | ||||
| -rw-r--r-- | res/layout/api_confirm.xml | 57 | ||||
| -rwxr-xr-x | res/values/strings.xml | 4 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/APIVpnProfile.aidl | 1 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/APIVpnProfile.java | 56 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/ConfirmDialog.java | 123 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/ExternalAppDatabase.java | 58 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/ExternalOpenVPNService.java | 238 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/GrantPermissionsActivity.java | 26 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl | 41 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl | 13 | ||||
| -rw-r--r-- | src/de/blinkt/openvpn/api/SecurityRemoteException.java | 12 | 
12 files changed, 640 insertions, 5 deletions
| diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b01e92d8..b8d231d4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -18,8 +18,8 @@  <manifest xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:tools="http://schemas.android.com/tools"      package="de.blinkt.openvpn" -    android:versionCode="65" -    android:versionName="0.5.36a" > +    android:versionCode="66" +    android:versionName="0.5.36b" >      <uses-permission android:name="android.permission.INTERNET" />      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -82,8 +82,13 @@          </service>          <activity -            android:name=".api.GrantPermissionsActivity" -            android:permission="de.blinkt.openvpn.REMOTE_API" > +            android:name=".api.GrantPermissionsActivity"> +            <intent-filter> +                <action android:name="android.intent.action.MAIN" /> +            </intent-filter> +        </activity> +        <activity +            android:name=".api.ConfirmDialog" >              <intent-filter>                  <action android:name="android.intent.action.MAIN" />              </intent-filter> @@ -152,6 +157,7 @@              android:targetActivity=".LaunchVPN" >              <intent-filter>                  <action android:name="android.intent.action.CREATE_SHORTCUT" /> +                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </activity-alias> @@ -164,4 +170,4 @@              tools:ignore="ExportedContentProvider" />      </application> -</manifest> +</manifest>
\ No newline at end of file diff --git a/res/layout/api_confirm.xml b/res/layout/api_confirm.xml new file mode 100644 index 00000000..bad20cc0 --- /dev/null +++ b/res/layout/api_confirm.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + +     Licensed under the Apache License, Version 2.0 (the "License"); +     you may not use this file except in compliance with the License. +     You may obtain a copy of the License at + +          http://www.apache.org/licenses/LICENSE-2.0 + +     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. +--> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" +        android:layout_width="match_parent" +        android:layout_height="wrap_content"> +    <LinearLayout android:layout_width="match_parent" +            android:layout_height="wrap_content" +            android:orientation="vertical" +            android:padding="3mm"> + +        <LinearLayout android:layout_width="match_parent" +                android:layout_height="wrap_content" +                android:orientation="horizontal" +                android:gravity="center_vertical"> + +            <ImageView android:id="@+id/icon" +                    android:layout_width="@android:dimen/app_icon_size" +                    android:layout_height="@android:dimen/app_icon_size" +                    android:paddingRight="1mm"/> + +            <TextView android:id="@+id/prompt" +                    android:layout_width="fill_parent" +                    android:layout_height="wrap_content" +                    android:textSize="18sp"/> +        </LinearLayout> + +        <TextView android:id="@+id/warning" +                android:layout_width="fill_parent" +                android:layout_height="wrap_content" +                android:paddingTop="1mm" +                android:paddingBottom="1mm" +                android:text="@string/remote_warning" +                android:textSize="18sp"/> + +        <CheckBox android:id="@+id/check" +                android:layout_width="fill_parent" +                android:layout_height="wrap_content" +                android:text="@string/remote_trust" +                android:textSize="20sp" +                android:checked="false"/> +    </LinearLayout> +</ScrollView>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index cdc42288..3e969f18 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -277,5 +277,9 @@      <string name="rdn_prefix">RDN prefix</string>      <string name="tls_remote_deprecated">tls-remote (DEPRECATED)</string>      <string name="help_translate">You can help translating by visiting http://crowdin.net/project/ics-openvpn/invite</string> +    <!-- Dialog title to identify the request from a VPN application. [CHAR LIMIT=60] --> +    <string name="prompt">%1$s attempts to control %2$s</string> +    <string name="remote_warning">By proceeding, you are giving the application permission to completely control OpenVPN for Android and to intercept all network traffic. <b> Do NOT accept unless you trust the application. </b> Otherwise, you run the risk of having your data compromised by malicious software."</string> +    <string name="remote_trust">I trust this application.</string>  </resources>
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/api/APIVpnProfile.aidl b/src/de/blinkt/openvpn/api/APIVpnProfile.aidl new file mode 100644 index 00000000..16cc85bc --- /dev/null +++ b/src/de/blinkt/openvpn/api/APIVpnProfile.aidl @@ -0,0 +1 @@ +parcelable APIVpnProfile;	
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/api/APIVpnProfile.java b/src/de/blinkt/openvpn/api/APIVpnProfile.java new file mode 100644 index 00000000..5445913a --- /dev/null +++ b/src/de/blinkt/openvpn/api/APIVpnProfile.java @@ -0,0 +1,56 @@ +package de.blinkt.openvpn.api;
 +
 +import android.os.Parcel;
 +import android.os.Parcelable;
 +
 +public class APIVpnProfile implements Parcelable {
 +
 +	public final String mUUID;
 +	public final String mName;
 +	public final boolean mUserEditable;
 +
 +	
 +
 +	public APIVpnProfile(Parcel in) {
 +		mUUID = in.readString();
 +		mName = in.readString();
 +		if(in.readInt()==0)
 +			mUserEditable=false;
 +		else
 +			mUserEditable=true;
 +	}
 +
 +	public APIVpnProfile(String uuidString, String name, boolean userEditable) {
 +		mUUID=uuidString;
 +		mName = name;
 +		mUserEditable=userEditable;
 +	}
 +
 +	@Override
 +	public int describeContents() {
 +		return 0;
 +	}
 +
 +	@Override
 +	public void writeToParcel(Parcel dest, int flags) {
 +		dest.writeString(mUUID);
 +		dest.writeString(mName);
 +		if(mUserEditable)
 +			dest.writeInt(0);
 +		else
 +			dest.writeInt(1);
 +	}
 +
 +	public static final Parcelable.Creator<APIVpnProfile> CREATOR
 +	= new Parcelable.Creator<APIVpnProfile>() {
 +		public APIVpnProfile createFromParcel(Parcel in) {
 +			return new APIVpnProfile(in);
 +		}
 +
 +		public APIVpnProfile[] newArray(int size) {
 +			return new APIVpnProfile[size];
 +		}
 +	};
 +
 +
 +}
 diff --git a/src/de/blinkt/openvpn/api/ConfirmDialog.java b/src/de/blinkt/openvpn/api/ConfirmDialog.java new file mode 100644 index 00000000..f72f4921 --- /dev/null +++ b/src/de/blinkt/openvpn/api/ConfirmDialog.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 de.blinkt.openvpn.api; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.content.DialogInterface; +import android.content.DialogInterface.OnShowListener; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.util.Log; +import android.view.View; +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.setOnShowListener (new OnShowListener() { +				 +				@Override +				public void onShow(DialogInterface dialog) { +					// TODO Auto-generated method stub +					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() { +	} + +	@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) { +			finish(); +		} +	} + +} + diff --git a/src/de/blinkt/openvpn/api/ExternalAppDatabase.java b/src/de/blinkt/openvpn/api/ExternalAppDatabase.java new file mode 100644 index 00000000..ca348152 --- /dev/null +++ b/src/de/blinkt/openvpn/api/ExternalAppDatabase.java @@ -0,0 +1,58 @@ +package de.blinkt.openvpn.api; + +import java.util.HashSet; +import java.util.Set; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.preference.PreferenceManager; + +public class ExternalAppDatabase { + +	Context mContext; +	 +	public ExternalAppDatabase(Context c) { +		mContext =c; +	} + +	private final String PREFERENCES_KEY = "PREFERENCES_KEY"; + +	boolean isAllowed(String packagename) { +		Set<String> allowedapps = getExtAppList(); + +		return allowedapps.contains(packagename);  + +	} + +	Set<String> getExtAppList() { +		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);         +		Set<String> allowedapps = prefs.getStringSet(PREFERENCES_KEY, new HashSet<String>()); +		return allowedapps; +	} + +	void addApp(String packagename) +	{ +		Set<String> allowedapps = getExtAppList(); +		allowedapps.add(packagename); +		saveExtAppList(allowedapps); +	} + +	private void saveExtAppList( Set<String> allowedapps) { +		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);         +		Editor prefedit = prefs.edit(); +		prefedit.putStringSet(PREFERENCES_KEY, allowedapps); +		prefedit.apply(); +	} +	 +	void clearAllApiApps() { +		saveExtAppList(new HashSet<String>()); +	} + +	public void removeApp(String packagename) { +		Set<String> allowedapps = getExtAppList(); +		allowedapps.remove(packagename); +		saveExtAppList(allowedapps);		 +	} + +} diff --git a/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java new file mode 100644 index 00000000..459bf790 --- /dev/null +++ b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java @@ -0,0 +1,238 @@ +package de.blinkt.openvpn.api;
 +
 +import java.io.IOException;
 +import java.io.StringReader;
 +import java.util.LinkedList;
 +import java.util.List;
 +
 +import android.app.Service;
 +import android.content.ComponentName;
 +import android.content.Context;
 +import android.content.Intent;
 +import android.content.ServiceConnection;
 +import android.content.pm.ApplicationInfo;
 +import android.content.pm.PackageManager;
 +import android.content.pm.PackageManager.NameNotFoundException;
 +import android.net.VpnService;
 +import android.os.Binder;
 +import android.os.IBinder;
 +import android.os.RemoteCallbackList;
 +import android.os.RemoteException;
 +import de.blinkt.openvpn.R;
 +import de.blinkt.openvpn.VpnProfile;
 +import de.blinkt.openvpn.core.ConfigParser;
 +import de.blinkt.openvpn.core.ConfigParser.ConfigParseError;
 +import de.blinkt.openvpn.core.OpenVPN;
 +import de.blinkt.openvpn.core.OpenVPN.ConnectionStatus;
 +import de.blinkt.openvpn.core.OpenVPN.StateListener;
 +import de.blinkt.openvpn.core.OpenVpnService;
 +import de.blinkt.openvpn.core.OpenVpnService.LocalBinder;
 +import de.blinkt.openvpn.core.ProfileManager;
 +import de.blinkt.openvpn.core.VPNLaunchHelper;
 +
 +public class ExternalOpenVPNService extends Service implements StateListener {
 +
 +	final RemoteCallbackList<IOpenVPNStatusCallback> mCallbacks =
 +			new RemoteCallbackList<IOpenVPNStatusCallback>();
 +
 +	private OpenVpnService mService;
 +	private ExternalAppDatabase mExtAppDb;	
 +
 +
 +	private ServiceConnection mConnection = new ServiceConnection() {
 +
 +
 +		@Override
 +		public void onServiceConnected(ComponentName className,
 +				IBinder service) {
 +			// We've bound to LocalService, cast the IBinder and get LocalService instance
 +			LocalBinder binder = (LocalBinder) service;
 +			mService = binder.getService();
 +		}
 +
 +		@Override
 +		public void onServiceDisconnected(ComponentName arg0) {
 +			mService =null;
 +		}
 +
 +	};
 +	
 +	@Override
 +	public void onCreate() {
 +		super.onCreate();
 +		OpenVPN.addStateListener(this);
 +		mExtAppDb = new ExternalAppDatabase(this);
 +
 +		Intent intent = new Intent(getBaseContext(), OpenVpnService.class);
 +		intent.setAction(OpenVpnService.START_SERVICE);
 +
 +		bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
 +	}
 +
 +	private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() {
 +		private boolean 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 true;
 +					}
 +				} catch (NameNotFoundException e) {
 +					// App not found. Remove it from the list
 +					mExtAppDb.removeApp(apppackage);
 +					e.printStackTrace();
 +				}
 +
 +			}
 +			throw new SecurityException("Unauthorized OpenVPN API Caller");
 +		}
 +
 +		@Override
 +		public List<APIVpnProfile> getProfiles() throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			ProfileManager pm = ProfileManager.getInstance(getBaseContext());
 +
 +			List<APIVpnProfile> profiles = new LinkedList<APIVpnProfile>();
 +
 +			for(VpnProfile vp: pm.getProfiles())
 +				profiles.add(new APIVpnProfile(vp.getUUIDString(),vp.mName,vp.mUserEditable));
 +
 +			return profiles;
 +		}
 +
 +		@Override
 +		public void startProfile(String profileUUID) throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			Intent shortVPNIntent = new Intent(Intent.ACTION_MAIN);
 +			shortVPNIntent.setClass(getBaseContext(),de.blinkt.openvpn.LaunchVPN.class);
 +			shortVPNIntent.putExtra(de.blinkt.openvpn.LaunchVPN.EXTRA_KEY,profileUUID);
 +			shortVPNIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 +			startActivity(shortVPNIntent);
 +		}
 +
 +		public void startVPN(String inlineconfig) throws RemoteException {
 +			checkOpenVPNPermission();
 +			
 +			ConfigParser cp = new ConfigParser();
 +			try {
 +				cp.parseConfig(new StringReader(inlineconfig));
 +				VpnProfile vp = cp.convertProfile();
 +				if(vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
 +					throw new RemoteException(getString(vp.checkProfile(getApplicationContext())));
 +
 +
 +				ProfileManager.setTemporaryProfile(vp);
 +				VPNLaunchHelper.startOpenVpn(vp, getBaseContext());
 +
 +
 +			} catch (IOException e) {
 +				throw new RemoteException(e.getMessage());
 +			} catch (ConfigParseError e) {
 +				throw new RemoteException(e.getMessage());
 +			}
 +		}
 +
 +		@Override
 +		public boolean addVPNProfile(String name, String config) throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			ConfigParser cp = new ConfigParser();
 +			try {
 +				cp.parseConfig(new StringReader(config));
 +				VpnProfile vp = cp.convertProfile();
 +				vp.mName = name;
 +				ProfileManager pm = ProfileManager.getInstance(getBaseContext());
 +				pm.addProfile(vp);
 +			} catch (IOException e) {
 +				e.printStackTrace();
 +				return false;
 +			} catch (ConfigParseError e) {
 +				e.printStackTrace();
 +				return false;
 +			}
 +
 +			return true;
 +		}
 +
 +
 +		@Override
 +		public Intent prepare(String packagename) {
 +			if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename))
 +				return null;
 +			
 +			Intent intent = new Intent();
 +			intent.setClass(ExternalOpenVPNService.this, ConfirmDialog.class);
 +			return intent;
 +		}
 +
 +		@Override
 +		public boolean hasPermission() throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			return VpnService.prepare(ExternalOpenVPNService.this)==null;
 +		}
 +
 +
 +		@Override
 +		public void registerStatusCallback(IOpenVPNStatusCallback cb)
 +				throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			if (cb != null) mCallbacks.register(cb);
 +
 +
 +		}
 +
 +		@Override
 +		public void unregisterStatusCallback(IOpenVPNStatusCallback cb)
 +				throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			if (cb != null) mCallbacks.unregister(cb);
 +
 +		}
 +
 +		@Override
 +		public void disconnect() throws RemoteException {
 +			checkOpenVPNPermission();
 +
 +			mService.getManagement().stopVPN();
 +		}
 +	};
 +
 +	@Override
 +	public IBinder onBind(Intent intent) {
 +		return mBinder;
 +	}
 +
 +	@Override
 +	public void onDestroy() {
 +		super.onDestroy();
 +		mCallbacks.kill();
 +		unbindService(mConnection);
 +		OpenVPN.removeStateListener(this);
 +	}
 +
 +	@Override
 +	public void updateState(String state, String logmessage, int resid, ConnectionStatus level) {
 +		// Broadcast to all clients the new value.
 +		final int N = mCallbacks.beginBroadcast();
 +		for (int i=0; i<N; i++) {
 +			try {
 +				mCallbacks.getBroadcastItem(i).newStatus(state,logmessage);
 +			} catch (RemoteException e) {
 +				// The RemoteCallbackList will take care of removing
 +				// the dead object for us.
 +			}
 +		}
 +		mCallbacks.finishBroadcast();
 +	}
 +
 +
 +
 +}
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/api/GrantPermissionsActivity.java b/src/de/blinkt/openvpn/api/GrantPermissionsActivity.java new file mode 100644 index 00000000..659ec24b --- /dev/null +++ b/src/de/blinkt/openvpn/api/GrantPermissionsActivity.java @@ -0,0 +1,26 @@ +package de.blinkt.openvpn.api; + +import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; + +public class GrantPermissionsActivity extends Activity { +	private static final int VPN_PREPARE = 0; + +	@Override +	protected void onStart() { +		super.onStart(); +		Intent i= VpnService.prepare(this); +		if(i==null) +			onActivityResult(VPN_PREPARE, RESULT_OK, null); +		else +			startActivityForResult(i, VPN_PREPARE); +	} +	 +	@Override +	protected void onActivityResult(int requestCode, int resultCode, Intent data) { +		super.onActivityResult(requestCode, resultCode, data); +		setResult(resultCode); +		finish(); +	} +} diff --git a/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl b/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl new file mode 100644 index 00000000..c1e32eac --- /dev/null +++ b/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl @@ -0,0 +1,41 @@ +// IOpenVPNAPIService.aidl
 +package de.blinkt.openvpn.api;
 +
 +import de.blinkt.openvpn.api.APIVpnProfile;
 +import de.blinkt.openvpn.api.IOpenVPNStatusCallback; 
 +
 +import android.content.Intent;
 +import android.os.ParcelFileDescriptor;
 +
 +interface IOpenVPNAPIService {
 +	List<APIVpnProfile> getProfiles();
 +	
 +	void startProfile (String profileUUID);
 +	
 +	/* Use a profile with all certificates etc. embedded */
 +	boolean addVPNProfile (String name, String config);
 +	
 +	/* start a profile using an config */
 +	void startVPN (String inlineconfig);
 +	
 +	/* This permission framework is used  to avoid confused deputy style attack to the VPN
 +	 * calling this will give null if the app is allowed to use the frame and null otherwise */
 +	Intent prepare (String packagename);
 +	
 +	/* Tells the calling app wether we already have permission to avoid calling the activity/flicker */
 +	boolean hasPermission();
 +
 +	/* Disconnect the VPN */
 +    void disconnect();
 +    
 +    /**
 +      * Registers to receive OpenVPN Status Updates
 +      */
 +    void registerStatusCallback(IOpenVPNStatusCallback cb);
 +    
 +    /**
 +     * Remove a previously registered callback interface.
 +     */
 +    void unregisterStatusCallback(IOpenVPNStatusCallback cb);
 +		
 +}
\ No newline at end of file diff --git a/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl b/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl new file mode 100644 index 00000000..11e369c2 --- /dev/null +++ b/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl @@ -0,0 +1,13 @@ +package de.blinkt.openvpn.api;
 +
 +/**
 + * Example of a callback interface used by IRemoteService to send
 + * synchronous notifications back to its clients.  Note that this is a
 + * one-way interface so the server does not block waiting for the client.
 + */
 +oneway interface IOpenVPNStatusCallback {
 +    /**
 +     * Called when the service has a new status for you.
 +     */
 +    void newStatus(String state, String message);
 +}
 diff --git a/src/de/blinkt/openvpn/api/SecurityRemoteException.java b/src/de/blinkt/openvpn/api/SecurityRemoteException.java new file mode 100644 index 00000000..e6011aa3 --- /dev/null +++ b/src/de/blinkt/openvpn/api/SecurityRemoteException.java @@ -0,0 +1,12 @@ +package de.blinkt.openvpn.api;
 +
 +import android.os.RemoteException;
 +
 +public class SecurityRemoteException extends RemoteException {
 +
 +	/**
 +	 * 
 +	 */
 +	private static final long serialVersionUID = 1L;
 +
 +}
 | 
