IpSecManager.java revision b548d251b7995a5b76e495978b61ad6c3c4183d1
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 20a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport android.annotation.IntDef; 2193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull; 22d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService; 23c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseriimport android.annotation.TestApi; 24d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context; 2593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder; 26330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor; 2793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException; 28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException; 298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log; 30b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 31a10003d5de52339f4d30fedd7294941378e5f13cNathan Haroldimport com.android.internal.annotations.VisibleForTesting; 32a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold 33330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard; 34b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 35330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor; 36330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException; 37a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.Retention; 38a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.RetentionPolicy; 39330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket; 40330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress; 41330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket; 42330e1089da80cddcd68758512370d217b19f8890Nathan Harold 43330e1089da80cddcd68758512370d217b19f8890Nathan Harold/** 44c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply 45c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * confidentiality (encryption) and integrity (authentication) to IP traffic. 46330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 47c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create 48c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * transport mode security associations and apply them to individual sockets. Applications looking 49c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * to create a VPN should use {@link VpnService}. 50c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 51c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the 525fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * Internet Protocol</a> 53330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 54d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE) 55330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager { 56330e1089da80cddcd68758512370d217b19f8890Nathan Harold private static final String TAG = "IpSecManager"; 57330e1089da80cddcd68758512370d217b19f8890Nathan Harold 58330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 59a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute 60a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * applies to traffic towards the host. 61a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 62a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_IN = 0; 63a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 64a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 65a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute 66a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * applies to traffic from the host. 67a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 68a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_OUT = 1; 69a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 70a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** @hide */ 71a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) 72a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @Retention(RetentionPolicy.SOURCE) 73a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public @interface PolicyDirection {} 74a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 75a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 76c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. 7793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * 7893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * <p>No IPsec packet may contain an SPI of 0. 79c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 80c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @hide 8193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold */ 825fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; 8393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 8493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 8593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public interface Status { 8693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int OK = 0; 8793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int RESOURCE_UNAVAILABLE = 1; 8893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int SPI_UNAVAILABLE = 2; 8993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 9093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 926119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold public static final int INVALID_RESOURCE_ID = -1; 9393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** 95c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that a requested SPI is in use. 96c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 97c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on 98c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * one device. If this error is encountered, a new SPI is required before a transform may be 99c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * created. This error can be avoided by calling {@link 1005fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * IpSecManager#allocateSecurityParameterIndex}. 101330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 102330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SpiUnavailableException extends AndroidException { 103330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final int mSpi; 104330e1089da80cddcd68758512370d217b19f8890Nathan Harold 105330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 106330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Construct an exception indicating that a transform with the given SPI is already in use 107330e1089da80cddcd68758512370d217b19f8890Nathan Harold * or otherwise unavailable. 108330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 109c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param msg description indicating the colliding SPI 110330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param spi the SPI that could not be used due to a collision 111330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 112330e1089da80cddcd68758512370d217b19f8890Nathan Harold SpiUnavailableException(String msg, int spi) { 113c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri super(msg + " (spi: " + spi + ")"); 114330e1089da80cddcd68758512370d217b19f8890Nathan Harold mSpi = spi; 115330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 116330e1089da80cddcd68758512370d217b19f8890Nathan Harold 117c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the SPI that caused a collision. */ 118330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 119330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 120330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 121330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 122330e1089da80cddcd68758512370d217b19f8890Nathan Harold 123330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 124c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that an IPsec resource is unavailable. 125c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 126c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link 127c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecTransform}, or other system resources. If this exception is thrown, users should release 128c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * allocated objects of the type requested. 129330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 130330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class ResourceUnavailableException extends AndroidException { 131330e1089da80cddcd68758512370d217b19f8890Nathan Harold 132330e1089da80cddcd68758512370d217b19f8890Nathan Harold ResourceUnavailableException(String msg) { 133330e1089da80cddcd68758512370d217b19f8890Nathan Harold super(msg); 134330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 135330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 136330e1089da80cddcd68758512370d217b19f8890Nathan Harold 1371afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 138330e1089da80cddcd68758512370d217b19f8890Nathan Harold 139c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** 140c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class represents a reserved SPI. 141c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 142c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Objects of this type are used to track reserved security parameter indices. They can be 1435fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released 144c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * by calling {@link #close()} when they are no longer needed. 145c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri */ 146330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SecurityParameterIndex implements AutoCloseable { 1471afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 148a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold private final InetAddress mDestinationAddress; 149330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 15093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; 1516119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 152330e1089da80cddcd68758512370d217b19f8890Nathan Harold 153c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the underlying SPI held by this object. */ 154330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 155330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 156330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 157330e1089da80cddcd68758512370d217b19f8890Nathan Harold 158330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 159330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Release an SPI that was previously reserved. 160330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 161c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is 162c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * applied to an IpSecTransform, it will become unusable for future transforms but should 163c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * still be closed to ensure system resources are released. 164330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 165330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 166330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void close() { 1678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 1688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.releaseSecurityParameterIndex(mResourceId); 1696119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold mResourceId = INVALID_RESOURCE_ID; 1708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 1718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 1728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 173330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 174330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 175330e1089da80cddcd68758512370d217b19f8890Nathan Harold 176c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the SPI was closed properly. */ 177330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 178440824f7434e1e2c343b21a9ca3e6f405b8e0ea1Nathan Harold protected void finalize() throws Throwable { 179330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 180330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 181330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 182330e1089da80cddcd68758512370d217b19f8890Nathan Harold 183330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 184330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 185330e1089da80cddcd68758512370d217b19f8890Nathan Harold 18693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private SecurityParameterIndex( 187a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @NonNull IIpSecService service, InetAddress destinationAddress, int spi) 18893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throws ResourceUnavailableException, SpiUnavailableException { 18993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService = service; 190a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mDestinationAddress = destinationAddress; 19193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold try { 1928dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecSpiResponse result = 1935fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri mService.allocateSecurityParameterIndex( 194a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress.getHostAddress(), spi, new Binder()); 19593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 19693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (result == null) { 19793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new NullPointerException("Received null response from IpSecService"); 19893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 19993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 2008dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int status = result.status; 20193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold switch (status) { 20293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.OK: 20393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold break; 20493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.RESOURCE_UNAVAILABLE: 20593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new ResourceUnavailableException( 20693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "No more SPIs may be allocated by this requester."); 20793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.SPI_UNAVAILABLE: 20893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new SpiUnavailableException("Requested SPI is unavailable", spi); 20993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold default: 21093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 21193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Unknown status returned by IpSecService: " + status); 21293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2138dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mSpi = result.spi; 2148dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 21593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 21693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { 21793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); 21893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 21993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 22093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mResourceId == INVALID_RESOURCE_ID) { 22193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 22293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Invalid Resource ID returned by IpSecService: " + status); 22393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 22493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 22593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 22693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 22793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 22893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mCloseGuard.open("open"); 22993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 2318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 232a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 233a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 2348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 2358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 23693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 237330e1089da80cddcd68758512370d217b19f8890Nathan Harold 238330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 239a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve a random SPI for traffic bound to or from the specified destination address. 240330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 241330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 242330e1089da80cddcd68758512370d217b19f8890Nathan Harold * SecurityParameterIndex#close()}. 243330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 244a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param destinationAddress the destination address for traffic bearing the requested SPI. 245a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For inbound traffic, the destination should be an address currently assigned on-device. 246330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return the reserved SecurityParameterIndex 247a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 248a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 249330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 250a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress) 251a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold throws ResourceUnavailableException { 2526045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold try { 2536045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold return new SecurityParameterIndex( 2546045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold mService, 255a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress, 2566045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); 2576045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } catch (SpiUnavailableException unlikely) { 2586045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new ResourceUnavailableException("No SPIs available"); 2596045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2606045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2616045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold 2626045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold /** 263a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve the requested SPI for traffic bound to or from the specified destination address. 2646045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 2656045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 2666045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * SecurityParameterIndex#close()}. 2676045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 268a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param destinationAddress the destination address for traffic bearing the requested SPI. 269a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For inbound traffic, the destination should be an address currently assigned on-device. 270c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param requestedSpi the requested SPI, or '0' to allocate a random SPI 2716045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @return the reserved SecurityParameterIndex 272a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 273a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 274a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be 275a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * reserved 2766045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold */ 2775fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri public SecurityParameterIndex allocateSecurityParameterIndex( 278a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold InetAddress destinationAddress, int requestedSpi) 279330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws SpiUnavailableException, ResourceUnavailableException { 2806045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { 2816045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); 2826045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 283a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); 284330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 285330e1089da80cddcd68758512370d217b19f8890Nathan Harold 286330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 287c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a stream socket. 288c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 289c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 290c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 291a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 292c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 293c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 294c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 2955fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 296c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 297c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 298a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 299c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 3005fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3015fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3025fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>When applying a new tranform to a socket, the previous transform will be removed. However, 3035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * inbound traffic on the old transform will continue to be decrypted until that transform is 3045fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures 3055fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * where both transforms are valid until both endpoints are using the new transform and all 3065fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * in-flight packets have been received. 307330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 308330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a stream socket 309a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} 310c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 311c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 312330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 313a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void applyTransportModeTransform( 314a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold Socket socket, int direction, IpSecTransform transform) 315330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException { 316b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 317330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 318330e1089da80cddcd68758512370d217b19f8890Nathan Harold 319330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 320c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a datagram socket. 321c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 322c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 323c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 324a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 325c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 326c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 327c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 328c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 329c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 330c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 331a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 332c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 3335fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3345fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3355fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>When applying a new tranform to a socket, the previous transform will be removed. However, 3365fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * inbound traffic on the old transform will continue to be decrypted until that transform is 3375fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures 3385fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * where both transforms are valid until both endpoints are using the new transform and all 3395fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * in-flight packets have been received. 340330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 341330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a datagram socket 342a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT 343c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 344c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 345330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 346a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void applyTransportModeTransform( 347a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { 348b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 34993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 350330e1089da80cddcd68758512370d217b19f8890Nathan Harold 351330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 352c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a socket. 353c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 354c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 355c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 356a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 357c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 358c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 359c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 360c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 361c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 362c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 363a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 364c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 3655fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3665fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3675fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>When applying a new tranform to a socket, the previous transform will be removed. However, 3685fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * inbound traffic on the old transform will continue to be decrypted until that transform is 3695fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures 3705fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * where both transforms are valid until both endpoints are using the new transform and all 3715fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * in-flight packets have been received. 372b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 373b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param socket a socket file descriptor 374a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT 375c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 376c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 377b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 378a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void applyTransportModeTransform( 379a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold FileDescriptor socket, int direction, IpSecTransform transform) 380b64993559b049327365bb63e81e8046a892a1033Nathan Harold throws IOException { 3818dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() 382b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold // constructor takes control and closes the user's FD when we exit the method. 3838dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 384a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); 3858dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 3868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 3878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 388b64993559b049327365bb63e81e8046a892a1033Nathan Harold } 389b64993559b049327365bb63e81e8046a892a1033Nathan Harold 390b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 391330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to 392330e1089da80cddcd68758512370d217b19f8890Nathan Harold * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to 393330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic). 394330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Applications should probably not use this API directly. Instead, they should use {@link 395330e1089da80cddcd68758512370d217b19f8890Nathan Harold * VpnService} to provide VPN capability in a more generic fashion. 396330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 3975fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. 3985fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 399330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a {@link Network} that will be tunneled via IP Sec. 400330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. 401330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 402330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 403330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} 404330e1089da80cddcd68758512370d217b19f8890Nathan Harold 405330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 406c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a stream socket. 407c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 408c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed 409c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * regardless of the state of the transform. Removing a transform from a socket allows the 410c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket to be reused for communication in the clear. 411c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 412c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 413c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 414c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 415330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 416c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 417330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 418c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 419330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 420a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void removeTransportModeTransforms(Socket socket, IpSecTransform transform) 4210bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 422b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold removeTransportModeTransforms(socket.getFileDescriptor$(), transform); 423330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 424330e1089da80cddcd68758512370d217b19f8890Nathan Harold 425330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 426c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a datagram socket. 427330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 428c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed 429c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * regardless of the state of the transform. Removing a transform from a socket allows the 430c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket to be reused for communication in the clear. 431c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 432c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 433c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 434c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 435c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 436c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 437330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 438c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 439330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 440a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform) 4410bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 442b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold removeTransportModeTransforms(socket.getFileDescriptor$(), transform); 443330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 444330e1089da80cddcd68758512370d217b19f8890Nathan Harold 445b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 446c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a socket. 447c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 448c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed 449c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * regardless of the state of the transform. Removing a transform from a socket allows the 450c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket to be reused for communication in the clear. 451b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 452c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 453c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 454c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 455c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 456c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 457b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 458c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 459b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 460a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform) 4610bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 4628dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 463a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mService.removeTransportModeTransforms(pfd, transform.getResourceId()); 46493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 46593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 46693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 46793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 468330e1089da80cddcd68758512370d217b19f8890Nathan Harold 469330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 470330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of 471330e1089da80cddcd68758512370d217b19f8890Nathan Harold * cleanup if a tunneled Network experiences a change in default route. The Network will drop 472330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is 473330e1089da80cddcd68758512370d217b19f8890Nathan Harold * lost, all traffic will drop. 474330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 4755fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. 4765fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 477330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a network that currently has transform applied to it. 478330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given 479330e1089da80cddcd68758512370d217b19f8890Nathan Harold * network 480330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 481330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 482330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} 483330e1089da80cddcd68758512370d217b19f8890Nathan Harold 484330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 485c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class provides access to a UDP encapsulation Socket. 486330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 487c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2 488c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link 489c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the 490c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * caller. The caller should not close the {@code FileDescriptor} returned by {@link 491c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * #getSocket}, but should use {@link #close} instead. 492c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 493c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic 494c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * of the next user who binds to that port. To prevent this scenario, these sockets are held 495c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * open by the system so that they may only be closed by calling {@link #close} or when the user 496c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * process exits. 497330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 498330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class UdpEncapsulationSocket implements AutoCloseable { 4998dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final ParcelFileDescriptor mPfd; 5001afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 5016119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 5028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final int mPort; 503330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 504330e1089da80cddcd68758512370d217b19f8890Nathan Harold 50593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) 5068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throws ResourceUnavailableException, IOException { 5071afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold mService = service; 5088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5098dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecUdpEncapResponse result = 5108dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.openUdpEncapsulationSocket(port, new Binder()); 5118dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold switch (result.status) { 5128dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.OK: 5138dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold break; 5148dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.RESOURCE_UNAVAILABLE: 5158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new ResourceUnavailableException( 5168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "No more Sockets may be allocated by this requester."); 5178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold default: 5188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new RuntimeException( 5198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "Unknown status returned by IpSecService: " + result.status); 5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPort = result.port; 5238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd = result.fileDescriptor; 5248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 5258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 5268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 527330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.open("constructor"); 528330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 529330e1089da80cddcd68758512370d217b19f8890Nathan Harold 530c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the wrapped socket. */ 531330e1089da80cddcd68758512370d217b19f8890Nathan Harold public FileDescriptor getSocket() { 5328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (mPfd == null) { 5338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return null; 5348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPfd.getFileDescriptor(); 536330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 537330e1089da80cddcd68758512370d217b19f8890Nathan Harold 538c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the bound port of the wrapped socket. */ 539330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getPort() { 5408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPort; 541330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 542330e1089da80cddcd68758512370d217b19f8890Nathan Harold 543330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 544c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Close this socket. 545330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 546c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's 547c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * resource limits, and forgetting to close them eventually will result in {@link 548c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * ResourceUnavailableException} being thrown. 549330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 550c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri @Override 5510bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void close() throws IOException { 5528dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5538dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.closeUdpEncapsulationSocket(mResourceId); 5546119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold mResourceId = INVALID_RESOURCE_ID; 5558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 5568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 5578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5588dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 5598dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5608dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd.close(); 5618dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (IOException e) { 5628dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); 5638dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e; 5648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 565330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 566330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 567330e1089da80cddcd68758512370d217b19f8890Nathan Harold 568c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the socket was closed properly. */ 569330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 570330e1089da80cddcd68758512370d217b19f8890Nathan Harold protected void finalize() throws Throwable { 571330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 572330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 573330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 574330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 575330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 5768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 5778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 578a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 579a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 5808dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 5818dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 582330e1089da80cddcd68758512370d217b19f8890Nathan Harold }; 583330e1089da80cddcd68758512370d217b19f8890Nathan Harold 584330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 585c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation and bind to the given port. 586330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 587c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 588330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 589c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param port a local UDP port 590c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to the given port 591c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 592c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 593330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 594330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 595330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 596330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 597330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 598330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 599330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) 600330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 6018dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /* 6028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * Most range checking is done in the service, but this version of the constructor expects 6038dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * a valid port number, and zero cannot be checked after being passed to the service. 6048dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold */ 6058dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (port == 0) { 6068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new IllegalArgumentException("Specified port must be a valid port number!"); 6078dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 6081afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold return new UdpEncapsulationSocket(mService, port); 609330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 610330e1089da80cddcd68758512370d217b19f8890Nathan Harold 611330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 612c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation. 613330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 614c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 615330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 616c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The local port of the returned socket can be obtained by calling {@link 617c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * UdpEncapsulationSocket#getPort()}. 618330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 619c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to a local port 620c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 621c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 622330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 623330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 624330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 625330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 626330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 627330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 628330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket() 629330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 6308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return new UdpEncapsulationSocket(mService, 0); 631330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 632330e1089da80cddcd68758512370d217b19f8890Nathan Harold 633330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 634c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Construct an instance of IpSecManager within an application context. 635330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 636330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param context the application context for this manager 637330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 638330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 6391afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold public IpSecManager(IIpSecService service) { 640330e1089da80cddcd68758512370d217b19f8890Nathan Harold mService = checkNotNull(service, "missing service"); 641330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 642330e1089da80cddcd68758512370d217b19f8890Nathan Harold} 643