From d7ec9395e2f4118a00109a3bffb9fef49bc0f583 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Mon, 30 Jul 2012 20:43:49 +0200 Subject: Use system proxy settings for openvpn --- res/values-de/strings.xml | 3 +- res/values/strings.xml | 4 ++ res/xml/general_settings.xml | 5 +++ src/de/blinkt/openvpn/OpenVpnManagementThread.java | 46 +++++++++++++------ src/de/blinkt/openvpn/ProxyDetection.java | 52 ++++++++++++++++++++++ src/de/blinkt/openvpn/ShowConfigFragment.java | 2 +- src/de/blinkt/openvpn/VpnProfile.java | 15 ++++++- 7 files changed, 110 insertions(+), 17 deletions(-) create mode 100644 src/de/blinkt/openvpn/ProxyDetection.java diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index c7a80eed..8884b9e2 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -194,5 +194,6 @@ Warnung beim Verbinden und Benachrichtigungston Auf manchen ROM Version sind eventuell die Zugriffsrechte von /dev/tun falsch oder das tun Kernel Modul fehlt. Für Cyanogenmod 9 ROMs mit root gibt einen provisorischen Fix in den generellen Einstellungen. Importiere die PKCS12 Datei, die in der Konfiguration angegeben ist, in den Android Keystore - + Benutze System Proxies + Benutze die System weiten Einstellungen für HTTP/HTTPS Proxies beim Verbinden. diff --git a/res/values/strings.xml b/res/values/strings.xml index 6ad486a5..dcdeb095 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -237,4 +237,8 @@ Try to load the tun.ko kernel module before trying to connect. Needs rooted devices. Load tun module Import PKCS12 from configuration into Android Keystore + Error getting proxy settings: %s + Using proxy %1$s %2$d + Use system proxy + Use the system wide configuration for HTTP/HTTPS proxies to connect. diff --git a/res/xml/general_settings.xml b/res/xml/general_settings.xml index 73b66b00..5a2be01d 100644 --- a/res/xml/general_settings.xml +++ b/res/xml/general_settings.xml @@ -16,6 +16,11 @@ android:key="statusafterconnect" android:summary="@string/keppstatus_summary" android:title="@string/keepstatus" /> + active=new Vector(); - + static private native void jniclose(int fdint); static private native byte[] rsasign(byte[] input,int pkey) throws InvalidKeyException; @@ -178,8 +180,10 @@ public class OpenVpnManagementThread implements Runnable { processNeedCommand(argument); } else if (cmd.equals("BYTECOUNT")){ processByteCount(argument); - } else if (cmd.equals("STATE")){ + } else if (cmd.equals("STATE")) { processState(argument); + } else if (cmd.equals("PROXY")) { + processProxyCMD(argument); } else if (cmd.equals("LOG")) { String[] args = argument.split(",",3); // 0 unix time stamp @@ -200,6 +204,22 @@ public class OpenVpnManagementThread implements Runnable { } } + private void processProxyCMD(String argument) { + SocketAddress proxyaddr = ProxyDetection.detectProxy(mProfile); + + + if(proxyaddr instanceof InetSocketAddress ){ + InetSocketAddress isa = (InetSocketAddress) proxyaddr; + + OpenVPN.logInfo(R.string.using_proxy, isa.getHostName(),isa.getPort()); + + String proxycmd = String.format("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); mCurrentstate = args[1]; @@ -337,7 +357,7 @@ public class OpenVpnManagementThread implements Runnable { } return false; } - + private void processPWCommand(String argument) { //argument has the form Need 'Private Key' password @@ -400,21 +420,21 @@ public class OpenVpnManagementThread implements Runnable { } private void processSignCommand(String b64data) { - + PrivateKey privkey = mProfile.getKeystoreKey(); Exception err =null; // The Jelly Bean *evil* Hack - + byte[] data = Base64.decode(b64data, Base64.DEFAULT); if(Build.VERSION.SDK_INT>=16){ processSignJellyBeans(privkey,data); return; } - - + + try{ - + Cipher rsasinger = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); @@ -450,19 +470,19 @@ public class OpenVpnManagementThread implements Runnable { System.out.println(allm); Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey"); getKey.setAccessible(true); - + // Real object type is OpenSSLKey Object opensslkey = getKey.invoke(privkey); - + getKey.setAccessible(false); - + Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext"); - + // integer pointer to EVP_pkey getPkeyContext.setAccessible(true); int pkey = (Integer) getPkeyContext.invoke(opensslkey); getPkeyContext.setAccessible(false); - + byte[] signed_bytes = rsasign(data, pkey); String signed_string = Base64.encodeToString(signed_bytes, Base64.NO_WRAP); managmentCommand("rsa-sig\n"); diff --git a/src/de/blinkt/openvpn/ProxyDetection.java b/src/de/blinkt/openvpn/ProxyDetection.java new file mode 100644 index 00000000..dfcfbf19 --- /dev/null +++ b/src/de/blinkt/openvpn/ProxyDetection.java @@ -0,0 +1,52 @@ +package de.blinkt.openvpn; + +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; + +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) { + OpenVPN.logError(R.string.getproxy_error,e.getLocalizedMessage()); + } catch (URISyntaxException e) { + OpenVPN.logError(R.string.getproxy_error,e.getLocalizedMessage()); + } + return null; + } + + static Proxy getFirstProxy(URL url) throws URISyntaxException { + System.setProperty("java.net.useSystemProxies", "true"); + + List 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/src/de/blinkt/openvpn/ShowConfigFragment.java b/src/de/blinkt/openvpn/ShowConfigFragment.java index 2f6c23d7..dae83438 100644 --- a/src/de/blinkt/openvpn/ShowConfigFragment.java +++ b/src/de/blinkt/openvpn/ShowConfigFragment.java @@ -27,7 +27,7 @@ public class ShowConfigFragment extends Fragment { configtext = getString(check); } else { - String cfg=vp.getConfigFile(getActivity().getCacheDir()); + String cfg=vp.getConfigFile(getActivity()); configtext= cfg; cv.setText(cfg); } diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java index 4e381fcc..199f6b54 100644 --- a/src/de/blinkt/openvpn/VpnProfile.java +++ b/src/de/blinkt/openvpn/VpnProfile.java @@ -23,7 +23,9 @@ import org.spongycastle.util.io.pem.PemWriter; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; +import android.preference.PreferenceManager; import android.security.KeyChain; import android.security.KeyChainException; @@ -144,9 +146,10 @@ public class VpnProfile implements Serializable{ } - public String getConfigFile(File cacheDir) + public String getConfigFile(Context context) { + File cacheDir= context.getCacheDir(); String cfg=""; // Enable managment interface @@ -331,6 +334,14 @@ public class VpnProfile implements Serializable{ if(mUseFloat) cfg+= "float\n"; + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean usesystemproxy = prefs.getBoolean("usesystemproxy", true); + if(usesystemproxy) { + cfg+= "# Use system proxy setting\n"; + cfg+= "management-query-proxy\n"; + } + + if(mUseCustomConfig) { cfg += "# Custom configuration options\n"; cfg += "# You are on your on own here :)\n"; @@ -464,7 +475,7 @@ public class VpnProfile implements Serializable{ try { FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE); - cfg.write(getConfigFile(context.getCacheDir())); + cfg.write(getConfigFile(context)); cfg.flush(); cfg.close(); } catch (IOException e) { -- cgit v1.2.3