/*
 * 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 android.net;

import static android.net.IpSecManager.INVALID_RESOURCE_ID;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import dalvik.system.CloseGuard;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;

/**
 * This class represents a transform, which roughly corresponds to an IPsec Security Association.
 *
 * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
 * object encapsulates the properties and state of an IPsec security association. That includes,
 * but is not limited to, algorithm choice, key material, and allocated system resources.
 *
 * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
 *     Internet Protocol</a>
 */
public final class IpSecTransform implements AutoCloseable {
    private static final String TAG = "IpSecTransform";

    /** @hide */
    public static final int MODE_TRANSPORT = 0;

    /** @hide */
    public static final int MODE_TUNNEL = 1;

    /** @hide */
    public static final int ENCAP_NONE = 0;

    /**
     * IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
     * header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
     *
     * @hide
     */
    public static final int ENCAP_ESPINUDP_NON_IKE = 1;

    /**
     * IPsec traffic will be encapsulated within UDP as per
     * <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
     *
     * @hide
     */
    public static final int ENCAP_ESPINUDP = 2;

    /** @hide */
    @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface EncapType {}

    /** @hide */
    @VisibleForTesting
    public IpSecTransform(Context context, IpSecConfig config) {
        mContext = context;
        mConfig = new IpSecConfig(config);
        mResourceId = INVALID_RESOURCE_ID;
    }

    private IIpSecService getIpSecService() {
        IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
        if (b == null) {
            throw new RemoteException("Failed to connect to IpSecService")
                    .rethrowAsRuntimeException();
        }

        return IIpSecService.Stub.asInterface(b);
    }

    /**
     * Checks the result status and throws an appropriate exception if the status is not Status.OK.
     */
    private void checkResultStatus(int status)
            throws IOException, IpSecManager.ResourceUnavailableException,
                    IpSecManager.SpiUnavailableException {
        switch (status) {
            case IpSecManager.Status.OK:
                return;
                // TODO: Pass Error string back from bundle so that errors can be more specific
            case IpSecManager.Status.RESOURCE_UNAVAILABLE:
                throw new IpSecManager.ResourceUnavailableException(
                        "Failed to allocate a new IpSecTransform");
            case IpSecManager.Status.SPI_UNAVAILABLE:
                Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
                // Fall through
            default:
                throw new IllegalStateException(
                        "Failed to Create a Transform with status code " + status);
        }
    }

