diff options
Diffstat (limited to 'src/de/blinkt/openvpn')
-rw-r--r-- | src/de/blinkt/openvpn/LogWindow.java | 9 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/api/ExternalOpenVPNService.java | 498 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/core/OpenVPNThread.java | 3 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/core/OpenVpnManagementThread.java | 11 | ||||
-rw-r--r-- | src/de/blinkt/openvpn/core/OpenVpnService.java | 33 |
5 files changed, 303 insertions, 251 deletions
diff --git a/src/de/blinkt/openvpn/LogWindow.java b/src/de/blinkt/openvpn/LogWindow.java index 82a2f4b6..843f85cc 100644 --- a/src/de/blinkt/openvpn/LogWindow.java +++ b/src/de/blinkt/openvpn/LogWindow.java @@ -2,6 +2,7 @@ package de.blinkt.openvpn; import android.app.Activity; import android.os.Bundle; +import android.view.MenuItem; /** * Created by arne on 13.10.13. @@ -11,5 +12,13 @@ public class LogWindow extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.log_window); + getActionBar().setDisplayHomeAsUpEnabled(true); + + } + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return super.onOptionsItemSelected(item); } } diff --git a/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java index 77374355..34b61325 100644 --- a/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java +++ b/src/de/blinkt/openvpn/api/ExternalOpenVPNService.java @@ -35,272 +35,272 @@ import de.blinkt.openvpn.core.VPNLaunchHelper; public class ExternalOpenVPNService extends Service implements StateListener {
- private static final int SEND_TOALL = 0;
+ private static final int SEND_TOALL = 0;
- final RemoteCallbackList<IOpenVPNStatusCallback> mCallbacks =
- new RemoteCallbackList<IOpenVPNStatusCallback>();
+ final RemoteCallbackList<IOpenVPNStatusCallback> mCallbacks =
+ new RemoteCallbackList<IOpenVPNStatusCallback>();
- private OpenVpnService mService;
- private ExternalAppDatabase mExtAppDb;
+ private OpenVpnService mService;
+ private ExternalAppDatabase mExtAppDb;
- private ServiceConnection mConnection = new ServiceConnection() {
+ 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 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);
+ @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() {
+ 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);
- e.printStackTrace();
- }
+ 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);
+ e.printStackTrace();
+ }
- }
- throw new SecurityException("Unauthorized OpenVPN API Caller");
- }
-
- @Override
- public List<APIVpnProfile> getProfiles() throws RemoteException {
- checkOpenVPNPermission();
+ }
+ throw new SecurityException("Unauthorized OpenVPN API Caller");
+ }
+
+ @Override
+ public List<APIVpnProfile> getProfiles() throws RemoteException {
+ checkOpenVPNPermission();
- ProfileManager pm = ProfileManager.getInstance(getBaseContext());
+ ProfileManager pm = ProfileManager.getInstance(getBaseContext());
- List<APIVpnProfile> profiles = new LinkedList<APIVpnProfile>();
+ List<APIVpnProfile> profiles = new LinkedList<APIVpnProfile>();
- for(VpnProfile vp: pm.getProfiles())
- profiles.add(new APIVpnProfile(vp.getUUIDString(),vp.mName,vp.mUserEditable));
+ for (VpnProfile vp : pm.getProfiles())
+ profiles.add(new APIVpnProfile(vp.getUUIDString(), vp.mName, vp.mUserEditable));
- return profiles;
- }
+ 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);
- }
+ @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();
+ public void startVPN(String inlineconfig) throws RemoteException {
+ checkOpenVPNPermission();
- ConfigParser cp = new ConfigParser();
- try {
- cp.parseConfig(new StringReader(inlineconfig));
- VpnProfile vp = cp.convertProfile();
- if(vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
- throw new RemoteException(getString(vp.checkProfile(getApplicationContext())));
-
-
- ProfileManager.setTemporaryProfile(vp);
- VPNLaunchHelper.startOpenVpn(vp, getBaseContext());
-
-
- } catch (IOException e) {
- throw new RemoteException(e.getMessage());
- } catch (ConfigParseError e) {
- throw new RemoteException(e.getMessage());
- }
- }
-
- @Override
- public boolean addVPNProfile(String name, String config) throws RemoteException {
- checkOpenVPNPermission();
-
- ConfigParser cp = new ConfigParser();
- try {
- cp.parseConfig(new StringReader(config));
- VpnProfile vp = cp.convertProfile();
- vp.mName = name;
- ProfileManager pm = ProfileManager.getInstance(getBaseContext());
- pm.addProfile(vp);
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- } catch (ConfigParseError e) {
- e.printStackTrace();
- return false;
- }
-
- return true;
- }
-
-
- @Override
- public Intent prepare(String packagename) {
- if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename))
- return null;
-
- Intent intent = new Intent();
- intent.setClass(ExternalOpenVPNService.this, ConfirmDialog.class);
- return intent;
- }
-
- @Override
- public 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();
- }
- };
-
-
-
- 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<ExternalOpenVPNService> service= null;
-
- private void setService(ExternalOpenVPNService eos)
- {
- service = new WeakReference<ExternalOpenVPNService>(eos);
- }
-
- @Override public void handleMessage(Message msg) {
-
- RemoteCallbackList<IOpenVPNStatusCallback> 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());
- }
- }
+ ConfigParser cp = new ConfigParser();
+ try {
+ cp.parseConfig(new StringReader(inlineconfig));
+ VpnProfile vp = cp.convertProfile();
+ if (vp.checkProfile(getApplicationContext()) != R.string.no_error_found)
+ throw new RemoteException(getString(vp.checkProfile(getApplicationContext())));
+
+
+ ProfileManager.setTemporaryProfile(vp);
+ VPNLaunchHelper.startOpenVpn(vp, getBaseContext());
+
+
+ } catch (IOException e) {
+ throw new RemoteException(e.getMessage());
+ } catch (ConfigParseError e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean addVPNProfile(String name, String config) throws RemoteException {
+ checkOpenVPNPermission();
+
+ ConfigParser cp = new ConfigParser();
+ try {
+ cp.parseConfig(new StringReader(config));
+ VpnProfile vp = cp.convertProfile();
+ vp.mName = name;
+ ProfileManager pm = ProfileManager.getInstance(getBaseContext());
+ pm.addProfile(vp);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ } catch (ConfigParseError e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+
+ @Override
+ public Intent prepare(String packagename) {
+ if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename))
+ return null;
+
+ Intent intent = new Intent();
+ intent.setClass(ExternalOpenVPNService.this, ConfirmDialog.class);
+ return intent;
+ }
+
+ @Override
+ public 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();
+ }
+ };
+
+
+ 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<ExternalOpenVPNService> service = null;
+
+ private void setService(ExternalOpenVPNService eos) {
+ service = new WeakReference<ExternalOpenVPNService>(eos);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ RemoteCallbackList<IOpenVPNStatusCallback> 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/src/de/blinkt/openvpn/core/OpenVPNThread.java b/src/de/blinkt/openvpn/core/OpenVPNThread.java index 0807b33d..f814ff29 100644 --- a/src/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/src/de/blinkt/openvpn/core/OpenVPNThread.java @@ -137,6 +137,9 @@ public class OpenVPNThread implements Runnable { 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 {
diff --git a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java index 03b36144..abca275a 100644 --- a/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/src/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -273,8 +273,12 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { }
int ovpnlevel = Integer.parseInt(args[2]) & 0x0F;
+ String msg = args[3];
- VpnStatus.logMessageOpenVPN(level,ovpnlevel, args[3]);
+ if (msg.startsWith("MANAGEMENT: CMD"))
+ ovpnlevel = Math.max(4, ovpnlevel);
+
+ VpnStatus.logMessageOpenVPN(level,ovpnlevel, msg);
}
private void handleHold() {
@@ -387,7 +391,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } else if (needed.equals("IFCONFIG6")) {
mOpenVPNService.setLocalIPv6(extra);
- } else if (needed.equals("OPENTUN")) {
+ } 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
diff --git a/src/de/blinkt/openvpn/core/OpenVpnService.java b/src/de/blinkt/openvpn/core/OpenVpnService.java index e4437d2c..ab21fc1b 100644 --- a/src/de/blinkt/openvpn/core/OpenVpnService.java +++ b/src/de/blinkt/openvpn/core/OpenVpnService.java @@ -14,6 +14,7 @@ import android.net.VpnService; import android.os.*; import android.os.Handler.Callback; import android.preference.PreferenceManager; +import android.text.TextUtils; import de.blinkt.openvpn.DisconnectVPN; import de.blinkt.openvpn.LogWindow; import de.blinkt.openvpn.R; @@ -24,6 +25,7 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.MessageDigest; import java.util.HashMap; import java.util.Locale; import java.util.Vector; @@ -55,6 +57,7 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac private long mConnecttime; private boolean mOvpn3 = false; private OpenVPNManagement mManagement; + private String mLastTunCfg; // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java public static String humanReadableByteCount(long bytes, boolean mbit) { @@ -386,6 +389,24 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac } + private String getTunConfigString() + { + // The format of the string is not important, only that + // two identical configurations produce the same result + String cfg="TUNCFG UNQIUE STRING ips:"; + + if (mLocalIP!=null) + cfg+=mLocalIP.toString(); + if (mLocalIPv6!=null) + cfg+=mLocalIPv6.toString(); + + cfg+= "routes: " + TextUtils.join("|",mRoutes) + TextUtils.join("|",mRoutesv6); + cfg+= "dns: " + TextUtils.join("|",mDnslist); + cfg+= "domain: " + mDomain; + cfg+= "mtu: " + mMtu; + return cfg; + } + public ParcelFileDescriptor openTun() { Builder builder = new Builder(); @@ -465,6 +486,8 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac if (mDnslist.size() == 0) VpnStatus.logInfo(R.string.warn_no_dns); + mLastTunCfg = getTunConfigString(); + // Reset information mDnslist.clear(); mRoutes.clear(); @@ -625,6 +648,16 @@ public class OpenVpnService extends VpnService implements StateListener, Callbac return mManagement; } + public String getTunReopenStatus() { + String currentConfiguration = getTunConfigString(); + if(currentConfiguration.equals(mLastTunCfg)) + return "NOACTION"; + else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + return "OPEN_AFTER_CLOSE"; + else + return "OPEN_BEFORE_CLOSE"; + } + public class LocalBinder extends Binder { public OpenVpnService getService() { // Return this instance of LocalService so clients can call public methods |