From 2d0ed30fd65ce6d5832dc857a69c8063cb8b48b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Wed, 14 May 2014 21:07:23 +0200 Subject: Filter R and BuildConfig to use ours. --- app/build.gradle | 1 + .../de/blinkt/openvpn/api/IOpenVPNAPIService.aidl | 98 +- .../blinkt/openvpn/api/IOpenVPNStatusCallback.aidl | 26 +- .../blinkt/openvpn/activities/ConfigConverter.java | 2 +- .../blinkt/openvpn/activities/CreateShortcuts.java | 2 +- .../blinkt/openvpn/activities/DisconnectVPN.java | 2 +- .../de/blinkt/openvpn/activities/FileSelect.java | 2 +- .../de/blinkt/openvpn/activities/LogWindow.java | 2 +- .../de/blinkt/openvpn/activities/MainActivity.java | 2 +- .../blinkt/openvpn/activities/VPNPreferences.java | 2 +- .../java/de/blinkt/openvpn/api/APIVpnProfile.java | 102 +- .../java/de/blinkt/openvpn/api/ConfirmDialog.java | 2 +- .../blinkt/openvpn/api/ExternalOpenVPNService.java | 632 +++++------ .../openvpn/api/SecurityRemoteException.java | 24 +- .../blinkt/openvpn/core/DeviceStateReceiver.java | 486 ++++---- .../java/de/blinkt/openvpn/core/NetworkSpace.java | 2 +- .../java/de/blinkt/openvpn/core/OpenVPNThread.java | 348 +++--- .../openvpn/core/OpenVpnManagementThread.java | 1196 ++++++++++---------- .../de/blinkt/openvpn/core/OpenVpnService.java | 6 +- .../de/blinkt/openvpn/core/ProxyDetection.java | 2 +- .../de/blinkt/openvpn/core/VPNLaunchHelper.java | 2 +- .../java/de/blinkt/openvpn/core/VpnStatus.java | 2 +- .../java/de/blinkt/openvpn/core/X509Utils.java | 2 +- .../de/blinkt/openvpn/fragments/AboutFragment.java | 2 +- .../de/blinkt/openvpn/fragments/FaqFragment.java | 2 +- .../openvpn/fragments/FileSelectionFragment.java | 2 +- .../de/blinkt/openvpn/fragments/InlineFileTab.java | 2 +- .../fragments/OpenVpnPreferencesFragment.java | 96 +- .../blinkt/openvpn/fragments/SendDumpFragment.java | 2 +- .../openvpn/fragments/Settings_Authentication.java | 2 +- .../blinkt/openvpn/fragments/Settings_Basic.java | 4 +- .../de/blinkt/openvpn/fragments/Settings_IP.java | 2 +- .../blinkt/openvpn/fragments/Settings_Obscure.java | 2 +- .../blinkt/openvpn/fragments/Settings_Routing.java | 2 +- .../openvpn/fragments/ShowConfigFragment.java | 2 +- .../de/blinkt/openvpn/views/FileSelectLayout.java | 2 +- .../blinkt/openvpn/views/RemoteCNPreference.java | 2 +- build.gradle | 14 +- 38 files changed, 1546 insertions(+), 1537 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5eb17444..44e48292 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -49,4 +49,5 @@ android { dependencies { androidTestCompile 'com.android.support:support-v4:+' androidTestCompile 'com.jayway.android.robotium:robotium-solo:4.3.1' + compile 'com.intellij:annotations:12.0' } \ No newline at end of file diff --git a/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl b/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl index 794e3aad..2e947d8b 100644 --- a/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl +++ b/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl @@ -1,50 +1,50 @@ -// 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 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 external API and an Intent - * that can be launched to request permissions otherwise */ - Intent prepare (String packagename); - - /** Used to trigger to the Android VPN permission dialog (VPNService.prepare()) in advance, - * if this return null OpenVPN for ANdroid already has the permissions otherwise you can start the returned Intent - * to let OpenVPN for Android request the permission */ - Intent prepareVPNService (); - - /* Disconnect the VPN */ - void disconnect(); - - /* Pause the VPN (same as using the pause feature in the notifcation bar) */ - void pause(); - - /* Resume the VPN (same as using the pause feature in the notifcation bar) */ - void resume(); - - /** - * Registers to receive OpenVPN Status Updates - */ - void registerStatusCallback(IOpenVPNStatusCallback cb); - - /** - * Remove a previously registered callback interface. - */ - void unregisterStatusCallback(IOpenVPNStatusCallback cb); - +// 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 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 external API and an Intent + * that can be launched to request permissions otherwise */ + Intent prepare (String packagename); + + /** Used to trigger to the Android VPN permission dialog (VPNService.prepare()) in advance, + * if this return null OpenVPN for ANdroid already has the permissions otherwise you can start the returned Intent + * to let OpenVPN for Android request the permission */ + Intent prepareVPNService (); + + /* Disconnect the VPN */ + void disconnect(); + + /* Pause the VPN (same as using the pause feature in the notifcation bar) */ + void pause(); + + /* Resume the VPN (same as using the pause feature in the notifcation bar) */ + void resume(); + + /** + * 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/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl b/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl index 1dfa1381..7de84f56 100644 --- a/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl +++ b/app/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl @@ -1,13 +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 uuid, String state, String message, String level); -} +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 uuid, String state, String message, String level); +} diff --git a/app/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java b/app/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java index f870e8a9..2cb79e05 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/ConfigConverter.java @@ -39,7 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Vector; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.ConfigParser.ConfigParseError; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/CreateShortcuts.java b/app/src/main/java/de/blinkt/openvpn/activities/CreateShortcuts.java index 53a829ff..590b7150 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/CreateShortcuts.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/CreateShortcuts.java @@ -11,7 +11,7 @@ import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import de.blinkt.openvpn.LaunchVPN; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ProfileManager; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java index c2d4c599..da011c98 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/DisconnectVPN.java @@ -5,7 +5,7 @@ import android.app.AlertDialog; import android.content.*; import android.os.IBinder; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.core.OpenVpnService; import de.blinkt.openvpn.core.ProfileManager; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/FileSelect.java b/app/src/main/java/de/blinkt/openvpn/activities/FileSelect.java index 511dc736..a30b694c 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/FileSelect.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/FileSelect.java @@ -19,7 +19,7 @@ import android.os.Bundle; import android.os.Environment; import android.util.Base64; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.fragments.FileSelectionFragment; import de.blinkt.openvpn.fragments.InlineFileTab; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java index 27197035..7ed09dd2 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/LogWindow.java @@ -4,7 +4,7 @@ import android.app.Activity; import android.os.Bundle; import android.view.MenuItem; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.fragments.LogFragment; /** diff --git a/app/src/main/java/de/blinkt/openvpn/activities/MainActivity.java b/app/src/main/java/de/blinkt/openvpn/activities/MainActivity.java index b32c80cc..26cd0269 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/MainActivity.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/MainActivity.java @@ -7,7 +7,7 @@ import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.fragments.*; diff --git a/app/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java b/app/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java index 1ebb16b2..1ee9a5f4 100644 --- a/app/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java +++ b/app/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java @@ -14,7 +14,7 @@ import android.preference.PreferenceFragment; import android.view.Menu; import android.view.MenuItem; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.fragments.Settings_Authentication; diff --git a/app/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java b/app/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java index f5591764..a44891ab 100644 --- a/app/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java @@ -1,51 +1,51 @@ -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(); - mUserEditable = in.readInt() != 0; - } - - 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 CREATOR - = new Parcelable.Creator() { - public APIVpnProfile createFromParcel(Parcel in) { - return new APIVpnProfile(in); - } - - public APIVpnProfile[] newArray(int size) { - return new APIVpnProfile[size]; - } - }; - - -} +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(); + mUserEditable = in.readInt() != 0; + } + + 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 CREATOR + = new Parcelable.Creator() { + public APIVpnProfile createFromParcel(Parcel in) { + return new APIVpnProfile(in); + } + + public APIVpnProfile[] newArray(int size) { + return new APIVpnProfile[size]; + } + }; + + +} diff --git a/app/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java b/app/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java index bcab79ed..3856a181 100644 --- a/app/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java +++ b/app/src/main/java/de/blinkt/openvpn/api/ConfirmDialog.java @@ -29,7 +29,7 @@ import android.widget.Button; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class ConfirmDialog extends Activity implements diff --git a/app/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java index 928a85eb..784ec72a 100644 --- a/app/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java @@ -1,317 +1,317 @@ -package de.blinkt.openvpn.api; - -import java.io.IOException; -import java.io.StringReader; -import java.lang.ref.WeakReference; -import java.util.LinkedList; -import java.util.List; - -import android.annotation.TargetApi; -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.*; -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.VpnStatus; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.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; - -@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) -public class ExternalOpenVPNService extends Service implements StateListener { - - private static final int SEND_TOALL = 0; - - final RemoteCallbackList mCallbacks = - new RemoteCallbackList(); - - 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(); - VpnStatus.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); - mHandler.setService(this); - } - - private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() { - - private void 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; - } - } catch (NameNotFoundException e) { - // App not found. Remove it from the list - mExtAppDb.removeApp(apppackage); - } - - } - throw new SecurityException("Unauthorized OpenVPN API Caller"); - } - - @Override - public List getProfiles() throws RemoteException { - checkOpenVPNPermission(); - - ProfileManager pm = ProfileManager.getInstance(getBaseContext()); - - List profiles = new LinkedList(); - - 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) { - VpnStatus.logException(e); - return false; - } catch (ConfigParseError e) { - VpnStatus.logException(e); - 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 Intent prepareVPNService() throws RemoteException { - checkOpenVPNPermission(); - - if (VpnService.prepare(ExternalOpenVPNService.this) == null) - return null; - else - return new Intent(getBaseContext(), GrantPermissionsActivity.class); - } - - - @Override - public void registerStatusCallback(IOpenVPNStatusCallback cb) - throws RemoteException { - checkOpenVPNPermission(); - - if (cb != null) { - cb.newStatus(mMostRecentState.vpnUUID, mMostRecentState.state, - mMostRecentState.logmessage, mMostRecentState.level.name()); - 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(); - if (mService != null && mService.getManagement() != null) - mService.getManagement().stopVPN(); - } - - @Override - public void pause() throws RemoteException { - checkOpenVPNPermission(); - if (mService != null) - mService.userPause(true); - } - - @Override - public void resume() throws RemoteException { - checkOpenVPNPermission(); - if (mService != null) - mService.userPause(false); - - } - }; - - - private UpdateMessage mMostRecentState; - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - @Override - public void onDestroy() { - super.onDestroy(); - mCallbacks.kill(); - unbindService(mConnection); - VpnStatus.removeStateListener(this); - } - - class UpdateMessage { - public String state; - public String logmessage; - public ConnectionStatus level; - public String vpnUUID; - - public UpdateMessage(String state, String logmessage, ConnectionStatus level) { - this.state = state; - this.logmessage = logmessage; - this.level = level; - } - } - - @Override - public void updateState(String state, String logmessage, int resid, ConnectionStatus level) { - mMostRecentState = new UpdateMessage(state, logmessage, level); - if (ProfileManager.getLastConnectedVpn() != null) - mMostRecentState.vpnUUID = ProfileManager.getLastConnectedVpn().getUUIDString(); - - Message msg = mHandler.obtainMessage(SEND_TOALL, mMostRecentState); - msg.sendToTarget(); - - } - - private static final OpenVPNServiceHandler mHandler = new OpenVPNServiceHandler(); - - - static class OpenVPNServiceHandler extends Handler { - WeakReference service = null; - - private void setService(ExternalOpenVPNService eos) { - service = new WeakReference(eos); - } - - @Override - public void handleMessage(Message msg) { - - RemoteCallbackList callbacks; - switch (msg.what) { - case SEND_TOALL: - if (service == null || service.get() == null) - return; - - callbacks = service.get().mCallbacks; - - - // Broadcast to all clients the new value. - final int N = callbacks.beginBroadcast(); - for (int i = 0; i < N; i++) { - try { - sendUpdate(callbacks.getBroadcastItem(i), (UpdateMessage) msg.obj); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing - // the dead object for us. - } - } - callbacks.finishBroadcast(); - break; - } - } - - private void sendUpdate(IOpenVPNStatusCallback broadcastItem, - UpdateMessage um) throws RemoteException { - broadcastItem.newStatus(um.vpnUUID, um.state, um.logmessage, um.level.name()); - } - } - - +package de.blinkt.openvpn.api; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.List; + +import android.annotation.TargetApi; +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.*; +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.ConfigParser.ConfigParseError; +import de.blinkt.openvpn.core.VpnStatus; +import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; +import de.blinkt.openvpn.core.VpnStatus.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; + +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) +public class ExternalOpenVPNService extends Service implements StateListener { + + private static final int SEND_TOALL = 0; + + final RemoteCallbackList mCallbacks = + new RemoteCallbackList(); + + 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(); + VpnStatus.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); + mHandler.setService(this); + } + + private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() { + + private void 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; + } + } catch (NameNotFoundException e) { + // App not found. Remove it from the list + mExtAppDb.removeApp(apppackage); + } + + } + throw new SecurityException("Unauthorized OpenVPN API Caller"); + } + + @Override + public List getProfiles() throws RemoteException { + checkOpenVPNPermission(); + + ProfileManager pm = ProfileManager.getInstance(getBaseContext()); + + List profiles = new LinkedList(); + + 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) { + VpnStatus.logException(e); + return false; + } catch (ConfigParseError e) { + VpnStatus.logException(e); + 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 Intent prepareVPNService() throws RemoteException { + checkOpenVPNPermission(); + + if (VpnService.prepare(ExternalOpenVPNService.this) == null) + return null; + else + return new Intent(getBaseContext(), GrantPermissionsActivity.class); + } + + + @Override + public void registerStatusCallback(IOpenVPNStatusCallback cb) + throws RemoteException { + checkOpenVPNPermission(); + + if (cb != null) { + cb.newStatus(mMostRecentState.vpnUUID, mMostRecentState.state, + mMostRecentState.logmessage, mMostRecentState.level.name()); + 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(); + if (mService != null && mService.getManagement() != null) + mService.getManagement().stopVPN(); + } + + @Override + public void pause() throws RemoteException { + checkOpenVPNPermission(); + if (mService != null) + mService.userPause(true); + } + + @Override + public void resume() throws RemoteException { + checkOpenVPNPermission(); + if (mService != null) + mService.userPause(false); + + } + }; + + + private UpdateMessage mMostRecentState; + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public void onDestroy() { + super.onDestroy(); + mCallbacks.kill(); + unbindService(mConnection); + VpnStatus.removeStateListener(this); + } + + class UpdateMessage { + public String state; + public String logmessage; + public ConnectionStatus level; + public String vpnUUID; + + public UpdateMessage(String state, String logmessage, ConnectionStatus level) { + this.state = state; + this.logmessage = logmessage; + this.level = level; + } + } + + @Override + public void updateState(String state, String logmessage, int resid, ConnectionStatus level) { + mMostRecentState = new UpdateMessage(state, logmessage, level); + if (ProfileManager.getLastConnectedVpn() != null) + mMostRecentState.vpnUUID = ProfileManager.getLastConnectedVpn().getUUIDString(); + + Message msg = mHandler.obtainMessage(SEND_TOALL, mMostRecentState); + msg.sendToTarget(); + + } + + private static final OpenVPNServiceHandler mHandler = new OpenVPNServiceHandler(); + + + static class OpenVPNServiceHandler extends Handler { + WeakReference service = null; + + private void setService(ExternalOpenVPNService eos) { + service = new WeakReference(eos); + } + + @Override + public void handleMessage(Message msg) { + + RemoteCallbackList callbacks; + switch (msg.what) { + case SEND_TOALL: + if (service == null || service.get() == null) + return; + + callbacks = service.get().mCallbacks; + + + // Broadcast to all clients the new value. + final int N = callbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + try { + sendUpdate(callbacks.getBroadcastItem(i), (UpdateMessage) msg.obj); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing + // the dead object for us. + } + } + callbacks.finishBroadcast(); + break; + } + } + + private void sendUpdate(IOpenVPNStatusCallback broadcastItem, + UpdateMessage um) throws RemoteException { + broadcastItem.newStatus(um.vpnUUID, um.state, um.logmessage, um.level.name()); + } + } + + } \ No newline at end of file diff --git a/app/src/main/java/de/blinkt/openvpn/api/SecurityRemoteException.java b/app/src/main/java/de/blinkt/openvpn/api/SecurityRemoteException.java index e6011aa3..08d90e3b 100644 --- a/app/src/main/java/de/blinkt/openvpn/api/SecurityRemoteException.java +++ b/app/src/main/java/de/blinkt/openvpn/api/SecurityRemoteException.java @@ -1,12 +1,12 @@ -package de.blinkt.openvpn.api; - -import android.os.RemoteException; - -public class SecurityRemoteException extends RemoteException { - - /** - * - */ - private static final long serialVersionUID = 1L; - -} +package de.blinkt.openvpn.api; + +import android.os.RemoteException; + +public class SecurityRemoteException extends RemoteException { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java index 41e8ff0a..18c5f1d9 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ b/app/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java @@ -1,243 +1,243 @@ -package de.blinkt.openvpn.core; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.NetworkInfo.State; -import android.preference.PreferenceManager; -import de.blinkt.openvpn.R; -import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; - -import java.util.LinkedList; - -import static de.blinkt.openvpn.core.OpenVPNManagement.pauseReason; - -public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener { - private int lastNetwork = -1; - private OpenVPNManagement mManagement; - - // Window time in s - private final int TRAFFIC_WINDOW = 60; - // Data traffic limit in bytes - private final long TRAFFIC_LIMIT = 64 * 1024; - - - connectState network = connectState.DISCONNECTED; - connectState screen = connectState.SHOULDBECONNECTED; - connectState userpause = connectState.SHOULDBECONNECTED; - - private String lastStateMsg = null; - - enum connectState { - SHOULDBECONNECTED, - PENDINGDISCONNECT, - DISCONNECTED - } - - static class Datapoint { - private Datapoint(long t, long d) { - timestamp = t; - data = d; - } - - long timestamp; - long data; - } - - LinkedList trafficdata = new LinkedList(); - - @Override - public void updateByteCount(long in, long out, long diffIn, long diffOut) { - if (screen != connectState.PENDINGDISCONNECT) - return; - - long total = diffIn + diffOut; - trafficdata.add(new Datapoint(System.currentTimeMillis(), total)); - - while (trafficdata.getFirst().timestamp <= (System.currentTimeMillis() - TRAFFIC_WINDOW * 1000)) { - trafficdata.removeFirst(); - } - - long windowtraffic = 0; - for (Datapoint dp : trafficdata) - windowtraffic += dp.data; - - if (windowtraffic < TRAFFIC_LIMIT) { - screen = connectState.DISCONNECTED; - VpnStatus.logInfo(R.string.screenoff_pause, - OpenVpnService.humanReadableByteCount(TRAFFIC_LIMIT, false), TRAFFIC_WINDOW); - - mManagement.pause(getPauseReason()); - } - } - - - public void userPause(boolean pause) { - if (pause) { - userpause = connectState.DISCONNECTED; - // Check if we should disconnect - mManagement.pause(getPauseReason()); - } else { - boolean wereConnected = shouldBeConnected(); - userpause = connectState.SHOULDBECONNECTED; - if (shouldBeConnected() && !wereConnected) - mManagement.resume(); - else - // Update the reason why we currently paused - mManagement.pause(getPauseReason()); - } - } - - public DeviceStateReceiver(OpenVPNManagement magnagement) { - super(); - mManagement = magnagement; - } - - - @Override - public void onReceive(Context context, Intent intent) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { - networkStateChange(context); - } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { - boolean screenOffPause = prefs.getBoolean("screenoff", false); - - if (screenOffPause) { - if (ProfileManager.getLastConnectedVpn()!=null && !ProfileManager.getLastConnectedVpn().mPersistTun) - VpnStatus.logError(R.string.screen_nopersistenttun); - - screen = connectState.PENDINGDISCONNECT; - fillTrafficData(); - if (network == connectState.DISCONNECTED || userpause == connectState.DISCONNECTED) - screen = connectState.DISCONNECTED; - } - } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { - // Network was disabled because screen off - boolean connected = shouldBeConnected(); - screen = connectState.SHOULDBECONNECTED; - - /* should be connected has changed because the screen is on now, connect the VPN */ - if (shouldBeConnected() != connected) - mManagement.resume(); - else if (!shouldBeConnected()) - /*Update the reason why we are still paused */ - mManagement.pause(getPauseReason()); - - } - } - - - private void fillTrafficData() { - trafficdata.add(new Datapoint(System.currentTimeMillis(), TRAFFIC_LIMIT)); - } - - - public void networkStateChange(Context context) { - NetworkInfo networkInfo = getCurrentNetworkInfo(context); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean sendusr1 = prefs.getBoolean("netchangereconnect", true); - - - String netstatestring; - if (networkInfo == null) { - netstatestring = "not connected"; - } else { - String subtype = networkInfo.getSubtypeName(); - if (subtype == null) - subtype = ""; - String extrainfo = networkInfo.getExtraInfo(); - if (extrainfo == null) - extrainfo = ""; - - /* - if(networkInfo.getType()==android.net.ConnectivityManager.TYPE_WIFI) { - WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - WifiInfo wifiinfo = wifiMgr.getConnectionInfo(); - extrainfo+=wifiinfo.getBSSID(); - - subtype += wifiinfo.getNetworkId(); - }*/ - - - netstatestring = String.format("%2$s %4$s to %1$s %3$s", networkInfo.getTypeName(), - networkInfo.getDetailedState(), extrainfo, subtype); - } - - if (networkInfo != null && networkInfo.getState() == State.CONNECTED) { - int newnet = networkInfo.getType(); - network = connectState.SHOULDBECONNECTED; - - if (lastNetwork != newnet) { - if (screen == connectState.PENDINGDISCONNECT) - screen = connectState.DISCONNECTED; - - if (shouldBeConnected()) { - if (sendusr1) { - if (lastNetwork == -1) { - mManagement.resume(); - } else { - mManagement.reconnect(); - } - } else { - mManagement.networkChange(); - } - } - - - lastNetwork = newnet; - } - } else if (networkInfo == null) { - // Not connected, stop openvpn, set last connected network to no network - lastNetwork = -1; - if (sendusr1) { - network = connectState.DISCONNECTED; - - // Set screen state to be disconnected if disconnect pending - if (screen == connectState.PENDINGDISCONNECT) - screen = connectState.DISCONNECTED; - - mManagement.pause(getPauseReason()); - } - } - - - if (!netstatestring.equals(lastStateMsg)) - VpnStatus.logInfo(R.string.netstatus, netstatestring); - lastStateMsg = netstatestring; - - } - - public boolean isUserPaused() { - return userpause == connectState.DISCONNECTED; - } - - private boolean shouldBeConnected() { - return (screen == connectState.SHOULDBECONNECTED && userpause == connectState.SHOULDBECONNECTED && - network == connectState.SHOULDBECONNECTED); - } - - private pauseReason getPauseReason() { - if (userpause == connectState.DISCONNECTED) - return pauseReason.userPause; - - if (screen == connectState.DISCONNECTED) - return pauseReason.screenOff; - - if (network == connectState.DISCONNECTED) - return pauseReason.noNetwork; - - return pauseReason.userPause; - } - - private NetworkInfo getCurrentNetworkInfo(Context context) { - ConnectivityManager conn = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - - return conn.getActiveNetworkInfo(); - } -} +package de.blinkt.openvpn.core; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.NetworkInfo.State; +import android.preference.PreferenceManager; +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; + +import java.util.LinkedList; + +import static de.blinkt.openvpn.core.OpenVPNManagement.pauseReason; + +public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener { + private int lastNetwork = -1; + private OpenVPNManagement mManagement; + + // Window time in s + private final int TRAFFIC_WINDOW = 60; + // Data traffic limit in bytes + private final long TRAFFIC_LIMIT = 64 * 1024; + + + connectState network = connectState.DISCONNECTED; + connectState screen = connectState.SHOULDBECONNECTED; + connectState userpause = connectState.SHOULDBECONNECTED; + + private String lastStateMsg = null; + + enum connectState { + SHOULDBECONNECTED, + PENDINGDISCONNECT, + DISCONNECTED + } + + static class Datapoint { + private Datapoint(long t, long d) { + timestamp = t; + data = d; + } + + long timestamp; + long data; + } + + LinkedList trafficdata = new LinkedList(); + + @Override + public void updateByteCount(long in, long out, long diffIn, long diffOut) { + if (screen != connectState.PENDINGDISCONNECT) + return; + + long total = diffIn + diffOut; + trafficdata.add(new Datapoint(System.currentTimeMillis(), total)); + + while (trafficdata.getFirst().timestamp <= (System.currentTimeMillis() - TRAFFIC_WINDOW * 1000)) { + trafficdata.removeFirst(); + } + + long windowtraffic = 0; + for (Datapoint dp : trafficdata) + windowtraffic += dp.data; + + if (windowtraffic < TRAFFIC_LIMIT) { + screen = connectState.DISCONNECTED; + VpnStatus.logInfo(R.string.screenoff_pause, + OpenVpnService.humanReadableByteCount(TRAFFIC_LIMIT, false), TRAFFIC_WINDOW); + + mManagement.pause(getPauseReason()); + } + } + + + public void userPause(boolean pause) { + if (pause) { + userpause = connectState.DISCONNECTED; + // Check if we should disconnect + mManagement.pause(getPauseReason()); + } else { + boolean wereConnected = shouldBeConnected(); + userpause = connectState.SHOULDBECONNECTED; + if (shouldBeConnected() && !wereConnected) + mManagement.resume(); + else + // Update the reason why we currently paused + mManagement.pause(getPauseReason()); + } + } + + public DeviceStateReceiver(OpenVPNManagement magnagement) { + super(); + mManagement = magnagement; + } + + + @Override + public void onReceive(Context context, Intent intent) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + + if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { + networkStateChange(context); + } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + boolean screenOffPause = prefs.getBoolean("screenoff", false); + + if (screenOffPause) { + if (ProfileManager.getLastConnectedVpn()!=null && !ProfileManager.getLastConnectedVpn().mPersistTun) + VpnStatus.logError(R.string.screen_nopersistenttun); + + screen = connectState.PENDINGDISCONNECT; + fillTrafficData(); + if (network == connectState.DISCONNECTED || userpause == connectState.DISCONNECTED) + screen = connectState.DISCONNECTED; + } + } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { + // Network was disabled because screen off + boolean connected = shouldBeConnected(); + screen = connectState.SHOULDBECONNECTED; + + /* should be connected has changed because the screen is on now, connect the VPN */ + if (shouldBeConnected() != connected) + mManagement.resume(); + else if (!shouldBeConnected()) + /*Update the reason why we are still paused */ + mManagement.pause(getPauseReason()); + + } + } + + + private void fillTrafficData() { + trafficdata.add(new Datapoint(System.currentTimeMillis(), TRAFFIC_LIMIT)); + } + + + public void networkStateChange(Context context) { + NetworkInfo networkInfo = getCurrentNetworkInfo(context); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean sendusr1 = prefs.getBoolean("netchangereconnect", true); + + + String netstatestring; + if (networkInfo == null) { + netstatestring = "not connected"; + } else { + String subtype = networkInfo.getSubtypeName(); + if (subtype == null) + subtype = ""; + String extrainfo = networkInfo.getExtraInfo(); + if (extrainfo == null) + extrainfo = ""; + + /* + if(networkInfo.getType()==android.net.ConnectivityManager.TYPE_WIFI) { + WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiinfo = wifiMgr.getConnectionInfo(); + extrainfo+=wifiinfo.getBSSID(); + + subtype += wifiinfo.getNetworkId(); + }*/ + + + netstatestring = String.format("%2$s %4$s to %1$s %3$s", networkInfo.getTypeName(), + networkInfo.getDetailedState(), extrainfo, subtype); + } + + if (networkInfo != null && networkInfo.getState() == State.CONNECTED) { + int newnet = networkInfo.getType(); + network = connectState.SHOULDBECONNECTED; + + if (lastNetwork != newnet) { + if (screen == connectState.PENDINGDISCONNECT) + screen = connectState.DISCONNECTED; + + if (shouldBeConnected()) { + if (sendusr1) { + if (lastNetwork == -1) { + mManagement.resume(); + } else { + mManagement.reconnect(); + } + } else { + mManagement.networkChange(); + } + } + + + lastNetwork = newnet; + } + } else if (networkInfo == null) { + // Not connected, stop openvpn, set last connected network to no network + lastNetwork = -1; + if (sendusr1) { + network = connectState.DISCONNECTED; + + // Set screen state to be disconnected if disconnect pending + if (screen == connectState.PENDINGDISCONNECT) + screen = connectState.DISCONNECTED; + + mManagement.pause(getPauseReason()); + } + } + + + if (!netstatestring.equals(lastStateMsg)) + VpnStatus.logInfo(R.string.netstatus, netstatestring); + lastStateMsg = netstatestring; + + } + + public boolean isUserPaused() { + return userpause == connectState.DISCONNECTED; + } + + private boolean shouldBeConnected() { + return (screen == connectState.SHOULDBECONNECTED && userpause == connectState.SHOULDBECONNECTED && + network == connectState.SHOULDBECONNECTED); + } + + private pauseReason getPauseReason() { + if (userpause == connectState.DISCONNECTED) + return pauseReason.userPause; + + if (screen == connectState.DISCONNECTED) + return pauseReason.screenOff; + + if (network == connectState.DISCONNECTED) + return pauseReason.noNetwork; + + return pauseReason.userPause; + } + + private NetworkInfo getCurrentNetworkInfo(Context context) { + ConnectivityManager conn = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); + + return conn.getActiveNetworkInfo(); + } +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java index afd01184..990e70d8 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java +++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java @@ -9,7 +9,7 @@ import java.math.BigInteger; import java.net.Inet6Address; import java.util.*; -import de.blinkt.openvpn.BuildConfig; +import se.leap.bitmaskclient.BuildConfig; public class NetworkSpace { diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index dacd41c9..67c24884 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -1,174 +1,174 @@ -package de.blinkt.openvpn.core; - -import android.util.Log; -import de.blinkt.openvpn.R; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.LogItem; - -import java.io.*; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class OpenVPNThread implements Runnable { - private static final String DUMP_PATH_STRING = "Dump path: "; - private static final String TAG = "OpenVPN"; - public static final int M_FATAL = (1 << 4); - public static final int M_NONFATAL = (1 << 5); - public static final int M_WARN = (1 << 6); - public static final int M_DEBUG = (1 << 7); - private String[] mArgv; - private Process mProcess; - private String mNativeDir; - private OpenVpnService mService; - private String mDumpPath; - private Map mProcessEnv; - - public OpenVPNThread(OpenVpnService service,String[] argv, Map processEnv, String nativelibdir) - { - mArgv = argv; - mNativeDir = nativelibdir; - mService = service; - mProcessEnv = processEnv; - } - - public void stopProcess() { - mProcess.destroy(); - } - - - - @Override - public void run() { - try { - Log.i(TAG, "Starting openvpn"); - startOpenVPNThreadArgs(mArgv, mProcessEnv); - Log.i(TAG, "Giving up"); - } catch (Exception e) { - VpnStatus.logException("Starting OpenVPN Thread" ,e); - Log.e(TAG, "OpenVPNThread Got " + e.toString()); - } finally { - int exitvalue = 0; - try { - if (mProcess!=null) - exitvalue = mProcess.waitFor(); - } catch ( IllegalThreadStateException ite) { - VpnStatus.logError("Illegal Thread state: " + ite.getLocalizedMessage()); - } catch (InterruptedException ie) { - VpnStatus.logError("InterruptedException: " + ie.getLocalizedMessage()); - } - if( exitvalue != 0) - VpnStatus.logError("Process exited with exit value " + exitvalue); - - VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); - if(mDumpPath!=null) { - try { - BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log")); - SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.GERMAN); - for(LogItem li : VpnStatus.getlogbuffer()){ - String time = timeformat.format(new Date(li.getLogtime())); - logout.write(time +" " + li.getString(mService) + "\n"); - } - logout.close(); - VpnStatus.logError(R.string.minidump_generated); - } catch (IOException e) { - VpnStatus.logError("Writing minidump log: " + e.getLocalizedMessage()); - } - } - - mService.processDied(); - Log.i(TAG, "Exiting"); - } - } - - private void startOpenVPNThreadArgs(String[] argv, Map env) { - LinkedList argvlist = new LinkedList(); - - Collections.addAll(argvlist, argv); - - ProcessBuilder pb = new ProcessBuilder(argvlist); - // Hack O rama - - String lbpath = genLibraryPath(argv, pb); - - pb.environment().put("LD_LIBRARY_PATH", lbpath); - - // Add extra variables - for(Entry e:env.entrySet()){ - pb.environment().put(e.getKey(), e.getValue()); - } - pb.redirectErrorStream(true); - try { - mProcess = pb.start(); - // Close the output, since we don't need it - mProcess.getOutputStream().close(); - InputStream in = mProcess.getInputStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - - while(true) { - String logline = br.readLine(); - if(logline==null) - return; - - if (logline.startsWith(DUMP_PATH_STRING)) - mDumpPath = logline.substring(DUMP_PATH_STRING.length()); - - - // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com' - - Pattern p = Pattern.compile("(\\d+).(\\d+) ([0-9a-f])+ (.*)"); - Matcher m = p.matcher(logline); - if(m.matches()) { - int flags = Integer.parseInt(m.group(3),16); - String msg = m.group(4); - int logLevel = flags & 0x0F; - - VpnStatus.LogLevel logStatus = VpnStatus.LogLevel.INFO; - - if ((flags & M_FATAL) != 0) - logStatus = VpnStatus.LogLevel.ERROR; - else if ((flags & M_NONFATAL)!=0) - logStatus = VpnStatus.LogLevel.WARNING; - else if ((flags & M_WARN)!=0) - logStatus = VpnStatus.LogLevel.WARNING; - else if ((flags & M_DEBUG)!=0) - logStatus = VpnStatus.LogLevel.VERBOSE; - - if (msg.startsWith("MANAGEMENT: CMD")) - logLevel = Math.max(4, logLevel); - - - VpnStatus.logMessageOpenVPN(logStatus,logLevel,msg); - } else { - VpnStatus.logInfo("P:" + logline); - } - } - - - } catch (IOException e) { - VpnStatus.logException("Error reading from output of OpenVPN process" , e); - stopProcess(); - } - - - } - - private String genLibraryPath(String[] argv, ProcessBuilder pb) { - // Hack until I find a good way to get the real library path - String applibpath = argv[0].replace("/cache/" + VpnProfile.MINIVPN , "/lib"); - - String lbpath = pb.environment().get("LD_LIBRARY_PATH"); - if(lbpath==null) - lbpath = applibpath; - else - lbpath = lbpath + ":" + applibpath; - - if (!applibpath.equals(mNativeDir)) { - lbpath = lbpath + ":" + mNativeDir; - } - return lbpath; - } -} +package de.blinkt.openvpn.core; + +import android.util.Log; +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; +import de.blinkt.openvpn.core.VpnStatus.LogItem; + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class OpenVPNThread implements Runnable { + private static final String DUMP_PATH_STRING = "Dump path: "; + private static final String TAG = "OpenVPN"; + public static final int M_FATAL = (1 << 4); + public static final int M_NONFATAL = (1 << 5); + public static final int M_WARN = (1 << 6); + public static final int M_DEBUG = (1 << 7); + private String[] mArgv; + private Process mProcess; + private String mNativeDir; + private OpenVpnService mService; + private String mDumpPath; + private Map mProcessEnv; + + public OpenVPNThread(OpenVpnService service,String[] argv, Map processEnv, String nativelibdir) + { + mArgv = argv; + mNativeDir = nativelibdir; + mService = service; + mProcessEnv = processEnv; + } + + public void stopProcess() { + mProcess.destroy(); + } + + + + @Override + public void run() { + try { + Log.i(TAG, "Starting openvpn"); + startOpenVPNThreadArgs(mArgv, mProcessEnv); + Log.i(TAG, "Giving up"); + } catch (Exception e) { + VpnStatus.logException("Starting OpenVPN Thread" ,e); + Log.e(TAG, "OpenVPNThread Got " + e.toString()); + } finally { + int exitvalue = 0; + try { + if (mProcess!=null) + exitvalue = mProcess.waitFor(); + } catch ( IllegalThreadStateException ite) { + VpnStatus.logError("Illegal Thread state: " + ite.getLocalizedMessage()); + } catch (InterruptedException ie) { + VpnStatus.logError("InterruptedException: " + ie.getLocalizedMessage()); + } + if( exitvalue != 0) + VpnStatus.logError("Process exited with exit value " + exitvalue); + + VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); + if(mDumpPath!=null) { + try { + BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log")); + SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.GERMAN); + for(LogItem li : VpnStatus.getlogbuffer()){ + String time = timeformat.format(new Date(li.getLogtime())); + logout.write(time +" " + li.getString(mService) + "\n"); + } + logout.close(); + VpnStatus.logError(R.string.minidump_generated); + } catch (IOException e) { + VpnStatus.logError("Writing minidump log: " + e.getLocalizedMessage()); + } + } + + mService.processDied(); + Log.i(TAG, "Exiting"); + } + } + + private void startOpenVPNThreadArgs(String[] argv, Map env) { + LinkedList argvlist = new LinkedList(); + + Collections.addAll(argvlist, argv); + + ProcessBuilder pb = new ProcessBuilder(argvlist); + // Hack O rama + + String lbpath = genLibraryPath(argv, pb); + + pb.environment().put("LD_LIBRARY_PATH", lbpath); + + // Add extra variables + for(Entry e:env.entrySet()){ + pb.environment().put(e.getKey(), e.getValue()); + } + pb.redirectErrorStream(true); + try { + mProcess = pb.start(); + // Close the output, since we don't need it + mProcess.getOutputStream().close(); + InputStream in = mProcess.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + + while(true) { + String logline = br.readLine(); + if(logline==null) + return; + + if (logline.startsWith(DUMP_PATH_STRING)) + mDumpPath = logline.substring(DUMP_PATH_STRING.length()); + + + // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com' + + Pattern p = Pattern.compile("(\\d+).(\\d+) ([0-9a-f])+ (.*)"); + Matcher m = p.matcher(logline); + if(m.matches()) { + int flags = Integer.parseInt(m.group(3),16); + String msg = m.group(4); + int logLevel = flags & 0x0F; + + VpnStatus.LogLevel logStatus = VpnStatus.LogLevel.INFO; + + if ((flags & M_FATAL) != 0) + logStatus = VpnStatus.LogLevel.ERROR; + else if ((flags & M_NONFATAL)!=0) + logStatus = VpnStatus.LogLevel.WARNING; + else if ((flags & M_WARN)!=0) + logStatus = VpnStatus.LogLevel.WARNING; + else if ((flags & M_DEBUG)!=0) + logStatus = VpnStatus.LogLevel.VERBOSE; + + if (msg.startsWith("MANAGEMENT: CMD")) + logLevel = Math.max(4, logLevel); + + + VpnStatus.logMessageOpenVPN(logStatus,logLevel,msg); + } else { + VpnStatus.logInfo("P:" + logline); + } + } + + + } catch (IOException e) { + VpnStatus.logException("Error reading from output of OpenVPN process" , e); + stopProcess(); + } + + + } + + private String genLibraryPath(String[] argv, ProcessBuilder pb) { + // Hack until I find a good way to get the real library path + String applibpath = argv[0].replace("/cache/" + VpnProfile.MINIVPN , "/lib"); + + String lbpath = pb.environment().get("LD_LIBRARY_PATH"); + if(lbpath==null) + lbpath = applibpath; + else + lbpath = lbpath + ":" + applibpath; + + if (!applibpath.equals(mNativeDir)) { + lbpath = lbpath + ":" + mNativeDir; + } + return lbpath; + } +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index 6ef41e1b..4cba4f5f 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -1,598 +1,598 @@ -package de.blinkt.openvpn.core; - -import android.content.Context; -import android.content.SharedPreferences; -import android.net.LocalServerSocket; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; -import android.os.ParcelFileDescriptor; -import android.preference.PreferenceManager; -import android.util.Log; - -import org.jetbrains.annotations.NotNull; - -import de.blinkt.openvpn.R; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.*; - -public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { - - private static final String TAG = "openvpn"; - private LocalSocket mSocket; - private VpnProfile mProfile; - private OpenVpnService mOpenVPNService; - private LinkedList mFDList=new LinkedList(); - private LocalServerSocket mServerSocket; - private boolean mReleaseHold=true; - private boolean mWaitingForRelease=false; - private long mLastHoldRelease=0; - - private static Vector active=new Vector(); - private LocalSocket mServerSocketLocal; - - private pauseReason lastPauseReason = pauseReason.noNetwork; - - public OpenVpnManagementThread(VpnProfile profile, OpenVpnService openVpnService) { - mProfile = profile; - mOpenVPNService = openVpnService; - - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(openVpnService); - boolean managemeNetworkState = prefs.getBoolean("netchangereconnect", true); - if(managemeNetworkState) - mReleaseHold=false; - - } - - public boolean openManagementInterface(@NotNull Context c) { - // Could take a while to open connection - int tries=8; - - String socketName = (c.getCacheDir().getAbsolutePath() + "/" + "mgmtsocket"); - // The mServerSocketLocal is transferred to the LocalServerSocket, ignore warning - - mServerSocketLocal = new LocalSocket(); - - while(tries > 0 && !mServerSocketLocal.isConnected()) { - try { - mServerSocketLocal.bind(new LocalSocketAddress(socketName, - LocalSocketAddress.Namespace.FILESYSTEM)); - } catch (IOException e) { - // wait 300 ms before retrying - try { Thread.sleep(300); - } catch (InterruptedException e1) { - } - - } - tries--; - } - - try { - - mServerSocket = new LocalServerSocket(mServerSocketLocal.getFileDescriptor()); - return true; - } catch (IOException e) { - VpnStatus.logException(e); - } - return false; - - - } - - public void managmentCommand(String cmd) { - try { - if(mSocket!=null && mSocket.getOutputStream() !=null) { - mSocket.getOutputStream().write(cmd.getBytes()); - mSocket.getOutputStream().flush(); - } - }catch (IOException e) { - // Ignore socket stack traces - } - } - - - @Override - public void run() { - byte [] buffer =new byte[2048]; - // mSocket.setSoTimeout(5); // Setting a timeout cannot be that bad - - String pendingInput=""; - active.add(this); - - try { - // Wait for a client to connect - mSocket= mServerSocket.accept(); - InputStream instream = mSocket.getInputStream(); - // Close the management socket after client connected - - mServerSocket.close(); - // Closing one of the two sockets also closes the other - //mServerSocketLocal.close(); - - while(true) { - int numbytesread = instream.read(buffer); - if(numbytesread==-1) - return; - - FileDescriptor[] fds = null; - try { - fds = mSocket.getAncillaryFileDescriptors(); - } catch (IOException e) { - VpnStatus.logException("Error reading fds from socket", e); - } - if(fds!=null){ - Collections.addAll(mFDList, fds); - } - - String input = new String(buffer,0,numbytesread,"UTF-8"); - - pendingInput += input; - - pendingInput=processInput(pendingInput); - - - - } - } catch (IOException e) { - if (!e.getMessage().equals("socket closed")) - VpnStatus.logException(e); - } - active.remove(this); - } - - //! Hack O Rama 2000! - private void protectFileDescriptor(FileDescriptor fd) { - Exception exp; - try { - Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$"); - int fdint = (Integer) getInt.invoke(fd); - - // You can even get more evil by parsing toString() and extract the int from that :) - - boolean result = mOpenVPNService.protect(fdint); - if (!result) - VpnStatus.logWarning("Could not protect VPN socket"); - - - //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint); - //pfd.close(); - NativeUtils.jniclose(fdint); - return; - } catch (NoSuchMethodException e) { - exp =e; - } catch (IllegalArgumentException e) { - exp =e; - } catch (IllegalAccessException e) { - exp =e; - } catch (InvocationTargetException e) { - exp =e; - } catch (NullPointerException e) { - exp =e; - } - - Log.d("Openvpn", "Failed to retrieve fd from socket: " + fd); - VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")" , exp); - } - - private String processInput(String pendingInput) { - - - while(pendingInput.contains("\n")) { - String[] tokens = pendingInput.split("\\r?\\n", 2); - processCommand(tokens[0]); - if(tokens.length == 1) - // No second part, newline was at the end - pendingInput=""; - else - pendingInput=tokens[1]; - } - return pendingInput; - } - - - private void processCommand(String command) { - //Log.i(TAG, "Line from managment" + command); - - - if (command.startsWith(">") && command.contains(":")) { - String[] parts = command.split(":",2); - String cmd = parts[0].substring(1); - String argument = parts[1]; - - - if(cmd.equals("INFO")) { - /* Ignore greeting from management */ - return; - }else if (cmd.equals("PASSWORD")) { - processPWCommand(argument); - } else if (cmd.equals("HOLD")) { - handleHold(); - } else if (cmd.equals("NEED-OK")) { - processNeedCommand(argument); - } else if (cmd.equals("BYTECOUNT")){ - processByteCount(argument); - } else if (cmd.equals("STATE")) { - processState(argument); - } else if (cmd.equals("PROXY")) { - processProxyCMD(argument); - } else if (cmd.equals("LOG")) { - processLogMessage(argument); - } else if (cmd.equals("RSA_SIGN")) { - processSignCommand(argument); - } else { - VpnStatus.logWarning("MGMT: Got unrecognized command" + command); - Log.i(TAG, "Got unrecognized command" + command); - } - } else if (command.startsWith("SUCCESS:")) { - /* Ignore this kind of message too */ - return; - } else if (command.startsWith("PROTECTFD: ")) { - FileDescriptor fdtoprotect = mFDList.pollFirst(); - if (fdtoprotect!=null) - protectFileDescriptor(fdtoprotect); - } else { - Log.i(TAG, "Got unrecognized line from managment" + command); - VpnStatus.logWarning("MGMT: Got unrecognized line from management:" + command); - } - } - - private void processLogMessage(String argument) { - String[] args = argument.split(",",4); - // 0 unix time stamp - // 1 log level N,I,E etc. - /* - (b) zero or more message flags in a single string: - I -- informational - F -- fatal error - N -- non-fatal error - W -- warning - D -- debug, and - */ - // 2 log message - - Log.d("OpenVPN", argument); - - VpnStatus.LogLevel level; - if (args[1].equals("I")) { - level = VpnStatus.LogLevel.INFO; - } else if (args[1].equals("W")) { - level = VpnStatus.LogLevel.WARNING; - } else if (args[1].equals("D")) { - level = VpnStatus.LogLevel.VERBOSE; - } else if (args[1].equals("F")) { - level = VpnStatus.LogLevel.ERROR; - } else { - level = VpnStatus.LogLevel.INFO; - } - - int ovpnlevel = Integer.parseInt(args[2]) & 0x0F; - String msg = args[3]; - - if (msg.startsWith("MANAGEMENT: CMD")) - ovpnlevel = Math.max(4, ovpnlevel); - - VpnStatus.logMessageOpenVPN(level,ovpnlevel, msg); - } - - private void handleHold() { - if(mReleaseHold) { - releaseHoldCmd(); - } else { - mWaitingForRelease=true; - - VpnStatus.updateStatePause(lastPauseReason); - - - } - } - private void releaseHoldCmd() { - if ((System.currentTimeMillis()- mLastHoldRelease) < 5000) { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - } - - } - mWaitingForRelease=false; - mLastHoldRelease = System.currentTimeMillis(); - managmentCommand("hold release\n"); - managmentCommand("bytecount " + mBytecountInterval + "\n"); - managmentCommand("state on\n"); - //managmentCommand("log on all\n"); - } - - public void releaseHold() { - mReleaseHold=true; - if(mWaitingForRelease) - releaseHoldCmd(); - - } - - private void processProxyCMD(String argument) { - String[] args = argument.split(",",3); - SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile); - - - if(args.length >= 2) { - String proto = args[1]; - if(proto.equals("UDP")) { - proxyaddr=null; - } - } - - if(proxyaddr instanceof InetSocketAddress ){ - InetSocketAddress isa = (InetSocketAddress) proxyaddr; - - VpnStatus.logInfo(R.string.using_proxy, isa.getHostName(), isa.getPort()); - - String proxycmd = String.format(Locale.ENGLISH,"proxy HTTP %s %d\n", isa.getHostName(),isa.getPort()); - managmentCommand(proxycmd); - } else { - managmentCommand("proxy NONE\n"); - } - - } - private void processState(String argument) { - String[] args = argument.split(",",3); - String currentstate = args[1]; - - if(args[2].equals(",,")) - VpnStatus.updateStateString(currentstate, ""); - else - VpnStatus.updateStateString(currentstate, args[2]); - } - - - private void processByteCount(String argument) { - // >BYTECOUNT:{BYTES_IN},{BYTES_OUT} - int comma = argument.indexOf(','); - long in = Long.parseLong(argument.substring(0, comma)); - long out = Long.parseLong(argument.substring(comma+1)); - - VpnStatus.updateByteCount(in, out); - - } - - - - private void processNeedCommand(String argument) { - int p1 =argument.indexOf('\''); - int p2 = argument.indexOf('\'',p1+1); - - String needed = argument.substring(p1+1, p2); - String extra = argument.split(":",2)[1]; - - String status = "ok"; - - - if (needed.equals("PROTECTFD")) { - FileDescriptor fdtoprotect = mFDList.pollFirst(); - protectFileDescriptor(fdtoprotect); - } else if (needed.equals("DNSSERVER")) { - mOpenVPNService.addDNS(extra); - }else if (needed.equals("DNSDOMAIN")){ - mOpenVPNService.setDomain(extra); - } else if (needed.equals("ROUTE")) { - String[] routeparts = extra.split(" "); - - /* - buf_printf (&out, "%s %s %s dev %s", network, netmask, gateway, rgi->iface); - else - buf_printf (&out, "%s %s %s", network, netmask, gateway); - */ - - if(routeparts.length==5) { - assert(routeparts[3].equals("dev")); - mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]); - } else if (routeparts.length >= 3) { - mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null); - } else { - VpnStatus.logError("Unrecognized ROUTE cmd:" + Arrays.toString(routeparts) + " | " + argument); - } - - } else if (needed.equals("ROUTE6")) { - String[] routeparts = extra.split(" "); - mOpenVPNService.addRoutev6(routeparts[0],routeparts[1]); - } else if (needed.equals("IFCONFIG")) { - String[] ifconfigparts = extra.split(" "); - int mtu = Integer.parseInt(ifconfigparts[2]); - mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1],mtu,ifconfigparts[3]); - } else if (needed.equals("IFCONFIG6")) { - mOpenVPNService.setLocalIPv6(extra); - - } else if (needed.equals("PERSIST_TUN_ACTION")) { - // check if tun cfg stayed the same - status = mOpenVPNService.getTunReopenStatus(); - } else if (needed.equals("OPENTUN")) { - if(sendTunFD(needed,extra)) - return; - else - status="cancel"; - // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :( - - } else { - Log.e(TAG,"Unkown needok command " + argument); - return; - } - - String cmd = String.format("needok '%s' %s\n", needed, status); - managmentCommand(cmd); - } - - private boolean sendTunFD (String needed, String extra) { - Exception exp; - if(!extra.equals("tun")) { - // We only support tun - VpnStatus.logError(String.format("Device type %s requested, but only tun is possible with the Android API, sorry!",extra)); - - return false; - } - ParcelFileDescriptor pfd = mOpenVPNService.openTun(); - if(pfd==null) - return false; - - Method setInt; - int fdint = pfd.getFd(); - try { - setInt = FileDescriptor.class.getDeclaredMethod("setInt$",int.class); - FileDescriptor fdtosend = new FileDescriptor(); - - setInt.invoke(fdtosend,fdint); - - FileDescriptor[] fds = {fdtosend}; - mSocket.setFileDescriptorsForSend(fds); - - // Trigger a send so we can close the fd on our side of the channel - // The API documentation fails to mention that it will not reset the file descriptor to - // be send and will happily send the file descriptor on every write ... - String cmd = String.format("needok '%s' %s\n", needed, "ok"); - managmentCommand(cmd); - - // Set the FileDescriptor to null to stop this mad behavior - mSocket.setFileDescriptorsForSend(null); - - pfd.close(); - - return true; - } catch (NoSuchMethodException e) { - exp =e; - } catch (IllegalArgumentException e) { - exp =e; - } catch (IllegalAccessException e) { - exp =e; - } catch (InvocationTargetException e) { - exp =e; - } catch (IOException e) { - exp =e; - } - VpnStatus.logException("Could not send fd over socket" , exp); - - return false; - } - - private void processPWCommand(String argument) { - //argument has the form Need 'Private Key' password - // or ">PASSWORD:Verification Failed: '%s' ['%s']" - String needed; - - - - try{ - - int p1 = argument.indexOf('\''); - int p2 = argument.indexOf('\'',p1+1); - needed = argument.substring(p1+1, p2); - if (argument.startsWith("Verification Failed")) { - proccessPWFailed(needed, argument.substring(p2+1)); - return; - } - } catch (StringIndexOutOfBoundsException sioob) { - VpnStatus.logError("Could not parse management Password command: " + argument); - return; - } - - String pw=null; - - if(needed.equals("Private Key")) { - pw = mProfile.getPasswordPrivateKey(); - } else if (needed.equals("Auth")) { - String usercmd = String.format("username '%s' %s\n", - needed, VpnProfile.openVpnEscape(mProfile.mUsername)); - managmentCommand(usercmd); - pw = mProfile.getPasswordAuth(); - } - if(pw!=null) { - String cmd = String.format("password '%s' %s\n", needed, VpnProfile.openVpnEscape(pw)); - managmentCommand(cmd); - } else { - VpnStatus.logError(String.format("Openvpn requires Authentication type '%s' but no password/key information available", needed)); - } - - } - - - - - private void proccessPWFailed(String needed, String args) { - VpnStatus.updateStateString("AUTH_FAILED", needed + args, R.string.state_auth_failed, ConnectionStatus.LEVEL_AUTH_FAILED); - } - - - private static boolean stopOpenVPN() { - boolean sendCMD=false; - for (OpenVpnManagementThread mt: active){ - mt.managmentCommand("signal SIGINT\n"); - sendCMD=true; - try { - if(mt.mSocket !=null) - mt.mSocket.close(); - } catch (IOException e) { - // Ignore close error on already closed socket - } - } - return sendCMD; - } - - @Override - public void networkChange() { - if(!mWaitingForRelease) - managmentCommand("network-change\n"); - } - - public void signalusr1() { - mReleaseHold=false; - - if(!mWaitingForRelease) - managmentCommand("signal SIGUSR1\n"); - else - // If signalusr1 is called update the state string - // if there is another for stopping - VpnStatus.updateStatePause(lastPauseReason); - } - - public void reconnect() { - signalusr1(); - releaseHold(); - } - - private void processSignCommand(String b64data) { - - String signed_string = mProfile.getSignedData(b64data); - if(signed_string==null) { - managmentCommand("rsa-sig\n"); - managmentCommand("\nEND\n"); - stopOpenVPN(); - return; - } - managmentCommand("rsa-sig\n"); - managmentCommand(signed_string); - managmentCommand("\nEND\n"); - } - - @Override - public void pause (pauseReason reason) { - lastPauseReason = reason; - signalusr1(); - } - - @Override - public void resume() { - releaseHold(); - /* Reset the reason why we are disconnected */ - lastPauseReason = pauseReason.noNetwork; - } - - @Override - public boolean stopVPN() { - return stopOpenVPN(); - } -} +package de.blinkt.openvpn.core; + +import android.content.Context; +import android.content.SharedPreferences; +import android.net.LocalServerSocket; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; +import android.os.ParcelFileDescriptor; +import android.preference.PreferenceManager; +import android.util.Log; + +import org.jetbrains.annotations.NotNull; + +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.*; + +public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { + + private static final String TAG = "openvpn"; + private LocalSocket mSocket; + private VpnProfile mProfile; + private OpenVpnService mOpenVPNService; + private LinkedList mFDList=new LinkedList(); + private LocalServerSocket mServerSocket; + private boolean mReleaseHold=true; + private boolean mWaitingForRelease=false; + private long mLastHoldRelease=0; + + private static Vector active=new Vector(); + private LocalSocket mServerSocketLocal; + + private pauseReason lastPauseReason = pauseReason.noNetwork; + + public OpenVpnManagementThread(VpnProfile profile, OpenVpnService openVpnService) { + mProfile = profile; + mOpenVPNService = openVpnService; + + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(openVpnService); + boolean managemeNetworkState = prefs.getBoolean("netchangereconnect", true); + if(managemeNetworkState) + mReleaseHold=false; + + } + + public boolean openManagementInterface(@NotNull Context c) { + // Could take a while to open connection + int tries=8; + + String socketName = (c.getCacheDir().getAbsolutePath() + "/" + "mgmtsocket"); + // The mServerSocketLocal is transferred to the LocalServerSocket, ignore warning + + mServerSocketLocal = new LocalSocket(); + + while(tries > 0 && !mServerSocketLocal.isConnected()) { + try { + mServerSocketLocal.bind(new LocalSocketAddress(socketName, + LocalSocketAddress.Namespace.FILESYSTEM)); + } catch (IOException e) { + // wait 300 ms before retrying + try { Thread.sleep(300); + } catch (InterruptedException e1) { + } + + } + tries--; + } + + try { + + mServerSocket = new LocalServerSocket(mServerSocketLocal.getFileDescriptor()); + return true; + } catch (IOException e) { + VpnStatus.logException(e); + } + return false; + + + } + + public void managmentCommand(String cmd) { + try { + if(mSocket!=null && mSocket.getOutputStream() !=null) { + mSocket.getOutputStream().write(cmd.getBytes()); + mSocket.getOutputStream().flush(); + } + }catch (IOException e) { + // Ignore socket stack traces + } + } + + + @Override + public void run() { + byte [] buffer =new byte[2048]; + // mSocket.setSoTimeout(5); // Setting a timeout cannot be that bad + + String pendingInput=""; + active.add(this); + + try { + // Wait for a client to connect + mSocket= mServerSocket.accept(); + InputStream instream = mSocket.getInputStream(); + // Close the management socket after client connected + + mServerSocket.close(); + // Closing one of the two sockets also closes the other + //mServerSocketLocal.close(); + + while(true) { + int numbytesread = instream.read(buffer); + if(numbytesread==-1) + return; + + FileDescriptor[] fds = null; + try { + fds = mSocket.getAncillaryFileDescriptors(); + } catch (IOException e) { + VpnStatus.logException("Error reading fds from socket", e); + } + if(fds!=null){ + Collections.addAll(mFDList, fds); + } + + String input = new String(buffer,0,numbytesread,"UTF-8"); + + pendingInput += input; + + pendingInput=processInput(pendingInput); + + + + } + } catch (IOException e) { + if (!e.getMessage().equals("socket closed")) + VpnStatus.logException(e); + } + active.remove(this); + } + + //! Hack O Rama 2000! + private void protectFileDescriptor(FileDescriptor fd) { + Exception exp; + try { + Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$"); + int fdint = (Integer) getInt.invoke(fd); + + // You can even get more evil by parsing toString() and extract the int from that :) + + boolean result = mOpenVPNService.protect(fdint); + if (!result) + VpnStatus.logWarning("Could not protect VPN socket"); + + + //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint); + //pfd.close(); + NativeUtils.jniclose(fdint); + return; + } catch (NoSuchMethodException e) { + exp =e; + } catch (IllegalArgumentException e) { + exp =e; + } catch (IllegalAccessException e) { + exp =e; + } catch (InvocationTargetException e) { + exp =e; + } catch (NullPointerException e) { + exp =e; + } + + Log.d("Openvpn", "Failed to retrieve fd from socket: " + fd); + VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")" , exp); + } + + private String processInput(String pendingInput) { + + + while(pendingInput.contains("\n")) { + String[] tokens = pendingInput.split("\\r?\\n", 2); + processCommand(tokens[0]); + if(tokens.length == 1) + // No second part, newline was at the end + pendingInput=""; + else + pendingInput=tokens[1]; + } + return pendingInput; + } + + + private void processCommand(String command) { + //Log.i(TAG, "Line from managment" + command); + + + if (command.startsWith(">") && command.contains(":")) { + String[] parts = command.split(":",2); + String cmd = parts[0].substring(1); + String argument = parts[1]; + + + if(cmd.equals("INFO")) { + /* Ignore greeting from management */ + return; + }else if (cmd.equals("PASSWORD")) { + processPWCommand(argument); + } else if (cmd.equals("HOLD")) { + handleHold(); + } else if (cmd.equals("NEED-OK")) { + processNeedCommand(argument); + } else if (cmd.equals("BYTECOUNT")){ + processByteCount(argument); + } else if (cmd.equals("STATE")) { + processState(argument); + } else if (cmd.equals("PROXY")) { + processProxyCMD(argument); + } else if (cmd.equals("LOG")) { + processLogMessage(argument); + } else if (cmd.equals("RSA_SIGN")) { + processSignCommand(argument); + } else { + VpnStatus.logWarning("MGMT: Got unrecognized command" + command); + Log.i(TAG, "Got unrecognized command" + command); + } + } else if (command.startsWith("SUCCESS:")) { + /* Ignore this kind of message too */ + return; + } else if (command.startsWith("PROTECTFD: ")) { + FileDescriptor fdtoprotect = mFDList.pollFirst(); + if (fdtoprotect!=null) + protectFileDescriptor(fdtoprotect); + } else { + Log.i(TAG, "Got unrecognized line from managment" + command); + VpnStatus.logWarning("MGMT: Got unrecognized line from management:" + command); + } + } + + private void processLogMessage(String argument) { + String[] args = argument.split(",",4); + // 0 unix time stamp + // 1 log level N,I,E etc. + /* + (b) zero or more message flags in a single string: + I -- informational + F -- fatal error + N -- non-fatal error + W -- warning + D -- debug, and + */ + // 2 log message + + Log.d("OpenVPN", argument); + + VpnStatus.LogLevel level; + if (args[1].equals("I")) { + level = VpnStatus.LogLevel.INFO; + } else if (args[1].equals("W")) { + level = VpnStatus.LogLevel.WARNING; + } else if (args[1].equals("D")) { + level = VpnStatus.LogLevel.VERBOSE; + } else if (args[1].equals("F")) { + level = VpnStatus.LogLevel.ERROR; + } else { + level = VpnStatus.LogLevel.INFO; + } + + int ovpnlevel = Integer.parseInt(args[2]) & 0x0F; + String msg = args[3]; + + if (msg.startsWith("MANAGEMENT: CMD")) + ovpnlevel = Math.max(4, ovpnlevel); + + VpnStatus.logMessageOpenVPN(level,ovpnlevel, msg); + } + + private void handleHold() { + if(mReleaseHold) { + releaseHoldCmd(); + } else { + mWaitingForRelease=true; + + VpnStatus.updateStatePause(lastPauseReason); + + + } + } + private void releaseHoldCmd() { + if ((System.currentTimeMillis()- mLastHoldRelease) < 5000) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + + } + mWaitingForRelease=false; + mLastHoldRelease = System.currentTimeMillis(); + managmentCommand("hold release\n"); + managmentCommand("bytecount " + mBytecountInterval + "\n"); + managmentCommand("state on\n"); + //managmentCommand("log on all\n"); + } + + public void releaseHold() { + mReleaseHold=true; + if(mWaitingForRelease) + releaseHoldCmd(); + + } + + private void processProxyCMD(String argument) { + String[] args = argument.split(",",3); + SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile); + + + if(args.length >= 2) { + String proto = args[1]; + if(proto.equals("UDP")) { + proxyaddr=null; + } + } + + if(proxyaddr instanceof InetSocketAddress ){ + InetSocketAddress isa = (InetSocketAddress) proxyaddr; + + VpnStatus.logInfo(R.string.using_proxy, isa.getHostName(), isa.getPort()); + + String proxycmd = String.format(Locale.ENGLISH,"proxy HTTP %s %d\n", isa.getHostName(),isa.getPort()); + managmentCommand(proxycmd); + } else { + managmentCommand("proxy NONE\n"); + } + + } + private void processState(String argument) { + String[] args = argument.split(",",3); + String currentstate = args[1]; + + if(args[2].equals(",,")) + VpnStatus.updateStateString(currentstate, ""); + else + VpnStatus.updateStateString(currentstate, args[2]); + } + + + private void processByteCount(String argument) { + // >BYTECOUNT:{BYTES_IN},{BYTES_OUT} + int comma = argument.indexOf(','); + long in = Long.parseLong(argument.substring(0, comma)); + long out = Long.parseLong(argument.substring(comma+1)); + + VpnStatus.updateByteCount(in, out); + + } + + + + private void processNeedCommand(String argument) { + int p1 =argument.indexOf('\''); + int p2 = argument.indexOf('\'',p1+1); + + String needed = argument.substring(p1+1, p2); + String extra = argument.split(":",2)[1]; + + String status = "ok"; + + + if (needed.equals("PROTECTFD")) { + FileDescriptor fdtoprotect = mFDList.pollFirst(); + protectFileDescriptor(fdtoprotect); + } else if (needed.equals("DNSSERVER")) { + mOpenVPNService.addDNS(extra); + }else if (needed.equals("DNSDOMAIN")){ + mOpenVPNService.setDomain(extra); + } else if (needed.equals("ROUTE")) { + String[] routeparts = extra.split(" "); + + /* + buf_printf (&out, "%s %s %s dev %s", network, netmask, gateway, rgi->iface); + else + buf_printf (&out, "%s %s %s", network, netmask, gateway); + */ + + if(routeparts.length==5) { + assert(routeparts[3].equals("dev")); + mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]); + } else if (routeparts.length >= 3) { + mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null); + } else { + VpnStatus.logError("Unrecognized ROUTE cmd:" + Arrays.toString(routeparts) + " | " + argument); + } + + } else if (needed.equals("ROUTE6")) { + String[] routeparts = extra.split(" "); + mOpenVPNService.addRoutev6(routeparts[0],routeparts[1]); + } else if (needed.equals("IFCONFIG")) { + String[] ifconfigparts = extra.split(" "); + int mtu = Integer.parseInt(ifconfigparts[2]); + mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1],mtu,ifconfigparts[3]); + } else if (needed.equals("IFCONFIG6")) { + mOpenVPNService.setLocalIPv6(extra); + + } else if (needed.equals("PERSIST_TUN_ACTION")) { + // check if tun cfg stayed the same + status = mOpenVPNService.getTunReopenStatus(); + } else if (needed.equals("OPENTUN")) { + if(sendTunFD(needed,extra)) + return; + else + status="cancel"; + // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :( + + } else { + Log.e(TAG,"Unkown needok command " + argument); + return; + } + + String cmd = String.format("needok '%s' %s\n", needed, status); + managmentCommand(cmd); + } + + private boolean sendTunFD (String needed, String extra) { + Exception exp; + if(!extra.equals("tun")) { + // We only support tun + VpnStatus.logError(String.format("Device type %s requested, but only tun is possible with the Android API, sorry!",extra)); + + return false; + } + ParcelFileDescriptor pfd = mOpenVPNService.openTun(); + if(pfd==null) + return false; + + Method setInt; + int fdint = pfd.getFd(); + try { + setInt = FileDescriptor.class.getDeclaredMethod("setInt$",int.class); + FileDescriptor fdtosend = new FileDescriptor(); + + setInt.invoke(fdtosend,fdint); + + FileDescriptor[] fds = {fdtosend}; + mSocket.setFileDescriptorsForSend(fds); + + // Trigger a send so we can close the fd on our side of the channel + // The API documentation fails to mention that it will not reset the file descriptor to + // be send and will happily send the file descriptor on every write ... + String cmd = String.format("needok '%s' %s\n", needed, "ok"); + managmentCommand(cmd); + + // Set the FileDescriptor to null to stop this mad behavior + mSocket.setFileDescriptorsForSend(null); + + pfd.close(); + + return true; + } catch (NoSuchMethodException e) { + exp =e; + } catch (IllegalArgumentException e) { + exp =e; + } catch (IllegalAccessException e) { + exp =e; + } catch (InvocationTargetException e) { + exp =e; + } catch (IOException e) { + exp =e; + } + VpnStatus.logException("Could not send fd over socket" , exp); + + return false; + } + + private void processPWCommand(String argument) { + //argument has the form Need 'Private Key' password + // or ">PASSWORD:Verification Failed: '%s' ['%s']" + String needed; + + + + try{ + + int p1 = argument.indexOf('\''); + int p2 = argument.indexOf('\'',p1+1); + needed = argument.substring(p1+1, p2); + if (argument.startsWith("Verification Failed")) { + proccessPWFailed(needed, argument.substring(p2+1)); + return; + } + } catch (StringIndexOutOfBoundsException sioob) { + VpnStatus.logError("Could not parse management Password command: " + argument); + return; + } + + String pw=null; + + if(needed.equals("Private Key")) { + pw = mProfile.getPasswordPrivateKey(); + } else if (needed.equals("Auth")) { + String usercmd = String.format("username '%s' %s\n", + needed, VpnProfile.openVpnEscape(mProfile.mUsername)); + managmentCommand(usercmd); + pw = mProfile.getPasswordAuth(); + } + if(pw!=null) { + String cmd = String.format("password '%s' %s\n", needed, VpnProfile.openVpnEscape(pw)); + managmentCommand(cmd); + } else { + VpnStatus.logError(String.format("Openvpn requires Authentication type '%s' but no password/key information available", needed)); + } + + } + + + + + private void proccessPWFailed(String needed, String args) { + VpnStatus.updateStateString("AUTH_FAILED", needed + args, R.string.state_auth_failed, ConnectionStatus.LEVEL_AUTH_FAILED); + } + + + private static boolean stopOpenVPN() { + boolean sendCMD=false; + for (OpenVpnManagementThread mt: active){ + mt.managmentCommand("signal SIGINT\n"); + sendCMD=true; + try { + if(mt.mSocket !=null) + mt.mSocket.close(); + } catch (IOException e) { + // Ignore close error on already closed socket + } + } + return sendCMD; + } + + @Override + public void networkChange() { + if(!mWaitingForRelease) + managmentCommand("network-change\n"); + } + + public void signalusr1() { + mReleaseHold=false; + + if(!mWaitingForRelease) + managmentCommand("signal SIGUSR1\n"); + else + // If signalusr1 is called update the state string + // if there is another for stopping + VpnStatus.updateStatePause(lastPauseReason); + } + + public void reconnect() { + signalusr1(); + releaseHold(); + } + + private void processSignCommand(String b64data) { + + String signed_string = mProfile.getSignedData(b64data); + if(signed_string==null) { + managmentCommand("rsa-sig\n"); + managmentCommand("\nEND\n"); + stopOpenVPN(); + return; + } + managmentCommand("rsa-sig\n"); + managmentCommand(signed_string); + managmentCommand("\nEND\n"); + } + + @Override + public void pause (pauseReason reason) { + lastPauseReason = reason; + signalusr1(); + } + + @Override + public void resume() { + releaseHold(); + /* Reset the reason why we are disconnected */ + lastPauseReason = pauseReason.noNetwork; + } + + @Override + public boolean stopVPN() { + return stopOpenVPN(); + } +} diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java index b1f9dbd4..8281aed8 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnService.java @@ -30,8 +30,8 @@ import java.util.HashMap; import java.util.Locale; import java.util.Vector; -import de.blinkt.openvpn.BuildConfig; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.activities.DisconnectVPN; import de.blinkt.openvpn.activities.LogWindow; @@ -50,7 +50,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE"; public static final String DISCONNECT_VPN = "de.blinkt.openvpn.DISCONNECT_VPN"; private static final String PAUSE_VPN = "de.blinkt.openvpn.PAUSE_VPN"; - private static final String RESUME_VPN = "de.blinkt.openvpn.RESUME_VPN"; + private static final String RESUME_VPN = "se.leap.bitmaskclient.RESUME_VPN"; private static final int OPENVPN_STATUS = 1; private static boolean mNotificationAlwaysVisible = false; private final Vector mDnslist = new Vector(); diff --git a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java index 4f66c503..47d88279 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java @@ -9,7 +9,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; public class ProxyDetection { diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java index 5f1efb5f..55fcb0ba 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -8,7 +8,7 @@ import java.io.InputStream; import android.content.Context; import android.content.Intent; import android.os.Build; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; public class VPNLaunchHelper { diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index d146aef8..c19daeb0 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -9,7 +9,7 @@ import android.content.pm.Signature; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; diff --git a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java index da1e4ed5..35e53c08 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java +++ b/app/src/main/java/de/blinkt/openvpn/core/X509Utils.java @@ -3,7 +3,7 @@ package de.blinkt.openvpn.core; import android.content.Context; import android.text.TextUtils; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import org.spongycastle.util.io.pem.PemObject; import org.spongycastle.util.io.pem.PemReader; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/AboutFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/AboutFragment.java index a43bbbe8..f878e4fb 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/AboutFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/AboutFragment.java @@ -22,7 +22,7 @@ import android.view.ViewGroup; import android.webkit.WebView; import android.widget.TextView; import com.android.vending.billing.IInAppBillingService; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.core.VpnStatus; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java index 238ad952..ef57a395 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java @@ -8,7 +8,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class FaqFragment extends Fragment { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/FileSelectionFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/FileSelectionFragment.java index 84e065a5..271af173 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/FileSelectionFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/FileSelectionFragment.java @@ -20,7 +20,7 @@ import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import de.blinkt.openvpn.activities.FileSelect; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class FileSelectionFragment extends ListFragment { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/InlineFileTab.java b/app/src/main/java/de/blinkt/openvpn/fragments/InlineFileTab.java index bea22442..f0aa4fe2 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/InlineFileTab.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/InlineFileTab.java @@ -10,7 +10,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import de.blinkt.openvpn.activities.FileSelect; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class InlineFileTab extends Fragment { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java index f23a50db..4a6f19b5 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/OpenVpnPreferencesFragment.java @@ -1,48 +1,48 @@ -package de.blinkt.openvpn.fragments; - -import android.os.Bundle; -import android.preference.PreferenceFragment; -import de.blinkt.openvpn.R; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.ProfileManager; - -public abstract class OpenVpnPreferencesFragment extends PreferenceFragment { - - protected VpnProfile mProfile; - - protected abstract void loadSettings(); - protected abstract void saveSettings(); - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); - mProfile = ProfileManager.get(getActivity(),profileUUID); - getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); - - } - - @Override - public void onPause() { - super.onPause(); - saveSettings(); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - if(savedInstanceState!=null) { - String profileUUID=savedInstanceState.getString(VpnProfile.EXTRA_PROFILEUUID); - mProfile = ProfileManager.get(getActivity(),profileUUID); - loadSettings(); - } - } - - @Override - public void onSaveInstanceState (Bundle outState) { - super.onSaveInstanceState(outState); - saveSettings(); - outState.putString(VpnProfile.EXTRA_PROFILEUUID, mProfile.getUUIDString()); - } -} +package de.blinkt.openvpn.fragments; + +import android.os.Bundle; +import android.preference.PreferenceFragment; +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ProfileManager; + +public abstract class OpenVpnPreferencesFragment extends PreferenceFragment { + + protected VpnProfile mProfile; + + protected abstract void loadSettings(); + protected abstract void saveSettings(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String profileUUID = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); + mProfile = ProfileManager.get(getActivity(),profileUUID); + getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); + + } + + @Override + public void onPause() { + super.onPause(); + saveSettings(); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if(savedInstanceState!=null) { + String profileUUID=savedInstanceState.getString(VpnProfile.EXTRA_PROFILEUUID); + mProfile = ProfileManager.get(getActivity(),profileUUID); + loadSettings(); + } + } + + @Override + public void onSaveInstanceState (Bundle outState) { + super.onSaveInstanceState(outState); + saveSettings(); + outState.putString(VpnProfile.EXTRA_PROFILEUUID, mProfile.getUUIDString()); + } +} diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/SendDumpFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/SendDumpFragment.java index d43f6427..fd01b89f 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/SendDumpFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/SendDumpFragment.java @@ -14,7 +14,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.core.VpnStatus; public class SendDumpFragment extends Fragment { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Authentication.java b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Authentication.java index 6ce9c915..9bd3bf54 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Authentication.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Authentication.java @@ -13,7 +13,7 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.SwitchPreference; import android.util.Pair; import de.blinkt.openvpn.activities.FileSelect; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.views.RemoteCNPreference; import de.blinkt.openvpn.VpnProfile; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java index 4145c65f..203d6c5c 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -27,9 +27,9 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.ToggleButton; import de.blinkt.openvpn.views.FileSelectLayout; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.R.id; +import se.leap.bitmaskclient.R.id; import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.core.X509Utils; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_IP.java b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_IP.java index 16e3a5c4..81988012 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_IP.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_IP.java @@ -6,7 +6,7 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceManager; import android.preference.SwitchPreference; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; public class Settings_IP extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Obscure.java b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Obscure.java index 0e8f1a02..4507d691 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Obscure.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Obscure.java @@ -6,7 +6,7 @@ import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class Settings_Obscure extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener { private CheckBoxPreference mUseRandomHostName; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Routing.java b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Routing.java index c6f0dcf8..8163a745 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Routing.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/Settings_Routing.java @@ -4,7 +4,7 @@ import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; public class Settings_Routing extends OpenVpnPreferencesFragment implements OnPreferenceChangeListener { diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/ShowConfigFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/ShowConfigFragment.java index bf673288..0cf2bbb7 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/ShowConfigFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/ShowConfigFragment.java @@ -10,7 +10,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ProfileManager; diff --git a/app/src/main/java/de/blinkt/openvpn/views/FileSelectLayout.java b/app/src/main/java/de/blinkt/openvpn/views/FileSelectLayout.java index 665b525f..06dbec22 100644 --- a/app/src/main/java/de/blinkt/openvpn/views/FileSelectLayout.java +++ b/app/src/main/java/de/blinkt/openvpn/views/FileSelectLayout.java @@ -1,6 +1,6 @@ package de.blinkt.openvpn.views; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.activities.FileSelect; import de.blinkt.openvpn.core.VpnStatus; diff --git a/app/src/main/java/de/blinkt/openvpn/views/RemoteCNPreference.java b/app/src/main/java/de/blinkt/openvpn/views/RemoteCNPreference.java index 388f892b..b24e6f8f 100644 --- a/app/src/main/java/de/blinkt/openvpn/views/RemoteCNPreference.java +++ b/app/src/main/java/de/blinkt/openvpn/views/RemoteCNPreference.java @@ -10,7 +10,7 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; -import de.blinkt.openvpn.R; +import se.leap.bitmaskclient.R; import de.blinkt.openvpn.VpnProfile; public class RemoteCNPreference extends DialogPreference { diff --git a/build.gradle b/build.gradle index 2e3ce0c8..6c667e73 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,5 @@ import au.com.coherentsoftware.gradle.mercurial.task.* +import org.apache.tools.ant.filters.ReplaceTokens buildscript { repositories { @@ -39,8 +40,15 @@ task pullIcsOpenVPN( type: HgPull ) { } task copyIcsOpenVPNClasses( type: Copy ) { - from 'ics-openvpn/main' + from ('ics-openvpn/main') { + include '**/*.java' + include '**/*.aidl' + filter { + line -> line.replaceAll('de.blinkt.openvpn.R', 'se.leap.bitmaskclient.R') + } + filter { + line -> line.replaceAll('de.blinkt.openvpn.BuildConfig', 'se.leap.bitmaskclient.BuildConfig') + } + } into 'app' - include '**/*.java' - include '**/*.aidl' } \ No newline at end of file -- cgit v1.2.3