Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96c73a3c authored by Benedict Wong's avatar Benedict Wong Committed by android-build-merger
Browse files

Merge "Add tunnel-mode calls to netd in IpSecService" am: 475fe28c am: 02d6d810

am: 3b181e9e

Change-Id: I998d44bac0993a8f2e9e228a0b0a80adfaa4d87e
parents dbcb0a35 3b181e9e
Loading
Loading
Loading
Loading
+159 −61
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

import libcore.io.IoUtils;
@@ -596,6 +595,10 @@ public class IpSecService extends IIpSecService.Stub {
            return mSpi;
        }

        public EncapSocketRecord getSocketRecord() {
            return mSocket;
        }

        /** always guarded by IpSecService#this */
        @Override
        public void freeUnderlyingResources() {
@@ -806,9 +809,29 @@ public class IpSecService extends IIpSecService.Stub {
        /** always guarded by IpSecService#this */
        @Override
        public void freeUnderlyingResources() {
            // TODO: Add calls to netd
            // Calls to netd
            //       Teardown VTI
            //       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();
            releaseNetId(mIkey);
@@ -1229,10 +1252,29 @@ public class IpSecService extends IIpSecService.Stub {
        final int okey = reserveNetId();
        String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId);

        // TODO: Add calls to netd:
        try {
            // Calls to netd:
            //       Create VTI
            //       Add inbound/outbound global policies
            //              (use reqid = 0)
            mSrvConfig
                    .getNetdInstance()
                    .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);

            for (int direction : DIRECTIONS) {
                int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;

                mSrvConfig
                        .getNetdInstance()
                        .ipSecAddSecurityPolicy(
                                0, // Use 0 for reqId
                                direction,
                                "",
                                "",
                                0,
                                mark,
                                0xffffffff);
            }

            userRecord.mTunnelInterfaceRecords.put(
                    resourceId,
@@ -1247,6 +1289,20 @@ public class IpSecService extends IIpSecService.Stub {
                                    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,37 +1437,12 @@ public class IpSecService extends IIpSecService.Stub {
        }
    }

    /**
     * Create a transport mode transform, which represent two security associations (one in each
     * direction) in the kernel. The transform will be cached by the system server and must be freed
     * when no longer needed. It is possible to free one, deleting the SA from underneath sockets
     * that are using it, which will result in all of those sockets becoming unable to send or
     * receive data.
     */
    @Override
    public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
    private void createOrUpdateTransform(
            IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
            throws RemoteException {
        checkIpSecConfig(c);
        checkNotNull(binder, "Null Binder passed to createTransform");
        final int resourceId = mNextResourceId++;

        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
        List<RefcountedResource> dependencies = new ArrayList<>();

        if (!userRecord.mTransformQuotaTracker.isAvailable()) {
            return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
        }

        int encapType, encapLocalPort = 0, encapRemotePort = 0;
        EncapSocketRecord socketRecord = null;
        encapType = c.getEncapType();
        int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0;
        if (encapType != IpSecTransform.ENCAP_NONE) {
            RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
                    userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
                            c.getEncapSocketResourceId());
            dependencies.add(refcountedSocketRecord);

            socketRecord = refcountedSocketRecord.getResource();
            encapLocalPort = socketRecord.getPort();
            encapRemotePort = c.getEncapRemotePort();
        }
@@ -1420,12 +1451,6 @@ public class IpSecService extends IIpSecService.Stub {
        IpSecAlgorithm crypt = c.getEncryption();
        IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();

        RefcountedResource<SpiRecord> refcountedSpiRecord =
                userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
        dependencies.add(refcountedSpiRecord);
        SpiRecord spiRecord = refcountedSpiRecord.getResource();

        try {
        mSrvConfig
                .getNetdInstance()
                .ipSecAddSecurityAssociation(
@@ -1449,11 +1474,50 @@ public class IpSecService extends IIpSecService.Stub {
                        encapType,
                        encapLocalPort,
                        encapRemotePort);
    }

    /**
     * Create a IPsec transform, which represents a single security association in the kernel. The
     * transform will be cached by the system server and must be freed when no longer needed. It is
     * possible to free one, deleting the SA from underneath sockets that are using it, which will
     * result in all of those sockets becoming unable to send or receive data.
     */
    @Override
    public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
            throws RemoteException {
        checkIpSecConfig(c);
        checkNotNull(binder, "Null Binder passed to createTransform");
        final int resourceId = mNextResourceId++;

        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
        List<RefcountedResource> dependencies = new ArrayList<>();

        if (!userRecord.mTransformQuotaTracker.isAvailable()) {
            return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
        }

        EncapSocketRecord socketRecord = null;
        if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
            RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
                    userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
                            c.getEncapSocketResourceId());
            dependencies.add(refcountedSocketRecord);
            socketRecord = refcountedSocketRecord.getResource();
        }

        RefcountedResource<SpiRecord> refcountedSpiRecord =
                userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
        dependencies.add(refcountedSpiRecord);
        SpiRecord spiRecord = refcountedSpiRecord.getResource();

        try {
            createOrUpdateTransform(c, resourceId, spiRecord, socketRecord);
        } catch (ServiceSpecificException e) {
            // FIXME: get the error code and throw is at an IOException from Errno Exception
            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(
                resourceId,
                new RefcountedResource<TransformRecord>(
@@ -1561,14 +1625,48 @@ public class IpSecService extends IIpSecService.Stub {
                c.getMode() == IpSecTransform.MODE_TUNNEL,
                "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 =
                (direction == IpSecManager.DIRECTION_IN)
                        ? tunnelInterfaceInfo.getIkey()
                        : tunnelInterfaceInfo.getOkey();

        // TODO: Add calls to netd:
        try {
            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.
                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)
        //       If outbound, add SPI to policy
            createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
        } catch (ServiceSpecificException e) {
            if (e.errorCode == EINVAL) {
                throw new IllegalArgumentException(e.toString());
            } else {
                throw e;
            }
        }
    }

    @Override
+2 −3
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -229,7 +228,7 @@ public class IpSecServiceParameterizedTest {
                        anyInt(),
                        anyString(),
                        anyString(),
                        anyLong(),
                        anyInt(),
                        eq(TEST_SPI),
                        anyInt(),
                        anyInt(),
@@ -264,7 +263,7 @@ public class IpSecServiceParameterizedTest {
                        anyInt(),
                        anyString(),
                        anyString(),
                        anyLong(),
                        anyInt(),
                        eq(TEST_SPI),
                        anyInt(),
                        anyInt(),