IpSecManager.java revision 93962f34ce21f5aac825afbcebf2f3e8c7a30910
1330e1089da80cddcd68758512370d217b19f8890Nathan Harold/*
2330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Copyright (C) 2017 The Android Open Source Project
3330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
4330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Licensed under the Apache License, Version 2.0 (the "License");
5330e1089da80cddcd68758512370d217b19f8890Nathan Harold * you may not use this file except in compliance with the License.
6330e1089da80cddcd68758512370d217b19f8890Nathan Harold * You may obtain a copy of the License at
7330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
8330e1089da80cddcd68758512370d217b19f8890Nathan Harold *      http://www.apache.org/licenses/LICENSE-2.0
9330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
10330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Unless required by applicable law or agreed to in writing, software
11330e1089da80cddcd68758512370d217b19f8890Nathan Harold * distributed under the License is distributed on an "AS IS" BASIS,
12330e1089da80cddcd68758512370d217b19f8890Nathan Harold * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13330e1089da80cddcd68758512370d217b19f8890Nathan Harold * See the License for the specific language governing permissions and
14330e1089da80cddcd68758512370d217b19f8890Nathan Harold * limitations under the License.
15330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
16330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpackage android.net;
17330e1089da80cddcd68758512370d217b19f8890Nathan Harold
18330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport static com.android.internal.util.Preconditions.checkNotNull;
19330e1089da80cddcd68758512370d217b19f8890Nathan Harold
2093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull;
2193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder;
2293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Bundle;
23330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor;
2493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException;
25330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException;
26330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard;
27330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor;
28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException;
29330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket;
30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress;
31330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket;
32330e1089da80cddcd68758512370d217b19f8890Nathan Harold
33330e1089da80cddcd68758512370d217b19f8890Nathan Harold/**
34330e1089da80cddcd68758512370d217b19f8890Nathan Harold * This class contains methods for managing IPsec sessions, which will perform kernel-space
35330e1089da80cddcd68758512370d217b19f8890Nathan Harold * encryption and decryption of socket or Network traffic.
36330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
37330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>An IpSecManager may be obtained by calling {@link
38330e1089da80cddcd68758512370d217b19f8890Nathan Harold * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
39330e1089da80cddcd68758512370d217b19f8890Nathan Harold * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
40330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
41330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager {
42330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final String TAG = "IpSecManager";
43330e1089da80cddcd68758512370d217b19f8890Nathan Harold
44330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
4593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
4693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     *
4793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * <p>No IPsec packet may contain an SPI of 0.
4893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     */
4993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
5093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
5193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
5293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public interface Status {
5393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int OK = 0;
5493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int RESOURCE_UNAVAILABLE = 1;
5593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int SPI_UNAVAILABLE = 2;
5693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
5793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
5893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
5993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final String KEY_STATUS = "status";
6093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
6193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final String KEY_RESOURCE_ID = "resourceId";
6293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
6393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final String KEY_SPI = "spi";
6493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
6593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public static final int INVALID_RESOURCE_ID = 0;
6693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
6793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /**
68330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Indicates that the combination of remote InetAddress and SPI was non-unique for a given
69330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * request. If encountered, selection of a new SPI is required before a transform may be
70330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random
71330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * or reserved using reserveSecurityParameterIndex.
72330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
73330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SpiUnavailableException extends AndroidException {
74330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final int mSpi;
75330e1089da80cddcd68758512370d217b19f8890Nathan Harold
76330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
77330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Construct an exception indicating that a transform with the given SPI is already in use
78330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * or otherwise unavailable.
79330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
80330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param msg Description indicating the colliding SPI
81330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param spi the SPI that could not be used due to a collision
82330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
83330e1089da80cddcd68758512370d217b19f8890Nathan Harold        SpiUnavailableException(String msg, int spi) {
84330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg + "(spi: " + spi + ")");
85330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mSpi = spi;
86330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
87330e1089da80cddcd68758512370d217b19f8890Nathan Harold
88330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Retrieve the SPI that caused a collision */
89330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
90330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
91330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
92330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
93330e1089da80cddcd68758512370d217b19f8890Nathan Harold
94330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
95330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Indicates that the requested system resource for IPsec, such as a socket or other system
96330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * resource is unavailable. If this exception is thrown, try releasing allocated objects of the
97330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * type requested.
98330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
99330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class ResourceUnavailableException extends AndroidException {
100330e1089da80cddcd68758512370d217b19f8890Nathan Harold
101330e1089da80cddcd68758512370d217b19f8890Nathan Harold        ResourceUnavailableException(String msg) {
102330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg);
103330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
104330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
105330e1089da80cddcd68758512370d217b19f8890Nathan Harold
1061afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    private final IIpSecService mService;
107330e1089da80cddcd68758512370d217b19f8890Nathan Harold
108330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SecurityParameterIndex implements AutoCloseable {
1091afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
110c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold        private final InetAddress mRemoteAddress;
111330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
11293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
11393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mResourceId;
114330e1089da80cddcd68758512370d217b19f8890Nathan Harold
115330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Return the underlying SPI held by this object */
116330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
117330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
118330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
119330e1089da80cddcd68758512370d217b19f8890Nathan Harold
120330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
121330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release an SPI that was previously reserved.
122330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
123c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
124c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * applied to an IpSecTransform, it will become unusable for future transforms but should
125c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * still be closed to ensure system resources are released.
126330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
127330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
128330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public void close() {
12993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mSpi = INVALID_SECURITY_PARAMETER_INDEX;
130330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
131330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
132330e1089da80cddcd68758512370d217b19f8890Nathan Harold
133330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
134330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() {
135330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
136330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
137330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
138330e1089da80cddcd68758512370d217b19f8890Nathan Harold
139330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
140330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
141330e1089da80cddcd68758512370d217b19f8890Nathan Harold
14293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private SecurityParameterIndex(
14393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi)
14493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throws ResourceUnavailableException, SpiUnavailableException {
14593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService = service;
14693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mRemoteAddress = remoteAddress;
14793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            try {
14893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                Bundle result =
14993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        mService.reserveSecurityParameterIndex(
15093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                direction, remoteAddress.getHostAddress(), spi, new Binder());
15193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
15293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (result == null) {
15393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new NullPointerException("Received null response from IpSecService");
15493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
15593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
15693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                int status = result.getInt(KEY_STATUS);
15793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                switch (status) {
15893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.OK:
15993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        break;
16093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.RESOURCE_UNAVAILABLE:
16193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new ResourceUnavailableException(
16293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "No more SPIs may be allocated by this requester.");
16393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.SPI_UNAVAILABLE:
16493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new SpiUnavailableException("Requested SPI is unavailable", spi);
16593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    default:
16693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new RuntimeException(
16793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "Unknown status returned by IpSecService: " + status);
16893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
16993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                mSpi = result.getInt(KEY_SPI);
17093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                mResourceId = result.getInt(KEY_RESOURCE_ID);
17193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
17293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
17393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
17493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
17593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
17693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mResourceId == INVALID_RESOURCE_ID) {
17793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException(
17893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            "Invalid Resource ID returned by IpSecService: " + status);
17993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
18093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
18193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            } catch (RemoteException e) {
18293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw e.rethrowFromSystemServer();
18393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            }
18493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.open("open");
18593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
18693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
187330e1089da80cddcd68758512370d217b19f8890Nathan Harold
188330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
189c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * Reserve an SPI for traffic bound towards the specified remote address.
190330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
191330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
192330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * SecurityParameterIndex#close()}.
193330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
194c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
195c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold     * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
196330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
197330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return the reserved SecurityParameterIndex
198330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
199330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     for this user
200330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
201330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
202330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public SecurityParameterIndex reserveSecurityParameterIndex(
203c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold            int direction, InetAddress remoteAddress, int requestedSpi)
204330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws SpiUnavailableException, ResourceUnavailableException {
205c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold        return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
206330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
207330e1089da80cddcd68758512370d217b19f8890Nathan Harold
208330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
209330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
210330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
211330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform. For security reasons, attempts to send traffic to any IP address other than the
212330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * address associated with that transform will throw an IOException. In addition, if the
213330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
214330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * send() or receive() until the transform is removed from the socket by calling {@link
215330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * #removeTransportModeTransform(Socket, IpSecTransform)};
216330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
217330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a stream socket
218330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
219330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
220330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
221330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException {
222330e1089da80cddcd68758512370d217b19f8890Nathan Harold        applyTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
223330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
224330e1089da80cddcd68758512370d217b19f8890Nathan Harold
225330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
226330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec
227330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
228330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform. For security reasons, attempts to send traffic to any IP address other than the
229330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * address associated with that transform will throw an IOException. In addition, if the
230330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
231330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * send() or receive() until the transform is removed from the socket by calling {@link
232330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * #removeTransportModeTransform(DatagramSocket, IpSecTransform)};
233330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
234330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a datagram socket
235330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
236330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
237330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
238330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException {
239330e1089da80cddcd68758512370d217b19f8890Nathan Harold        applyTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
240330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
241330e1089da80cddcd68758512370d217b19f8890Nathan Harold
242330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Call down to activate a transform */
24393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
24493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        try {
24593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService.applyTransportModeTransform(pfd, transform.getResourceId());
24693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
24793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowFromSystemServer();
24893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
24993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
250330e1089da80cddcd68758512370d217b19f8890Nathan Harold
251330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
252330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
253330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
254330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
255330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Applications should probably not use this API directly. Instead, they should use {@link
256330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * VpnService} to provide VPN capability in a more generic fashion.
257330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
258330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a {@link Network} that will be tunneled via IP Sec.
259330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
260330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
261330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
262330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
263330e1089da80cddcd68758512370d217b19f8890Nathan Harold
264330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
265330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a transform from a given stream socket. Once removed, traffic on the socket will not
266330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
267330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * communication in the clear in the event socket reuse is desired. This operation will succeed
268330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * regardless of the underlying state of a transform. If a transform is removed, communication
269330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * on all sockets to which that transform was applied will fail until this method is called.
270330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
271330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a socket that previously had a transform applied to it.
272330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform the IPsec Transform that was previously applied to the given socket
273330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
274330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
275330e1089da80cddcd68758512370d217b19f8890Nathan Harold        removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
276330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
277330e1089da80cddcd68758512370d217b19f8890Nathan Harold
278330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
279330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a transform from a given datagram socket. Once removed, traffic on the socket will not
280330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
281330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * communication in the clear in the event socket reuse is desired. This operation will succeed
282330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * regardless of the underlying state of a transform. If a transform is removed, communication
283330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * on all sockets to which that transform was applied will fail until this method is called.
284330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
285330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a socket that previously had a transform applied to it.
286330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform the IPsec Transform that was previously applied to the given socket
287330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
288330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
289330e1089da80cddcd68758512370d217b19f8890Nathan Harold        removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
290330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
291330e1089da80cddcd68758512370d217b19f8890Nathan Harold
292330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Call down to activate a transform */
29393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
29493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        try {
29593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService.removeTransportModeTransform(pfd, transform.getResourceId());
29693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
29793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowFromSystemServer();
29893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
29993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
300330e1089da80cddcd68758512370d217b19f8890Nathan Harold
301330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
302330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
303330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
304330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
305330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * lost, all traffic will drop.
306330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
307330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a network that currently has transform applied to it.
308330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
309330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     network
310330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
311330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
312330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
313330e1089da80cddcd68758512370d217b19f8890Nathan Harold
314330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
315330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Class providing access to a system-provided UDP Encapsulation Socket, which may be used for
316330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic.
317330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
318330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>The socket provided by this class cannot be re-bound or closed via the inner
319330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * FileDescriptor. Instead, disposing of this socket requires a call to close().
320330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
321330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class UdpEncapsulationSocket implements AutoCloseable {
322330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final FileDescriptor mFd;
3231afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
324330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
325330e1089da80cddcd68758512370d217b19f8890Nathan Harold
32693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
327330e1089da80cddcd68758512370d217b19f8890Nathan Harold                throws ResourceUnavailableException {
3281afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold            mService = service;
329330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.open("constructor");
330330e1089da80cddcd68758512370d217b19f8890Nathan Harold            // TODO: go down to the kernel and get a socket on the specified
331330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mFd = new FileDescriptor();
332330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
333330e1089da80cddcd68758512370d217b19f8890Nathan Harold
3341afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException {
3351afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold            mService = service;
336330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.open("constructor");
337330e1089da80cddcd68758512370d217b19f8890Nathan Harold            // TODO: go get a random socket on a random port
338330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mFd = new FileDescriptor();
339330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
340330e1089da80cddcd68758512370d217b19f8890Nathan Harold
341330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Access the inner UDP Encapsulation Socket */
342330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public FileDescriptor getSocket() {
343330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mFd;
344330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
345330e1089da80cddcd68758512370d217b19f8890Nathan Harold
346330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /** Retrieve the port number of the inner encapsulation socket */
347330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getPort() {
348330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return 0; // TODO get the port number from the Socket;
349330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
350330e1089da80cddcd68758512370d217b19f8890Nathan Harold
351330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
352330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
353330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release the resources that have been reserved for this Socket.
354330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
355330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>This method closes the underlying socket, reducing a user's allocated sockets in the
356330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * system. This must be done as part of cleanup following use of a socket. Failure to do so
357330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * will cause the socket to count against a total allocation limit for IpSec and eventually
358330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * fail due to resource limits.
359330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
360330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
361330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
362330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public void close() {
363330e1089da80cddcd68758512370d217b19f8890Nathan Harold            // TODO: Go close the socket
364330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
365330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
366330e1089da80cddcd68758512370d217b19f8890Nathan Harold
367330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
368330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() throws Throwable {
369330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
370330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
371330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
372330e1089da80cddcd68758512370d217b19f8890Nathan Harold
373330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
374330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
375330e1089da80cddcd68758512370d217b19f8890Nathan Harold    };
376330e1089da80cddcd68758512370d217b19f8890Nathan Harold
377330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
378330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Open a socket that is bound to a free UDP port on the system.
379330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
380330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
381330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
382330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Encapsulation port.
383330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
384330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
385330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * socket port. Explicitly opening this port is only necessary if communication is desired on
386330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * that port.
387330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
388330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this
389330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     method will bind to the specified port or fail. To retrieve the port number, call {@link
390330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     android.system.Os#getsockname(FileDescriptor)}.
391330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime
392330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     of the object.
393330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
394330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
395330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
396330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
397330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
398330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
399330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
400330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
401330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // Temporary code
4021afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        return new UdpEncapsulationSocket(mService, port);
403330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
404330e1089da80cddcd68758512370d217b19f8890Nathan Harold
405330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
406330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Open a socket that is bound to a port selected by the system.
407330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
408330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
409330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
410330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Encapsulation port.
411330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
412330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
413330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * socket port. Explicitly opening this port is only necessary if communication is desired on
414330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * that port.
415330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
416330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port
417330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
418330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
419330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
420330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
421330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
422330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
423330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket()
424330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
425330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // Temporary code
4261afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        return new UdpEncapsulationSocket(mService);
427330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
428330e1089da80cddcd68758512370d217b19f8890Nathan Harold
429330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
430330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Retrieve an instance of an IpSecManager within you application context
431330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
432330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param context the application context for this manager
433330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
434330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
4351afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    public IpSecManager(IIpSecService service) {
436330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mService = checkNotNull(service, "missing service");
437330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
438330e1089da80cddcd68758512370d217b19f8890Nathan Harold}
439