IpSecManager.java revision 6ea93c4bcaf5c2c8489695308e77b659b70b64d4
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; 225a920ca377efaaaaabf3fe6c77111d8158202055Nathan Haroldimport android.annotation.RequiresPermission; 23c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Haroldimport android.annotation.SystemApi; 24d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService; 25c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseriimport android.annotation.TestApi; 26d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context; 2793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder; 28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor; 2993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException; 30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException; 318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log; 32b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 33a10003d5de52339f4d30fedd7294941378e5f13cNathan Haroldimport com.android.internal.annotations.VisibleForTesting; 34a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold 35330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard; 36b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 37330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor; 38330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException; 39a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.Retention; 40a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.RetentionPolicy; 41330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket; 42330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress; 43330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket; 44330e1089da80cddcd68758512370d217b19f8890Nathan Harold 45330e1089da80cddcd68758512370d217b19f8890Nathan Harold/** 46c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply 47c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * confidentiality (encryption) and integrity (authentication) to IP traffic. 48330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 49c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create 50c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * transport mode security associations and apply them to individual sockets. Applications looking 51c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * to create a VPN should use {@link VpnService}. 52c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 53c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the 545fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * Internet Protocol</a> 55330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 56d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE) 57330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager { 58330e1089da80cddcd68758512370d217b19f8890Nathan Harold private static final String TAG = "IpSecManager"; 59330e1089da80cddcd68758512370d217b19f8890Nathan Harold 60330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 617b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Used when applying a transform to direct traffic through an {@link IpSecTransform} 627b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * towards the host. 637b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 647b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 65a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 66a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_IN = 0; 67a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 68a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 697b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Used when applying a transform to direct traffic through an {@link IpSecTransform} 707b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * away from the host. 717b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 727b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 73a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 74a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_OUT = 1; 75a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 76a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** @hide */ 77a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) 78a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @Retention(RetentionPolicy.SOURCE) 79a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public @interface PolicyDirection {} 80a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 81a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 82c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. 8393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * 8493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * <p>No IPsec packet may contain an SPI of 0. 85c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 86c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @hide 8793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold */ 885fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; 8993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 9193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public interface Status { 9293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int OK = 0; 9393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int RESOURCE_UNAVAILABLE = 1; 9493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int SPI_UNAVAILABLE = 2; 9593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 9693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 986119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold public static final int INVALID_RESOURCE_ID = -1; 9993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 10093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** 101c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that a requested SPI is in use. 102c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 103c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on 104c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * one device. If this error is encountered, a new SPI is required before a transform may be 105c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * created. This error can be avoided by calling {@link 1065fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * IpSecManager#allocateSecurityParameterIndex}. 107330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 108330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SpiUnavailableException extends AndroidException { 109330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final int mSpi; 110330e1089da80cddcd68758512370d217b19f8890Nathan Harold 111330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 112330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Construct an exception indicating that a transform with the given SPI is already in use 113330e1089da80cddcd68758512370d217b19f8890Nathan Harold * or otherwise unavailable. 114330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 115c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param msg description indicating the colliding SPI 116330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param spi the SPI that could not be used due to a collision 117330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 118330e1089da80cddcd68758512370d217b19f8890Nathan Harold SpiUnavailableException(String msg, int spi) { 119c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri super(msg + " (spi: " + spi + ")"); 120330e1089da80cddcd68758512370d217b19f8890Nathan Harold mSpi = spi; 121330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 122330e1089da80cddcd68758512370d217b19f8890Nathan Harold 123c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the SPI that caused a collision. */ 124330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 125330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 126330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 127330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 128330e1089da80cddcd68758512370d217b19f8890Nathan Harold 129330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 130c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that an IPsec resource is unavailable. 131c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 132c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link 133c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecTransform}, or other system resources. If this exception is thrown, users should release 134c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * allocated objects of the type requested. 135330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 136330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class ResourceUnavailableException extends AndroidException { 137330e1089da80cddcd68758512370d217b19f8890Nathan Harold 138330e1089da80cddcd68758512370d217b19f8890Nathan Harold ResourceUnavailableException(String msg) { 139330e1089da80cddcd68758512370d217b19f8890Nathan Harold super(msg); 140330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 141330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 142330e1089da80cddcd68758512370d217b19f8890Nathan Harold 1431afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 144330e1089da80cddcd68758512370d217b19f8890Nathan Harold 145c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** 146c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class represents a reserved SPI. 147c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 148c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Objects of this type are used to track reserved security parameter indices. They can be 1495fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released 150c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * by calling {@link #close()} when they are no longer needed. 151c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri */ 152330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SecurityParameterIndex implements AutoCloseable { 1531afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 154a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold private final InetAddress mDestinationAddress; 155330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 15693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; 1576119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 158330e1089da80cddcd68758512370d217b19f8890Nathan Harold 159c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the underlying SPI held by this object. */ 160330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 161330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 162330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 163330e1089da80cddcd68758512370d217b19f8890Nathan Harold 164330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 165330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Release an SPI that was previously reserved. 166330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 167c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is 168c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * applied to an IpSecTransform, it will become unusable for future transforms but should 169c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * still be closed to ensure system resources are released. 170330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 171330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 172330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void close() { 1738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 1748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.releaseSecurityParameterIndex(mResourceId); 1756119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold mResourceId = INVALID_RESOURCE_ID; 1768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 1778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 1788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 179330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 180330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 181330e1089da80cddcd68758512370d217b19f8890Nathan Harold 182c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the SPI was closed properly. */ 183330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 184440824f7434e1e2c343b21a9ca3e6f405b8e0ea1Nathan Harold protected void finalize() throws Throwable { 185330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 186330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 187330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 188330e1089da80cddcd68758512370d217b19f8890Nathan Harold 189330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 190330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 191330e1089da80cddcd68758512370d217b19f8890Nathan Harold 19293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private SecurityParameterIndex( 193a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @NonNull IIpSecService service, InetAddress destinationAddress, int spi) 19493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throws ResourceUnavailableException, SpiUnavailableException { 19593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService = service; 196a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mDestinationAddress = destinationAddress; 19793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold try { 1988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecSpiResponse result = 1995fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri mService.allocateSecurityParameterIndex( 200a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress.getHostAddress(), spi, new Binder()); 20193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 20293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (result == null) { 20393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new NullPointerException("Received null response from IpSecService"); 20493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 20593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 2068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int status = result.status; 20793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold switch (status) { 20893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.OK: 20993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold break; 21093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.RESOURCE_UNAVAILABLE: 21193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new ResourceUnavailableException( 21293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "No more SPIs may be allocated by this requester."); 21393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.SPI_UNAVAILABLE: 21493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new SpiUnavailableException("Requested SPI is unavailable", spi); 21593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold default: 21693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 21793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Unknown status returned by IpSecService: " + status); 21893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mSpi = result.spi; 2208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 22193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 22293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { 22393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); 22493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 22593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 22693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mResourceId == INVALID_RESOURCE_ID) { 22793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 22893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Invalid Resource ID returned by IpSecService: " + status); 22993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 23093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 23193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 23293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 23393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 23493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mCloseGuard.open("open"); 23593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 2378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 238a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 239a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 2408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 2418dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 24293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 243330e1089da80cddcd68758512370d217b19f8890Nathan Harold 244330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 245a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve a random SPI for traffic bound to or from the specified destination address. 246330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 247330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 248330e1089da80cddcd68758512370d217b19f8890Nathan Harold * SecurityParameterIndex#close()}. 249330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 250a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param destinationAddress the destination address for traffic bearing the requested SPI. 251a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For inbound traffic, the destination should be an address currently assigned on-device. 252330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return the reserved SecurityParameterIndex 253a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 254a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 255330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 2565cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 2575cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public SecurityParameterIndex allocateSecurityParameterIndex( 2585cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull InetAddress destinationAddress) throws ResourceUnavailableException { 2596045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold try { 2606045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold return new SecurityParameterIndex( 2616045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold mService, 262a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress, 2636045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); 2646045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } catch (SpiUnavailableException unlikely) { 2656045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new ResourceUnavailableException("No SPIs available"); 2666045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2676045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2686045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold 2696045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold /** 270a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve the requested SPI for traffic bound to or from the specified destination address. 2716045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 2726045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 2736045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * SecurityParameterIndex#close()}. 2746045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 275a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param destinationAddress the destination address for traffic bearing the requested SPI. 276a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For inbound traffic, the destination should be an address currently assigned on-device. 277c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param requestedSpi the requested SPI, or '0' to allocate a random SPI 2786045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @return the reserved SecurityParameterIndex 279a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 280a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 281a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be 282a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * reserved 2836045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold */ 2845cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 2855fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri public SecurityParameterIndex allocateSecurityParameterIndex( 2865cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull InetAddress destinationAddress, int requestedSpi) 287330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws SpiUnavailableException, ResourceUnavailableException { 2886045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { 2896045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); 2906045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 291a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); 292330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 293330e1089da80cddcd68758512370d217b19f8890Nathan Harold 294330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 295c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a stream socket. 296c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 297c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 298c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 299a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 300c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 301c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 302c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 3035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 304c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 305c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 306a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 307c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 308420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 309420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * applied transform before completion of graceful shutdown may result in the shutdown sequence 310420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 311420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to deactivating the applied transform. Socket closure may be performed asynchronously 312420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 313420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 314420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * sufficient to ensure shutdown. 315420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 316420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 317420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 318420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 319420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 320420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 3215fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3225fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3237b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 3247b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 3257b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 3267b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 3277b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 3287b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 3297b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 330330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 331330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a stream socket 3327b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 333c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 334c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 335330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 3365cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull Socket socket, 3375cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 338b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 339330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 340330e1089da80cddcd68758512370d217b19f8890Nathan Harold 341330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 342c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a datagram socket. 343c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 344c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 345c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 346a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 347c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 348c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 349c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 350c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 351c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 352c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 353a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 354c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 3555fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3565fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3577b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 3587b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 3597b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 3607b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 3617b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 3627b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 3637b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 364330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 365330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a datagram socket 3667b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 367c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 368c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 369330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 3705cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull DatagramSocket socket, 3715cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 372b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 37393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 374330e1089da80cddcd68758512370d217b19f8890Nathan Harold 375330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 376c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a socket. 377c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 378c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 379c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 380a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 381c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 382c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 383c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 384c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 385c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 386c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 387a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 388c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 389420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 390420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * applied transform before completion of graceful shutdown may result in the shutdown sequence 391420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 392420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to deactivating the applied transform. Socket closure may be performed asynchronously 393420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 394420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 395420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * sufficient to ensure shutdown. 396420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 397420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 398420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 399420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 400420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 401420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 4025fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 4035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 4047b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 4057b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 4067b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 4077b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 4087b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 4097b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 4107b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 411b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 412b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param socket a socket file descriptor 4137b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 414c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 415c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 416b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 4175cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull FileDescriptor socket, 4185cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 4198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() 420b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold // constructor takes control and closes the user's FD when we exit the method. 4218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 422a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); 4238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 4248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 4258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 426b64993559b049327365bb63e81e8046a892a1033Nathan Harold } 427b64993559b049327365bb63e81e8046a892a1033Nathan Harold 428b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 429c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a stream socket. 430c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 431f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 432f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 433c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 434c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 435c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 436c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 437330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 438c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 439c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 440330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4415cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { 442f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold removeTransportModeTransforms(socket.getFileDescriptor$()); 443330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 444330e1089da80cddcd68758512370d217b19f8890Nathan Harold 445330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 446c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a datagram socket. 447330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 448f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 449f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 450c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 451c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 452c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 453c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 454c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 455c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 456c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 457330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4585cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException { 459f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold removeTransportModeTransforms(socket.getFileDescriptor$()); 460330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 461330e1089da80cddcd68758512370d217b19f8890Nathan Harold 462b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 463c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a socket. 464c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 465f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 466f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 467b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 468c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 469c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 470c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 471c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 472c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 473c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 474b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 4755cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { 4768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 477f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold mService.removeTransportModeTransforms(pfd); 47893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 47993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 48093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 48193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 482330e1089da80cddcd68758512370d217b19f8890Nathan Harold 483330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 484330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of 485330e1089da80cddcd68758512370d217b19f8890Nathan Harold * cleanup if a tunneled Network experiences a change in default route. The Network will drop 486330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is 487330e1089da80cddcd68758512370d217b19f8890Nathan Harold * lost, all traffic will drop. 488330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 4895fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. 4905fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 491330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a network that currently has transform applied to it. 492330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given 493330e1089da80cddcd68758512370d217b19f8890Nathan Harold * network 494330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 495330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 496330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} 497330e1089da80cddcd68758512370d217b19f8890Nathan Harold 498330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 499c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class provides access to a UDP encapsulation Socket. 500330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 501c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2 502c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link 503c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the 504c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * caller. The caller should not close the {@code FileDescriptor} returned by {@link 5056ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong * #getFileDescriptor}, but should use {@link #close} instead. 506c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 507c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic 508c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * of the next user who binds to that port. To prevent this scenario, these sockets are held 509c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * open by the system so that they may only be closed by calling {@link #close} or when the user 510c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * process exits. 511330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 512330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class UdpEncapsulationSocket implements AutoCloseable { 5138dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final ParcelFileDescriptor mPfd; 5141afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 5156119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 5168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final int mPort; 517330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 518330e1089da80cddcd68758512370d217b19f8890Nathan Harold 51993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) 5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throws ResourceUnavailableException, IOException { 5211afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold mService = service; 5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecUdpEncapResponse result = 5248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.openUdpEncapsulationSocket(port, new Binder()); 5258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold switch (result.status) { 5268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.OK: 5278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold break; 5288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.RESOURCE_UNAVAILABLE: 5298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new ResourceUnavailableException( 5308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "No more Sockets may be allocated by this requester."); 5318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold default: 5328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new RuntimeException( 5338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "Unknown status returned by IpSecService: " + result.status); 5348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 5368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPort = result.port; 5378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd = result.fileDescriptor; 5388dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 5398dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 5408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 541330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.open("constructor"); 542330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 543330e1089da80cddcd68758512370d217b19f8890Nathan Harold 5446ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong /** Get the encapsulation socket's file descriptor. */ 5456ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong public FileDescriptor getFileDescriptor() { 5468dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (mPfd == null) { 5478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return null; 5488dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPfd.getFileDescriptor(); 550330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 551330e1089da80cddcd68758512370d217b19f8890Nathan Harold 552c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the bound port of the wrapped socket. */ 553330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getPort() { 5548dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPort; 555330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 556330e1089da80cddcd68758512370d217b19f8890Nathan Harold 557330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 558c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Close this socket. 559330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 560c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's 561c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * resource limits, and forgetting to close them eventually will result in {@link 562c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * ResourceUnavailableException} being thrown. 563330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 564c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri @Override 5650bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void close() throws IOException { 5668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.closeUdpEncapsulationSocket(mResourceId); 5686119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold mResourceId = INVALID_RESOURCE_ID; 5698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 5708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 5718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 5738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd.close(); 5758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (IOException e) { 5768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); 5778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e; 5788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 579330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 580330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 581330e1089da80cddcd68758512370d217b19f8890Nathan Harold 582c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the socket was closed properly. */ 583330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 584330e1089da80cddcd68758512370d217b19f8890Nathan Harold protected void finalize() throws Throwable { 585330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 586330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 587330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 588330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 589330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 5908dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 5918dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 592a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 593a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 5948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 5958dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 596330e1089da80cddcd68758512370d217b19f8890Nathan Harold }; 597330e1089da80cddcd68758512370d217b19f8890Nathan Harold 598330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 599c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation and bind to the given port. 600330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 601c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 602330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 603c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param port a local UDP port 604c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to the given port 605c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 606c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 607330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 608330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 609330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 610330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 611330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 612330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 6135cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 614330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) 615330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 6168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /* 6178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * Most range checking is done in the service, but this version of the constructor expects 6188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * a valid port number, and zero cannot be checked after being passed to the service. 6198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold */ 6208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (port == 0) { 6218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new IllegalArgumentException("Specified port must be a valid port number!"); 6228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 6231afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold return new UdpEncapsulationSocket(mService, port); 624330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 625330e1089da80cddcd68758512370d217b19f8890Nathan Harold 626330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 627c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation. 628330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 629c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 630330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 631c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The local port of the returned socket can be obtained by calling {@link 632c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * UdpEncapsulationSocket#getPort()}. 633330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 634c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to a local port 635c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 636c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 637330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 638330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 639330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 640330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 641330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 642330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 6435cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 644330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket() 645330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 6468dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return new UdpEncapsulationSocket(mService, 0); 647330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 648330e1089da80cddcd68758512370d217b19f8890Nathan Harold 649330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 650c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * This class represents an IpSecTunnelInterface 651c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 652c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as 653c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * local endpoints for IPsec tunnels. 654c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 655c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be 656c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * applied to provide IPsec security to packets sent through the tunnel. While a tunnel 657c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * cannot be used in standalone mode within Android, the higher layers may use the tunnel 658c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * to create Network objects which are accessible to the Android system. 659c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 660c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 661c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @SystemApi 662c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public static final class IpSecTunnelInterface implements AutoCloseable { 663c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final IIpSecService mService; 664c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final InetAddress mRemoteAddress; 665c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final InetAddress mLocalAddress; 666c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final Network mUnderlyingNetwork; 667c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 668c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private String mInterfaceName; 669c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private int mResourceId = INVALID_RESOURCE_ID; 670c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 671c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** Get the underlying SPI held by this object. */ 6725cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 673c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public String getInterfaceName() { 674c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold return mInterfaceName; 675c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 676c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 677c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 678c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Add an address to the IpSecTunnelInterface 679c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 680c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Add an address which may be used as the local inner address for 681c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * tunneled traffic. 682c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 683c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param address the local address for traffic inside the tunnel 684c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 685c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 686c8f63060adc880eb6cfdee1e08cafcf2f379096aNathan Harold @SystemApi 687159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 6885cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void addAddress(@NonNull LinkAddress address) throws IOException { 689da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong try { 690da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong mService.addAddressToTunnelInterface(mResourceId, address); 691da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } catch (RemoteException e) { 692da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong throw e.rethrowFromSystemServer(); 693da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } 694c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 695c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 696c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 697c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Remove an address from the IpSecTunnelInterface 698c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 699c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Remove an address which was previously added to the IpSecTunnelInterface 700c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 701c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param address to be removed 702c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 703c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 704c8f63060adc880eb6cfdee1e08cafcf2f379096aNathan Harold @SystemApi 705159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 7065cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeAddress(@NonNull LinkAddress address) throws IOException { 707da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong try { 708da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong mService.removeAddressFromTunnelInterface(mResourceId, address); 709da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } catch (RemoteException e) { 710da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong throw e.rethrowFromSystemServer(); 711da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } 712c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 713c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 714c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private IpSecTunnelInterface(@NonNull IIpSecService service, 715c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, 716c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull Network underlyingNetwork) 717c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold throws ResourceUnavailableException, IOException { 718c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mService = service; 719c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mLocalAddress = localAddress; 720c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mRemoteAddress = remoteAddress; 721c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mUnderlyingNetwork = underlyingNetwork; 7228149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong 7238149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 7248149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong IpSecTunnelInterfaceResponse result = 7258149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mService.createTunnelInterface( 7268149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong localAddress.getHostAddress(), 7278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong remoteAddress.getHostAddress(), 7288149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong underlyingNetwork, 7298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong new Binder()); 7308149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong switch (result.status) { 7318149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong case Status.OK: 7328149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong break; 7338149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong case Status.RESOURCE_UNAVAILABLE: 7348149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw new ResourceUnavailableException( 7358149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong "No more tunnel interfaces may be allocated by this requester."); 7368149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong default: 7378149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw new RuntimeException( 7388149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong "Unknown status returned by IpSecService: " + result.status); 7398149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 7408149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mResourceId = result.resourceId; 7418149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mInterfaceName = result.interfaceName; 7428149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 7438149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 7448149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 7458149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mCloseGuard.open("constructor"); 746c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 747c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 748c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 749c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Delete an IpSecTunnelInterface 750c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 751c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system 752c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * resources. Any packets bound for this interface either inbound or outbound will 753c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * all be lost. 754c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 755c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @Override 756c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public void close() { 7578149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 7588149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mService.deleteTunnelInterface(mResourceId); 7598149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mResourceId = INVALID_RESOURCE_ID; 7608149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 7618149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 7628149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 763c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mCloseGuard.close(); 764c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 765c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 766c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** Check that the Interface was closed properly. */ 767c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @Override 768c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold protected void finalize() throws Throwable { 769c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold if (mCloseGuard != null) { 770c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mCloseGuard.warnIfOpen(); 771c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 772c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold close(); 773c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 7748149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong 7758149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong /** @hide */ 7768149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong @VisibleForTesting 7778149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong public int getResourceId() { 7788149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong return mResourceId; 7798149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 780c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 781c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 782c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 783c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. 784c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 7858149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the 7868149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * underlying network goes away, and the onLost() callback is received. 7878149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * 788c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param localAddress The local addres of the tunnel 789c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param remoteAddress The local addres of the tunnel 790c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. 791c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * This network should almost certainly be a network such as WiFi with an L2 address. 792c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties 793c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws IOException indicating that the socket could not be opened or bound 794c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 795c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 796c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 797c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @SystemApi 7985cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 799159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 800c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, 801c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) 802c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold throws ResourceUnavailableException, IOException { 803c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork); 804c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 805c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 806c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 8077b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will 8087b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * tunnel all traffic for the given direction through the underlying network's interface with 8097b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional 8107b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * IP header and IPsec Header on all inbound traffic). 8117b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>Applications should probably not use this API directly. 8127b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 813c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 814c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied 815c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * transform. 816c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which 817c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * the transform will be used. 818c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param transform an {@link IpSecTransform} created in tunnel mode 819c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws IOException indicating that the transform could not be applied due to a lower 820c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * layer failure. 821c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 822c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 823c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @SystemApi 824159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 8255cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, 8265cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 8278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 8288149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mService.applyTunnelModeTransform( 8298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong tunnel.getResourceId(), direction, transform.getResourceId()); 8308149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 8318149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 8328149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 833c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 8347b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold 835c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 836c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Construct an instance of IpSecManager within an application context. 837330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 838330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param context the application context for this manager 839330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 840330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 8411afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold public IpSecManager(IIpSecService service) { 842330e1089da80cddcd68758512370d217b19f8890Nathan Harold mService = checkNotNull(service, "missing service"); 843330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 844330e1089da80cddcd68758512370d217b19f8890Nathan Harold} 845