Extract IPsec and test network utility methods
This patch moves some test setup functions to util classes in
preparation for IKEv2 VPN tests which will use those same utilities.
Bug: 148582947
Test: atest IpSecManagerTunnelTest; passing
Change-Id: I9aeafa45ab515ce72a72c3de6f70fb26e32e7fd4
Merged-In: I9aeafa45ab515ce72a72c3de6f70fb26e32e7fd4
(cherry picked from commit 30432fa7640603c1e746b7d8c83e2e6052d8f967)
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
index 1d83dda..ae38faa 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -18,20 +18,17 @@
import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
import static android.net.IpSecManager.UdpEncapsulationSocket;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
-import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
import static android.net.cts.PacketUtils.BytePayload;
import static android.net.cts.PacketUtils.EspHeader;
import static android.net.cts.PacketUtils.IP4_HDRLEN;
import static android.net.cts.PacketUtils.IP6_HDRLEN;
-import static android.net.cts.PacketUtils.Ip4Header;
-import static android.net.cts.PacketUtils.Ip6Header;
import static android.net.cts.PacketUtils.IpHeader;
import static android.net.cts.PacketUtils.UDP_HDRLEN;
import static android.net.cts.PacketUtils.UdpHeader;
+import static android.net.cts.PacketUtils.getIpHeader;
+import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
@@ -40,38 +37,28 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
-import android.app.AppOpsManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.net.LinkAddress;
import android.net.Network;
-import android.net.NetworkRequest;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.cts.PacketUtils.Payload;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
+import android.net.cts.util.CtsNetUtils;
import android.os.ParcelFileDescriptor;
-import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.SystemUtil;
-
-import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;
import org.junit.Before;
@@ -114,7 +101,7 @@
private static TunUtils sTunUtils;
private static Context sContext = InstrumentationRegistry.getContext();
- private static IBinder sBinder = new Binder();
+ private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext);
@BeforeClass
public static void setUpBeforeClass() throws Exception {
@@ -127,7 +114,7 @@
// Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted, and
// a standard permission is insufficient. So we shell out the appop, to give us the
// right appop permissions.
- setAppop(OP_MANAGE_IPSEC_TUNNELS, true);
+ mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true);
TestNetworkInterface testIface =
sTNM.createTunInterface(
@@ -137,8 +124,9 @@
});
sTunFd = testIface.getFileDescriptor();
- sTunNetworkCallback = setupAndGetTestNetwork(testIface.getInterfaceName());
- sTunNetwork = sTunNetworkCallback.getNetworkBlocking();
+ sTunNetworkCallback = mCtsNetUtils.setupAndGetTestNetwork(testIface.getInterfaceName());
+ sTunNetworkCallback.waitForAvailable();
+ sTunNetwork = sTunNetworkCallback.currentNetwork;
sTunUtils = new TunUtils(sTunFd);
}
@@ -149,7 +137,7 @@
super.setUp();
// Set to true before every run; some tests flip this.
- setAppop(OP_MANAGE_IPSEC_TUNNELS, true);
+ mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true);
// Clear sTunUtils state
sTunUtils.reset();
@@ -157,7 +145,7 @@
@AfterClass
public static void tearDownAfterClass() throws Exception {
- setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
+ mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false);
sCM.unregisterNetworkCallback(sTunNetworkCallback);
@@ -169,50 +157,12 @@
.dropShellPermissionIdentity();
}
- private static boolean hasTunnelsFeature() {
- return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- || SystemProperties.getInt("ro.product.first_api_level", 0)
- >= Build.VERSION_CODES.Q;
- }
-
- private static void setAppop(int appop, boolean allow) {
- String opName = AppOpsManager.opToName(appop);
- for (String pkg : new String[] {"com.android.shell", sContext.getPackageName()}) {
- String cmd =
- String.format(
- "appops set %s %s %s",
- pkg, // Package name
- opName, // Appop
- (allow ? "allow" : "deny")); // Action
- SystemUtil.runShellCommand(cmd);
- }
- }
-
- private static TestNetworkCallback setupAndGetTestNetwork(String ifname) throws Exception {
- // Build a network request
- NetworkRequest nr =
- new NetworkRequest.Builder()
- .clearCapabilities()
- .addTransportType(TRANSPORT_TEST)
- .setNetworkSpecifier(ifname)
- .build();
-
- TestNetworkCallback cb = new TestNetworkCallback();
- sCM.requestNetwork(nr, cb);
-
- // Setup the test network after network request is filed to prevent Network from being
- // reaped due to no requests matching it.
- sTNM.setupTestNetwork(ifname, sBinder);
-
- return cb;
- }
-
@Test
public void testSecurityExceptionCreateTunnelInterfaceWithoutAppop() throws Exception {
- if (!hasTunnelsFeature()) return;
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
// Ensure we don't have the appop. Permission is not requested in the Manifest
- setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
+ mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false);
// Security exceptions are thrown regardless of IPv4/IPv6. Just test one
try {
@@ -224,10 +174,10 @@
@Test
public void testSecurityExceptionBuildTunnelTransformWithoutAppop() throws Exception {
- if (!hasTunnelsFeature()) return;
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
// Ensure we don't have the appop. Permission is not requested in the Manifest
- setAppop(OP_MANAGE_IPSEC_TUNNELS, false);
+ mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false);
// Security exceptions are thrown regardless of IPv4/IPv6. Just test one
try (IpSecManager.SecurityParameterIndex spi =
@@ -253,19 +203,6 @@
public abstract int run(Network ipsecNetwork) throws Exception;
}
- private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
- private final CompletableFuture<Network> futureNetwork = new CompletableFuture<>();
-
- @Override
- public void onAvailable(Network network) {
- futureNetwork.complete(network);
- }
-
- public Network getNetworkBlocking() throws Exception {
- return futureNetwork.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
- }
-
private int getPacketSize(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) {
int expectedPacketSize = TEST_DATA.length + UDP_HDRLEN;
@@ -499,8 +436,6 @@
public void checkTunnelReflected(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
- if (!hasTunnelsFeature()) return;
-
InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6;
InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6;
@@ -580,7 +515,6 @@
boolean transportInTunnelMode,
IpSecTunnelTestRunnableFactory factory)
throws Exception {
- if (!hasTunnelsFeature()) return;
InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6;
InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6;
@@ -648,8 +582,9 @@
mISM.createIpSecTunnelInterface(localOuter, remoteOuter, sTunNetwork)) {
// Build the test network
tunnelIface.addAddress(localInner, innerPrefixLen);
- testNetworkCb = setupAndGetTestNetwork(tunnelIface.getInterfaceName());
- Network testNetwork = testNetworkCb.getNetworkBlocking();
+ testNetworkCb = mCtsNetUtils.setupAndGetTestNetwork(tunnelIface.getInterfaceName());
+ testNetworkCb.waitForAvailable();
+ Network testNetwork = testNetworkCb.currentNetwork;
// Check interface was created
assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName()));
@@ -718,18 +653,6 @@
}
}
- private IpHeader getIpHeader(int protocol, InetAddress src, InetAddress dst, Payload payload) {
- if ((src instanceof Inet6Address) != (dst instanceof Inet6Address)) {
- throw new IllegalArgumentException("Invalid src/dst address combination");
- }
-
- if (src instanceof Inet6Address) {
- return new Ip6Header(protocol, (Inet6Address) src, (Inet6Address) dst, payload);
- } else {
- return new Ip4Header(protocol, (Inet4Address) src, (Inet4Address) dst, payload);
- }
- }
-
private EspHeader buildTransportModeEspPacket(
int spi, InetAddress src, InetAddress dst, int port, Payload payload) throws Exception {
IpHeader preEspIpHeader = getIpHeader(payload.getProtocolId(), src, dst, payload);
@@ -819,134 +742,158 @@
// Transport-in-Tunnel mode tests
@Test
public void testTransportInTunnelModeV4InV4() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET, false, true);
checkTunnelInput(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV4InV4UdpEncap() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET, true, true);
checkTunnelInput(AF_INET, AF_INET, true, true);
}
@Test
public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV4InV6() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET6, false, true);
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
@Test
public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV6InV4() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET6, AF_INET, false, true);
checkTunnelInput(AF_INET6, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV6InV4UdpEncap() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET6, AF_INET, true, true);
checkTunnelInput(AF_INET6, AF_INET, true, true);
}
@Test
public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
@Test
public void testTransportInTunnelModeV6InV6() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET6, false, true);
checkTunnelInput(AF_INET, AF_INET6, false, true);
}
@Test
public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, true);
}
// Tunnel mode tests
@Test
public void testTunnelV4InV4() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET, false, false);
checkTunnelInput(AF_INET, AF_INET, false, false);
}
@Test
public void testTunnelV4InV4Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, false, false);
}
@Test
public void testTunnelV4InV4UdpEncap() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET, true, false);
checkTunnelInput(AF_INET, AF_INET, true, false);
}
@Test
public void testTunnelV4InV4UdpEncapReflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET, true, false);
}
@Test
public void testTunnelV4InV6() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET, AF_INET6, false, false);
checkTunnelInput(AF_INET, AF_INET6, false, false);
}
@Test
public void testTunnelV4InV6Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET, AF_INET6, false, false);
}
@Test
public void testTunnelV6InV4() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET6, AF_INET, false, false);
checkTunnelInput(AF_INET6, AF_INET, false, false);
}
@Test
public void testTunnelV6InV4Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET6, AF_INET, false, false);
}
@Test
public void testTunnelV6InV4UdpEncap() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET6, AF_INET, true, false);
checkTunnelInput(AF_INET6, AF_INET, true, false);
}
@Test
public void testTunnelV6InV4UdpEncapReflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET6, AF_INET, true, false);
}
@Test
public void testTunnelV6InV6() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelOutput(AF_INET6, AF_INET6, false, false);
checkTunnelInput(AF_INET6, AF_INET6, false, false);
}
@Test
public void testTunnelV6InV6Reflected() throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET6, AF_INET6, false, false);
}
}
diff --git a/tests/tests/net/src/android/net/cts/PacketUtils.java b/tests/tests/net/src/android/net/cts/PacketUtils.java
index 6177827..0aedecb 100644
--- a/tests/tests/net/src/android/net/cts/PacketUtils.java
+++ b/tests/tests/net/src/android/net/cts/PacketUtils.java
@@ -27,6 +27,7 @@
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Arrays;
+
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
@@ -443,6 +444,19 @@
return Arrays.copyOfRange(buffer.array(), 0, buffer.position());
}
+ public static IpHeader getIpHeader(
+ int protocol, InetAddress src, InetAddress dst, Payload payload) {
+ if ((src instanceof Inet6Address) != (dst instanceof Inet6Address)) {
+ throw new IllegalArgumentException("Invalid src/dst address combination");
+ }
+
+ if (src instanceof Inet6Address) {
+ return new Ip6Header(protocol, (Inet6Address) src, (Inet6Address) dst, payload);
+ } else {
+ return new Ip4Header(protocol, (Inet4Address) src, (Inet4Address) dst, payload);
+ }
+ }
+
/*
* Debug printing
*/
diff --git a/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
index f39b184..32cdf92 100644
--- a/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/tests/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -20,6 +20,7 @@
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -27,11 +28,13 @@
import static org.junit.Assert.fail;
import android.annotation.NonNull;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.LinkProperties;
@@ -40,7 +43,12 @@
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.NetworkRequest;
+import android.net.TestNetworkManager;
import android.net.wifi.WifiManager;
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.SystemProperties;
import android.provider.Settings;
import android.system.Os;
import android.system.OsConstants;
@@ -73,6 +81,7 @@
public static final String NETWORK_CALLBACK_ACTION =
"ConnectivityManagerTest.NetworkCallbackAction";
+ private final IBinder mBinder = new Binder();
private final Context mContext;
private final ConnectivityManager mCm;
private final ContentResolver mCR;
@@ -88,6 +97,51 @@
mCR = context.getContentResolver();
}
+ /** Checks if FEATURE_IPSEC_TUNNELS is enabled on the device */
+ public boolean hasIpsecTunnelsFeature() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+ || SystemProperties.getInt("ro.product.first_api_level", 0)
+ >= Build.VERSION_CODES.Q;
+ }
+
+ /**
+ * Sets the given appop using shell commands
+ *
+ * <p>Expects caller to hold the shell permission identity.
+ */
+ public void setAppopPrivileged(int appop, boolean allow) {
+ final String opName = AppOpsManager.opToName(appop);
+ for (final String pkg : new String[] {"com.android.shell", mContext.getPackageName()}) {
+ final String cmd =
+ String.format(
+ "appops set %s %s %s",
+ pkg, // Package name
+ opName, // Appop
+ (allow ? "allow" : "deny")); // Action
+ SystemUtil.runShellCommand(cmd);
+ }
+ }
+
+ /** Sets up a test network using the provided interface name */
+ public TestNetworkCallback setupAndGetTestNetwork(String ifname) throws Exception {
+ // Build a network request
+ final NetworkRequest nr =
+ new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(TRANSPORT_TEST)
+ .setNetworkSpecifier(ifname)
+ .build();
+
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(nr, cb);
+
+ // Setup the test network after network request is filed to prevent Network from being
+ // reaped due to no requests matching it.
+ mContext.getSystemService(TestNetworkManager.class).setupTestNetwork(ifname, mBinder);
+
+ return cb;
+ }
+
// Toggle WiFi twice, leaving it in the state it started in
public void toggleWifi() {
if (mWifiManager.isWifiEnabled()) {