Merge "Add tunnel-mode calls to netd in IpSecService" am: 475fe28c50

am: 02d6d81006

Change-Id: I8a3d16c8e58ad1c09d967943abe1c729fe37636a
This commit is contained in:
Benedict Wong
2018-01-24 19:56:24 +00:00
committed by android-build-merger

View File

@@ -65,7 +65,6 @@ import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.List; import java.util.List;
import libcore.io.IoUtils; import libcore.io.IoUtils;
@@ -596,6 +595,10 @@ public class IpSecService extends IIpSecService.Stub {
return mSpi; return mSpi;
} }
public EncapSocketRecord getSocketRecord() {
return mSocket;
}
/** always guarded by IpSecService#this */ /** always guarded by IpSecService#this */
@Override @Override
public void freeUnderlyingResources() { public void freeUnderlyingResources() {
@@ -806,9 +809,29 @@ public class IpSecService extends IIpSecService.Stub {
/** always guarded by IpSecService#this */ /** always guarded by IpSecService#this */
@Override @Override
public void freeUnderlyingResources() { public void freeUnderlyingResources() {
// TODO: Add calls to netd // Calls to netd
// Teardown VTI // Teardown VTI
// Delete global policies // Delete global policies
try {
mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName);
for (int direction : DIRECTIONS) {
int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
mSrvConfig
.getNetdInstance()
.ipSecDeleteSecurityPolicy(
0, direction, mLocalAddress, mRemoteAddress, mark, 0xffffffff);
}
} catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception
} catch (RemoteException e) {
Log.e(
TAG,
"Failed to delete VTI with interface name: "
+ mInterfaceName
+ " and id: "
+ mResourceId);
}
getResourceTracker().give(); getResourceTracker().give();
releaseNetId(mIkey); releaseNetId(mIkey);
@@ -1229,24 +1252,57 @@ public class IpSecService extends IIpSecService.Stub {
final int okey = reserveNetId(); final int okey = reserveNetId();
String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId);
// TODO: Add calls to netd: try {
// Create VTI // Calls to netd:
// Add inbound/outbound global policies // Create VTI
// (use reqid = 0) // Add inbound/outbound global policies
// (use reqid = 0)
mSrvConfig
.getNetdInstance()
.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
userRecord.mTunnelInterfaceRecords.put( for (int direction : DIRECTIONS) {
resourceId, int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
new RefcountedResource<TunnelInterfaceRecord>(
new TunnelInterfaceRecord( mSrvConfig
resourceId, .getNetdInstance()
intfName, .ipSecAddSecurityPolicy(
underlyingNetwork, 0, // Use 0 for reqId
localAddr, direction,
remoteAddr, "",
ikey, "",
okey), 0,
binder)); mark,
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); 0xffffffff);
}
userRecord.mTunnelInterfaceRecords.put(
resourceId,
new RefcountedResource<TunnelInterfaceRecord>(
new TunnelInterfaceRecord(
resourceId,
intfName,
underlyingNetwork,
localAddr,
remoteAddr,
ikey,
okey),
binder));
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
} catch (RemoteException e) {
// Release keys if we got an error.
releaseNetId(ikey);
releaseNetId(okey);
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception
}
// If we make it to here, then something has gone wrong and we couldn't create a VTI.
// Release the keys that we reserved, and return an error status.
releaseNetId(ikey);
releaseNetId(okey);
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
} }
/** /**
@@ -1381,12 +1437,50 @@ public class IpSecService extends IIpSecService.Stub {
} }
} }
private void createOrUpdateTransform(
IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
throws RemoteException {
int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0;
if (encapType != IpSecTransform.ENCAP_NONE) {
encapLocalPort = socketRecord.getPort();
encapRemotePort = c.getEncapRemotePort();
}
IpSecAlgorithm auth = c.getAuthentication();
IpSecAlgorithm crypt = c.getEncryption();
IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
mSrvConfig
.getNetdInstance()
.ipSecAddSecurityAssociation(
resourceId,
c.getMode(),
c.getSourceAddress(),
c.getDestinationAddress(),
(c.getNetwork() != null) ? c.getNetwork().netId : 0,
spiRecord.getSpi(),
c.getMarkValue(),
c.getMarkMask(),
(auth != null) ? auth.getName() : "",
(auth != null) ? auth.getKey() : new byte[] {},
(auth != null) ? auth.getTruncationLengthBits() : 0,
(crypt != null) ? crypt.getName() : "",
(crypt != null) ? crypt.getKey() : new byte[] {},
(crypt != null) ? crypt.getTruncationLengthBits() : 0,
(authCrypt != null) ? authCrypt.getName() : "",
(authCrypt != null) ? authCrypt.getKey() : new byte[] {},
(authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
encapType,
encapLocalPort,
encapRemotePort);
}
/** /**
* Create a transport mode transform, which represent two security associations (one in each * Create a IPsec transform, which represents a single security association in the kernel. The
* direction) in the kernel. The transform will be cached by the system server and must be freed * transform will be cached by the system server and must be freed when no longer needed. It is
* when no longer needed. It is possible to free one, deleting the SA from underneath sockets * possible to free one, deleting the SA from underneath sockets that are using it, which will
* that are using it, which will result in all of those sockets becoming unable to send or * result in all of those sockets becoming unable to send or receive data.
* receive data.
*/ */
@Override @Override
public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
@@ -1402,58 +1496,28 @@ public class IpSecService extends IIpSecService.Stub {
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
} }
int encapType, encapLocalPort = 0, encapRemotePort = 0;
EncapSocketRecord socketRecord = null; EncapSocketRecord socketRecord = null;
encapType = c.getEncapType(); if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
if (encapType != IpSecTransform.ENCAP_NONE) {
RefcountedResource<EncapSocketRecord> refcountedSocketRecord = RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
c.getEncapSocketResourceId()); c.getEncapSocketResourceId());
dependencies.add(refcountedSocketRecord); dependencies.add(refcountedSocketRecord);
socketRecord = refcountedSocketRecord.getResource(); socketRecord = refcountedSocketRecord.getResource();
encapLocalPort = socketRecord.getPort();
encapRemotePort = c.getEncapRemotePort();
} }
IpSecAlgorithm auth = c.getAuthentication();
IpSecAlgorithm crypt = c.getEncryption();
IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
RefcountedResource<SpiRecord> refcountedSpiRecord = RefcountedResource<SpiRecord> refcountedSpiRecord =
userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId()); userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
dependencies.add(refcountedSpiRecord); dependencies.add(refcountedSpiRecord);
SpiRecord spiRecord = refcountedSpiRecord.getResource(); SpiRecord spiRecord = refcountedSpiRecord.getResource();
try { try {
mSrvConfig createOrUpdateTransform(c, resourceId, spiRecord, socketRecord);
.getNetdInstance()
.ipSecAddSecurityAssociation(
resourceId,
c.getMode(),
c.getSourceAddress(),
c.getDestinationAddress(),
(c.getNetwork() != null) ? c.getNetwork().netId : 0,
spiRecord.getSpi(),
c.getMarkValue(),
c.getMarkMask(),
(auth != null) ? auth.getName() : "",
(auth != null) ? auth.getKey() : new byte[] {},
(auth != null) ? auth.getTruncationLengthBits() : 0,
(crypt != null) ? crypt.getName() : "",
(crypt != null) ? crypt.getKey() : new byte[] {},
(crypt != null) ? crypt.getTruncationLengthBits() : 0,
(authCrypt != null) ? authCrypt.getName() : "",
(authCrypt != null) ? authCrypt.getKey() : new byte[] {},
(authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
encapType,
encapLocalPort,
encapRemotePort);
} catch (ServiceSpecificException e) { } catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception // FIXME: get the error code and throw is at an IOException from Errno Exception
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
} }
// Both SAs were created successfully, time to construct a record and lock it away
// SA was created successfully, time to construct a record and lock it away
userRecord.mTransformRecords.put( userRecord.mTransformRecords.put(
resourceId, resourceId,
new RefcountedResource<TransformRecord>( new RefcountedResource<TransformRecord>(
@@ -1561,14 +1625,48 @@ public class IpSecService extends IIpSecService.Stub {
c.getMode() == IpSecTransform.MODE_TUNNEL, c.getMode() == IpSecTransform.MODE_TUNNEL,
"Transform mode was not Tunnel mode; cannot be applied to a tunnel interface"); "Transform mode was not Tunnel mode; cannot be applied to a tunnel interface");
EncapSocketRecord socketRecord = null;
if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
socketRecord =
userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId());
}
SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId());
int mark = int mark =
(direction == IpSecManager.DIRECTION_IN) (direction == IpSecManager.DIRECTION_IN)
? tunnelInterfaceInfo.getIkey() ? tunnelInterfaceInfo.getIkey()
: tunnelInterfaceInfo.getOkey(); : tunnelInterfaceInfo.getOkey();
// TODO: Add calls to netd: try {
// Update SA with tunnel mark (ikey or okey based on direction) c.setMarkValue(mark);
// If outbound, add SPI to policy 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.
mSrvConfig
.getNetdInstance()
.ipSecUpdateSecurityPolicy(
0, // Use 0 for reqId
direction,
"",
"",
transformInfo.getSpiRecord().getSpi(),
mark,
0xffffffff);
}
// Update SA with tunnel mark (ikey or okey based on direction)
createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
} catch (ServiceSpecificException e) {
if (e.errorCode == EINVAL) {
throw new IllegalArgumentException(e.toString());
} else {
throw e;
}
}
} }
@Override @Override