    private IpSecTransform activate()
            throws IOException, IpSecManager.ResourceUnavailableException,
                    IpSecManager.SpiUnavailableException {
        synchronized (this) {
            try {
                IIpSecService svc = getIpSecService();
                IpSecTransformResponse result = svc.createTransform(
                        mConfig, new Binder(), mContext.getOpPackageName());
                int status = result.status;
                checkResultStatus(status);
                mResourceId = result.resourceId;
                Log.d(TAG, "Added Transform with Id " + mResourceId);
                mCloseGuard.open("build");
            } catch (ServiceSpecificException e) {
                throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }

        return this;
    }

    /**
     * Standard equals.
     */
    public boolean equals(Object other) {
        if (this == other) return true;
        if (!(other instanceof IpSecTransform)) return false;
        final IpSecTransform rhs = (IpSecTransform) other;
        return getConfig().equals(rhs.getConfig()) && mResourceId == rhs.mResourceId;
    }

    /**
     * Deactivate this {@code IpSecTransform} and free allocated resources.
     *
     * <p>Deactivating a transform while it is still applied to a socket will result in errors on
     * that socket. Make sure to remove transforms by calling {@link
     * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
     * socket will not deactivate it (because one transform may be applied to multiple sockets).
     *
     * <p>It is safe to call this method on a transform that has already been deactivated.
     */
    public void close() {
        Log.d(TAG, "Removing Transform with Id " + mResourceId);

        // Always safe to attempt cleanup
        if (mResourceId == INVALID_RESOURCE_ID) {
            mCloseGuard.close();
            return;
        }
        try {
            IIpSecService svc = getIpSecService();
            svc.deleteTransform(mResourceId);
            stopNattKeepalive();
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        } catch (Exception e) {
            // On close we swallow all random exceptions since failure to close is not
            // actionable by the user.
            Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
        } finally {
            mResourceId = INVALID_RESOURCE_ID;
            mCloseGuard.close();
        }
    }

    /** Check that the transform was closed properly. */
    @Override
    protected void finalize() throws Throwable {
        if (mCloseGuard != null) {
            mCloseGuard.warnIfOpen();
        }
        close();
    }

    /* Package */
    IpSecConfig getConfig() {
        return mConfig;
    }

    private final IpSecConfig mConfig;
    private int mResourceId;
    private final Context mContext;
    private final CloseGuard mCloseGuard = CloseGuard.get();
    private ConnectivityManager.PacketKeepalive mKeepalive;
    private Handler mCallbackHandler;
    private final ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
            new ConnectivityManager.PacketKeepaliveCallback() {

                @Override
                public void onStarted() {
                    synchronized (this) {
                        mCallbackHandler.post(() -> mUserKeepaliveCallback.onStarted());
                    }
                }

                @Override
                public void onStopped() {
                    synchronized (this) {
                        mKeepalive = null;
                        mCallbackHandler.post(() -> mUserKeepaliveCallback.onStopped());
                    }
                }

                @Override
                public void onError(int error) {
                    synchronized (this) {
                        mKeepalive = null;
                        mCallbackHandler.post(() -> mUserKeepaliveCallback.onError(error));
                    }
                }
            };

    private NattKeepaliveCallback mUserKeepaliveCallback;

    /** @hide */
    @VisibleForTesting
    public int getResourceId() {
        return mResourceId;
    }

    /**
     * A callback class to provide status information regarding a NAT-T keepalive session
     *
     * <p>Use this callback to receive status information regarding a NAT-T keepalive session
     * by registering it when calling {@link #startNattKeepalive}.
     *
     * @hide
     */
    public static class NattKeepaliveCallback {
        /** The specified {@code Network} is not connected. */
        public static final int ERROR_INVALID_NETWORK = 1;
        /** The hardware does not support this request. */
        public static final int ERROR_HARDWARE_UNSUPPORTED = 2;
        /** The hardware returned an error. */
        public static final int ERROR_HARDWARE_ERROR = 3;

        /** The requested keepalive was successfully started. */
        public void onStarted() {}
        /** The keepalive was successfully stopped. */
        public void onStopped() {}
        /** An error occurred. */
        public void onError(int error) {}
    }

    /**
     * Start a NAT-T keepalive session for the current transform.
     *
     * For a transform that is using UDP encapsulated IPv4, NAT-T offloading provides
     * a power efficient mechanism of sending NAT-T packets at a specified interval.
     *
     * @param userCallback a {@link #NattKeepaliveCallback} to receive asynchronous status
     *      information about the requested NAT-T keepalive session.
     * @param intervalSeconds the interval between NAT-T keepalives being sent. The
     *      the allowed range is between 20 and 3600 seconds.
     * @param handler a handler on which to post callbacks when received.
     *
     * @hide
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.MANAGE_IPSEC_TUNNELS,
            android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
    })
    public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback,
            int intervalSeconds, @NonNull Handler handler) throws IOException {
        checkNotNull(userCallback);
        if (intervalSeconds < 20 || intervalSeconds > 3600) {
            throw new IllegalArgumentException("Invalid NAT-T keepalive interval");
        }
        checkNotNull(handler);
        if (mResourceId == INVALID_RESOURCE_ID) {
            throw new IllegalStateException(
                    "Packet keepalive cannot be started for an inactive transform");
        }

        synchronized (mKeepaliveCallback) {
            if (mKeepaliveCallback != null) {
                throw new IllegalStateException("Keepalive already active");
            }

            mUserKeepaliveCallback = userCallback;
            ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
                    Context.CONNECTIVITY_SERVICE);
            mKeepalive = cm.startNattKeepalive(
                    mConfig.getNetwork(), intervalSeconds, mKeepaliveCallback,
                    NetworkUtils.numericToInetAddress(mConfig.getSourceAddress()),
                    4500, // FIXME urgently, we need to get the port number from the Encap socket
                    NetworkUtils.numericToInetAddress(mConfig.getDestinationAddress()));
            mCallbackHandler = handler;
        }
    }

    /**
     * Stop an ongoing NAT-T keepalive session.
     *
     * Calling this API will request that an ongoing NAT-T keepalive session be terminated.
     * If this API is not called when a Transform is closed, the underlying NAT-T session will
     * be terminated automatically.
     *
     * @hide
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.MANAGE_IPSEC_TUNNELS,
            android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD
    })
    public void stopNattKeepalive() {
        synchronized (mKeepaliveCallback) {
            if (mKeepalive == null) {
                Log.e(TAG, "No active keepalive to stop");
                return;
            }
            mKeepalive.stop();
        }
    }

    /** This class is used to build {@link IpSecTransform} objects. */
    public static class Builder {
        private Context mContext;
        private IpSecConfig mConfig;

        /**
         * Set the encryption algorithm.
         *
         * <p>Encryption is mutually exclusive with authenticated encryption.
         *
         * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
         */
        @NonNull
        public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
            // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
            Preconditions.checkNotNull(algo);
            mConfig.setEncryption(algo);
            return this;
        }

        /**
         * Set the authentication (integrity) algorithm.
         *
         * <p>Authentication is mutually exclusive with authenticated encryption.
         *
         * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
         */
        @NonNull
        public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
            // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
            Preconditions.checkNotNull(algo);
            mConfig.setAuthentication(algo);
            return this;
        }

