Loading core/java/android/net/IpSecConfig.java +32 −4 Original line number Diff line number Diff line Loading @@ -65,10 +65,13 @@ public final class IpSecConfig implements Parcelable { // An interval, in seconds between the NattKeepalive packets private int mNattKeepaliveInterval; // XFRM mark and mask // XFRM mark and mask; defaults to 0 (no mark/mask) private int mMarkValue; private int mMarkMask; // XFRM interface id private int mXfrmInterfaceId; /** Set the mode for this IPsec transform */ public void setMode(int mode) { mMode = mode; Loading Loading @@ -125,14 +128,30 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = interval; } /** * Sets the mark value * * <p>Internal (System server) use only. Marks passed in by users will be overwritten or * ignored. */ public void setMarkValue(int mark) { mMarkValue = mark; } /** * Sets the mark mask * * <p>Internal (System server) use only. Marks passed in by users will be overwritten or * ignored. */ public void setMarkMask(int mask) { mMarkMask = mask; } public void setXfrmInterfaceId(int xfrmInterfaceId) { mXfrmInterfaceId = xfrmInterfaceId; } // Transport or Tunnel public int getMode() { return mMode; Loading Loading @@ -190,6 +209,10 @@ public final class IpSecConfig implements Parcelable { return mMarkMask; } public int getXfrmInterfaceId() { return mXfrmInterfaceId; } // Parcelable Methods @Override Loading @@ -213,6 +236,7 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mNattKeepaliveInterval); out.writeInt(mMarkValue); out.writeInt(mMarkMask); out.writeInt(mXfrmInterfaceId); } @VisibleForTesting Loading @@ -235,6 +259,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = c.mNattKeepaliveInterval; mMarkValue = c.mMarkValue; mMarkMask = c.mMarkMask; mXfrmInterfaceId = c.mXfrmInterfaceId; } private IpSecConfig(Parcel in) { Loading @@ -255,6 +280,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = in.readInt(); mMarkValue = in.readInt(); mMarkMask = in.readInt(); mXfrmInterfaceId = in.readInt(); } @Override Loading Loading @@ -289,6 +315,8 @@ public final class IpSecConfig implements Parcelable { .append(mMarkValue) .append(", mMarkMask=") .append(mMarkMask) .append(", mXfrmInterfaceId=") .append(mXfrmInterfaceId) .append("}"); return strBuilder.toString(); Loading Loading @@ -320,10 +348,10 @@ public final class IpSecConfig implements Parcelable { && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval && lhs.mSpiResourceId == rhs.mSpiResourceId && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) && IpSecAlgorithm.equals( lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) && IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication) && lhs.mMarkValue == rhs.mMarkValue && lhs.mMarkMask == rhs.mMarkMask); && lhs.mMarkMask == rhs.mMarkMask && lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId); } } services/core/java/com/android/server/IpSecService.java +70 −29 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; Loading Loading @@ -62,6 +63,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import libcore.io.IoUtils; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; Loading @@ -73,8 +76,6 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import libcore.io.IoUtils; /** * A service to manage multiple clients that want to access the IpSec API. The service is * responsible for maintaining a list of clients and managing the resources (and related quotas) Loading Loading @@ -621,7 +622,8 @@ public class IpSecService extends IIpSecService.Stub { mConfig.getDestinationAddress(), spi, mConfig.getMarkValue(), mConfig.getMarkMask()); mConfig.getMarkMask(), mConfig.getXfrmInterfaceId()); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } Loading Loading @@ -683,7 +685,8 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0); uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); Loading Loading @@ -795,6 +798,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIkey; private final int mOkey; private final int mIfId; TunnelInterfaceRecord( int resourceId, String interfaceName, Loading @@ -802,7 +807,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, int ikey, int okey) { int okey, int intfId) { super(resourceId); mInterfaceName = interfaceName; Loading @@ -811,6 +817,7 @@ public class IpSecService extends IIpSecService.Stub { mRemoteAddress = remoteAddr; mIkey = ikey; mOkey = okey; mIfId = intfId; } /** always guarded by IpSecService#this */ Loading @@ -821,7 +828,7 @@ public class IpSecService extends IIpSecService.Stub { // Delete global policies try { final INetd netd = mSrvConfig.getNetdInstance(); netd.removeVirtualTunnelInterface(mInterfaceName); netd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( Loading @@ -829,13 +836,15 @@ public class IpSecService extends IIpSecService.Stub { selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff); 0xffffffff, mIfId); netd.ipSecDeleteSecurityPolicy( uid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, 0xffffffff); 0xffffffff, mIfId); } } catch (ServiceSpecificException | RemoteException e) { Log.e( Loading Loading @@ -877,6 +886,10 @@ public class IpSecService extends IIpSecService.Stub { return mOkey; } public int getIfId() { return mIfId; } @Override protected ResourceTracker getResourceTracker() { return getUserRecord().mTunnelQuotaTracker; Loading Loading @@ -1286,7 +1299,7 @@ public class IpSecService extends IIpSecService.Stub { // Add inbound/outbound global policies // (use reqid = 0) final INetd netd = mSrvConfig.getNetdInstance(); netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. Loading @@ -1298,7 +1311,8 @@ public class IpSecService extends IIpSecService.Stub { remoteAddr, 0, okey, 0xffffffff); 0xffffffff, resourceId); netd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, Loading @@ -1307,7 +1321,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, 0, ikey, 0xffffffff); 0xffffffff, resourceId); } userRecord.mTunnelInterfaceRecords.put( Loading @@ -1320,7 +1335,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, remoteAddr, ikey, okey), okey, resourceId), binder)); return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); } catch (RemoteException e) { Loading Loading @@ -1523,6 +1539,9 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Invalid IpSecTransform.mode: " + config.getMode()); } config.setMarkValue(0); config.setMarkMask(0); } private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; Loading Loading @@ -1584,7 +1603,8 @@ public class IpSecService extends IIpSecService.Stub { (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, encapType, encapLocalPort, encapRemotePort); encapRemotePort, c.getXfrmInterfaceId()); } /** Loading Loading @@ -1740,14 +1760,35 @@ public class IpSecService extends IIpSecService.Stub { : tunnelInterfaceInfo.getIkey(); try { c.setMarkValue(mark); c.setMarkMask(0xffffffff); // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip // SPI matching as part of the template resolution. int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId()); // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream // (and backporting) would allow us to narrow the mark space, and ensure that the SA // and SPs have matching marks (as VTI are meant to be built). // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the // config matches the actual allocated resources in the kernel. // All SAs will have zero marks (from creation time), and any policy that matches the // same src/dst could match these SAs. Non-IpSecService governed processes that // establish floating policies with the same src/dst may result in undefined // behavior. This is generally limited to vendor code due to the permissions // (CAP_NET_ADMIN) required. // // c.setMarkValue(mark); // c.setMarkMask(0xffffffff); if (direction == IpSecManager.DIRECTION_OUT) { // Set output mark via underlying network (output only) c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); // If outbound, also add SPI to the policy. // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys, // but want to guarantee outbound packets are sent over the new SA. spi = transformInfo.getSpiRecord().getSpi(); } // Always update the policy with the relevant XFRM_IF_ID for (int selAddrFamily : ADDRESS_FAMILIES) { mSrvConfig .getNetdInstance() Loading @@ -1755,12 +1796,12 @@ public class IpSecService extends IIpSecService.Stub { callingUid, selAddrFamily, direction, tunnelInterfaceInfo.getLocalAddress(), tunnelInterfaceInfo.getRemoteAddress(), transformInfo.getSpiRecord().getSpi(), mark, 0xffffffff); } transformInfo.getConfig().getSourceAddress(), transformInfo.getConfig().getDestinationAddress(), spi, // If outbound, also add SPI to the policy. mark, // Must always set policy mark; ikey/okey for VTIs 0xffffffff, c.getXfrmInterfaceId()); } // Update SA with tunnel mark (ikey or okey based on direction) Loading tests/net/java/android/net/IpSecConfigTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class IpSecConfigTest { assertNull(c.getEncryption()); assertNull(c.getAuthentication()); assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId()); assertEquals(0, c.getXfrmInterfaceId()); } private IpSecConfig getSampleConfig() { Loading Loading @@ -77,6 +78,7 @@ public class IpSecConfigTest { c.setNattKeepaliveInterval(42); c.setMarkValue(12); c.setMarkMask(23); c.setXfrmInterfaceId(34); return c; } Loading tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +50 −4 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ public class IpSecServiceParameterizedTest { private final LinkAddress mLocalInnerAddress; private final int mFamily; private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6}; @Parameterized.Parameters public static Collection ipSecConfigs() { return Arrays.asList( Loading Loading @@ -196,6 +199,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -231,6 +235,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -304,7 +309,8 @@ public class IpSecServiceParameterizedTest { eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), eq(config.getEncapType()), eq(encapSocketPort), eq(config.getEncapRemotePort())); eq(config.getEncapRemotePort()), eq(config.getXfrmInterfaceId())); } @Test Loading Loading @@ -430,6 +436,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // quota is not released until the SPI is released by the Transform assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); Loading @@ -452,6 +459,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading @@ -469,6 +477,7 @@ public class IpSecServiceParameterizedTest { anyString(), anyInt(), anyInt(), anyInt(), anyInt()); assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); Loading Loading @@ -504,6 +513,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -572,11 +582,12 @@ public class IpSecServiceParameterizedTest { assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd) .addVirtualTunnelInterface( .ipSecAddTunnelInterface( eq(createTunnelResp.interfaceName), eq(mSourceAddr), eq(mDestinationAddr), anyInt(), anyInt(), anyInt()); } Loading @@ -591,7 +602,7 @@ public class IpSecServiceParameterizedTest { // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName)); verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); try { userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( createTunnelResp.resourceId); Loading @@ -614,7 +625,7 @@ public class IpSecServiceParameterizedTest { // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName)); verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); try { userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( createTunnelResp.resourceId); Loading @@ -623,6 +634,41 @@ public class IpSecServiceParameterizedTest { } } @Test public void testApplyTunnelModeTransform() throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); IpSecTunnelInterfaceResponse createTunnelResp = createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); int transformResourceId = createTransformResp.resourceId; int tunnelResourceId = createTunnelResp.resourceId; mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, "blessedPackage"); for (int selAddrFamily : ADDRESS_FAMILIES) { verify(mMockNetd) .ipSecUpdateSecurityPolicy( eq(mUid), eq(selAddrFamily), eq(IpSecManager.DIRECTION_OUT), anyString(), anyString(), eq(TEST_SPI), anyInt(), // iKey/oKey anyInt(), // mask eq(tunnelResourceId)); } ipSecConfig.setXfrmInterfaceId(tunnelResourceId); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test public void testAddRemoveAddressFromTunnelInterface() throws Exception { for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) { Loading Loading
core/java/android/net/IpSecConfig.java +32 −4 Original line number Diff line number Diff line Loading @@ -65,10 +65,13 @@ public final class IpSecConfig implements Parcelable { // An interval, in seconds between the NattKeepalive packets private int mNattKeepaliveInterval; // XFRM mark and mask // XFRM mark and mask; defaults to 0 (no mark/mask) private int mMarkValue; private int mMarkMask; // XFRM interface id private int mXfrmInterfaceId; /** Set the mode for this IPsec transform */ public void setMode(int mode) { mMode = mode; Loading Loading @@ -125,14 +128,30 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = interval; } /** * Sets the mark value * * <p>Internal (System server) use only. Marks passed in by users will be overwritten or * ignored. */ public void setMarkValue(int mark) { mMarkValue = mark; } /** * Sets the mark mask * * <p>Internal (System server) use only. Marks passed in by users will be overwritten or * ignored. */ public void setMarkMask(int mask) { mMarkMask = mask; } public void setXfrmInterfaceId(int xfrmInterfaceId) { mXfrmInterfaceId = xfrmInterfaceId; } // Transport or Tunnel public int getMode() { return mMode; Loading Loading @@ -190,6 +209,10 @@ public final class IpSecConfig implements Parcelable { return mMarkMask; } public int getXfrmInterfaceId() { return mXfrmInterfaceId; } // Parcelable Methods @Override Loading @@ -213,6 +236,7 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mNattKeepaliveInterval); out.writeInt(mMarkValue); out.writeInt(mMarkMask); out.writeInt(mXfrmInterfaceId); } @VisibleForTesting Loading @@ -235,6 +259,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = c.mNattKeepaliveInterval; mMarkValue = c.mMarkValue; mMarkMask = c.mMarkMask; mXfrmInterfaceId = c.mXfrmInterfaceId; } private IpSecConfig(Parcel in) { Loading @@ -255,6 +280,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = in.readInt(); mMarkValue = in.readInt(); mMarkMask = in.readInt(); mXfrmInterfaceId = in.readInt(); } @Override Loading Loading @@ -289,6 +315,8 @@ public final class IpSecConfig implements Parcelable { .append(mMarkValue) .append(", mMarkMask=") .append(mMarkMask) .append(", mXfrmInterfaceId=") .append(mXfrmInterfaceId) .append("}"); return strBuilder.toString(); Loading Loading @@ -320,10 +348,10 @@ public final class IpSecConfig implements Parcelable { && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval && lhs.mSpiResourceId == rhs.mSpiResourceId && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) && IpSecAlgorithm.equals( lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) && IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication) && lhs.mMarkValue == rhs.mMarkValue && lhs.mMarkMask == rhs.mMarkMask); && lhs.mMarkMask == rhs.mMarkMask && lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId); } }
services/core/java/com/android/server/IpSecService.java +70 −29 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; Loading Loading @@ -62,6 +63,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import libcore.io.IoUtils; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; Loading @@ -73,8 +76,6 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import libcore.io.IoUtils; /** * A service to manage multiple clients that want to access the IpSec API. The service is * responsible for maintaining a list of clients and managing the resources (and related quotas) Loading Loading @@ -621,7 +622,8 @@ public class IpSecService extends IIpSecService.Stub { mConfig.getDestinationAddress(), spi, mConfig.getMarkValue(), mConfig.getMarkMask()); mConfig.getMarkMask(), mConfig.getXfrmInterfaceId()); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } Loading Loading @@ -683,7 +685,8 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0); uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); Loading Loading @@ -795,6 +798,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIkey; private final int mOkey; private final int mIfId; TunnelInterfaceRecord( int resourceId, String interfaceName, Loading @@ -802,7 +807,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, int ikey, int okey) { int okey, int intfId) { super(resourceId); mInterfaceName = interfaceName; Loading @@ -811,6 +817,7 @@ public class IpSecService extends IIpSecService.Stub { mRemoteAddress = remoteAddr; mIkey = ikey; mOkey = okey; mIfId = intfId; } /** always guarded by IpSecService#this */ Loading @@ -821,7 +828,7 @@ public class IpSecService extends IIpSecService.Stub { // Delete global policies try { final INetd netd = mSrvConfig.getNetdInstance(); netd.removeVirtualTunnelInterface(mInterfaceName); netd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( Loading @@ -829,13 +836,15 @@ public class IpSecService extends IIpSecService.Stub { selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff); 0xffffffff, mIfId); netd.ipSecDeleteSecurityPolicy( uid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, 0xffffffff); 0xffffffff, mIfId); } } catch (ServiceSpecificException | RemoteException e) { Log.e( Loading Loading @@ -877,6 +886,10 @@ public class IpSecService extends IIpSecService.Stub { return mOkey; } public int getIfId() { return mIfId; } @Override protected ResourceTracker getResourceTracker() { return getUserRecord().mTunnelQuotaTracker; Loading Loading @@ -1286,7 +1299,7 @@ public class IpSecService extends IIpSecService.Stub { // Add inbound/outbound global policies // (use reqid = 0) final INetd netd = mSrvConfig.getNetdInstance(); netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. Loading @@ -1298,7 +1311,8 @@ public class IpSecService extends IIpSecService.Stub { remoteAddr, 0, okey, 0xffffffff); 0xffffffff, resourceId); netd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, Loading @@ -1307,7 +1321,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, 0, ikey, 0xffffffff); 0xffffffff, resourceId); } userRecord.mTunnelInterfaceRecords.put( Loading @@ -1320,7 +1335,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, remoteAddr, ikey, okey), okey, resourceId), binder)); return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); } catch (RemoteException e) { Loading Loading @@ -1523,6 +1539,9 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Invalid IpSecTransform.mode: " + config.getMode()); } config.setMarkValue(0); config.setMarkMask(0); } private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; Loading Loading @@ -1584,7 +1603,8 @@ public class IpSecService extends IIpSecService.Stub { (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, encapType, encapLocalPort, encapRemotePort); encapRemotePort, c.getXfrmInterfaceId()); } /** Loading Loading @@ -1740,14 +1760,35 @@ public class IpSecService extends IIpSecService.Stub { : tunnelInterfaceInfo.getIkey(); try { c.setMarkValue(mark); c.setMarkMask(0xffffffff); // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip // SPI matching as part of the template resolution. int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId()); // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream // (and backporting) would allow us to narrow the mark space, and ensure that the SA // and SPs have matching marks (as VTI are meant to be built). // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the // config matches the actual allocated resources in the kernel. // All SAs will have zero marks (from creation time), and any policy that matches the // same src/dst could match these SAs. Non-IpSecService governed processes that // establish floating policies with the same src/dst may result in undefined // behavior. This is generally limited to vendor code due to the permissions // (CAP_NET_ADMIN) required. // // c.setMarkValue(mark); // c.setMarkMask(0xffffffff); if (direction == IpSecManager.DIRECTION_OUT) { // Set output mark via underlying network (output only) c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); // If outbound, also add SPI to the policy. // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys, // but want to guarantee outbound packets are sent over the new SA. spi = transformInfo.getSpiRecord().getSpi(); } // Always update the policy with the relevant XFRM_IF_ID for (int selAddrFamily : ADDRESS_FAMILIES) { mSrvConfig .getNetdInstance() Loading @@ -1755,12 +1796,12 @@ public class IpSecService extends IIpSecService.Stub { callingUid, selAddrFamily, direction, tunnelInterfaceInfo.getLocalAddress(), tunnelInterfaceInfo.getRemoteAddress(), transformInfo.getSpiRecord().getSpi(), mark, 0xffffffff); } transformInfo.getConfig().getSourceAddress(), transformInfo.getConfig().getDestinationAddress(), spi, // If outbound, also add SPI to the policy. mark, // Must always set policy mark; ikey/okey for VTIs 0xffffffff, c.getXfrmInterfaceId()); } // Update SA with tunnel mark (ikey or okey based on direction) Loading
tests/net/java/android/net/IpSecConfigTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class IpSecConfigTest { assertNull(c.getEncryption()); assertNull(c.getAuthentication()); assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId()); assertEquals(0, c.getXfrmInterfaceId()); } private IpSecConfig getSampleConfig() { Loading Loading @@ -77,6 +78,7 @@ public class IpSecConfigTest { c.setNattKeepaliveInterval(42); c.setMarkValue(12); c.setMarkMask(23); c.setXfrmInterfaceId(34); return c; } Loading
tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +50 −4 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ public class IpSecServiceParameterizedTest { private final LinkAddress mLocalInnerAddress; private final int mFamily; private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6}; @Parameterized.Parameters public static Collection ipSecConfigs() { return Arrays.asList( Loading Loading @@ -196,6 +199,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -231,6 +235,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -304,7 +309,8 @@ public class IpSecServiceParameterizedTest { eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0), eq(config.getEncapType()), eq(encapSocketPort), eq(config.getEncapRemotePort())); eq(config.getEncapRemotePort()), eq(config.getXfrmInterfaceId())); } @Test Loading Loading @@ -430,6 +436,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // quota is not released until the SPI is released by the Transform assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); Loading @@ -452,6 +459,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading @@ -469,6 +477,7 @@ public class IpSecServiceParameterizedTest { anyString(), anyInt(), anyInt(), anyInt(), anyInt()); assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); Loading Loading @@ -504,6 +513,7 @@ public class IpSecServiceParameterizedTest { anyString(), eq(TEST_SPI), anyInt(), anyInt(), anyInt()); // Verify quota and RefcountedResource objects cleaned up Loading Loading @@ -572,11 +582,12 @@ public class IpSecServiceParameterizedTest { assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd) .addVirtualTunnelInterface( .ipSecAddTunnelInterface( eq(createTunnelResp.interfaceName), eq(mSourceAddr), eq(mDestinationAddr), anyInt(), anyInt(), anyInt()); } Loading @@ -591,7 +602,7 @@ public class IpSecServiceParameterizedTest { // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName)); verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); try { userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( createTunnelResp.resourceId); Loading @@ -614,7 +625,7 @@ public class IpSecServiceParameterizedTest { // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName)); verify(mMockNetd).ipSecRemoveTunnelInterface(eq(createTunnelResp.interfaceName)); try { userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow( createTunnelResp.resourceId); Loading @@ -623,6 +634,41 @@ public class IpSecServiceParameterizedTest { } } @Test public void testApplyTunnelModeTransform() throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); IpSecTunnelInterfaceResponse createTunnelResp = createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); int transformResourceId = createTransformResp.resourceId; int tunnelResourceId = createTunnelResp.resourceId; mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, transformResourceId, "blessedPackage"); for (int selAddrFamily : ADDRESS_FAMILIES) { verify(mMockNetd) .ipSecUpdateSecurityPolicy( eq(mUid), eq(selAddrFamily), eq(IpSecManager.DIRECTION_OUT), anyString(), anyString(), eq(TEST_SPI), anyInt(), // iKey/oKey anyInt(), // mask eq(tunnelResourceId)); } ipSecConfig.setXfrmInterfaceId(tunnelResourceId); verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } @Test public void testAddRemoveAddressFromTunnelInterface() throws Exception { for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) { Loading