├── .gitignore ├── COPYING ├── OpenVpnLib ├── .classpath ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── assets │ ├── minivpn.armeabi │ ├── minivpn.armeabi-v7a │ ├── minivpn.mips │ └── minivpn.x86 ├── build.xml ├── libs │ ├── android-support-v4.jar │ ├── armeabi │ │ ├── libopenvpn.so │ │ ├── libopvpnutil.so │ │ └── libstlport_shared.so │ └── x86 │ │ ├── libopenvpn.so │ │ ├── libopvpnutil.so │ │ └── libstlport_shared.so ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-xhdpi │ │ └── notification_icon.png │ ├── drawable-xxhdpi │ │ └── notification_icon.png │ ├── drawable │ │ └── launcher.png │ └── values │ │ └── strings.xml └── src │ ├── de │ └── blinkt │ │ └── openvpn │ │ ├── EclipseBuildConfig.java │ │ ├── VpnProfile.java │ │ └── core │ │ ├── CIDRIP.java │ │ ├── ConfigParser.java │ │ ├── GetRestrictionReceiver.java │ │ ├── ICSOpenVPNApplication.java │ │ ├── NativeUtils.java │ │ ├── NetworkSpace.java │ │ ├── NetworkStateManager.java │ │ ├── OpenVPNManagement.java │ │ ├── OpenVPNThread.java │ │ ├── OpenVpnManagementThread.java │ │ ├── OpenVpnService.java │ │ ├── PRNGFixes.java │ │ ├── ProfileManager.java │ │ ├── ProxyDetection.java │ │ ├── VPNLaunchHelper.java │ │ ├── VpnStatus.java │ │ └── X509Utils.java │ ├── me │ └── disconnect │ │ └── securefi │ │ └── openvpnlib │ │ └── OpenVPNImplementation.java │ └── org │ └── spongycastle │ └── util │ ├── encoders │ ├── Base64.java │ ├── Base64Encoder.java │ └── Encoder.java │ └── io │ └── pem │ ├── PemGenerationException.java │ ├── PemHeader.java │ ├── PemObject.java │ ├── PemObjectGenerator.java │ ├── PemReader.java │ └── PemWriter.java ├── README.md ├── disconnect ├── .classpath ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── ant.properties ├── assets │ ├── fonts │ │ ├── AvenirNextLTPro-Bold.otf │ │ ├── AvenirNextLTPro-Demi.otf │ │ ├── AvenirNextLTPro-Medium.otf │ │ ├── AvenirNextLTPro-Regular.otf │ │ └── AvenirNextLTPro-Thin.otf │ ├── minivpn.armeabi │ ├── minivpn.armeabi-v7a │ ├── minivpn.mips │ └── minivpn.x86 ├── build.xml ├── ic_launcher-web.png ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── color │ │ └── package_button_text_color.xml │ ├── drawable-hdpi │ │ ├── ic_action_cancel.png │ │ ├── icon.png │ │ ├── launcher.png │ │ └── notification_icon.png │ ├── drawable-mdpi │ │ └── ic_action_cancel.png │ ├── drawable-sw600dp-xhdpi │ │ ├── background_collusion_off.png │ │ ├── background_collusion_on.png │ │ ├── background_pack_repeat.png │ │ ├── ic_ad_off.png │ │ ├── ic_ad_on.png │ │ ├── ic_basic_off.png │ │ ├── ic_basic_on.png │ │ ├── ic_circle_off.png │ │ ├── ic_circle_on.png │ │ ├── ic_malware_off.png │ │ └── ic_malware_on.png │ ├── drawable-sw720dp-xhdpi │ │ ├── background_collusion_off.png │ │ ├── background_collusion_on.png │ │ ├── background_pack_repeat.png │ │ ├── ic_ad_off.png │ │ ├── ic_ad_on.png │ │ ├── ic_basic_off.png │ │ ├── ic_basic_on.png │ │ ├── ic_circle_off.png │ │ ├── ic_circle_on.png │ │ ├── ic_malware_off.png │ │ └── ic_malware_on.png │ ├── drawable-xhdpi │ │ ├── background_collusion_off.png │ │ ├── background_collusion_on.png │ │ ├── background_pack_repeat.png │ │ ├── background_sampling.png │ │ ├── ic_action_cancel.png │ │ ├── ic_ad_off.png │ │ ├── ic_ad_on.png │ │ ├── ic_basic_off.png │ │ ├── ic_basic_on.png │ │ ├── ic_circle_off.png │ │ ├── ic_circle_on.png │ │ ├── ic_disconnect.png │ │ ├── ic_malware_off.png │ │ ├── ic_malware_on.png │ │ ├── icon.png │ │ ├── launcher.png │ │ └── notification_icon.png │ ├── drawable-xxhdpi │ │ ├── ic_action_cancel.png │ │ ├── icon.png │ │ ├── launcher.png │ │ └── notification_icon.png │ ├── drawable │ │ ├── ad_button.xml │ │ ├── basic_button.xml │ │ ├── malware_button.xml │ │ ├── overlay_button_shape.xml │ │ ├── packages_background.xml │ │ └── protect_button.xml │ ├── layout │ │ ├── activity_info.xml │ │ ├── activity_main.xml │ │ ├── connecting_overlay.xml │ │ ├── front_screen.xml │ │ ├── package_alert_dialog.xml │ │ ├── startup_overlay.xml │ │ └── web_upgrade.xml │ ├── menu │ │ ├── main.xml │ │ └── web_upgrade_menu.xml │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ ├── values-w820dp │ │ └── dimens.xml │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── invisible.xml │ │ ├── strings.xml │ │ ├── strings_non_translate.xml │ │ └── styles.xml └── src │ ├── com │ └── android │ │ └── vending │ │ └── billing │ │ └── IInAppBillingService.aidl │ └── me │ └── disconnect │ └── mobile │ ├── ConnectButton.java │ ├── DisconnectMobileConfig.java │ ├── DisconnectMobilePrefs.java │ ├── FrontScreenFragment.java │ ├── InfoActivity.java │ ├── InvisibleActivity.java │ ├── MainActivity.java │ ├── PackageButton.java │ ├── WebUpgradeActivity.java │ ├── billing │ ├── Base64.java │ ├── Base64DecoderException.java │ ├── BillingHelper.java │ ├── BillingObserver.java │ ├── IabException.java │ ├── IabHelper.java │ ├── IabResult.java │ ├── Inventory.java │ ├── Purchase.java │ ├── Security.java │ └── SkuDetails.java │ ├── packages │ ├── PackageAlertDialog.java │ ├── PackageDescription.java │ ├── PackageDescriptionManager.java │ └── Provisioner.java │ └── vpn │ ├── ConnectivityReceiver.java │ ├── SecureFiDetector.java │ ├── SynchronizedFactory.java │ ├── VPNProvider.java │ └── VpnManager.java └── engineinterface ├── .classpath ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── build.xml ├── config └── LoggingConfig.java ├── custom_rules.xml ├── custom_rules.xml~ ├── proguard-project.txt ├── project.properties └── src └── me └── disconnect └── securefi └── engine ├── LoggingConfig.java └── VPNImplementation.java /.gitignore: -------------------------------------------------------------------------------- 1 | gen 2 | bin 3 | obj 4 | *.DS_Store 5 | .DS_Store 6 | 7 | # Built application files 8 | *.apk 9 | *.ap_ 10 | 11 | # Files for the Dalvik VM 12 | *.dex 13 | 14 | # Java class files 15 | *.class 16 | 17 | # Local configuration file (sdk path, etc) 18 | local.properties 19 | 20 | # Proguard folder generated by Eclipse 21 | proguard/ 22 | -------------------------------------------------------------------------------- /OpenVpnLib/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /OpenVpnLib/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | OpenVpnLib 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /OpenVpnLib/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /OpenVpnLib/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /OpenVpnLib/assets/minivpn.armeabi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/assets/minivpn.armeabi -------------------------------------------------------------------------------- /OpenVpnLib/assets/minivpn.armeabi-v7a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/assets/minivpn.armeabi-v7a -------------------------------------------------------------------------------- /OpenVpnLib/assets/minivpn.mips: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/assets/minivpn.mips -------------------------------------------------------------------------------- /OpenVpnLib/assets/minivpn.x86: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/assets/minivpn.x86 -------------------------------------------------------------------------------- /OpenVpnLib/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /OpenVpnLib/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/android-support-v4.jar -------------------------------------------------------------------------------- /OpenVpnLib/libs/armeabi/libopenvpn.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/armeabi/libopenvpn.so -------------------------------------------------------------------------------- /OpenVpnLib/libs/armeabi/libopvpnutil.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/armeabi/libopvpnutil.so -------------------------------------------------------------------------------- /OpenVpnLib/libs/armeabi/libstlport_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/armeabi/libstlport_shared.so -------------------------------------------------------------------------------- /OpenVpnLib/libs/x86/libopenvpn.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/x86/libopenvpn.so -------------------------------------------------------------------------------- /OpenVpnLib/libs/x86/libopvpnutil.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/x86/libopvpnutil.so -------------------------------------------------------------------------------- /OpenVpnLib/libs/x86/libstlport_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/libs/x86/libstlport_shared.so -------------------------------------------------------------------------------- /OpenVpnLib/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /OpenVpnLib/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | android.library=true 16 | android.library.reference.1=../engineinterface 17 | -------------------------------------------------------------------------------- /OpenVpnLib/res/drawable-xhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/res/drawable-xhdpi/notification_icon.png -------------------------------------------------------------------------------- /OpenVpnLib/res/drawable-xxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/res/drawable-xxhdpi/notification_icon.png -------------------------------------------------------------------------------- /OpenVpnLib/res/drawable/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/OpenVpnLib/res/drawable/launcher.png -------------------------------------------------------------------------------- /OpenVpnLib/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | You must select a User certificate 5 | No error found 6 | Error parsing the IPv4 address 7 | Error parsing the custom routes 8 | Route rejected by Android 9 | Disconnect 10 | On some custom ICS images the permission on /dev/tun might be wrong, or the tun module might be missing completely. For CM9 images try the fix ownership option under general settings 11 | Failed to open the tun interface 12 | "Error: " 13 | Opening tun interface: 14 | Local IPv4: %1$s/%2$d IPv6: %3$s MTU: %4$d 15 | DNS Server: %1$s, Domain: %2$s 16 | Routes: %1$s %2$s 17 | Routes excluded: %1$s %2$s 18 | VpnService routes installed: %1$s %2$s 19 | Got interface information %1$s and %2$s, assuming second address is peer address of remote. Using /32 netmask for local IP. Mode given by OpenVPN is \"%3$s\". 20 | Cannot make sense of %1$s and %2$s as IP route with CIDR netmask, using /32 as netmask. 21 | Corrected route %1$s/%2$s to %3$s/%2$s 22 | Cannot access the Android Keychain Certificates. This can be caused by a firmware upgrade or by restoring a backup of the app/app settings. Please edit the VPN and reselect the certificate under basic settings to recreate the permission to access the certificate. 23 | Refusing to open tun device without IP information 24 | PKCS12 File Encryption Key 25 | Private Key Password 26 | Password 27 | Building configuration… 28 | Network Status: %s 29 | No CA Certificate returned while reading from Android keystore. Auhtentication will probably fail. 30 | Running on %1$s (%2$s) %3$s, Android API %4$d 31 | Error signing with Android keystore key %1$s: %2$s 32 | No DNS servers being used. Name resolution may not work. Consider setting custom DNS Servers. Please also note that Android will keep using your proxy settings specified for your mobile/Wi-Fi connection when no DNS servers are set. 33 | Could not add DNS Server \"%1$s\", rejected by the system: %2$s 34 | Could not configure IP Address \"%1$s\", rejected by the system: %2$s 35 | Error getting proxy settings: %s 36 | Using proxy %1$s %2$d 37 | OpenVPN crashed unexpectedly. Please consider using the send Minidump option in the main menu 38 | Connecting 39 | Waiting for server reply 40 | Authenticating 41 | Getting client configuration 42 | Assigning IP addresses 43 | Adding routes 44 | Connected 45 | Disconnect 46 | Reconnecting 47 | Exiting 48 | Not running 49 | Resolving host names 50 | Connecting (TCP) 51 | Authentication failed 52 | Waiting for usable network 53 | ↓%2$s/s %1$s - ↑%4$s/s %3$s 54 | Connecting to VPN %s 55 | Connecting to VPN %s 56 | Some versions of Android 4.1 have problems if the name of the keystore certificate contains non alphanumeric characters (like spaces, underscores or dashes). Try to reimport the certificate without special characters 57 | Running on %1$s (%2$s) %3$s, Android API %4$d, version %5$s, %6$s 58 | built by %s 59 | debug build 60 | official build 61 | Pausing connection in screen off state: less than %1$s in %2$ss 62 | Warning: Persistent tun not enabled for this VPN. Traffic will use the normal Internet connection when the screen is off. 63 | Pause VPN 64 | Resume VPN 65 | VPN pause requested by user 66 | VPN paused - screen off 67 | Cannot display certificate information 68 | Allow changes to VPN Profiles 69 | KeyChain Access error: %s 70 | Unhandled exception: %1$s\n\n%2$s 71 | %3$s: %1$s\n\n%2$s 72 | 73 | Unknown state 74 | 75 | Currently blocking 76 | Not currently protected. Tap to protect 77 | Connecting 78 | Disconnect 79 | 80 | 81 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/EclipseBuildConfig.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn; 2 | 3 | import me.disconnect.securefi.openvpnlib.BuildConfig; 4 | 5 | public class EclipseBuildConfig { 6 | public static final boolean DEBUG = BuildConfig.DEBUG; 7 | public static final String PACKAGE_NAME = "de.blinkt.openvpn"; 8 | public static final String BUILD_TYPE = "debug"; 9 | public static final String FLAVOR = "normal"; 10 | public static final int VERSION_CODE = 93; 11 | public static final String VERSION_NAME = "0.6.12"; 12 | } 13 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/CIDRIP.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import java.util.Locale; 4 | 5 | class CIDRIP { 6 | String mIp; 7 | int len; 8 | 9 | 10 | public CIDRIP(String ip, String mask) { 11 | mIp = ip; 12 | long netmask = getInt(mask); 13 | 14 | // Add 33. bit to ensure the loop terminates 15 | netmask += 1l << 32; 16 | 17 | int lenZeros = 0; 18 | while ((netmask & 0x1) == 0) { 19 | lenZeros++; 20 | netmask = netmask >> 1; 21 | } 22 | // Check if rest of netmask is only 1s 23 | if (netmask != (0x1ffffffffl >> lenZeros)) { 24 | // Asume no CIDR, set /32 25 | len = 32; 26 | } else { 27 | len = 32 - lenZeros; 28 | } 29 | 30 | } 31 | 32 | public CIDRIP(String address, int prefix_length) { 33 | len = prefix_length; 34 | mIp = address; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return String.format(Locale.ENGLISH, "%s/%d", mIp, len); 40 | } 41 | 42 | public boolean normalise() { 43 | long ip = getInt(mIp); 44 | 45 | long newip = ip & (0xffffffffl << (32 - len)); 46 | if (newip != ip) { 47 | mIp = String.format("%d.%d.%d.%d", (newip & 0xff000000) >> 24, (newip & 0xff0000) >> 16, (newip & 0xff00) >> 8, newip & 0xff); 48 | return true; 49 | } else { 50 | return false; 51 | } 52 | } 53 | 54 | static long getInt(String ipaddr) { 55 | String[] ipt = ipaddr.split("\\."); 56 | long ip = 0; 57 | 58 | ip += Long.parseLong(ipt[0]) << 24; 59 | ip += Integer.parseInt(ipt[1]) << 16; 60 | ip += Integer.parseInt(ipt[2]) << 8; 61 | ip += Integer.parseInt(ipt[3]); 62 | 63 | return ip; 64 | } 65 | 66 | public long getInt() { 67 | return getInt(mIp); 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/GetRestrictionReceiver.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.RestrictionEntry; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | 12 | import java.util.ArrayList; 13 | 14 | import me.disconnect.securefi.openvpnlib.R; 15 | 16 | 17 | /** 18 | * Created by arne on 25.07.13. 19 | */ 20 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 21 | public class GetRestrictionReceiver extends BroadcastReceiver { 22 | @Override 23 | public void onReceive(final Context context, Intent intent) { 24 | final PendingResult result = goAsync(); 25 | 26 | new Thread() { 27 | @Override 28 | public void run() { 29 | final Bundle extras = new Bundle(); 30 | 31 | ArrayList restrictionEntries = initRestrictions(context); 32 | 33 | extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, restrictionEntries); 34 | result.setResult(Activity.RESULT_OK,null,extras); 35 | result.finish(); 36 | } 37 | }.run(); 38 | } 39 | 40 | private ArrayList initRestrictions(Context context) { 41 | ArrayList restrictions = new ArrayList(); 42 | RestrictionEntry allowChanges = new RestrictionEntry("allow_changes",false); 43 | allowChanges.setTitle(context.getString(R.string.allow_vpn_changes)); 44 | restrictions.add(allowChanges); 45 | 46 | return restrictions; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/ICSOpenVPNApplication.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * Created by arne on 28.12.13. 7 | */ 8 | public class ICSOpenVPNApplication extends Application { 9 | @Override 10 | public void onCreate() { 11 | super.onCreate(); 12 | PRNGFixes.apply(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/NativeUtils.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import java.security.InvalidKeyException; 4 | 5 | public class NativeUtils { 6 | public static native byte[] rsasign(byte[] input,int pkey) throws InvalidKeyException; 7 | static native void jniclose(int fdint); 8 | 9 | static { 10 | System.loadLibrary("stlport_shared"); 11 | System.loadLibrary("opvpnutil"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/NetworkStateManager.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.SharedPreferences; 7 | import android.net.ConnectivityManager; 8 | import android.net.NetworkInfo; 9 | import android.net.NetworkInfo.State; 10 | import android.preference.PreferenceManager; 11 | 12 | import java.util.LinkedList; 13 | 14 | import me.disconnect.securefi.openvpnlib.R; 15 | 16 | 17 | public class NetworkStateManager { 18 | private int lastNetwork = -1; 19 | private OpenVPNManagement mManagement; 20 | 21 | 22 | connectState network = connectState.DISCONNECTED; 23 | 24 | private String lastStateMsg = null; 25 | 26 | enum connectState { 27 | SHOULDBECONNECTED, 28 | PENDINGDISCONNECT, 29 | DISCONNECTED 30 | } 31 | 32 | 33 | public NetworkStateManager(OpenVPNManagement magnagement) { 34 | super(); 35 | mManagement = magnagement; 36 | } 37 | 38 | 39 | public void networkStateChange(Context context) { 40 | NetworkInfo networkInfo = getCurrentNetworkInfo(context); 41 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 42 | boolean sendusr1 = prefs.getBoolean("netchangereconnect", true); 43 | 44 | 45 | String netstatestring; 46 | if (networkInfo == null) { 47 | netstatestring = "not connected"; 48 | } else { 49 | String subtype = networkInfo.getSubtypeName(); 50 | if (subtype == null) 51 | subtype = ""; 52 | String extrainfo = networkInfo.getExtraInfo(); 53 | if (extrainfo == null) 54 | extrainfo = ""; 55 | 56 | /* 57 | if(networkInfo.getType()==android.net.ConnectivityManager.TYPE_WIFI) { 58 | WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 59 | WifiInfo wifiinfo = wifiMgr.getConnectionInfo(); 60 | extrainfo+=wifiinfo.getBSSID(); 61 | 62 | subtype += wifiinfo.getNetworkId(); 63 | }*/ 64 | 65 | 66 | netstatestring = String.format("%2$s %4$s to %1$s %3$s", networkInfo.getTypeName(), 67 | networkInfo.getDetailedState(), extrainfo, subtype); 68 | } 69 | 70 | if (networkInfo != null && networkInfo.getState() == State.CONNECTED) { 71 | int newnet = networkInfo.getType(); 72 | network = connectState.SHOULDBECONNECTED; 73 | 74 | if (lastNetwork != newnet) { 75 | if (sendusr1) { 76 | if (lastNetwork == -1) { 77 | mManagement.resume(); 78 | } else { 79 | mManagement.reconnect(); 80 | } 81 | } else { 82 | mManagement.networkChange(); 83 | } 84 | 85 | lastNetwork = newnet; 86 | } 87 | } else if (networkInfo == null) { 88 | // No network coverage should be handled in the apps 89 | // connectivity receiver. 90 | } 91 | 92 | 93 | if (!netstatestring.equals(lastStateMsg)) 94 | VpnStatus.logInfo(R.string.netstatus, netstatestring); 95 | lastStateMsg = netstatestring; 96 | 97 | } 98 | 99 | private NetworkInfo getCurrentNetworkInfo(Context context) { 100 | ConnectivityManager conn = (ConnectivityManager) 101 | context.getSystemService(Context.CONNECTIVITY_SERVICE); 102 | 103 | return conn.getActiveNetworkInfo(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/OpenVPNManagement.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | public interface OpenVPNManagement { 4 | enum pauseReason { 5 | noNetwork, 6 | userPause, 7 | screenOff 8 | } 9 | 10 | int mBytecountInterval =2; 11 | 12 | void reconnect(); 13 | 14 | void pause(pauseReason reason); 15 | 16 | void resume(); 17 | 18 | boolean stopVPN(); 19 | 20 | /* 21 | * Rebind the interface 22 | */ 23 | void networkChange(); 24 | } 25 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/OpenVPNThread.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import android.util.Log; 4 | import de.blinkt.openvpn.VpnProfile; 5 | import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; 6 | import de.blinkt.openvpn.core.VpnStatus.LogItem; 7 | 8 | import java.io.*; 9 | import java.text.SimpleDateFormat; 10 | import java.util.*; 11 | import java.util.Map.Entry; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | import me.disconnect.securefi.engine.LoggingConfig; 16 | import me.disconnect.securefi.openvpnlib.R; 17 | 18 | public class OpenVPNThread implements Runnable { 19 | private static final String DUMP_PATH_STRING = "Dump path: "; 20 | private static final String TAG = "OpenVPN"; 21 | public static final int M_FATAL = (1 << 4); 22 | public static final int M_NONFATAL = (1 << 5); 23 | public static final int M_WARN = (1 << 6); 24 | public static final int M_DEBUG = (1 << 7); 25 | private String[] mArgv; 26 | private Process mProcess; 27 | private String mNativeDir; 28 | private OpenVpnService mService; 29 | private String mDumpPath; 30 | private Map mProcessEnv; 31 | 32 | public OpenVPNThread(OpenVpnService service,String[] argv, Map processEnv, String nativelibdir) 33 | { 34 | mArgv = argv; 35 | mNativeDir = nativelibdir; 36 | mService = service; 37 | mProcessEnv = processEnv; 38 | } 39 | 40 | public void stopProcess() { 41 | mProcess.destroy(); 42 | } 43 | 44 | 45 | 46 | @Override 47 | public void run() { 48 | try { 49 | if ( LoggingConfig.LOGGING ){ 50 | Log.i(TAG, "Starting openvpn"); 51 | } 52 | 53 | startOpenVPNThreadArgs(mArgv, mProcessEnv); 54 | 55 | if ( LoggingConfig.LOGGING ){ 56 | Log.i(TAG, "Giving up"); 57 | } 58 | } catch (Exception e) { 59 | VpnStatus.logException("Starting OpenVPN Thread" ,e); 60 | if ( LoggingConfig.LOGGING ){ 61 | Log.e(TAG, "OpenVPNThread Got " + e.toString()); 62 | } 63 | } finally { 64 | int exitvalue = 0; 65 | try { 66 | if (mProcess!=null) 67 | exitvalue = mProcess.waitFor(); 68 | } catch ( IllegalThreadStateException ite) { 69 | VpnStatus.logError("Illegal Thread state: " + ite.getLocalizedMessage()); 70 | } catch (InterruptedException ie) { 71 | VpnStatus.logError("InterruptedException: " + ie.getLocalizedMessage()); 72 | } 73 | if( exitvalue != 0) 74 | VpnStatus.logError("Process exited with exit value " + exitvalue); 75 | 76 | VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); 77 | if(mDumpPath!=null) { 78 | try { 79 | BufferedWriter logout = new BufferedWriter(new FileWriter(mDumpPath + ".log")); 80 | SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.GERMAN); 81 | for(LogItem li : VpnStatus.getlogbuffer()){ 82 | String time = timeformat.format(new Date(li.getLogtime())); 83 | logout.write(time +" " + li.getString(mService) + "\n"); 84 | } 85 | logout.close(); 86 | VpnStatus.logError(R.string.minidump_generated); 87 | } catch (IOException e) { 88 | VpnStatus.logError("Writing minidump log: " + e.getLocalizedMessage()); 89 | } 90 | } 91 | 92 | mService.processDied(); 93 | if ( LoggingConfig.LOGGING ){ 94 | Log.i(TAG, "Exiting"); 95 | } 96 | } 97 | } 98 | 99 | private void startOpenVPNThreadArgs(String[] argv, Map env) { 100 | LinkedList argvlist = new LinkedList(); 101 | 102 | Collections.addAll(argvlist, argv); 103 | 104 | ProcessBuilder pb = new ProcessBuilder(argvlist); 105 | // Hack O rama 106 | 107 | String lbpath = genLibraryPath(argv, pb); 108 | 109 | pb.environment().put("LD_LIBRARY_PATH", lbpath); 110 | 111 | // Add extra variables 112 | for(Entry e:env.entrySet()){ 113 | pb.environment().put(e.getKey(), e.getValue()); 114 | } 115 | pb.redirectErrorStream(true); 116 | try { 117 | mProcess = pb.start(); 118 | // Close the output, since we don't need it 119 | mProcess.getOutputStream().close(); 120 | InputStream in = mProcess.getInputStream(); 121 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 122 | 123 | while( true) { 124 | String logline = br.readLine(); 125 | if(logline==null) 126 | return; 127 | 128 | if ( Thread.interrupted() ){ 129 | // Force stopped. 130 | stopProcess(); 131 | break; 132 | } 133 | 134 | if (logline.startsWith(DUMP_PATH_STRING)) 135 | mDumpPath = logline.substring(DUMP_PATH_STRING.length()); 136 | 137 | 138 | // 1380308330.240114 18000002 Send to HTTP proxy: 'X-Online-Host: bla.blabla.com' 139 | 140 | Pattern p = Pattern.compile("(\\d+).(\\d+) ([0-9a-f])+ (.*)"); 141 | Matcher m = p.matcher(logline); 142 | if(m.matches()) { 143 | int flags = Integer.parseInt(m.group(3),16); 144 | String msg = m.group(4); 145 | int logLevel = flags & 0x0F; 146 | 147 | VpnStatus.LogLevel logStatus = VpnStatus.LogLevel.INFO; 148 | 149 | if ((flags & M_FATAL) != 0) 150 | logStatus = VpnStatus.LogLevel.ERROR; 151 | else if ((flags & M_NONFATAL)!=0) 152 | logStatus = VpnStatus.LogLevel.WARNING; 153 | else if ((flags & M_WARN)!=0) 154 | logStatus = VpnStatus.LogLevel.WARNING; 155 | else if ((flags & M_DEBUG)!=0) 156 | logStatus = VpnStatus.LogLevel.VERBOSE; 157 | 158 | if (msg.startsWith("MANAGEMENT: CMD")) 159 | logLevel = Math.max(4, logLevel); 160 | 161 | 162 | VpnStatus.logMessageOpenVPN(logStatus,logLevel,msg); 163 | } else { 164 | VpnStatus.logInfo("P:" + logline); 165 | } 166 | } 167 | 168 | 169 | } catch (IOException e) { 170 | VpnStatus.logException("Error reading from output of OpenVPN process" , e); 171 | stopProcess(); 172 | } 173 | } 174 | 175 | private String genLibraryPath(String[] argv, ProcessBuilder pb) { 176 | // Hack until I find a good way to get the real library path 177 | String applibpath = argv[0].replace("/cache/" + VpnProfile.MINIVPN , "/lib"); 178 | 179 | String lbpath = pb.environment().get("LD_LIBRARY_PATH"); 180 | if(lbpath==null) 181 | lbpath = applibpath; 182 | else 183 | lbpath = lbpath + ":" + applibpath; 184 | 185 | if (!applibpath.equals(mNativeDir)) { 186 | lbpath = lbpath + ":" + mNativeDir; 187 | } 188 | return lbpath; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/ProfileManager.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | import java.io.StreamCorruptedException; 8 | import java.util.Collection; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | import de.blinkt.openvpn.VpnProfile; 14 | 15 | import android.app.Activity; 16 | import android.content.Context; 17 | import android.content.SharedPreferences; 18 | import android.content.SharedPreferences.Editor; 19 | import android.preference.PreferenceManager; 20 | 21 | public class ProfileManager { 22 | private static final String PREFS_NAME = "VPNList"; 23 | 24 | 25 | 26 | private static final String ONBOOTPROFILE = "onBootProfile"; 27 | 28 | 29 | 30 | private static ProfileManager instance; 31 | 32 | 33 | 34 | private static VpnProfile mLastConnectedVpn=null; 35 | private HashMap profiles=new HashMap(); 36 | private static VpnProfile tmpprofile=null; 37 | 38 | 39 | private static VpnProfile get(String key) { 40 | if (tmpprofile!=null && tmpprofile.getUUIDString().equals(key)) 41 | return tmpprofile; 42 | 43 | if(instance==null) 44 | return null; 45 | return instance.profiles.get(key); 46 | 47 | } 48 | 49 | 50 | 51 | private ProfileManager() { } 52 | 53 | private static void checkInstance(Context context) { 54 | if(instance == null) { 55 | instance = new ProfileManager(); 56 | instance.loadVPNList(context); 57 | } 58 | } 59 | 60 | synchronized public static ProfileManager getInstance(Context context) { 61 | checkInstance(context); 62 | return instance; 63 | } 64 | 65 | public static void setConntectedVpnProfileDisconnected(Context c) { 66 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); 67 | Editor prefsedit = prefs.edit(); 68 | prefsedit.putString(ONBOOTPROFILE, null); 69 | prefsedit.apply(); 70 | 71 | } 72 | 73 | public static void setConnectedVpnProfile(Context c, VpnProfile connectedrofile) { 74 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); 75 | Editor prefsedit = prefs.edit(); 76 | 77 | prefsedit.putString(ONBOOTPROFILE, connectedrofile.getUUIDString()); 78 | prefsedit.apply(); 79 | mLastConnectedVpn=connectedrofile; 80 | 81 | } 82 | 83 | public static VpnProfile getOnBootProfile(Context c) { 84 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c); 85 | 86 | boolean useStartOnBoot = prefs.getBoolean("restartvpnonboot", false); 87 | 88 | 89 | String mBootProfileUUID = prefs.getString(ONBOOTPROFILE,null); 90 | if(useStartOnBoot && mBootProfileUUID!=null) 91 | return get(c, mBootProfileUUID); 92 | else 93 | return null; 94 | } 95 | 96 | 97 | 98 | 99 | public Collection getProfiles() { 100 | return profiles.values(); 101 | } 102 | 103 | public VpnProfile getProfileByName(String name) { 104 | for (VpnProfile vpnp : profiles.values()) { 105 | if(vpnp.getName().equals(name)) { 106 | return vpnp; 107 | } 108 | } 109 | return null; 110 | } 111 | 112 | public void saveProfileList(Context context) { 113 | SharedPreferences sharedprefs = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE); 114 | Editor editor = sharedprefs.edit(); 115 | editor.putStringSet("vpnlist", profiles.keySet()); 116 | 117 | // For reasing I do not understand at all 118 | // Android saves my prefs file only one time 119 | // if I remove the debug code below :( 120 | int counter = sharedprefs.getInt("counter", 0); 121 | editor.putInt("counter", counter+1); 122 | editor.apply(); 123 | 124 | } 125 | 126 | public void addProfile(VpnProfile profile) { 127 | profiles.put(profile.getUUID().toString(),profile); 128 | 129 | } 130 | 131 | public static void setTemporaryProfile(VpnProfile tmp) { 132 | ProfileManager.tmpprofile = tmp; 133 | } 134 | 135 | 136 | public void saveProfile(Context context,VpnProfile profile) { 137 | // First let basic settings save its state 138 | 139 | ObjectOutputStream vpnfile; 140 | try { 141 | vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE)); 142 | 143 | vpnfile.writeObject(profile); 144 | vpnfile.flush(); 145 | vpnfile.close(); 146 | } catch (FileNotFoundException e) { 147 | 148 | VpnStatus.logException("saving VPN profile", e); 149 | throw new RuntimeException(e); 150 | } catch (IOException e) { 151 | VpnStatus.logException("saving VPN profile", e); 152 | throw new RuntimeException(e); 153 | } 154 | } 155 | 156 | 157 | private void loadVPNList(Context context) { 158 | profiles = new HashMap(); 159 | SharedPreferences listpref = context.getSharedPreferences(PREFS_NAME,Activity.MODE_PRIVATE); 160 | Set vlist = listpref.getStringSet("vpnlist", null); 161 | Exception exp =null; 162 | if(vlist==null){ 163 | vlist = new HashSet(); 164 | } 165 | 166 | for (String vpnentry : vlist) { 167 | try { 168 | ObjectInputStream vpnfile = new ObjectInputStream(context.openFileInput(vpnentry + ".vp")); 169 | VpnProfile vp = ((VpnProfile) vpnfile.readObject()); 170 | 171 | // Sanity check 172 | if(vp==null || vp.mName==null || vp.getUUID()==null) 173 | continue; 174 | 175 | vp.upgradeProfile(); 176 | profiles.put(vp.getUUID().toString(), vp); 177 | 178 | } catch (StreamCorruptedException e) { 179 | exp=e; 180 | } catch (FileNotFoundException e) { 181 | exp=e; 182 | } catch (IOException e) { 183 | exp=e; 184 | } catch (ClassNotFoundException e) { 185 | exp=e; 186 | } 187 | if(exp!=null) { 188 | VpnStatus.logException("Loading VPN List",exp); 189 | } 190 | } 191 | } 192 | 193 | public int getNumberOfProfiles() { 194 | return profiles.size(); 195 | } 196 | 197 | 198 | 199 | public void removeProfile(Context context,VpnProfile profile) { 200 | String vpnentry = profile.getUUID().toString(); 201 | profiles.remove(vpnentry); 202 | saveProfileList(context); 203 | context.deleteFile(vpnentry + ".vp"); 204 | if(mLastConnectedVpn==profile) 205 | mLastConnectedVpn=null; 206 | 207 | } 208 | 209 | 210 | 211 | public static VpnProfile get(Context context, String profileUUID) { 212 | checkInstance(context); 213 | return get(profileUUID); 214 | } 215 | 216 | 217 | 218 | public static VpnProfile getLastConnectedVpn() { 219 | return mLastConnectedVpn; 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/ProxyDetection.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.net.MalformedURLException; 5 | import java.net.Proxy; 6 | import java.net.ProxySelector; 7 | import java.net.SocketAddress; 8 | import java.net.URISyntaxException; 9 | import java.net.URL; 10 | import java.util.List; 11 | 12 | import me.disconnect.securefi.openvpnlib.R; 13 | 14 | import de.blinkt.openvpn.VpnProfile; 15 | 16 | public class ProxyDetection { 17 | static SocketAddress detectProxy(VpnProfile vp) { 18 | // Construct a new url with https as protocol 19 | try { 20 | // TODO which port number is being used? 21 | URL url = new URL(String.format("https://%s:%s",vp.mServerName,vp.mServerPorts[0])); 22 | Proxy proxy = getFirstProxy(url); 23 | 24 | if(proxy==null) 25 | return null; 26 | SocketAddress addr = proxy.address(); 27 | if (addr instanceof InetSocketAddress) { 28 | return addr; 29 | } 30 | 31 | } catch (MalformedURLException e) { 32 | VpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage()); 33 | } catch (URISyntaxException e) { 34 | VpnStatus.logError(R.string.getproxy_error, e.getLocalizedMessage()); 35 | } 36 | return null; 37 | } 38 | 39 | static Proxy getFirstProxy(URL url) throws URISyntaxException { 40 | System.setProperty("java.net.useSystemProxies", "true"); 41 | 42 | List proxylist = ProxySelector.getDefault().select(url.toURI()); 43 | 44 | 45 | if (proxylist != null) { 46 | for (Proxy proxy: proxylist) { 47 | SocketAddress addr = proxy.address(); 48 | 49 | if (addr != null) { 50 | return proxy; 51 | } 52 | } 53 | 54 | } 55 | return null; 56 | } 57 | } -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/VPNLaunchHelper.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | import me.disconnect.securefi.openvpnlib.R; 9 | 10 | import android.content.Context; 11 | import android.content.Intent; 12 | import android.os.Build; 13 | import de.blinkt.openvpn.VpnProfile; 14 | 15 | public class VPNLaunchHelper { 16 | static private boolean writeMiniVPN(Context context) { 17 | File mvpnout = new File(context.getCacheDir(),VpnProfile.MINIVPN); 18 | if (mvpnout.exists() && mvpnout.canExecute()) 19 | return true; 20 | 21 | IOException e2 = null; 22 | 23 | try { 24 | InputStream mvpn; 25 | 26 | try { 27 | mvpn = context.getAssets().open("minivpn." + Build.CPU_ABI); 28 | } 29 | catch (IOException errabi) { 30 | VpnStatus.logInfo("Failed getting assets for archicture " + Build.CPU_ABI); 31 | e2=errabi; 32 | mvpn = context.getAssets().open("minivpn." + Build.CPU_ABI2); 33 | 34 | } 35 | 36 | 37 | FileOutputStream fout = new FileOutputStream(mvpnout); 38 | 39 | byte buf[]= new byte[4096]; 40 | 41 | int lenread = mvpn.read(buf); 42 | while(lenread> 0) { 43 | fout.write(buf, 0, lenread); 44 | lenread = mvpn.read(buf); 45 | } 46 | fout.close(); 47 | 48 | if(!mvpnout.setExecutable(true)) { 49 | VpnStatus.logError("Failed to set minivpn executable"); 50 | return false; 51 | } 52 | 53 | 54 | return true; 55 | } catch (IOException e) { 56 | if(e2!=null) 57 | VpnStatus.logException(e2); 58 | VpnStatus.logException(e); 59 | 60 | return false; 61 | } 62 | } 63 | 64 | 65 | public static void startOpenVpn(VpnProfile startprofile, Context context) { 66 | if(!writeMiniVPN(context)) { 67 | VpnStatus.logError("Error writing minivpn binary"); 68 | return; 69 | } 70 | 71 | VpnStatus.logInfo(R.string.building_configration); 72 | 73 | Intent startVPN = startprofile.prepareIntent(context); 74 | if(startVPN!=null) 75 | context.startService(startVPN); 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /OpenVpnLib/src/de/blinkt/openvpn/core/X509Utils.java: -------------------------------------------------------------------------------- 1 | package de.blinkt.openvpn.core; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import de.blinkt.openvpn.VpnProfile; 7 | import me.disconnect.securefi.openvpnlib.R; 8 | 9 | import org.spongycastle.util.io.pem.PemObject; 10 | import org.spongycastle.util.io.pem.PemReader; 11 | 12 | 13 | import javax.security.auth.x500.X500Principal; 14 | import java.io.*; 15 | import java.lang.reflect.InvocationTargetException; 16 | import java.lang.reflect.Method; 17 | import java.security.cert.Certificate; 18 | import java.security.cert.CertificateException; 19 | import java.security.cert.CertificateFactory; 20 | import java.security.cert.X509Certificate; 21 | import java.util.Hashtable; 22 | 23 | public class X509Utils { 24 | public static Certificate getCertificateFromFile(String certfilename) throws FileNotFoundException, CertificateException { 25 | CertificateFactory certFact = CertificateFactory.getInstance("X.509"); 26 | 27 | InputStream inStream; 28 | 29 | if(VpnProfile.isEmbedded(certfilename)) { 30 | // The java certifcate reader is ... kind of stupid 31 | // It does NOT ignore chars before the --BEGIN ... 32 | int subIndex = certfilename.indexOf("-----BEGIN CERTIFICATE-----"); 33 | subIndex = Math.max(0,subIndex); 34 | inStream = new ByteArrayInputStream(certfilename.substring(subIndex).getBytes()); 35 | 36 | 37 | } else { 38 | inStream = new FileInputStream(certfilename); 39 | } 40 | 41 | 42 | return certFact.generateCertificate(inStream); 43 | } 44 | 45 | public static PemObject readPemObjectFromFile (String keyfilename) throws IOException { 46 | 47 | Reader inStream; 48 | 49 | if(VpnProfile.isEmbedded(keyfilename)) 50 | inStream = new StringReader(VpnProfile.getEmbeddedContent(keyfilename)); 51 | else 52 | inStream = new FileReader(new File(keyfilename)); 53 | 54 | PemReader pr = new PemReader(inStream); 55 | PemObject r = pr.readPemObject(); 56 | pr.close(); 57 | return r; 58 | } 59 | 60 | 61 | 62 | 63 | public static String getCertificateFriendlyName (Context c, String filename) { 64 | if(!TextUtils.isEmpty(filename)) { 65 | try { 66 | X509Certificate cert = (X509Certificate) getCertificateFromFile(filename); 67 | 68 | return getCertificateFriendlyName(cert); 69 | 70 | } catch (Exception e) { 71 | VpnStatus.logError("Could not read certificate" + e.getLocalizedMessage()); 72 | } 73 | } 74 | return c.getString(R.string.cannotparsecert); 75 | } 76 | 77 | public static String getCertificateFriendlyName(X509Certificate cert) { 78 | X500Principal principal = cert.getSubjectX500Principal(); 79 | byte[] encodedSubject = principal.getEncoded(); 80 | String friendlyName=null; 81 | 82 | /* Hack so we do not have to ship a whole Spongy/bouncycastle */ 83 | Exception exp=null; 84 | try { 85 | Class X509NameClass = Class.forName("com.android.org.bouncycastle.asn1.x509.X509Name"); 86 | Method getInstance = X509NameClass.getMethod("getInstance",Object.class); 87 | 88 | Hashtable defaultSymbols = (Hashtable) X509NameClass.getField("DefaultSymbols").get(X509NameClass); 89 | 90 | if (!defaultSymbols.containsKey("1.2.840.113549.1.9.1")) 91 | defaultSymbols.put("1.2.840.113549.1.9.1","eMail"); 92 | 93 | Object subjectName = getInstance.invoke(X509NameClass, encodedSubject); 94 | 95 | Method toString = X509NameClass.getMethod("toString",boolean.class,Hashtable.class); 96 | 97 | friendlyName= (String) toString.invoke(subjectName,true,defaultSymbols); 98 | 99 | } catch (ClassNotFoundException e) { 100 | exp =e ; 101 | } catch (NoSuchMethodException e) { 102 | exp =e; 103 | } catch (InvocationTargetException e) { 104 | exp =e; 105 | } catch (IllegalAccessException e) { 106 | exp =e; 107 | } catch (NoSuchFieldException e) { 108 | exp =e; 109 | } 110 | if (exp!=null) 111 | VpnStatus.logException("Getting X509 Name from certificate", exp); 112 | 113 | /* Fallback if the reflection method did not work */ 114 | if(friendlyName==null) 115 | friendlyName = principal.getName(); 116 | 117 | 118 | // Really evil hack to decode email address 119 | // See: http://code.google.com/p/android/issues/detail?id=21531 120 | 121 | String[] parts = friendlyName.split(","); 122 | for (int i=0;i 0) 39 | { 40 | return loadObject(type); 41 | } 42 | } 43 | 44 | return null; 45 | } 46 | 47 | private PemObject loadObject(String type) 48 | throws IOException 49 | { 50 | String line; 51 | String endMarker = END + type; 52 | StringBuffer buf = new StringBuffer(); 53 | List headers = new ArrayList(); 54 | 55 | while ((line = readLine()) != null) 56 | { 57 | if (line.indexOf(":") >= 0) 58 | { 59 | int index = line.indexOf(':'); 60 | String hdr = line.substring(0, index); 61 | String value = line.substring(index + 1).trim(); 62 | 63 | headers.add(new PemHeader(hdr, value)); 64 | 65 | continue; 66 | } 67 | 68 | if (line.indexOf(endMarker) != -1) 69 | { 70 | break; 71 | } 72 | 73 | buf.append(line.trim()); 74 | } 75 | 76 | if (line == null) 77 | { 78 | throw new IOException(endMarker + " not found"); 79 | } 80 | 81 | return new PemObject(type, headers, Base64.decode(buf.toString())); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /OpenVpnLib/src/org/spongycastle/util/io/pem/PemWriter.java: -------------------------------------------------------------------------------- 1 | package org.spongycastle.util.io.pem; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.IOException; 5 | import java.io.Writer; 6 | import java.util.Iterator; 7 | 8 | import org.spongycastle.util.encoders.Base64; 9 | 10 | /** 11 | * A generic PEM writer, based on RFC 1421 12 | */ 13 | @SuppressWarnings("all") 14 | public class PemWriter 15 | extends BufferedWriter 16 | { 17 | private static final int LINE_LENGTH = 64; 18 | 19 | private final int nlLength; 20 | private char[] buf = new char[LINE_LENGTH]; 21 | 22 | /** 23 | * Base constructor. 24 | * 25 | * @param out output stream to use. 26 | */ 27 | public PemWriter(Writer out) 28 | { 29 | super(out); 30 | 31 | String nl = System.getProperty("line.separator"); 32 | if (nl != null) 33 | { 34 | nlLength = nl.length(); 35 | } 36 | else 37 | { 38 | nlLength = 2; 39 | } 40 | } 41 | 42 | /** 43 | * Return the number of bytes or characters required to contain the 44 | * passed in object if it is PEM encoded. 45 | * 46 | * @param obj pem object to be output 47 | * @return an estimate of the number of bytes 48 | */ 49 | public int getOutputSize(PemObject obj) 50 | { 51 | // BEGIN and END boundaries. 52 | int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4; 53 | 54 | if (!obj.getHeaders().isEmpty()) 55 | { 56 | for (Iterator it = obj.getHeaders().iterator(); it.hasNext();) 57 | { 58 | PemHeader hdr = (PemHeader)it.next(); 59 | 60 | size += hdr.getName().length() + ": ".length() + hdr.getValue().length() + nlLength; 61 | } 62 | 63 | size += nlLength; 64 | } 65 | 66 | // base64 encoding 67 | int dataLen = ((obj.getContent().length + 2) / 3) * 4; 68 | 69 | size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength); 70 | 71 | return size; 72 | } 73 | 74 | public void writeObject(PemObjectGenerator objGen) 75 | throws IOException 76 | { 77 | PemObject obj = objGen.generate(); 78 | 79 | writePreEncapsulationBoundary(obj.getType()); 80 | 81 | if (!obj.getHeaders().isEmpty()) 82 | { 83 | for (Iterator it = obj.getHeaders().iterator(); it.hasNext();) 84 | { 85 | PemHeader hdr = (PemHeader)it.next(); 86 | 87 | this.write(hdr.getName()); 88 | this.write(": "); 89 | this.write(hdr.getValue()); 90 | this.newLine(); 91 | } 92 | 93 | this.newLine(); 94 | } 95 | 96 | writeEncoded(obj.getContent()); 97 | writePostEncapsulationBoundary(obj.getType()); 98 | } 99 | 100 | private void writeEncoded(byte[] bytes) 101 | throws IOException 102 | { 103 | bytes = Base64.encode(bytes); 104 | 105 | for (int i = 0; i < bytes.length; i += buf.length) 106 | { 107 | int index = 0; 108 | 109 | while (index != buf.length) 110 | { 111 | if ((i + index) >= bytes.length) 112 | { 113 | break; 114 | } 115 | buf[index] = (char)bytes[i + index]; 116 | index++; 117 | } 118 | this.write(buf, 0, index); 119 | this.newLine(); 120 | } 121 | } 122 | 123 | private void writePreEncapsulationBoundary( 124 | String type) 125 | throws IOException 126 | { 127 | this.write("-----BEGIN " + type + "-----"); 128 | this.newLine(); 129 | } 130 | 131 | private void writePostEncapsulationBoundary( 132 | String type) 133 | throws IOException 134 | { 135 | this.write("-----END " + type + "-----"); 136 | this.newLine(); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Disconnect Mobile for Android 2 | 3 | To build and connect - download, import into eclipse, and plug in your certificates! 4 | 5 | See strings_non_translate.xml for details. 6 | 7 | ## License 8 | 9 | Copyright 2014 Disconnect, Inc. 10 | 11 | This program is free software, excluding the brand features and third-party 12 | portions of the program identified in the “Exceptions” below: you can 13 | redistribute it and/or modify it under the terms of the GNU General Public 14 | License as published by the Free Software Foundation, either version 3 of the 15 | License, or (at your option) any later version. 16 | 17 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 18 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 19 | PARTICULAR PURPOSE. See the 20 | [GNU General Public License](https://www.gnu.org/licenses/gpl.html) for more 21 | details. 22 | 23 | ## Exceptions 24 | 25 | The Disconnect logos, trademarks, domain names, and other brand features used in 26 | this program cannot be reused without permission and no license is granted 27 | thereto. 28 | 29 | -------------------------------------------------------------------------------- /disconnect/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /disconnect/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | DisconnectMobile 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /disconnect/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /disconnect/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 39 | 40 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /disconnect/ant.properties: -------------------------------------------------------------------------------- 1 | key.store.password=MYPASSWORD 2 | key.alias.password=MYPASSWORD 3 | key.store=MYPATH 4 | key.alias=MYALIAS 5 | -------------------------------------------------------------------------------- /disconnect/assets/fonts/AvenirNextLTPro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/fonts/AvenirNextLTPro-Bold.otf -------------------------------------------------------------------------------- /disconnect/assets/fonts/AvenirNextLTPro-Demi.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/fonts/AvenirNextLTPro-Demi.otf -------------------------------------------------------------------------------- /disconnect/assets/fonts/AvenirNextLTPro-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/fonts/AvenirNextLTPro-Medium.otf -------------------------------------------------------------------------------- /disconnect/assets/fonts/AvenirNextLTPro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/fonts/AvenirNextLTPro-Regular.otf -------------------------------------------------------------------------------- /disconnect/assets/fonts/AvenirNextLTPro-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/fonts/AvenirNextLTPro-Thin.otf -------------------------------------------------------------------------------- /disconnect/assets/minivpn.armeabi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/minivpn.armeabi -------------------------------------------------------------------------------- /disconnect/assets/minivpn.armeabi-v7a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/minivpn.armeabi-v7a -------------------------------------------------------------------------------- /disconnect/assets/minivpn.mips: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/minivpn.mips -------------------------------------------------------------------------------- /disconnect/assets/minivpn.x86: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/assets/minivpn.x86 -------------------------------------------------------------------------------- /disconnect/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /disconnect/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/ic_launcher-web.png -------------------------------------------------------------------------------- /disconnect/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/libs/android-support-v4.jar -------------------------------------------------------------------------------- /disconnect/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /disconnect/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | android.library.reference.1=../engineinterface 16 | android.library.reference.2=../OpenVpnLib 17 | -------------------------------------------------------------------------------- /disconnect/res/color/package_button_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /disconnect/res/drawable-hdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-hdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /disconnect/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable-hdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-hdpi/launcher.png -------------------------------------------------------------------------------- /disconnect/res/drawable-hdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-hdpi/notification_icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable-mdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-mdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/background_collusion_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/background_collusion_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/background_collusion_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/background_collusion_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/background_pack_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/background_pack_repeat.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_ad_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_ad_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_ad_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_ad_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_basic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_basic_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_basic_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_basic_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_circle_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_circle_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_circle_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_circle_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_malware_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_malware_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw600dp-xhdpi/ic_malware_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw600dp-xhdpi/ic_malware_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/background_collusion_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/background_collusion_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/background_collusion_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/background_collusion_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/background_pack_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/background_pack_repeat.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_ad_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_ad_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_ad_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_ad_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_basic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_basic_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_basic_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_basic_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_circle_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_circle_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_circle_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_circle_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_malware_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_malware_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-sw720dp-xhdpi/ic_malware_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-sw720dp-xhdpi/ic_malware_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/background_collusion_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/background_collusion_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/background_collusion_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/background_collusion_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/background_pack_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/background_pack_repeat.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/background_sampling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/background_sampling.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_ad_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_ad_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_ad_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_ad_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_basic_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_basic_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_basic_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_basic_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_circle_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_circle_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_circle_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_circle_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_disconnect.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_malware_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_malware_off.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/ic_malware_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/ic_malware_on.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/launcher.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xhdpi/notification_icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xxhdpi/ic_action_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xxhdpi/ic_action_cancel.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xxhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xxhdpi/launcher.png -------------------------------------------------------------------------------- /disconnect/res/drawable-xxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disconnectme/disconnect-mobile-android/98bed0f21cd1702f53cb9b5acca05b525bb62263/disconnect/res/drawable-xxhdpi/notification_icon.png -------------------------------------------------------------------------------- /disconnect/res/drawable/ad_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /disconnect/res/drawable/basic_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /disconnect/res/drawable/malware_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /disconnect/res/drawable/overlay_button_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /disconnect/res/drawable/packages_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /disconnect/res/drawable/protect_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /disconnect/res/layout/activity_info.xml: -------------------------------------------------------------------------------- 1 | 11 | 20 | 21 | -------------------------------------------------------------------------------- /disconnect/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /disconnect/res/layout/connecting_overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 22 | 31 | 32 |