diff options
| author | 2019-01-22 07:19:18 -0800 | |
|---|---|---|
| committer | 2019-01-22 07:19:18 -0800 | |
| commit | 18d0de7ecc6db0341e406cf4be049c6bb591175c (patch) | |
| tree | eef11e421b38b19596d72a337e5df03bb95c9f27 | |
| parent | 6afb4045c88c0633b0e43354b2499fc49acc8833 (diff) | |
| parent | 43c0ffc1b1f723da1a4d8fc48fb8ee4ce6dcf7f9 (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.txt | 2 | ||||
| -rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/net/VpnService.java | 23 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 40 | ||||
| -rw-r--r-- | services/core/java/com/android/server/connectivity/Vpn.java | 15 | ||||
| -rw-r--r-- | tests/net/java/com/android/server/connectivity/VpnTest.java | 26 |
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); |