diff options
author | cyBerta <cyberta@riseup.net> | 2018-10-19 23:15:13 +0200 |
---|---|---|
committer | cyBerta <cyberta@riseup.net> | 2018-10-19 23:15:13 +0200 |
commit | 74842cba92591aa9fbf64e8c6f39900a68b0c11c (patch) | |
tree | 3b81a830c7eff45b1dc04421201a4b675fc46c18 /app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java | |
parent | 6c994f657ecf88bdbb2480141b9904cc2eeac6ce (diff) |
#8919 update dependencies
Diffstat (limited to 'app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java')
-rw-r--r-- | app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java | 239 |
1 files changed, 178 insertions, 61 deletions
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 2b6df9af..4f7a5bda 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -6,16 +6,20 @@ package de.blinkt.openvpn.core; import android.content.Context; +import android.content.Intent; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; +import android.os.Build; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.support.annotation.NonNull; -import android.text.TextUtils; +import android.support.annotation.RequiresApi; +import android.system.ErrnoException; +import android.system.Os; import android.util.Log; - -import junit.framework.Assert; +import se.leap.bitmaskclient.R; +import de.blinkt.openvpn.VpnProfile; import java.io.FileDescriptor; import java.io.IOException; @@ -24,19 +28,13 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.Locale; -import java.util.Vector; - -import se.leap.bitmaskclient.BuildConfig; -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; +import java.util.*; public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { + public static final int ORBOT_TIMEOUT_MS = 20 * 1000; private static final String TAG = "openvpn"; + private static final Vector<OpenVpnManagementThread> active = new Vector<>(); private final Handler mResumeHandler; private LocalSocket mSocket; private VpnProfile mProfile; @@ -45,13 +43,55 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { private LocalServerSocket mServerSocket; private boolean mWaitingForRelease = false; private long mLastHoldRelease = 0; - - private static final Vector<OpenVpnManagementThread> active = new Vector<>(); private LocalSocket mServerSocketLocal; private pauseReason lastPauseReason = pauseReason.noNetwork; private PausedStateCallback mPauseCallback; private boolean mShuttingDown; + private Runnable mResumeHoldRunnable = () -> { + if (shouldBeRunning()) { + releaseHoldCmd(); + } + }; + private Runnable orbotStatusTimeOutRunnable = new Runnable() { + @Override + public void run() { + sendProxyCMD(Connection.ProxyType.SOCKS5, "127.0.0.1", Integer.toString(OrbotHelper.SOCKS_PROXY_PORT_DEFAULT), false); + OrbotHelper.get(mOpenVPNService).removeStatusCallback(statusCallback); + + } + }; + private OrbotHelper.StatusCallback statusCallback = new OrbotHelper.StatusCallback() { + + @Override + public void onStatus(Intent statusIntent) { + StringBuilder extras = new StringBuilder(); + for (String key : statusIntent.getExtras().keySet()) { + Object val = statusIntent.getExtras().get(key); + + extras.append(String.format(Locale.ENGLISH, "%s - '%s'", key, val == null ? "null" : val.toString())); + } + VpnStatus.logDebug("Got Orbot status: " + extras); + } + + @Override + public void onNotYetInstalled() { + VpnStatus.logDebug("Orbot not yet installed"); + } + + @Override + public void onOrbotReady(Intent intent, String socksHost, int socksPort) { + mResumeHandler.removeCallbacks(orbotStatusTimeOutRunnable); + sendProxyCMD(Connection.ProxyType.SOCKS5, socksHost, Integer.toString(socksPort), false); + OrbotHelper.get(mOpenVPNService).removeStatusCallback(this); + } + + @Override + public void onDisabled(Intent intent) { + VpnStatus.logWarning("Orbot integration for external applications is disabled. Waiting %ds before connecting to the default port. Enable external app integration in Orbot or use Socks v5 config instead of Orbot to avoid this delay."); + } + }; + private transient Connection mCurrentProxyConnection; public OpenVpnManagementThread(VpnProfile profile, OpenVPNService openVpnService) { mProfile = profile; @@ -60,14 +100,21 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } - private Runnable mResumeHoldRunnable = new Runnable() { - @Override - public void run() { - if (shouldBeRunning()) { - releaseHoldCmd(); + private static boolean stopOpenVPN() { + synchronized (active) { + boolean sendCMD = false; + for (OpenVpnManagementThread mt : active) { + sendCMD = mt.managmentCommand("signal SIGINT\n"); + try { + if (mt.mSocket != null) + mt.mSocket.close(); + } catch (IOException e) { + // Ignore close error on already closed socket + } } + return sendCMD; } - }; + } public boolean openManagementInterface(@NonNull Context c) { // Could take a while to open connection @@ -122,7 +169,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { return false; } - @Override public void run() { byte[] buffer = new byte[2048]; @@ -198,9 +244,13 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint); //pfd.close(); - NativeUtils.jniclose(fdint); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fdCloseLollipop(fd); + } else { + NativeUtils.jniclose(fdint); + } return; - } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) { + } catch ( NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) { VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")", e); } @@ -208,6 +258,15 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void fdCloseLollipop(FileDescriptor fd) { + try { + Os.close(fd); + } catch (Exception e) { + VpnStatus.logException("Failed to close fd (" + fd + ")", e); + } + } + private String processInput(String pendingInput) { @@ -223,11 +282,9 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { 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); @@ -263,6 +320,9 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { case "PK_SIGN": processSignCommand(argument); break; + case "INFOMSG": + processInfoMessage(argument); + break; default: VpnStatus.logWarning("MGMT: Got unrecognized command" + command); Log.i(TAG, "Got unrecognized command" + command); @@ -281,6 +341,14 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } } + private void processInfoMessage(String info) + { + if (info.startsWith("OPEN_URL:")) + { + mOpenVPNService.trigger_url_open(info); + } + } + private void processLogMessage(String argument) { String[] args = argument.split(",", 4); // 0 unix time stamp @@ -367,7 +435,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { //managmentCommand("log on all\n"); } - public void releaseHold() { if (mWaitingForRelease) releaseHoldCmd(); @@ -375,27 +442,81 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { private void processProxyCMD(String argument) { String[] args = argument.split(",", 3); - SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile); + Connection.ProxyType proxyType = Connection.ProxyType.NONE; + + int connectionEntryNumber = Integer.parseInt(args[0]) - 1; + String proxyport = null; + String proxyname = null; + boolean proxyUseAuth = false; + + if (mProfile.mConnections.length > connectionEntryNumber) { + Connection connection = mProfile.mConnections[connectionEntryNumber]; + proxyType = connection.mProxyType; + proxyname = connection.mProxyName; + proxyport = connection.mProxyPort; + proxyUseAuth = connection.mUseProxyAuth; + + // Use transient variable to remember http user/password + mCurrentProxyConnection = connection; + + } else { + VpnStatus.logError(String.format(Locale.ENGLISH, "OpenVPN is asking for a proxy of an unknown connection entry (%d)", connectionEntryNumber)); + } - if (args.length >= 2) { + // atuo detection of proxy + if (proxyType == Connection.ProxyType.NONE) { + SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile); + if (proxyaddr instanceof InetSocketAddress) { + InetSocketAddress isa = (InetSocketAddress) proxyaddr; + proxyType = Connection.ProxyType.HTTP; + proxyname = isa.getHostName(); + proxyport = String.valueOf(isa.getPort()); + proxyUseAuth = false; + + } + } + + + if (args.length >= 2 && proxyType == Connection.ProxyType.HTTP) { String proto = args[1]; if (proto.equals("UDP")) { - proxyaddr = null; + proxyname = null; + VpnStatus.logInfo("Not using an HTTP proxy since the connection uses UDP"); } } - if (proxyaddr instanceof InetSocketAddress) { - InetSocketAddress isa = (InetSocketAddress) proxyaddr; - VpnStatus.logInfo(R.string.using_proxy, isa.getHostName(), isa.getPort()); + if (proxyType == Connection.ProxyType.ORBOT) { + VpnStatus.updateStateString("WAIT_ORBOT", "Waiting for Orbot to start", R.string.state_waitorbot, ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET); + OrbotHelper orbotHelper = OrbotHelper.get(mOpenVPNService); + if (!orbotHelper.checkTorReceier(mOpenVPNService)) + VpnStatus.logError("Orbot does not seem to be installed!"); + + mResumeHandler.postDelayed(orbotStatusTimeOutRunnable, ORBOT_TIMEOUT_MS); + orbotHelper.addStatusCallback(mOpenVPNService, statusCallback); + + orbotHelper.sendOrbotStartAndStatusBroadcast(); + + } else { + sendProxyCMD(proxyType, proxyname, proxyport, proxyUseAuth); + } + } + + private void sendProxyCMD(Connection.ProxyType proxyType, String proxyname, String proxyport, boolean usePwAuth) { + if (proxyType != Connection.ProxyType.NONE && proxyname != null) { + + VpnStatus.logInfo(R.string.using_proxy, proxyname, proxyname); - String proxycmd = String.format(Locale.ENGLISH, "proxy HTTP %s %d\n", isa.getHostName(), isa.getPort()); + String pwstr = usePwAuth ? " auto" : ""; + + String proxycmd = String.format(Locale.ENGLISH, "proxy %s %s %s%s\n", + proxyType == Connection.ProxyType.HTTP ? "HTTP" : "SOCKS", + proxyname, proxyport, pwstr); managmentCommand(proxycmd); } else { managmentCommand("proxy NONE\n"); } - } private void processState(String argument) { @@ -408,7 +529,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { VpnStatus.updateStateString(currentstate, args[2]); } - private void processByteCount(String argument) { // >BYTECOUNT:{BYTES_IN},{BYTES_OUT} int comma = argument.indexOf(','); @@ -419,7 +539,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } - private void processNeedCommand(String argument) { int p1 = argument.indexOf('\''); int p2 = argument.indexOf('\'', p1 + 1); @@ -452,7 +571,8 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { */ if (routeparts.length == 5) { - if (BuildConfig.DEBUG) Assert.assertEquals("dev", routeparts[3]); + //if (BuildConfig.DEBUG) + // assertEquals("dev", routeparts[3]); mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]); } else if (routeparts.length >= 3) { mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null); @@ -473,8 +593,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1], mtu, ifconfigparts[3]); break; case "IFCONFIG6": - mOpenVPNService.setLocalIPv6(extra); - + String[] ifconfig6parts = extra.split(" "); + mtu = Integer.parseInt(ifconfig6parts[1]); + mOpenVPNService.setMtu(mtu); + mOpenVPNService.setLocalIPv6(ifconfig6parts[0]); break; case "PERSIST_TUN_ACTION": // check if tun cfg stayed the same @@ -546,6 +668,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { try { + // Ignore Auth token message, already managed by openvpn itself + if (argument.startsWith("Auth-Token:")) { + return; + } int p1 = argument.indexOf('\''); int p2 = argument.indexOf('\'', p1 + 1); @@ -560,17 +686,26 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } String pw = null; + String username = null; if (needed.equals("Private Key")) { pw = mProfile.getPasswordPrivateKey(); } else if (needed.equals("Auth")) { pw = mProfile.getPasswordAuth(); + username = mProfile.mUsername; - String usercmd = String.format("username '%s' %s\n", - needed, VpnProfile.openVpnEscape(mProfile.mUsername)); - managmentCommand(usercmd); + } else if (needed.equals("HTTP Proxy")) { + if( mCurrentProxyConnection != null) { + pw = mCurrentProxyConnection.mProxyAuthPassword; + username = mCurrentProxyConnection.mProxyAuthUser; + } } if (pw != null) { + if (username !=null) { + String usercmd = String.format("username '%s' %s\n", + needed, VpnProfile.openVpnEscape(username)); + managmentCommand(usercmd); + } String cmd = String.format("password '%s' %s\n", needed, VpnProfile.openVpnEscape(pw)); managmentCommand(cmd); } else { @@ -580,28 +715,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { } - 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() { - synchronized (active) { - boolean sendCMD = false; - for (OpenVpnManagementThread mt : active) { - sendCMD = mt.managmentCommand("signal SIGINT\n"); - try { - if (mt.mSocket != null) - mt.mSocket.close(); - } catch (IOException e) { - // Ignore close error on already closed socket - } - } - return sendCMD; - } - } - @Override public void networkChange(boolean samenetwork) { if (mWaitingForRelease) @@ -634,7 +751,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { private void processSignCommand(String b64data) { - String signed_string = mProfile.getSignedData(b64data); + String signed_string = mProfile.getSignedData(mOpenVPNService, b64data, false); if (signed_string == null) { managmentCommand("pk-sig\n"); |