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