/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import static android.Manifest.permission.DUMP;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
import static com.android.internal.util.Preconditions.checkNotNull;

import android.content.Context;
import android.net.IIpSecService;
import android.net.INetd;
import android.net.IpSecAlgorithm;
import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
import android.net.IpSecTransformResponse;
import android.net.IpSecUdpEncapResponse;
import android.net.NetworkUtils;
import android.net.util.NetdService;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicInteger;

import libcore.io.IoUtils;

/** @hide */
public class IpSecService extends IIpSecService.Stub {
    private static final String TAG = "IpSecService";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

    private static final String NETD_SERVICE_NAME = "netd";
    private static final int[] DIRECTIONS =
            new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};

    private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
    private static final int MAX_PORT_BIND_ATTEMPTS = 10;
    private static final InetAddress INADDR_ANY;

    static {
        try {
            INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

    static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved
    static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer

    /* Binder context for this service */
    private final Context mContext;

    /** Should be a never-repeating global ID for resources */
    private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0);

    @GuardedBy("this")
    private final ManagedResourceArray<SpiRecord> mSpiRecords = new ManagedResourceArray<>();

    @GuardedBy("this")
    private final ManagedResourceArray<TransformRecord> mTransformRecords =
            new ManagedResourceArray<>();

    @GuardedBy("this")
    private final ManagedResourceArray<UdpSocketRecord> mUdpSocketRecords =
            new ManagedResourceArray<>();

    interface IpSecServiceConfiguration {
        INetd getNetdInstance() throws RemoteException;

        static IpSecServiceConfiguration GETSRVINSTANCE =
                new IpSecServiceConfiguration() {
                    @Override
                    public INetd getNetdInstance() throws RemoteException {
                        final INetd netd = NetdService.getInstance();
                        if (netd == null) {
                            throw new RemoteException("Failed to Get Netd Instance");
                        }
                        return netd;
                    }
                };
    }

    private final IpSecServiceConfiguration mSrvConfig;

    /* Very simple counting class that looks much like a counting semaphore */
    public static class ResourceTracker {
        private final int mMax;
        int mCurrent;

        ResourceTracker(int max) {
            mMax = max;
            mCurrent = 0;
        }

        synchronized boolean isAvailable() {
            return (mCurrent < mMax);
        }

        synchronized void take() {
            if (!isAvailable()) {
                Log.wtf(TAG, "Too many resources allocated!");
            }
            mCurrent++;
        }

        synchronized void give() {
            if (mCurrent <= 0) {
                Log.wtf(TAG, "We've released this resource too many times");
            }
            mCurrent--;
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append("{mCurrent=")
                    .append(mCurrent)
                    .append(", mMax=")
                    .append(mMax)
                    .append("}")
                    .toString();
        }
    }

    private static final class UserQuotaTracker {
        /* Maximum number of UDP Encap Sockets that a single UID may possess */
        public static final int MAX_NUM_ENCAP_SOCKETS = 2;

        /* Maximum number of IPsec Transforms that a single UID may possess */
        public static final int MAX_NUM_TRANSFORMS = 4;

        /* Maximum number of IPsec Transforms that a single UID may possess */
        public static final int MAX_NUM_SPIS = 8;

        /* Record for one users's IpSecService-managed objects */
        public static class UserRecord {
            public final ResourceTracker socket = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
            public final ResourceTracker transform = new ResourceTracker(MAX_NUM_TRANSFORMS);
            public final ResourceTracker spi = new ResourceTracker(MAX_NUM_SPIS);

            @Override
            public String toString() {
                return new StringBuilder()
                        .append("{socket=")
                        .append(socket)
                        .append(", transform=")
                        .append(transform)
                        .append(", spi=")
                        .append(spi)
                        .append("}")
                        .toString();
            }
        }

        private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();

        /* a never-fail getter so that we can populate the list of UIDs as-needed */
        public synchronized UserRecord getUserRecord(int uid) {
            UserRecord r = mUserRecords.get(uid);
            if (r == null) {
                r = new UserRecord();
                mUserRecords.put(uid, r);
            }
            return r;
        }

        @Override
        public String toString() {
            return mUserRecords.toString();
        }
    }

    private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker();

    /**
     * The ManagedResource class provides a facility to cleanly and reliably release system
     * resources. It relies on two things: an IBinder that allows ManagedResource to automatically
     * clean up in the event that the Binder dies and a user-provided resourceId that should
     * uniquely identify the managed resource. To use this class, the user should implement the
     * releaseResources() method that is responsible for releasing system resources when invoked.
     */
    private abstract class ManagedResource implements IBinder.DeathRecipient {
        final int pid;
        final int uid;
        private IBinder mBinder;
        protected int mResourceId;

        private AtomicInteger mReferenceCount = new AtomicInteger(0);

        ManagedResource(int resourceId, IBinder binder) {
            super();
            if (resourceId == INVALID_RESOURCE_ID) {
                throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
            }
            mBinder = binder;
            mResourceId = resourceId;
            pid = Binder.getCallingPid();
            uid = Binder.getCallingUid();

            getResourceTracker().take();
            try {
                mBinder.linkToDeath(this, 0);
            } catch (RemoteException e) {
                binderDied();
            }
        }

        public void addReference() {
            mReferenceCount.incrementAndGet();
        }

        public void removeReference() {
            if (mReferenceCount.decrementAndGet() < 0) {
                Log.wtf(TAG, "Programming error: negative reference count");
            }
        }

        public boolean isReferenced() {
            return (mReferenceCount.get() > 0);
        }

        /**
         * Ensures that the caller is either the owner of this resource or has the system UID and
         * throws a SecurityException otherwise.
         */
        public void checkOwnerOrSystem() {
            if (uid != Binder.getCallingUid()
                    && android.os.Process.SYSTEM_UID != Binder.getCallingUid()) {
                throw new SecurityException("Only the owner may access managed resources!");
            }
        }

        /**
         * When this record is no longer needed for managing system resources this function should
         * clean up all system resources and nullify the record. This function shall perform all
         * necessary cleanup of the resources managed by this record.
         *
         * <p>NOTE: this function verifies ownership before allowing resources to be freed.
         */
        public final void release() throws RemoteException {
            synchronized (IpSecService.this) {
                if (isReferenced()) {
                    throw new IllegalStateException(
                            "Cannot release a resource that has active references!");
                }

                if (mResourceId == INVALID_RESOURCE_ID) {
                    return;
                }

                releaseResources();
                getResourceTracker().give();
                if (mBinder != null) {
                    mBinder.unlinkToDeath(this, 0);
                }
                mBinder = null;

                mResourceId = INVALID_RESOURCE_ID;
            }
        }

        /**
         * If the Binder object dies, this function is called to free the system resources that are
         * being managed by this record and to subsequently release this record for garbage
         * collection
         */
        public final void binderDied() {
            try {
                release();
            } catch (Exception e) {
                Log.e(TAG, "Failed to release resource: " + e);
            }
        }

        /**
         * Implement this method to release all system resources that are being protected by this
         * record. Once the resources are released, the record should be invalidated and no longer
         * used by calling release(). This should NEVER be called directly.
         *
         * <p>Calls to this are always guarded by IpSecService#this
         */
        protected abstract void releaseResources() throws RemoteException;

        /** Get the resource tracker for this resource */
        protected abstract ResourceTracker getResourceTracker();

        @Override
        public String toString() {
            return new StringBuilder()
                    .append("{mResourceId=")
                    .append(mResourceId)
                    .append(", pid=")
                    .append(pid)
                    .append(", uid=")
                    .append(uid)
                    .append(", mReferenceCount=")
                    .append(mReferenceCount.get())
                    .append("}")
                    .toString();
        }
    };

    /**
     * Minimal wrapper around SparseArray that performs ownership validation on element accesses.
     */
    private class ManagedResourceArray<T extends ManagedResource> {
        SparseArray<T> mArray = new SparseArray<>();

        T getAndCheckOwner(int key) {
            T val = mArray.get(key);
            // The value should never be null unless the resource doesn't exist
            // (since we do not allow null resources to be added).
            if (val != null) {
                val.checkOwnerOrSystem();
            }
            return val;
        }

        void put(int key, T obj) {
            checkNotNull(obj, "Null resources cannot be added");
            mArray.put(key, obj);
        }

        void remove(int key) {
            mArray.remove(key);
        }

        @Override
        public String toString() {
            return mArray.toString();
        }
    }

    private final class TransformRecord extends ManagedResource {
        private final IpSecConfig mConfig;
        private final SpiRecord[] mSpis;
        private final UdpSocketRecord mSocket;

        TransformRecord(
                int resourceId,
                IBinder binder,
                IpSecConfig config,
                SpiRecord[] spis,
                UdpSocketRecord socket) {
            super(resourceId, binder);
            mConfig = config;
            mSpis = spis;
            mSocket = socket;

            for (int direction : DIRECTIONS) {
                mSpis[direction].addReference();
                mSpis[direction].setOwnedByTransform();
            }

            if (mSocket != null) {
                mSocket.addReference();
            }
        }

        public IpSecConfig getConfig() {
            return mConfig;
        }

        public SpiRecord getSpiRecord(int direction) {
            return mSpis[direction];
        }

        /** always guarded by IpSecService#this */
        @Override
        protected void releaseResources() {
            for (int direction : DIRECTIONS) {
                int spi = mSpis[direction].getSpi();
                try {
                    mSrvConfig
                            .getNetdInstance()
                            .ipSecDeleteSecurityAssociation(
                                    mResourceId,
                                    direction,
                                    mConfig.getLocalAddress(),
                                    mConfig.getRemoteAddress(),
                                    spi);
                } 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 SA with ID: " + mResourceId);
                }
            }

            for (int direction : DIRECTIONS) {
                mSpis[direction].removeReference();
            }

            if (mSocket != null) {
                mSocket.removeReference();
            }
        }

        protected ResourceTracker getResourceTracker() {
            return mUserQuotaTracker.getUserRecord(this.uid).transform;
        }

        @Override
        public String toString() {
            StringBuilder strBuilder = new StringBuilder();
            strBuilder
                    .append("{super=")
                    .append(super.toString())
                    .append(", mSocket=")
                    .append(mSocket)
                    .append(", mSpis[OUT].mResourceId=")
                    .append(mSpis[IpSecTransform.DIRECTION_OUT].mResourceId)
                    .append(", mSpis[IN].mResourceId=")
                    .append(mSpis[IpSecTransform.DIRECTION_IN].mResourceId)
                    .append(", mConfig=")
                    .append(mConfig)
                    .append("}");
            return strBuilder.toString();
        }
    }

    private final class SpiRecord extends ManagedResource {
        private final int mDirection;
        private final String mLocalAddress;
        private final String mRemoteAddress;
        private int mSpi;

        private boolean mOwnedByTransform = false;

        SpiRecord(
                int resourceId,
                IBinder binder,
                int direction,
                String localAddress,
                String remoteAddress,
                int spi) {
            super(resourceId, binder);
            mDirection = direction;
            mLocalAddress = localAddress;
            mRemoteAddress = remoteAddress;
            mSpi = spi;
        }

        /** always guarded by IpSecService#this */
        @Override
        protected void releaseResources() {
            if (mOwnedByTransform) {
                Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform");
                // Because SPIs are "handed off" to transform, objects, they should never be
                // freed from the SpiRecord once used in a transform. (They refer to the same SA,
                // thus ownership and responsibility for freeing these resources passes to the
                // Transform object). Thus, we should let the user free them without penalty once
                // they are applied in a Transform object.
                return;
            }

            try {
                mSrvConfig
                        .getNetdInstance()
                        .ipSecDeleteSecurityAssociation(
                                mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi);
            } 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 SPI reservation with ID: " + mResourceId);
            }

            mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
        }

        @Override
        protected ResourceTracker getResourceTracker() {
            return mUserQuotaTracker.getUserRecord(this.uid).spi;
        }

        public int getSpi() {
            return mSpi;
        }

        public void setOwnedByTransform() {
            if (mOwnedByTransform) {
                // Programming error
                throw new IllegalStateException("Cannot own an SPI twice!");
            }

            mOwnedByTransform = true;
        }

        @Override
        public String toString() {
            StringBuilder strBuilder = new StringBuilder();
            strBuilder
                    .append("{super=")
                    .append(super.toString())
                    .append(", mSpi=")
                    .append(mSpi)
                    .append(", mDirection=")
                    .append(mDirection)
                    .append(", mLocalAddress=")
                    .append(mLocalAddress)
                    .append(", mRemoteAddress=")
                    .append(mRemoteAddress)
                    .append(", mOwnedByTransform=")
                    .append(mOwnedByTransform)
                    .append("}");
            return strBuilder.toString();
        }
    }

    private final class UdpSocketRecord extends ManagedResource {
        private FileDescriptor mSocket;
        private final int mPort;

        UdpSocketRecord(int resourceId, IBinder binder, FileDescriptor socket, int port) {
            super(resourceId, binder);
            mSocket = socket;
            mPort = port;
        }

        /** always guarded by IpSecService#this */
        @Override
        protected void releaseResources() {
            Log.d(TAG, "Closing port " + mPort);
            IoUtils.closeQuietly(mSocket);
            mSocket = null;
        }

        @Override
        protected ResourceTracker getResourceTracker() {
            return mUserQuotaTracker.getUserRecord(this.uid).socket;
        }

        public int getPort() {
            return mPort;
        }

        public FileDescriptor getSocket() {
            return mSocket;
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append("{super=")
                    .append(super.toString())
                    .append(", mSocket=")
                    .append(mSocket)
                    .append(", mPort=")
                    .append(mPort)
                    .append("}")
                    .toString();
        }
    }

    /**
     * Constructs a new IpSecService instance
     *
     * @param context Binder context for this service
     */
    private IpSecService(Context context) {
        this(context, IpSecServiceConfiguration.GETSRVINSTANCE);
    }

    static IpSecService create(Context context) throws InterruptedException {
        final IpSecService service = new IpSecService(context);
        service.connectNativeNetdService();
        return service;
    }

    /** @hide */
    @VisibleForTesting
    public IpSecService(Context context, IpSecServiceConfiguration config) {
        mContext = context;
        mSrvConfig = config;
    }

    public void systemReady() {
        if (isNetdAlive()) {
            Slog.d(TAG, "IpSecService is ready");
        } else {
            Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
        }
    }

    private void connectNativeNetdService() {
        // Avoid blocking the system server to do this
        new Thread() {
            @Override
            public void run() {
                synchronized (IpSecService.this) {
                    NetdService.get(NETD_FETCH_TIMEOUT_MS);
                }
            }
        }.start();
    }

    synchronized boolean isNetdAlive() {
        try {
            final INetd netd = mSrvConfig.getNetdInstance();
            if (netd == null) {
                return false;
            }
            return netd.isAlive();
        } catch (RemoteException re) {
            return false;
        }
    }

    /**
     * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
     * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
     */
    private static void checkInetAddress(String inetAddress) {
        if (TextUtils.isEmpty(inetAddress)) {
            throw new IllegalArgumentException("Unspecified address");
        }

        InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress);

        if (checkAddr.isAnyLocalAddress()) {
            throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
        }
    }

    /**
     * Checks the user-provided direction field and throws an IllegalArgumentException if it is not
     * DIRECTION_IN or DIRECTION_OUT
     */
    private static void checkDirection(int direction) {
        switch (direction) {
            case IpSecTransform.DIRECTION_OUT:
            case IpSecTransform.DIRECTION_IN:
                return;
        }
        throw new IllegalArgumentException("Invalid Direction: " + direction);
    }

    @Override
    /** Get a new SPI and maintain the reservation in the system server */
    public synchronized IpSecSpiResponse reserveSecurityParameterIndex(
            int direction, String remoteAddress, int requestedSpi, IBinder binder)
            throws RemoteException {
        checkDirection(direction);
        checkInetAddress(remoteAddress);
        /* requestedSpi can be anything in the int range, so no check is needed. */
        checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex");

        int resourceId = mNextResourceId.getAndIncrement();

        int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
        String localAddress = "";

        try {
            if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) {
                return new IpSecSpiResponse(
                        IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
            }
            spi =
                    mSrvConfig
                            .getNetdInstance()
                            .ipSecAllocateSpi(
                                    resourceId,
                                    direction,
                                    localAddress,
                                    remoteAddress,
                                    requestedSpi);
            Log.d(TAG, "Allocated SPI " + spi);
            mSpiRecords.put(
                    resourceId,
                    new SpiRecord(resourceId, binder, direction, localAddress, remoteAddress, spi));
        } catch (ServiceSpecificException e) {
            // TODO: Add appropriate checks when other ServiceSpecificException types are supported
            return new IpSecSpiResponse(
                    IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, spi);
    }

    /* This method should only be called from Binder threads. Do not call this from
     * within the system server as it will crash the system on failure.
     */
    private synchronized <T extends ManagedResource> void releaseManagedResource(
            ManagedResourceArray<T> resArray, int resourceId, String typeName)
            throws RemoteException {
        // We want to non-destructively get so that we can check credentials before removing
        // this from the records.
        T record = resArray.getAndCheckOwner(resourceId);

        if (record == null) {
            throw new IllegalArgumentException(
                    typeName + " " + resourceId + " is not available to be deleted");
        }

        record.release();
        resArray.remove(resourceId);
    }

    /** Release a previously allocated SPI that has been registered with the system server */
    @Override
    public void releaseSecurityParameterIndex(int resourceId) throws RemoteException {
        releaseManagedResource(mSpiRecords, resourceId, "SecurityParameterIndex");
    }

    /**
     * This function finds and forcibly binds to a random system port, ensuring that the port cannot
     * be unbound.
     *
     * <p>A socket cannot be un-bound from a port if it was bound to that port by number. To select
     * a random open port and then bind by number, this function creates a temp socket, binds to a
     * random port (specifying 0), gets that port number, and then uses is to bind the user's UDP
     * Encapsulation Socket forcibly, so that it cannot be un-bound by the user with the returned
     * FileHandle.
     *
     * <p>The loop in this function handles the inherent race window between un-binding to a port
     * and re-binding, during which the system could *technically* hand that port out to someone
     * else.
     */
    private int bindToRandomPort(FileDescriptor sockFd) throws IOException {
        for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) {
            try {
                FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                Os.bind(probeSocket, INADDR_ANY, 0);
                int port = ((InetSocketAddress) Os.getsockname(probeSocket)).getPort();
                Os.close(probeSocket);
                Log.v(TAG, "Binding to port " + port);
                Os.bind(sockFd, INADDR_ANY, port);
                return port;
            } catch (ErrnoException e) {
                // Someone miraculously claimed the port just after we closed probeSocket.
                if (e.errno == OsConstants.EADDRINUSE) {
                    continue;
                }
                throw e.rethrowAsIOException();
            }
        }
        throw new IOException("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
    }

    /**
     * Open a socket via the system server and bind it to the specified port (random if port=0).
     * This will return a PFD to the user that represent a bound UDP socket. The system server will
     * cache the socket and a record of its owner so that it can and must be freed when no longer
     * needed.
     */
    @Override
    public synchronized IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, IBinder binder)
            throws RemoteException {
        if (port != 0 && (port < FREE_PORT_MIN || port > PORT_MAX)) {
            throw new IllegalArgumentException(
                    "Specified port number must be a valid non-reserved UDP port");
        }
        checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");

        int resourceId = mNextResourceId.getAndIncrement();
        FileDescriptor sockFd = null;
        try {
            if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).socket.isAvailable()) {
                return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
            }

            sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

            if (port != 0) {
                Log.v(TAG, "Binding to port " + port);
                Os.bind(sockFd, INADDR_ANY, port);
            } else {
                port = bindToRandomPort(sockFd);
            }
            // This code is common to both the unspecified and specified port cases
            Os.setsockoptInt(
                    sockFd,
                    OsConstants.IPPROTO_UDP,
                    OsConstants.UDP_ENCAP,
                    OsConstants.UDP_ENCAP_ESPINUDP);

            mUdpSocketRecords.put(
                    resourceId, new UdpSocketRecord(resourceId, binder, sockFd, port));
            return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, sockFd);
        } catch (IOException | ErrnoException e) {
            IoUtils.closeQuietly(sockFd);
        }
        // If we make it to here, then something has gone wrong and we couldn't open a socket.
        // The only reasonable condition that would cause that is resource unavailable.
        return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
    }

    /** close a socket that has been been allocated by and registered with the system server */
    @Override
    public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException {

        releaseManagedResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket");
    }

    /**
     * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
     * IllegalArgumentException if they are not.
     */
    private void checkIpSecConfig(IpSecConfig config) {
        if (config.getLocalAddress() == null) {
            throw new IllegalArgumentException("Invalid null Local InetAddress");
        }

        if (config.getRemoteAddress() == null) {
            throw new IllegalArgumentException("Invalid null Remote InetAddress");
        }

        switch (config.getMode()) {
            case IpSecTransform.MODE_TRANSPORT:
                if (!config.getLocalAddress().isEmpty()) {
                    throw new IllegalArgumentException("Non-empty Local Address");
                }
                // Must be valid, and not a wildcard
                checkInetAddress(config.getRemoteAddress());
                break;
            case IpSecTransform.MODE_TUNNEL:
                break;
            default:
                throw new IllegalArgumentException(
                        "Invalid IpSecTransform.mode: " + config.getMode());
        }

        switch (config.getEncapType()) {
            case IpSecTransform.ENCAP_NONE:
                break;
            case IpSecTransform.ENCAP_ESPINUDP:
            case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
                if (mUdpSocketRecords.getAndCheckOwner(
                            config.getEncapSocketResourceId()) == null) {
                    throw new IllegalStateException(
                            "No Encapsulation socket for Resource Id: "
                                    + config.getEncapSocketResourceId());
                }

                int port = config.getEncapRemotePort();
                if (port <= 0 || port > 0xFFFF) {
                    throw new IllegalArgumentException("Invalid remote UDP port: " + port);
                }
                break;
            default:
                throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
        }

        for (int direction : DIRECTIONS) {
            IpSecAlgorithm crypt = config.getEncryption(direction);
            IpSecAlgorithm auth = config.getAuthentication(direction);
            IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction);
            if (authenticatedEncryption == null && crypt == null && auth == null) {
                throw new IllegalArgumentException(
                        "No Encryption or Authentication algorithms specified");
            } else if (authenticatedEncryption != null && (auth != null || crypt != null)) {
                throw new IllegalArgumentException(
                        "Authenticated Encryption is mutually"
                                + " exclusive with other Authentication or Encryption algorithms");
            }

            if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) {
                throw new IllegalStateException("No SPI for specified Resource Id");
            }
        }
    }

    /**
     * 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 createTransportModeTransform(
            IpSecConfig c, IBinder binder) throws RemoteException {
        checkIpSecConfig(c);
        checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
        int resourceId = mNextResourceId.getAndIncrement();
        if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) {
            return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
        }
        SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];

        int encapType, encapLocalPort = 0, encapRemotePort = 0;
        UdpSocketRecord socketRecord = null;
        encapType = c.getEncapType();
        if (encapType != IpSecTransform.ENCAP_NONE) {
            socketRecord = mUdpSocketRecords.getAndCheckOwner(c.getEncapSocketResourceId());
            encapLocalPort = socketRecord.getPort();
            encapRemotePort = c.getEncapRemotePort();
        }

        for (int direction : DIRECTIONS) {
            IpSecAlgorithm auth = c.getAuthentication(direction);
            IpSecAlgorithm crypt = c.getEncryption(direction);
            IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction);

            spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction));
            int spi = spis[direction].getSpi();
            try {
                mSrvConfig
                        .getNetdInstance()
                        .ipSecAddSecurityAssociation(
                                resourceId,
                                c.getMode(),
                                direction,
                                c.getLocalAddress(),
                                c.getRemoteAddress(),
                                (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0,
                                spi,
                                (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) {
                // 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
        mTransformRecords.put(
                resourceId, new TransformRecord(resourceId, binder, c, spis, socketRecord));
        return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
    }

    /**
     * Delete a transport mode transform that was previously allocated by + registered with the
     * system server. If this is called on an inactive (or non-existent) transform, it will not
     * return an error. It's safe to de-allocate transforms that may have already been deleted for
     * other reasons.
     */
    @Override
    public void deleteTransportModeTransform(int resourceId) throws RemoteException {
        releaseManagedResource(mTransformRecords, resourceId, "IpSecTransform");
    }

    /**
     * Apply an active transport mode transform to a socket, which will apply the IPsec security
     * association as a correspondent policy to the provided socket
     */
    @Override
    public synchronized void applyTransportModeTransform(
            ParcelFileDescriptor socket, int resourceId) throws RemoteException {
        // Synchronize liberally here because we are using ManagedResources in this block
        TransformRecord info;
        // FIXME: this code should be factored out into a security check + getter
        info = mTransformRecords.getAndCheckOwner(resourceId);

        if (info == null) {
            throw new IllegalArgumentException("Transform " + resourceId + " is not active");
        }

        // TODO: make this a function.
        if (info.pid != getCallingPid() || info.uid != getCallingUid()) {
            throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
        }

        IpSecConfig c = info.getConfig();
        try {
            for (int direction : DIRECTIONS) {
                mSrvConfig
                        .getNetdInstance()
                        .ipSecApplyTransportModeTransform(
                                socket.getFileDescriptor(),
                                resourceId,
                                direction,
                                c.getLocalAddress(),
                                c.getRemoteAddress(),
                                info.getSpiRecord(direction).getSpi());
            }
        } catch (ServiceSpecificException e) {
            // FIXME: get the error code and throw is at an IOException from Errno Exception
        }
    }

    /**
     * Remove a transport mode transform from a socket, applying the default (empty) policy. This
     * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of
     * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not
     * used: reserved for future improved input validation.
     */
    @Override
    public void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId)
            throws RemoteException {
        try {
            mSrvConfig
                    .getNetdInstance()
                    .ipSecRemoveTransportModeTransform(socket.getFileDescriptor());
        } catch (ServiceSpecificException e) {
            // FIXME: get the error code and throw is at an IOException from Errno Exception
        }
    }

    @Override
    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        mContext.enforceCallingOrSelfPermission(DUMP, TAG);

        pw.println("IpSecService dump:");
        pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead"));
        pw.println();

        pw.println("mUserQuotaTracker:");
        pw.println(mUserQuotaTracker);
        pw.println("mTransformRecords:");
        pw.println(mTransformRecords);
        pw.println("mUdpSocketRecords:");
        pw.println(mUdpSocketRecords);
        pw.println("mSpiRecords:");
        pw.println(mSpiRecords);
    }
}
