Merge changes Ifc8ad902,I6d1b8d0e
* changes: [API] Expose IpSecTunnelInterface#setUnderlyingNetwork Update underlying network of IpSecTunnelInterface
This commit is contained in:
@@ -6150,6 +6150,7 @@ package android.net {
|
|||||||
method public void close();
|
method public void close();
|
||||||
method @NonNull public String getInterfaceName();
|
method @NonNull public String getInterfaceName();
|
||||||
method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
|
method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
|
||||||
|
method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void setUnderlyingNetwork(@NonNull android.net.Network) throws java.io.IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IpSecTransform.Builder {
|
public static class IpSecTransform.Builder {
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ interface IIpSecService
|
|||||||
in LinkAddress localAddr,
|
in LinkAddress localAddr,
|
||||||
in String callingPackage);
|
in String callingPackage);
|
||||||
|
|
||||||
|
void setNetworkForTunnelInterface(
|
||||||
|
int tunnelResourceId, in Network underlyingNetwork, in String callingPackage);
|
||||||
|
|
||||||
void deleteTunnelInterface(int resourceId, in String callingPackage);
|
void deleteTunnelInterface(int resourceId, in String callingPackage);
|
||||||
|
|
||||||
IpSecTransformResponse createTransform(
|
IpSecTransformResponse createTransform(
|
||||||
|
|||||||
@@ -782,6 +782,42 @@ public final class IpSecManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the underlying network for this IpSecTunnelInterface.
|
||||||
|
*
|
||||||
|
* <p>This new underlying network will be used for all transforms applied AFTER this call is
|
||||||
|
* complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to
|
||||||
|
* this tunnel interface, traffic will still use the old SA, and be routed on the old
|
||||||
|
* underlying network.
|
||||||
|
*
|
||||||
|
* <p>To migrate IPsec tunnel mode traffic, a caller should:
|
||||||
|
*
|
||||||
|
* <ol>
|
||||||
|
* <li>Update the IpSecTunnelInterface’s underlying network.
|
||||||
|
* <li>Apply {@link IpSecTransform}(s) with matching addresses to this
|
||||||
|
* IpSecTunnelInterface.
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
|
||||||
|
* This network MUST never be the network exposing this IpSecTunnelInterface, otherwise
|
||||||
|
* this method will throw an {@link IllegalArgumentException}.
|
||||||
|
*/
|
||||||
|
// TODO: b/169171001 Update the documentation when transform migration is supported.
|
||||||
|
// The purpose of making updating network and applying transforms separate is to leave open
|
||||||
|
// the possibility to support lossless migration procedures. To do that, Android platform
|
||||||
|
// will need to support multiple inbound tunnel mode transforms, just like it can support
|
||||||
|
// multiple transport mode transforms.
|
||||||
|
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
|
||||||
|
public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException {
|
||||||
|
try {
|
||||||
|
mService.setNetworkForTunnelInterface(
|
||||||
|
mResourceId, underlyingNetwork, mOpPackageName);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service,
|
private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service,
|
||||||
@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
|
@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
|
||||||
@NonNull Network underlyingNetwork)
|
@NonNull Network underlyingNetwork)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.annotation.NonNull;
|
|||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
import android.net.IIpSecService;
|
import android.net.IIpSecService;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
@@ -41,6 +42,7 @@ import android.net.IpSecTransformResponse;
|
|||||||
import android.net.IpSecTunnelInterfaceResponse;
|
import android.net.IpSecTunnelInterfaceResponse;
|
||||||
import android.net.IpSecUdpEncapResponse;
|
import android.net.IpSecUdpEncapResponse;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.TrafficStats;
|
import android.net.TrafficStats;
|
||||||
import android.net.util.NetdService;
|
import android.net.util.NetdService;
|
||||||
@@ -797,9 +799,15 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class TunnelInterfaceRecord extends OwnedResourceRecord {
|
/**
|
||||||
|
* Tracks an tunnel interface, and manages cleanup paths.
|
||||||
|
*
|
||||||
|
* <p>This class is not thread-safe, and expects that that users of this class will ensure
|
||||||
|
* synchronization and thread safety by holding the IpSecService.this instance lock
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
final class TunnelInterfaceRecord extends OwnedResourceRecord {
|
||||||
private final String mInterfaceName;
|
private final String mInterfaceName;
|
||||||
private final Network mUnderlyingNetwork;
|
|
||||||
|
|
||||||
// outer addresses
|
// outer addresses
|
||||||
private final String mLocalAddress;
|
private final String mLocalAddress;
|
||||||
@@ -810,6 +818,8 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
|
|
||||||
private final int mIfId;
|
private final int mIfId;
|
||||||
|
|
||||||
|
private Network mUnderlyingNetwork;
|
||||||
|
|
||||||
TunnelInterfaceRecord(
|
TunnelInterfaceRecord(
|
||||||
int resourceId,
|
int resourceId,
|
||||||
String interfaceName,
|
String interfaceName,
|
||||||
@@ -870,14 +880,22 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
releaseNetId(mOkey);
|
releaseNetId(mOkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInterfaceName() {
|
@GuardedBy("IpSecService.this")
|
||||||
return mInterfaceName;
|
public void setUnderlyingNetwork(Network underlyingNetwork) {
|
||||||
|
// When #applyTunnelModeTransform is called, this new underlying network will be used to
|
||||||
|
// update the output mark of the input transform.
|
||||||
|
mUnderlyingNetwork = underlyingNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("IpSecService.this")
|
||||||
public Network getUnderlyingNetwork() {
|
public Network getUnderlyingNetwork() {
|
||||||
return mUnderlyingNetwork;
|
return mUnderlyingNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getInterfaceName() {
|
||||||
|
return mInterfaceName;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the local, outer address for the tunnelInterface */
|
/** Returns the local, outer address for the tunnelInterface */
|
||||||
public String getLocalAddress() {
|
public String getLocalAddress() {
|
||||||
return mLocalAddress;
|
return mLocalAddress;
|
||||||
@@ -1429,6 +1447,34 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set TunnelInterface to use a specific underlying network. */
|
||||||
|
@Override
|
||||||
|
public synchronized void setNetworkForTunnelInterface(
|
||||||
|
int tunnelResourceId, Network underlyingNetwork, String callingPackage) {
|
||||||
|
enforceTunnelFeatureAndPermissions(callingPackage);
|
||||||
|
Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
|
||||||
|
|
||||||
|
final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||||
|
|
||||||
|
// Get tunnelInterface record; if no such interface is found, will throw
|
||||||
|
// IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null
|
||||||
|
final TunnelInterfaceRecord tunnelInterfaceInfo =
|
||||||
|
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
|
||||||
|
|
||||||
|
final ConnectivityManager connectivityManager =
|
||||||
|
mContext.getSystemService(ConnectivityManager.class);
|
||||||
|
final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork);
|
||||||
|
if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Underlying network cannot be the network being exposed by this tunnel");
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is meaningless to check if the network exists or is valid because the network might
|
||||||
|
// disconnect at any time after it passes the check.
|
||||||
|
|
||||||
|
tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a TunnelInterface that has been been allocated by and registered with the system
|
* Delete a TunnelInterface that has been been allocated by and registered with the system
|
||||||
* server
|
* server
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpSecAlgorithm;
|
import android.net.IpSecAlgorithm;
|
||||||
@@ -44,6 +45,7 @@ import android.net.IpSecTransformResponse;
|
|||||||
import android.net.IpSecTunnelInterfaceResponse;
|
import android.net.IpSecTunnelInterfaceResponse;
|
||||||
import android.net.IpSecUdpEncapResponse;
|
import android.net.IpSecUdpEncapResponse;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
@@ -53,6 +55,8 @@ import android.test.mock.MockContext;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.server.IpSecService.TunnelInterfaceRecord;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -109,6 +113,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AppOpsManager mMockAppOps = mock(AppOpsManager.class);
|
AppOpsManager mMockAppOps = mock(AppOpsManager.class);
|
||||||
|
ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class);
|
||||||
|
|
||||||
MockContext mMockContext = new MockContext() {
|
MockContext mMockContext = new MockContext() {
|
||||||
@Override
|
@Override
|
||||||
@@ -116,11 +121,21 @@ public class IpSecServiceParameterizedTest {
|
|||||||
switch(name) {
|
switch(name) {
|
||||||
case Context.APP_OPS_SERVICE:
|
case Context.APP_OPS_SERVICE:
|
||||||
return mMockAppOps;
|
return mMockAppOps;
|
||||||
|
case Context.CONNECTIVITY_SERVICE:
|
||||||
|
return mMockConnectivityMgr;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSystemServiceName(Class<?> serviceClass) {
|
||||||
|
if (ConnectivityManager.class == serviceClass) {
|
||||||
|
return Context.CONNECTIVITY_SERVICE;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PackageManager getPackageManager() {
|
public PackageManager getPackageManager() {
|
||||||
return mMockPkgMgr;
|
return mMockPkgMgr;
|
||||||
@@ -151,6 +166,10 @@ public class IpSecServiceParameterizedTest {
|
|||||||
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
|
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
|
||||||
private static final int REMOTE_ENCAP_PORT = 4500;
|
private static final int REMOTE_ENCAP_PORT = 4500;
|
||||||
|
|
||||||
|
private static final String BLESSED_PACKAGE = "blessedPackage";
|
||||||
|
private static final String SYSTEM_PACKAGE = "systemPackage";
|
||||||
|
private static final String BAD_PACKAGE = "badPackage";
|
||||||
|
|
||||||
public IpSecServiceParameterizedTest(
|
public IpSecServiceParameterizedTest(
|
||||||
String sourceAddr, String destAddr, String localInnerAddr, int family) {
|
String sourceAddr, String destAddr, String localInnerAddr, int family) {
|
||||||
mSourceAddr = sourceAddr;
|
mSourceAddr = sourceAddr;
|
||||||
@@ -174,14 +193,14 @@ public class IpSecServiceParameterizedTest {
|
|||||||
when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true);
|
when(mMockPkgMgr.hasSystemFeature(anyString())).thenReturn(true);
|
||||||
|
|
||||||
// A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
|
// A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED.
|
||||||
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage")))
|
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BLESSED_PACKAGE)))
|
||||||
.thenReturn(AppOpsManager.MODE_ALLOWED);
|
.thenReturn(AppOpsManager.MODE_ALLOWED);
|
||||||
// A system package will not be granted the app op, so this should fall back to
|
// A system package will not be granted the app op, so this should fall back to
|
||||||
// a permissions check, which should pass.
|
// a permissions check, which should pass.
|
||||||
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage")))
|
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(SYSTEM_PACKAGE)))
|
||||||
.thenReturn(AppOpsManager.MODE_DEFAULT);
|
.thenReturn(AppOpsManager.MODE_DEFAULT);
|
||||||
// A mismatch between the package name and the UID will return MODE_IGNORED.
|
// A mismatch between the package name and the UID will return MODE_IGNORED.
|
||||||
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage")))
|
when(mMockAppOps.noteOp(anyInt(), anyInt(), eq(BAD_PACKAGE)))
|
||||||
.thenReturn(AppOpsManager.MODE_IGNORED);
|
.thenReturn(AppOpsManager.MODE_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +357,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
||||||
|
|
||||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
||||||
@@ -352,7 +371,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
|
ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
||||||
|
|
||||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
||||||
@@ -370,14 +389,14 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
if (mFamily == AF_INET) {
|
if (mFamily == AF_INET) {
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
||||||
|
|
||||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
|
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
|
fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
|
||||||
} catch (IllegalArgumentException expected) {
|
} catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
@@ -396,14 +415,14 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
if (mFamily == AF_INET) {
|
if (mFamily == AF_INET) {
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
||||||
|
|
||||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
|
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
|
fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
|
||||||
} catch (IllegalArgumentException expected) {
|
} catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
@@ -417,12 +436,12 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
|
||||||
|
|
||||||
// Attempting to create transform a second time with the same SPIs should throw an error...
|
// Attempting to create transform a second time with the same SPIs should throw an error...
|
||||||
try {
|
try {
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
fail("IpSecService should have thrown an error for reuse of SPI");
|
fail("IpSecService should have thrown an error for reuse of SPI");
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
}
|
}
|
||||||
@@ -430,7 +449,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
// ... even if the transform is deleted
|
// ... even if the transform is deleted
|
||||||
mIpSecService.deleteTransform(createTransformResp.resourceId);
|
mIpSecService.deleteTransform(createTransformResp.resourceId);
|
||||||
try {
|
try {
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
fail("IpSecService should have thrown an error for reuse of SPI");
|
fail("IpSecService should have thrown an error for reuse of SPI");
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
}
|
}
|
||||||
@@ -443,7 +462,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
|
assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
|
||||||
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
||||||
@@ -467,7 +486,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
mIpSecService.deleteTransform(createTransformResp.resourceId);
|
mIpSecService.deleteTransform(createTransformResp.resourceId);
|
||||||
|
|
||||||
verify(mMockNetd, times(1))
|
verify(mMockNetd, times(1))
|
||||||
@@ -515,7 +534,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
|
|
||||||
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
IpSecService.RefcountedResource refcountedRecord =
|
IpSecService.RefcountedResource refcountedRecord =
|
||||||
@@ -562,7 +581,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
|
|
||||||
if (closeSpiBeforeApply) {
|
if (closeSpiBeforeApply) {
|
||||||
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
||||||
@@ -592,7 +611,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
|
|
||||||
// Close SPI record
|
// Close SPI record
|
||||||
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
||||||
@@ -638,7 +657,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateTunnelInterface() throws Exception {
|
public void testCreateTunnelInterface() throws Exception {
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
|
||||||
// Check that we have stored the tracking object, and retrieve it
|
// Check that we have stored the tracking object, and retrieve it
|
||||||
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
@@ -661,11 +680,11 @@ public class IpSecServiceParameterizedTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeleteTunnelInterface() throws Exception {
|
public void testDeleteTunnelInterface() throws Exception {
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
|
||||||
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
|
|
||||||
mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage");
|
mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, BLESSED_PACKAGE);
|
||||||
|
|
||||||
// Verify quota and RefcountedResource objects cleaned up
|
// Verify quota and RefcountedResource objects cleaned up
|
||||||
assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
|
assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
|
||||||
@@ -678,10 +697,73 @@ public class IpSecServiceParameterizedTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Network createFakeUnderlyingNetwork(String interfaceName) {
|
||||||
|
final Network fakeNetwork = new Network(1000);
|
||||||
|
final LinkProperties fakeLp = new LinkProperties();
|
||||||
|
fakeLp.setInterfaceName(interfaceName);
|
||||||
|
when(mMockConnectivityMgr.getLinkProperties(eq(fakeNetwork))).thenReturn(fakeLp);
|
||||||
|
return fakeNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetNetworkForTunnelInterface() throws Exception {
|
||||||
|
final IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
final Network newFakeNetwork = createFakeUnderlyingNetwork("newFakeNetworkInterface");
|
||||||
|
final int tunnelIfaceResourceId = createTunnelResp.resourceId;
|
||||||
|
mIpSecService.setNetworkForTunnelInterface(
|
||||||
|
tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE);
|
||||||
|
|
||||||
|
final IpSecService.UserRecord userRecord =
|
||||||
|
mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
|
assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
|
||||||
|
|
||||||
|
final TunnelInterfaceRecord tunnelInterfaceInfo =
|
||||||
|
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId);
|
||||||
|
assertEquals(newFakeNetwork, tunnelInterfaceInfo.getUnderlyingNetwork());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception {
|
||||||
|
final IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
final Network newFakeNetwork = new Network(1000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
mIpSecService.setNetworkForTunnelInterface(
|
||||||
|
IpSecManager.INVALID_RESOURCE_ID, newFakeNetwork, BLESSED_PACKAGE);
|
||||||
|
fail("Expected an IllegalArgumentException for invalid resource ID.");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetNetworkForTunnelInterfaceFailsWhenSettingTunnelNetwork() throws Exception {
|
||||||
|
final IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
final int tunnelIfaceResourceId = createTunnelResp.resourceId;
|
||||||
|
final IpSecService.UserRecord userRecord =
|
||||||
|
mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
|
final TunnelInterfaceRecord tunnelInterfaceInfo =
|
||||||
|
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelIfaceResourceId);
|
||||||
|
|
||||||
|
final Network newFakeNetwork =
|
||||||
|
createFakeUnderlyingNetwork(tunnelInterfaceInfo.getInterfaceName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
mIpSecService.setNetworkForTunnelInterface(
|
||||||
|
tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE);
|
||||||
|
fail(
|
||||||
|
"Expected an IllegalArgumentException because the underlying network is the"
|
||||||
|
+ " network being exposed by this tunnel.");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTunnelInterfaceBinderDeath() throws Exception {
|
public void testTunnelInterfaceBinderDeath() throws Exception {
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
|
||||||
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid);
|
||||||
IpSecService.RefcountedResource refcountedRecord =
|
IpSecService.RefcountedResource refcountedRecord =
|
||||||
@@ -718,9 +800,9 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
|
||||||
if (closeSpiBeforeApply) {
|
if (closeSpiBeforeApply) {
|
||||||
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
||||||
@@ -728,8 +810,8 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
int transformResourceId = createTransformResp.resourceId;
|
int transformResourceId = createTransformResp.resourceId;
|
||||||
int tunnelResourceId = createTunnelResp.resourceId;
|
int tunnelResourceId = createTunnelResp.resourceId;
|
||||||
mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
|
mIpSecService.applyTunnelModeTransform(
|
||||||
transformResourceId, "blessedPackage");
|
tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE);
|
||||||
|
|
||||||
for (int selAddrFamily : ADDRESS_FAMILIES) {
|
for (int selAddrFamily : ADDRESS_FAMILIES) {
|
||||||
verify(mMockNetd)
|
verify(mMockNetd)
|
||||||
@@ -758,17 +840,17 @@ public class IpSecServiceParameterizedTest {
|
|||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
|
|
||||||
IpSecTransformResponse createTransformResp =
|
IpSecTransformResponse createTransformResp =
|
||||||
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
|
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
|
||||||
|
|
||||||
// Close SPI record
|
// Close SPI record
|
||||||
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
|
||||||
|
|
||||||
int transformResourceId = createTransformResp.resourceId;
|
int transformResourceId = createTransformResp.resourceId;
|
||||||
int tunnelResourceId = createTunnelResp.resourceId;
|
int tunnelResourceId = createTunnelResp.resourceId;
|
||||||
mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
|
mIpSecService.applyTunnelModeTransform(
|
||||||
transformResourceId, "blessedPackage");
|
tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, BLESSED_PACKAGE);
|
||||||
|
|
||||||
for (int selAddrFamily : ADDRESS_FAMILIES) {
|
for (int selAddrFamily : ADDRESS_FAMILIES) {
|
||||||
verify(mMockNetd)
|
verify(mMockNetd)
|
||||||
@@ -790,7 +872,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddRemoveAddressFromTunnelInterface() throws Exception {
|
public void testAddRemoveAddressFromTunnelInterface() throws Exception {
|
||||||
for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) {
|
for (String pkgName : new String[] {BLESSED_PACKAGE, SYSTEM_PACKAGE}) {
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName);
|
||||||
mIpSecService.addAddressToTunnelInterface(
|
mIpSecService.addAddressToTunnelInterface(
|
||||||
@@ -816,7 +898,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
public void testAddTunnelFailsForBadPackageName() throws Exception {
|
public void testAddTunnelFailsForBadPackageName() throws Exception {
|
||||||
try {
|
try {
|
||||||
IpSecTunnelInterfaceResponse createTunnelResp =
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage");
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BAD_PACKAGE);
|
||||||
fail("Expected a SecurityException for badPackage.");
|
fail("Expected a SecurityException for badPackage.");
|
||||||
} catch (SecurityException expected) {
|
} catch (SecurityException expected) {
|
||||||
}
|
}
|
||||||
@@ -830,7 +912,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
try {
|
try {
|
||||||
String addr = Inet4Address.getLoopbackAddress().getHostAddress();
|
String addr = Inet4Address.getLoopbackAddress().getHostAddress();
|
||||||
mIpSecService.createTunnelInterface(
|
mIpSecService.createTunnelInterface(
|
||||||
addr, addr, new Network(0), new Binder(), "blessedPackage");
|
addr, addr, new Network(0), new Binder(), BLESSED_PACKAGE);
|
||||||
fail("Expected UnsupportedOperationException for disabled feature");
|
fail("Expected UnsupportedOperationException for disabled feature");
|
||||||
} catch (UnsupportedOperationException expected) {
|
} catch (UnsupportedOperationException expected) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user