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