summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/blinkt/openvpn/core
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2016-04-02 12:40:10 +0200
committerParménides GV <parmegv@sdf.org>2016-04-02 12:40:10 +0200
commit3a409ed35f0f26644d99b8704801103de8783864 (patch)
treef07a09830b2a70c4617ab8da73dde0e2d4fbd3d7 /app/src/main/java/de/blinkt/openvpn/core
parent93aca53eae03b4b31877e97991d61bdc11a2db44 (diff)
Update ics-openvpn
Diffstat (limited to 'app/src/main/java/de/blinkt/openvpn/core')
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java28
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java62
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java14
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java139
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java255
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java10
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java20
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java24
8 files changed, 320 insertions, 232 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index 80a15c54..d14e643e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -32,8 +32,6 @@ public class ConfigParser {
private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>();
private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>();
private String auth_user_pass_file;
- private String crl_verify_file;
-
public void parseConfig(Reader reader) throws IOException, ConfigParseError {
@@ -132,10 +130,6 @@ public class ConfigParser {
return auth_user_pass_file;
}
- public String getCrlVerifyFile() {
- return crl_verify_file;
- }
-
enum linestate {
initial,
readin_single_quote, reading_quoted, reading_unquoted, done
@@ -299,7 +293,8 @@ public class ConfigParser {
{
{"setenv", "IV_GUI_VER"},
{"setenv", "IV_OPENVPN_GUI_VERSION"},
- {"engine", "dynamic"}
+ {"engine", "dynamic"},
+ {"setenv", "CLIENT_CERT"}
};
final String[] connectionOptions = {
@@ -621,11 +616,12 @@ public class ConfigParser {
Vector<String> crlfile = getOption("crl-verify", 1, 2);
if (crlfile != null) {
// If the 'dir' parameter is present just add it as custom option ..
- np.mCustomConfigOptions += TextUtils.join(" ", crlfile) + "\n";
- if (crlfile.size() == 2) {
+ if (crlfile.size() == 3 && crlfile.get(2).equals("dir"))
+ np.mCustomConfigOptions += TextUtils.join(" ", crlfile) + "\n";
+ else
// Save the filename for the config converter to add later
- crl_verify_file = crlfile.get(1);
- }
+ np.mCrlFilename = crlfile.get(1);
+
}
@@ -813,16 +809,6 @@ public class ConfigParser {
}
}
- public static void removeCRLCustomOption(VpnProfile np) {
- String lines[] = np.mCustomConfigOptions.split("\\r?\\n");
- Vector<String> keeplines = new Vector<>();
- for (String l : lines) {
- if (!l.startsWith("crl-verify "))
- keeplines.add(l);
- }
- np.mCustomConfigOptions = TextUtils.join("\n", keeplines);
- }
-
private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError {
for (String option : unsupportedOptions)
if (options.containsKey(option))
diff --git a/app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java b/app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java
index 5c1741d9..288c7934 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java
@@ -11,12 +11,15 @@ import android.os.Message;
import android.os.Parcel;
import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Locale;
+
+import se.leap.bitmaskclient.R;
/**
* Created by arne on 23.01.16.
@@ -27,7 +30,6 @@ class LogFileHandler extends Handler {
static final int LOG_INIT = 102;
public static final int LOG_MESSAGE = 103;
private static FileOutputStream mLogFile;
- private static BufferedOutputStream mBufLogfile;
public static final String LOGFILE_NAME = "logcache.dat";
@@ -41,6 +43,8 @@ class LogFileHandler extends Handler {
public void handleMessage(Message msg) {
try {
if (msg.what == LOG_INIT) {
+ if (mLogFile != null)
+ throw new RuntimeException("mLogFile not null");
readLogCache((File) msg.obj);
openLogFile((File) msg.obj);
} else if (msg.what == LOG_MESSAGE && msg.obj instanceof VpnStatus.LogItem) {
@@ -70,15 +74,13 @@ class LogFileHandler extends Handler {
private static void trimLogFile() {
try {
- mBufLogfile.flush();
+ mLogFile.flush();
mLogFile.getChannel().truncate(0);
-
} catch (IOException e) {
e.printStackTrace();
}
}
-
private void writeLogItemToDisk(VpnStatus.LogItem li) throws IOException {
Parcel p = Parcel.obtain();
li.writeToParcel(p, 0);
@@ -86,8 +88,8 @@ class LogFileHandler extends Handler {
// write binary format to disc
byte[] liBytes = p.marshall();
- mLogFile.write(liBytes.length & 0xff);
- mLogFile.write(liBytes.length >> 8);
+ byte[] lenBytes = ByteBuffer.allocate(4).putInt(liBytes.length).array();
+ mLogFile.write(lenBytes);
mLogFile.write(liBytes);
p.recycle();
}
@@ -95,39 +97,56 @@ class LogFileHandler extends Handler {
private void openLogFile (File cacheDir) throws FileNotFoundException {
File logfile = new File(cacheDir, LOGFILE_NAME);
mLogFile = new FileOutputStream(logfile);
- mBufLogfile = new BufferedOutputStream(mLogFile);
}
private void readLogCache(File cacheDir) {
File logfile = new File(cacheDir, LOGFILE_NAME);
+
if (!logfile.exists() || !logfile.canRead())
return;
- VpnStatus.logDebug("Reread log items from cache file");
+
try {
+
BufferedInputStream logFile = new BufferedInputStream(new FileInputStream(logfile));
byte[] buf = new byte[8192];
- int read = logFile.read(buf, 0, 2);
+ int read = logFile.read(buf, 0, 4);
+ int itemsRead=0;
- while (read > 0) {
- // Marshalled LogItem
- int len = (0xff & buf[0]) | buf[1] << 8;
+ while (read >= 4) {
+ int len = ByteBuffer.wrap(buf, 0, 4).asIntBuffer().get();
+ // Marshalled LogItem
read = logFile.read(buf, 0, len);
Parcel p = Parcel.obtain();
p.unmarshall(buf, 0, read);
p.setDataPosition(0);
VpnStatus.LogItem li = VpnStatus.LogItem.CREATOR.createFromParcel(p);
- VpnStatus.newLogItem(li, true);
+ if (li.verify()) {
+ VpnStatus.newLogItem(li, true);
+ } else {
+ VpnStatus.logError(String.format(Locale.getDefault(),
+ "Could not read log item from file: %d/%d: %s",
+ read, len, bytesToHex(buf, Math.max(read,80))));
+ }
p.recycle();
//Next item
- read = logFile.read(buf, 0, 2);
+ read = logFile.read(buf, 0, 4);
+ itemsRead++;
+ if (itemsRead > 2*VpnStatus.MAXLOGENTRIES) {
+ VpnStatus.logError("Too many logentries read from cache, aborting.");
+ read = 0;
+ }
+
}
+ VpnStatus.logDebug(R.string.reread_log, itemsRead);
+
+
} catch (java.io.IOException | java.lang.RuntimeException e) {
VpnStatus.logError("Reading cached logfile failed");
@@ -137,4 +156,17 @@ class LogFileHandler extends Handler {
}
}
+ final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+ public static String bytesToHex(byte[] bytes, int len) {
+ len = Math.min(bytes.length, len);
+ char[] hexChars = new char[len * 2];
+ for ( int j = 0; j < len; j++ ) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java
index 2771fa6a..2911fb1e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java
@@ -16,15 +16,19 @@ public interface OpenVPNManagement {
screenOff
}
- int mBytecountInterval =2;
+ int mBytecountInterval = 2;
- void reconnect();
+ void reconnect();
- void pause(pauseReason reason);
+ void pause(pauseReason reason);
- void resume();
+ void resume();
- boolean stopVPN();
+ /**
+ * @param replaceConnection True if the VPN is connected by a new connection.
+ * @return true if there was a process that has been send a stop signal
+ */
+ boolean stopVPN(boolean replaceConnection);
/*
* Rebind the interface
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 17be29b0..2917bce1 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -32,6 +32,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet6Address;
@@ -87,6 +88,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private final Object mProcessLock = new Object();
private Handler guiHandler;
private Toast mlastToast;
+ private Runnable mOpenVPNThread;
// 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) {
@@ -116,7 +118,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
@Override
public void onRevoke() {
VpnStatus.logInfo(R.string.permission_revoked);
- mManagement.stopVPN();
+ mManagement.stopVPN(false);
endVpnService();
}
@@ -132,6 +134,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.removeByteCountListener(this);
unregisterDeviceStateReceiver();
ProfileManager.setConntectedVpnProfileDisconnected(this);
+ mOpenVPNThread = null;
if (!mStarting) {
stopForeground(!mNotificationAlwaysVisible);
@@ -182,16 +185,16 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mNotificationManager.notify(OPENVPN_STATUS, notification);
- //startForeground(OPENVPN_STATUS, notification);
+ // startForeground(OPENVPN_STATUS, notification);
// Check if running on a TV
- if(runningOnAndroidTV() && !lowpriority)
+ if (runningOnAndroidTV() && !lowpriority)
guiHandler.post(new Runnable() {
@Override
public void run() {
- if (mlastToast!=null)
+ if (mlastToast != null)
mlastToast.cancel();
String toastText = String.format(Locale.getDefault(), "%s - %s", mProfile.mName, msg);
mlastToast = Toast.makeText(getBaseContext(), toastText, Toast.LENGTH_SHORT);
@@ -378,38 +381,50 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mProfile = ProfileManager.get(this, profileUUID);
}
+ /* start the OpenVPN process itself in a background thread */
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ startOpenVPN();
+ }
+ }).start();
+
+
+ ProfileManager.setConnectedVpnProfile(this, mProfile);
+ /* TODO: At the moment we have no way to handle asynchronous PW input
+ * Fixing will also allow to handle challenge/response authentication */
+ if (mProfile.needUserPWInput(true) != 0)
+ return START_NOT_STICKY;
+
+ return START_STICKY;
+ }
+
+ private void startOpenVPN() {
+ VpnStatus.logInfo(R.string.building_configration);
+ VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, VpnStatus.ConnectionStatus.LEVEL_START);
+
+
+ try {
+ mProfile.writeConfigFile(this);
+ } catch (IOException e) {
+ VpnStatus.logException("Error writing config file", e);
+ endVpnService();
+ return;
+ }
// Extract information from the intent.
String prefix = getPackageName();
- String[] argv = intent.getStringArrayExtra(prefix + ".ARGV");
- String nativeLibraryDirectory = intent.getStringExtra(prefix + ".nativelib");
+ String nativeLibraryDirectory = getApplicationInfo().nativeLibraryDir;
+
+ // Also writes OpenVPN binary
+ String[] argv = VPNLaunchHelper.buildOpenvpnArgv(this);
- String startTitle = getString(R.string.start_vpn_title, mProfile.mName);
- String startTicker = getString(R.string.start_vpn_ticker, mProfile.mName);
- showNotification(startTitle, startTicker,
- false, 0, LEVEL_CONNECTING_NO_SERVER_REPLY_YET);
// Set a flag that we are starting a new VPN
mStarting = true;
// Stop the previous session by interrupting the thread.
- if (mManagement != null && mManagement.stopVPN())
- // an old was asked to exit, wait 1s
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- //ignore
- }
- synchronized (mProcessLock) {
- if (mProcessThread != null) {
- mProcessThread.interrupt();
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- //ignore
- }
- }
- }
+ stopOldOpenVPNProcess();
// An old running VPN should now be exited
mStarting = false;
@@ -420,10 +435,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (!"ovpn3".equals(BuildConfig.FLAVOR))
mOvpn3 = false;
-
// Open the Management Interface
if (!mOvpn3) {
-
// start a Thread that handles incoming messages of the managment socket
OpenVpnManagementThread ovpnManagementThread = new OpenVpnManagementThread(mProfile, this);
if (ovpnManagementThread.openManagementInterface(this)) {
@@ -433,13 +446,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mManagement = ovpnManagementThread;
VpnStatus.logInfo("started Socket Thread");
} else {
- return START_NOT_STICKY;
+ endVpnService();
+ return;
}
}
-
Runnable processThread;
- if (mOvpn3) {
+ if (mOvpn3)
+
+ {
OpenVPNManagement mOpenVPN3 = instantiateOpenVPN3Core();
processThread = (Runnable) mOpenVPN3;
@@ -449,25 +464,53 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
} else {
HashMap<String, String> env = new HashMap<>();
processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory);
+ mOpenVPNThread = processThread;
}
- synchronized (mProcessLock) {
+ synchronized (mProcessLock)
+
+ {
mProcessThread = new Thread(processThread, "OpenVPNProcessThread");
mProcessThread.start();
}
- if (mDeviceStateReceiver != null)
- unregisterDeviceStateReceiver();
- registerDeviceStateReceiver(mManagement);
+ new Handler(getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ if (mDeviceStateReceiver != null)
+ unregisterDeviceStateReceiver();
+ registerDeviceStateReceiver(mManagement);
+ }
+ }
- ProfileManager.setConnectedVpnProfile(this, mProfile);
- /* TODO: At the moment we have no way to handle asynchronous PW input
- * Fixing will also allow to handle challenge/response authentication */
- if (mProfile.needUserPWInput(true) != 0)
- return START_NOT_STICKY;
+ );
+ }
- return START_STICKY;
+ private void stopOldOpenVPNProcess() {
+ if (mManagement != null) {
+ if (mOpenVPNThread!=null)
+ ((OpenVPNThread) mOpenVPNThread).setReplaceConnection();
+ if (mManagement.stopVPN(true)) {
+ // an old was asked to exit, wait 1s
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ //ignore
+ }
+ }
+ }
+
+ synchronized (mProcessLock) {
+ if (mProcessThread != null) {
+ mProcessThread.interrupt();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ //ignore
+ }
+ }
+ }
}
private OpenVPNManagement instantiateOpenVPN3Core() {
@@ -475,7 +518,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3");
return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile);
} catch (IllegalArgumentException | InstantiationException | InvocationTargetException |
- NoSuchMethodException | ClassNotFoundException | IllegalAccessException e ) {
+ NoSuchMethodException | ClassNotFoundException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
@@ -485,7 +528,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
public void onDestroy() {
synchronized (mProcessLock) {
if (mProcessThread != null) {
- mManagement.stopVPN();
+ mManagement.stopVPN(true);
}
}
@@ -581,7 +624,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// Check if the first DNS Server is in the VPN range
try {
ipAddress dnsServer = new ipAddress(new CIDRIP(mDnslist.get(0), 32), true);
- boolean dnsIncluded=false;
+ boolean dnsIncluded = false;
for (ipAddress net : positiveIPv4Routes) {
if (net.containsNet(dnsServer)) {
dnsIncluded = true;
@@ -620,8 +663,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
-
-
if (mDomain != null)
builder.addSearchDomain(mDomain);
@@ -716,7 +757,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setAllowedVpnPackages(Builder builder) {
- boolean atLeastOneAllowedApp=false;
+ boolean atLeastOneAllowedApp = false;
for (String pkg : mProfile.mAllowedAppsVpn) {
try {
if (mProfile.mAllowedAppsVpnAreDisallowed) {
@@ -910,7 +951,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// Does not work :(
String msg = getString(resid);
// showNotification(VpnStatus.getLastCleanLogMessage(this),
- // msg, lowpriority, 0, level);
+ // msg, lowpriority, 0, level);
}
}
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 10bc9e87..e0c39546 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
@@ -34,51 +34,56 @@ public class OpenVPNThread implements Runnable {
@SuppressLint("SdCardPath")
private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn";
private final static String BROKEN_PIE_SUPPORT2 = "syntax error";
- private static final String TAG = "OpenVPN";
+ 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<String, String> mProcessEnv;
- private boolean mBrokenPie=false;
-
- public OpenVPNThread(OpenVPNService service,String[] argv, Map<String,String> 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) {
+ private Process mProcess;
+ private String mNativeDir;
+ private OpenVPNService mService;
+ private String mDumpPath;
+ private Map<String, String> mProcessEnv;
+ private boolean mBrokenPie = false;
+ private boolean mNoProcessExitStatus = false;
+
+ public OpenVPNThread(OpenVPNService service, String[] argv, Map<String, String> processEnv, String nativelibdir) {
+ mArgv = argv;
+ mNativeDir = nativelibdir;
+ mService = service;
+ mProcessEnv = processEnv;
+ }
+
+ public void stopProcess() {
+ mProcess.destroy();
+ }
+
+ void setReplaceConnection()
+ {
+ mNoProcessExitStatus=true;
+ }
+
+ @Override
+ public void run() {
+ try {
+ Log.i(TAG, "Starting openvpn");
+ startOpenVPNThreadArgs(mArgv, mProcessEnv);
+ Log.i(TAG, "OpenVPN process exited");
+ } 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);
if (mBrokenPie) {
/* This will probably fail since the NoPIE binary is probably not written */
@@ -95,70 +100,72 @@ public class OpenVPNThread implements Runnable {
}
}
-
- 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<String, String> env) {
- LinkedList<String> argvlist = new LinkedList<String>();
+
+ if (!mNoProcessExitStatus)
+ 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<String, String> env) {
+ LinkedList<String> argvlist = new LinkedList<String>();
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<String,String> 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());
+
+ 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<String, String> 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());
if (logline.startsWith(BROKEN_PIE_SUPPORT) || logline.contains(BROKEN_PIE_SUPPORT2))
mBrokenPie = true;
-
+
// 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);
+ if (m.matches()) {
+ int flags = Integer.parseInt(m.group(3), 16);
String msg = m.group(4);
int logLevel = flags & 0x0F;
@@ -166,45 +173,45 @@ public class OpenVPNThread implements Runnable {
if ((flags & M_FATAL) != 0)
logStatus = VpnStatus.LogLevel.ERROR;
- else if ((flags & M_NONFATAL)!=0)
+ else if ((flags & M_NONFATAL) != 0)
logStatus = VpnStatus.LogLevel.WARNING;
- else if ((flags & M_WARN)!=0)
+ else if ((flags & M_WARN) != 0)
logStatus = VpnStatus.LogLevel.WARNING;
- else if ((flags & M_DEBUG)!=0)
+ 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);
+ 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].replaceFirst("/cache/.*$" , "/lib");
-
- String lbpath = pb.environment().get("LD_LIBRARY_PATH");
- if(lbpath==null)
- lbpath = applibpath;
- else
- lbpath = applibpath + ":" + lbpath;
-
- if (!applibpath.equals(mNativeDir)) {
- lbpath = mNativeDir + ":" + lbpath;
- }
- return lbpath;
- }
+ }
+
+
+ } 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].replaceFirst("/cache/.*$", "/lib");
+
+ String lbpath = pb.environment().get("LD_LIBRARY_PATH");
+ if (lbpath == null)
+ lbpath = applibpath;
+ else
+ lbpath = applibpath + ":" + lbpath;
+
+ if (!applibpath.equals(mNativeDir)) {
+ lbpath = mNativeDir + ":" + lbpath;
+ }
+ 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 4c550f47..569a3846 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -49,6 +49,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
private pauseReason lastPauseReason = pauseReason.noNetwork;
private PausedStateCallback mPauseCallback;
+ private boolean mShuttingDown;
public OpenVpnManagementThread(VpnProfile profile, OpenVPNService openVpnService) {
mProfile = profile;
@@ -223,7 +224,8 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
processByteCount(argument);
break;
case "STATE":
- processState(argument);
+ if (!mShuttingDown)
+ processState(argument);
break;
case "PROXY":
processProxyCMD(argument);
@@ -452,7 +454,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
break;
default:
- Log.e(TAG, "Unkown needok command " + argument);
+ Log.e(TAG, "Unknown needok command " + argument);
return;
}
@@ -621,7 +623,9 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
}
@Override
- public boolean stopVPN() {
+ public boolean stopVPN(boolean replaceConnection) {
+ mShuttingDown = true;
return stopOpenVPN();
}
+
}
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 f2cf8cec..78f462e7 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -27,7 +27,7 @@ public class VPNLaunchHelper {
- static private String writeMiniVPN(Context context) {
+ private static String writeMiniVPN(Context context) {
String[] abis;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
abis = getSupportedABIsLollipop();
@@ -73,12 +73,18 @@ public class VPNLaunchHelper {
}
- public static String[] buildOpenvpnArgv(Context c) {
+ static String[] buildOpenvpnArgv(Context c) {
Vector<String> args = new Vector<>();
+ String binaryName = writeMiniVPN(c);
// Add fixed paramenters
//args.add("/data/data/de.blinkt.openvpn/lib/openvpn");
- args.add(writeMiniVPN(c));
+ if(binaryName==null) {
+ VpnStatus.logError("Error writing minivpn binary");
+ return null;
+ }
+
+ args.add(binaryName);
args.add("--config");
args.add(getConfigFilePath(c));
@@ -126,14 +132,6 @@ public class VPNLaunchHelper {
public static void startOpenVpn(VpnProfile startprofile, Context context) {
- VpnStatus.logInfo(R.string.building_configration);
- VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, VpnStatus.ConnectionStatus.LEVEL_START);
- if(writeMiniVPN(context)==null) {
- VpnStatus.logError("Error writing minivpn binary");
- return;
- }
-
-
Intent startVPN = startprofile.prepareStartService(context);
if(startVPN!=null)
context.startService(startVPN);
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 3ac1595c..1e2ccba3 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
@@ -17,9 +17,12 @@ import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.Log;
import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
import java.io.File;
+import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.MessageDigest;
@@ -34,6 +37,7 @@ import java.util.Locale;
import java.util.UnknownFormatConversionException;
import java.util.Vector;
+import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
public class VpnStatus {
@@ -73,7 +77,7 @@ public class VpnStatus {
logException(LogLevel.ERROR, context, e);
}
- private static final int MAXLOGENTRIES = 1000;
+ static final int MAXLOGENTRIES = 1000;
public static String getLastCleanLogMessage(Context c) {
@@ -291,7 +295,6 @@ public class VpnStatus {
if (mArgs != null)
str += TextUtils.join("|", mArgs);
-
return str;
}
}
@@ -369,6 +372,16 @@ public class VpnStatus {
}
return mVerbosityLevel;
}
+
+ public boolean verify() {
+ if (mLevel == null)
+ return false;
+
+ if (mMessage == null && mRessourceId == 0)
+ return false;
+
+ return true;
+ }
}
public interface LogListener {
@@ -575,6 +588,9 @@ public class VpnStatus {
mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE));
}
+ if (BuildConfig.DEBUG && !cachedLine)
+ Log.d("OpenVPN", logItem.getString(null));
+
for (LogListener ll : logListener) {
ll.newLog(logItem);
@@ -613,8 +629,8 @@ public class VpnStatus {
public static synchronized void updateByteCount(long in, long out) {
long lastIn = mlastByteCount[0];
long lastOut = mlastByteCount[1];
- long diffIn = mlastByteCount[2] = in - lastIn;
- long diffOut = mlastByteCount[3] = out - lastOut;
+ long diffIn = mlastByteCount[2] = Math.max(0, in - lastIn);
+ long diffOut = mlastByteCount[3] = Math.max(0, out - lastOut);
mlastByteCount = new long[]{in, out, diffIn, diffOut};