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