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

Commit 4f6ec3d1 authored by nharold's avatar nharold Committed by Gerrit Code Review
Browse files

Merge "Add UDP Encap Socket Support to IpSecManager"

parents 75b7ef15 8dc1fd02
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package android.net;

import android.net.Network;
import android.net.IpSecConfig;
import android.net.IpSecUdpEncapResponse;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransformResponse;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -27,16 +30,16 @@ import android.os.ParcelFileDescriptor;
 */
interface IIpSecService
{
    Bundle reserveSecurityParameterIndex(
    IpSecSpiResponse reserveSecurityParameterIndex(
            int direction, in String remoteAddress, int requestedSpi, in IBinder binder);

    void releaseSecurityParameterIndex(int resourceId);

    Bundle openUdpEncapsulationSocket(int port, in IBinder binder);
    IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder);

    void closeUdpEncapsulationSocket(in ParcelFileDescriptor socket);
    void closeUdpEncapsulationSocket(int resourceId);

    Bundle createTransportModeTransform(in IpSecConfig c, in IBinder binder);
    IpSecTransformResponse createTransportModeTransform(in IpSecConfig c, in IBinder binder);

    void deleteTransportModeTransform(int transformId);

+12 −12
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ public final class IpSecConfig implements Parcelable {
        // Minimum requirements for identifying a transform
        // SPI identifying the IPsec flow in packet processing
        // and a remote IP address
        int spi;
        int spiResourceId;

        // Encryption Algorithm
        IpSecAlgorithm encryption;
@@ -54,7 +54,7 @@ public final class IpSecConfig implements Parcelable {
    // For tunnel mode IPv4 UDP Encapsulation
    // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
    int encapType;
    int encapLocalPort;
    int encapLocalPortResourceId;
    int encapRemotePort;

    // An interval, in seconds between the NattKeepalive packets
@@ -69,8 +69,8 @@ public final class IpSecConfig implements Parcelable {
        return localAddress;
    }

    public int getSpi(int direction) {
        return flow[direction].spi;
    public int getSpiResourceId(int direction) {
        return flow[direction].spiResourceId;
    }

    public InetAddress getRemoteAddress() {
@@ -93,8 +93,8 @@ public final class IpSecConfig implements Parcelable {
        return encapType;
    }

    public int getEncapLocalPort() {
        return encapLocalPort;
    public int getEncapLocalResourceId() {
        return encapLocalPortResourceId;
    }

    public int getEncapRemotePort() {
@@ -119,14 +119,14 @@ public final class IpSecConfig implements Parcelable {
        // TODO: Use a byte array or other better method for storing IPs that can also include scope
        out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null);
        out.writeParcelable(network, flags);
        out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi);
        out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId);
        out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags);
        out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags);
        out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi);
        out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId);
        out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags);
        out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags);
        out.writeInt(encapType);
        out.writeInt(encapLocalPort);
        out.writeInt(encapLocalPortResourceId);
        out.writeInt(encapRemotePort);
    }

@@ -151,18 +151,18 @@ public final class IpSecConfig implements Parcelable {
        localAddress = readInetAddressFromParcel(in);
        remoteAddress = readInetAddressFromParcel(in);
        network = (Network) in.readParcelable(Network.class.getClassLoader());
        flow[IpSecTransform.DIRECTION_IN].spi = in.readInt();
        flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt();
        flow[IpSecTransform.DIRECTION_IN].encryption =
                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
        flow[IpSecTransform.DIRECTION_IN].authentication =
                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
        flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt();
        flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt();
        flow[IpSecTransform.DIRECTION_OUT].encryption =
                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
        flow[IpSecTransform.DIRECTION_OUT].authentication =
                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
        encapType = in.readInt();
        encapLocalPort = in.readInt();
        encapLocalPortResourceId = in.readInt();
        encapRemotePort = in.readInt();
    }

+99 −46
Original line number Diff line number Diff line
@@ -19,10 +19,10 @@ import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.NonNull;
import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.AndroidException;
import android.util.Log;
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -57,12 +57,6 @@ public final class IpSecManager {
        public static final int SPI_UNAVAILABLE = 2;
    }

    /** @hide */
    public static final String KEY_STATUS = "status";
    /** @hide */
    public static final String KEY_RESOURCE_ID = "resourceId";
    /** @hide */
    public static final String KEY_SPI = "spi";
    /** @hide */
    public static final int INVALID_RESOURCE_ID = 0;

