1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.net; 17 18 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 19 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.RequiresFeature; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.annotation.SystemService; 26 import android.annotation.TestApi; 27 import android.content.Context; 28 import android.content.pm.PackageManager; 29 import android.os.Binder; 30 import android.os.IBinder; 31 import android.os.ParcelFileDescriptor; 32 import android.os.RemoteException; 33 import android.os.ServiceSpecificException; 34 import android.system.ErrnoException; 35 import android.system.OsConstants; 36 import android.util.AndroidException; 37 import android.util.Log; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.modules.utils.build.SdkLevel; 41 42 import dalvik.system.CloseGuard; 43 44 import java.io.FileDescriptor; 45 import java.io.IOException; 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.net.DatagramSocket; 49 import java.net.InetAddress; 50 import java.net.Socket; 51 import java.util.Objects; 52 53 /** 54 * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply 55 * confidentiality (encryption) and integrity (authentication) to IP traffic. 56 * 57 * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create 58 * transport mode security associations and apply them to individual sockets. Applications looking 59 * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}. 60 * 61 * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the 62 * Internet Protocol</a> 63 */ 64 @SystemService(Context.IPSEC_SERVICE) 65 public class IpSecManager { 66 private static final String TAG = "IpSecManager"; 67 68 /** 69 * Feature flag to declare the kernel support of updating IPsec SAs. 70 * 71 * <p>Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device 72 * has the requisite kernel support for migrating IPsec tunnels to new source/destination 73 * addresses. 74 * 75 * <p>This feature implies that the device supports XFRM Migration (CONFIG_XFRM_MIGRATE) and has 76 * the kernel fixes to allow XFRM Migration correctly 77 * 78 * @see android.content.pm.PackageManager#FEATURE_IPSEC_TUNNEL_MIGRATION 79 * @hide 80 */ 81 // Redefine this flag here so that IPsec code shipped in a mainline module can build on old 82 // platforms before FEATURE_IPSEC_TUNNEL_MIGRATION API is released. 83 public static final String FEATURE_IPSEC_TUNNEL_MIGRATION = 84 "android.software.ipsec_tunnel_migration"; 85 86 /** 87 * Used when applying a transform to direct traffic through an {@link IpSecTransform} 88 * towards the host. 89 * 90 * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 91 */ 92 public static final int DIRECTION_IN = 0; 93 94 /** 95 * Used when applying a transform to direct traffic through an {@link IpSecTransform} 96 * away from the host. 97 * 98 * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 99 */ 100 public static final int DIRECTION_OUT = 1; 101 102 /** 103 * Used when applying a transform to direct traffic through an {@link IpSecTransform} for 104 * forwarding between interfaces. 105 * 106 * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. 107 * 108 * @hide 109 */ 110 @SystemApi(client = MODULE_LIBRARIES) 111 public static final int DIRECTION_FWD = 2; 112 113 /** @hide */ 114 @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) 115 @Retention(RetentionPolicy.SOURCE) 116 public @interface PolicyDirection {} 117 118 /** 119 * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. 120 * 121 * <p>No IPsec packet may contain an SPI of 0. 122 * 123 * @hide 124 */ 125 @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; 126 127 /** @hide */ 128 public interface Status { 129 int OK = 0; 130 int RESOURCE_UNAVAILABLE = 1; 131 int SPI_UNAVAILABLE = 2; 132 } 133 134 /** @hide */ 135 public static final int INVALID_RESOURCE_ID = -1; 136 137 /** 138 * Thrown to indicate that a requested SPI is in use. 139 * 140 * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on 141 * one device. If this error is encountered, a new SPI is required before a transform may be 142 * created. This error can be avoided by calling {@link 143 * IpSecManager#allocateSecurityParameterIndex}. 144 */ 145 public static final class SpiUnavailableException extends AndroidException { 146 private final int mSpi; 147 148 /** 149 * Construct an exception indicating that a transform with the given SPI is already in use 150 * or otherwise unavailable. 151 * 152 * @param msg description indicating the colliding SPI 153 * @param spi the SPI that could not be used due to a collision 154 */ SpiUnavailableException(String msg, int spi)155 SpiUnavailableException(String msg, int spi) { 156 super(msg + " (spi: " + spi + ")"); 157 mSpi = spi; 158 } 159 160 /** Get the SPI that caused a collision. */ getSpi()161 public int getSpi() { 162 return mSpi; 163 } 164 } 165 166 /** 167 * Thrown to indicate that an IPsec resource is unavailable. 168 * 169 * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link 170 * IpSecTransform}, or other system resources. If this exception is thrown, users should release 171 * allocated objects of the type requested. 172 */ 173 public static final class ResourceUnavailableException extends AndroidException { 174 ResourceUnavailableException(String msg)175 ResourceUnavailableException(String msg) { 176 super(msg); 177 } 178 } 179 180 private final Context mContext; 181 private final IIpSecService mService; 182 183 /** 184 * This class represents a reserved SPI. 185 * 186 * <p>Objects of this type are used to track reserved security parameter indices. They can be 187 * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released 188 * by calling {@link #close()} when they are no longer needed. 189 */ 190 public static final class SecurityParameterIndex implements AutoCloseable { 191 private final IIpSecService mService; 192 private final InetAddress mDestinationAddress; 193 private final CloseGuard mCloseGuard = CloseGuard.get(); 194 private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; 195 private int mResourceId = INVALID_RESOURCE_ID; 196 197 /** Get the underlying SPI held by this object. */ getSpi()198 public int getSpi() { 199 return mSpi; 200 } 201 202 /** 203 * Release an SPI that was previously reserved. 204 * 205 * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is 206 * applied to an IpSecTransform, it will become unusable for future transforms but should 207 * still be closed to ensure system resources are released. 208 */ 209 @Override close()210 public void close() { 211 try { 212 mService.releaseSecurityParameterIndex(mResourceId); 213 } catch (RemoteException e) { 214 throw e.rethrowFromSystemServer(); 215 } catch (Exception e) { 216 // On close we swallow all random exceptions since failure to close is not 217 // actionable by the user. 218 Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 219 } finally { 220 mResourceId = INVALID_RESOURCE_ID; 221 mCloseGuard.close(); 222 } 223 } 224 225 /** Check that the SPI was closed properly. */ 226 @Override finalize()227 protected void finalize() throws Throwable { 228 if (mCloseGuard != null) { 229 mCloseGuard.warnIfOpen(); 230 } 231 232 close(); 233 } 234 SecurityParameterIndex( @onNull IIpSecService service, InetAddress destinationAddress, int spi)235 private SecurityParameterIndex( 236 @NonNull IIpSecService service, InetAddress destinationAddress, int spi) 237 throws ResourceUnavailableException, SpiUnavailableException { 238 mService = service; 239 mDestinationAddress = destinationAddress; 240 try { 241 IpSecSpiResponse result = 242 mService.allocateSecurityParameterIndex( 243 destinationAddress.getHostAddress(), spi, new Binder()); 244 245 if (result == null) { 246 throw new NullPointerException("Received null response from IpSecService"); 247 } 248 249 int status = result.status; 250 switch (status) { 251 case Status.OK: 252 break; 253 case Status.RESOURCE_UNAVAILABLE: 254 throw new ResourceUnavailableException( 255 "No more SPIs may be allocated by this requester."); 256 case Status.SPI_UNAVAILABLE: 257 throw new SpiUnavailableException("Requested SPI is unavailable", spi); 258 default: 259 throw new RuntimeException( 260 "Unknown status returned by IpSecService: " + status); 261 } 262 mSpi = result.spi; 263 mResourceId = result.resourceId; 264 265 if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { 266 throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); 267 } 268 269 if (mResourceId == INVALID_RESOURCE_ID) { 270 throw new RuntimeException( 271 "Invalid Resource ID returned by IpSecService: " + status); 272 } 273 } catch (RemoteException e) { 274 throw e.rethrowFromSystemServer(); 275 } 276 mCloseGuard.open("close"); 277 } 278 279 /** @hide */ 280 @VisibleForTesting getResourceId()281 public int getResourceId() { 282 return mResourceId; 283 } 284 285 @Override toString()286 public String toString() { 287 return new StringBuilder() 288 .append("SecurityParameterIndex{spi=") 289 .append(mSpi) 290 .append(",resourceId=") 291 .append(mResourceId) 292 .append("}") 293 .toString(); 294 } 295 } 296 297 /** 298 * Reserve a random SPI for traffic bound to or from the specified destination address. 299 * 300 * <p>If successful, this SPI is guaranteed available until released by a call to {@link 301 * SecurityParameterIndex#close()}. 302 * 303 * @param destinationAddress the destination address for traffic bearing the requested SPI. 304 * For inbound traffic, the destination should be an address currently assigned on-device. 305 * @return the reserved SecurityParameterIndex 306 * @throws ResourceUnavailableException indicating that too many SPIs are 307 * currently allocated for this user 308 */ 309 @NonNull allocateSecurityParameterIndex( @onNull InetAddress destinationAddress)310 public SecurityParameterIndex allocateSecurityParameterIndex( 311 @NonNull InetAddress destinationAddress) throws ResourceUnavailableException { 312 try { 313 return new SecurityParameterIndex( 314 mService, 315 destinationAddress, 316 IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); 317 } catch (ServiceSpecificException e) { 318 throw rethrowUncheckedExceptionFromServiceSpecificException(e); 319 } catch (SpiUnavailableException unlikely) { 320 // Because this function allocates a totally random SPI, it really shouldn't ever 321 // fail to allocate an SPI; we simply need this because the exception is checked. 322 throw new ResourceUnavailableException("No SPIs available"); 323 } 324 } 325 326 /** 327 * Reserve the requested SPI for traffic bound to or from the specified destination address. 328 * 329 * <p>If successful, this SPI is guaranteed available until released by a call to {@link 330 * SecurityParameterIndex#close()}. 331 * 332 * @param destinationAddress the destination address for traffic bearing the requested SPI. 333 * For inbound traffic, the destination should be an address currently assigned on-device. 334 * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See 335 * RFC 4303 Section 2.1. 336 * @return the reserved SecurityParameterIndex 337 * @throws ResourceUnavailableException indicating that too many SPIs are 338 * currently allocated for this user 339 * @throws SpiUnavailableException indicating that the requested SPI could not be 340 * reserved 341 */ 342 @NonNull allocateSecurityParameterIndex( @onNull InetAddress destinationAddress, int requestedSpi)343 public SecurityParameterIndex allocateSecurityParameterIndex( 344 @NonNull InetAddress destinationAddress, int requestedSpi) 345 throws SpiUnavailableException, ResourceUnavailableException { 346 if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { 347 throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); 348 } 349 try { 350 return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); 351 } catch (ServiceSpecificException e) { 352 throw rethrowUncheckedExceptionFromServiceSpecificException(e); 353 } 354 } 355 356 /** 357 * Apply an IPsec transform to a stream socket. 358 * 359 * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 360 * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 361 * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 362 * unprotected traffic can resume on that socket. 363 * 364 * <p>For security reasons, the destination address of any traffic on the socket must match the 365 * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 366 * other IP address will result in an IOException. In addition, reads and writes on the socket 367 * will throw IOException if the user deactivates the transform (by calling {@link 368 * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 369 * 370 * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 371 * applied transform before completion of graceful shutdown may result in the shutdown sequence 372 * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 373 * prior to deactivating the applied transform. Socket closure may be performed asynchronously 374 * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 375 * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 376 * sufficient to ensure shutdown. 377 * 378 * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 379 * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 380 * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 381 * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 382 * 383 * <h4>Rekey Procedure</h4> 384 * 385 * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 386 * will be removed and the new transform will take effect immediately, sending all traffic on 387 * the new transform; however, when applying a transform in the inbound direction, traffic 388 * on the old transform will continue to be decrypted and delivered until that transform is 389 * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 390 * procedures where both transforms are valid until both endpoints are using the new transform 391 * and all in-flight packets have been received. 392 * 393 * @param socket a stream socket 394 * @param direction the direction in which the transform should be applied 395 * @param transform a transport mode {@code IpSecTransform} 396 * @throws IOException indicating that the transform could not be applied 397 */ applyTransportModeTransform(@onNull Socket socket, @PolicyDirection int direction, @NonNull IpSecTransform transform)398 public void applyTransportModeTransform(@NonNull Socket socket, 399 @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 400 // Ensure creation of FD. See b/77548890 for more details. 401 socket.getSoLinger(); 402 403 applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 404 } 405 406 /** 407 * Apply an IPsec transform to a datagram socket. 408 * 409 * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 410 * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 411 * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 412 * unprotected traffic can resume on that socket. 413 * 414 * <p>For security reasons, the destination address of any traffic on the socket must match the 415 * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 416 * other IP address will result in an IOException. In addition, reads and writes on the socket 417 * will throw IOException if the user deactivates the transform (by calling {@link 418 * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 419 * 420 * <h4>Rekey Procedure</h4> 421 * 422 * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 423 * will be removed and the new transform will take effect immediately, sending all traffic on 424 * the new transform; however, when applying a transform in the inbound direction, traffic 425 * on the old transform will continue to be decrypted and delivered until that transform is 426 * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 427 * procedures where both transforms are valid until both endpoints are using the new transform 428 * and all in-flight packets have been received. 429 * 430 * @param socket a datagram socket 431 * @param direction the direction in which the transform should be applied 432 * @param transform a transport mode {@code IpSecTransform} 433 * @throws IOException indicating that the transform could not be applied 434 */ applyTransportModeTransform(@onNull DatagramSocket socket, @PolicyDirection int direction, @NonNull IpSecTransform transform)435 public void applyTransportModeTransform(@NonNull DatagramSocket socket, 436 @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 437 applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); 438 } 439 440 /** 441 * Apply an IPsec transform to a socket. 442 * 443 * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the 444 * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When 445 * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, 446 * unprotected traffic can resume on that socket. 447 * 448 * <p>For security reasons, the destination address of any traffic on the socket must match the 449 * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any 450 * other IP address will result in an IOException. In addition, reads and writes on the socket 451 * will throw IOException if the user deactivates the transform (by calling {@link 452 * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. 453 * 454 * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an 455 * applied transform before completion of graceful shutdown may result in the shutdown sequence 456 * failing to complete. As such, applications requiring graceful shutdown MUST close the socket 457 * prior to deactivating the applied transform. Socket closure may be performed asynchronously 458 * (in batches), so the returning of a close function does not guarantee shutdown of a socket. 459 * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is 460 * sufficient to ensure shutdown. 461 * 462 * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), 463 * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] 464 * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the 465 * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. 466 * 467 * <h4>Rekey Procedure</h4> 468 * 469 * <p>When applying a new tranform to a socket in the outbound direction, the previous transform 470 * will be removed and the new transform will take effect immediately, sending all traffic on 471 * the new transform; however, when applying a transform in the inbound direction, traffic 472 * on the old transform will continue to be decrypted and delivered until that transform is 473 * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey 474 * procedures where both transforms are valid until both endpoints are using the new transform 475 * and all in-flight packets have been received. 476 * 477 * @param socket a socket file descriptor 478 * @param direction the direction in which the transform should be applied 479 * @param transform a transport mode {@code IpSecTransform} 480 * @throws IOException indicating that the transform could not be applied 481 */ applyTransportModeTransform(@onNull FileDescriptor socket, @PolicyDirection int direction, @NonNull IpSecTransform transform)482 public void applyTransportModeTransform(@NonNull FileDescriptor socket, 483 @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 484 // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() 485 // constructor takes control and closes the user's FD when we exit the method. 486 try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 487 mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); 488 } catch (ServiceSpecificException e) { 489 throw rethrowCheckedExceptionFromServiceSpecificException(e); 490 } catch (RemoteException e) { 491 throw e.rethrowFromSystemServer(); 492 } 493 } 494 495 /** 496 * Remove an IPsec transform from a stream socket. 497 * 498 * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 499 * socket allows the socket to be reused for communication in the clear. 500 * 501 * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 502 * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 503 * is called. 504 * 505 * @param socket a socket that previously had a transform applied to it 506 * @throws IOException indicating that the transform could not be removed from the socket 507 */ removeTransportModeTransforms(@onNull Socket socket)508 public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { 509 // Ensure creation of FD. See b/77548890 for more details. 510 socket.getSoLinger(); 511 512 removeTransportModeTransforms(socket.getFileDescriptor$()); 513 } 514 515 /** 516 * Remove an IPsec transform from a datagram socket. 517 * 518 * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 519 * socket allows the socket to be reused for communication in the clear. 520 * 521 * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 522 * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 523 * is called. 524 * 525 * @param socket a socket that previously had a transform applied to it 526 * @throws IOException indicating that the transform could not be removed from the socket 527 */ removeTransportModeTransforms(@onNull DatagramSocket socket)528 public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException { 529 removeTransportModeTransforms(socket.getFileDescriptor$()); 530 } 531 532 /** 533 * Remove an IPsec transform from a socket. 534 * 535 * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a 536 * socket allows the socket to be reused for communication in the clear. 537 * 538 * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling 539 * {@link IpSecTransform#close()}, then communication on the socket will fail until this method 540 * is called. 541 * 542 * @param socket a socket that previously had a transform applied to it 543 * @throws IOException indicating that the transform could not be removed from the socket 544 */ removeTransportModeTransforms(@onNull FileDescriptor socket)545 public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { 546 try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 547 mService.removeTransportModeTransforms(pfd); 548 } catch (ServiceSpecificException e) { 549 throw rethrowCheckedExceptionFromServiceSpecificException(e); 550 } catch (RemoteException e) { 551 throw e.rethrowFromSystemServer(); 552 } 553 } 554 555 /** 556 * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of 557 * cleanup if a tunneled Network experiences a change in default route. The Network will drop 558 * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is 559 * lost, all traffic will drop. 560 * 561 * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. 562 * 563 * @param net a network that currently has transform applied to it. 564 * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given 565 * network 566 * @hide 567 */ removeTunnelModeTransform(Network net, IpSecTransform transform)568 public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} 569 570 /** 571 * This class provides access to a UDP encapsulation Socket. 572 * 573 * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2 574 * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link 575 * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the 576 * caller. The caller should not close the {@code FileDescriptor} returned by {@link 577 * #getFileDescriptor}, but should use {@link #close} instead. 578 * 579 * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic 580 * of the next user who binds to that port. To prevent this scenario, these sockets are held 581 * open by the system so that they may only be closed by calling {@link #close} or when the user 582 * process exits. 583 */ 584 public static final class UdpEncapsulationSocket implements AutoCloseable { 585 private final ParcelFileDescriptor mPfd; 586 private final IIpSecService mService; 587 private int mResourceId = INVALID_RESOURCE_ID; 588 private final int mPort; 589 private final CloseGuard mCloseGuard = CloseGuard.get(); 590 UdpEncapsulationSocket(@onNull IIpSecService service, int port)591 private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) 592 throws ResourceUnavailableException, IOException { 593 mService = service; 594 try { 595 IpSecUdpEncapResponse result = 596 mService.openUdpEncapsulationSocket(port, new Binder()); 597 switch (result.status) { 598 case Status.OK: 599 break; 600 case Status.RESOURCE_UNAVAILABLE: 601 throw new ResourceUnavailableException( 602 "No more Sockets may be allocated by this requester."); 603 default: 604 throw new RuntimeException( 605 "Unknown status returned by IpSecService: " + result.status); 606 } 607 mResourceId = result.resourceId; 608 mPort = result.port; 609 mPfd = result.fileDescriptor; 610 } catch (RemoteException e) { 611 throw e.rethrowFromSystemServer(); 612 } 613 mCloseGuard.open("close"); 614 } 615 616 /** Get the encapsulation socket's file descriptor. */ getFileDescriptor()617 public FileDescriptor getFileDescriptor() { 618 if (mPfd == null) { 619 return null; 620 } 621 return mPfd.getFileDescriptor(); 622 } 623 624 /** Get the bound port of the wrapped socket. */ getPort()625 public int getPort() { 626 return mPort; 627 } 628 629 /** 630 * Close this socket. 631 * 632 * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's 633 * resource limits, and forgetting to close them eventually will result in {@link 634 * ResourceUnavailableException} being thrown. 635 */ 636 @Override close()637 public void close() throws IOException { 638 try { 639 mService.closeUdpEncapsulationSocket(mResourceId); 640 mResourceId = INVALID_RESOURCE_ID; 641 } catch (RemoteException e) { 642 throw e.rethrowFromSystemServer(); 643 } catch (Exception e) { 644 // On close we swallow all random exceptions since failure to close is not 645 // actionable by the user. 646 Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 647 } finally { 648 mResourceId = INVALID_RESOURCE_ID; 649 mCloseGuard.close(); 650 } 651 652 try { 653 mPfd.close(); 654 } catch (IOException e) { 655 Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); 656 throw e; 657 } 658 } 659 660 /** Check that the socket was closed properly. */ 661 @Override finalize()662 protected void finalize() throws Throwable { 663 if (mCloseGuard != null) { 664 mCloseGuard.warnIfOpen(); 665 } 666 close(); 667 } 668 669 /** @hide */ 670 @SystemApi(client = MODULE_LIBRARIES) getResourceId()671 public int getResourceId() { 672 return mResourceId; 673 } 674 675 @Override toString()676 public String toString() { 677 return new StringBuilder() 678 .append("UdpEncapsulationSocket{port=") 679 .append(mPort) 680 .append(",resourceId=") 681 .append(mResourceId) 682 .append("}") 683 .toString(); 684 } 685 }; 686 687 /** 688 * Open a socket for UDP encapsulation and bind to the given port. 689 * 690 * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 691 * 692 * @param port a local UDP port 693 * @return a socket that is bound to the given port 694 * @throws IOException indicating that the socket could not be opened or bound 695 * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 696 */ 697 // Returning a socket in this fashion that has been created and bound by the system 698 // is the only safe way to ensure that a socket is both accessible to the user and 699 // safely usable for Encapsulation without allowing a user to possibly unbind from/close 700 // the port, which could potentially impact the traffic of the next user who binds to that 701 // socket. 702 @NonNull openUdpEncapsulationSocket(int port)703 public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) 704 throws IOException, ResourceUnavailableException { 705 /* 706 * Most range checking is done in the service, but this version of the constructor expects 707 * a valid port number, and zero cannot be checked after being passed to the service. 708 */ 709 if (port == 0) { 710 throw new IllegalArgumentException("Specified port must be a valid port number!"); 711 } 712 try { 713 return new UdpEncapsulationSocket(mService, port); 714 } catch (ServiceSpecificException e) { 715 throw rethrowCheckedExceptionFromServiceSpecificException(e); 716 } 717 } 718 719 /** 720 * Open a socket for UDP encapsulation. 721 * 722 * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. 723 * 724 * <p>The local port of the returned socket can be obtained by calling {@link 725 * UdpEncapsulationSocket#getPort()}. 726 * 727 * @return a socket that is bound to a local port 728 * @throws IOException indicating that the socket could not be opened or bound 729 * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 730 */ 731 // Returning a socket in this fashion that has been created and bound by the system 732 // is the only safe way to ensure that a socket is both accessible to the user and 733 // safely usable for Encapsulation without allowing a user to possibly unbind from/close 734 // the port, which could potentially impact the traffic of the next user who binds to that 735 // socket. 736 @NonNull openUdpEncapsulationSocket()737 public UdpEncapsulationSocket openUdpEncapsulationSocket() 738 throws IOException, ResourceUnavailableException { 739 try { 740 return new UdpEncapsulationSocket(mService, 0); 741 } catch (ServiceSpecificException e) { 742 throw rethrowCheckedExceptionFromServiceSpecificException(e); 743 } 744 } 745 746 /** 747 * This class represents an IpSecTunnelInterface 748 * 749 * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as 750 * local endpoints for IPsec tunnels. 751 * 752 * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be 753 * applied to provide IPsec security to packets sent through the tunnel. While a tunnel 754 * cannot be used in standalone mode within Android, the higher layers may use the tunnel 755 * to create Network objects which are accessible to the Android system. 756 * @hide 757 */ 758 @SystemApi 759 public static final class IpSecTunnelInterface implements AutoCloseable { 760 private final String mOpPackageName; 761 private final IIpSecService mService; 762 private final InetAddress mRemoteAddress; 763 private final InetAddress mLocalAddress; 764 private final Network mUnderlyingNetwork; 765 private final CloseGuard mCloseGuard = CloseGuard.get(); 766 private String mInterfaceName; 767 private int mResourceId = INVALID_RESOURCE_ID; 768 769 /** Get the underlying SPI held by this object. */ 770 @NonNull getInterfaceName()771 public String getInterfaceName() { 772 return mInterfaceName; 773 } 774 775 /** 776 * Add an address to the IpSecTunnelInterface 777 * 778 * <p>Add an address which may be used as the local inner address for 779 * tunneled traffic. 780 * 781 * @param address the local address for traffic inside the tunnel 782 * @param prefixLen length of the InetAddress prefix 783 * @hide 784 */ 785 @SystemApi 786 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) 787 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) addAddress(@onNull InetAddress address, int prefixLen)788 public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { 789 try { 790 mService.addAddressToTunnelInterface( 791 mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); 792 } catch (ServiceSpecificException e) { 793 throw rethrowCheckedExceptionFromServiceSpecificException(e); 794 } catch (RemoteException e) { 795 throw e.rethrowFromSystemServer(); 796 } 797 } 798 799 /** 800 * Remove an address from the IpSecTunnelInterface 801 * 802 * <p>Remove an address which was previously added to the IpSecTunnelInterface 803 * 804 * @param address to be removed 805 * @param prefixLen length of the InetAddress prefix 806 * @hide 807 */ 808 @SystemApi 809 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) 810 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) removeAddress(@onNull InetAddress address, int prefixLen)811 public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { 812 try { 813 mService.removeAddressFromTunnelInterface( 814 mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); 815 } catch (ServiceSpecificException e) { 816 throw rethrowCheckedExceptionFromServiceSpecificException(e); 817 } catch (RemoteException e) { 818 throw e.rethrowFromSystemServer(); 819 } 820 } 821 822 /** 823 * Update the underlying network for this IpSecTunnelInterface. 824 * 825 * <p>This new underlying network will be used for all transforms applied AFTER this call is 826 * complete. Before {@link IpSecTransform}(s) with matching addresses are applied to this 827 * tunnel interface, traffic will still use the old transform, and be routed on the old 828 * underlying network. 829 * 830 * <p>To migrate IPsec tunnel mode traffic, a caller should: 831 * 832 * <ol> 833 * <li>Update the IpSecTunnelInterface’s underlying network. 834 * <li>Apply the new {@link IpSecTransform}(s) to this IpSecTunnelInterface. These can be 835 * new {@link IpSecTransform}(s) with matching addresses, or {@link IpSecTransform}(s) 836 * that have started migration (see {@link 837 * IpSecManager#startTunnelModeTransformMigration}). 838 * </ol> 839 * 840 * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. 841 * This network MUST be a functional {@link Network} with valid {@link LinkProperties}, 842 * and MUST never be the network exposing this IpSecTunnelInterface, otherwise this 843 * method will throw an {@link IllegalArgumentException}. If the IpSecTunnelInterface is 844 * later added to this network, all outbound traffic will be blackholed. 845 */ 846 // The purpose of making updating network and applying transforms separate is to leave open 847 // the possibility to support lossless migration procedures. To do that, Android platform 848 // will need to support multiple inbound tunnel mode transforms, just like it can support 849 // multiple transport mode transforms. 850 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) 851 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) setUnderlyingNetwork(@onNull Network underlyingNetwork)852 public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException { 853 try { 854 mService.setNetworkForTunnelInterface( 855 mResourceId, underlyingNetwork, mOpPackageName); 856 } catch (RemoteException e) { 857 throw e.rethrowFromSystemServer(); 858 } 859 } 860 IpSecTunnelInterface(@onNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)861 private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, 862 @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, 863 @NonNull Network underlyingNetwork) 864 throws ResourceUnavailableException, IOException { 865 mOpPackageName = ctx.getOpPackageName(); 866 mService = service; 867 mLocalAddress = localAddress; 868 mRemoteAddress = remoteAddress; 869 mUnderlyingNetwork = underlyingNetwork; 870 871 try { 872 IpSecTunnelInterfaceResponse result = 873 mService.createTunnelInterface( 874 localAddress.getHostAddress(), 875 remoteAddress.getHostAddress(), 876 underlyingNetwork, 877 new Binder(), 878 mOpPackageName); 879 switch (result.status) { 880 case Status.OK: 881 break; 882 case Status.RESOURCE_UNAVAILABLE: 883 throw new ResourceUnavailableException( 884 "No more tunnel interfaces may be allocated by this requester."); 885 default: 886 throw new RuntimeException( 887 "Unknown status returned by IpSecService: " + result.status); 888 } 889 mResourceId = result.resourceId; 890 mInterfaceName = result.interfaceName; 891 } catch (RemoteException e) { 892 throw e.rethrowFromSystemServer(); 893 } 894 mCloseGuard.open("close"); 895 } 896 897 /** 898 * Delete an IpSecTunnelInterface 899 * 900 * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system 901 * resources. Any packets bound for this interface either inbound or outbound will 902 * all be lost. 903 */ 904 @Override close()905 public void close() { 906 try { 907 mService.deleteTunnelInterface(mResourceId, mOpPackageName); 908 } catch (RemoteException e) { 909 throw e.rethrowFromSystemServer(); 910 } catch (Exception e) { 911 // On close we swallow all random exceptions since failure to close is not 912 // actionable by the user. 913 Log.e(TAG, "Failed to close " + this + ", Exception=" + e); 914 } finally { 915 mResourceId = INVALID_RESOURCE_ID; 916 mCloseGuard.close(); 917 } 918 } 919 920 /** Check that the Interface was closed properly. */ 921 @Override finalize()922 protected void finalize() throws Throwable { 923 if (mCloseGuard != null) { 924 mCloseGuard.warnIfOpen(); 925 } 926 close(); 927 } 928 929 /** @hide */ 930 @VisibleForTesting getResourceId()931 public int getResourceId() { 932 return mResourceId; 933 } 934 935 @NonNull 936 @Override toString()937 public String toString() { 938 return new StringBuilder() 939 .append("IpSecTunnelInterface{ifname=") 940 .append(mInterfaceName) 941 .append(",resourceId=") 942 .append(mResourceId) 943 .append("}") 944 .toString(); 945 } 946 } 947 948 /** 949 * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. 950 * 951 * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the 952 * underlying network goes away, and the onLost() callback is received. 953 * 954 * @param localAddress The local addres of the tunnel 955 * @param remoteAddress The local addres of the tunnel 956 * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. 957 * This network should almost certainly be a network such as WiFi with an L2 address. 958 * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties 959 * @throws IOException indicating that the socket could not be opened or bound 960 * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open 961 * @hide 962 */ 963 @SystemApi 964 @NonNull 965 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) 966 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) createIpSecTunnelInterface(@onNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)967 public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, 968 @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) 969 throws ResourceUnavailableException, IOException { 970 try { 971 return new IpSecTunnelInterface( 972 mContext, mService, localAddress, remoteAddress, underlyingNetwork); 973 } catch (ServiceSpecificException e) { 974 throw rethrowCheckedExceptionFromServiceSpecificException(e); 975 } 976 } 977 978 /** 979 * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will 980 * tunnel all traffic for the given direction through the underlying network's interface with 981 * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional 982 * IP header and IPsec Header on all inbound traffic). 983 * <p>Applications should probably not use this API directly. 984 * 985 * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied 986 * transform. 987 * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which 988 * the transform will be used. 989 * @param transform an {@link IpSecTransform} created in tunnel mode 990 * @throws IOException indicating that the transform could not be applied due to a lower 991 * layer failure. 992 * @hide 993 */ 994 @SystemApi 995 @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) 996 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) applyTunnelModeTransform(@onNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform)997 public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, 998 @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { 999 try { 1000 mService.applyTunnelModeTransform( 1001 tunnel.getResourceId(), direction, 1002 transform.getResourceId(), mContext.getOpPackageName()); 1003 } catch (ServiceSpecificException e) { 1004 throw rethrowCheckedExceptionFromServiceSpecificException(e); 1005 } catch (RemoteException e) { 1006 throw e.rethrowFromSystemServer(); 1007 } 1008 } 1009 1010 /** 1011 * Migrate an active Tunnel Mode IPsec Transform to new source/destination addresses. 1012 * 1013 * <p>Begins the process of migrating a transform and cache the new addresses. To complete the 1014 * migration once started, callers MUST apply the same transform to the appropriate tunnel using 1015 * {@link IpSecManager#applyTunnelModeTransform}. Otherwise, the address update will not be 1016 * committed and the transform will still only process traffic between the current source and 1017 * destination address. One common use case is that the control plane will start the migration 1018 * process and then hand off the transform to the IPsec caller to perform the actual migration 1019 * when the tunnel is ready. 1020 * 1021 * <p>If this method is called multiple times before {@link 1022 * IpSecManager#applyTunnelModeTransform} is called, when the transform is applied, it will be 1023 * migrated to the addresses from the last call. 1024 * 1025 * <p>The provided source and destination addresses MUST share the same address family, but they 1026 * can have a different family from the current addresses. 1027 * 1028 * <p>Transform migration is only supported for tunnel mode transforms. Calling this method on 1029 * other types of transforms will throw an {@code UnsupportedOperationException}. 1030 * 1031 * @see IpSecTunnelInterface#setUnderlyingNetwork 1032 * @param transform a tunnel mode {@link IpSecTransform} 1033 * @param newSourceAddress the new source address 1034 * @param newDestinationAddress the new destination address 1035 * @hide 1036 */ 1037 @SystemApi 1038 @RequiresFeature(FEATURE_IPSEC_TUNNEL_MIGRATION) 1039 @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) startTunnelModeTransformMigration( @onNull IpSecTransform transform, @NonNull InetAddress newSourceAddress, @NonNull InetAddress newDestinationAddress)1040 public void startTunnelModeTransformMigration( 1041 @NonNull IpSecTransform transform, 1042 @NonNull InetAddress newSourceAddress, 1043 @NonNull InetAddress newDestinationAddress) { 1044 if (!SdkLevel.isAtLeastU()) { 1045 throw new UnsupportedOperationException( 1046 "Transform migration only supported for Android 14+"); 1047 } 1048 1049 Objects.requireNonNull(transform, "transform was null"); 1050 Objects.requireNonNull(newSourceAddress, "newSourceAddress was null"); 1051 Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null"); 1052 1053 try { 1054 mService.migrateTransform( 1055 transform.getResourceId(), 1056 newSourceAddress.getHostAddress(), 1057 newDestinationAddress.getHostAddress(), 1058 mContext.getOpPackageName()); 1059 } catch (RemoteException e) { 1060 throw e.rethrowFromSystemServer(); 1061 } 1062 } 1063 1064 /** 1065 * @hide 1066 */ createTransform(IpSecConfig config, IBinder binder, String callingPackage)1067 public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder, 1068 String callingPackage) { 1069 try { 1070 return mService.createTransform(config, binder, callingPackage); 1071 } catch (RemoteException e) { 1072 throw e.rethrowFromSystemServer(); 1073 } 1074 } 1075 1076 /** 1077 * @hide 1078 */ deleteTransform(int resourceId)1079 public void deleteTransform(int resourceId) { 1080 try { 1081 mService.deleteTransform(resourceId); 1082 } catch (RemoteException e) { 1083 throw e.rethrowFromSystemServer(); 1084 } 1085 } 1086 1087 /** @hide */ getTransformState(int transformId)1088 public IpSecTransformState getTransformState(int transformId) 1089 throws IllegalStateException, RemoteException { 1090 return mService.getTransformState(transformId); 1091 } 1092 1093 /** 1094 * Construct an instance of IpSecManager within an application context. 1095 * 1096 * @param context the application context for this manager 1097 * @hide 1098 */ IpSecManager(Context ctx, IIpSecService service)1099 public IpSecManager(Context ctx, IIpSecService service) { 1100 mContext = ctx; 1101 mService = Objects.requireNonNull(service, "missing service"); 1102 } 1103 maybeHandleServiceSpecificException(ServiceSpecificException sse)1104 private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { 1105 // OsConstants are late binding, so switch statements can't be used. 1106 if (sse.errorCode == OsConstants.EINVAL) { 1107 throw new IllegalArgumentException(sse); 1108 } else if (sse.errorCode == OsConstants.EAGAIN) { 1109 throw new IllegalStateException(sse); 1110 } else if (sse.errorCode == OsConstants.EOPNOTSUPP 1111 || sse.errorCode == OsConstants.EPROTONOSUPPORT) { 1112 throw new UnsupportedOperationException(sse); 1113 } 1114 } 1115 1116 /** 1117 * Convert an Errno SSE to the correct Unchecked exception type. 1118 * 1119 * This method never actually returns. 1120 */ 1121 // package 1122 static RuntimeException rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse)1123 rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) { 1124 maybeHandleServiceSpecificException(sse); 1125 throw new RuntimeException(sse); 1126 } 1127 1128 /** 1129 * Convert an Errno SSE to the correct Checked or Unchecked exception type. 1130 * 1131 * This method may throw IOException, or it may throw an unchecked exception; it will never 1132 * actually return. 1133 */ 1134 // package rethrowCheckedExceptionFromServiceSpecificException( ServiceSpecificException sse)1135 static IOException rethrowCheckedExceptionFromServiceSpecificException( 1136 ServiceSpecificException sse) throws IOException { 1137 // First see if this is an unchecked exception of a type we know. 1138 // If so, then we prefer the unchecked (specific) type of exception. 1139 maybeHandleServiceSpecificException(sse); 1140 // If not, then all we can do is provide the SSE in the form of an IOException. 1141 throw new ErrnoException( 1142 "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException(); 1143 } 1144 } 1145