summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2022-05-04 13:21:26 +0200
committerArne Schwabe <arne@rfc2549.org>2022-05-04 19:21:46 +0200
commit6d364856a35661e7dad414d38dc34c8cbd8b5985 (patch)
tree2851d7143c2a1e10a5a8735f5186f8c00a8d1b3f
parent0a649719fa0c37d86078bef6f8a7f6942e6f29ff (diff)
Remove API support for API < 21 and lower (Lollipop)
Supporting just APIs 19 and 20 keeps a lot of code and the number of users is extremely small.
-rw-r--r--main/build.gradle.kts5
-rw-r--r--main/src/main/cpp/CMakeLists.txt2
-rw-r--r--main/src/main/cpp/ovpnutil/jniglue.c5
-rw-r--r--main/src/main/cpp/ovpnutil/scan_ifs.c109
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java10
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java4
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java58
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java48
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java11
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java339
-rw-r--r--main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java14
-rw-r--r--main/src/main/res/xml/app_restrictions.xml4
-rw-r--r--main/src/ui/AndroidManifest.xml4
13 files changed, 36 insertions, 577 deletions
diff --git a/main/build.gradle.kts b/main/build.gradle.kts
index 181cf84c..41a69ed9 100644
--- a/main/build.gradle.kts
+++ b/main/build.gradle.kts
@@ -18,7 +18,7 @@ android {
ndkVersion = "24.0.8215888"
defaultConfig {
- minSdk = 19
+ minSdk = 21
targetSdk = 32
versionCode = 189
versionName = "0.7.34"
@@ -188,8 +188,7 @@ dependencies {
dependencies.add("uiImplementation", "androidx.webkit:webkit:1.4.0")
dependencies.add("uiImplementation", "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1")
dependencies.add("uiImplementation", "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1")
- dependencies.add("uiImplementation", "androidx.multidex:multidex:2.0.1")
-
+
testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21")
testImplementation("junit:junit:4.13.2")
testImplementation("org.mockito:mockito-core:3.9.0")
diff --git a/main/src/main/cpp/CMakeLists.txt b/main/src/main/cpp/CMakeLists.txt
index 72425792..d1f809fb 100644
--- a/main/src/main/cpp/CMakeLists.txt
+++ b/main/src/main/cpp/CMakeLists.txt
@@ -97,7 +97,7 @@ else ()
message("Not budiling OpenVPN for output dir ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
endif ()
-add_library(ovpnutil SHARED ovpnutil/jniglue.c ovpnutil/scan_ifs.c)
+add_library(ovpnutil SHARED ovpnutil/jniglue.c)
target_compile_definitions(ovpnutil PRIVATE -DTARGET_ARCH_ABI=\"${ANDROID_ABI}\"
-DOPENVPN2_GIT_REVISION=\"${OPENVPN2_GIT}\"
-DOPENVPN3_GIT_REVISION=\"${OPENVPN3_GIT}\"
diff --git a/main/src/main/cpp/ovpnutil/jniglue.c b/main/src/main/cpp/ovpnutil/jniglue.c
index 264b18a8..65a13406 100644
--- a/main/src/main/cpp/ovpnutil/jniglue.c
+++ b/main/src/main/cpp/ovpnutil/jniglue.c
@@ -19,11 +19,6 @@ void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,con
__android_log_print(ANDROID_LOG_DEBUG,"openvpn","%s%s%s",prefix,prefix_sep,m1);
}
-void Java_de_blinkt_openvpn_core_NativeUtils_jniclose(JNIEnv *env,jclass jo, jint fd)
-{
- int ret = close(fd);
-}
-
//! Hack to get the current installed ABI of the libraries. See also https://github.com/schwabe/ics-openvpn/issues/391
jstring Java_de_blinkt_openvpn_core_NativeUtils_getJNIAPI(JNIEnv *env, jclass jo)
diff --git a/main/src/main/cpp/ovpnutil/scan_ifs.c b/main/src/main/cpp/ovpnutil/scan_ifs.c
deleted file mode 100644
index 85021d88..00000000
--- a/main/src/main/cpp/ovpnutil/scan_ifs.c
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <jni.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <android/log.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "jniglue.h"
-
-jobjectArray Java_de_blinkt_openvpn_core_NativeUtils_getIfconfig(JNIEnv* env)
-{
- int sd;
- if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "Opening socket for intface get failed");
- //jniThrowException(env, "java/lang/IllegalArgumentException", "Opening socket for intface get failed");
- return NULL;
- }
-
- struct ifreq ifs[23];
-
- struct ifconf ifc;
- ifc.ifc_req = ifs;
- ifc.ifc_len = sizeof (ifs);
-
- if (ioctl (sd, SIOCGIFCONF, &ifc) < 0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IOCTL for intface get failed");
- //jniThrowException(env, "java/lang/IllegalArgumentException", "IOTCL socket for intface get failed");
- close(sd);
- return NULL;
- }
-
-
-
-
- char buf[NI_MAXHOST];
-
- int ji=0;
-
- /*
- jtmp = (*env)->NewStringUTF(env, "HALLO WELT");
- (*env)->SetObjectArrayElement(env, ret, ji++, jtmp);
- */
-
- size_t num_intf=ifc.ifc_len / sizeof(struct ifreq);
- jobjectArray ret= (jobjectArray) (*env)->NewObjectArray(env, num_intf*3,(*env)->FindClass(env, "java/lang/String"), NULL);
-
- for (struct ifreq* ifr = ifc.ifc_req; ifr < ifs + num_intf; ifr++) {
-
- if (ifr->ifr_addr.sa_family != AF_INET) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "NOT AF_INET: %s", ifr->ifr_name);
- continue;
- }
-
- /* get interface addr, prefilled by SIOGIFCONF */
-
- int err;
- if ((err=getnameinfo(&ifr->ifr_addr, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0,
- NI_NUMERICHOST)) !=0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for %s: %s", ifr->ifr_name, gai_strerror(err));
- continue;
- }
- jstring jaddr = (*env)->NewStringUTF(env, buf);
- jstring jname = (*env)->NewStringUTF(env, ifr->ifr_name);
-
-
- struct ifreq ifreq;
- strncpy (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
-
- /* interface is up */
- if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCGIFFLAGS failed for %s: %s", ifr->ifr_name, strerror(errno));
- continue;
- }
-
- if (!(ifreq.ifr_flags & IFF_UP)) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "IFF_UP failed for %s", ifr->ifr_name);
- continue;
- }
-
- /* interface netmask */
- if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "SIOCIFNETMASK failed for %s: %s", ifr->ifr_name, strerror(errno));
- continue;
- }
-
- if ((err=getnameinfo(&ifreq.ifr_netmask, sizeof(struct sockaddr_in), buf, NI_MAXHOST, NULL, 0,
- NI_NUMERICHOST)) !=0) {
- __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "getnameinfo failed for %s: %s", ifr->ifr_name, gai_strerror(err));
- continue;
- }
- jstring jnetmask = (*env)->NewStringUTF(env, buf);
-
- (*env)->SetObjectArrayElement(env, ret, ji++, jname);
- (*env)->SetObjectArrayElement(env, ret, ji++, jaddr);
- (*env)->SetObjectArrayElement(env, ret, ji++, jnetmask);
- }
- if (sd >= 0)
- close (sd);
-
- return ret;
-}
-
diff --git a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
index b8e3d646..1df46525 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/ICSOpenVPNApplication.java
@@ -40,20 +40,12 @@ public class ICSOpenVPNApplication extends Application {
LocaleHelper.setDesiredLocale(this);
super.onCreate();
- PRNGFixes.apply();
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createNotificationChannels();
mStatus = new StatusListener();
mStatus.init(getApplicationContext());
-
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- AppRestrictions.getInstance(this).checkRestrictions(this);
- }
-
-
+ AppRestrictions.getInstance(this).checkRestrictions(this);
}
@Override
diff --git a/main/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java b/main/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java
index 04e4e8b4..7017fc1d 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/LollipopDeviceStateListener.java
@@ -12,10 +12,6 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Build;
-/**
- * Created by arne on 26.11.14.
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class LollipopDeviceStateListener extends ConnectivityManager.NetworkCallback {
private String mLastConnectedStatus;
diff --git a/main/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java b/main/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
index 8710ce7f..00f45ed4 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
@@ -21,56 +21,30 @@ public class NetworkUtils {
public static Vector<String> getLocalNetworks(Context c, boolean ipv6) {
Vector<String> nets = new Vector<>();
ConnectivityManager conn = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- Network[] networks = conn.getAllNetworks();
- for (Network network : networks) {
- NetworkInfo ni = conn.getNetworkInfo(network);
- LinkProperties li = conn.getLinkProperties(network);
- NetworkCapabilities nc = conn.getNetworkCapabilities(network);
+ Network[] networks = conn.getAllNetworks();
+ for (Network network : networks) {
+ NetworkInfo ni = conn.getNetworkInfo(network);
+ LinkProperties li = conn.getLinkProperties(network);
- // Skip VPN networks like ourselves
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN))
- continue;
+ NetworkCapabilities nc = conn.getNetworkCapabilities(network);
- // Also skip mobile networks
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
- continue;
+ // Skip VPN networks like ourselves
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN))
+ continue;
+ // Also skip mobile networks
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ continue;
- for (LinkAddress la : li.getLinkAddresses()) {
- if ((la.getAddress() instanceof Inet4Address && !ipv6) ||
- (la.getAddress() instanceof Inet6Address && ipv6))
- nets.add(la.toString());
- }
- }
- } else {
- // Old Android Version, use native utils via ifconfig instead
- // Add local network interfaces
- if (ipv6)
- return nets;
-
- 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;
- }
- nets.add(ipAddr + "/" + CIDRIP.calculateLenFromMask(netMask));
+ for (LinkAddress la : li.getLinkAddresses()) {
+ if ((la.getAddress() instanceof Inet4Address && !ipv6) ||
+ (la.getAddress() instanceof Inet6Address && ipv6))
+ nets.add(la.toString());
}
-
}
+
return nets;
}
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index f1f2edb7..b8871222 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -278,9 +278,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// Try to set the priority available since API 16 (Jellybean)
jbNotificationExtras(priority, nbuilder);
addVpnActionsToNotification(nbuilder);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- lpNotificationExtras(nbuilder, Notification.CATEGORY_SERVICE);
+ lpNotificationExtras(nbuilder, Notification.CATEGORY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//noinspection NewApi
@@ -324,7 +322,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
});
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void lpNotificationExtras(Notification.Builder nbuilder, String category) {
nbuilder.setCategory(category);
nbuilder.setLocalOnly(true);
@@ -744,7 +741,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
return null;
}
- boolean allowUnsetAF = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !mProfile.mBlockUnusedAddressFamilies;
+ boolean allowUnsetAF = !mProfile.mBlockUnusedAddressFamilies;
if (allowUnsetAF) {
allowAllAFFamilies(builder);
}
@@ -787,19 +784,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
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);
- }
+ builder.setMtu(mMtu);
Collection<IpAddress> positiveIPv4Routes = mRoutes.getPositiveIPList();
Collection<IpAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList();
- if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist.size() >= 1) {
+ if ("samsung".equals(Build.BRAND) && mDnslist.size() >= 1) {
// Check if the first DNS Server is in the VPN range
try {
IpAddress dnsServer = new IpAddress(new CIDRIP(mDnslist.get(0), 32), true);
@@ -877,13 +867,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
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)));
- if (mProxyInfo != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort());
- }
+ VpnStatus.logInfo(R.string.proxy_info, mProxyInfo.getHost(), mProxyInfo.getPort());
VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- setAllowedVpnPackages(builder);
- }
+ setAllowedVpnPackages(builder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
// VPN always uses the default network
builder.setUnderlyingNetworks(null);
@@ -956,7 +942,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void allowAllAFFamilies(Builder builder) {
builder.allowFamily(OsConstants.AF_INET);
builder.allowFamily(OsConstants.AF_INET6);
@@ -985,8 +970,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setAllowedVpnPackages(Builder builder) {
boolean profileUsesOrBot = false;
@@ -1064,9 +1047,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
public boolean addHttpProxy(String proxy, int port) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
- return false;
-
try {
mProxyInfo = ProxyInfo.buildDirectProxy(proxy, port);
} catch (Exception e) {
@@ -1173,8 +1153,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
- /* 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) {
+ /* Workaround for Lollipop and higher, it does not route traffic to the VPNs own network mask */
+ if (mLocalIP.len <= 31) {
CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len);
interfaceRoute.normalise();
addRoute(interfaceRoute, true);
@@ -1268,13 +1248,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
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";
+ return "OPEN_BEFORE_CLOSE";
}
}
@@ -1362,9 +1336,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
nbuilder.setContentIntent(pIntent);
jbNotificationExtras(PRIORITY_MAX, nbuilder);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- lpNotificationExtras(nbuilder, Notification.CATEGORY_STATUS);
+ lpNotificationExtras(nbuilder, Notification.CATEGORY_STATUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//noinspection NewApi
diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
index e32aabe3..11b2608b 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -239,14 +239,8 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
if (!result)
VpnStatus.logWarning("Could not protect VPN socket");
+ fdClose(fd);
- //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);
- //pfd.close();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- fdCloseLollipop(fd);
- } else {
- NativeUtils.jniclose(fdint);
- }
return;
} catch ( NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) {
VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")", e);
@@ -256,8 +250,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
}
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- private void fdCloseLollipop(FileDescriptor fd) {
+ private void fdClose(FileDescriptor fd) {
try {
Os.close(fd);
} catch (Exception e) {
diff --git a/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java b/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java
deleted file mode 100644
index 49a7eaa9..00000000
--- a/main/src/main/java/de/blinkt/openvpn/core/PRNGFixes.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2012-2016 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/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index cbb27c22..c859e845 100644
--- a/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/main/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -5,7 +5,6 @@
package de.blinkt.openvpn.core;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -28,12 +27,8 @@ public class VPNLaunchHelper {
/* Q does not allow executing binaries written in temp directory anymore */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
return new File(context.getApplicationInfo().nativeLibraryDir, "libovpnexec.so").getPath();
- String[] abis;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- abis = getSupportedABIsLollipop();
- else
- //noinspection deprecation
- abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};
+
+ String[] abis = Build.SUPPORTED_ABIS;
if (!nativeAPI.equals(abis[0])) {
VpnStatus.logWarning(R.string.abi_mismatch, Arrays.toString(abis), nativeAPI);
@@ -51,11 +46,6 @@ public class VPNLaunchHelper {
throw new RuntimeException("Cannot find any executable for this device's ABIs " + Arrays.toString(abis));
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private static String[] getSupportedABIsLollipop() {
- return Build.SUPPORTED_ABIS;
- }
-
static String[] buildOpenvpnArgv(Context c) {
Vector<String> args = new Vector<>();
diff --git a/main/src/main/res/xml/app_restrictions.xml b/main/src/main/res/xml/app_restrictions.xml
index bd053388..813e9bd3 100644
--- a/main/src/main/res/xml/app_restrictions.xml
+++ b/main/src/main/res/xml/app_restrictions.xml
@@ -4,9 +4,7 @@
~ Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
-->
-<restrictions xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"
- tools:targetApi="lollipop">
-
+<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
<restriction
android:key="version"
diff --git a/main/src/ui/AndroidManifest.xml b/main/src/ui/AndroidManifest.xml
index 0caccd5d..b3bd8ecf 100644
--- a/main/src/ui/AndroidManifest.xml
+++ b/main/src/ui/AndroidManifest.xml
@@ -14,9 +14,7 @@
android:name="android.hardware.touchscreen"
android:required="false" />
- <application
- android:banner="@mipmap/banner_tv"
- tools:targetApi="lollipop">
+ <application android:banner="@mipmap/banner_tv">
<activity
android:exported="true"
android:name=".activities.MainActivity"