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