@@ -128,7 +122,11 @@ public final class IpSecManager {
         */
        @Override
        public void close() {
            mSpi = INVALID_SECURITY_PARAMETER_INDEX;
            try {
                mService.releaseSecurityParameterIndex(mResourceId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            mCloseGuard.close();
        }

@@ -147,7 +145,7 @@ public final class IpSecManager {
            mService = service;
            mRemoteAddress = remoteAddress;
            try {
                Bundle result =
                IpSecSpiResponse result =
                        mService.reserveSecurityParameterIndex(
                                direction, remoteAddress.getHostAddress(), spi, new Binder());

@@ -155,7 +153,7 @@ public final class IpSecManager {
                    throw new NullPointerException("Received null response from IpSecService");
                }

                int status = result.getInt(KEY_STATUS);
                int status = result.status;
                switch (status) {
                    case Status.OK:
                        break;
@@ -168,8 +166,8 @@ public final class IpSecManager {
                        throw new RuntimeException(
                                "Unknown status returned by IpSecService: " + status);
                }
                mSpi = result.getInt(KEY_SPI);
                mResourceId = result.getInt(KEY_RESOURCE_ID);
                mSpi = result.spi;
                mResourceId = result.resourceId;

                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
@@ -185,6 +183,11 @@ public final class IpSecManager {
            }
            mCloseGuard.open("open");
        }

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

    /**
@@ -201,8 +204,7 @@ public final class IpSecManager {
     * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
     */
    public SecurityParameterIndex reserveSecurityParameterIndex(
            int direction, InetAddress remoteAddress)
            throws ResourceUnavailableException {
            int direction, InetAddress remoteAddress) throws ResourceUnavailableException {
        try {
            return new SecurityParameterIndex(
                    mService,
@@ -251,7 +253,9 @@ public final class IpSecManager {
     */
    public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
            throws IOException {
        applyTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
            applyTransportModeTransform(pfd, transform);
        }
    }

    /**
@@ -269,15 +273,8 @@ public final class IpSecManager {
     */
    public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
            throws IOException {
        applyTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
    }

    /* Call down to activate a transform */
    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
        try {
            mService.applyTransportModeTransform(pfd, transform.getResourceId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
            applyTransportModeTransform(pfd, transform);
        }
    }

@@ -295,7 +292,22 @@ public final class IpSecManager {
     */
    public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
            throws IOException {
        applyTransportModeTransform(new ParcelFileDescriptor(socket), transform);
        // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
        // constructor takes control and closes the user's FD when we exit the method
        // This is behaviorally the same as the other versions, but the PFD constructor does not
        // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup().
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
            applyTransportModeTransform(pfd, transform);
        }
    }

    /* Call down to activate a transform */
    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
        try {
            mService.applyTransportModeTransform(pfd, transform.getResourceId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
@@ -324,7 +336,9 @@ public final class IpSecManager {
     */
    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
            throws IOException {
        removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) {
            removeTransportModeTransform(pfd, transform);
        }
    }

    /**
@@ -340,7 +354,9 @@ public final class IpSecManager {
     */
    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
            throws IOException {
        removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) {
            removeTransportModeTransform(pfd, transform);
        }
    }

    /**
@@ -355,7 +371,9 @@ public final class IpSecManager {
     */
    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
            throws IOException {
        removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
            removeTransportModeTransform(pfd, transform);
        }
    }

    /* Call down to activate a transform */
@@ -388,33 +406,48 @@ public final class IpSecManager {
     * FileDescriptor. Instead, disposing of this socket requires a call to close().
     */
    public static final class UdpEncapsulationSocket implements AutoCloseable {
        private final FileDescriptor mFd;
        private final ParcelFileDescriptor mPfd;
        private final IIpSecService mService;
        private final int mResourceId;
        private final int mPort;
        private final CloseGuard mCloseGuard = CloseGuard.get();

        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
                throws ResourceUnavailableException {
                throws ResourceUnavailableException, IOException {
            mService = service;
            mCloseGuard.open("constructor");
            // TODO: go down to the kernel and get a socket on the specified
            mFd = new FileDescriptor();
            try {
                IpSecUdpEncapResponse result =
                        mService.openUdpEncapsulationSocket(port, new Binder());
                switch (result.status) {
                    case Status.OK:
                        break;
                    case Status.RESOURCE_UNAVAILABLE:
                        throw new ResourceUnavailableException(
                                "No more Sockets may be allocated by this requester.");
                    default:
                        throw new RuntimeException(
                                "Unknown status returned by IpSecService: " + result.status);
                }
                mResourceId = result.resourceId;
                mPort = result.port;
                mPfd = result.fileDescriptor;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }

        private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException {
            mService = service;
            mCloseGuard.open("constructor");
            // TODO: go get a random socket on a random port
            mFd = new FileDescriptor();
        }

        /** Access the inner UDP Encapsulation Socket */
        public FileDescriptor getSocket() {
            return mFd;
            if (mPfd == null) {
                return null;
            }
            return mPfd.getFileDescriptor();
        }

        /** Retrieve the port number of the inner encapsulation socket */
        public int getPort() {
            return 0; // TODO get the port number from the Socket;
            return mPort;
        }

        @Override
@@ -429,7 +462,18 @@ public final class IpSecManager {
         * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
         */
        public void close() throws IOException {
            // TODO: Go close the socket
            try {
                mService.closeUdpEncapsulationSocket(mResourceId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }

            try {
                mPfd.close();
            } catch (IOException e) {
                Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
                throw e;
            }
            mCloseGuard.close();
        }

@@ -438,9 +482,13 @@ public final class IpSecManager {
            if (mCloseGuard != null) {
                mCloseGuard.warnIfOpen();
            }

            close();
        }

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

    /**
@@ -467,7 +515,13 @@ public final class IpSecManager {
    // socket.
    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
            throws IOException, ResourceUnavailableException {
        // Temporary code
        /*
         * Most range checking is done in the service, but this version of the constructor expects
         * a valid port number, and zero cannot be checked after being passed to the service.
         */
        if (port == 0) {
            throw new IllegalArgumentException("Specified port must be a valid port number!");
        }
        return new UdpEncapsulationSocket(mService, port);
    }

@@ -491,8 +545,7 @@ public final class IpSecManager {
    // socket.
    public UdpEncapsulationSocket openUdpEncapsulationSocket()
            throws IOException, ResourceUnavailableException {
        // Temporary code
        return new UdpEncapsulationSocket(mService);
        return new UdpEncapsulationSocket(mService, 0);
    }

    /**
+20 −0
Original line number Diff line number Diff line
/*
 * 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;

/** @hide */
parcelable IpSecSpiResponse;
+78 −0
Original line number Diff line number Diff line
/*
 * 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 android.os.Parcel;
import android.os.Parcelable;

/**
 * This class is used to return an SPI and corresponding status from the IpSecService to an
 * IpSecManager.SecurityParameterIndex.
 *
 * @hide
 */
public final class IpSecSpiResponse implements Parcelable {
    private static final String TAG = "IpSecSpiResponse";

    public final int resourceId;
    public final int status;
    public final int spi;
    // Parcelable Methods

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(status);
        out.writeInt(resourceId);
        out.writeInt(spi);
    }

    public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) {
        status = inStatus;
        resourceId = inResourceId;
        spi = inSpi;
    }

    public IpSecSpiResponse(int inStatus) {
        if (inStatus == IpSecManager.Status.OK) {
            throw new IllegalArgumentException("Valid status implies other args must be provided");
        }
        status = inStatus;
        resourceId = IpSecManager.INVALID_RESOURCE_ID;
        spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
    }

    private IpSecSpiResponse(Parcel in) {
        status = in.readInt();
        resourceId = in.readInt();
        spi = in.readInt();
    }

    public static final Parcelable.Creator<IpSecSpiResponse> CREATOR =
            new Parcelable.Creator<IpSecSpiResponse>() {
                public IpSecSpiResponse createFromParcel(Parcel in) {
                    return new IpSecSpiResponse(in);
                }

                public IpSecSpiResponse[] newArray(int size) {
                    return new IpSecSpiResponse[size];
                }
            };
}
Loading