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; 23d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService; 24c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseriimport android.annotation.TestApi; 25d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context; 2693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder; 27330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor; 2893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException; 29ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Haroldimport android.os.ServiceSpecificException; 30ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Haroldimport android.system.ErrnoException; 31ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Haroldimport android.system.OsConstants; 32330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException; 338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log; 34b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 35a10003d5de52339f4d30fedd7294941378e5f13cNathan Haroldimport com.android.internal.annotations.VisibleForTesting; 36a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold 37330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard; 38b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold 39330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor; 40330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException; 41a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.Retention; 42a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.RetentionPolicy; 43330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket; 44330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress; 45330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket; 46330e1089da80cddcd68758512370d217b19f8890Nathan Harold 47330e1089da80cddcd68758512370d217b19f8890Nathan Harold/** 48c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply 49c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * confidentiality (encryption) and integrity (authentication) to IP traffic. 50330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 51c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create 52c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * transport mode security associations and apply them to individual sockets. Applications looking 53c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * to create a VPN should use {@link VpnService}. 54c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 55c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the 565fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * Internet Protocol</a> 57330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 58d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE) 59330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager { 60330e1089da80cddcd68758512370d217b19f8890Nathan Harold private static final String TAG = "IpSecManager"; 61330e1089da80cddcd68758512370d217b19f8890Nathan Harold 62330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 637b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Used when applying a transform to direct traffic through an {@link IpSecTransform} 647b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * towards the host. 657b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 667b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 67a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 68a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_IN = 0; 69a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 70a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 717b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Used when applying a transform to direct traffic through an {@link IpSecTransform} 727b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * away from the host. 737b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 747b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 75a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold */ 76a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public static final int DIRECTION_OUT = 1; 77a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 78a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** @hide */ 79a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) 80a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @Retention(RetentionPolicy.SOURCE) 81a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold public @interface PolicyDirection {} 82a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold 83a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold /** 84c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. 8593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * 8693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * <p>No IPsec packet may contain an SPI of 0. 87c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 88c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @hide 8993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold */ 905fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; 9193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 9393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public interface Status { 9493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int OK = 0; 9593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int RESOURCE_UNAVAILABLE = 1; 9693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int SPI_UNAVAILABLE = 2; 9793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 9893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 9993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 1006119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold public static final int INVALID_RESOURCE_ID = -1; 10193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 10293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** 103c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that a requested SPI is in use. 104c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 105c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on 106c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * one device. If this error is encountered, a new SPI is required before a transform may be 107c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * created. This error can be avoided by calling {@link 1085fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * IpSecManager#allocateSecurityParameterIndex}. 109330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 110330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SpiUnavailableException extends AndroidException { 111330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final int mSpi; 112330e1089da80cddcd68758512370d217b19f8890Nathan Harold 113330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 114330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Construct an exception indicating that a transform with the given SPI is already in use 115330e1089da80cddcd68758512370d217b19f8890Nathan Harold * or otherwise unavailable. 116330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 117c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param msg description indicating the colliding SPI 118330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param spi the SPI that could not be used due to a collision 119330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 120330e1089da80cddcd68758512370d217b19f8890Nathan Harold SpiUnavailableException(String msg, int spi) { 121c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri super(msg + " (spi: " + spi + ")"); 122330e1089da80cddcd68758512370d217b19f8890Nathan Harold mSpi = spi; 123330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 124330e1089da80cddcd68758512370d217b19f8890Nathan Harold 125c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the SPI that caused a collision. */ 126330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 127330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 128330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 129330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 130330e1089da80cddcd68758512370d217b19f8890Nathan Harold 131330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 132c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Thrown to indicate that an IPsec resource is unavailable. 133c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 134c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link 135c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecTransform}, or other system resources. If this exception is thrown, users should release 136c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * allocated objects of the type requested. 137330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 138330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class ResourceUnavailableException extends AndroidException { 139330e1089da80cddcd68758512370d217b19f8890Nathan Harold 140330e1089da80cddcd68758512370d217b19f8890Nathan Harold ResourceUnavailableException(String msg) { 141330e1089da80cddcd68758512370d217b19f8890Nathan Harold super(msg); 142330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 143330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 144330e1089da80cddcd68758512370d217b19f8890Nathan Harold 145592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold private final Context mContext; 1461afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 147330e1089da80cddcd68758512370d217b19f8890Nathan Harold 148c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** 149c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class represents a reserved SPI. 150c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 151c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Objects of this type are used to track reserved security parameter indices. They can be 1525fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released 153c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * by calling {@link #close()} when they are no longer needed. 154c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri */ 155330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SecurityParameterIndex implements AutoCloseable { 1561afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 157a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold private final InetAddress mDestinationAddress; 158330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 15993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; 1606119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 161330e1089da80cddcd68758512370d217b19f8890Nathan Harold 162c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the underlying SPI held by this object. */ 163330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 164330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 165330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 166330e1089da80cddcd68758512370d217b19f8890Nathan Harold 167330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 168330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Release an SPI that was previously reserved. 169330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 170c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is 171c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * applied to an IpSecTransform, it will become unusable for future transforms but should 172c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * still be closed to ensure system resources are released. 173330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 174330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 175330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void close() { 1768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 1778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.releaseSecurityParameterIndex(mResourceId); 1788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 1798dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 180ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (Exception e) { 181ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // On close we swallow all random exceptions since failure to close is not 182ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // actionable by the user. 183ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 184ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } finally { 185ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mResourceId = INVALID_RESOURCE_ID; 186ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mCloseGuard.close(); 1878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 188330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 189330e1089da80cddcd68758512370d217b19f8890Nathan Harold 190c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the SPI was closed properly. */ 191330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 192440824f7434e1e2c343b21a9ca3e6f405b8e0ea1Nathan Harold protected void finalize() throws Throwable { 193330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 194330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 195330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 196330e1089da80cddcd68758512370d217b19f8890Nathan Harold 197330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 198330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 199330e1089da80cddcd68758512370d217b19f8890Nathan Harold 20093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private SecurityParameterIndex( 201a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold @NonNull IIpSecService service, InetAddress destinationAddress, int spi) 20293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throws ResourceUnavailableException, SpiUnavailableException { 20393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService = service; 204a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mDestinationAddress = destinationAddress; 20593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold try { 2068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecSpiResponse result = 2075fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri mService.allocateSecurityParameterIndex( 208a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress.getHostAddress(), spi, new Binder()); 20993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 21093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (result == null) { 21193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new NullPointerException("Received null response from IpSecService"); 21293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 21393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 2148dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int status = result.status; 21593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold switch (status) { 21693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.OK: 21793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold break; 21893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.RESOURCE_UNAVAILABLE: 21993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new ResourceUnavailableException( 22093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "No more SPIs may be allocated by this requester."); 22193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.SPI_UNAVAILABLE: 22293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new SpiUnavailableException("Requested SPI is unavailable", spi); 22393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold default: 22493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 22593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Unknown status returned by IpSecService: " + status); 22693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mSpi = result.spi; 2288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 22993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 23093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { 23193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); 23293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 23393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 23493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mResourceId == INVALID_RESOURCE_ID) { 23593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 23693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Invalid Resource ID returned by IpSecService: " + status); 23793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 23893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 23993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 24093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 24193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mCloseGuard.open("open"); 24293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 2438dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 2448dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 245a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 246a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 2478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 2488dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 249ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 250ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold @Override 251ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold public String toString() { 252ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new StringBuilder() 253ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("SecurityParameterIndex{spi=") 254ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mSpi) 255ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(",resourceId=") 256ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mResourceId) 257ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("}") 258ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .toString(); 259ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 26093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 261330e1089da80cddcd68758512370d217b19f8890Nathan Harold 262330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 263a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve a random SPI for traffic bound to or from the specified destination address. 264330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 265330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 266330e1089da80cddcd68758512370d217b19f8890Nathan Harold * SecurityParameterIndex#close()}. 267330e1089da80cddcd68758512370d217b19f8890Nathan 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. 270330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return the reserved SecurityParameterIndex 271a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 272a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 273330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 2745cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 2755cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public SecurityParameterIndex allocateSecurityParameterIndex( 2765cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull InetAddress destinationAddress) throws ResourceUnavailableException { 2776045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold try { 2786045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold return new SecurityParameterIndex( 2796045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold mService, 280a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold destinationAddress, 2816045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); 282ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 283ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowUncheckedExceptionFromServiceSpecificException(e); 2846045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } catch (SpiUnavailableException unlikely) { 285ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // Because this function allocates a totally random SPI, it really shouldn't ever 286ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // fail to allocate an SPI; we simply need this because the exception is checked. 2876045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new ResourceUnavailableException("No SPIs available"); 2886045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2896045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2906045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold 2916045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold /** 292a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * Reserve the requested SPI for traffic bound to or from the specified destination address. 2936045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 2946045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 2956045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * SecurityParameterIndex#close()}. 2966045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 297a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @param destinationAddress the destination address for traffic bearing the requested SPI. 298a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * For inbound traffic, the destination should be an address currently assigned on-device. 299ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See 300ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * RFC 4303 Section 2.1. 3016045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @return the reserved SecurityParameterIndex 302a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are 303a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * currently allocated for this user 304a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be 305a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * reserved 3066045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold */ 3075cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 3085fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri public SecurityParameterIndex allocateSecurityParameterIndex( 3095cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull InetAddress destinationAddress, int requestedSpi) 310330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws SpiUnavailableException, ResourceUnavailableException { 3116045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { 3126045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); 3136045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 314ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold try { 315ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); 316ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 317ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowUncheckedExceptionFromServiceSpecificException(e); 318ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 319330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 320330e1089da80cddcd68758512370d217b19f8890Nathan Harold 321330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 322c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a stream socket. 323c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 324c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 325c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 326a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 327c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 328c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 329c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 3305fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 331c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 332c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 333a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 334c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 335420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 336420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * applied transform before completion of graceful shutdown may result in the shutdown sequence 337420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 338420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to deactivating the applied transform. Socket closure may be performed asynchronously 339420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 340420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 341420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * sufficient to ensure shutdown. 342420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 343420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 344420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 345420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 346420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 347420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 3485fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3495fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3507b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 3517b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 3527b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 3537b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 3547b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 3557b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 3567b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 357330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 358330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a stream socket 3597b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 360c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 361c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 362330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 3635cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull Socket socket, 3645cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 3655e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong // Ensure creation of FD. See b/77548890 for more details. 3665e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong socket.getSoLinger(); 3675e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong 368b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 369330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 370330e1089da80cddcd68758512370d217b19f8890Nathan Harold 371330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 372c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a datagram socket. 373c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 374c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 375c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 376a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 377c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 378c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 379c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 380c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 381c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 382c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 383a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 384c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 3855fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 3865fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 3877b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 3887b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 3897b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 3907b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 3917b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 3927b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 3937b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 394330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 395330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a datagram socket 3967b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 397c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 398c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 399330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4005cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull DatagramSocket socket, 4015cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 402b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 40393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 404330e1089da80cddcd68758512370d217b19f8890Nathan Harold 405330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 406c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Apply an IPsec transform to a socket. 407c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 408c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 409c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 410a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 411c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * unprotected traffic can resume on that socket. 412c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 413c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>For security reasons, the destination address of any traffic on the socket must match the 414c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 415c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * other IP address will result in an IOException. In addition, reads and writes on the socket 416c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * will throw IOException if the user deactivates the transform (by calling {@link 417a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 418c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 419420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 420420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * applied transform before completion of graceful shutdown may result in the shutdown sequence 421420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 422420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to deactivating the applied transform. Socket closure may be performed asynchronously 423420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 424420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 425420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * sufficient to ensure shutdown. 426420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 427420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 428420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 429420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 430420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 431420fe002f1d35e870d519344a13de9f6501e4ddbBenedict Wong * 4325fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <h4>Rekey Procedure</h4> 4335fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 4347b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 4357b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * will be removed and the new transform will take effect immediately, sending all traffic on 4367b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * the new transform; however, when applying a transform in the inbound direction, traffic 4377b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * on the old transform will continue to be decrypted and delivered until that transform is 4387b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 4397b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * procedures where both transforms are valid until both endpoints are using the new transform 4407b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * and all in-flight packets have been received. 441b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 442b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param socket a socket file descriptor 4437b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * @param direction the direction in which the transform should be applied 444c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param transform a transport mode {@code IpSecTransform} 445c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be applied 446b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 4475cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTransportModeTransform(@NonNull FileDescriptor socket, 4485cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 4498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() 450b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold // constructor takes control and closes the user's FD when we exit the method. 4518dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 452a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); 453ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 454ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 4558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 4568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 4578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 458b64993559b049327365bb63e81e8046a892a1033Nathan Harold } 459b64993559b049327365bb63e81e8046a892a1033Nathan Harold 460b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 461c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a stream socket. 462c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 463f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 464f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 465c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 466c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 467c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 468c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 469330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 470c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 471c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 472330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4735cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { 4745e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong // Ensure creation of FD. See b/77548890 for more details. 4755e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong socket.getSoLinger(); 4765e9b4c7c338e31b9acc2e4d3fb877202e435a32eBenedict Wong 477f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold removeTransportModeTransforms(socket.getFileDescriptor$()); 478330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 479330e1089da80cddcd68758512370d217b19f8890Nathan Harold 480330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 481c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a datagram socket. 482330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 483f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 484f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 485c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 486c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 487c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 488c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 489c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 490c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 491c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 492330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4935cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException { 494f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold removeTransportModeTransforms(socket.getFileDescriptor$()); 495330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 496330e1089da80cddcd68758512370d217b19f8890Nathan Harold 497b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 498c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Remove an IPsec transform from a socket. 499c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 500f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 501f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold * socket allows the socket to be reused for communication in the clear. 502b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 503c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 504c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 505c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * is called. 506c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 507c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param socket a socket that previously had a transform applied to it 508c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the transform could not be removed from the socket 509b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 5105cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { 5118dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 512f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold mService.removeTransportModeTransforms(pfd); 513ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 514ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 51593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 51693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 51793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 51893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 519330e1089da80cddcd68758512370d217b19f8890Nathan Harold 520330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 521330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of 522330e1089da80cddcd68758512370d217b19f8890Nathan Harold * cleanup if a tunneled Network experiences a change in default route. The Network will drop 523330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is 524330e1089da80cddcd68758512370d217b19f8890Nathan Harold * lost, all traffic will drop. 525330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 5265fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. 5275fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri * 528330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a network that currently has transform applied to it. 529330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given 530330e1089da80cddcd68758512370d217b19f8890Nathan Harold * network 531330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 532330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 533330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} 534330e1089da80cddcd68758512370d217b19f8890Nathan Harold 535330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 536c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class provides access to a UDP encapsulation Socket. 537330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 538c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2 539c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link 540c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the 541c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * caller. The caller should not close the {@code FileDescriptor} returned by {@link 5426ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong * #getFileDescriptor}, but should use {@link #close} instead. 543c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * 544c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic 545c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * of the next user who binds to that port. To prevent this scenario, these sockets are held 546c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * open by the system so that they may only be closed by calling {@link #close} or when the user 547c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * process exits. 548330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 549330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class UdpEncapsulationSocket implements AutoCloseable { 5508dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final ParcelFileDescriptor mPfd; 5511afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 5526119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold private int mResourceId = INVALID_RESOURCE_ID; 5538dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final int mPort; 554330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 555330e1089da80cddcd68758512370d217b19f8890Nathan Harold 55693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) 5578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throws ResourceUnavailableException, IOException { 5581afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold mService = service; 5598dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 5608dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecUdpEncapResponse result = 5618dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.openUdpEncapsulationSocket(port, new Binder()); 5628dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold switch (result.status) { 5638dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.OK: 5648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold break; 5658dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.RESOURCE_UNAVAILABLE: 5668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new ResourceUnavailableException( 5678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "No more Sockets may be allocated by this requester."); 5688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold default: 5698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new RuntimeException( 5708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "Unknown status returned by IpSecService: " + result.status); 5718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 5738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPort = result.port; 5748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd = result.fileDescriptor; 5758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 5768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 5778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 578330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.open("constructor"); 579330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 580330e1089da80cddcd68758512370d217b19f8890Nathan Harold 5816ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong /** Get the encapsulation socket's file descriptor. */ 5826ea93c4bcaf5c2c8489695308e77b659b70b64d4Benedict Wong public FileDescriptor getFileDescriptor() { 5838dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (mPfd == null) { 5848dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return null; 5858dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPfd.getFileDescriptor(); 587330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 588330e1089da80cddcd68758512370d217b19f8890Nathan Harold 589c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Get the bound port of the wrapped socket. */ 590330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getPort() { 5918dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPort; 592330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 593330e1089da80cddcd68758512370d217b19f8890Nathan Harold 594330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 595c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Close this socket. 596330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 597c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's 598c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * resource limits, and forgetting to close them eventually will result in {@link 599c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * ResourceUnavailableException} being thrown. 600330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 601c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri @Override 6020bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void close() throws IOException { 6038dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 6048dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.closeUdpEncapsulationSocket(mResourceId); 6056119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold mResourceId = INVALID_RESOURCE_ID; 6068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 6078dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 608ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (Exception e) { 609ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // On close we swallow all random exceptions since failure to close is not 610ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // actionable by the user. 611ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 612ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } finally { 613ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mResourceId = INVALID_RESOURCE_ID; 614ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mCloseGuard.close(); 6158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 6168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 6178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 6188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd.close(); 6198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (IOException e) { 6208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); 6218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e; 6228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 623330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 624330e1089da80cddcd68758512370d217b19f8890Nathan Harold 625c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri /** Check that the socket was closed properly. */ 626330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 627330e1089da80cddcd68758512370d217b19f8890Nathan Harold protected void finalize() throws Throwable { 628330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 629330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 630330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 631330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 632330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 6338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 6348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 635a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold @VisibleForTesting 636a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold public int getResourceId() { 6378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 6388dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 639ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 640ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold @Override 641ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold public String toString() { 642ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new StringBuilder() 643ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("UdpEncapsulationSocket{port=") 644ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mPort) 645ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(",resourceId=") 646ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mResourceId) 647ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("}") 648ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .toString(); 649ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 650330e1089da80cddcd68758512370d217b19f8890Nathan Harold }; 651330e1089da80cddcd68758512370d217b19f8890Nathan Harold 652330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 653c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation and bind to the given port. 654330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 655c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 656330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 657c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @param port a local UDP port 658c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to the given port 659c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 660c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 661330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 662330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 663330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 664330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 665330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 666330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 6675cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 668330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) 669330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 6708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /* 6718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * Most range checking is done in the service, but this version of the constructor expects 6728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * a valid port number, and zero cannot be checked after being passed to the service. 6738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold */ 6748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (port == 0) { 6758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new IllegalArgumentException("Specified port must be a valid port number!"); 6768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 677ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold try { 678ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new UdpEncapsulationSocket(mService, port); 679ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 680ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 681ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 682330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 683330e1089da80cddcd68758512370d217b19f8890Nathan Harold 684330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 685c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Open a socket for UDP encapsulation. 686330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 687c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 688330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 689c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>The local port of the returned socket can be obtained by calling {@link 690c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * UdpEncapsulationSocket#getPort()}. 691330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 692c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @return a socket that is bound to a local port 693c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws IOException indicating that the socket could not be opened or bound 694c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 695330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 696330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 697330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 698330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 699330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 700330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 7015cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 702330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket() 703330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 704ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold try { 705ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new UdpEncapsulationSocket(mService, 0); 706ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 707ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 708ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 709330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 710330e1089da80cddcd68758512370d217b19f8890Nathan Harold 711330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 712c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * This class represents an IpSecTunnelInterface 713c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 714c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as 715c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * local endpoints for IPsec tunnels. 716c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 717c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be 718c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * applied to provide IPsec security to packets sent through the tunnel. While a tunnel 719c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * cannot be used in standalone mode within Android, the higher layers may use the tunnel 720c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * to create Network objects which are accessible to the Android system. 721c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 722c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 723c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public static final class IpSecTunnelInterface implements AutoCloseable { 724592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold private final String mOpPackageName; 725c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final IIpSecService mService; 726c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final InetAddress mRemoteAddress; 727c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final InetAddress mLocalAddress; 728c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final Network mUnderlyingNetwork; 729c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 730c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private String mInterfaceName; 731c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold private int mResourceId = INVALID_RESOURCE_ID; 732c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 733c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** Get the underlying SPI held by this object. */ 7345cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 735c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public String getInterfaceName() { 736c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold return mInterfaceName; 737c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 738c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 739c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 740c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Add an address to the IpSecTunnelInterface 741c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 742c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Add an address which may be used as the local inner address for 743c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * tunneled traffic. 744c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 745c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param address the local address for traffic inside the tunnel 7463f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong * @param prefixLen length of the InetAddress prefix 747c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 748c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 749159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 7503f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { 751da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong try { 752592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mService.addAddressToTunnelInterface( 7533f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); 754ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 755ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 756da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } catch (RemoteException e) { 757da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong throw e.rethrowFromSystemServer(); 758da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } 759c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 760c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 761c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 762c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Remove an address from the IpSecTunnelInterface 763c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 764c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Remove an address which was previously added to the IpSecTunnelInterface 765c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 766c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param address to be removed 7673f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong * @param prefixLen length of the InetAddress prefix 768c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 769c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 770159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 7713f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { 772da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong try { 773592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mService.removeAddressFromTunnelInterface( 7743f2c54b7820c3a568890700479230966fdbcf0a4Benedict Wong mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); 775ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 776ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 777da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } catch (RemoteException e) { 778da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong throw e.rethrowFromSystemServer(); 779da4b0c65a5cbebf6c5e66b869b75dd3a6625cd2eBenedict Wong } 780c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 781c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 782592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, 783c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, 784c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull Network underlyingNetwork) 785c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold throws ResourceUnavailableException, IOException { 786592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mOpPackageName = ctx.getOpPackageName(); 787c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mService = service; 788c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mLocalAddress = localAddress; 789c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mRemoteAddress = remoteAddress; 790c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mUnderlyingNetwork = underlyingNetwork; 7918149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong 7928149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 7938149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong IpSecTunnelInterfaceResponse result = 7948149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mService.createTunnelInterface( 7958149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong localAddress.getHostAddress(), 7968149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong remoteAddress.getHostAddress(), 7978149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong underlyingNetwork, 798592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold new Binder(), 799592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mOpPackageName); 8008149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong switch (result.status) { 8018149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong case Status.OK: 8028149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong break; 8038149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong case Status.RESOURCE_UNAVAILABLE: 8048149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw new ResourceUnavailableException( 8058149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong "No more tunnel interfaces may be allocated by this requester."); 8068149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong default: 8078149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw new RuntimeException( 8088149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong "Unknown status returned by IpSecService: " + result.status); 8098149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 8108149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mResourceId = result.resourceId; 8118149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mInterfaceName = result.interfaceName; 8128149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 8138149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 8148149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 8158149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mCloseGuard.open("constructor"); 816c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 817c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 818c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 819c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Delete an IpSecTunnelInterface 820c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 821c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system 822c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * resources. Any packets bound for this interface either inbound or outbound will 823c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * all be lost. 824c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 825c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @Override 826c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public void close() { 8278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 828592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mService.deleteTunnelInterface(mResourceId, mOpPackageName); 8298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 8308149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 831ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (Exception e) { 832ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // On close we swallow all random exceptions since failure to close is not 833ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // actionable by the user. 834ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 835ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } finally { 836ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mResourceId = INVALID_RESOURCE_ID; 837ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mCloseGuard.close(); 8388149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 839c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 840c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 841c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** Check that the Interface was closed properly. */ 842c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @Override 843c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold protected void finalize() throws Throwable { 844c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold if (mCloseGuard != null) { 845c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold mCloseGuard.warnIfOpen(); 846c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 847c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold close(); 848c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 8498149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong 8508149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong /** @hide */ 8518149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong @VisibleForTesting 8528149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong public int getResourceId() { 8538149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong return mResourceId; 8548149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 855ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 856ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold @Override 857ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold public String toString() { 858ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new StringBuilder() 859ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("IpSecTunnelInterface{ifname=") 860ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mInterfaceName) 861ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(",resourceId=") 862ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append(mResourceId) 863ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .append("}") 864ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold .toString(); 865ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 866c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 867c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 868c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 869c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. 870c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 8718149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the 8728149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * underlying network goes away, and the onLost() callback is received. 8738149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong * 874c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param localAddress The local addres of the tunnel 875c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param remoteAddress The local addres of the tunnel 876c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. 877c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * This network should almost certainly be a network such as WiFi with an L2 address. 878c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties 879c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws IOException indicating that the socket could not be opened or bound 880c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 881c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 882c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 8835cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @NonNull 884159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 885c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, 886c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) 887c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold throws ResourceUnavailableException, IOException { 888ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold try { 889ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold return new IpSecTunnelInterface( 890ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold mContext, mService, localAddress, remoteAddress, underlyingNetwork); 891ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 892ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 893ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 894c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 895c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold 896c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 8977b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will 8987b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * tunnel all traffic for the given direction through the underlying network's interface with 8997b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional 9007b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * IP header and IPsec Header on all inbound traffic). 9017b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * <p>Applications should probably not use this API directly. 9027b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold * 903c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * 904c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied 905c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * transform. 906c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which 907c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * the transform will be used. 908c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @param transform an {@link IpSecTransform} created in tunnel mode 909c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @throws IOException indicating that the transform could not be applied due to a lower 910c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * layer failure. 911c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold * @hide 912c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold */ 913159788455c79fa47847d0c40fcee7aceff2551aeNathan Harold @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) 9145cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, 9155cd64cc8012243c656875be6b84456caeabd60f5Nathan Harold @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 9168149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong try { 9178149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong mService.applyTunnelModeTransform( 918592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold tunnel.getResourceId(), direction, 919592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold transform.getResourceId(), mContext.getOpPackageName()); 920ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } catch (ServiceSpecificException e) { 921ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw rethrowCheckedExceptionFromServiceSpecificException(e); 9228149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } catch (RemoteException e) { 9238149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong throw e.rethrowFromSystemServer(); 9248149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong } 925c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold } 9267b7bea048511a54a628a8c340a2890dc50e7b451Nathan Harold 927c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold /** 928c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * Construct an instance of IpSecManager within an application context. 929330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 930330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param context the application context for this manager 931330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 932330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 933592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold public IpSecManager(Context ctx, IIpSecService service) { 934592dadbd43fcb7c5d67e737adb34d07923da90c4Nathan Harold mContext = ctx; 935330e1089da80cddcd68758512370d217b19f8890Nathan Harold mService = checkNotNull(service, "missing service"); 936330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 937ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 938ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { 939ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // OsConstants are late binding, so switch statements can't be used. 940ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold if (sse.errorCode == OsConstants.EINVAL) { 941ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw new IllegalArgumentException(sse); 942ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } else if (sse.errorCode == OsConstants.EAGAIN) { 943ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw new IllegalStateException(sse); 944ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { 945ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw new UnsupportedOperationException(sse); 946ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 947ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 948ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 949ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold /** 950ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * Convert an Errno SSE to the correct Unchecked exception type. 951ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * 952ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * This method never actually returns. 953ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold */ 954ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // package 955ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold static RuntimeException 956ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) { 957ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold maybeHandleServiceSpecificException(sse); 958ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw new RuntimeException(sse); 959ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 960ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold 961ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold /** 962ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * Convert an Errno SSE to the correct Checked or Unchecked exception type. 963ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * 964ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * This method may throw IOException, or it may throw an unchecked exception; it will never 965ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold * actually return. 966ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold */ 967ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // package 968ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold static IOException rethrowCheckedExceptionFromServiceSpecificException( 969ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold ServiceSpecificException sse) throws IOException { 970ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // First see if this is an unchecked exception of a type we know. 971ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // If so, then we prefer the unchecked (specific) type of exception. 972ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold maybeHandleServiceSpecificException(sse); 973ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold // If not, then all we can do is provide the SSE in the form of an IOException. 974ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold throw new ErrnoException( 975ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException(); 976ddeb90aa9db108d4a2e5aadc778a726b65e5c921Nathan Harold } 977330e1089da80cddcd68758512370d217b19f8890Nathan Harold} 978