        /**
         * Set the authenticated encryption algorithm.
         *
         * <p>The Authenticated Encryption (AE) class of algorithms are also known as
         * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
         * algorithms (as referred to in
         * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
         *
         * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
         *
         * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
         *     be applied.
         */
        @NonNull
        public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
            Preconditions.checkNotNull(algo);
            mConfig.setAuthenticatedEncryption(algo);
            return this;
        }

        /**
         * Add UDP encapsulation to an IPv4 transform.
         *
         * <p>This allows IPsec traffic to pass through a NAT.
         *
         * @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
         *     ESP Packets</a>
         * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
         *     NAT Traversal of IKEv2</a>
         * @param localSocket a socket for sending and receiving encapsulated traffic
         * @param remotePort the UDP port number of the remote host that will send and receive
         *     encapsulated traffic. In the case of IKEv2, this should be port 4500.
         */
        @NonNull
        public IpSecTransform.Builder setIpv4Encapsulation(
                @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
            Preconditions.checkNotNull(localSocket);
            mConfig.setEncapType(ENCAP_ESPINUDP);
            if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
                throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
            }
            mConfig.setEncapSocketResourceId(localSocket.getResourceId());
            mConfig.setEncapRemotePort(remotePort);
            return this;
        }

        /**
         * Build a transport mode {@link IpSecTransform}.
         *
         * <p>This builds and activates a transport mode transform. Note that an active transform
         * will not affect any network traffic until it has been applied to one or more sockets.
         *
         * @see IpSecManager#applyTransportModeTransform
         * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
         *     this transform; this address must belong to the Network used by all sockets that
         *     utilize this transform; if provided, then only traffic originating from the
         *     specified source address will be processed.
         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
         *     traffic
         * @throws IllegalArgumentException indicating that a particular combination of transform
         *     properties is invalid
         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
         *     are active
         * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
         *     collides with an existing transform
         * @throws IOException indicating other errors
         */
        @NonNull
        public IpSecTransform buildTransportModeTransform(
                @NonNull InetAddress sourceAddress,
                @NonNull IpSecManager.SecurityParameterIndex spi)
                throws IpSecManager.ResourceUnavailableException,
                        IpSecManager.SpiUnavailableException, IOException {
            Preconditions.checkNotNull(sourceAddress);
            Preconditions.checkNotNull(spi);
            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
            }
            mConfig.setMode(MODE_TRANSPORT);
            mConfig.setSourceAddress(sourceAddress.getHostAddress());
            mConfig.setSpiResourceId(spi.getResourceId());
            // FIXME: modifying a builder after calling build can change the built transform.
            return new IpSecTransform(mContext, mConfig).activate();
        }

        /**
         * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
         * parameters have interdependencies that are checked at build time.
         *
         * @param sourceAddress the {@link InetAddress} that provides the source address for this
         *     IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
         *     that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
         *     traffic
         * @throws IllegalArgumentException indicating that a particular combination of transform
         *     properties is invalid.
         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
         *     are active
         * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
         *     collides with an existing transform
         * @throws IOException indicating other errors
         * @hide
         */
        @SystemApi
        @NonNull
        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
        public IpSecTransform buildTunnelModeTransform(
                @NonNull InetAddress sourceAddress,
                @NonNull IpSecManager.SecurityParameterIndex spi)
                throws IpSecManager.ResourceUnavailableException,
                        IpSecManager.SpiUnavailableException, IOException {
            Preconditions.checkNotNull(sourceAddress);
            Preconditions.checkNotNull(spi);
            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
            }
            mConfig.setMode(MODE_TUNNEL);
            mConfig.setSourceAddress(sourceAddress.getHostAddress());
            mConfig.setSpiResourceId(spi.getResourceId());
            return new IpSecTransform(mContext, mConfig).activate();
        }

        /**
         * Create a new IpSecTransform.Builder.
         *
         * @param context current context
         */
        public Builder(@NonNull Context context) {
            Preconditions.checkNotNull(context);
            mContext = context;
            mConfig = new IpSecConfig();
        }
    }

    @Override
    public String toString() {
        return new StringBuilder()
            .append("IpSecTransform{resourceId=")
            .append(mResourceId)
            .append("}")
            .toString();
    }
}
