summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pavel Grafov <pgrafov@google.com> 2019-01-22 07:19:18 -0800
committer android-build-merger <android-build-merger@google.com> 2019-01-22 07:19:18 -0800
commit18d0de7ecc6db0341e406cf4be049c6bb591175c (patch)
treeeef11e421b38b19596d72a337e5df03bb95c9f27
parent6afb4045c88c0633b0e43354b2499fc49acc8833 (diff)
parent43c0ffc1b1f723da1a4d8fc48fb8ee4ce6dcf7f9 (diff)
Merge "Add API for VPN apps to query always-on and lockdown." am: 479c0769f1 am: 5fb1be5c0b
am: 43c0ffc1b1 Change-Id: Ied8e5a01cdf76d8da02d2dc292943e6a559cc84e
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/VpnService.java23
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java40
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java15
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java26
6 files changed, 94 insertions, 14 deletions
diff --git a/api/current.txt b/api/current.txt
index 9053a00df53c..482d498651cd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29118,6 +29118,8 @@ package android.net {
public class VpnService extends android.app.Service {
ctor public VpnService();
+ method public final boolean isAlwaysOn();
+ method public final boolean isLockdownEnabled();
method public android.os.IBinder onBind(android.content.Intent);
method public void onRevoke();
method public static android.content.Intent prepare(android.content.Context);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index da5d96e49d02..3d34574440dd 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -187,4 +187,6 @@ interface IConnectivityManager
byte[] getNetworkWatchlistConfigHash();
int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
+ boolean isCallerCurrentAlwaysOnVpnApp();
+ boolean isCallerCurrentAlwaysOnVpnLockdownApp();
}
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index f0c0462cec18..37bf3a71ce62 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -368,6 +368,29 @@ public class VpnService extends Service {
}
/**
+ * Returns whether the service is running in always-on VPN mode.
+ */
+ public final boolean isAlwaysOn() {
+ try {
+ return getService().isCallerCurrentAlwaysOnVpnApp();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the service is running in always-on VPN mode blocking connections without
+ * VPN.
+ */
+ public final boolean isLockdownEnabled() {
+ try {
+ return getService().isCallerCurrentAlwaysOnVpnLockdownApp();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return the communication interface to the service. This method returns
* {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE}
* action. Applications overriding this method must identify the intent
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 00550d9c660e..919a5ab4eecd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -6346,6 +6346,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ @GuardedBy("mVpns")
+ private Vpn getVpnIfOwner() {
+ final int uid = Binder.getCallingUid();
+ final int user = UserHandle.getUserId(uid);
+
+ final Vpn vpn = mVpns.get(user);
+ if (vpn == null) {
+ return null;
+ } else {
+ final VpnInfo info = vpn.getVpnInfo();
+ return (info == null || info.ownerUid != uid) ? null : vpn;
+ }
+ }
+
/**
* Caller either needs to be an active VPN, or hold the NETWORK_STACK permission
* for testing.
@@ -6354,14 +6368,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (checkNetworkStackPermission()) {
return null;
}
- final int uid = Binder.getCallingUid();
- final int user = UserHandle.getUserId(uid);
synchronized (mVpns) {
- Vpn vpn = mVpns.get(user);
- try {
- if (vpn.getVpnInfo().ownerUid == uid) return vpn;
- } catch (NullPointerException e) {
- /* vpn is null, or VPN is not connected and getVpnInfo() is null. */
+ Vpn vpn = getVpnIfOwner();
+ if (vpn != null) {
+ return vpn;
}
}
throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK "
@@ -6390,4 +6400,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
return uid;
}
+
+ @Override
+ public boolean isCallerCurrentAlwaysOnVpnApp() {
+ synchronized (mVpns) {
+ Vpn vpn = getVpnIfOwner();
+ return vpn != null && vpn.getAlwaysOn();
+ }
+ }
+
+ @Override
+ public boolean isCallerCurrentAlwaysOnVpnLockdownApp() {
+ synchronized (mVpns) {
+ Vpn vpn = getVpnIfOwner();
+ return vpn != null && vpn.getLockdown();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 602aedbc2d00..c72c9ddf3f7a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -60,7 +60,6 @@ import android.net.NetworkMisc;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.UidRange;
-import android.net.Uri;
import android.net.VpnService;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
@@ -71,7 +70,6 @@ import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
-import android.os.PatternMatcher;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -100,6 +98,8 @@ import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.net.BaseNetworkObserver;
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -121,8 +121,6 @@ import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
-import libcore.io.IoUtils;
-
/**
* @hide
*/
@@ -346,11 +344,18 @@ public class Vpn {
*
* @return {@code true} if VPN lockdown is enabled.
*/
- public boolean getLockdown() {
+ public synchronized boolean getLockdown() {
return mLockdown;
}
/**
+ * Returns whether VPN is configured as always-on.
+ */
+ public synchronized boolean getAlwaysOn() {
+ return mAlwaysOn;
+ }
+
+ /**
* Checks if a VPN app supports always-on mode.
*
* In order to support the always-on feature, an app has to
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 9bf758797ed2..0b74d878f069 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -57,7 +57,6 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
-import android.net.IConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.Network;
@@ -97,7 +96,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -240,6 +238,30 @@ public class VpnTest {
}
@Test
+ public void testGetAlwaysAndOnGetLockDown() throws Exception {
+ final Vpn vpn = createVpn(primaryUser.id);
+
+ // Default state.
+ assertFalse(vpn.getAlwaysOn());
+ assertFalse(vpn.getLockdown());
+
+ // Set always-on without lockdown.
+ assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false));
+ assertTrue(vpn.getAlwaysOn());
+ assertFalse(vpn.getLockdown());
+
+ // Set always-on with lockdown.
+ assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true));
+ assertTrue(vpn.getAlwaysOn());
+ assertTrue(vpn.getLockdown());
+
+ // Remove always-on configuration.
+ assertTrue(vpn.setAlwaysOnPackage(null, false));
+ assertFalse(vpn.getAlwaysOn());
+ assertFalse(vpn.getLockdown());
+ }
+
+ @Test
public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);