diff options
Diffstat (limited to 'ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core')
16 files changed, 0 insertions, 4863 deletions
diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/CIDRIP.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/CIDRIP.java deleted file mode 100644 index e525abd5..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/CIDRIP.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import java.util.Locale; - -class CIDRIP { - String mIp; - int len; - - - public CIDRIP(String ip, String mask) { - mIp = ip; - long netmask = getInt(mask); - - // Add 33. bit to ensure the loop terminates - netmask += 1l << 32; - - int lenZeros = 0; - while ((netmask & 0x1) == 0) { - lenZeros++; - netmask = netmask >> 1; - } - // Check if rest of netmask is only 1s - if (netmask != (0x1ffffffffl >> lenZeros)) { - // Asume no CIDR, set /32 - len = 32; - } else { - len = 32 - lenZeros; - } - - } - - public CIDRIP(String address, int prefix_length) { - len = prefix_length; - mIp = address; - } - - @Override - public String toString() { - return String.format(Locale.ENGLISH, "%s/%d", mIp, len); - } - - public boolean normalise() { - long ip = getInt(mIp); - - long newip = ip & (0xffffffffl << (32 - len)); - if (newip != ip) { - mIp = String.format("%d.%d.%d.%d", (newip & 0xff000000) >> 24, (newip & 0xff0000) >> 16, (newip & 0xff00) >> 8, newip & 0xff); - return true; - } else { - return false; - } - } - - static long getInt(String ipaddr) { - String[] ipt = ipaddr.split("\\."); - long ip = 0; - - ip += Long.parseLong(ipt[0]) << 24; - ip += Integer.parseInt(ipt[1]) << 16; - ip += Integer.parseInt(ipt[2]) << 8; - ip += Integer.parseInt(ipt[3]); - - return ip; - } - - public long getInt() { - return getInt(mIp); - } - -}
\ No newline at end of file diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java deleted file mode 100644 index 5dc96bbc..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ /dev/null @@ -1,880 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.text.TextUtils; -import android.util.Pair; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Vector; - -import de.blinkt.openvpn.VpnProfile; - -//! Openvpn Config FIle Parser, probably not 100% accurate but close enough - -// And remember, this is valid :) -// --<foo> -// bar -// </foo> -public class ConfigParser { - - - public static final String CONVERTED_PROFILE = "converted Profile"; - private HashMap<String, Vector<Vector<String>>> options = new HashMap<String, Vector<Vector<String>>>(); - private HashMap<String, Vector<String>> meta = new HashMap<String, Vector<String>>(); - - public void parseConfig(Reader reader) throws IOException, ConfigParseError { - - - BufferedReader br = new BufferedReader(reader); - - int lineno = 0; - try { - while (true) { - String line = br.readLine(); - lineno++; - if (line == null) - break; - - if (lineno == 1 && (line.startsWith("PK\003\004") - || (line.startsWith("PK\007\008")))) - throw new ConfigParseError("Input looks like a ZIP Archive. Import is only possible for OpenVPN config files (.ovpn/.conf)"); - - // Check for OpenVPN Access Server Meta information - if (line.startsWith("# OVPN_ACCESS_SERVER_")) { - Vector<String> metaarg = parsemeta(line); - meta.put(metaarg.get(0), metaarg); - continue; - } - Vector<String> args = parseline(line); - - if (args.size() == 0) - continue; - - - if (args.get(0).startsWith("--")) - args.set(0, args.get(0).substring(2)); - - checkinlinefile(args, br); - - String optionname = args.get(0); - if (!options.containsKey(optionname)) { - options.put(optionname, new Vector<Vector<String>>()); - } - options.get(optionname).add(args); - } - } catch (java.lang.OutOfMemoryError memoryError) { - throw new ConfigParseError("File too large to parse: " + memoryError.getLocalizedMessage()); - } - } - - private Vector<String> parsemeta(String line) { - String meta = line.split("#\\sOVPN_ACCESS_SERVER_", 2)[1]; - String[] parts = meta.split("=",2); - Vector<String> rval = new Vector<String>(); - Collections.addAll(rval, parts); - return rval; - - } - - private void checkinlinefile(Vector<String> args, BufferedReader br) throws IOException, ConfigParseError { - String arg0 = args.get(0).trim(); - // CHeck for <foo> - if(arg0.startsWith("<") && arg0.endsWith(">")) { - String argname = arg0.substring(1, arg0.length()-1); - String inlinefile = VpnProfile.INLINE_TAG; - - String endtag = String.format("</%s>",argname); - do { - String line = br.readLine(); - if(line==null){ - throw new ConfigParseError(String.format("No endtag </%s> for starttag <%s> found",argname,argname)); - } - if(line.trim().equals(endtag)) - break; - else { - inlinefile+=line; - inlinefile+= "\n"; - } - } while(true); - - args.clear(); - args.add(argname); - args.add(inlinefile); - } - - } - - enum linestate { - initial, - readin_single_quote - , reading_quoted, reading_unquoted, done} - - private boolean space(char c) { - // I really hope nobody is using zero bytes inside his/her config file - // to sperate parameter but here we go: - return Character.isWhitespace(c) || c == '\0'; - - } - - public class ConfigParseError extends Exception { - private static final long serialVersionUID = -60L; - - public ConfigParseError(String msg) { - super(msg); - } - } - - - // adapted openvpn's parse function to java - private Vector<String> parseline(String line) throws ConfigParseError { - Vector<String> parameters = new Vector<String>(); - - if (line.length()==0) - return parameters; - - - linestate state = linestate.initial; - boolean backslash = false; - char out=0; - - int pos=0; - String currentarg=""; - - do { - // Emulate the c parsing ... - char in; - if(pos < line.length()) - in = line.charAt(pos); - else - in = '\0'; - - if (!backslash && in == '\\' && state != linestate.readin_single_quote) - { - backslash = true; - } - else - { - if (state == linestate.initial) - { - if (!space (in)) - { - if (in == ';' || in == '#') /* comment */ - break; - if (!backslash && in == '\"') - state = linestate.reading_quoted; - else if (!backslash && in == '\'') - state = linestate.readin_single_quote; - else - { - out = in; - state = linestate.reading_unquoted; - } - } - } - else if (state == linestate.reading_unquoted) - { - if (!backslash && space (in)) - state = linestate.done; - else - out = in; - } - else if (state == linestate.reading_quoted) - { - if (!backslash && in == '\"') - state = linestate.done; - else - out = in; - } - else if (state == linestate.readin_single_quote) - { - if (in == '\'') - state = linestate.done; - else - out = in; - } - - if (state == linestate.done) - { - /* ASSERT (parm_len > 0); */ - state = linestate.initial; - parameters.add(currentarg); - currentarg = ""; - out =0; - } - - if (backslash && out!=0) - { - if (!(out == '\\' || out == '\"' || space (out))) - { - throw new ConfigParseError("Options warning: Bad backslash ('\\') usage"); - } - } - backslash = false; - } - - /* store parameter character */ - if (out!=0) - { - currentarg+=out; - } - } while (pos++ < line.length()); - - return parameters; - } - - - final String[] unsupportedOptions = { "config", - "tls-server" - - }; - - // Ignore all scripts - // in most cases these won't work and user who wish to execute scripts will - // figure out themselves - final String[] ignoreOptions = { "tls-client", - "askpass", - "auth-nocache", - "up", - "down", - "route-up", - "ipchange", - "route-up", - "route-pre-down", - "auth-user-pass-verify", - "dhcp-release", - "dhcp-renew", - "dh", - "group", - "ip-win32", - "management-hold", - "management", - "management-client", - "management-query-remote", - "management-query-passwords", - "management-query-proxy", - "management-external-key", - "management-forget-disconnect", - "management-signal", - "management-log-cache", - "management-up-down", - "management-client-user", - "management-client-group", - "pause-exit", - "plugin", - "machine-readable-output", - "persist-key", - "register-dns", - "route-delay", - "route-gateway", - "route-metric", - "route-method", - "status", - "script-security", - "show-net-up", - "suppress-timestamps", - "tmp-dir", - "tun-ipv6", - "topology", - "user", - "win-sys", - - }; - - final String[][] ignoreOptionsWithArg = - { - {"setenv", "IV_GUI_VER"}, - {"setenv", "IV_OPENVPN_GUI_VERSION"} - }; - - final String[] connectionOptions = { - "local", - "remote", - "float", - "port", - "connect-retry", - "connect-timeout", - "connect-retry-max", - "link-mtu", - "tun-mtu", - "tun-mtu-extra", - "fragment", - "mtu-disc", - "local-port", - "remote-port", - "bind", - "nobind", - "proto", - "http-proxy", - "http-proxy-retry", - "http-proxy-timeout", - "http-proxy-option", - "socks-proxy", - "socks-proxy-retry", - "explicit-exit-notify", - "mssfix" - }; - - - // This method is far too long - @SuppressWarnings("ConstantConditions") - public VpnProfile convertProfile() throws ConfigParseError, IOException { - boolean noauthtypeset=true; - VpnProfile np = new VpnProfile(CONVERTED_PROFILE); - // Pull, client, tls-client - np.clearDefaults(); - - if(options.containsKey("client") || options.containsKey("pull")) { - np.mUsePull=true; - options.remove("pull"); - options.remove("client"); - } - - Vector<String> secret = getOption("secret", 1, 2); - if(secret!=null) - { - np.mAuthenticationType=VpnProfile.TYPE_STATICKEYS; - noauthtypeset=false; - np.mUseTLSAuth=true; - np.mTLSAuthFilename=secret.get(1); - if(secret.size()==3) - np.mTLSAuthDirection=secret.get(2); - - } - - Vector<Vector<String>> routes = getAllOption("route", 1, 4); - if(routes!=null) { - String routeopt = ""; - String routeExcluded = ""; - for(Vector<String> route:routes){ - String netmask = "255.255.255.255"; - String gateway = "vpn_gateway"; - - if(route.size() >= 3) - netmask = route.get(2); - if (route.size() >= 4) - gateway = route.get(3); - - String net = route.get(1); - try { - CIDRIP cidr = new CIDRIP(net, netmask); - if (gateway.equals("net_gateway")) - routeExcluded += cidr.toString() + " "; - else - routeopt+=cidr.toString() + " "; - } catch (ArrayIndexOutOfBoundsException aioob) { - throw new ConfigParseError("Could not parse netmask of route " + netmask); - } catch (NumberFormatException ne) { - - - - - throw new ConfigParseError("Could not parse netmask of route " + netmask); - } - - } - np.mCustomRoutes=routeopt; - np.mExcludedRoutes=routeExcluded; - } - - Vector<Vector<String>> routesV6 = getAllOption("route-ipv6", 1, 4); - if (routesV6!=null) { - String customIPv6Routes = ""; - for (Vector<String> route:routesV6){ - customIPv6Routes += route.get(1) + " "; - } - - np.mCustomRoutesv6 = customIPv6Routes; - } - - // Also recognize tls-auth [inline] direction ... - Vector<Vector<String>> tlsauthoptions = getAllOption("tls-auth", 1, 2); - if(tlsauthoptions!=null) { - for(Vector<String> tlsauth:tlsauthoptions) { - if(tlsauth!=null) - { - if(!tlsauth.get(1).equals("[inline]")) { - np.mTLSAuthFilename=tlsauth.get(1); - np.mUseTLSAuth=true; - } - if(tlsauth.size()==3) - np.mTLSAuthDirection=tlsauth.get(2); - } - } - } - - Vector<String> direction = getOption("key-direction", 1, 1); - if(direction!=null) - np.mTLSAuthDirection=direction.get(1); - - Vector<Vector<String>> defgw = getAllOption("redirect-gateway", 0, 5); - if(defgw != null) - { - np.mUseDefaultRoute=true; - checkRedirectParameters(np, defgw); - } - - Vector<Vector<String>> redirectPrivate = getAllOption("redirect-private",0,5); - if (redirectPrivate != null) - { - checkRedirectParameters(np,redirectPrivate); - } - Vector<String> dev =getOption("dev",1,1); - Vector<String> devtype =getOption("dev-type",1,1); - - if ((devtype != null && devtype.get(1).equals("tun")) || - (dev != null && dev.get(1).startsWith("tun")) || - (devtype == null && dev == null)) { - //everything okay - } else { - throw new ConfigParseError("Sorry. Only tun mode is supported. See the FAQ for more detail"); - } - - Vector<String> mssfix = getOption("mssfix",0,1); - - if (mssfix!=null) { - if (mssfix.size()>=2) { - try { - np.mMssFix=Integer.parseInt(mssfix.get(1)); - } catch(NumberFormatException e) { - throw new ConfigParseError("Argument to --mssfix has to be an integer"); - } - } else { - np.mMssFix = VpnProfile.DEFAULT_MSSFIX_SIZE; - } - } - - - Vector<String> mode =getOption("mode",1,1); - if (mode != null){ - if(!mode.get(1).equals("p2p")) - throw new ConfigParseError("Invalid mode for --mode specified, need p2p"); - } - - - - Vector<Vector<String>> dhcpoptions = getAllOption("dhcp-option", 2, 2); - if(dhcpoptions!=null) { - for(Vector<String> dhcpoption:dhcpoptions) { - String type=dhcpoption.get(1); - String arg = dhcpoption.get(2); - if(type.equals("DOMAIN")) { - np.mSearchDomain=dhcpoption.get(2); - } else if(type.equals("DNS")) { - np.mOverrideDNS=true; - if(np.mDNS1.equals(VpnProfile.DEFAULT_DNS1)) - np.mDNS1=arg; - else - np.mDNS2=arg; - } - } - } - - Vector<String> ifconfig = getOption("ifconfig", 2, 2); - if(ifconfig!=null) { - try { - CIDRIP cidr = new CIDRIP(ifconfig.get(1), ifconfig.get(2)); - np.mIPv4Address=cidr.toString(); - } catch (NumberFormatException nfe) { - throw new ConfigParseError("Could not pase ifconfig IP address: " + nfe.getLocalizedMessage()); - } - - } - - if(getOption("remote-random-hostname", 0, 0)!=null) - np.mUseRandomHostname=true; - - if(getOption("float", 0, 0)!=null) - np.mUseFloat=true; - - if(getOption("comp-lzo", 0, 1)!=null) - np.mUseLzo=true; - - Vector<String> cipher = getOption("cipher", 1, 1); - if(cipher!=null) - np.mCipher= cipher.get(1); - - Vector<String> auth = getOption("auth", 1, 1); - if(auth!=null) - np.mAuth = auth.get(1); - - - Vector<String> ca = getOption("ca",1,1); - if(ca!=null){ - np.mCaFilename = ca.get(1); - } - - Vector<String> cert = getOption("cert",1,1); - if(cert!=null){ - np.mClientCertFilename = cert.get(1); - np.mAuthenticationType = VpnProfile.TYPE_CERTIFICATES; - noauthtypeset=false; - } - Vector<String> key= getOption("key",1,1); - if(key!=null) - np.mClientKeyFilename=key.get(1); - - Vector<String> pkcs12 = getOption("pkcs12",1,1); - if(pkcs12!=null) { - np.mPKCS12Filename = pkcs12.get(1); - np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE; - noauthtypeset=false; - } - - Vector<String> cryptoapicert = getOption("cryptoapicert",1,1); - if(cryptoapicert!=null) { - np.mAuthenticationType = VpnProfile.TYPE_KEYSTORE; - noauthtypeset=false; - } - - Vector<String> compatnames = getOption("compat-names",1,2); - Vector<String> nonameremapping = getOption("no-name-remapping",1,1); - Vector<String> tlsremote = getOption("tls-remote",1,1); - if(tlsremote!=null){ - np.mRemoteCN = tlsremote.get(1); - np.mCheckRemoteCN=true; - np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE; - - if((compatnames!=null && compatnames.size() > 2) || - (nonameremapping!=null)) - np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_COMPAT_NOREMAPPING; - } - - Vector<String> verifyx509name = getOption("verify-x509-name",1,2); - if(verifyx509name!=null){ - np.mRemoteCN = verifyx509name.get(1); - np.mCheckRemoteCN=true; - if(verifyx509name.size()>2) { - if (verifyx509name.get(2).equals("name")) - np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN; - else if (verifyx509name.get(2).equals("name-prefix")) - np.mX509AuthType=VpnProfile.X509_VERIFY_TLSREMOTE_RDN_PREFIX; - else - throw new ConfigParseError("Unknown parameter to x509-verify-name: " + verifyx509name.get(2) ); - } else { - np.mX509AuthType = VpnProfile.X509_VERIFY_TLSREMOTE_DN; - } - - } - - - Vector<String> verb = getOption("verb",1,1); - if(verb!=null){ - np.mVerb=verb.get(1); - } - - - if(getOption("nobind", 0, 0) != null) - np.mNobind=true; - - if(getOption("persist-tun", 0,0) != null) - np.mPersistTun=true; - - Vector<String> connectretry = getOption("connect-retry", 1, 1); - if(connectretry!=null) - np.mConnectRetry =connectretry.get(1); - - Vector<String> connectretrymax = getOption("connect-retry-max", 1, 1); - if(connectretrymax!=null) - np.mConnectRetryMax =connectretrymax.get(1); - - Vector<Vector<String>> remotetls = getAllOption("remote-cert-tls", 1, 1); - if(remotetls!=null) - if(remotetls.get(0).get(1).equals("server")) - np.mExpectTLSCert=true; - else - options.put("remotetls",remotetls); - - Vector<String> authuser = getOption("auth-user-pass",0,1); - if(authuser !=null){ - if(noauthtypeset) { - np.mAuthenticationType=VpnProfile.TYPE_USERPASS; - } else if(np.mAuthenticationType==VpnProfile.TYPE_CERTIFICATES) { - np.mAuthenticationType=VpnProfile.TYPE_USERPASS_CERTIFICATES; - } else if(np.mAuthenticationType==VpnProfile.TYPE_KEYSTORE) { - np.mAuthenticationType=VpnProfile.TYPE_USERPASS_KEYSTORE; - } - if(authuser.size()>1) { - // Set option value to password get to embed later. - np.mUsername=null; - useEmbbedUserAuth(np, authuser.get(1)); - } - } - - Pair<Connection, Connection[]> conns = parseConnectionOptions(null); - np.mConnections =conns.second; - - Vector<Vector<String>> connectionBlocks = getAllOption("connection", 1, 1); - - if (np.mConnections.length > 0 && connectionBlocks !=null ) { - throw new ConfigParseError("Using a <connection> block and --remote is not allowed."); - } - - if (connectionBlocks!=null) { - np.mConnections = new Connection[connectionBlocks.size()]; - - int connIndex = 0; - for (Vector<String> conn : connectionBlocks) { - Pair<Connection, Connection[]> connectionBlockConnection = - parseConnection(conn.get(1), conns.first); - - if (connectionBlockConnection.second.length != 1) - throw new ConfigParseError("A <connection> block must have exactly one remote"); - np.mConnections[connIndex] = connectionBlockConnection.second[0]; - connIndex++; - } - } - if(getOption("remote-random", 0, 0) != null) - np.mRemoteRandom=true; - - Vector<String> protoforce = getOption("proto-force", 1, 1); - if(protoforce!=null) { - boolean disableUDP; - String protoToDisable = protoforce.get(1); - if (protoToDisable.equals("udp")) - disableUDP=true; - else if (protoToDisable.equals("tcp")) - disableUDP=false; - else - throw new ConfigParseError(String.format("Unknown protocol %s in proto-force", protoToDisable)); - - for (Connection conn:np.mConnections) - if(conn.mUseUdp==disableUDP) - conn.mEnabled=false; - } - - // Parse OpenVPN Access Server extra - Vector<String> friendlyname = meta.get("FRIENDLY_NAME"); - if(friendlyname !=null && friendlyname.size() > 1) - np.mName=friendlyname.get(1); - - - Vector<String> ocusername = meta.get("USERNAME"); - if(ocusername !=null && ocusername.size() > 1) - np.mUsername=ocusername.get(1); - - checkIgnoreAndInvalidOptions(np); - fixup(np); - - return np; - } - - private Pair<Connection, Connection[]> parseConnection(String connection, Connection defaultValues) throws IOException, ConfigParseError { - // Parse a connection Block as a new configuration file - - - ConfigParser connectionParser = new ConfigParser(); - StringReader reader = new StringReader(connection.substring(VpnProfile.INLINE_TAG.length())); - connectionParser.parseConfig(reader); - - Pair<Connection, Connection[]> conn = connectionParser.parseConnectionOptions(defaultValues); - - return conn; - } - - private Pair<Connection, Connection[]> parseConnectionOptions(Connection connDefault) throws ConfigParseError { - Connection conn; - if (connDefault!=null) - try { - conn = connDefault.clone(); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - return null; - } - else - conn = new Connection(); - - Vector<String> port = getOption("port", 1,1); - if(port!=null){ - conn.mServerPort = port.get(1); - } - - Vector<String> rport = getOption("rport", 1,1); - if(rport!=null){ - conn.mServerPort = rport.get(1); - } - - Vector<String> proto = getOption("proto", 1,1); - if(proto!=null){ - conn.mUseUdp=isUdpProto(proto.get(1)); - } - - - // Parse remote config - Vector<Vector<String>> remotes = getAllOption("remote",1,3); - - - // Assume that we need custom options if connectionDefault are set - if(connDefault!=null) { - for (Vector<Vector<String>> option : options.values()) { - - conn.mCustomConfiguration += getOptionStrings(option); - - } - if (!TextUtils.isEmpty(conn.mCustomConfiguration)) - conn.mUseCustomConfig = true; - } - // Make remotes empty to simplify code - if (remotes==null) - remotes = new Vector<Vector<String>>(); - - Connection[] connections = new Connection[remotes.size()]; - - - int i=0; - for (Vector<String> remote: remotes) { - try { - connections[i] = conn.clone(); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - switch (remote.size()) { - case 4: - connections[i].mUseUdp=isUdpProto(remote.get(3)); - case 3: - connections[i].mServerPort = remote.get(2); - case 2: - connections[i].mServerName = remote.get(1); - } - i++; - } - return Pair.create(conn, connections); - - } - - private void checkRedirectParameters(VpnProfile np, Vector<Vector<String>> defgw) { - for (Vector<String> redirect: defgw) - for (int i=1;i<redirect.size();i++){ - if (redirect.get(i).equals("block-local")) - np.mAllowLocalLAN=false; - else if (redirect.get(i).equals("unblock-local")) - np.mAllowLocalLAN=true; - } - } - - private boolean isUdpProto(String proto) throws ConfigParseError { - boolean isudp; - if(proto.equals("udp") || proto.equals("udp6")) - isudp=true; - else if (proto.equals("tcp-client") || - proto.equals("tcp") || - proto.equals("tcp6") || - proto.endsWith("tcp6-client")) - isudp =false; - else - throw new ConfigParseError("Unsupported option to --proto " + proto); - return isudp; - } - - static public void useEmbbedUserAuth(VpnProfile np, String inlinedata) - { - String data = VpnProfile.getEmbeddedContent(inlinedata); - String[] parts = data.split("\n"); - if(parts.length >= 2) { - np.mUsername=parts[0]; - np.mPassword=parts[1]; - } - } - - private void checkIgnoreAndInvalidOptions(VpnProfile np) throws ConfigParseError { - for(String option:unsupportedOptions) - if(options.containsKey(option)) - throw new ConfigParseError(String.format("Unsupported Option %s encountered in config file. Aborting",option)); - - for(String option:ignoreOptions) - // removing an item which is not in the map is no error - options.remove(option); - - - - - if(options.size()> 0) { - np.mCustomConfigOptions += "# These Options were found in the config file do not map to config settings:\n"; - - for(Vector<Vector<String>> option:options.values()) { - - np.mCustomConfigOptions += getOptionStrings(option); - - } - np.mUseCustomConfig=true; - - } - } - - - boolean ignoreThisOption(Vector<String> option) { - for (String[] ignoreOption : ignoreOptionsWithArg) { - - if (option.size() < ignoreOption.length) - continue; - - boolean ignore = true; - for (int i = 0; i < ignoreOption.length; i++) { - if (!ignoreOption[i].equals(option.get(i))) - ignore = false; - } - if (ignore) - return true; - - } - return false; - } - - private String getOptionStrings(Vector<Vector<String>> option) { - String custom = ""; - for (Vector<String> optionsline : option) { - if (!ignoreThisOption(optionsline)) { - for (String arg : optionsline) - custom += VpnProfile.openVpnEscape(arg) + " "; - custom += "\n"; - } - } - return custom; - } - - - private void fixup(VpnProfile np) { - if(np.mRemoteCN.equals(np.mServerName)) { - np.mRemoteCN=""; - } - } - - private Vector<String> getOption(String option, int minarg, int maxarg) throws ConfigParseError { - Vector<Vector<String>> alloptions = getAllOption(option, minarg, maxarg); - if(alloptions==null) - return null; - else - return alloptions.lastElement(); - } - - - private Vector<Vector<String>> getAllOption(String option, int minarg, int maxarg) throws ConfigParseError { - Vector<Vector<String>> args = options.get(option); - if(args==null) - return null; - - for(Vector<String> optionline:args) - - if(optionline.size()< (minarg+1) || optionline.size() > maxarg+1) { - String err = String.format(Locale.getDefault(),"Option %s has %d parameters, expected between %d and %d", - option,optionline.size()-1,minarg,maxarg ); - throw new ConfigParseError(err); - } - options.remove(option); - return args; - } - -} - - - - diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java deleted file mode 100644 index 4ccf5472..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -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<Datapoint> trafficdata = new LinkedList<DeviceStateReceiver.Datapoint>(); - - @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 (lastNetwork == -1) { - mManagement.resume(); - } 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/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java deleted file mode 100644 index 56a574dc..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; -import android.app.Application; - -/* -import org.acra.ACRA; -import org.acra.ReportingInteractionMode; -import org.acra.annotation.ReportsCrashes; -*/ - -import se.leap.bitmaskclient.BuildConfig; -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.core.PRNGFixes; - -/* -@ReportsCrashes( - formKey = "", - formUri = "http://reports.blinkt.de/report-icsopenvpn", - reportType = org.acra.sender.HttpSender.Type.JSON, - httpMethod = org.acra.sender.HttpSender.Method.PUT, - formUriBasicAuthLogin="report-icsopenvpn", - formUriBasicAuthPassword="Tohd4neiF9Ai!!!!111eleven", - mode = ReportingInteractionMode.TOAST, - resToastText = R.string.crash_toast_text -) -*/ -public class ICSOpenVPNApplication extends Application { - @Override - public void onCreate() { - super.onCreate(); - PRNGFixes.apply(); - - if (BuildConfig.DEBUG) { - //ACRA.init(this); - } - } - -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java deleted file mode 100644 index f67b7730..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NativeUtils.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import java.security.InvalidKeyException; - -public class NativeUtils { - public static native byte[] rsasign(byte[] input,int pkey) throws InvalidKeyException; - public static native String[] getIfconfig() throws IllegalArgumentException; - static native void jniclose(int fdint); - - static { - System.loadLibrary("stlport_shared"); - System.loadLibrary("opvpnutil"); - } -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java deleted file mode 100644 index 26354689..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.os.Build; -import android.text.TextUtils; - -import junit.framework.Assert; - -import org.jetbrains.annotations.NotNull; - -import java.math.BigInteger; -import java.net.Inet6Address; -import java.util.*; - -import se.leap.bitmaskclient.BuildConfig; - -public class NetworkSpace { - - - - - static class ipAddress implements Comparable<ipAddress> { - private BigInteger netAddress; - public int networkMask; - private boolean included; - private boolean isV4; - private BigInteger firstAddress; - private BigInteger lastAddress; - - - /** - * sorts the networks with following criteria: - * 1. compares first 1 of the network - * 2. smaller networks are returned as smaller - */ - @Override - public int compareTo(@NotNull ipAddress another) { - int comp = getFirstAddress().compareTo(another.getFirstAddress()); - if (comp != 0) - return comp; - - - if (networkMask > another.networkMask) - return -1; - else if (another.networkMask == networkMask) - return 0; - else - return 1; - } - - /** - * Warning ignores the included integer - * - * @param o - * the object to compare this instance with. - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof ipAddress)) - return super.equals(o); - - - ipAddress on = (ipAddress) o; - return (networkMask == on.networkMask) && on.getFirstAddress().equals(getFirstAddress()); - } - - public ipAddress(CIDRIP ip, boolean include) { - included = include; - netAddress = BigInteger.valueOf(ip.getInt()); - networkMask = ip.len; - isV4 = true; - } - - public ipAddress(Inet6Address address, int mask, boolean include) { - networkMask = mask; - included = include; - - int s = 128; - - netAddress = BigInteger.ZERO; - for (byte b : address.getAddress()) { - s -= 8; - netAddress = netAddress.add(BigInteger.valueOf((b & 0xFF)).shiftLeft(s)); - } - } - - public BigInteger getLastAddress() { - if(lastAddress ==null) - lastAddress = getMaskedAddress(true); - return lastAddress; - } - - - public BigInteger getFirstAddress() { - if (firstAddress ==null) - firstAddress =getMaskedAddress(false); - return firstAddress; - } - - - private BigInteger getMaskedAddress(boolean one) { - BigInteger numAddress = netAddress; - - int numBits; - if (isV4) { - numBits = 32 - networkMask; - } else { - numBits = 128 - networkMask; - } - - for (int i = 0; i < numBits; i++) { - if (one) - numAddress = numAddress.setBit(i); - else - numAddress = numAddress.clearBit(i); - } - return numAddress; - } - - - @Override - public String toString() { - //String in = included ? "+" : "-"; - if (isV4) - return String.format(Locale.US,"%s/%d", getIPv4Address(), networkMask); - else - return String.format(Locale.US, "%s/%d", getIPv6Address(), networkMask); - } - - ipAddress(BigInteger baseAddress, int mask, boolean included, boolean isV4) { - this.netAddress = baseAddress; - this.networkMask = mask; - this.included = included; - this.isV4 = isV4; - } - - - public ipAddress[] split() { - ipAddress firstHalf = new ipAddress(getFirstAddress(), networkMask + 1, included, isV4); - ipAddress secondHalf = new ipAddress(firstHalf.getLastAddress().add(BigInteger.ONE), networkMask + 1, included, isV4); - if (BuildConfig.DEBUG) Assert.assertTrue(secondHalf.getLastAddress().equals(getLastAddress())); - return new ipAddress[]{firstHalf, secondHalf}; - } - - String getIPv4Address() { - if (BuildConfig.DEBUG) { - Assert.assertTrue (isV4); - Assert.assertTrue (netAddress.longValue() <= 0xffffffffl); - Assert.assertTrue (netAddress.longValue() >= 0); - } - long ip = netAddress.longValue(); - return String.format(Locale.US, "%d.%d.%d.%d", (ip >> 24) % 256, (ip >> 16) % 256, (ip >> 8) % 256, ip % 256); - } - - String getIPv6Address() { - if (BuildConfig.DEBUG) Assert.assertTrue (!isV4); - BigInteger r = netAddress; - if (r.compareTo(BigInteger.ZERO)==0 && networkMask==0) - return "::"; - - Vector<String> parts = new Vector<String>(); - while (r.compareTo(BigInteger.ZERO) == 1) { - parts.add(0, String.format(Locale.US, "%x", r.mod(BigInteger.valueOf(0x10000)).longValue())); - r = r.shiftRight(16); - } - - return TextUtils.join(":", parts); - } - - public boolean containsNet(ipAddress network) { - return getFirstAddress().compareTo(network.getFirstAddress()) != 1 && - getLastAddress().compareTo(network.getLastAddress()) != -1; - } - } - - - TreeSet<ipAddress> mIpAddresses = new TreeSet<ipAddress>(); - - - public Collection<ipAddress> getNetworks(boolean included) { - Vector<ipAddress> ips = new Vector<ipAddress>(); - for (ipAddress ip : mIpAddresses) { - if (ip.included == included) - ips.add(ip); - } - return ips; - } - - public void clear() { - mIpAddresses.clear(); - } - - - void addIP(CIDRIP cidrIp, boolean include) { - - mIpAddresses.add(new ipAddress(cidrIp, include)); - } - - public void addIPSplit(CIDRIP cidrIp, boolean include) { - ipAddress newIP = new ipAddress(cidrIp, include); - ipAddress[] splitIps = newIP.split(); - for (ipAddress split: splitIps) - mIpAddresses.add(split); - } - - void addIPv6(Inet6Address address, int mask, boolean included) { - mIpAddresses.add(new ipAddress(address, mask, included)); - } - - TreeSet<ipAddress> generateIPList() { - - PriorityQueue<ipAddress> networks = new PriorityQueue<ipAddress>(mIpAddresses); - - TreeSet<ipAddress> ipsDone = new TreeSet<ipAddress>(); - - ipAddress currentNet = networks.poll(); - if (currentNet==null) - return ipsDone; - - while (currentNet!=null) { - // Check if it and the next of it are compatible - ipAddress nextNet = networks.poll(); - - if (BuildConfig.DEBUG) Assert.assertNotNull(currentNet); - if (nextNet== null || currentNet.getLastAddress().compareTo(nextNet.getFirstAddress()) == -1) { - // Everything good, no overlapping nothing to do - ipsDone.add(currentNet); - - currentNet = nextNet; - } else { - // This network is smaller or equal to the next but has the same base address - if (currentNet.getFirstAddress().equals(nextNet.getFirstAddress()) && currentNet.networkMask >= nextNet.networkMask) { - if (currentNet.included == nextNet.included) { - // Included in the next next and same type - // Simply forget our current network - currentNet=nextNet; - } else { - // our currentNet is included in next and types differ. Need to split the next network - ipAddress[] newNets = nextNet.split(); - - - // TODO: The contains method of the Priority is stupid linear search - - // First add the second half to keep the order in networks - if (!networks.contains(newNets[1])) - networks.add(newNets[1]); - - if (newNets[0].getLastAddress().equals(currentNet.getLastAddress())) { - if (BuildConfig.DEBUG) Assert.assertEquals (newNets[0].networkMask, currentNet.networkMask); - // Don't add the lower half that would conflict with currentNet - } else { - if (!networks.contains(newNets[0])) - networks.add(newNets[0]); - } - // Keep currentNet as is - } - } else { - if (BuildConfig.DEBUG) { - Assert.assertTrue(currentNet.networkMask < nextNet.networkMask); - Assert.assertTrue (nextNet.getFirstAddress().compareTo(currentNet.getFirstAddress()) == 1); - Assert.assertTrue (currentNet.getLastAddress().compareTo(nextNet.getLastAddress()) != -1); - } - // This network is bigger than the next and last ip of current >= next - - //noinspection StatementWithEmptyBody - if (currentNet.included == nextNet.included) { - // Next network is in included in our network with the same type, - // simply ignore the next and move on - } else { - // We need to split our network - ipAddress[] newNets = currentNet.split(); - - - if (newNets[1].networkMask == nextNet.networkMask) { - if (BuildConfig.DEBUG) { - Assert.assertTrue (newNets[1].getFirstAddress().equals(nextNet.getFirstAddress())); - Assert.assertTrue (newNets[1].getLastAddress().equals(currentNet.getLastAddress())); - // split second equal the next network, do not add it - } - networks.add(nextNet); - } else { - // Add the smaller network first - networks.add(newNets[1]); - networks.add(nextNet); - } - currentNet = newNets[0]; - - } - } - } - - } - - return ipsDone; - } - - Collection<ipAddress> getPositiveIPList() { - TreeSet<ipAddress> ipsSorted = generateIPList(); - - Vector<ipAddress> ips = new Vector<ipAddress>(); - for (ipAddress ia : ipsSorted) { - if (ia.included) - ips.add(ia); - } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - // Include postive routes from the original set under < 4.4 since these might overrule the local - // network but only if no smaller negative route exists - for(ipAddress origIp: mIpAddresses){ - if (!origIp.included) - continue; - - // The netspace exists - if(ipsSorted.contains(origIp)) - continue; - - boolean skipIp=false; - // If there is any smaller net that is excluded we may not add the positive route back - for (ipAddress calculatedIp: ipsSorted) { - if(!calculatedIp.included && origIp.containsNet(calculatedIp)) { - skipIp=true; - break; - } - } - if (skipIp) - continue; - - // It is safe to include the IP - ips.add(origIp); - } - - } - - return ips; - } - -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java deleted file mode 100644 index 1f28c77d..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -public interface OpenVPNManagement { - enum pauseReason { - noNetwork, - userPause, - screenOff - } - - int mBytecountInterval =2; - - void reconnect(); - - void pause(pauseReason reason); - - void resume(); - - boolean stopVPN(); - - /* - * Rebind the interface - */ - void networkChange(); -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java deleted file mode 100644 index 578d95e7..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ /dev/null @@ -1,934 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.Manifest.permission; -import android.annotation.TargetApi; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.NetworkRequest; -import android.net.VpnService; -import android.os.Binder; -import android.os.Build; -import android.os.Handler.Callback; -import android.os.IBinder; -import android.os.Message; -import android.os.ParcelFileDescriptor; -import android.preference.PreferenceManager; -import android.system.OsConstants; -import android.text.TextUtils; -import android.util.Log; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Vector; - -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.core.VpnStatus.ByteCountListener; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.StateListener; - -import static de.blinkt.openvpn.core.NetworkSpace.ipAddress; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NONETWORK; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; -import se.leap.bitmaskclient.Dashboard; - -public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener { - - public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE"; - public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY"; - 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 = "se.leap.bitmaskclient.RESUME_VPN"; - private static final int OPENVPN_STATUS = 1; - private static boolean mNotificationAlwaysVisible = false; - private final Vector<String> mDnslist = new Vector<String>(); - private final NetworkSpace mRoutes = new NetworkSpace(); - private final NetworkSpace mRoutesv6 = new NetworkSpace(); - private final IBinder mBinder = new LocalBinder(); - private Thread mProcessThread = null; - private VpnProfile mProfile; - private String mDomain = null; - private CIDRIP mLocalIP = null; - private int mMtu; - private String mLocalIPv6 = null; - private DeviceStateReceiver mDeviceStateReceiver; - private boolean mDisplayBytecount = false; - private boolean mStarting = false; - private long mConnecttime; - private boolean mOvpn3 = false; - private OpenVPNManagement mManagement; - private String mLastTunCfg; - private String mRemoteGW; - private final Object mProcessLock = new Object(); - private LollipopDeviceStateListener mLollipopDeviceStateListener; - - // 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) { - if (mbit) - bytes = bytes * 8; - int unit = mbit ? 1000 : 1024; - if (bytes < unit) - return bytes + (mbit ? " bit" : " B"); - - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (mbit ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (mbit ? "" : ""); - if (mbit) - return String.format(Locale.getDefault(), "%.1f %sbit", bytes / Math.pow(unit, exp), pre); - else - return String.format(Locale.getDefault(), "%.1f %sB", bytes / Math.pow(unit, exp), pre); - } - - @Override - public IBinder onBind(Intent intent) { - String action = intent.getAction(); - if (action != null && action.equals(START_SERVICE)) - return mBinder; - else - return super.onBind(intent); - } - - @Override - public void onRevoke() { - mManagement.stopVPN(); - endVpnService(); - } - - // Similar to revoke but do not try to stop process - public void processDied() { - endVpnService(); - } - - private void endVpnService() { - synchronized (mProcessLock) { - mProcessThread = null; - } - mConnecttime = 0; - VpnStatus.removeByteCountListener(this); - unregisterDeviceStateReceiver(); - ProfileManager.setConntectedVpnProfileDisconnected(this); - if (!mStarting) { - stopForeground(!mNotificationAlwaysVisible); - - if (!mNotificationAlwaysVisible) { - stopSelf(); - VpnStatus.removeStateListener(this); - } - } - } - - private void showNotification(String msg, String tickerText, boolean lowpriority, long when, ConnectionStatus status) { - String ns = Context.NOTIFICATION_SERVICE; - NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); - - - int icon = getIconByConnectionStatus(status); - - android.app.Notification.Builder nbuilder = new Notification.Builder(this); - - if (mProfile != null) - nbuilder.setContentTitle(getString(R.string.notifcation_title, mProfile.mName)); - else - nbuilder.setContentTitle(getString(R.string.notifcation_title_notconnect)); - - nbuilder.setContentText(msg); - nbuilder.setOnlyAlertOnce(true); - nbuilder.setOngoing(true); - nbuilder.setContentIntent(getLogPendingIntent()); - nbuilder.setSmallIcon(icon); - - - if (when != 0) - nbuilder.setWhen(when); - - - // Try to set the priority available since API 16 (Jellybean) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - jbNotificationExtras(lowpriority, nbuilder); - - if (tickerText != null && !tickerText.equals("")) - nbuilder.setTicker(tickerText); - - @SuppressWarnings("deprecation") - Notification notification = nbuilder.getNotification(); - - - mNotificationManager.notify(OPENVPN_STATUS, notification); - //startForeground(OPENVPN_STATUS, notification); - } - - private int getIconByConnectionStatus(ConnectionStatus level) { - switch (level) { - case LEVEL_CONNECTED: - return R.drawable.ic_stat_vpn; - case LEVEL_AUTH_FAILED: - case LEVEL_NONETWORK: - case LEVEL_NOTCONNECTED: - return R.drawable.ic_stat_vpn_offline; - case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: - case LEVEL_WAITING_FOR_USER_INPUT: - return R.drawable.ic_stat_vpn_outline; - case LEVEL_CONNECTING_SERVER_REPLIED: - return R.drawable.ic_stat_vpn_empty_halo; - case LEVEL_VPNPAUSED: - return android.R.drawable.ic_media_pause; - case UNKNOWN_LEVEL: - default: - return R.drawable.ic_stat_vpn; - - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void jbNotificationExtras(boolean lowpriority, - android.app.Notification.Builder nbuilder) { - try { - if (lowpriority) { - Method setpriority = nbuilder.getClass().getMethod("setPriority", int.class); - // PRIORITY_MIN == -2 - setpriority.invoke(nbuilder, -2); - - Method setUsesChronometer = nbuilder.getClass().getMethod("setUsesChronometer", boolean.class); - setUsesChronometer.invoke(nbuilder, true); - - } - - Intent disconnectVPN = new Intent(this, DisconnectVPN.class); - disconnectVPN.setAction(DISCONNECT_VPN); - PendingIntent disconnectPendingIntent = PendingIntent.getActivity(this, 0, disconnectVPN, 0); - - nbuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, - getString(R.string.cancel_connection), disconnectPendingIntent); - - Intent pauseVPN = new Intent(this, OpenVPNService.class); - if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) { - pauseVPN.setAction(PAUSE_VPN); - PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); - nbuilder.addAction(android.R.drawable.ic_media_pause, - getString(R.string.pauseVPN), pauseVPNPending); - - } else { - pauseVPN.setAction(RESUME_VPN); - PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0); - nbuilder.addAction(android.R.drawable.ic_media_play, - getString(R.string.resumevpn), resumeVPNPending); - } - - - //ignore exception - } catch (NoSuchMethodException nsm) { - VpnStatus.logException(nsm); - } catch (IllegalArgumentException e) { - VpnStatus.logException(e); - } catch (IllegalAccessException e) { - VpnStatus.logException(e); - } catch (InvocationTargetException e) { - VpnStatus.logException(e); - } - - } - - PendingIntent getLogPendingIntent() { - // Let the configure Button show the Log - Intent intent = new Intent(getBaseContext(), Dashboard.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - PendingIntent startLW = PendingIntent.getActivity(this, 0, intent, 0); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - return startLW; - - } - - synchronized void registerDeviceStateReceiver(OpenVPNManagement magnagement) { - // Registers BroadcastReceiver to track network connection changes. - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(Intent.ACTION_SCREEN_ON); - mDeviceStateReceiver = new DeviceStateReceiver(magnagement); - registerReceiver(mDeviceStateReceiver, filter); - VpnStatus.addByteCountListener(mDeviceStateReceiver); - - /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - addLollipopCMListener(); */ - } - - synchronized void unregisterDeviceStateReceiver() { - if (mDeviceStateReceiver != null) - try { - VpnStatus.removeByteCountListener(mDeviceStateReceiver); - this.unregisterReceiver(mDeviceStateReceiver); - } catch (IllegalArgumentException iae) { - // I don't know why this happens: - // java.lang.IllegalArgumentException: Receiver not registered: de.blinkt.openvpn.NetworkSateReceiver@41a61a10 - // Ignore for now ... - iae.printStackTrace(); - } - mDeviceStateReceiver = null; - - /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - removeLollipopCMListener();*/ - - } - - public void userPause(boolean shouldBePaused) { - if (mDeviceStateReceiver != null) - mDeviceStateReceiver.userPause(shouldBePaused); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - - if (intent != null && intent.getBooleanExtra(ALWAYS_SHOW_NOTIFICATION, false)) - mNotificationAlwaysVisible = true; - - VpnStatus.addStateListener(this); - VpnStatus.addByteCountListener(this); - - if (intent != null && PAUSE_VPN.equals(intent.getAction())) { - if (mDeviceStateReceiver != null) - mDeviceStateReceiver.userPause(true); - return START_NOT_STICKY; - } - - if (intent != null && RESUME_VPN.equals(intent.getAction())) { - if (mDeviceStateReceiver != null) - mDeviceStateReceiver.userPause(false); - return START_NOT_STICKY; - } - - - if (intent != null && START_SERVICE.equals(intent.getAction())) - return START_NOT_STICKY; - if (intent != null && START_SERVICE_STICKY.equals(intent.getAction())) { - return START_REDELIVER_INTENT; - } - - /* The intent is null when the service has been restarted */ - if (intent == null) { - mProfile = ProfileManager.getLastConnectedProfile(this, false); - - /* Got no profile, just stop */ - if (mProfile == null) { - Log.d("OpenVPN", "Got no last connected profile on null intent. Stopping"); - stopSelf(startId); - return START_NOT_STICKY; - } - /* Do the asynchronous keychain certificate stuff */ - mProfile.checkForRestart(this); - - /* Recreate the intent */ - intent = mProfile.getStartServiceIntent(this); - - } else { - String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID"); - mProfile = ProfileManager.get(this, profileUUID); - } - - - // Extract information from the intent. - String prefix = getPackageName(); - String[] argv = intent.getStringArrayExtra(prefix + ".ARGV"); - String nativeLibraryDirectory = intent.getStringExtra(prefix + ".nativelib"); - - 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 - } - } - } - // An old running VPN should now be exited - mStarting = false; - - // Start a new session by creating a new thread. - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - - mOvpn3 = prefs.getBoolean("ovpn3", false); - 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)) { - - Thread mSocketManagerThread = new Thread(ovpnManagementThread, "OpenVPNManagementThread"); - mSocketManagerThread.start(); - mManagement = ovpnManagementThread; - VpnStatus.logInfo("started Socket Thread"); - } else { - return START_NOT_STICKY; - } - } - - - Runnable processThread; - if (mOvpn3) { - - OpenVPNManagement mOpenVPN3 = instantiateOpenVPN3Core(); - processThread = (Runnable) mOpenVPN3; - mManagement = mOpenVPN3; - - - } else { - HashMap<String, String> env = new HashMap<String, String>(); - processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory); - } - - synchronized (mProcessLock) { - mProcessThread = new Thread(processThread, "OpenVPNProcessThread"); - mProcessThread.start(); - } - 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/responsee authentication */ - if (mProfile.needUserPWInput(true) != 0) - return START_NOT_STICKY; - - return START_STICKY; - } - - private OpenVPNManagement instantiateOpenVPN3Core() { - try { - Class cl = Class.forName("de.blinkt.openvpn.core.OpenVPNThreadv3"); - return (OpenVPNManagement) cl.getConstructor(OpenVPNService.class, VpnProfile.class).newInstance(this, mProfile); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public void onDestroy() { - synchronized (mProcessLock) { - if (mProcessThread != null) { - mManagement.stopVPN(); - } - } - - if (mDeviceStateReceiver != null) { - this.unregisterReceiver(mDeviceStateReceiver); - } - // Just in case unregister for state - VpnStatus.removeStateListener(this); - - } - - 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; - - - cfg += "routes: " + TextUtils.join("|", mRoutes.getNetworks(true)) + TextUtils.join("|", mRoutesv6.getNetworks(true)); - cfg += "excl. routes:" + TextUtils.join("|", mRoutes.getNetworks(false)) + TextUtils.join("|", mRoutesv6.getNetworks(false)); - cfg += "dns: " + TextUtils.join("|", mDnslist); - cfg += "domain: " + mDomain; - cfg += "mtu: " + mMtu; - return cfg; - } - - public ParcelFileDescriptor openTun() { - - //Debug.startMethodTracing(getExternalFilesDir(null).toString() + "/opentun.trace", 40* 1024 * 1024); - - Builder builder = new Builder(); - - VpnStatus.logInfo(R.string.last_openvpn_tun_config); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) - { - allowAllAFFamilies(builder); - } - - if (mLocalIP == null && mLocalIPv6 == null) { - VpnStatus.logError(getString(R.string.opentun_no_ipaddr)); - return null; - } - - if (mLocalIP != null) { - addLocalNetworksToRoutes(); - try { - builder.addAddress(mLocalIP.mIp, mLocalIP.len); - } catch (IllegalArgumentException iae) { - VpnStatus.logError(R.string.dns_add_error, mLocalIP, iae.getLocalizedMessage()); - return null; - } - } - - if (mLocalIPv6 != null) { - String[] ipv6parts = mLocalIPv6.split("/"); - try { - builder.addAddress(ipv6parts[0], Integer.parseInt(ipv6parts[1])); - } catch (IllegalArgumentException iae) { - VpnStatus.logError(R.string.ip_add_error, mLocalIPv6, iae.getLocalizedMessage()); - return null; - } - - } - - - for (String dns : mDnslist) { - try { - builder.addDnsServer(dns); - } catch (IllegalArgumentException iae) { - VpnStatus.logError(R.string.dns_add_error, dns, iae.getLocalizedMessage()); - } - } - - String release = Build.VERSION.RELEASE; - if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") - && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) - && mMtu < 1280) { - VpnStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu)); - builder.setMtu(1280); - } else { - builder.setMtu(mMtu); - } - - Collection<ipAddress> positiveIPv4Routes = mRoutes.getPositiveIPList(); - Collection<ipAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList(); - - for (NetworkSpace.ipAddress route : positiveIPv4Routes) { - try { - builder.addRoute(route.getIPv4Address(), route.networkMask); - } catch (IllegalArgumentException ia) { - VpnStatus.logError(getString(R.string.route_rejected) + route + " " + ia.getLocalizedMessage()); - } - } - - for (NetworkSpace.ipAddress route6 : positiveIPv6Routes) { - try { - builder.addRoute(route6.getIPv6Address(), route6.networkMask); - } catch (IllegalArgumentException ia) { - VpnStatus.logError(getString(R.string.route_rejected) + route6 + " " + ia.getLocalizedMessage()); - } - } - - if (mDomain != null) - builder.addSearchDomain(mDomain); - - VpnStatus.logInfo(R.string.local_ip_info, mLocalIP.mIp, mLocalIP.len, mLocalIPv6, mMtu); - VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain); - VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true))); - VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false))); - VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - setAllowedVpnPackages(builder); - } - - - String session = mProfile.mName; - if (mLocalIP != null && mLocalIPv6 != null) - session = getString(R.string.session_ipv6string, session, mLocalIP, mLocalIPv6); - else if (mLocalIP != null) - session = getString(R.string.session_ipv4string, session, mLocalIP); - - builder.setSession(session); - - // No DNS Server, log a warning - if (mDnslist.size() == 0) - VpnStatus.logInfo(R.string.warn_no_dns); - - mLastTunCfg = getTunConfigString(); - - // Reset information - mDnslist.clear(); - mRoutes.clear(); - mRoutesv6.clear(); - mLocalIP = null; - mLocalIPv6 = null; - mDomain = null; - - builder.setConfigureIntent(getLogPendingIntent()); - - try { - //Debug.stopMethodTracing(); - return builder.establish(); - } catch (Exception e) { - VpnStatus.logError(R.string.tun_open_error); - VpnStatus.logError(getString(R.string.error) + e.getLocalizedMessage()); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) { - VpnStatus.logError(R.string.tun_error_helpful); - } - return null; - } - - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private void allowAllAFFamilies(Builder builder) { - builder.allowFamily(OsConstants.AF_INET); - builder.allowFamily(OsConstants.AF_INET6); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - void removeLollipopCMListener() { - ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE); - cm.unregisterNetworkCallback(mLollipopDeviceStateListener); - mLollipopDeviceStateListener = null; - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - void addLollipopCMListener() { - ConnectivityManager cm = (ConnectivityManager) getBaseContext().getSystemService(CONNECTIVITY_SERVICE); - NetworkRequest.Builder nrb = new NetworkRequest.Builder(); - - mLollipopDeviceStateListener = new LollipopDeviceStateListener(); - cm.registerNetworkCallback(nrb.build(), mLollipopDeviceStateListener); - } - - private void addLocalNetworksToRoutes() { - - // Add local network interfaces - String[] localRoutes = NativeUtils.getIfconfig(); - - // The format of mLocalRoutes is kind of broken because I don't really like JNI - for (int i = 0; i < localRoutes.length; i += 3) { - String intf = localRoutes[i]; - String ipAddr = localRoutes[i + 1]; - String netMask = localRoutes[i + 2]; - - if (intf == null || intf.equals("lo") || - intf.startsWith("tun") || intf.startsWith("rmnet")) - continue; - - if (ipAddr==null || netMask == null) { - VpnStatus.logError("Local routes are broken?! (Report to author) " + TextUtils.join("|", localRoutes)); - continue; - } - - if (ipAddr.equals(mLocalIP.mIp)) - continue; - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mProfile.mAllowLocalLAN) { - mRoutes.addIPSplit(new CIDRIP(ipAddr, netMask), true); - - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mProfile.mAllowLocalLAN) - mRoutes.addIP(new CIDRIP(ipAddr, netMask), false); - } - } - - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private void setAllowedVpnPackages(Builder builder) { - for (String pkg : mProfile.mAllowedAppsVpn) { - try { - if (mProfile.mAllowedAppsVpnAreDisallowed) { - builder.addDisallowedApplication(pkg); - } else { - builder.addAllowedApplication(pkg); - } - } catch (PackageManager.NameNotFoundException e) { - mProfile.mAllowedAppsVpn.remove(pkg); - VpnStatus.logInfo(R.string.app_no_longer_exists, pkg); - } - } - - if (mProfile.mAllowedAppsVpnAreDisallowed) { - VpnStatus.logDebug(R.string.disallowed_vpn_apps_info, TextUtils.join(", ", mProfile.mAllowedAppsVpn)); - } else { - VpnStatus.logDebug(R.string.allowed_vpn_apps_info, TextUtils.join(", ", mProfile.mAllowedAppsVpn)); - } - } - - public void addDNS(String dns) { - mDnslist.add(dns); - } - - public void setDomain(String domain) { - if (mDomain == null) { - mDomain = domain; - } - } - - /** - * Route that is always included, used by the v3 core - */ - public void addRoute(CIDRIP route) { - mRoutes.addIP(route, true); - } - - public void addRoute(String dest, String mask, String gateway, String device) { - CIDRIP route = new CIDRIP(dest, mask); - boolean include = isAndroidTunDevice(device); - - NetworkSpace.ipAddress gatewayIP = new NetworkSpace.ipAddress(new CIDRIP(gateway, 32), false); - - if (mLocalIP == null) { - VpnStatus.logError("Local IP address unset but adding route?! This is broken! Please contact author with log"); - return; - } - NetworkSpace.ipAddress localNet = new NetworkSpace.ipAddress(mLocalIP, true); - if (localNet.containsNet(gatewayIP)) - include = true; - - if (gateway != null && - (gateway.equals("255.255.255.255") || gateway.equals(mRemoteGW))) - include = true; - - - if (route.len == 32 && !mask.equals("255.255.255.255")) { - VpnStatus.logWarning(R.string.route_not_cidr, dest, mask); - } - - if (route.normalise()) - VpnStatus.logWarning(R.string.route_not_netip, dest, route.len, route.mIp); - - mRoutes.addIP(route, include); - } - - public void addRoutev6(String network, String device) { - String[] v6parts = network.split("/"); - boolean included = isAndroidTunDevice(device); - - // Tun is opened after ROUTE6, no device name may be present - - try { - Inet6Address ip = (Inet6Address) InetAddress.getAllByName(v6parts[0])[0]; - int mask = Integer.parseInt(v6parts[1]); - mRoutesv6.addIPv6(ip, mask, included); - - } catch (UnknownHostException e) { - VpnStatus.logException(e); - } - - - } - - private boolean isAndroidTunDevice(String device) { - return device != null && - (device.startsWith("tun") || "(null)".equals(device) || "vpnservice-tun".equals(device)); - } - - public void setMtu(int mtu) { - mMtu = mtu; - } - - public void setLocalIP(CIDRIP cdrip) { - mLocalIP = cdrip; - } - - public void setLocalIP(String local, String netmask, int mtu, String mode) { - mLocalIP = new CIDRIP(local, netmask); - mMtu = mtu; - mRemoteGW = null; - - long netMaskAsInt = CIDRIP.getInt(netmask); - - if (mLocalIP.len == 32 && !netmask.equals("255.255.255.255")) { - // get the netmask as IP - - int masklen; - long mask; - if ("net30".equals(mode)) { - masklen = 30; - mask = 0xfffffffc; - } else { - masklen = 31; - mask = 0xfffffffe; - } - - // Netmask is Ip address +/-1, assume net30/p2p with small net - if ((netMaskAsInt & mask) == (mLocalIP.getInt() & mask)) { - mLocalIP.len = masklen; - } else { - mLocalIP.len = 32; - if (!"p2p".equals(mode)) - VpnStatus.logWarning(R.string.ip_not_cidr, local, netmask, mode); - } - } - if (("p2p".equals(mode) && mLocalIP.len < 32) || ("net30".equals(mode) && mLocalIP.len < 30)) { - VpnStatus.logWarning(R.string.ip_looks_like_subnet, local, netmask, mode); - } - - - /* Workaround for Lollipop, it does not route traffic to the VPNs own network mask */ - if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - addRoute(mLocalIP); - - - // Configurations are sometimes really broken... - mRemoteGW = netmask; - } - - public void setLocalIPv6(String ipv6addr) { - mLocalIPv6 = ipv6addr; - } - - @Override - public void updateState(String state, String logmessage, int resid, ConnectionStatus level) { - // If the process is not running, ignore any state, - // Notification should be invisible in this state - - doSendBroadcast(state, level); - if (mProcessThread == null && !mNotificationAlwaysVisible) - return; - - boolean lowpriority = false; - // Display byte count only after being connected - - { - if (level == LEVEL_WAITING_FOR_USER_INPUT) { - // The user is presented a dialog of some kind, no need to inform the user - // with a notifcation - return; - } else if (level == LEVEL_CONNECTED) { - mDisplayBytecount = true; - mConnecttime = System.currentTimeMillis(); - lowpriority = true; - if(mProfile.mPersistTun) { - NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - ns.cancel(OPENVPN_STATUS); - return; - } - } else if (level == LEVEL_NONETWORK || level == LEVEL_NOTCONNECTED) { - NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - ns.cancel(OPENVPN_STATUS); - return; - } else if (level != LEVEL_NOTCONNECTED && mConnecttime > 0) { - mDisplayBytecount = false; - String msg = "Traffic is blocked until the VPN becomes active."; - String ticker = msg; - showNotification(msg, ticker, lowpriority , 0, level); - return; - } else { - mDisplayBytecount = false; - } - - // Other notifications are shown, - // This also mean we are no longer connected, ignore bytecount messages until next - // CONNECTED - // Does not work :( - String msg = getString(resid); - String ticker = msg; - showNotification(msg + " " + logmessage, ticker, lowpriority , 0, level); - } - } - - private void doSendBroadcast(String state, ConnectionStatus level) { - Intent vpnstatus = new Intent(); - vpnstatus.setAction("de.blinkt.openvpn.VPN_STATUS"); - vpnstatus.putExtra("status", level.toString()); - vpnstatus.putExtra("detailstatus", state); - sendBroadcast(vpnstatus, permission.ACCESS_NETWORK_STATE); - } - - @Override - public void updateByteCount(long in, long out, long diffIn, long diffOut) { - if (mDisplayBytecount) { - String netstat = String.format(getString(R.string.statusline_bytecount), - humanReadableByteCount(in, false), - humanReadableByteCount(diffIn / OpenVPNManagement.mBytecountInterval, true), - humanReadableByteCount(out, false), - humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true)); - - boolean lowpriority = !mNotificationAlwaysVisible; - //showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); - } - - } - - @Override - public boolean handleMessage(Message msg) { - Runnable r = msg.getCallback(); - if (r != null) { - r.run(); - return true; - } else { - return false; - } - } - - public OpenVPNManagement getManagement() { - return mManagement; - } - - public String getTunReopenStatus() { - String currentConfiguration = getTunConfigString(); - if (currentConfiguration.equals(mLastTunCfg)) { - return "NOACTION"; - } else { - String release = Build.VERSION.RELEASE; - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3") - && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6")) - // There will be probably no 4.4.4 or 4.4.5 version, so don't waste effort to do parsing here - 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 - return OpenVPNService.this; - } - } -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java deleted file mode 100644 index 298a6c40..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.annotation.SuppressLint; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.LinkedList; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; -import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.LogItem; - -public class OpenVPNThread implements Runnable { - private static final String DUMP_PATH_STRING = "Dump path: "; - @SuppressLint("SdCardPath") - private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:"; - 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) { - VpnStatus.logError("Process exited with exit value " + exitvalue); - if (mBrokenPie) { - /* This will probably fail since the NoPIE binary is probably not written */ - String[] noPieArgv = VPNLaunchHelper.replacePieWithNoPie(mArgv); - - // We are already noPIE, nothing to gain - if (!noPieArgv.equals(mArgv)) { - mArgv = noPieArgv; - VpnStatus.logInfo("PIE Version could not be executed. Trying no PIE version"); - run(); - return; - } - - } - - } - - 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()); - - if (logline.startsWith(BROKEN_PIE_SUPPORT)) - 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); - 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].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/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java deleted file mode 100644 index 1c3b3362..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -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 junit.framework.Assert; - -import org.jetbrains.annotations.NotNull; - -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.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 de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; - -public class OpenVpnManagementThread implements Runnable, OpenVPNManagement { - - private static final String TAG = "openvpn"; - private LocalSocket mSocket; - private VpnProfile mProfile; - private OpenVPNService mOpenVPNService; - private LinkedList<FileDescriptor> mFDList = new LinkedList<FileDescriptor>(); - private LocalServerSocket mServerSocket; - private boolean mReleaseHold = true; - private boolean mWaitingForRelease = false; - private long mLastHoldRelease = 0; - - private static final Vector<OpenVpnManagementThread> active = new Vector<OpenVpnManagementThread>(); - 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 = ""; - synchronized (active) { - 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") && !e.getMessage().equals("Connection reset by peer")) - VpnStatus.logException(e); - } - synchronized (active) { - 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 ignored) { - } - - } - 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) { - if (BuildConfig.DEBUG) Assert.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); - } 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() { - synchronized (active) { - 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/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java deleted file mode 100644 index a788426a..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core;/* - * This software is provided 'as-is', without any express or implied - * warranty. In no event will Google be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, as long as the origin is not misrepresented. - */ - -import android.os.Build; -import android.os.Process; -import android.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -import java.security.Security; - -/** - * Fixes for the output of the default PRNG having low entropy. - * - * The fixes need to be applied via {@link #apply()} before any use of Java - * Cryptography Architecture primitives. A good place to invoke them is in the - * application's {@code onCreate}. - */ -public final class PRNGFixes { - - private static final int VERSION_CODE_JELLY_BEAN = 16; - private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; - private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); - - /** Hidden constructor to prevent instantiation. */ - private PRNGFixes() {} - - /** - * Applies all fixes. - * - * @throws SecurityException if a fix is needed but could not be applied. - */ - public static void apply() { - applyOpenSSLFix(); - installLinuxPRNGSecureRandom(); - } - - /** - * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the - * fix is not needed. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void applyOpenSSLFix() throws SecurityException { - if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN) - || (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) { - // No need to apply the fix - return; - } - - try { - // Mix in the device- and invocation-specific seed. - Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_seed", byte[].class) - .invoke(null, generateSeed()); - - // Mix output of Linux PRNG into OpenSSL's PRNG - int bytesRead = (Integer) Class.forName( - "org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_load_file", String.class, long.class) - .invoke(null, "/dev/urandom", 1024); - if (bytesRead != 1024) { - throw new IOException( - "Unexpected number of bytes read from Linux PRNG: " - + bytesRead); - } - } catch (Exception e) { - throw new SecurityException("Failed to seed OpenSSL PRNG", e); - } - } - - /** - * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the - * default. Does nothing if the implementation is already the default or if - * there is not need to install the implementation. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void installLinuxPRNGSecureRandom() - throws SecurityException { - if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { - // No need to apply the fix - return; - } - - // Install a Linux PRNG-based SecureRandom implementation as the - // default, if not yet installed. - Provider[] secureRandomProviders = - Security.getProviders("SecureRandom.SHA1PRNG"); - if ((secureRandomProviders == null) - || (secureRandomProviders.length < 1) - || (!LinuxPRNGSecureRandomProvider.class.equals( - secureRandomProviders[0].getClass()))) { - Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); - } - - // Assert that new SecureRandom() and - // SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed - // by the Linux PRNG-based SecureRandom implementation. - SecureRandom rng1 = new SecureRandom(); - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng1.getProvider().getClass())) { - throw new SecurityException( - "new SecureRandom() backed by wrong Provider: " - + rng1.getProvider().getClass()); - } - - SecureRandom rng2; - try { - rng2 = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("SHA1PRNG not available", e); - } - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng2.getProvider().getClass())) { - throw new SecurityException( - "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" - + " Provider: " + rng2.getProvider().getClass()); - } - } - - /** - * {@code Provider} of {@code SecureRandom} engines which pass through - * all requests to the Linux PRNG. - */ - private static class LinuxPRNGSecureRandomProvider extends Provider { - - public LinuxPRNGSecureRandomProvider() { - super("LinuxPRNG", - 1.0, - "A Linux-specific random number provider that uses" - + " /dev/urandom"); - // Although /dev/urandom is not a SHA-1 PRNG, some apps - // explicitly request a SHA1PRNG SecureRandom and we thus need to - // prevent them from getting the default implementation whose output - // may have low entropy. - put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName()); - put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); - } - } - - /** - * {@link SecureRandomSpi} which passes all requests to the Linux PRNG - * ({@code /dev/urandom}). - */ - public static class LinuxPRNGSecureRandom extends SecureRandomSpi { - - /* - * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed - * are passed through to the Linux PRNG (/dev/urandom). Instances of - * this class seed themselves by mixing in the current time, PID, UID, - * build fingerprint, and hardware serial number (where available) into - * Linux PRNG. - * - * Concurrency: Read requests to the underlying Linux PRNG are - * serialized (on sLock) to ensure that multiple threads do not get - * duplicated PRNG output. - */ - - private static final File URANDOM_FILE = new File("/dev/urandom"); - - private static final Object sLock = new Object(); - - /** - * Input stream for reading from Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static DataInputStream sUrandomIn; - - /** - * Output stream for writing to Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static OutputStream sUrandomOut; - - /** - * Whether this engine instance has been seeded. This is needed because - * each instance needs to seed itself if the client does not explicitly - * seed it. - */ - private boolean mSeeded; - - @Override - protected void engineSetSeed(byte[] bytes) { - try { - OutputStream out; - synchronized (sLock) { - out = getUrandomOutputStream(); - } - out.write(bytes); - out.flush(); - } catch (IOException e) { - // On a small fraction of devices /dev/urandom is not writable. - // Log and ignore. - Log.w(PRNGFixes.class.getSimpleName(), - "Failed to mix seed into " + URANDOM_FILE); - } finally { - mSeeded = true; - } - } - - @Override - protected void engineNextBytes(byte[] bytes) { - if (!mSeeded) { - // Mix in the device- and invocation-specific seed. - engineSetSeed(generateSeed()); - } - - try { - DataInputStream in; - synchronized (sLock) { - in = getUrandomInputStream(); - } - synchronized (in) { - in.readFully(bytes); - } - } catch (IOException e) { - throw new SecurityException( - "Failed to read from " + URANDOM_FILE, e); - } - } - - @Override - protected byte[] engineGenerateSeed(int size) { - byte[] seed = new byte[size]; - engineNextBytes(seed); - return seed; - } - - private DataInputStream getUrandomInputStream() { - synchronized (sLock) { - if (sUrandomIn == null) { - // NOTE: Consider inserting a BufferedInputStream between - // DataInputStream and FileInputStream if you need higher - // PRNG output performance and can live with future PRNG - // output being pulled into this process prematurely. - try { - sUrandomIn = new DataInputStream( - new FileInputStream(URANDOM_FILE)); - } catch (IOException e) { - throw new SecurityException("Failed to open " - + URANDOM_FILE + " for reading", e); - } - } - return sUrandomIn; - } - } - - private OutputStream getUrandomOutputStream() throws IOException { - synchronized (sLock) { - if (sUrandomOut == null) { - sUrandomOut = new FileOutputStream(URANDOM_FILE); - } - return sUrandomOut; - } - } - } - - /** - * Generates a device- and invocation-specific seed to be mixed into the - * Linux PRNG. - */ - private static byte[] generateSeed() { - try { - ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); - DataOutputStream seedBufferOut = - new DataOutputStream(seedBuffer); - seedBufferOut.writeLong(System.currentTimeMillis()); - seedBufferOut.writeLong(System.nanoTime()); - seedBufferOut.writeInt(Process.myPid()); - seedBufferOut.writeInt(Process.myUid()); - seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); - seedBufferOut.close(); - return seedBuffer.toByteArray(); - } catch (IOException e) { - throw new SecurityException("Failed to generate seed", e); - } - } - - /** - * Gets the hardware serial number of this device. - * - * @return serial number or {@code null} if not available. - */ - private static String getDeviceSerialNumber() { - // We're using the Reflection API because Build.SERIAL is only available - // since API Level 9 (Gingerbread, Android 2.3). - try { - return (String) Build.class.getField("SERIAL").get(null); - } catch (Exception ignored) { - return null; - } - } - - private static byte[] getBuildFingerprintAndDeviceSerial() { - StringBuilder result = new StringBuilder(); - String fingerprint = Build.FINGERPRINT; - if (fingerprint != null) { - result.append(fingerprint); - } - String serial = getDeviceSerialNumber(); - if (serial != null) { - result.append(serial); - } - try { - return result.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not supported"); - } - } -}
\ No newline at end of file diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java deleted file mode 100644 index 1ebc0a57..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.StreamCorruptedException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import de.blinkt.openvpn.VpnProfile; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.preference.PreferenceManager; - -public class ProfileManager { - private static final String PREFS_NAME = "VPNList"; - - - - private static final String LAST_CONNECTED_PROFILE = "lastConnectedProfile"; - - - - private static ProfileManager instance; - - - - private static VpnProfile mLastConnectedVpn=null; - private HashMap<String,VpnProfile> profiles=new HashMap<String, VpnProfile>(); - private static VpnProfile tmpprofile=null; - - - private static VpnProfile get(String key) { - if (tmpprofile!=null && tmpprofile.getUUIDString().equals(key)) - return tmpprofile; - - if(instance==null) - return null; - return instance.profiles.get(key); - - } - - - - private ProfileManager() { } - - private static void checkInstance(Context context) { - if(instance == null) { - instance = new ProfileManager(); - instance.loadVPNList(context); - } - } - - synchronized public static ProfileManager getInstance(Context context) { - checkInstance(context); - return instance; - } - - public static void setConntectedVpnProfileDisconnected(Context c) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); - Editor prefsedit = prefs.edit(); - prefsedit.putString(LAST_CONNECTED_PROFILE, null); - prefsedit.apply(); - - } - - public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); - Editor prefsedit = prefs.edit(); - - prefsedit.putString(LAST_CONNECTED_PROFILE, connectedrofile.getUUIDString()); - prefsedit.apply(); - mLastConnectedVpn=connectedrofile; - - } - - public static VpnProfile getLastConnectedProfile(Context c, boolean onBoot) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); - - boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false); - - if (onBoot && !useStartOnBoot) - return null; - - String lastConnectedProfile = prefs.getString(LAST_CONNECTED_PROFILE, null); - if(lastConnectedProfile!=null) - return get(c, lastConnectedProfile); - else - return null; - } - - - - - public Collection<VpnProfile> getProfiles() { - return profiles.values(); - } - - public VpnProfile getProfileByName(String name) { - for (VpnProfile vpnp : profiles.values()) { - if(vpnp.getName().equals(name)) { - return vpnp; - } - } - return null; - } - - public void saveProfileList(Context context) { - SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE); - Editor editor = sharedprefs.edit(); - editor.putStringSet("vpnlist", profiles.keySet()); - - // For reasing I do not understand at all - // Android saves my prefs file only one time - // if I remove the debug code below :( - int counter = sharedprefs.getInt("counter", 0); - editor.putInt("counter", counter+1); - editor.apply(); - - } - - public void addProfile(VpnProfile profile) { - profiles.put(profile.getUUID().toString(),profile); - - } - - public static void setTemporaryProfile(VpnProfile tmp) { - ProfileManager.tmpprofile = tmp; - } - - - public void saveProfile(Context context,VpnProfile profile) { - // First let basic settings save its state - - ObjectOutputStream vpnfile; - try { - vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE)); - - vpnfile.writeObject(profile); - vpnfile.flush(); - vpnfile.close(); - } catch (FileNotFoundException e) { - - VpnStatus.logException("saving VPN profile", e); - throw new RuntimeException(e); - } catch (IOException e) { - VpnStatus.logException("saving VPN profile", e); - throw new RuntimeException(e); - } - } - - - private void loadVPNList(Context context) { - profiles = new HashMap<String, VpnProfile>(); - SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE); - Set<String> vlist = listpref.getStringSet("vpnlist", null); - Exception exp =null; - if(vlist==null){ - vlist = new HashSet<String>(); - } - - for (String vpnentry : vlist) { - try { - ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp")); - VpnProfile vp = ((VpnProfile) vpnfile.readObject()); - - // Sanity check - if(vp==null || vp.mName==null || vp.getUUID()==null) - continue; - - vp.upgradeProfile(); - profiles.put(vp.getUUID().toString(), vp); - - } catch (StreamCorruptedException e) { - exp=e; - } catch (FileNotFoundException e) { - exp=e; - } catch (IOException e) { - exp=e; - } catch (ClassNotFoundException e) { - exp=e; - } - if(exp!=null) { - VpnStatus.logException("Loading VPN List",exp); - } - } - } - - public int getNumberOfProfiles() { - return profiles.size(); - } - - - - public void removeProfile(Context context,VpnProfile profile) { - String vpnentry = profile.getUUID().toString(); - profiles.remove(vpnentry); - saveProfileList(context); - context.deleteFile(vpnentry + ".vp"); - if(mLastConnectedVpn==profile) - mLastConnectedVpn=null; - - } - - - - public static VpnProfile get(Context context, String profileUUID) { - checkInstance(context); - return get(profileUUID); - } - - - - public static VpnProfile getLastConnectedVpn() { - return mLastConnectedVpn; - } - -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java deleted file mode 100644 index 6e2abb13..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/ProxyDetection.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Proxy; -import java.net.ProxySelector; -import java.net.SocketAddress; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.List; - -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; - -public class ProxyDetection { - static SocketAddress detectProxy(VpnProfile vp) { - // Construct a new url with https as protocol - try { - URL url = new URL(String.format("https://%s:%s",vp.mServerName,vp.mServerPort)); - Proxy proxy = getFirstProxy(url); - - if(proxy==null) - return null; - SocketAddress addr = proxy.address(); - if (addr instanceof InetSocketAddress) { - return addr; - } - - } catch (MalformedURLException e) { - VpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage()); - } catch (URISyntaxException e) { - VpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage()); - } - return null; - } - - static Proxy getFirstProxy(URL url) throws URISyntaxException { - System.setProperty("java.net.useSystemProxies", "true"); - - List<Proxy> proxylist = ProxySelector.getDefault().select(url.toURI()); - - - if (proxylist != null) { - for (Proxy proxy: proxylist) { - SocketAddress addr = proxy.address(); - - if (addr != null) { - return proxy; - } - } - - } - return null; - } -}
\ No newline at end of file diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java deleted file mode 100644 index 73ed05bc..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.os.Build; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Vector; - -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; - -public class VPNLaunchHelper { - private static final String MININONPIEVPN = "nopievpn"; - private static final String MINIPIEVPN = "pievpn"; - private static final String OVPNCONFIGFILE = "android.conf"; - - - - static private String writeMiniVPN(Context context) { - String[] abis; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - abis = getSupportedAbisLollipop(); - else - abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2}; - - for (String abi: abis) { - - File mvpnout = new File(context.getCacheDir(), getMiniVPNExecutableName() + "." + abi); - if ((mvpnout.exists() && mvpnout.canExecute()) || writeMiniVPNBinary(context, abi, mvpnout)) { - return mvpnout.getPath(); - } - } - - return null; - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static String[] getSupportedAbisLollipop() { - return Build.SUPPORTED_ABIS; - } - - private static String getMiniVPNExecutableName() - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - return MINIPIEVPN; - else - return MININONPIEVPN; - } - - - public static String[] replacePieWithNoPie(String[] mArgv) - { - mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN); - return mArgv; - } - - - public static String[] buildOpenvpnArgv(Context c) { - Vector<String> args = new Vector<String>(); - - // Add fixed paramenters - //args.add("/data/data/de.blinkt.openvpn/lib/openvpn"); - args.add(writeMiniVPN(c)); - - args.add("--config"); - args.add(c.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE); - - return args.toArray(new String[args.size()]); - } - - private static boolean writeMiniVPNBinary(Context context, String abi, File mvpnout) { - try { - InputStream mvpn; - - try { - mvpn = context.getAssets().open(getMiniVPNExecutableName() + "." + abi); - } - catch (IOException errabi) { - VpnStatus.logInfo("Failed getting assets for archicture " + abi); - return false; - } - - - FileOutputStream fout = new FileOutputStream(mvpnout); - - byte buf[]= new byte[4096]; - - int lenread = mvpn.read(buf); - while(lenread> 0) { - fout.write(buf, 0, lenread); - lenread = mvpn.read(buf); - } - fout.close(); - - if(!mvpnout.setExecutable(true)) { - VpnStatus.logError("Failed to make OpenVPN executable"); - return false; - } - - - return true; - } catch (IOException e) { - VpnStatus.logException(e); - return false; - } - - } - - - public static void startOpenVpn(VpnProfile startprofile, Context context) { - if(writeMiniVPN(context)==null) { - VpnStatus.logError("Error writing minivpn binary"); - return; - } - - VpnStatus.logInfo(R.string.building_configration); - - Intent startVPN = startprofile.prepareStartService(context); - if(startVPN!=null) - context.startService(startVPN); - - } - - public static String getConfigFilePath(Context context) { - return context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE; - } - -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java deleted file mode 100644 index ffc8097d..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import se.leap.bitmaskclient.R; - -import java.io.ByteArrayInputStream; -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.FormatFlagsConversionMismatchException; -import java.util.LinkedList; -import java.util.Locale; -import java.util.UnknownFormatConversionException; -import java.util.Vector; - -public class VpnStatus { - - - public static LinkedList<LogItem> logbuffer; - - private static Vector<LogListener> logListener; - private static Vector<StateListener> stateListener; - private static Vector<ByteCountListener> byteCountListener; - - private static String mLaststatemsg=""; - - private static String mLaststate = "NOPROCESS"; - - private static int mLastStateresid=R.string.state_noprocess; - - private static long mlastByteCount[]={0,0,0,0}; - - public static void logException(LogLevel ll, String context, Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - LogItem li; - if (context !=null) { - li = new LogItem(ll, R.string.unhandled_exception_context, e.getMessage(), sw.toString(), context); - } else { - li = new LogItem(ll, R.string.unhandled_exception, e.getMessage(), sw.toString()); - } - newLogItem(li); - } - - public static void logException(Exception e) { - logException(LogLevel.ERROR, null, e); - } - - public static void logException(String context, Exception e) { - logException(LogLevel.ERROR, context, e); - } - - private static final int MAXLOGENTRIES = 1000; - - public static final String MANAGMENT_PREFIX = "M:"; - - public enum ConnectionStatus { - LEVEL_CONNECTED, - LEVEL_VPNPAUSED, - LEVEL_CONNECTING_SERVER_REPLIED, - LEVEL_CONNECTING_NO_SERVER_REPLY_YET, - LEVEL_NONETWORK, - LEVEL_NOTCONNECTED, - LEVEL_AUTH_FAILED, - LEVEL_WAITING_FOR_USER_INPUT, - UNKNOWN_LEVEL - } - - public enum LogLevel { - INFO(2), - ERROR(-2), - WARNING(1), - VERBOSE(3), - DEBUG(4); - - protected int mValue; - LogLevel(int value) { - mValue = value; - } - - public int getInt() { - return mValue; - } - - public static LogLevel getEnumByValue(int value) { - switch (value) { - case 1: return INFO; - case 2: return ERROR; - case 3: return WARNING; - case 4: return DEBUG; - default: return null; - } - } - } - - // keytool -printcert -jarfile de.blinkt.openvpn_85.apk - public static final byte[] officalkey = {-58, -42, -44, -106, 90, -88, -87, -88, -52, -124, 84, 117, 66, 79, -112, -111, -46, 86, -37, 109}; - public static final byte[] officaldebugkey = {-99, -69, 45, 71, 114, -116, 82, 66, -99, -122, 50, -70, -56, -111, 98, -35, -65, 105, 82, 43}; - public static final byte[] amazonkey = {-116, -115, -118, -89, -116, -112, 120, 55, 79, -8, -119, -23, 106, -114, -85, -56, -4, 105, 26, -57}; - public static final byte[] fdroidkey = {-92, 111, -42, -46, 123, -96, -60, 79, -27, -31, 49, 103, 11, -54, -68, -27, 17, 2, 121, 104}; - - - private static ConnectionStatus mLastLevel=ConnectionStatus.LEVEL_NOTCONNECTED; - - static { - logbuffer = new LinkedList<LogItem>(); - logListener = new Vector<VpnStatus.LogListener>(); - stateListener = new Vector<VpnStatus.StateListener>(); - byteCountListener = new Vector<VpnStatus.ByteCountListener>(); - logInformation(); - } - - - public static class LogItem implements Parcelable { - - - private Object [] mArgs = null; - private String mMessage = null; - private int mRessourceId; - // Default log priority - LogLevel mLevel = LogLevel.INFO; - private long logtime = System.currentTimeMillis(); - private int mVerbosityLevel = -1; - - private LogItem(int ressourceId, Object[] args) { - mRessourceId = ressourceId; - mArgs = args; - } - - public LogItem(LogLevel level, int verblevel, String message) { - mMessage=message; - mLevel = level; - mVerbosityLevel = verblevel; - } - - @Override - public int describeContents() { - return 0; - } - - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeArray(mArgs); - dest.writeString(mMessage); - dest.writeInt(mRessourceId); - dest.writeInt(mLevel.getInt()); - dest.writeInt(mVerbosityLevel); - - dest.writeLong(logtime); - } - - public LogItem(Parcel in) { - mArgs = in.readArray(Object.class.getClassLoader()); - mMessage = in.readString(); - mRessourceId = in.readInt(); - mLevel = LogLevel.getEnumByValue(in.readInt()); - mVerbosityLevel = in.readInt(); - logtime = in.readLong(); - } - - public static final Parcelable.Creator<LogItem> CREATOR - = new Parcelable.Creator<LogItem>() { - public LogItem createFromParcel(Parcel in) { - return new LogItem(in); - } - - public LogItem[] newArray(int size) { - return new LogItem[size]; - } - }; - - public LogItem(LogLevel loglevel,int ressourceId, Object... args) { - mRessourceId = ressourceId; - mArgs =args; - mLevel = loglevel; - } - - - public LogItem(LogLevel loglevel, String msg) { - mLevel = loglevel; - mMessage = msg; - } - - - public LogItem(LogLevel loglevel, int ressourceId) { - mRessourceId =ressourceId; - mLevel = loglevel; - } - - public String getString(Context c) { - try { - if(mMessage !=null) { - return mMessage; - } else { - if(c!=null) { - if(mRessourceId==R.string.mobile_info) - return getMobileInfoString(c); - if(mArgs == null) - return c.getString(mRessourceId); - else - return c.getString(mRessourceId,mArgs); - } else { - String str = String.format(Locale.ENGLISH,"Log (no context) resid %d", mRessourceId); - if(mArgs !=null) - for(Object o:mArgs) - str += "|" + o.toString(); - - return str; - } - } - } catch (UnknownFormatConversionException e) { - if (c != null) - throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); - else - throw e; - } catch (java.util.FormatFlagsConversionMismatchException e) { - if (c != null) - throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null),e.getConversion()); - else - throw e; - } - - } - - public LogLevel getLogLevel() - { - return mLevel; - } - - // The lint is wrong here - @SuppressLint("StringFormatMatches") - private String getMobileInfoString(Context c) { - c.getPackageManager(); - String apksign="error getting package signature"; - - String version="error getting version"; - try { - Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] der = cert.getEncoded(); - md.update(der); - byte[] digest = md.digest(); - - if (Arrays.equals(digest, officalkey)) - apksign = c.getString(R.string.official_build); - else if (Arrays.equals(digest, officaldebugkey)) - apksign = c.getString(R.string.debug_build); - else if (Arrays.equals(digest, amazonkey)) - apksign = "amazon version"; - else if (Arrays.equals(digest, fdroidkey)) - apksign = "F-Droid built and signed version"; - else - apksign = c.getString(R.string.built_by,cert.getSubjectX500Principal().getName()); - - PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); - version = packageinfo.versionName; - - } catch (NameNotFoundException e) { - } catch (CertificateException e) { - } catch (NoSuchAlgorithmException e) { - } - - Object[] argsext = Arrays.copyOf(mArgs, mArgs.length+2); - argsext[argsext.length-1]=apksign; - argsext[argsext.length-2]=version; - - return c.getString(R.string.mobile_info_extended, argsext); - - } - - public long getLogtime() { - return logtime; - } - - - public int getVerbosityLevel() { - if (mVerbosityLevel==-1) { - // Hack: - // For message not from OpenVPN, report the status level as log level - return mLevel.getInt(); - } - return mVerbosityLevel; - } - } - - - - public interface LogListener { - void newLog(LogItem logItem); - } - - public interface StateListener { - void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level); - } - - public interface ByteCountListener { - void updateByteCount(long in, long out, long diffIn, long diffOut); - } - - public synchronized static void logMessage(LogLevel level,String prefix, String message) - { - newLogItem(new LogItem(level, prefix + message)); - - } - - public synchronized static void clearLog() { - logbuffer.clear(); - logInformation(); - } - - private static void logInformation() { - logInfo(R.string.mobile_info,Build.MODEL, Build.BOARD,Build.BRAND,Build.VERSION.SDK_INT); - } - - public synchronized static void addLogListener(LogListener ll){ - logListener.add(ll); - } - - public synchronized static void removeLogListener(LogListener ll) { - logListener.remove(ll); - } - - public synchronized static void addByteCountListener(ByteCountListener bcl) { - bcl.updateByteCount(mlastByteCount[0], mlastByteCount[1], mlastByteCount[2], mlastByteCount[3]); - byteCountListener.add(bcl); - } - - public synchronized static void removeByteCountListener(ByteCountListener bcl) { - byteCountListener.remove(bcl); - } - - - public synchronized static void addStateListener(StateListener sl){ - if(!stateListener.contains(sl)){ - stateListener.add(sl); - if(mLaststate!=null) - sl.updateState(mLaststate, mLaststatemsg, mLastStateresid, mLastLevel); - } - } - - private static int getLocalizedState(String state){ - if (state.equals("CONNECTING")) - return R.string.state_connecting; - else if (state.equals("WAIT")) - return R.string.state_wait; - else if (state.equals("AUTH")) - return R.string.state_auth; - else if (state.equals("GET_CONFIG")) - return R.string.state_get_config; - else if (state.equals("ASSIGN_IP")) - return R.string.state_assign_ip; - else if (state.equals("ADD_ROUTES")) - return R.string.state_add_routes; - else if (state.equals("CONNECTED")) - return R.string.state_connected; - else if (state.equals("DISCONNECTED")) - return R.string.state_disconnected; - else if (state.equals("RECONNECTING")) - return R.string.state_reconnecting; - else if (state.equals("EXITING")) - return R.string.state_exiting; - else if (state.equals("RESOLVE")) - return R.string.state_resolve; - else if (state.equals("TCP_CONNECT")) - return R.string.state_tcp_connect; - else - return R.string.unknown_state; - - } - - public static void updateStatePause(OpenVPNManagement.pauseReason pauseReason) { - switch (pauseReason) { - case noNetwork: - VpnStatus.updateStateString("NONETWORK", "", R.string.state_nonetwork, ConnectionStatus.LEVEL_NONETWORK); - break; - case screenOff: - VpnStatus.updateStateString("SCREENOFF", "", R.string.state_screenoff, ConnectionStatus.LEVEL_VPNPAUSED); - break; - case userPause: - VpnStatus.updateStateString("USERPAUSE", "", R.string.state_userpause, ConnectionStatus.LEVEL_VPNPAUSED); - break; - } - - } - - private static ConnectionStatus getLevel(String state){ - String[] noreplyet = {"CONNECTING","WAIT", "RECONNECTING", "RESOLVE", "TCP_CONNECT"}; - String[] reply = {"AUTH","GET_CONFIG","ASSIGN_IP","ADD_ROUTES"}; - String[] connected = {"CONNECTED"}; - String[] notconnected = {"DISCONNECTED", "EXITING"}; - - for(String x:noreplyet) - if(state.equals(x)) - return ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET; - - for(String x:reply) - if(state.equals(x)) - return ConnectionStatus.LEVEL_CONNECTING_SERVER_REPLIED; - - for(String x:connected) - if(state.equals(x)) - return ConnectionStatus.LEVEL_CONNECTED; - - for(String x:notconnected) - if(state.equals(x)) - return ConnectionStatus.LEVEL_NOTCONNECTED; - - return ConnectionStatus.UNKNOWN_LEVEL; - - } - - - - - public synchronized static void removeStateListener(StateListener sl) { - stateListener.remove(sl); - } - - - synchronized public static LogItem[] getlogbuffer() { - - // The stoned way of java to return an array from a vector - // brought to you by eclipse auto complete - return logbuffer.toArray(new LogItem[logbuffer.size()]); - - } - - public static void updateStateString (String state, String msg) { - int rid = getLocalizedState(state); - ConnectionStatus level = getLevel(state); - updateStateString(state, msg, rid, level); - } - - public synchronized static void updateStateString(String state, String msg, int resid, ConnectionStatus level) { - // Workound for OpenVPN doing AUTH and wait and being connected - // Simply ignore these state - if (mLastLevel == ConnectionStatus.LEVEL_CONNECTED && - (state.equals("WAIT") || state.equals("AUTH"))) - { - newLogItem(new LogItem((LogLevel.DEBUG), String.format("Ignoring OpenVPN Status in CONNECTED state (%s->%s): %s",state,level.toString(),msg))); - return; - } - - mLaststate= state; - mLaststatemsg = msg; - mLastStateresid = resid; - mLastLevel = level; - - - - for (StateListener sl : stateListener) { - sl.updateState(state,msg,resid,level); - } - //newLogItem(new LogItem((LogLevel.DEBUG), String.format("New OpenVPN Status (%s->%s): %s",state,level.toString(),msg))); - } - - public static void logInfo(String message) { - newLogItem(new LogItem(LogLevel.INFO, message)); - } - - public static void logDebug(String message) { - newLogItem(new LogItem(LogLevel.DEBUG, message)); - } - - public static void logInfo(int resourceId, Object... args) { - newLogItem(new LogItem(LogLevel.INFO, resourceId, args)); - } - - public static void logDebug(int resourceId, Object... args) { - newLogItem(new LogItem(LogLevel.DEBUG, resourceId, args)); - } - - - private synchronized static void newLogItem(LogItem logItem) { - logbuffer.addLast(logItem); - if(logbuffer.size()>MAXLOGENTRIES) - logbuffer.removeFirst(); - - for (LogListener ll : logListener) { - ll.newLog(logItem); - } - } - - public static void logError(String msg) { - newLogItem(new LogItem(LogLevel.ERROR, msg)); - - } - - public static void logWarning(int resourceId, Object... args) { - newLogItem(new LogItem(LogLevel.WARNING, resourceId, args)); - } - - public static void logWarning(String msg) { - newLogItem(new LogItem(LogLevel.WARNING, msg)); - } - - - public static void logError(int resourceId) { - newLogItem(new LogItem(LogLevel.ERROR, resourceId)); - } - public static void logError(int resourceId, Object... args) { - newLogItem(new LogItem(LogLevel.ERROR, resourceId, args)); - } - - public static void logMessageOpenVPN(LogLevel level, int ovpnlevel, String message) { - newLogItem(new LogItem(level, ovpnlevel, message)); - - } - - - 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; - - - - mlastByteCount = new long[] {in,out,diffIn,diffOut}; - for(ByteCountListener bcl:byteCountListener){ - bcl.updateByteCount(in, out, diffIn,diffOut); - } - } - - - -} diff --git a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/X509Utils.java b/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/X509Utils.java deleted file mode 100644 index 0786967b..00000000 --- a/ics-openvpn-stripped/main/src/main/java/de/blinkt/openvpn/core/X509Utils.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2012-2014 Arne Schwabe - * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt - */ - -package de.blinkt.openvpn.core; - -import android.content.Context; -import android.text.TextUtils; - -import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; -import org.spongycastle.util.io.pem.PemObject; -import org.spongycastle.util.io.pem.PemReader; - - -import javax.security.auth.x500.X500Principal; -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Hashtable; - -public class X509Utils { - public static Certificate getCertificateFromFile(String certfilename) throws FileNotFoundException, CertificateException { - CertificateFactory certFact = CertificateFactory.getInstance("X.509"); - - InputStream inStream; - - if(VpnProfile.isEmbedded(certfilename)) { - // The java certifcate reader is ... kind of stupid - // It does NOT ignore chars before the --BEGIN ... - int subIndex = certfilename.indexOf("-----BEGIN CERTIFICATE-----"); - subIndex = Math.max(0,subIndex); - inStream = new ByteArrayInputStream(certfilename.substring(subIndex).getBytes()); - - - } else { - inStream = new FileInputStream(certfilename); - } - - - return certFact.generateCertificate(inStream); - } - - public static PemObject readPemObjectFromFile (String keyfilename) throws IOException { - - Reader inStream; - - if(VpnProfile.isEmbedded(keyfilename)) - inStream = new StringReader(VpnProfile.getEmbeddedContent(keyfilename)); - else - inStream = new FileReader(new File(keyfilename)); - - PemReader pr = new PemReader(inStream); - PemObject r = pr.readPemObject(); - pr.close(); - return r; - } - - - - - public static String getCertificateFriendlyName (Context c, String filename) { - if(!TextUtils.isEmpty(filename)) { - try { - X509Certificate cert = (X509Certificate) getCertificateFromFile(filename); - - return getCertificateFriendlyName(cert); - - } catch (Exception e) { - VpnStatus.logError("Could not read certificate" + e.getLocalizedMessage()); - } - } - return c.getString(R.string.cannotparsecert); - } - - public static String getCertificateFriendlyName(X509Certificate cert) { - X500Principal principal = cert.getSubjectX500Principal(); - byte[] encodedSubject = principal.getEncoded(); - String friendlyName=null; - - /* Hack so we do not have to ship a whole Spongy/bouncycastle */ - Exception exp=null; - try { - Class X509NameClass = Class.forName("com.android.org.bouncycastle.asn1.x509.X509Name"); - Method getInstance = X509NameClass.getMethod("getInstance",Object.class); - - Hashtable defaultSymbols = (Hashtable) X509NameClass.getField("DefaultSymbols").get(X509NameClass); - - if (!defaultSymbols.containsKey("1.2.840.113549.1.9.1")) - defaultSymbols.put("1.2.840.113549.1.9.1","eMail"); - - Object subjectName = getInstance.invoke(X509NameClass, encodedSubject); - - Method toString = X509NameClass.getMethod("toString",boolean.class,Hashtable.class); - - friendlyName= (String) toString.invoke(subjectName,true,defaultSymbols); - - } catch (ClassNotFoundException e) { - exp =e ; - } catch (NoSuchMethodException e) { - exp =e; - } catch (InvocationTargetException e) { - exp =e; - } catch (IllegalAccessException e) { - exp =e; - } catch (NoSuchFieldException e) { - exp =e; - } - if (exp!=null) - VpnStatus.logException("Getting X509 Name from certificate", exp); - - /* Fallback if the reflection method did not work */ - if(friendlyName==null) - friendlyName = principal.getName(); - - - // Really evil hack to decode email address - // See: http://code.google.com/p/android/issues/detail?id=21531 - - String[] parts = friendlyName.split(","); - for (int i=0;i<parts.length;i++){ - String part = parts[i]; - if (part.startsWith("1.2.840.113549.1.9.1=#16")) { - parts[i] = "email=" + ia5decode(part.replace("1.2.840.113549.1.9.1=#16", "")); - } - } - friendlyName = TextUtils.join(",", parts); - return friendlyName; - } - - public static boolean isPrintableChar(char c) { - Character.UnicodeBlock block = Character.UnicodeBlock.of( c ); - return (!Character.isISOControl(c)) && - block != null && - block != Character.UnicodeBlock.SPECIALS; - } - - private static String ia5decode(String ia5string) { - String d = ""; - for (int i=1;i<ia5string.length();i=i+2) { - String hexstr = ia5string.substring(i-1,i+1); - char c = (char) Integer.parseInt(hexstr,16); - if (isPrintableChar(c)) { - d+=c; - } else if (i==1 && (c==0x12 || c==0x1b)) { - ; // ignore - } else { - d += "\\x" + hexstr; - } - } - return d; - } - - -} |