diff options
| author | 2018-11-08 19:45:34 -0800 | |
|---|---|---|
| committer | 2019-05-08 00:11:28 +0000 | |
| commit | e265d5f9a58599244272d00d13014b4d451cd4fe (patch) | |
| tree | 5bd6063a3856911a65519f1599bee83e606aa334 | |
| parent | 168f5980f7e3efb8d348b3988fb8b698af61e347 (diff) | |
Add IPsec checks for IPSEC_TUNNEL feature
This patch adds checks to ensure that the IPSEC_TUNNEL feature flag is
enabled.
Bug: 117183273
Test: Compiles & tests passing
Change-Id: I2699dda29e1eed139bc6fd1b70071e5ab33cad88
4 files changed, 49 insertions, 7 deletions
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 1145d5bd4d9a..61fa04aed020 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -19,11 +19,13 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -749,6 +751,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -771,6 +774,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -886,6 +890,7 @@ public final class IpSecManager { */ @SystemApi @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) @@ -916,6 +921,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index e519fdf65e50..36111f2a372d 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -21,9 +21,11 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -483,6 +485,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2055b64483d9..fe22dcda9683 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -30,6 +30,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -1276,7 +1277,7 @@ public class IpSecService extends IIpSecService.Stub { public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); checkNotNull(binder, "Null Binder passed to createTunnelInterface"); checkNotNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); @@ -1362,7 +1363,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void addAddressToTunnelInterface( int tunnelResourceId, LinkAddress localAddr, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1391,7 +1392,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeAddressFromTunnelInterface( int tunnelResourceId, LinkAddress localAddr, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1420,7 +1421,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void deleteTunnelInterface( int resourceId, String callingPackage) throws RemoteException { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); } @@ -1549,7 +1550,12 @@ public class IpSecService extends IIpSecService.Stub { private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; - private void enforceTunnelPermissions(String callingPackage) { + private void enforceTunnelFeatureAndPermissions(String callingPackage) { + if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) { + throw new UnsupportedOperationException( + "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS"); + } + checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { case AppOpsManager.MODE_DEFAULT: @@ -1621,7 +1627,7 @@ public class IpSecService extends IIpSecService.Stub { IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { checkNotNull(c); if (c.getMode() == IpSecTransform.MODE_TUNNEL) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); } checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransform"); @@ -1729,7 +1735,7 @@ public class IpSecService extends IIpSecService.Stub { public synchronized void applyTunnelModeTransform( int tunnelResourceId, int direction, int transformResourceId, String callingPackage) throws RemoteException { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); checkDirection(direction); int callingUid = Binder.getCallingUid(); diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 7c40adfac002..71b72b84de81 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -32,6 +32,7 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.net.INetd; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; @@ -57,6 +58,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import java.net.Inet4Address; import java.net.Socket; import java.util.Arrays; import java.util.Collection; @@ -119,6 +121,11 @@ public class IpSecServiceParameterizedTest { } @Override + public PackageManager getPackageManager() { + return mMockPkgMgr; + } + + @Override public void enforceCallingOrSelfPermission(String permission, String message) { if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) { return; @@ -128,6 +135,7 @@ public class IpSecServiceParameterizedTest { }; INetd mMockNetd; + PackageManager mMockPkgMgr; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; Network fakeNetwork = new Network(0xAB); @@ -152,11 +160,16 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { mMockNetd = mock(INetd.class); + mMockPkgMgr = mock(PackageManager.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); + + // PackageManager should always return true (feature flag tests in IpSecServiceTest) + when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true); + // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage"))) .thenReturn(AppOpsManager.MODE_ALLOWED); @@ -709,4 +722,18 @@ public class IpSecServiceParameterizedTest { } catch (SecurityException expected) { } } + + @Test + public void testFeatureFlagVerification() throws Exception { + when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS))) + .thenReturn(false); + + try { + String addr = Inet4Address.getLoopbackAddress().getHostAddress(); + mIpSecService.createTunnelInterface( + addr, addr, new Network(0), new Binder(), "blessedPackage"); + fail("Expected UnsupportedOperationException for disabled feature"); + } catch (UnsupportedOperationException expected) { + } + } } |