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