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