1 /* 2 * Copyright (C) 2011 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 17 package com.android.server.connectivity; 18 19 import static android.Manifest.permission.BIND_VPN_SERVICE; 20 import static android.Manifest.permission.CONTROL_VPN; 21 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 23 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; 24 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 25 import static android.net.RouteInfo.RTN_THROW; 26 import static android.net.RouteInfo.RTN_UNREACHABLE; 27 import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; 28 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO; 29 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO; 30 import static android.os.PowerWhitelistManager.REASON_VPN; 31 import static android.os.UserHandle.PER_USER_RANGE; 32 import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; 33 import static android.telephony.CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT; 34 35 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; 36 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; 37 38 import static java.util.Objects.requireNonNull; 39 40 import android.Manifest; 41 import android.annotation.NonNull; 42 import android.annotation.Nullable; 43 import android.annotation.UserIdInt; 44 import android.app.AppOpsManager; 45 import android.app.Notification; 46 import android.app.NotificationManager; 47 import android.app.PendingIntent; 48 import android.content.BroadcastReceiver; 49 import android.content.ComponentName; 50 import android.content.ContentResolver; 51 import android.content.Context; 52 import android.content.Intent; 53 import android.content.IntentFilter; 54 import android.content.ServiceConnection; 55 import android.content.pm.ApplicationInfo; 56 import android.content.pm.PackageManager; 57 import android.content.pm.PackageManager.NameNotFoundException; 58 import android.content.pm.ResolveInfo; 59 import android.content.pm.UserInfo; 60 import android.net.ConnectivityDiagnosticsManager; 61 import android.net.ConnectivityManager; 62 import android.net.DnsResolver; 63 import android.net.INetd; 64 import android.net.INetworkManagementEventObserver; 65 import android.net.Ikev2VpnProfile; 66 import android.net.InetAddresses; 67 import android.net.IpPrefix; 68 import android.net.IpSecManager; 69 import android.net.IpSecManager.IpSecTunnelInterface; 70 import android.net.IpSecTransform; 71 import android.net.LinkAddress; 72 import android.net.LinkProperties; 73 import android.net.LocalSocket; 74 import android.net.LocalSocketAddress; 75 import android.net.Network; 76 import android.net.NetworkAgent; 77 import android.net.NetworkAgentConfig; 78 import android.net.NetworkCapabilities; 79 import android.net.NetworkInfo; 80 import android.net.NetworkInfo.DetailedState; 81 import android.net.NetworkProvider; 82 import android.net.NetworkRequest; 83 import android.net.NetworkScore; 84 import android.net.NetworkSpecifier; 85 import android.net.RouteInfo; 86 import android.net.TelephonyNetworkSpecifier; 87 import android.net.TransportInfo; 88 import android.net.UidRangeParcel; 89 import android.net.UnderlyingNetworkInfo; 90 import android.net.Uri; 91 import android.net.VpnManager; 92 import android.net.VpnProfileState; 93 import android.net.VpnService; 94 import android.net.VpnTransportInfo; 95 import android.net.ipsec.ike.ChildSaProposal; 96 import android.net.ipsec.ike.ChildSessionCallback; 97 import android.net.ipsec.ike.ChildSessionConfiguration; 98 import android.net.ipsec.ike.ChildSessionParams; 99 import android.net.ipsec.ike.IkeSession; 100 import android.net.ipsec.ike.IkeSessionCallback; 101 import android.net.ipsec.ike.IkeSessionConfiguration; 102 import android.net.ipsec.ike.IkeSessionConnectionInfo; 103 import android.net.ipsec.ike.IkeSessionParams; 104 import android.net.ipsec.ike.IkeTunnelConnectionParams; 105 import android.net.ipsec.ike.exceptions.IkeIOException; 106 import android.net.ipsec.ike.exceptions.IkeNetworkLostException; 107 import android.net.ipsec.ike.exceptions.IkeNonProtocolException; 108 import android.net.ipsec.ike.exceptions.IkeProtocolException; 109 import android.net.ipsec.ike.exceptions.IkeTimeoutException; 110 import android.net.vcn.VcnGatewayConnectionConfig; 111 import android.net.vcn.VcnTransportInfo; 112 import android.os.Binder; 113 import android.os.Build.VERSION_CODES; 114 import android.os.Bundle; 115 import android.os.CancellationSignal; 116 import android.os.FileUtils; 117 import android.os.Handler; 118 import android.os.IBinder; 119 import android.os.INetworkManagementService; 120 import android.os.Looper; 121 import android.os.Parcel; 122 import android.os.ParcelFileDescriptor; 123 import android.os.PersistableBundle; 124 import android.os.Process; 125 import android.os.RemoteException; 126 import android.os.SystemClock; 127 import android.os.SystemService; 128 import android.os.UserHandle; 129 import android.os.UserManager; 130 import android.provider.Settings; 131 import android.security.Credentials; 132 import android.security.KeyStore2; 133 import android.security.keystore.KeyProperties; 134 import android.system.keystore2.Domain; 135 import android.system.keystore2.KeyDescriptor; 136 import android.system.keystore2.KeyPermission; 137 import android.telephony.CarrierConfigManager; 138 import android.telephony.SubscriptionManager; 139 import android.telephony.TelephonyManager; 140 import android.text.TextUtils; 141 import android.util.ArraySet; 142 import android.util.IndentingPrintWriter; 143 import android.util.LocalLog; 144 import android.util.Log; 145 import android.util.Range; 146 import android.util.SparseArray; 147 148 import com.android.internal.R; 149 import com.android.internal.annotations.GuardedBy; 150 import com.android.internal.annotations.VisibleForTesting; 151 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 152 import com.android.internal.net.LegacyVpnInfo; 153 import com.android.internal.net.VpnConfig; 154 import com.android.internal.net.VpnProfile; 155 import com.android.modules.utils.build.SdkLevel; 156 import com.android.net.module.util.BinderUtils; 157 import com.android.net.module.util.LinkPropertiesUtils; 158 import com.android.net.module.util.NetdUtils; 159 import com.android.net.module.util.NetworkStackConstants; 160 import com.android.server.DeviceIdleInternal; 161 import com.android.server.LocalServices; 162 import com.android.server.net.BaseNetworkObserver; 163 import com.android.server.vcn.util.MtuUtils; 164 import com.android.server.vcn.util.PersistableBundleUtils; 165 166 import libcore.io.IoUtils; 167 168 import java.io.File; 169 import java.io.FileDescriptor; 170 import java.io.IOException; 171 import java.io.InputStream; 172 import java.io.OutputStream; 173 import java.net.Inet4Address; 174 import java.net.Inet6Address; 175 import java.net.InetAddress; 176 import java.net.NetworkInterface; 177 import java.net.SocketException; 178 import java.net.UnknownHostException; 179 import java.nio.charset.StandardCharsets; 180 import java.security.GeneralSecurityException; 181 import java.security.KeyStore; 182 import java.security.KeyStoreException; 183 import java.security.NoSuchAlgorithmException; 184 import java.security.cert.Certificate; 185 import java.security.cert.CertificateEncodingException; 186 import java.security.cert.CertificateException; 187 import java.util.ArrayList; 188 import java.util.Arrays; 189 import java.util.Collection; 190 import java.util.Collections; 191 import java.util.HashSet; 192 import java.util.List; 193 import java.util.Objects; 194 import java.util.Set; 195 import java.util.SortedSet; 196 import java.util.TreeSet; 197 import java.util.UUID; 198 import java.util.concurrent.CompletableFuture; 199 import java.util.concurrent.ExecutionException; 200 import java.util.concurrent.Executor; 201 import java.util.concurrent.RejectedExecutionException; 202 import java.util.concurrent.ScheduledFuture; 203 import java.util.concurrent.ScheduledThreadPoolExecutor; 204 import java.util.concurrent.TimeUnit; 205 import java.util.concurrent.atomic.AtomicInteger; 206 207 /** 208 * @hide 209 */ 210 public class Vpn { 211 private static final String NETWORKTYPE = "VPN"; 212 private static final String TAG = "Vpn"; 213 private static final String VPN_PROVIDER_NAME_BASE = "VpnNetworkProvider:"; 214 private static final boolean LOGD = true; 215 private static final String ANDROID_KEYSTORE_PROVIDER = "AndroidKeyStore"; 216 /** Key containing prefix of vpn app excluded list */ 217 @VisibleForTesting static final String VPN_APP_EXCLUDED = "VPNAPPEXCLUDED_"; 218 219 // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on 220 // the device idle allowlist during service launch and VPN bootstrap. 221 private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000; 222 223 // Length of time (in milliseconds) that an app registered for VpnManager events is placed on 224 // the device idle allowlist each time the VpnManager event is fired. 225 private static final long VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS = 30 * 1000; 226 227 private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME = 228 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST; 229 230 /** 231 * The retries for consecutive failures. 232 * 233 * <p>If retries have exceeded the length of this array, the last entry in the array will be 234 * used as a repeating interval. 235 */ 236 private static final long[] IKEV2_VPN_RETRY_DELAYS_MS = 237 {1_000L, 2_000L, 5_000L, 30_000L, 60_000L, 300_000L, 900_000L}; 238 239 /** 240 * A constant to pass to {@link IkeV2VpnRunner#scheduleStartIkeSession(long)} to mean the 241 * delay should be computed automatically with backoff. 242 */ 243 private static final long RETRY_DELAY_AUTO_BACKOFF = -1; 244 245 /** 246 * How long to wait before trying to migrate the IKE connection when NetworkCapabilities or 247 * LinkProperties change in a way that may require migration. 248 * 249 * This delay is useful to avoid multiple migration tries (e.g. when a network changes 250 * both its NC and LP at the same time, e.g. when it first connects) and to minimize the 251 * cases where an old list of addresses is detected for the network. 252 * 253 * In practice, the IKE library reads the LinkProperties of the passed network with 254 * the synchronous {@link ConnectivityManager#getLinkProperties(Network)}, which means in 255 * most cases the race would resolve correctly, but this delay increases the chance that 256 * it correctly is. 257 * Further, using the synchronous method in the IKE library is actually dangerous because 258 * it is racy (it races with {@code IkeNetworkCallbackBase#onLost} and it should be fixed 259 * by using callbacks instead. When that happens, the race within IKE is fixed but the 260 * race between that callback and the one in IkeV2VpnRunner becomes a much bigger problem, 261 * and this delay will be necessary to ensure the correct link address list is used. 262 */ 263 private static final long IKE_DELAY_ON_NC_LP_CHANGE_MS = 300; 264 265 /** 266 * Largest profile size allowable for Platform VPNs. 267 * 268 * <p>The largest platform VPN profiles use IKEv2 RSA Certificate Authentication and have two 269 * X509Certificates, and one RSAPrivateKey. This should lead to a max size of 2x 12kB for the 270 * certificates, plus a reasonable upper bound on the private key of 32kB. The rest of the 271 * profile is expected to be negligible in size. 272 */ 273 @VisibleForTesting static final int MAX_VPN_PROFILE_SIZE_BYTES = 1 << 17; // 128kB 274 275 /** 276 * Network score that VPNs will announce to ConnectivityService. 277 * TODO: remove when the network scoring refactor lands. 278 */ 279 private static final int VPN_DEFAULT_SCORE = 101; 280 281 /** 282 * The recovery timer for data stall. If a session has not successfully revalidated after 283 * the delay, the session will perform MOBIKE or be restarted in an attempt to recover. Delay 284 * counter is reset on successful validation only. 285 * 286 * <p>The first {@code MOBIKE_RECOVERY_ATTEMPT} timers are used for performing MOBIKE. 287 * System will perform session reset for the remaining timers. 288 * <p>If retries have exceeded the length of this array, the last entry in the array will be 289 * used as a repeating interval. 290 */ 291 // TODO: use ms instead to speed up the test. 292 private static final long[] DATA_STALL_RECOVERY_DELAYS_SEC = 293 {1L, 5L, 30L, 60L, 120L, 240L, 480L, 960L}; 294 /** 295 * Maximum attempts to perform MOBIKE when the network is bad. 296 */ 297 private static final int MAX_MOBIKE_RECOVERY_ATTEMPT = 2; 298 /** 299 * The initial token value of IKE session. 300 */ 301 private static final int STARTING_TOKEN = -1; 302 303 // TODO : read this from carrier config instead of a constant 304 @VisibleForTesting 305 public static final int AUTOMATIC_KEEPALIVE_DELAY_SECONDS = 30; 306 307 // Default keepalive timeout for carrier config is 5 minutes. Mimic this. 308 @VisibleForTesting 309 static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60; 310 311 /** 312 * Default keepalive value to consider long-lived TCP connections are expensive on the 313 * VPN network from battery usage point of view. 314 * TODO: consider reading from setting. 315 */ 316 @VisibleForTesting 317 static final int DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC = 60; 318 319 private static final int PREFERRED_IKE_PROTOCOL_UNKNOWN = -1; 320 /** 321 * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_AUTO} and 322 * {@link IkeSessionParams.ESP_ENCAP_TYPE_AUTO} for ESP packets. 323 * 324 * This is one of the possible customization values for 325 * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. 326 */ 327 @VisibleForTesting 328 public static final int PREFERRED_IKE_PROTOCOL_AUTO = 0; 329 /** 330 * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV4} and 331 * {@link IkeSessionParams.ESP_ENCAP_TYPE_UDP} for ESP packets. 332 * 333 * This is one of the possible customization values for 334 * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. 335 */ 336 @VisibleForTesting 337 public static final int PREFERRED_IKE_PROTOCOL_IPV4_UDP = 40; 338 /** 339 * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV6} and 340 * {@link IkeSessionParams.ESP_ENCAP_TYPE_UDP} for ESP packets. 341 * 342 * Do not use this value for production code. Its numeric value will change in future versions. 343 */ 344 @VisibleForTesting 345 public static final int PREFERRED_IKE_PROTOCOL_IPV6_UDP = 60; 346 /** 347 * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV6} and 348 * {@link IkeSessionParams.ESP_ENCAP_TYPE_NONE} for ESP packets. 349 * 350 * This is one of the possible customization values for 351 * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. 352 */ 353 @VisibleForTesting 354 public static final int PREFERRED_IKE_PROTOCOL_IPV6_ESP = 61; 355 356 // TODO: create separate trackers for each unique VPN to support 357 // automated reconnection 358 359 private final Context mContext; 360 private final ConnectivityManager mConnectivityManager; 361 private final AppOpsManager mAppOpsManager; 362 private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager; 363 private final TelephonyManager mTelephonyManager; 364 private final CarrierConfigManager mCarrierConfigManager; 365 private final SubscriptionManager mSubscriptionManager; 366 367 // The context is for specific user which is created from mUserId 368 private final Context mUserIdContext; 369 @VisibleForTesting final Dependencies mDeps; 370 private final NetworkInfo mNetworkInfo; 371 @GuardedBy("this") 372 private int mLegacyState; 373 @GuardedBy("this") 374 @VisibleForTesting protected String mPackage; 375 private int mOwnerUID; 376 private boolean mIsPackageTargetingAtLeastQ; 377 @VisibleForTesting 378 protected String mInterface; 379 private Connection mConnection; 380 381 /** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */ 382 @VisibleForTesting protected VpnRunner mVpnRunner; 383 384 private PendingIntent mStatusIntent; 385 private volatile boolean mEnableTeardown = true; 386 private final INetworkManagementService mNms; 387 private final INetd mNetd; 388 @VisibleForTesting 389 @GuardedBy("this") 390 protected VpnConfig mConfig; 391 private final NetworkProvider mNetworkProvider; 392 @VisibleForTesting 393 protected NetworkAgent mNetworkAgent; 394 private final Looper mLooper; 395 @VisibleForTesting 396 protected NetworkCapabilities mNetworkCapabilities; 397 private final SystemServices mSystemServices; 398 private final Ikev2SessionCreator mIkev2SessionCreator; 399 private final UserManager mUserManager; 400 401 private final VpnProfileStore mVpnProfileStore; 402 403 @VisibleForTesting getVpnProfileStore()404 VpnProfileStore getVpnProfileStore() { 405 return mVpnProfileStore; 406 } 407 408 private static final int MAX_EVENTS_LOGS = 100; 409 private final LocalLog mEventChanges = new LocalLog(MAX_EVENTS_LOGS); 410 411 /** 412 * Cached Map of <subscription ID, CarrierConfigInfo> since retrieving the PersistableBundle 413 * and the target value from CarrierConfigManager is somewhat expensive as it has hundreds of 414 * fields. This cache is cleared when the carrier config changes to ensure data freshness. 415 */ 416 @GuardedBy("this") 417 private final SparseArray<CarrierConfigInfo> mCachedCarrierConfigInfoPerSubId = 418 new SparseArray<>(); 419 420 /** 421 * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This 422 * only applies to {@link VpnService} connections. 423 */ 424 @GuardedBy("this") 425 @VisibleForTesting protected boolean mAlwaysOn = false; 426 427 /** 428 * Whether to disable traffic outside of this VPN even when the VPN is not connected. System 429 * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is 430 * not set. Applies to all types of VPNs. 431 */ 432 @GuardedBy("this") 433 @VisibleForTesting protected boolean mLockdown = false; 434 435 /** 436 * Set of packages in addition to the VPN app itself that can access the network directly when 437 * VPN is not connected even if {@code mLockdown} is set. 438 */ 439 private @NonNull List<String> mLockdownAllowlist = Collections.emptyList(); 440 441 /** 442 * A memory of what UIDs this class told ConnectivityService to block for the lockdown feature. 443 * 444 * Netd maintains ranges of UIDs for which network should be restricted to using only the VPN 445 * for the lockdown feature. This class manages these UIDs and sends this information to netd. 446 * To avoid sending the same commands multiple times (which would be wasteful) and to be able 447 * to revoke lists (when the rules should change), it's simplest to keep this cache of what 448 * netd knows, so it can be diffed and sent most efficiently. 449 * 450 * The contents of this list must only be changed when updating the UIDs lists with netd, 451 * since it needs to keep in sync with the picture netd has of them. 452 * 453 * @see mLockdown 454 */ 455 @GuardedBy("this") 456 private final Set<UidRangeParcel> mBlockedUidsAsToldToConnectivity = new ArraySet<>(); 457 458 // The user id of initiating VPN. 459 private final int mUserId; 460 461 interface RetryScheduler { checkInterruptAndDelay(boolean sleepLonger)462 void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; 463 } 464 465 private static class CarrierConfigInfo { 466 public final String mccMnc; 467 public final int keepaliveDelaySec; 468 public final int encapType; 469 public final int ipVersion; 470 CarrierConfigInfo(String mccMnc, int keepaliveDelaySec, int encapType, int ipVersion)471 CarrierConfigInfo(String mccMnc, int keepaliveDelaySec, 472 int encapType, 473 int ipVersion) { 474 this.mccMnc = mccMnc; 475 this.keepaliveDelaySec = keepaliveDelaySec; 476 this.encapType = encapType; 477 this.ipVersion = ipVersion; 478 } 479 480 @Override toString()481 public String toString() { 482 return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelaySec=" + keepaliveDelaySec 483 + ", encapType=" + encapType + ", ipVersion=" + ipVersion + "]"; 484 } 485 } 486 487 @VisibleForTesting 488 public static class Dependencies { isCallerSystem()489 public boolean isCallerSystem() { 490 return Binder.getCallingUid() == Process.SYSTEM_UID; 491 } 492 startService(final String serviceName)493 public void startService(final String serviceName) { 494 SystemService.start(serviceName); 495 } 496 stopService(final String serviceName)497 public void stopService(final String serviceName) { 498 SystemService.stop(serviceName); 499 } 500 isServiceRunning(final String serviceName)501 public boolean isServiceRunning(final String serviceName) { 502 return SystemService.isRunning(serviceName); 503 } 504 isServiceStopped(final String serviceName)505 public boolean isServiceStopped(final String serviceName) { 506 return SystemService.isStopped(serviceName); 507 } 508 getStateFile()509 public File getStateFile() { 510 return new File("/data/misc/vpn/state"); 511 } 512 getDeviceIdleInternal()513 public DeviceIdleInternal getDeviceIdleInternal() { 514 return LocalServices.getService(DeviceIdleInternal.class); 515 } 516 getIntentForStatusPanel(Context context)517 public PendingIntent getIntentForStatusPanel(Context context) { 518 return VpnConfig.getIntentForStatusPanel(context); 519 } 520 sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final RetryScheduler retryScheduler)521 public void sendArgumentsToDaemon( 522 final String daemon, final LocalSocket socket, final String[] arguments, 523 final RetryScheduler retryScheduler) throws IOException, InterruptedException { 524 final LocalSocketAddress address = new LocalSocketAddress( 525 daemon, LocalSocketAddress.Namespace.RESERVED); 526 527 // Wait for the socket to connect. 528 while (true) { 529 try { 530 socket.connect(address); 531 break; 532 } catch (Exception e) { 533 // ignore 534 } 535 retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); 536 } 537 socket.setSoTimeout(500); 538 539 final OutputStream out = socket.getOutputStream(); 540 for (String argument : arguments) { 541 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 542 if (bytes.length >= 0xFFFF) { 543 throw new IllegalArgumentException("Argument is too large"); 544 } 545 out.write(bytes.length >> 8); 546 out.write(bytes.length); 547 out.write(bytes); 548 retryScheduler.checkInterruptAndDelay(false /* sleepLonger */); 549 } 550 out.write(0xFF); 551 out.write(0xFF); 552 553 // Wait for End-of-File. 554 final InputStream in = socket.getInputStream(); 555 while (true) { 556 try { 557 if (in.read() == -1) { 558 break; 559 } 560 } catch (Exception e) { 561 // ignore 562 } 563 retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); 564 } 565 } 566 567 @NonNull resolve(final String endpoint)568 public InetAddress resolve(final String endpoint) 569 throws ExecutionException, InterruptedException { 570 try { 571 return InetAddresses.parseNumericAddress(endpoint); 572 } catch (IllegalArgumentException e) { 573 // Endpoint is not numeric : fall through and resolve 574 } 575 576 final CancellationSignal cancellationSignal = new CancellationSignal(); 577 try { 578 final DnsResolver resolver = DnsResolver.getInstance(); 579 final CompletableFuture<InetAddress> result = new CompletableFuture(); 580 final DnsResolver.Callback<List<InetAddress>> cb = 581 new DnsResolver.Callback<List<InetAddress>>() { 582 @Override 583 public void onAnswer(@NonNull final List<InetAddress> answer, 584 final int rcode) { 585 if (answer.size() > 0) { 586 result.complete(answer.get(0)); 587 } else { 588 result.completeExceptionally( 589 new UnknownHostException(endpoint)); 590 } 591 } 592 593 @Override 594 public void onError(@Nullable final DnsResolver.DnsException error) { 595 // Unfortunately UnknownHostException doesn't accept a cause, so 596 // print a message here instead. Only show the summary, not the 597 // full stack trace. 598 Log.e(TAG, "Async dns resolver error : " + error); 599 result.completeExceptionally(new UnknownHostException(endpoint)); 600 } 601 }; 602 resolver.query(null /* network, null for default */, endpoint, 603 DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb); 604 return result.get(); 605 } catch (final ExecutionException e) { 606 Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e); 607 throw e; 608 } catch (final InterruptedException e) { 609 Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e); 610 cancellationSignal.cancel(); 611 throw e; 612 } 613 } 614 isInterfacePresent(final Vpn vpn, final String iface)615 public boolean isInterfacePresent(final Vpn vpn, final String iface) { 616 return vpn.jniCheck(iface) != 0; 617 } 618 619 /** 620 * @see ParcelFileDescriptor#adoptFd(int) 621 */ adoptFd(Vpn vpn, int mtu)622 public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { 623 return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu)); 624 } 625 626 /** 627 * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun. 628 */ jniCreate(Vpn vpn, int mtu)629 public int jniCreate(Vpn vpn, int mtu) { 630 return vpn.jniCreate(mtu); 631 } 632 633 /** 634 * Call native method to get the interface name of VPN. 635 */ jniGetName(Vpn vpn, int fd)636 public String jniGetName(Vpn vpn, int fd) { 637 return vpn.jniGetName(fd); 638 } 639 640 /** 641 * Call native method to set the VPN addresses and return the number of addresses. 642 */ jniSetAddresses(Vpn vpn, String interfaze, String addresses)643 public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { 644 return vpn.jniSetAddresses(interfaze, addresses); 645 } 646 647 /** 648 * @see IoUtils#setBlocking(FileDescriptor, boolean) 649 */ setBlocking(FileDescriptor fd, boolean blocking)650 public void setBlocking(FileDescriptor fd, boolean blocking) { 651 try { 652 IoUtils.setBlocking(fd, blocking); 653 } catch (IOException e) { 654 throw new IllegalStateException( 655 "Cannot set tunnel's fd as blocking=" + blocking, e); 656 } 657 } 658 659 /** 660 * Retrieves the next retry delay 661 * 662 * <p>If retries have exceeded the size of IKEV2_VPN_RETRY_DELAYS_MS, the last entry in 663 * the array will be used as a repeating interval. 664 */ getNextRetryDelayMs(int retryCount)665 public long getNextRetryDelayMs(int retryCount) { 666 if (retryCount >= IKEV2_VPN_RETRY_DELAYS_MS.length) { 667 return IKEV2_VPN_RETRY_DELAYS_MS[IKEV2_VPN_RETRY_DELAYS_MS.length - 1]; 668 } else { 669 return IKEV2_VPN_RETRY_DELAYS_MS[retryCount]; 670 } 671 } 672 673 /** Get single threaded executor for IKEv2 VPN */ newScheduledThreadPoolExecutor()674 public ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor() { 675 return new ScheduledThreadPoolExecutor(1); 676 } 677 678 /** Get a NetworkAgent instance */ newNetworkAgent( @onNull Context context, @NonNull Looper looper, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider, @Nullable ValidationStatusCallback callback)679 public NetworkAgent newNetworkAgent( 680 @NonNull Context context, 681 @NonNull Looper looper, 682 @NonNull String logTag, 683 @NonNull NetworkCapabilities nc, 684 @NonNull LinkProperties lp, 685 @NonNull NetworkScore score, 686 @NonNull NetworkAgentConfig config, 687 @Nullable NetworkProvider provider, 688 @Nullable ValidationStatusCallback callback) { 689 return new VpnNetworkAgentWrapper( 690 context, looper, logTag, nc, lp, score, config, provider, callback); 691 } 692 693 /** 694 * Get the length of time to wait before perform data stall recovery when the validation 695 * result is bad. 696 */ getValidationFailRecoverySeconds(int count)697 public long getValidationFailRecoverySeconds(int count) { 698 if (count >= DATA_STALL_RECOVERY_DELAYS_SEC.length) { 699 return DATA_STALL_RECOVERY_DELAYS_SEC[DATA_STALL_RECOVERY_DELAYS_SEC.length - 1]; 700 } else { 701 return DATA_STALL_RECOVERY_DELAYS_SEC[count]; 702 } 703 } 704 705 /** Gets the MTU of an interface using Java NetworkInterface primitives */ getJavaNetworkInterfaceMtu(@ullable String iface, int defaultValue)706 public int getJavaNetworkInterfaceMtu(@Nullable String iface, int defaultValue) 707 throws SocketException { 708 if (iface == null) return defaultValue; 709 710 final NetworkInterface networkInterface = NetworkInterface.getByName(iface); 711 return networkInterface == null ? defaultValue : networkInterface.getMTU(); 712 } 713 714 /** Calculates the VPN Network's max MTU based on underlying network and configuration */ calculateVpnMtu( @onNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu, boolean isIpv4)715 public int calculateVpnMtu( 716 @NonNull List<ChildSaProposal> childProposals, 717 int maxMtu, 718 int underlyingMtu, 719 boolean isIpv4) { 720 return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4); 721 } 722 723 /** Verify the binder calling UID is the one passed in arguments */ verifyCallingUidAndPackage(Context context, String packageName, int userId)724 public void verifyCallingUidAndPackage(Context context, String packageName, int userId) { 725 final int callingUid = Binder.getCallingUid(); 726 if (getAppUid(context, packageName, userId) != callingUid) { 727 throw new SecurityException(packageName + " does not belong to uid " + callingUid); 728 } 729 } 730 } 731 732 @VisibleForTesting 733 interface ValidationStatusCallback { onValidationStatus(int status)734 void onValidationStatus(int status); 735 } 736 Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, @UserIdInt int userId, VpnProfileStore vpnProfileStore)737 public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, 738 @UserIdInt int userId, VpnProfileStore vpnProfileStore) { 739 this(looper, context, new Dependencies(), netService, netd, userId, vpnProfileStore, 740 new SystemServices(context), new Ikev2SessionCreator()); 741 } 742 743 @VisibleForTesting Vpn(Looper looper, Context context, Dependencies deps, INetworkManagementService netService, INetd netd, @UserIdInt int userId, VpnProfileStore vpnProfileStore)744 public Vpn(Looper looper, Context context, Dependencies deps, 745 INetworkManagementService netService, INetd netd, @UserIdInt int userId, 746 VpnProfileStore vpnProfileStore) { 747 this(looper, context, deps, netService, netd, userId, vpnProfileStore, 748 new SystemServices(context), new Ikev2SessionCreator()); 749 } 750 751 @VisibleForTesting Vpn(Looper looper, Context context, Dependencies deps, INetworkManagementService netService, INetd netd, int userId, VpnProfileStore vpnProfileStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator)752 protected Vpn(Looper looper, Context context, Dependencies deps, 753 INetworkManagementService netService, INetd netd, 754 int userId, VpnProfileStore vpnProfileStore, SystemServices systemServices, 755 Ikev2SessionCreator ikev2SessionCreator) { 756 mVpnProfileStore = vpnProfileStore; 757 mContext = context; 758 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); 759 mAppOpsManager = mContext.getSystemService(AppOpsManager.class); 760 mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); 761 mConnectivityDiagnosticsManager = 762 mContext.getSystemService(ConnectivityDiagnosticsManager.class); 763 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 764 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 765 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 766 767 mDeps = deps; 768 mNms = netService; 769 mNetd = netd; 770 mUserId = userId; 771 mLooper = looper; 772 mSystemServices = systemServices; 773 mIkev2SessionCreator = ikev2SessionCreator; 774 mUserManager = mContext.getSystemService(UserManager.class); 775 776 mPackage = VpnConfig.LEGACY_VPN; 777 mOwnerUID = getAppUid(mContext, mPackage, mUserId); 778 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage); 779 780 try { 781 netService.registerObserver(mObserver); 782 } catch (RemoteException e) { 783 Log.wtf(TAG, "Problem registering observer", e); 784 } 785 786 mNetworkProvider = new NetworkProvider(context, looper, VPN_PROVIDER_NAME_BASE + mUserId); 787 // This constructor is called in onUserStart and registers the provider. The provider 788 // will be unregistered in onUserStop. 789 mConnectivityManager.registerNetworkProvider(mNetworkProvider); 790 mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED; 791 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE, 792 "" /* subtypeName */); 793 mNetworkCapabilities = new NetworkCapabilities.Builder() 794 .addTransportType(NetworkCapabilities.TRANSPORT_VPN) 795 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 796 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) 797 .setTransportInfo(new VpnTransportInfo( 798 VpnManager.TYPE_VPN_NONE, 799 null /* sessionId */, 800 false /* bypassable */, 801 false /* longLivedTcpConnectionsExpensive */)) 802 .build(); 803 804 loadAlwaysOnPackage(); 805 } 806 807 /** 808 * Set whether this object is responsible for watching for {@link NetworkInfo} 809 * teardown. When {@code false}, teardown is handled externally by someone 810 * else. 811 */ setEnableTeardown(boolean enableTeardown)812 public void setEnableTeardown(boolean enableTeardown) { 813 mEnableTeardown = enableTeardown; 814 } 815 816 @VisibleForTesting getEnableTeardown()817 public boolean getEnableTeardown() { 818 return mEnableTeardown; 819 } 820 821 /** 822 * Update current state, dispatching event to listeners. 823 */ 824 @VisibleForTesting 825 @GuardedBy("this") updateState(DetailedState detailedState, String reason)826 protected void updateState(DetailedState detailedState, String reason) { 827 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 828 mLegacyState = LegacyVpnInfo.stateFromNetworkInfo(detailedState); 829 mNetworkInfo.setDetailedState(detailedState, reason, null); 830 // TODO : only accept transitions when the agent is in the correct state (non-null for 831 // CONNECTED, DISCONNECTED and FAILED, null for CONNECTED). 832 // This will require a way for tests to pretend the VPN is connected that's not 833 // calling this method with CONNECTED. 834 // It will also require audit of where the code calls this method with DISCONNECTED 835 // with a null agent, which it was doing historically to make sure the agent is 836 // disconnected as this was a no-op if the agent was null. 837 switch (detailedState) { 838 case CONNECTED: 839 if (null != mNetworkAgent) { 840 mNetworkAgent.markConnected(); 841 } 842 break; 843 case DISCONNECTED: 844 case FAILED: 845 if (null != mNetworkAgent) { 846 mNetworkAgent.unregister(); 847 mNetworkAgent = null; 848 } 849 break; 850 case CONNECTING: 851 if (null != mNetworkAgent) { 852 throw new IllegalStateException("VPN can only go to CONNECTING state when" 853 + " the agent is null."); 854 } 855 break; 856 default: 857 throw new IllegalArgumentException("Illegal state argument " + detailedState); 858 } 859 updateAlwaysOnNotification(detailedState); 860 } 861 resetNetworkCapabilities()862 private void resetNetworkCapabilities() { 863 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) 864 .setUids(null) 865 .setTransportInfo(new VpnTransportInfo( 866 VpnManager.TYPE_VPN_NONE, 867 null /* sessionId */, 868 false /* bypassable */, 869 false /* longLivedTcpConnectionsExpensive */)) 870 .build(); 871 } 872 873 /** 874 * Chooses whether to force all connections to go through VPN. 875 * 876 * Used to enable/disable legacy VPN lockdown. 877 * 878 * This uses the same ip rule mechanism as 879 * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling 880 * that function will be replaced and saved with the always-on state. 881 * 882 * @param lockdown whether to prevent all traffic outside of the VPN. 883 */ setLockdown(boolean lockdown)884 public synchronized void setLockdown(boolean lockdown) { 885 enforceControlPermissionOrInternalCaller(); 886 887 setVpnForcedLocked(lockdown); 888 mLockdown = lockdown; 889 890 // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by 891 // LockdownVpnTracker.isEnabled() which keeps track of its own state. 892 if (mAlwaysOn) { 893 saveAlwaysOnPackage(); 894 } 895 } 896 897 /** Returns the package name that is currently prepared. */ getPackage()898 public synchronized String getPackage() { 899 return mPackage; 900 } 901 902 /** 903 * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected. 904 * 905 * @return {@code true} if VPN lockdown is enabled. 906 */ getLockdown()907 public synchronized boolean getLockdown() { 908 return mLockdown; 909 } 910 911 /** 912 * Returns whether VPN is configured as always-on. 913 */ getAlwaysOn()914 public synchronized boolean getAlwaysOn() { 915 return mAlwaysOn; 916 } 917 918 /** 919 * Checks if a VPN app supports always-on mode. 920 * 921 * <p>In order to support the always-on feature, an app has to either have an installed 922 * PlatformVpnProfile, or: 923 * 924 * <ul> 925 * <li>target {@link VERSION_CODES#N API 24} or above, and 926 * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} 927 * meta-data field. 928 * </ul> 929 * 930 * @param packageName the canonical package name of the VPN app 931 * @return {@code true} if and only if the VPN app exists and supports always-on mode 932 */ isAlwaysOnPackageSupported(String packageName)933 public boolean isAlwaysOnPackageSupported(String packageName) { 934 enforceSettingsPermission(); 935 936 if (packageName == null) { 937 return false; 938 } 939 940 final long oldId = Binder.clearCallingIdentity(); 941 try { 942 if (getVpnProfilePrivileged(packageName) != null) { 943 return true; 944 } 945 } finally { 946 Binder.restoreCallingIdentity(oldId); 947 } 948 949 PackageManager pm = mContext.getPackageManager(); 950 ApplicationInfo appInfo = null; 951 try { 952 appInfo = pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserId); 953 } catch (NameNotFoundException unused) { 954 Log.w(TAG, "Can't find \"" + packageName + "\" when checking always-on support"); 955 } 956 if (appInfo == null || appInfo.targetSdkVersion < VERSION_CODES.N) { 957 return false; 958 } 959 960 final Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 961 intent.setPackage(packageName); 962 List<ResolveInfo> services = 963 pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, mUserId); 964 if (services == null || services.size() == 0) { 965 return false; 966 } 967 968 for (ResolveInfo rInfo : services) { 969 final Bundle metaData = rInfo.serviceInfo.metaData; 970 if (metaData != null && 971 !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) { 972 return false; 973 } 974 } 975 976 return true; 977 } 978 buildVpnManagerEventIntent(@onNull String category, int errorClass, int errorCode, @NonNull final String packageName, @Nullable final String sessionKey, @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork, @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp)979 private Intent buildVpnManagerEventIntent(@NonNull String category, int errorClass, 980 int errorCode, @NonNull final String packageName, @Nullable final String sessionKey, 981 @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork, 982 @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) { 983 // Add log for debugging flaky test. b/242833779 984 Log.d(TAG, "buildVpnManagerEventIntent: sessionKey = " + sessionKey); 985 final Intent intent = new Intent(VpnManager.ACTION_VPN_MANAGER_EVENT); 986 intent.setPackage(packageName); 987 intent.addCategory(category); 988 intent.putExtra(VpnManager.EXTRA_VPN_PROFILE_STATE, profileState); 989 intent.putExtra(VpnManager.EXTRA_SESSION_KEY, sessionKey); 990 intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK, underlyingNetwork); 991 intent.putExtra(VpnManager.EXTRA_UNDERLYING_NETWORK_CAPABILITIES, nc); 992 intent.putExtra(VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES, lp); 993 intent.putExtra(VpnManager.EXTRA_TIMESTAMP_MILLIS, System.currentTimeMillis()); 994 if (!VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER.equals(category) 995 || !VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED.equals(category)) { 996 intent.putExtra(VpnManager.EXTRA_ERROR_CLASS, errorClass); 997 intent.putExtra(VpnManager.EXTRA_ERROR_CODE, errorCode); 998 } 999 1000 return intent; 1001 } 1002 sendEventToVpnManagerApp(@onNull String category, int errorClass, int errorCode, @NonNull final String packageName, @Nullable final String sessionKey, @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork, @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp)1003 private boolean sendEventToVpnManagerApp(@NonNull String category, int errorClass, 1004 int errorCode, @NonNull final String packageName, @Nullable final String sessionKey, 1005 @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork, 1006 @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) { 1007 mEventChanges.log("[VMEvent] Event class=" + getVpnManagerEventClassName(errorClass) 1008 + ", err=" + getVpnManagerEventErrorName(errorCode) + " for " + packageName 1009 + " on session " + sessionKey); 1010 final Intent intent = buildVpnManagerEventIntent(category, errorClass, errorCode, 1011 packageName, sessionKey, profileState, underlyingNetwork, nc, lp); 1012 return sendEventToVpnManagerApp(intent, packageName); 1013 } 1014 sendEventToVpnManagerApp(@onNull final Intent intent, @NonNull final String packageName)1015 private boolean sendEventToVpnManagerApp(@NonNull final Intent intent, 1016 @NonNull final String packageName) { 1017 // Allow VpnManager app to temporarily run background services to handle this error. 1018 // If an app requires anything beyond this grace period, they MUST either declare 1019 // themselves as a foreground service, or schedule a job/workitem. 1020 final long token = Binder.clearCallingIdentity(); 1021 try { 1022 final DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); 1023 idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, 1024 VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, 1025 "VpnManager event"); 1026 1027 try { 1028 return mUserIdContext.startService(intent) != null; 1029 } catch (RuntimeException e) { 1030 Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e); 1031 return false; 1032 } 1033 } finally { 1034 Binder.restoreCallingIdentity(token); 1035 } 1036 } 1037 isVpnApp(String packageName)1038 private static boolean isVpnApp(String packageName) { 1039 return packageName != null && !VpnConfig.LEGACY_VPN.equals(packageName); 1040 } 1041 1042 /** 1043 * Configures an always-on VPN connection through a specific application. This connection is 1044 * automatically granted and persisted after a reboot. 1045 * 1046 * <p>The designated package should either have a PlatformVpnProfile installed, or declare a 1047 * {@link VpnService} in its manifest guarded by {@link 1048 * android.Manifest.permission.BIND_VPN_SERVICE}, otherwise the call will fail. 1049 * 1050 * <p>Note that this method does not check if the VPN app supports always-on mode. The check is 1051 * delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this method 1052 * in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}. 1053 * 1054 * @param packageName the package to designate as always-on VPN supplier. 1055 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 1056 * @param lockdownAllowlist packages to be allowed from lockdown. 1057 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 1058 */ setAlwaysOnPackage( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownAllowlist)1059 public synchronized boolean setAlwaysOnPackage( 1060 @Nullable String packageName, 1061 boolean lockdown, 1062 @Nullable List<String> lockdownAllowlist) { 1063 enforceControlPermissionOrInternalCaller(); 1064 // Store mPackage since it might be reset or might be replaced with the other VPN app. 1065 final String oldPackage = mPackage; 1066 final boolean isPackageChanged = !Objects.equals(packageName, oldPackage); 1067 // TODO: Remove "SdkLevel.isAtLeastT()" check once VpnManagerService is decoupled from 1068 // ConnectivityServiceTest. 1069 // Only notify VPN apps that were already always-on, and only if the always-on provider 1070 // changed, or the lockdown mode changed. 1071 final boolean shouldNotifyOldPkg = isVpnApp(oldPackage) && mAlwaysOn 1072 && (lockdown != mLockdown || isPackageChanged); 1073 // Also notify the new package if there was a provider change. 1074 final boolean shouldNotifyNewPkg = isVpnApp(packageName) && isPackageChanged; 1075 1076 if (!setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) { 1077 return false; 1078 } 1079 1080 saveAlwaysOnPackage(); 1081 1082 // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from 1083 // ConnectivityServiceTest. 1084 if (!SdkLevel.isAtLeastT()) { 1085 return true; 1086 } 1087 1088 if (shouldNotifyOldPkg) { 1089 // If both of shouldNotifyOldPkg & isPackageChanged are true, that means the 1090 // always-on of old package is disabled or the old package is replaced with the new 1091 // package. In this case, VpnProfileState should be disconnected. 1092 sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, 1093 -1 /* errorClass */, -1 /* errorCode*/, oldPackage, 1094 null /* sessionKey */, isPackageChanged ? makeDisconnectedVpnProfileState() 1095 : makeVpnProfileStateLocked(), 1096 null /* underlyingNetwork */, null /* nc */, null /* lp */); 1097 } 1098 1099 if (shouldNotifyNewPkg) { 1100 sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, 1101 -1 /* errorClass */, -1 /* errorCode*/, packageName, 1102 getSessionKeyLocked(), makeVpnProfileStateLocked(), 1103 null /* underlyingNetwork */, null /* nc */, null /* lp */); 1104 } 1105 return true; 1106 } 1107 1108 /** 1109 * Configures an always-on VPN connection through a specific application, the same as {@link 1110 * #setAlwaysOnPackage}. 1111 * 1112 * <p>Does not perform permission checks. Does not persist any of the changes to storage. 1113 * 1114 * @param packageName the package to designate as always-on VPN supplier. 1115 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 1116 * @param lockdownAllowlist packages to be allowed to bypass lockdown. This is only used if 1117 * {@code lockdown} is {@code true}. Packages must not contain commas. 1118 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 1119 */ 1120 @GuardedBy("this") setAlwaysOnPackageInternal( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownAllowlist)1121 private boolean setAlwaysOnPackageInternal( 1122 @Nullable String packageName, boolean lockdown, 1123 @Nullable List<String> lockdownAllowlist) { 1124 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 1125 Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); 1126 return false; 1127 } 1128 1129 if (lockdownAllowlist != null) { 1130 for (String pkg : lockdownAllowlist) { 1131 if (pkg.contains(",")) { 1132 Log.w(TAG, "Not setting always-on vpn, invalid allowed package: " + pkg); 1133 return false; 1134 } 1135 } 1136 } 1137 1138 if (packageName != null) { 1139 final VpnProfile profile; 1140 final long oldId = Binder.clearCallingIdentity(); 1141 try { 1142 profile = getVpnProfilePrivileged(packageName); 1143 } finally { 1144 Binder.restoreCallingIdentity(oldId); 1145 } 1146 1147 // Pre-authorize new always-on VPN package. 1148 final int grantType = 1149 (profile == null) ? VpnManager.TYPE_VPN_SERVICE : VpnManager.TYPE_VPN_PLATFORM; 1150 if (!setPackageAuthorization(packageName, grantType)) { 1151 return false; 1152 } 1153 mAlwaysOn = true; 1154 } else { 1155 packageName = VpnConfig.LEGACY_VPN; 1156 mAlwaysOn = false; 1157 } 1158 1159 final boolean oldLockdownState = mLockdown; 1160 mLockdown = (mAlwaysOn && lockdown); 1161 mLockdownAllowlist = (mLockdown && lockdownAllowlist != null) 1162 ? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist)) 1163 : Collections.emptyList(); 1164 mEventChanges.log("[LockdownAlwaysOn] Mode changed: lockdown=" + mLockdown + " alwaysOn=" 1165 + mAlwaysOn + " calling from " + Binder.getCallingUid()); 1166 1167 if (isCurrentPreparedPackage(packageName)) { 1168 updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); 1169 setVpnForcedLocked(mLockdown); 1170 1171 // Lockdown forces the VPN to be non-bypassable (see #agentConnect) because it makes 1172 // no sense for a VPN to be bypassable when connected but not when not connected. 1173 // As such, changes in lockdown need to restart the agent. 1174 if (mNetworkAgent != null && oldLockdownState != mLockdown) { 1175 startNewNetworkAgent(mNetworkAgent, "Lockdown mode changed"); 1176 } 1177 } else { 1178 // Prepare this app. The notification will update as a side-effect of updateState(). 1179 // It also calls setVpnForcedLocked(). 1180 prepareInternal(packageName); 1181 } 1182 return true; 1183 } 1184 isNullOrLegacyVpn(String packageName)1185 private static boolean isNullOrLegacyVpn(String packageName) { 1186 return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName); 1187 } 1188 1189 /** 1190 * @return the package name of the VPN controller responsible for always-on VPN, 1191 * or {@code null} if none is set or always-on VPN is controlled through 1192 * lockdown instead. 1193 */ getAlwaysOnPackage()1194 public synchronized String getAlwaysOnPackage() { 1195 enforceControlPermissionOrInternalCaller(); 1196 return (mAlwaysOn ? mPackage : null); 1197 } 1198 1199 /** 1200 * @return an immutable list of packages allowed to bypass always-on VPN lockdown. 1201 */ getLockdownAllowlist()1202 public synchronized List<String> getLockdownAllowlist() { 1203 return mLockdown ? mLockdownAllowlist : null; 1204 } 1205 1206 /** 1207 * Save the always-on package and lockdown config into Settings.Secure 1208 */ 1209 @GuardedBy("this") saveAlwaysOnPackage()1210 private void saveAlwaysOnPackage() { 1211 final long token = Binder.clearCallingIdentity(); 1212 try { 1213 mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP, 1214 getAlwaysOnPackage(), mUserId); 1215 mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 1216 (mAlwaysOn && mLockdown ? 1 : 0), mUserId); 1217 mSystemServices.settingsSecurePutStringForUser( 1218 LOCKDOWN_ALLOWLIST_SETTING_NAME, 1219 String.join(",", mLockdownAllowlist), mUserId); 1220 } finally { 1221 Binder.restoreCallingIdentity(token); 1222 } 1223 } 1224 1225 /** Load the always-on package and lockdown config from Settings. */ 1226 @GuardedBy("this") loadAlwaysOnPackage()1227 private void loadAlwaysOnPackage() { 1228 final long token = Binder.clearCallingIdentity(); 1229 try { 1230 final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser( 1231 Settings.Secure.ALWAYS_ON_VPN_APP, mUserId); 1232 final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser( 1233 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserId) != 0; 1234 final String allowlistString = mSystemServices.settingsSecureGetStringForUser( 1235 LOCKDOWN_ALLOWLIST_SETTING_NAME, mUserId); 1236 final List<String> allowedPackages = TextUtils.isEmpty(allowlistString) 1237 ? Collections.emptyList() : Arrays.asList(allowlistString.split(",")); 1238 setAlwaysOnPackageInternal( 1239 alwaysOnPackage, alwaysOnLockdown, allowedPackages); 1240 } finally { 1241 Binder.restoreCallingIdentity(token); 1242 } 1243 } 1244 1245 /** 1246 * Starts the currently selected always-on VPN 1247 * 1248 * @return {@code true} if the service was started, the service was already connected, or there 1249 * was no always-on VPN to start. {@code false} otherwise. 1250 */ startAlwaysOnVpn()1251 public boolean startAlwaysOnVpn() { 1252 final String alwaysOnPackage; 1253 synchronized (this) { 1254 alwaysOnPackage = getAlwaysOnPackage(); 1255 // Skip if there is no service to start. 1256 if (alwaysOnPackage == null) { 1257 return true; 1258 } 1259 // Remove always-on VPN if it's not supported. 1260 if (!isAlwaysOnPackageSupported(alwaysOnPackage)) { 1261 setAlwaysOnPackage(null, false, null); 1262 return false; 1263 } 1264 // Skip if the service is already established. This isn't bulletproof: it's not bound 1265 // until after establish(), so if it's mid-setup onStartCommand will be sent twice, 1266 // which may restart the connection. 1267 if (getNetworkInfo().isConnected()) { 1268 return true; 1269 } 1270 } 1271 1272 final long oldId = Binder.clearCallingIdentity(); 1273 try { 1274 // Prefer VPN profiles, if any exist. 1275 VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage); 1276 if (profile != null) { 1277 startVpnProfilePrivileged(profile, alwaysOnPackage); 1278 // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was 1279 // correctly parsed, and the VPN has started running in a different thread. The only 1280 // other possibility is that the above call threw an exception, which will be 1281 // caught below, and returns false (clearing the always-on VPN). Once started, the 1282 // Platform VPN cannot permanently fail, and is resilient to temporary failures. It 1283 // will continue retrying until shut down by the user, or always-on is toggled off. 1284 return true; 1285 } 1286 1287 // Tell the OS that background services in this app need to be allowed for 1288 // a short time, so we can bootstrap the VPN service. 1289 DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); 1290 idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, 1291 VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN, 1292 "vpn"); 1293 1294 // Start the VPN service declared in the app's manifest. 1295 Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); 1296 serviceIntent.setPackage(alwaysOnPackage); 1297 try { 1298 return mUserIdContext.startService(serviceIntent) != null; 1299 } catch (RuntimeException e) { 1300 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e); 1301 return false; 1302 } 1303 } catch (Exception e) { 1304 Log.e(TAG, "Error starting always-on VPN", e); 1305 return false; 1306 } finally { 1307 Binder.restoreCallingIdentity(oldId); 1308 } 1309 } 1310 1311 /** 1312 * Prepare for a VPN application. This method is designed to solve 1313 * race conditions. It first compares the current prepared package 1314 * with {@code oldPackage}. If they are the same, the prepared 1315 * package is revoked and replaced with {@code newPackage}. If 1316 * {@code oldPackage} is {@code null}, the comparison is omitted. 1317 * If {@code newPackage} is the same package or {@code null}, the 1318 * revocation is omitted. This method returns {@code true} if the 1319 * operation is succeeded. 1320 * 1321 * Legacy VPN is handled specially since it is not a real package. 1322 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 1323 * it can be revoked by itself. 1324 * 1325 * The permission checks to verify that the VPN has already been granted 1326 * user consent are dependent on the type of the VPN being prepared. See 1327 * {@link AppOpsManager#OP_ACTIVATE_VPN} and {@link 1328 * AppOpsManager#OP_ACTIVATE_PLATFORM_VPN} for more information. 1329 * 1330 * Note: when we added VPN pre-consent in 1331 * https://android.googlesource.com/platform/frameworks/base/+/0554260 1332 * the names oldPackage and newPackage became misleading, because when 1333 * an app is pre-consented, we actually prepare oldPackage, not newPackage. 1334 * 1335 * Their meanings actually are: 1336 * 1337 * - oldPackage non-null, newPackage null: App calling VpnService#prepare(). 1338 * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn(). 1339 * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect 1340 * and revoke any current app VPN and re-prepare legacy vpn. 1341 * - oldPackage null, newPackage null: always returns true for backward compatibility. 1342 * 1343 * TODO: Rename the variables - or split this method into two - and end this confusion. 1344 * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN) 1345 * to prepare(oldPackage=null, newPackage=LEGACY_VPN) 1346 * 1347 * @param oldPackage The package name of the old VPN application 1348 * @param newPackage The package name of the new VPN application 1349 * @param vpnType The type of VPN being prepared. One of {@link VpnManager.VpnType} Preparing a 1350 * platform VPN profile requires only the lesser ACTIVATE_PLATFORM_VPN appop. 1351 * @return true if the operation succeeded. 1352 */ prepare( String oldPackage, String newPackage, @VpnManager.VpnType int vpnType)1353 public synchronized boolean prepare( 1354 String oldPackage, String newPackage, @VpnManager.VpnType int vpnType) { 1355 // Except for Settings and VpnDialogs, the caller should be matched one of oldPackage or 1356 // newPackage. Otherwise, non VPN owner might get the VPN always-on status of the VPN owner. 1357 // See b/191382886. 1358 if (mContext.checkCallingOrSelfPermission(CONTROL_VPN) != PERMISSION_GRANTED) { 1359 if (oldPackage != null) { 1360 verifyCallingUidAndPackage(oldPackage); 1361 } 1362 if (newPackage != null) { 1363 verifyCallingUidAndPackage(newPackage); 1364 } 1365 } 1366 1367 if (oldPackage != null) { 1368 // Stop an existing always-on VPN from being dethroned by other apps. 1369 if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) { 1370 return false; 1371 } 1372 1373 // Package is not the same or old package was reinstalled. 1374 if (!isCurrentPreparedPackage(oldPackage)) { 1375 // The package doesn't match. We return false (to obtain user consent) unless the 1376 // user has already consented to that VPN package. 1377 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 1378 && isVpnPreConsented(mContext, oldPackage, vpnType)) { 1379 prepareInternal(oldPackage); 1380 return true; 1381 } 1382 return false; 1383 } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 1384 && !isVpnPreConsented(mContext, oldPackage, vpnType)) { 1385 // Currently prepared VPN is revoked, so unprepare it and return false. 1386 prepareInternal(VpnConfig.LEGACY_VPN); 1387 return false; 1388 } 1389 } 1390 1391 // Return true if we do not need to revoke. 1392 if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) && 1393 isCurrentPreparedPackage(newPackage))) { 1394 return true; 1395 } 1396 1397 // Check that the caller is authorized. 1398 enforceControlPermission(); 1399 1400 // Stop an existing always-on VPN from being dethroned by other apps. 1401 if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) { 1402 return false; 1403 } 1404 1405 prepareInternal(newPackage); 1406 return true; 1407 } 1408 1409 @GuardedBy("this") isCurrentPreparedPackage(String packageName)1410 private boolean isCurrentPreparedPackage(String packageName) { 1411 // We can't just check that packageName matches mPackage, because if the app was uninstalled 1412 // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the 1413 // calling package may not be the same as the prepared package. Check both UID and package. 1414 return getAppUid(mContext, packageName, mUserId) == mOwnerUID 1415 && mPackage.equals(packageName); 1416 } 1417 1418 /** Prepare the VPN for the given package. Does not perform permission checks. */ 1419 @GuardedBy("this") prepareInternal(String newPackage)1420 private void prepareInternal(String newPackage) { 1421 final long token = Binder.clearCallingIdentity(); 1422 try { 1423 // Reset the interface. 1424 if (mInterface != null) { 1425 mStatusIntent = null; 1426 agentDisconnect(); 1427 jniReset(mInterface); 1428 mInterface = null; 1429 resetNetworkCapabilities(); 1430 } 1431 1432 // Revoke the connection or stop the VpnRunner. 1433 if (mConnection != null) { 1434 try { 1435 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 1436 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 1437 } catch (Exception e) { 1438 // ignore 1439 } 1440 mAppOpsManager.finishOp( 1441 AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null); 1442 mContext.unbindService(mConnection); 1443 cleanupVpnStateLocked(); 1444 } else if (mVpnRunner != null) { 1445 stopVpnRunnerAndNotifyAppLocked(); 1446 } 1447 1448 try { 1449 mNms.denyProtect(mOwnerUID); 1450 } catch (Exception e) { 1451 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 1452 } 1453 1454 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 1455 mPackage = newPackage; 1456 mOwnerUID = getAppUid(mContext, newPackage, mUserId); 1457 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); 1458 try { 1459 mNms.allowProtect(mOwnerUID); 1460 } catch (Exception e) { 1461 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 1462 } 1463 mConfig = null; 1464 1465 updateState(DetailedState.DISCONNECTED, "prepare"); 1466 setVpnForcedLocked(mLockdown); 1467 } finally { 1468 Binder.restoreCallingIdentity(token); 1469 } 1470 } 1471 1472 /** Set whether a package has the ability to launch VPNs without user intervention. */ setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType)1473 public boolean setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType) { 1474 // Check if the caller is authorized. 1475 enforceControlPermissionOrInternalCaller(); 1476 1477 final int uid = getAppUid(mContext, packageName, mUserId); 1478 if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { 1479 // Authorization for nonexistent packages (or fake ones) can't be updated. 1480 return false; 1481 } 1482 1483 final long token = Binder.clearCallingIdentity(); 1484 try { 1485 final String[] toChange; 1486 1487 // Clear all AppOps if the app is being unauthorized. 1488 switch (vpnType) { 1489 case VpnManager.TYPE_VPN_NONE: 1490 toChange = new String[] { 1491 AppOpsManager.OPSTR_ACTIVATE_VPN, 1492 AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN 1493 }; 1494 break; 1495 case VpnManager.TYPE_VPN_PLATFORM: 1496 toChange = new String[] {AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN}; 1497 break; 1498 case VpnManager.TYPE_VPN_SERVICE: 1499 toChange = new String[] {AppOpsManager.OPSTR_ACTIVATE_VPN}; 1500 break; 1501 case VpnManager.TYPE_VPN_LEGACY: 1502 return false; 1503 default: 1504 Log.wtf(TAG, "Unrecognized VPN type while granting authorization"); 1505 return false; 1506 } 1507 1508 for (final String appOpStr : toChange) { 1509 mAppOpsManager.setMode( 1510 appOpStr, 1511 uid, 1512 packageName, 1513 vpnType == VpnManager.TYPE_VPN_NONE 1514 ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED); 1515 } 1516 return true; 1517 } catch (Exception e) { 1518 Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e); 1519 } finally { 1520 Binder.restoreCallingIdentity(token); 1521 } 1522 return false; 1523 } 1524 isVpnPreConsented(Context context, String packageName, int vpnType)1525 private static boolean isVpnPreConsented(Context context, String packageName, int vpnType) { 1526 switch (vpnType) { 1527 case VpnManager.TYPE_VPN_SERVICE: 1528 return isVpnServicePreConsented(context, packageName); 1529 case VpnManager.TYPE_VPN_PLATFORM: 1530 return isVpnProfilePreConsented(context, packageName); 1531 case VpnManager.TYPE_VPN_LEGACY: 1532 return VpnConfig.LEGACY_VPN.equals(packageName); 1533 default: 1534 return false; 1535 } 1536 } 1537 doesPackageHaveAppop(Context context, String packageName, String appOpStr)1538 private static boolean doesPackageHaveAppop(Context context, String packageName, 1539 String appOpStr) { 1540 final AppOpsManager appOps = 1541 (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 1542 1543 // Verify that the caller matches the given package and has the required permission. 1544 return appOps.noteOpNoThrow(appOpStr, Binder.getCallingUid(), packageName, 1545 null /* attributionTag */, null /* message */) == AppOpsManager.MODE_ALLOWED; 1546 } 1547 isVpnServicePreConsented(Context context, String packageName)1548 private static boolean isVpnServicePreConsented(Context context, String packageName) { 1549 return doesPackageHaveAppop(context, packageName, AppOpsManager.OPSTR_ACTIVATE_VPN); 1550 } 1551 isVpnProfilePreConsented(Context context, String packageName)1552 private static boolean isVpnProfilePreConsented(Context context, String packageName) { 1553 return doesPackageHaveAppop(context, packageName, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN) 1554 || isVpnServicePreConsented(context, packageName); 1555 } 1556 getAppUid(final Context context, final String app, final int userId)1557 private static int getAppUid(final Context context, final String app, final int userId) { 1558 if (VpnConfig.LEGACY_VPN.equals(app)) { 1559 return Process.myUid(); 1560 } 1561 PackageManager pm = context.getPackageManager(); 1562 final long token = Binder.clearCallingIdentity(); 1563 try { 1564 return pm.getPackageUidAsUser(app, userId); 1565 } catch (NameNotFoundException e) { 1566 return -1; 1567 } finally { 1568 Binder.restoreCallingIdentity(token); 1569 } 1570 } 1571 doesPackageTargetAtLeastQ(String packageName)1572 private boolean doesPackageTargetAtLeastQ(String packageName) { 1573 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 1574 return true; 1575 } 1576 PackageManager pm = mContext.getPackageManager(); 1577 try { 1578 ApplicationInfo appInfo = 1579 pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserId); 1580 return appInfo.targetSdkVersion >= VERSION_CODES.Q; 1581 } catch (NameNotFoundException unused) { 1582 Log.w(TAG, "Can't find \"" + packageName + "\""); 1583 return false; 1584 } 1585 } 1586 getNetworkInfo()1587 public NetworkInfo getNetworkInfo() { 1588 return mNetworkInfo; 1589 } 1590 1591 /** 1592 * Return Network of current running VPN network. 1593 * 1594 * @return a Network if there is a running VPN network or null if there is no running VPN 1595 * network or network is null. 1596 */ 1597 @VisibleForTesting 1598 @Nullable getNetwork()1599 public synchronized Network getNetwork() { 1600 final NetworkAgent agent = mNetworkAgent; 1601 if (null == agent) return null; 1602 final Network network = agent.getNetwork(); 1603 if (null == network) return null; 1604 return network; 1605 } 1606 1607 // TODO : this is not synchronized(this) but reads from mConfig, which is dangerous 1608 // This file makes an effort to avoid partly initializing mConfig, but this is still not great makeLinkProperties()1609 private LinkProperties makeLinkProperties() { 1610 // The design of disabling IPv6 is only enabled for IKEv2 VPN because it needs additional 1611 // logic to handle IPv6 only VPN, and the IPv6 only VPN may be restarted when its MTU 1612 // is lower than 1280. The logic is controlled by IKEv2VpnRunner, so the design is only 1613 // enabled for IKEv2 VPN. 1614 final boolean disableIPV6 = (isIkev2VpnRunner() && mConfig.mtu < IPV6_MIN_MTU); 1615 boolean allowIPv4 = mConfig.allowIPv4; 1616 boolean allowIPv6 = mConfig.allowIPv6; 1617 1618 LinkProperties lp = new LinkProperties(); 1619 1620 lp.setInterfaceName(mInterface); 1621 1622 if (mConfig.addresses != null) { 1623 for (LinkAddress address : mConfig.addresses) { 1624 if (disableIPV6 && address.isIpv6()) continue; 1625 lp.addLinkAddress(address); 1626 allowIPv4 |= address.getAddress() instanceof Inet4Address; 1627 allowIPv6 |= address.getAddress() instanceof Inet6Address; 1628 } 1629 } 1630 1631 if (mConfig.routes != null) { 1632 for (RouteInfo route : mConfig.routes) { 1633 final InetAddress address = route.getDestination().getAddress(); 1634 if (disableIPV6 && address instanceof Inet6Address) continue; 1635 lp.addRoute(route); 1636 1637 if (route.getType() == RouteInfo.RTN_UNICAST) { 1638 allowIPv4 |= address instanceof Inet4Address; 1639 allowIPv6 |= address instanceof Inet6Address; 1640 } 1641 } 1642 } 1643 1644 if (mConfig.dnsServers != null) { 1645 for (String dnsServer : mConfig.dnsServers) { 1646 final InetAddress address = InetAddresses.parseNumericAddress(dnsServer); 1647 if (disableIPV6 && address instanceof Inet6Address) continue; 1648 lp.addDnsServer(address); 1649 allowIPv4 |= address instanceof Inet4Address; 1650 allowIPv6 |= address instanceof Inet6Address; 1651 } 1652 } 1653 1654 lp.setHttpProxy(mConfig.proxyInfo); 1655 1656 if (!allowIPv4) { 1657 lp.addRoute(new RouteInfo(new IpPrefix( 1658 NetworkStackConstants.IPV4_ADDR_ANY, 0), null /*gateway*/, 1659 null /*iface*/, RTN_UNREACHABLE)); 1660 } 1661 if (!allowIPv6 || disableIPV6) { 1662 lp.addRoute(new RouteInfo(new IpPrefix( 1663 NetworkStackConstants.IPV6_ADDR_ANY, 0), null /*gateway*/, 1664 null /*iface*/, RTN_UNREACHABLE)); 1665 } 1666 1667 // Concatenate search domains into a string. 1668 StringBuilder buffer = new StringBuilder(); 1669 if (mConfig.searchDomains != null) { 1670 for (String domain : mConfig.searchDomains) { 1671 buffer.append(domain).append(' '); 1672 } 1673 } 1674 lp.setDomains(buffer.toString().trim()); 1675 1676 if (mConfig.mtu > 0) { 1677 lp.setMtu(mConfig.mtu); 1678 } 1679 1680 // TODO: Stop setting the MTU in jniCreate 1681 1682 return lp; 1683 } 1684 1685 /** 1686 * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without 1687 * registering a new NetworkAgent. This is not always possible if the new VPN configuration 1688 * has certain changes, in which case this method would just return {@code false}. 1689 */ 1690 // TODO : this method is not synchronized(this) but reads from mConfig updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig)1691 private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { 1692 // NetworkAgentConfig cannot be updated without registering a new NetworkAgent. 1693 // Strictly speaking, bypassability is affected by lockdown and therefore it's possible 1694 // it doesn't actually change even if mConfig.allowBypass changed. It might be theoretically 1695 // possible to do handover in this case, but this is far from obvious to VPN authors and 1696 // it's simpler if the rule is just "can't update in place if you change allow bypass". 1697 if (oldConfig.allowBypass != mConfig.allowBypass) { 1698 Log.i(TAG, "Handover not possible due to changes to allowBypass"); 1699 return false; 1700 } 1701 1702 // TODO: we currently do not support seamless handover if the allowed or disallowed 1703 // applications have changed. Consider diffing UID ranges and only applying the delta. 1704 if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) || 1705 !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) { 1706 Log.i(TAG, "Handover not possible due to changes to allowed/denied apps"); 1707 return false; 1708 } 1709 1710 agent.sendLinkProperties(makeLinkProperties()); 1711 return true; 1712 } 1713 1714 @GuardedBy("this") agentConnect()1715 private void agentConnect() { 1716 agentConnect(null /* validationCallback */); 1717 } 1718 1719 @GuardedBy("this") agentConnect(@ullable ValidationStatusCallback validationCallback)1720 private void agentConnect(@Nullable ValidationStatusCallback validationCallback) { 1721 LinkProperties lp = makeLinkProperties(); 1722 1723 // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel 1724 // that falls back to the default network, which by definition provides INTERNET (unless 1725 // there is no default network, in which case none of this matters in any sense). 1726 // Also, always setting the INTERNET bit guarantees that when a VPN applies to an app, 1727 // the VPN will always be reported as the network by getDefaultNetwork and callbacks 1728 // registered with registerDefaultNetworkCallback. This in turn protects the invariant 1729 // that an app calling ConnectivityManager#bindProcessToNetwork(getDefaultNetwork()) 1730 // behaves the same as when it uses the default network. 1731 final NetworkCapabilities.Builder capsBuilder = 1732 new NetworkCapabilities.Builder(mNetworkCapabilities); 1733 capsBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 1734 1735 mLegacyState = LegacyVpnInfo.STATE_CONNECTING; 1736 updateState(DetailedState.CONNECTING, "agentConnect"); 1737 1738 final boolean bypassable = mConfig.allowBypass && !mLockdown; 1739 final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder() 1740 .setLegacyType(ConnectivityManager.TYPE_VPN) 1741 .setLegacyTypeName("VPN") 1742 .setBypassableVpn(bypassable) 1743 .setVpnRequiresValidation(mConfig.requiresInternetValidation) 1744 .setLocalRoutesExcludedForVpn(mConfig.excludeLocalRoutes) 1745 .build(); 1746 1747 capsBuilder.setOwnerUid(mOwnerUID); 1748 capsBuilder.setAdministratorUids(new int[] {mOwnerUID}); 1749 capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId, 1750 mConfig.allowedApplications, mConfig.disallowedApplications)); 1751 1752 final boolean expensive = areLongLivedTcpConnectionsExpensive(mVpnRunner); 1753 capsBuilder.setTransportInfo(new VpnTransportInfo( 1754 getActiveVpnType(), 1755 mConfig.session, 1756 bypassable, 1757 expensive)); 1758 1759 // Only apps targeting Q and above can explicitly declare themselves as metered. 1760 // These VPNs are assumed metered unless they state otherwise. 1761 if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) { 1762 capsBuilder.removeCapability(NET_CAPABILITY_NOT_METERED); 1763 } else { 1764 capsBuilder.addCapability(NET_CAPABILITY_NOT_METERED); 1765 } 1766 1767 capsBuilder.setUnderlyingNetworks((mConfig.underlyingNetworks != null) 1768 ? Arrays.asList(mConfig.underlyingNetworks) : null); 1769 1770 mNetworkCapabilities = capsBuilder.build(); 1771 logUnderlyNetworkChanges(mNetworkCapabilities.getUnderlyingNetworks()); 1772 mNetworkAgent = mDeps.newNetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */, 1773 mNetworkCapabilities, lp, 1774 new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(), 1775 networkAgentConfig, mNetworkProvider, validationCallback); 1776 final long token = Binder.clearCallingIdentity(); 1777 try { 1778 mNetworkAgent.register(); 1779 } catch (final Exception e) { 1780 // If register() throws, don't keep an unregistered agent. 1781 mNetworkAgent = null; 1782 throw e; 1783 } finally { 1784 Binder.restoreCallingIdentity(token); 1785 } 1786 updateState(DetailedState.CONNECTED, "agentConnect"); 1787 if (isIkev2VpnRunner()) { 1788 final IkeSessionWrapper session = ((IkeV2VpnRunner) mVpnRunner).mSession; 1789 if (null != session) session.setUnderpinnedNetwork(mNetworkAgent.getNetwork()); 1790 } 1791 } 1792 areLongLivedTcpConnectionsExpensive(@onNull VpnRunner runner)1793 private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) { 1794 if (!(runner instanceof IkeV2VpnRunner)) return false; 1795 1796 final int delay = ((IkeV2VpnRunner) runner).getOrGuessKeepaliveDelaySeconds(); 1797 return areLongLivedTcpConnectionsExpensive(delay); 1798 } 1799 areLongLivedTcpConnectionsExpensive(int keepaliveDelaySec)1800 private static boolean areLongLivedTcpConnectionsExpensive(int keepaliveDelaySec) { 1801 return keepaliveDelaySec < DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC; 1802 } 1803 canHaveRestrictedProfile(int userId)1804 private boolean canHaveRestrictedProfile(int userId) { 1805 final long token = Binder.clearCallingIdentity(); 1806 try { 1807 final Context userContext = mContext.createContextAsUser(UserHandle.of(userId), 0); 1808 return userContext.getSystemService(UserManager.class).canHaveRestrictedProfile(); 1809 } finally { 1810 Binder.restoreCallingIdentity(token); 1811 } 1812 } 1813 logUnderlyNetworkChanges(List<Network> networks)1814 private void logUnderlyNetworkChanges(List<Network> networks) { 1815 mEventChanges.log("[UnderlyingNW] Switch to " 1816 + ((networks != null) ? TextUtils.join(", ", networks) : "null")); 1817 } 1818 agentDisconnect(NetworkAgent networkAgent)1819 private void agentDisconnect(NetworkAgent networkAgent) { 1820 if (networkAgent != null) { 1821 networkAgent.unregister(); 1822 } 1823 } 1824 agentDisconnect()1825 private void agentDisconnect() { 1826 updateState(DetailedState.DISCONNECTED, "agentDisconnect"); 1827 } 1828 1829 @GuardedBy("this") startNewNetworkAgent(NetworkAgent oldNetworkAgent, String reason)1830 private void startNewNetworkAgent(NetworkAgent oldNetworkAgent, String reason) { 1831 // Initialize the state for a new agent, while keeping the old one connected 1832 // in case this new connection fails. 1833 mNetworkAgent = null; 1834 updateState(DetailedState.CONNECTING, reason); 1835 // Bringing up a new NetworkAgent to prevent the data leakage before tearing down the old 1836 // NetworkAgent. 1837 agentConnect(); 1838 agentDisconnect(oldNetworkAgent); 1839 } 1840 1841 /** 1842 * Establish a VPN network and return the file descriptor of the VPN interface. This methods 1843 * returns {@code null} if the application is revoked or not prepared. 1844 * 1845 * <p>This method supports ONLY VpnService-based VPNs. For Platform VPNs, see {@link 1846 * provisionVpnProfile} and {@link startVpnProfile} 1847 * 1848 * @param config The parameters to configure the network. 1849 * @return The file descriptor of the VPN interface. 1850 */ establish(VpnConfig config)1851 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 1852 // Check if the caller is already prepared. 1853 if (Binder.getCallingUid() != mOwnerUID) { 1854 return null; 1855 } 1856 // Check to ensure consent hasn't been revoked since we were prepared. 1857 if (!isVpnServicePreConsented(mContext, mPackage)) { 1858 return null; 1859 } 1860 // Check if the service is properly declared. 1861 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 1862 intent.setClassName(mPackage, config.user); 1863 final long token = Binder.clearCallingIdentity(); 1864 try { 1865 // Restricted users are not allowed to create VPNs, they are tied to Owner 1866 enforceNotRestrictedUser(); 1867 1868 final PackageManager packageManager = mUserIdContext.getPackageManager(); 1869 if (packageManager == null) { 1870 throw new IllegalStateException("Cannot get PackageManager."); 1871 } 1872 final ResolveInfo info = packageManager.resolveService(intent, 0 /* flags */); 1873 if (info == null) { 1874 throw new SecurityException("Cannot find " + config.user); 1875 } 1876 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 1877 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 1878 } 1879 } finally { 1880 Binder.restoreCallingIdentity(token); 1881 } 1882 1883 // Save the old config in case we need to go back. 1884 VpnConfig oldConfig = mConfig; 1885 String oldInterface = mInterface; 1886 Connection oldConnection = mConnection; 1887 NetworkAgent oldNetworkAgent = mNetworkAgent; 1888 Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids(); 1889 1890 // Configure the interface. Abort if any of these steps fails. 1891 final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu); 1892 try { 1893 final String interfaze = mDeps.jniGetName(this, tun.getFd()); 1894 1895 // TEMP use the old jni calls until there is support for netd address setting 1896 StringBuilder builder = new StringBuilder(); 1897 for (LinkAddress address : config.addresses) { 1898 builder.append(" "); 1899 builder.append(address); 1900 } 1901 if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) { 1902 throw new IllegalArgumentException("At least one address must be specified"); 1903 } 1904 Connection connection = new Connection(); 1905 if (!mContext.bindServiceAsUser(intent, connection, 1906 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 1907 new UserHandle(mUserId))) { 1908 throw new IllegalStateException("Cannot bind " + config.user); 1909 } 1910 1911 mConnection = connection; 1912 mInterface = interfaze; 1913 1914 // Fill more values. 1915 config.user = mPackage; 1916 config.interfaze = mInterface; 1917 config.startTime = SystemClock.elapsedRealtime(); 1918 mConfig = config; 1919 1920 // Set up forwarding and DNS rules. 1921 // First attempt to do a seamless handover that only changes the interface name and 1922 // parameters. If that fails, disconnect. 1923 if (oldConfig != null 1924 && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) { 1925 // Update underlying networks if it is changed. 1926 if (!Arrays.equals(oldConfig.underlyingNetworks, config.underlyingNetworks)) { 1927 setUnderlyingNetworks(config.underlyingNetworks); 1928 } 1929 } else { 1930 startNewNetworkAgent(oldNetworkAgent, "establish"); 1931 } 1932 1933 if (oldConnection != null) { 1934 mContext.unbindService(oldConnection); 1935 } 1936 1937 if (oldInterface != null && !oldInterface.equals(interfaze)) { 1938 jniReset(oldInterface); 1939 } 1940 1941 mDeps.setBlocking(tun.getFileDescriptor(), config.blocking); 1942 // Record that the VPN connection is established by an app which uses VpnService API. 1943 if (oldNetworkAgent != mNetworkAgent) { 1944 mAppOpsManager.startOp( 1945 AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null); 1946 } 1947 } catch (RuntimeException e) { 1948 IoUtils.closeQuietly(tun); 1949 // If this is not seamless handover, disconnect partially-established network when error 1950 // occurs. 1951 if (oldNetworkAgent != mNetworkAgent) { 1952 agentDisconnect(); 1953 } 1954 // restore old state 1955 mConfig = oldConfig; 1956 mConnection = oldConnection; 1957 mNetworkCapabilities = 1958 new NetworkCapabilities.Builder(mNetworkCapabilities).setUids(oldUsers).build(); 1959 mNetworkAgent = oldNetworkAgent; 1960 mInterface = oldInterface; 1961 throw e; 1962 } 1963 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 1964 return tun; 1965 } 1966 isRunningLocked()1967 private boolean isRunningLocked() { 1968 return mNetworkAgent != null && mInterface != null; 1969 } 1970 1971 // Returns true if the VPN has been established and the calling UID is its owner. Used to check 1972 // that a call to mutate VPN state is admissible. 1973 @VisibleForTesting isCallerEstablishedOwnerLocked()1974 protected boolean isCallerEstablishedOwnerLocked() { 1975 return isRunningLocked() && Binder.getCallingUid() == mOwnerUID; 1976 } 1977 1978 // Note: Return type guarantees results are deduped and sorted, which callers require. 1979 // This method also adds the SDK sandbox UIDs corresponding to the applications by default, 1980 // since apps are generally not aware of them, yet they should follow the VPN configuration 1981 // of the app they belong to. getAppsUids(List<String> packageNames, int userId)1982 private SortedSet<Integer> getAppsUids(List<String> packageNames, int userId) { 1983 SortedSet<Integer> uids = new TreeSet<>(); 1984 for (String app : packageNames) { 1985 int uid = getAppUid(mContext, app, userId); 1986 if (uid != -1) uids.add(uid); 1987 // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from 1988 // ConnectivityServiceTest. 1989 if (Process.isApplicationUid(uid) && SdkLevel.isAtLeastT()) { 1990 uids.add(Process.toSdkSandboxUid(uid)); 1991 } 1992 } 1993 return uids; 1994 } 1995 1996 /** 1997 * Creates a {@link Set} of non-intersecting {@code Range<Integer>} objects including all UIDs 1998 * associated with one user, and any restricted profiles attached to that user. 1999 * 2000 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 2001 * the UID ranges will match the app list specified there. Otherwise, all UIDs 2002 * in each user and profile will be included. 2003 * 2004 * @param userId The userId to create UID ranges for along with any of its restricted 2005 * profiles. 2006 * @param allowedApplications (optional) List of applications to allow. 2007 * @param disallowedApplications (optional) List of applications to deny. 2008 */ 2009 @VisibleForTesting createUserAndRestrictedProfilesRanges(@serIdInt int userId, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications)2010 Set<Range<Integer>> createUserAndRestrictedProfilesRanges(@UserIdInt int userId, 2011 @Nullable List<String> allowedApplications, 2012 @Nullable List<String> disallowedApplications) { 2013 final Set<Range<Integer>> ranges = new ArraySet<>(); 2014 2015 // Assign the top-level user to the set of ranges 2016 addUserToRanges(ranges, userId, allowedApplications, disallowedApplications); 2017 2018 // If the user can have restricted profiles, assign all its restricted profiles too 2019 if (canHaveRestrictedProfile(userId)) { 2020 final long token = Binder.clearCallingIdentity(); 2021 List<UserInfo> users; 2022 try { 2023 users = mUserManager.getAliveUsers(); 2024 } finally { 2025 Binder.restoreCallingIdentity(token); 2026 } 2027 for (UserInfo user : users) { 2028 if (user.isRestricted() && (user.restrictedProfileParentId == userId)) { 2029 addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications); 2030 } 2031 } 2032 } 2033 return ranges; 2034 } 2035 2036 /** 2037 * Updates a {@link Set} of non-intersecting {@code Range<Integer>} objects to include all UIDs 2038 * associated with one user. 2039 * 2040 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 2041 * the UID ranges will match the app allowlist or denylist specified there. Otherwise, all UIDs 2042 * in the user will be included. 2043 * 2044 * @param ranges {@link Set} of {@code Range<Integer>}s to which to add. 2045 * @param userId The userId to add to {@param ranges}. 2046 * @param allowedApplications (optional) allowlist of applications to include. 2047 * @param disallowedApplications (optional) denylist of applications to exclude. 2048 */ 2049 @VisibleForTesting addUserToRanges(@onNull Set<Range<Integer>> ranges, @UserIdInt int userId, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications)2050 void addUserToRanges(@NonNull Set<Range<Integer>> ranges, @UserIdInt int userId, 2051 @Nullable List<String> allowedApplications, 2052 @Nullable List<String> disallowedApplications) { 2053 if (allowedApplications != null) { 2054 // Add ranges covering all UIDs for allowedApplications. 2055 int start = -1, stop = -1; 2056 for (int uid : getAppsUids(allowedApplications, userId)) { 2057 if (start == -1) { 2058 start = uid; 2059 } else if (uid != stop + 1) { 2060 ranges.add(new Range<Integer>(start, stop)); 2061 start = uid; 2062 } 2063 stop = uid; 2064 } 2065 if (start != -1) ranges.add(new Range<Integer>(start, stop)); 2066 } else if (disallowedApplications != null) { 2067 // Add all ranges for user skipping UIDs for disallowedApplications. 2068 final Range<Integer> userRange = createUidRangeForUser(userId); 2069 int start = userRange.getLower(); 2070 for (int uid : getAppsUids(disallowedApplications, userId)) { 2071 if (uid == start) { 2072 start++; 2073 } else { 2074 ranges.add(new Range<Integer>(start, uid - 1)); 2075 start = uid + 1; 2076 } 2077 } 2078 if (start <= userRange.getUpper()) { 2079 ranges.add(new Range<Integer>(start, userRange.getUpper())); 2080 } 2081 } else { 2082 // Add all UIDs for the user. 2083 ranges.add(createUidRangeForUser(userId)); 2084 } 2085 } 2086 2087 // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that 2088 // apply to userId. uidRangesForUser(int userId, Set<Range<Integer>> existingRanges)2089 private static List<Range<Integer>> uidRangesForUser(int userId, 2090 Set<Range<Integer>> existingRanges) { 2091 final Range<Integer> userRange = createUidRangeForUser(userId); 2092 final List<Range<Integer>> ranges = new ArrayList<>(); 2093 for (Range<Integer> range : existingRanges) { 2094 if (userRange.contains(range)) { 2095 ranges.add(range); 2096 } 2097 } 2098 return ranges; 2099 } 2100 2101 /** 2102 * Updates UID ranges for this VPN and also updates its internal capabilities. 2103 * 2104 * <p>Should be called on primary ConnectivityService thread. 2105 */ onUserAdded(int userId)2106 public void onUserAdded(int userId) { 2107 // If the user is restricted tie them to the parent user's VPN 2108 UserInfo user = mUserManager.getUserInfo(userId); 2109 if (user.isRestricted() && user.restrictedProfileParentId == mUserId) { 2110 synchronized(Vpn.this) { 2111 final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids(); 2112 if (existingRanges != null) { 2113 try { 2114 addUserToRanges(existingRanges, userId, mConfig.allowedApplications, 2115 mConfig.disallowedApplications); 2116 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) 2117 .setUids(existingRanges).build(); 2118 } catch (Exception e) { 2119 Log.wtf(TAG, "Failed to add restricted user to owner", e); 2120 } 2121 if (mNetworkAgent != null) { 2122 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); 2123 } 2124 } 2125 setVpnForcedLocked(mLockdown); 2126 } 2127 } 2128 } 2129 2130 /** 2131 * Updates UID ranges for this VPN and also updates its capabilities. 2132 * 2133 * <p>Should be called on primary ConnectivityService thread. 2134 */ onUserRemoved(int userId)2135 public void onUserRemoved(int userId) { 2136 // clean up if restricted 2137 UserInfo user = mUserManager.getUserInfo(userId); 2138 if (user.isRestricted() && user.restrictedProfileParentId == mUserId) { 2139 synchronized(Vpn.this) { 2140 final Set<Range<Integer>> existingRanges = mNetworkCapabilities.getUids(); 2141 if (existingRanges != null) { 2142 try { 2143 final List<Range<Integer>> removedRanges = 2144 uidRangesForUser(userId, existingRanges); 2145 existingRanges.removeAll(removedRanges); 2146 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) 2147 .setUids(existingRanges).build(); 2148 } catch (Exception e) { 2149 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 2150 } 2151 if (mNetworkAgent != null) { 2152 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); 2153 } 2154 } 2155 setVpnForcedLocked(mLockdown); 2156 } 2157 } 2158 } 2159 2160 /** 2161 * Called when the user associated with this VPN has just been stopped. 2162 */ onUserStopped()2163 public synchronized void onUserStopped() { 2164 // Switch off networking lockdown (if it was enabled) 2165 setVpnForcedLocked(false); 2166 mAlwaysOn = false; 2167 2168 // Quit any active connections 2169 agentDisconnect(); 2170 2171 // The provider has been registered in the constructor, which is called in onUserStart. 2172 mConnectivityManager.unregisterNetworkProvider(mNetworkProvider); 2173 } 2174 2175 /** 2176 * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN 2177 * service app itself and allowed packages, to only sockets that have had {@code protect()} 2178 * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the 2179 * kernel. 2180 * 2181 * The exception for the VPN UID isn't technically necessary -- setup should use protected 2182 * sockets -- but in practice it saves apps that don't protect their sockets from breaking. 2183 * 2184 * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to 2185 * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}. 2186 * 2187 * @param enforce {@code true} to require that all traffic under the jurisdiction of this 2188 * {@link Vpn} goes through a VPN connection or is blocked until one is 2189 * available, {@code false} to lift the requirement. 2190 * 2191 * @see #mBlockedUidsAsToldToConnectivity 2192 */ 2193 @GuardedBy("this") setVpnForcedLocked(boolean enforce)2194 private void setVpnForcedLocked(boolean enforce) { 2195 final List<String> exemptedPackages; 2196 if (isNullOrLegacyVpn(mPackage)) { 2197 exemptedPackages = null; 2198 } else { 2199 exemptedPackages = new ArrayList<>(mLockdownAllowlist); 2200 exemptedPackages.add(mPackage); 2201 } 2202 final Set<UidRangeParcel> rangesToRemove = new ArraySet<>(mBlockedUidsAsToldToConnectivity); 2203 final Set<UidRangeParcel> rangesToAdd; 2204 if (enforce) { 2205 final Set<Range<Integer>> restrictedProfilesRanges = 2206 createUserAndRestrictedProfilesRanges(mUserId, 2207 /* allowedApplications */ null, 2208 /* disallowedApplications */ exemptedPackages); 2209 final Set<UidRangeParcel> rangesThatShouldBeBlocked = new ArraySet<>(); 2210 2211 // The UID range of the first user (0-99999) would block the IPSec traffic, which comes 2212 // directly from the kernel and is marked as uid=0. So we adjust the range to allow 2213 // it through (b/69873852). 2214 for (Range<Integer> range : restrictedProfilesRanges) { 2215 if (range.getLower() == 0 && range.getUpper() != 0) { 2216 rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.getUpper())); 2217 } else if (range.getLower() != 0) { 2218 rangesThatShouldBeBlocked.add( 2219 new UidRangeParcel(range.getLower(), range.getUpper())); 2220 } 2221 } 2222 2223 rangesToRemove.removeAll(rangesThatShouldBeBlocked); 2224 rangesToAdd = rangesThatShouldBeBlocked; 2225 // The ranges to tell ConnectivityService to add are the ones that should be blocked 2226 // minus the ones it already knows to block. Note that this will change the contents of 2227 // rangesThatShouldBeBlocked, but the list of ranges that should be blocked is 2228 // not used after this so it's fine to destroy it. 2229 rangesToAdd.removeAll(mBlockedUidsAsToldToConnectivity); 2230 } else { 2231 rangesToAdd = Collections.emptySet(); 2232 } 2233 2234 // If mBlockedUidsAsToldToNetd used to be empty, this will always be a no-op. 2235 setAllowOnlyVpnForUids(false, rangesToRemove); 2236 // If nothing should be blocked now, this will now be a no-op. 2237 setAllowOnlyVpnForUids(true, rangesToAdd); 2238 } 2239 2240 /** 2241 * Tell ConnectivityService to add or remove a list of {@link UidRangeParcel}s to the list of 2242 * UIDs that are only allowed to make connections through sockets that have had 2243 * {@code protect()} called on them. 2244 * 2245 * @param enforce {@code true} to add to the denylist, {@code false} to remove. 2246 * @param ranges {@link Collection} of {@link UidRangeParcel}s to add (if {@param enforce} is 2247 * {@code true}) or to remove. 2248 * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, 2249 * including added ranges that already existed or removed ones that didn't. 2250 */ 2251 @GuardedBy("this") setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges)2252 private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges) { 2253 if (ranges.size() == 0) { 2254 return true; 2255 } 2256 // Convert to Collection<Range> which is what the ConnectivityManager API takes. 2257 ArrayList<Range<Integer>> integerRanges = new ArrayList<>(ranges.size()); 2258 for (UidRangeParcel uidRange : ranges) { 2259 integerRanges.add(new Range<>(uidRange.start, uidRange.stop)); 2260 } 2261 try { 2262 mConnectivityManager.setRequireVpnForUids(enforce, integerRanges); 2263 } catch (RuntimeException e) { 2264 Log.e(TAG, "Updating blocked=" + enforce 2265 + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e); 2266 return false; 2267 } 2268 if (enforce) { 2269 mBlockedUidsAsToldToConnectivity.addAll(ranges); 2270 } else { 2271 mBlockedUidsAsToldToConnectivity.removeAll(ranges); 2272 } 2273 return true; 2274 } 2275 2276 /** 2277 * Return the configuration of the currently running VPN. 2278 */ getVpnConfig()2279 public synchronized VpnConfig getVpnConfig() { 2280 enforceControlPermission(); 2281 // Constructor of VpnConfig cannot take a null parameter. Return null directly if mConfig is 2282 // null 2283 if (mConfig == null) return null; 2284 // mConfig is guarded by "this" and can be modified by another thread as soon as 2285 // this method returns, so this method must return a copy. 2286 return new VpnConfig(mConfig); 2287 } 2288 2289 @Deprecated interfaceStatusChanged(String iface, boolean up)2290 public synchronized void interfaceStatusChanged(String iface, boolean up) { 2291 try { 2292 mObserver.interfaceStatusChanged(iface, up); 2293 } catch (RemoteException e) { 2294 // ignored; target is local 2295 } 2296 } 2297 2298 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 2299 @Override 2300 public void interfaceStatusChanged(String interfaze, boolean up) { 2301 synchronized (Vpn.this) { 2302 if (!up && mVpnRunner != null && mVpnRunner instanceof LegacyVpnRunner) { 2303 ((LegacyVpnRunner) mVpnRunner).exitIfOuterInterfaceIs(interfaze); 2304 } 2305 } 2306 } 2307 2308 @Override 2309 public void interfaceRemoved(String interfaze) { 2310 synchronized (Vpn.this) { 2311 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 2312 if (mConnection != null) { 2313 mAppOpsManager.finishOp( 2314 AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, 2315 null); 2316 mContext.unbindService(mConnection); 2317 cleanupVpnStateLocked(); 2318 } else if (mVpnRunner != null) { 2319 if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { 2320 mAppOpsManager.finishOp( 2321 AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, 2322 null); 2323 } 2324 // cleanupVpnStateLocked() is called from mVpnRunner.exit() 2325 mVpnRunner.exit(); 2326 } 2327 } 2328 } 2329 } 2330 }; 2331 2332 @GuardedBy("this") cleanupVpnStateLocked()2333 private void cleanupVpnStateLocked() { 2334 mStatusIntent = null; 2335 resetNetworkCapabilities(); 2336 mConfig = null; 2337 mInterface = null; 2338 2339 // Unconditionally clear both VpnService and VpnRunner fields. 2340 mVpnRunner = null; 2341 mConnection = null; 2342 agentDisconnect(); 2343 } 2344 enforceControlPermission()2345 private void enforceControlPermission() { 2346 mContext.enforceCallingPermission(CONTROL_VPN, "Unauthorized Caller"); 2347 } 2348 enforceControlPermissionOrInternalCaller()2349 private void enforceControlPermissionOrInternalCaller() { 2350 // Require the caller to be either an application with CONTROL_VPN permission or a process 2351 // in the system server. 2352 mContext.enforceCallingOrSelfPermission(CONTROL_VPN, "Unauthorized Caller"); 2353 } 2354 enforceSettingsPermission()2355 private void enforceSettingsPermission() { 2356 mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_SETTINGS, 2357 "Unauthorized Caller"); 2358 } 2359 2360 private class Connection implements ServiceConnection { 2361 private IBinder mService; 2362 2363 @Override onServiceConnected(ComponentName name, IBinder service)2364 public void onServiceConnected(ComponentName name, IBinder service) { 2365 mService = service; 2366 } 2367 2368 @Override onServiceDisconnected(ComponentName name)2369 public void onServiceDisconnected(ComponentName name) { 2370 mService = null; 2371 } 2372 } 2373 prepareStatusIntent()2374 private void prepareStatusIntent() { 2375 final long token = Binder.clearCallingIdentity(); 2376 try { 2377 mStatusIntent = mDeps.getIntentForStatusPanel(mContext); 2378 } finally { 2379 Binder.restoreCallingIdentity(token); 2380 } 2381 } 2382 addAddress(String address, int prefixLength)2383 public synchronized boolean addAddress(String address, int prefixLength) { 2384 if (!isCallerEstablishedOwnerLocked()) { 2385 return false; 2386 } 2387 boolean success = jniAddAddress(mInterface, address, prefixLength); 2388 doSendLinkProperties(mNetworkAgent, makeLinkProperties()); 2389 return success; 2390 } 2391 removeAddress(String address, int prefixLength)2392 public synchronized boolean removeAddress(String address, int prefixLength) { 2393 if (!isCallerEstablishedOwnerLocked()) { 2394 return false; 2395 } 2396 boolean success = jniDelAddress(mInterface, address, prefixLength); 2397 doSendLinkProperties(mNetworkAgent, makeLinkProperties()); 2398 return success; 2399 } 2400 2401 /** 2402 * Updates underlying network set. 2403 */ setUnderlyingNetworks(@ullable Network[] networks)2404 public synchronized boolean setUnderlyingNetworks(@Nullable Network[] networks) { 2405 if (!isCallerEstablishedOwnerLocked()) { 2406 return false; 2407 } 2408 // Make defensive copy since the content of array might be altered by the caller. 2409 mConfig.underlyingNetworks = 2410 (networks != null) ? Arrays.copyOf(networks, networks.length) : null; 2411 doSetUnderlyingNetworks( 2412 mNetworkAgent, 2413 (mConfig.underlyingNetworks != null) 2414 ? Arrays.asList(mConfig.underlyingNetworks) 2415 : null); 2416 return true; 2417 } 2418 2419 /** 2420 * This method should not be called if underlying interfaces field is needed, because it doesn't 2421 * have enough data to fill VpnInfo.underlyingIfaces field. 2422 */ getUnderlyingNetworkInfo()2423 public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() { 2424 if (!isRunningLocked()) { 2425 return null; 2426 } 2427 2428 return new UnderlyingNetworkInfo(mOwnerUID, mInterface, new ArrayList<>()); 2429 } 2430 appliesToUid(int uid)2431 public synchronized boolean appliesToUid(int uid) { 2432 if (!isRunningLocked()) { 2433 return false; 2434 } 2435 final Set<Range<Integer>> uids = mNetworkCapabilities.getUids(); 2436 if (uids == null) return true; 2437 for (final Range<Integer> range : uids) { 2438 if (range.contains(uid)) return true; 2439 } 2440 return false; 2441 } 2442 2443 /** 2444 * Gets the currently running VPN type 2445 * 2446 * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running a 2447 * VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always 2448 * Settings-based, the Platform VPNs can be initiated by both apps and Settings. 2449 */ getActiveVpnType()2450 public synchronized int getActiveVpnType() { 2451 if (!mNetworkInfo.isConnectedOrConnecting()) return VpnManager.TYPE_VPN_NONE; 2452 if (mVpnRunner == null) return VpnManager.TYPE_VPN_SERVICE; 2453 return isIkev2VpnRunner() ? VpnManager.TYPE_VPN_PLATFORM : VpnManager.TYPE_VPN_LEGACY; 2454 } 2455 2456 @GuardedBy("this") updateAlwaysOnNotification(DetailedState networkState)2457 private void updateAlwaysOnNotification(DetailedState networkState) { 2458 final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); 2459 2460 final UserHandle user = UserHandle.of(mUserId); 2461 final long token = Binder.clearCallingIdentity(); 2462 try { 2463 final NotificationManager notificationManager = 2464 mUserIdContext.getSystemService(NotificationManager.class); 2465 if (!visible) { 2466 notificationManager.cancel(TAG, SystemMessage.NOTE_VPN_DISCONNECTED); 2467 return; 2468 } 2469 final Intent intent = new Intent(); 2470 intent.setComponent(ComponentName.unflattenFromString(mContext.getString( 2471 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))); 2472 intent.putExtra("lockdown", mLockdown); 2473 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2474 final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser( 2475 intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user); 2476 final Notification.Builder builder = 2477 new Notification.Builder(mContext, NOTIFICATION_CHANNEL_VPN) 2478 .setSmallIcon(R.drawable.vpn_connected) 2479 .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected)) 2480 .setContentText(mContext.getString(R.string.vpn_lockdown_config)) 2481 .setContentIntent(configIntent) 2482 .setCategory(Notification.CATEGORY_SYSTEM) 2483 .setVisibility(Notification.VISIBILITY_PUBLIC) 2484 .setOngoing(true) 2485 .setColor(mContext.getColor( 2486 android.R.color.system_notification_accent_color)); 2487 notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build()); 2488 } finally { 2489 Binder.restoreCallingIdentity(token); 2490 } 2491 } 2492 2493 /** 2494 * Facade for system service calls that change, or depend on, state outside of 2495 * {@link ConnectivityService} and have hard-to-mock interfaces. 2496 * 2497 * @see com.android.server.connectivity.VpnTest 2498 */ 2499 @VisibleForTesting 2500 public static class SystemServices { 2501 private final Context mContext; 2502 SystemServices(@onNull Context context)2503 public SystemServices(@NonNull Context context) { 2504 mContext = context; 2505 } 2506 2507 /** 2508 * @see PendingIntent#getActivityAsUser() 2509 */ pendingIntentGetActivityAsUser( Intent intent, int flags, UserHandle user)2510 public PendingIntent pendingIntentGetActivityAsUser( 2511 Intent intent, int flags, UserHandle user) { 2512 return PendingIntent.getActivity( 2513 mContext.createContextAsUser(user, 0 /* flags */), 0 /* requestCode */, 2514 intent, flags); 2515 } 2516 2517 /** 2518 * @see Settings.Secure#putStringForUser 2519 */ settingsSecurePutStringForUser(String key, String value, int userId)2520 public void settingsSecurePutStringForUser(String key, String value, int userId) { 2521 Settings.Secure.putString(getContentResolverAsUser(userId), key, value); 2522 } 2523 2524 /** 2525 * @see Settings.Secure#putIntForUser 2526 */ settingsSecurePutIntForUser(String key, int value, int userId)2527 public void settingsSecurePutIntForUser(String key, int value, int userId) { 2528 Settings.Secure.putInt(getContentResolverAsUser(userId), key, value); 2529 } 2530 2531 /** 2532 * @see Settings.Secure#getStringForUser 2533 */ settingsSecureGetStringForUser(String key, int userId)2534 public String settingsSecureGetStringForUser(String key, int userId) { 2535 return Settings.Secure.getString(getContentResolverAsUser(userId), key); 2536 } 2537 2538 /** 2539 * @see Settings.Secure#getIntForUser 2540 */ settingsSecureGetIntForUser(String key, int def, int userId)2541 public int settingsSecureGetIntForUser(String key, int def, int userId) { 2542 return Settings.Secure.getInt(getContentResolverAsUser(userId), key, def); 2543 } 2544 getContentResolverAsUser(int userId)2545 private ContentResolver getContentResolverAsUser(int userId) { 2546 return mContext.createContextAsUser( 2547 UserHandle.of(userId), 0 /* flags */).getContentResolver(); 2548 } 2549 } 2550 jniCreate(int mtu)2551 private native int jniCreate(int mtu); jniGetName(int tun)2552 private native String jniGetName(int tun); jniSetAddresses(String interfaze, String addresses)2553 private native int jniSetAddresses(String interfaze, String addresses); jniReset(String interfaze)2554 private native void jniReset(String interfaze); jniCheck(String interfaze)2555 private native int jniCheck(String interfaze); jniAddAddress(String interfaze, String address, int prefixLen)2556 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); jniDelAddress(String interfaze, String address, int prefixLen)2557 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 2558 findIPv4DefaultRoute(LinkProperties prop)2559 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 2560 for (RouteInfo route : prop.getAllRoutes()) { 2561 // Currently legacy VPN only works on IPv4. 2562 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 2563 return route; 2564 } 2565 } 2566 2567 throw new IllegalStateException("Unable to find IPv4 default gateway"); 2568 } 2569 enforceNotRestrictedUser()2570 private void enforceNotRestrictedUser() { 2571 final long token = Binder.clearCallingIdentity(); 2572 try { 2573 final UserInfo user = mUserManager.getUserInfo(mUserId); 2574 2575 if (user.isRestricted()) { 2576 throw new SecurityException("Restricted users cannot configure VPNs"); 2577 } 2578 } finally { 2579 Binder.restoreCallingIdentity(token); 2580 } 2581 } 2582 2583 /** 2584 * Start legacy VPN, controlling native daemons as needed. Creates a 2585 * secondary thread to perform connection work, returning quickly. 2586 * 2587 * Should only be called to respond to Binder requests as this enforces caller permission. Use 2588 * {@link #startLegacyVpnPrivileged(VpnProfile, Network, LinkProperties)} to skip the 2589 * permission check only when the caller is trusted (or the call is initiated by the system). 2590 */ startLegacyVpn(VpnProfile profile, @Nullable Network underlying, LinkProperties egress)2591 public void startLegacyVpn(VpnProfile profile, @Nullable Network underlying, 2592 LinkProperties egress) { 2593 enforceControlPermission(); 2594 final long token = Binder.clearCallingIdentity(); 2595 try { 2596 startLegacyVpnPrivileged(profile, underlying, egress); 2597 } finally { 2598 Binder.restoreCallingIdentity(token); 2599 } 2600 } 2601 makeKeystoreEngineGrantString(String alias)2602 private String makeKeystoreEngineGrantString(String alias) { 2603 if (alias == null) { 2604 return null; 2605 } 2606 final KeyStore2 keystore2 = KeyStore2.getInstance(); 2607 2608 KeyDescriptor key = new KeyDescriptor(); 2609 key.domain = Domain.APP; 2610 key.nspace = KeyProperties.NAMESPACE_APPLICATION; 2611 key.alias = alias; 2612 key.blob = null; 2613 2614 final int grantAccessVector = KeyPermission.USE | KeyPermission.GET_INFO; 2615 2616 try { 2617 // The native vpn daemon is running as VPN_UID. This tells Keystore 2.0 2618 // to allow a process running with this UID to access the key designated by 2619 // the KeyDescriptor `key`. `grant` returns a new KeyDescriptor with a grant 2620 // identifier. This identifier needs to be communicated to the vpn daemon. 2621 key = keystore2.grant(key, android.os.Process.VPN_UID, grantAccessVector); 2622 } catch (android.security.KeyStoreException e) { 2623 Log.e(TAG, "Failed to get grant for keystore key.", e); 2624 throw new IllegalStateException("Failed to get grant for keystore key.", e); 2625 } 2626 2627 // Turn the grant identifier into a string as understood by the keystore boringssl engine 2628 // in system/security/keystore-engine. 2629 return KeyStore2.makeKeystoreEngineGrantString(key.nspace); 2630 } 2631 getCaCertificateFromKeystoreAsPem(@onNull KeyStore keystore, @NonNull String alias)2632 private String getCaCertificateFromKeystoreAsPem(@NonNull KeyStore keystore, 2633 @NonNull String alias) 2634 throws KeyStoreException, IOException, CertificateEncodingException { 2635 if (keystore.isCertificateEntry(alias)) { 2636 final Certificate cert = keystore.getCertificate(alias); 2637 if (cert == null) return null; 2638 return new String(Credentials.convertToPem(cert), StandardCharsets.UTF_8); 2639 } else { 2640 final Certificate[] certs = keystore.getCertificateChain(alias); 2641 // If there is none or one entry it means there is no CA entry associated with this 2642 // alias. 2643 if (certs == null || certs.length <= 1) { 2644 return null; 2645 } 2646 // If this is not a (pure) certificate entry, then there is a user certificate which 2647 // will be included at the beginning of the certificate chain. But the caller of this 2648 // function does not expect this certificate to be included, so we cut it off. 2649 return new String(Credentials.convertToPem( 2650 Arrays.copyOfRange(certs, 1, certs.length)), StandardCharsets.UTF_8); 2651 } 2652 } 2653 2654 /** 2655 * Like {@link #startLegacyVpn(VpnProfile, Network, LinkProperties)}, but does not 2656 * check permissions under the assumption that the caller is the system. 2657 * 2658 * Callers are responsible for checking permissions if needed. 2659 */ startLegacyVpnPrivileged(VpnProfile profile, @Nullable Network underlying, @NonNull LinkProperties egress)2660 public void startLegacyVpnPrivileged(VpnProfile profile, 2661 @Nullable Network underlying, @NonNull LinkProperties egress) { 2662 UserInfo user = mUserManager.getUserInfo(mUserId); 2663 if (user.isRestricted() || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, 2664 new UserHandle(mUserId))) { 2665 throw new SecurityException("Restricted users cannot establish VPNs"); 2666 } 2667 2668 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 2669 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 2670 final String iface = ipv4DefaultRoute.getInterface(); 2671 2672 // Load certificates. 2673 String privateKey = ""; 2674 String userCert = ""; 2675 String caCert = ""; 2676 String serverCert = ""; 2677 2678 try { 2679 final KeyStore keystore = KeyStore.getInstance(ANDROID_KEYSTORE_PROVIDER); 2680 keystore.load(null); 2681 if (!profile.ipsecUserCert.isEmpty()) { 2682 privateKey = profile.ipsecUserCert; 2683 final Certificate cert = keystore.getCertificate(profile.ipsecUserCert); 2684 userCert = (cert == null) ? null 2685 : new String(Credentials.convertToPem(cert), StandardCharsets.UTF_8); 2686 } 2687 if (!profile.ipsecCaCert.isEmpty()) { 2688 caCert = getCaCertificateFromKeystoreAsPem(keystore, profile.ipsecCaCert); 2689 } 2690 if (!profile.ipsecServerCert.isEmpty()) { 2691 final Certificate cert = keystore.getCertificate(profile.ipsecServerCert); 2692 serverCert = (cert == null) ? null 2693 : new String(Credentials.convertToPem(cert), StandardCharsets.UTF_8); 2694 } 2695 } catch (CertificateException | KeyStoreException | IOException 2696 | NoSuchAlgorithmException e) { 2697 throw new IllegalStateException("Failed to load credentials from AndroidKeyStore", e); 2698 } 2699 if (userCert == null || caCert == null || serverCert == null) { 2700 throw new IllegalStateException("Cannot load credentials"); 2701 } 2702 2703 // Prepare arguments for racoon. 2704 String[] racoon = null; 2705 switch (profile.type) { 2706 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 2707 // Secret key is still just the alias (not the actual private key). The private key 2708 // is retrieved from the KeyStore during conversion of the VpnProfile to an 2709 // Ikev2VpnProfile. 2710 profile.ipsecSecret = Ikev2VpnProfile.PREFIX_KEYSTORE_ALIAS + privateKey; 2711 profile.ipsecUserCert = userCert; 2712 // Fallthrough 2713 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 2714 profile.ipsecCaCert = caCert; 2715 2716 // Start VPN profile 2717 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); 2718 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN); 2719 return; 2720 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 2721 // Ikev2VpnProfiles expect a base64-encoded preshared key. 2722 profile.ipsecSecret = 2723 Ikev2VpnProfile.encodeForIpsecSecret(profile.ipsecSecret.getBytes()); 2724 2725 // Start VPN profile 2726 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); 2727 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN); 2728 return; 2729 case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS: 2730 // All the necessary IKE options should come from IkeTunnelConnectionParams in the 2731 // profile. 2732 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN); 2733 return; 2734 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 2735 racoon = new String[] { 2736 iface, profile.server, "udppsk", profile.ipsecIdentifier, 2737 profile.ipsecSecret, "1701", 2738 }; 2739 break; 2740 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 2741 racoon = new String[] { 2742 iface, profile.server, "udprsa", makeKeystoreEngineGrantString(privateKey), 2743 userCert, caCert, serverCert, "1701", 2744 }; 2745 break; 2746 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 2747 racoon = new String[] { 2748 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 2749 profile.ipsecSecret, profile.username, profile.password, "", gateway, 2750 }; 2751 break; 2752 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 2753 racoon = new String[] { 2754 iface, profile.server, "xauthrsa", makeKeystoreEngineGrantString(privateKey), 2755 userCert, caCert, serverCert, profile.username, profile.password, "", gateway, 2756 }; 2757 break; 2758 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 2759 racoon = new String[] { 2760 iface, profile.server, "hybridrsa", 2761 caCert, serverCert, profile.username, profile.password, "", gateway, 2762 }; 2763 break; 2764 } 2765 2766 // Prepare arguments for mtpd. MTU/MRU calculated conservatively. Only IPv4 supported 2767 // because LegacyVpn. 2768 // 1500 - 60 (Carrier-internal IPv6 + UDP + GTP) - 10 (PPP) - 16 (L2TP) - 8 (UDP) 2769 // - 77 (IPsec w/ SHA-2 512, 256b trunc-len, AES-CBC) - 8 (UDP encap) - 20 (IPv4) 2770 // - 28 (464xlat) 2771 String[] mtpd = null; 2772 switch (profile.type) { 2773 case VpnProfile.TYPE_PPTP: 2774 mtpd = new String[] { 2775 iface, "pptp", profile.server, "1723", 2776 "name", profile.username, "password", profile.password, 2777 "linkname", "vpn", "refuse-eap", "nodefaultroute", 2778 "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270", 2779 (profile.mppe ? "+mppe" : "nomppe"), 2780 }; 2781 if (profile.mppe) { 2782 // Disallow PAP authentication when MPPE is requested, as MPPE cannot work 2783 // with PAP anyway, and users may not expect PAP (plain text) to be used when 2784 // MPPE was requested. 2785 mtpd = Arrays.copyOf(mtpd, mtpd.length + 1); 2786 mtpd[mtpd.length - 1] = "-pap"; 2787 } 2788 break; 2789 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 2790 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 2791 mtpd = new String[] { 2792 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 2793 "name", profile.username, "password", profile.password, 2794 "linkname", "vpn", "refuse-eap", "nodefaultroute", 2795 "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270", 2796 }; 2797 break; 2798 } 2799 2800 VpnConfig config = new VpnConfig(); 2801 config.legacy = true; 2802 config.user = profile.key; 2803 config.interfaze = iface; 2804 config.session = profile.name; 2805 config.isMetered = false; 2806 config.proxyInfo = profile.proxy; 2807 if (underlying != null) { 2808 config.underlyingNetworks = new Network[] { underlying }; 2809 } 2810 2811 config.addLegacyRoutes(profile.routes); 2812 if (!profile.dnsServers.isEmpty()) { 2813 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 2814 } 2815 if (!profile.searchDomains.isEmpty()) { 2816 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 2817 } 2818 startLegacyVpn(config, racoon, mtpd, profile); 2819 } 2820 startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile)2821 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, 2822 VpnProfile profile) { 2823 stopVpnRunnerPrivileged(); 2824 2825 // Prepare for the new request. 2826 prepareInternal(VpnConfig.LEGACY_VPN); 2827 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 2828 2829 // Start a new LegacyVpnRunner and we are done! 2830 mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile); 2831 startLegacyVpnRunner(); 2832 } 2833 2834 @VisibleForTesting startLegacyVpnRunner()2835 protected void startLegacyVpnRunner() { 2836 mVpnRunner.start(); 2837 } 2838 2839 /** 2840 * Checks if this the currently running VPN (if any) was started by the Settings app 2841 * 2842 * <p>This includes both Legacy VPNs and Platform VPNs. 2843 */ isSettingsVpnLocked()2844 private boolean isSettingsVpnLocked() { 2845 return mVpnRunner != null && VpnConfig.LEGACY_VPN.equals(mPackage); 2846 } 2847 2848 /** Stop VPN runner. Permissions must be checked by callers. */ stopVpnRunnerPrivileged()2849 public synchronized void stopVpnRunnerPrivileged() { 2850 if (!isSettingsVpnLocked()) { 2851 return; 2852 } 2853 2854 final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner; 2855 mVpnRunner.exit(); 2856 2857 // LegacyVpn uses daemons that must be shut down before new ones are brought up. 2858 // The same limitation does not apply to Platform VPNs. 2859 if (isLegacyVpn) { 2860 synchronized (LegacyVpnRunner.TAG) { 2861 // wait for old thread to completely finish before spinning up 2862 // new instance, otherwise state updates can be out of order. 2863 } 2864 } 2865 } 2866 2867 /** 2868 * Return the information of the current ongoing legacy VPN. 2869 */ getLegacyVpnInfo()2870 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 2871 // Check if the caller is authorized. 2872 enforceControlPermission(); 2873 return getLegacyVpnInfoPrivileged(); 2874 } 2875 2876 /** 2877 * Return the information of the current ongoing legacy VPN. 2878 * Callers are responsible for checking permissions if needed. 2879 */ getLegacyVpnInfoPrivileged()2880 private synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() { 2881 if (!isSettingsVpnLocked()) return null; 2882 2883 final LegacyVpnInfo info = new LegacyVpnInfo(); 2884 info.key = mConfig.user; 2885 info.state = mLegacyState; 2886 if (mNetworkInfo.isConnected()) { 2887 info.intent = mStatusIntent; 2888 } 2889 return info; 2890 } 2891 getLegacyVpnConfig()2892 public synchronized VpnConfig getLegacyVpnConfig() { 2893 if (isSettingsVpnLocked()) { 2894 return mConfig; 2895 } else { 2896 return null; 2897 } 2898 } 2899 2900 @Nullable getRedactedNetworkCapabilities( NetworkCapabilities nc)2901 private synchronized NetworkCapabilities getRedactedNetworkCapabilities( 2902 NetworkCapabilities nc) { 2903 if (nc == null) return null; 2904 return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage( 2905 nc, mOwnerUID, mPackage); 2906 } 2907 2908 @Nullable getRedactedLinkProperties(LinkProperties lp)2909 private synchronized LinkProperties getRedactedLinkProperties(LinkProperties lp) { 2910 if (lp == null) return null; 2911 return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage); 2912 } 2913 2914 /** This class represents the common interface for all VPN runners. */ 2915 @VisibleForTesting 2916 abstract class VpnRunner extends Thread { 2917 VpnRunner(String name)2918 protected VpnRunner(String name) { 2919 super(name); 2920 } 2921 run()2922 public abstract void run(); 2923 2924 /** 2925 * Disconnects the NetworkAgent and cleans up all state related to the VpnRunner. 2926 * 2927 * <p>All outer Vpn instance state is cleaned up in cleanupVpnStateLocked() 2928 */ exitVpnRunner()2929 protected abstract void exitVpnRunner(); 2930 2931 /** 2932 * Triggers the cleanup of the VpnRunner, and additionally cleans up Vpn instance-wide state 2933 * 2934 * <p>This method ensures that simple calls to exit() will always clean up global state 2935 * properly. 2936 */ exit()2937 protected final void exit() { 2938 synchronized (Vpn.this) { 2939 exitVpnRunner(); 2940 cleanupVpnStateLocked(); 2941 } 2942 } 2943 } 2944 2945 interface IkeV2VpnRunnerCallback { onDefaultNetworkChanged(@onNull Network network)2946 void onDefaultNetworkChanged(@NonNull Network network); 2947 onDefaultNetworkCapabilitiesChanged(@onNull NetworkCapabilities nc)2948 void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc); 2949 onDefaultNetworkLinkPropertiesChanged(@onNull LinkProperties lp)2950 void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp); 2951 onDefaultNetworkLost(@onNull Network network)2952 void onDefaultNetworkLost(@NonNull Network network); 2953 onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration)2954 void onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration); 2955 onIkeConnectionInfoChanged( int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo)2956 void onIkeConnectionInfoChanged( 2957 int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo); 2958 onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig)2959 void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig); 2960 onChildTransformCreated(int token, @NonNull IpSecTransform transform, int direction)2961 void onChildTransformCreated(int token, @NonNull IpSecTransform transform, int direction); 2962 onChildMigrated( int token, @NonNull IpSecTransform inTransform, @NonNull IpSecTransform outTransform)2963 void onChildMigrated( 2964 int token, 2965 @NonNull IpSecTransform inTransform, 2966 @NonNull IpSecTransform outTransform); 2967 onSessionLost(int token, @Nullable Exception exception)2968 void onSessionLost(int token, @Nullable Exception exception); 2969 } 2970 isIPv6Only(List<LinkAddress> linkAddresses)2971 private static boolean isIPv6Only(List<LinkAddress> linkAddresses) { 2972 boolean hasIPV6 = false; 2973 boolean hasIPV4 = false; 2974 for (final LinkAddress address : linkAddresses) { 2975 hasIPV6 |= address.isIpv6(); 2976 hasIPV4 |= address.isIpv4(); 2977 } 2978 2979 return hasIPV6 && !hasIPV4; 2980 } 2981 setVpnNetworkPreference(String session, Set<Range<Integer>> ranges)2982 private void setVpnNetworkPreference(String session, Set<Range<Integer>> ranges) { 2983 BinderUtils.withCleanCallingIdentity( 2984 () -> mConnectivityManager.setVpnDefaultForUids(session, ranges)); 2985 } 2986 clearVpnNetworkPreference(String session)2987 private void clearVpnNetworkPreference(String session) { 2988 BinderUtils.withCleanCallingIdentity( 2989 () -> mConnectivityManager.setVpnDefaultForUids(session, Collections.EMPTY_LIST)); 2990 } 2991 2992 /** 2993 * Internal class managing IKEv2/IPsec VPN connectivity 2994 * 2995 * <p>The IKEv2 VPN will listen to, and run based on the lifecycle of Android's default Network. 2996 * As a new default is selected, old IKE sessions will be torn down, and a new one will be 2997 * started. 2998 * 2999 * <p>This class uses locking minimally - the Vpn instance lock is only ever held when fields of 3000 * the outer class are modified. As such, care must be taken to ensure that no calls are added 3001 * that might modify the outer class' state without acquiring a lock. 3002 * 3003 * <p>The overall structure of the Ikev2VpnRunner is as follows: 3004 * 3005 * <ol> 3006 * <li>Upon startup, a NetworkRequest is registered with ConnectivityManager. This is called 3007 * any time a new default network is selected 3008 * <li>When a new default is connected, an IKE session is started on that Network. If there 3009 * were any existing IKE sessions on other Networks, they are torn down before starting 3010 * the new IKE session 3011 * <li>Upon establishment, the onChildTransformCreated() callback is called twice, one for 3012 * each direction, and finally onChildOpened() is called 3013 * <li>Upon the onChildOpened() call, the VPN is fully set up. 3014 * <li>Subsequent Network changes result in new onDefaultNetworkChanged() callbacks. See (2). 3015 * </ol> 3016 */ 3017 class IkeV2VpnRunner extends VpnRunner implements IkeV2VpnRunnerCallback { 3018 @NonNull private static final String TAG = "IkeV2VpnRunner"; 3019 3020 // 5 seconds grace period before tearing down the IKE Session in case new default network 3021 // will come up 3022 private static final long NETWORK_LOST_TIMEOUT_MS = 5000L; 3023 3024 @NonNull private final IpSecManager mIpSecManager; 3025 @NonNull private final Ikev2VpnProfile mProfile; 3026 @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback; 3027 3028 /** 3029 * Executor upon which ALL callbacks must be run. 3030 * 3031 * <p>This executor MUST be a single threaded executor, in order to ensure the consistency 3032 * of the mutable Ikev2VpnRunner fields. The Ikev2VpnRunner is built mostly lock-free by 3033 * virtue of everything being serialized on this executor. 3034 */ 3035 @NonNull private final ScheduledThreadPoolExecutor mExecutor; 3036 3037 @Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostFuture; 3038 @Nullable private ScheduledFuture<?> mScheduledHandleRetryIkeSessionFuture; 3039 @Nullable private ScheduledFuture<?> mScheduledHandleDataStallFuture; 3040 /** Signal to ensure shutdown is honored even if a new Network is connected. */ 3041 private boolean mIsRunning = true; 3042 3043 /** 3044 * The token that identifies the most recently created IKE session. 3045 * 3046 * <p>This token is monotonically increasing and will never be reset in the lifetime of this 3047 * Ikev2VpnRunner, but it does get reset across runs. It also MUST be accessed on the 3048 * executor thread and updated when a new IKE session is created. 3049 */ 3050 private int mCurrentToken = STARTING_TOKEN; 3051 3052 @Nullable private IpSecTunnelInterface mTunnelIface; 3053 @Nullable private Network mActiveNetwork; 3054 @Nullable private NetworkCapabilities mUnderlyingNetworkCapabilities; 3055 @Nullable private LinkProperties mUnderlyingLinkProperties; 3056 private final String mSessionKey; 3057 3058 @Nullable private IkeSessionWrapper mSession; 3059 @Nullable private IkeSessionConnectionInfo mIkeConnectionInfo; 3060 3061 // mMobikeEnabled can only be updated after IKE AUTH is finished. 3062 private boolean mMobikeEnabled = false; 3063 3064 /** 3065 * The number of attempts to reset the IKE session since the last successful connection. 3066 * 3067 * <p>This variable controls the retry delay, and is reset when the VPN pass network 3068 * validation. 3069 */ 3070 private int mValidationFailRetryCount = 0; 3071 3072 /** 3073 * The number of attempts since the last successful connection. 3074 * 3075 * <p>This variable controls the retry delay, and is reset when a new IKE session is 3076 * opened or when there is a new default network. 3077 */ 3078 private int mRetryCount = 0; 3079 3080 private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener = 3081 new CarrierConfigManager.CarrierConfigChangeListener() { 3082 @Override 3083 public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId, 3084 int specificCarrierId) { 3085 mEventChanges.log("[CarrierConfig] Changed on slot " + slotIndex + " subId=" 3086 + subId + " carrerId=" + carrierId 3087 + " specificCarrierId=" + specificCarrierId); 3088 synchronized (Vpn.this) { 3089 mCachedCarrierConfigInfoPerSubId.remove(subId); 3090 3091 // Ignore stale runner. 3092 if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return; 3093 3094 maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); 3095 } 3096 } 3097 }; 3098 3099 // GuardedBy("Vpn.this") (annotation can't be applied to constructor) IkeV2VpnRunner( @onNull Ikev2VpnProfile profile, @NonNull ScheduledThreadPoolExecutor executor)3100 IkeV2VpnRunner( 3101 @NonNull Ikev2VpnProfile profile, @NonNull ScheduledThreadPoolExecutor executor) { 3102 super(TAG); 3103 mProfile = profile; 3104 mExecutor = executor; 3105 mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); 3106 mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this, mExecutor); 3107 mSessionKey = UUID.randomUUID().toString(); 3108 // Add log for debugging flaky test. b/242833779 3109 Log.d(TAG, "Generate session key = " + mSessionKey); 3110 3111 // Set the policy so that cancelled tasks will be removed from the work queue 3112 mExecutor.setRemoveOnCancelPolicy(true); 3113 3114 // Set the policy so that all delayed tasks will not be executed 3115 mExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); 3116 3117 // To avoid hitting RejectedExecutionException upon shutdown of the mExecutor */ 3118 mExecutor.setRejectedExecutionHandler( 3119 (r, exe) -> { 3120 Log.d(TAG, "Runnable " + r + " rejected by the mExecutor"); 3121 }); 3122 setVpnNetworkPreference(mSessionKey, 3123 createUserAndRestrictedProfilesRanges(mUserId, 3124 mConfig.allowedApplications, mConfig.disallowedApplications)); 3125 3126 mCarrierConfigManager.registerCarrierConfigChangeListener(mExecutor, 3127 mCarrierConfigChangeListener); 3128 } 3129 3130 @Override run()3131 public void run() { 3132 // Unless the profile is restricted to test networks, explicitly use only the network 3133 // that ConnectivityService thinks is the "best." In other words, only ever use the 3134 // currently selected default network. This does mean that in both onLost() and 3135 // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs. 3136 // 3137 // When restricted to test networks, select any network with TRANSPORT_TEST. Since the 3138 // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, 3139 // this is considered safe. 3140 3141 if (mProfile.isRestrictedToTestNetworks()) { 3142 final NetworkRequest req = new NetworkRequest.Builder() 3143 .clearCapabilities() 3144 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 3145 .addCapability(NET_CAPABILITY_NOT_VPN) 3146 .build(); 3147 mConnectivityManager.requestNetwork(req, mNetworkCallback); 3148 } else { 3149 mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback, 3150 new Handler(mLooper)); 3151 } 3152 } 3153 isActiveNetwork(@ullable Network network)3154 private boolean isActiveNetwork(@Nullable Network network) { 3155 return Objects.equals(mActiveNetwork, network) && mIsRunning; 3156 } 3157 isActiveToken(int token)3158 private boolean isActiveToken(int token) { 3159 return (mCurrentToken == token) && mIsRunning; 3160 } 3161 3162 /** 3163 * Called when an IKE session has been opened 3164 * 3165 * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor 3166 * thread in order to ensure consistency of the Ikev2VpnRunner fields. 3167 */ onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration)3168 public void onIkeOpened(int token, @NonNull IkeSessionConfiguration ikeConfiguration) { 3169 if (!isActiveToken(token)) { 3170 mEventChanges.log("[IKEEvent-" + mSessionKey + "] onIkeOpened obsolete token=" 3171 + token); 3172 Log.d(TAG, "onIkeOpened called for obsolete token " + token); 3173 return; 3174 } 3175 3176 mMobikeEnabled = 3177 ikeConfiguration.isIkeExtensionEnabled( 3178 IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE); 3179 final IkeSessionConnectionInfo info = ikeConfiguration.getIkeSessionConnectionInfo(); 3180 mEventChanges.log("[IKEEvent-" + mSessionKey + "] onIkeOpened token=" + token 3181 + ", localAddr=" + info.getLocalAddress() 3182 + ", network=" + info.getNetwork() 3183 + ", mobikeEnabled= " + mMobikeEnabled); 3184 onIkeConnectionInfoChanged(token, info); 3185 } 3186 3187 /** 3188 * Called when an IKE session's {@link IkeSessionConnectionInfo} is available or updated 3189 * 3190 * <p>This callback is usually fired when an IKE session has been opened or migrated. 3191 * 3192 * <p>This method is called multiple times over the lifetime of an IkeSession, and MUST run 3193 * on the mExecutor thread in order to ensure consistency of the Ikev2VpnRunner fields. 3194 */ onIkeConnectionInfoChanged( int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo)3195 public void onIkeConnectionInfoChanged( 3196 int token, @NonNull IkeSessionConnectionInfo ikeConnectionInfo) { 3197 3198 if (!isActiveToken(token)) { 3199 mEventChanges.log("[IKEEvent-" + mSessionKey 3200 + "] onIkeConnectionInfoChanged obsolete token=" + token); 3201 Log.d(TAG, "onIkeConnectionInfoChanged called for obsolete token " + token); 3202 return; 3203 } 3204 mEventChanges.log("[IKEEvent-" + mSessionKey 3205 + "] onIkeConnectionInfoChanged token=" + token 3206 + ", localAddr=" + ikeConnectionInfo.getLocalAddress() 3207 + ", network=" + ikeConnectionInfo.getNetwork()); 3208 // The update on VPN and the IPsec tunnel will be done when migration is fully complete 3209 // in onChildMigrated 3210 mIkeConnectionInfo = ikeConnectionInfo; 3211 } 3212 3213 /** 3214 * Called when an IKE Child session has been opened, signalling completion of the startup. 3215 * 3216 * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor 3217 * thread in order to ensure consistency of the Ikev2VpnRunner fields. 3218 */ onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig)3219 public void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig) { 3220 if (!isActiveToken(token)) { 3221 mEventChanges.log("[IKEEvent-" + mSessionKey 3222 + "] onChildOpened obsolete token=" + token); 3223 Log.d(TAG, "onChildOpened called for obsolete token " + token); 3224 3225 // Do nothing; this signals that either: (1) a new/better Network was found, 3226 // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in 3227 // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, 3228 // or an error was encountered somewhere else). In both cases, all resources and 3229 // sessions are torn down via resetIkeState(). 3230 return; 3231 } 3232 mEventChanges.log("[IKEEvent-" + mSessionKey + "] onChildOpened token=" + token 3233 + ", addr=" + TextUtils.join(", ", childConfig.getInternalAddresses()) 3234 + " dns=" + TextUtils.join(", ", childConfig.getInternalDnsServers())); 3235 try { 3236 final String interfaceName = mTunnelIface.getInterfaceName(); 3237 final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses(); 3238 final List<String> dnsAddrStrings = new ArrayList<>(); 3239 int vpnMtu; 3240 vpnMtu = calculateVpnMtu(); 3241 3242 // If the VPN is IPv6 only and its MTU is lower than 1280, mark the network as lost 3243 // and send the VpnManager event to the VPN app. 3244 if (isIPv6Only(internalAddresses) && vpnMtu < IPV6_MIN_MTU) { 3245 onSessionLost( 3246 token, 3247 new IkeIOException( 3248 new IOException("No valid addresses for MTU < 1280"))); 3249 return; 3250 } 3251 3252 final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors( 3253 childConfig.getOutboundTrafficSelectors()); 3254 for (final LinkAddress address : internalAddresses) { 3255 mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength()); 3256 } 3257 3258 for (InetAddress addr : childConfig.getInternalDnsServers()) { 3259 dnsAddrStrings.add(addr.getHostAddress()); 3260 } 3261 3262 // The actual network of this IKE session has been set up with is 3263 // mIkeConnectionInfo.getNetwork() instead of mActiveNetwork because 3264 // mActiveNetwork might have been updated after the setup was triggered. 3265 final Network network = mIkeConnectionInfo.getNetwork(); 3266 3267 final NetworkAgent networkAgent; 3268 final LinkProperties lp; 3269 3270 synchronized (Vpn.this) { 3271 // Ignore stale runner. 3272 if (mVpnRunner != this) return; 3273 3274 mInterface = interfaceName; 3275 mConfig.mtu = vpnMtu; 3276 mConfig.interfaze = mInterface; 3277 3278 mConfig.addresses.clear(); 3279 mConfig.addresses.addAll(internalAddresses); 3280 3281 mConfig.routes.clear(); 3282 mConfig.routes.addAll(newRoutes); 3283 3284 if (mConfig.dnsServers == null) mConfig.dnsServers = new ArrayList<>(); 3285 mConfig.dnsServers.clear(); 3286 mConfig.dnsServers.addAll(dnsAddrStrings); 3287 3288 mConfig.underlyingNetworks = new Network[] {network}; 3289 3290 networkAgent = mNetworkAgent; 3291 3292 // The below must be done atomically with the mConfig update, otherwise 3293 // isRunningLocked() will be racy. 3294 if (networkAgent == null) { 3295 if (isSettingsVpnLocked()) { 3296 prepareStatusIntent(); 3297 } 3298 agentConnect(this::onValidationStatus); 3299 return; // Link properties are already sent. 3300 } else { 3301 // Underlying networks also set in agentConnect() 3302 doSetUnderlyingNetworks(networkAgent, Collections.singletonList(network)); 3303 mNetworkCapabilities = 3304 new NetworkCapabilities.Builder(mNetworkCapabilities) 3305 .setUnderlyingNetworks(Collections.singletonList(network)) 3306 .build(); 3307 } 3308 3309 lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked 3310 } 3311 3312 doSendLinkProperties(networkAgent, lp); 3313 mRetryCount = 0; 3314 } catch (Exception e) { 3315 Log.d(TAG, "Error in ChildOpened for token " + token, e); 3316 onSessionLost(token, e); 3317 } 3318 } 3319 3320 /** 3321 * Called when an IPsec transform has been created, and should be applied. 3322 * 3323 * <p>This method is called multiple times over the lifetime of an IkeSession (or default 3324 * network), and MUST always be called on the mExecutor thread in order to ensure 3325 * consistency of the Ikev2VpnRunner fields. 3326 */ onChildTransformCreated( int token, @NonNull IpSecTransform transform, int direction)3327 public void onChildTransformCreated( 3328 int token, @NonNull IpSecTransform transform, int direction) { 3329 if (!isActiveToken(token)) { 3330 mEventChanges.log("[IKEEvent-" + mSessionKey 3331 + "] onChildTransformCreated obsolete token=" + token); 3332 Log.d(TAG, "ChildTransformCreated for obsolete token " + token); 3333 3334 // Do nothing; this signals that either: (1) a new/better Network was found, 3335 // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in 3336 // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, 3337 // or an error was encountered somewhere else). In both cases, all resources and 3338 // sessions are torn down via resetIkeState(). 3339 return; 3340 } 3341 mEventChanges.log("[IKEEvent-" + mSessionKey 3342 + "] onChildTransformCreated token=" + token + ", direction=" + direction 3343 + ", transform=" + transform); 3344 try { 3345 mTunnelIface.setUnderlyingNetwork(mIkeConnectionInfo.getNetwork()); 3346 3347 // Transforms do not need to be persisted; the IkeSession will keep 3348 // them alive for us 3349 mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform); 3350 } catch (IOException e) { 3351 Log.d(TAG, "Transform application failed for token " + token, e); 3352 onSessionLost(token, e); 3353 } 3354 } 3355 3356 /** 3357 * Called when an IPsec transform has been created, and should be re-applied. 3358 * 3359 * <p>This method is called multiple times over the lifetime of an IkeSession (or default 3360 * network), and MUST always be called on the mExecutor thread in order to ensure 3361 * consistency of the Ikev2VpnRunner fields. 3362 */ onChildMigrated( int token, @NonNull IpSecTransform inTransform, @NonNull IpSecTransform outTransform)3363 public void onChildMigrated( 3364 int token, 3365 @NonNull IpSecTransform inTransform, 3366 @NonNull IpSecTransform outTransform) { 3367 if (!isActiveToken(token)) { 3368 mEventChanges.log("[IKEEvent-" + mSessionKey 3369 + "] onChildMigrated obsolete token=" + token); 3370 Log.d(TAG, "onChildMigrated for obsolete token " + token); 3371 return; 3372 } 3373 mEventChanges.log("[IKEEvent-" + mSessionKey 3374 + "] onChildMigrated token=" + token 3375 + ", in=" + inTransform + ", out=" + outTransform); 3376 // The actual network of this IKE session has migrated to is 3377 // mIkeConnectionInfo.getNetwork() instead of mActiveNetwork because mActiveNetwork 3378 // might have been updated after the migration was triggered. 3379 final Network network = mIkeConnectionInfo.getNetwork(); 3380 3381 try { 3382 synchronized (Vpn.this) { 3383 // Ignore stale runner. 3384 if (mVpnRunner != this) return; 3385 3386 final LinkProperties oldLp = makeLinkProperties(); 3387 3388 final boolean underlyingNetworkHasChanged = 3389 !Arrays.equals(mConfig.underlyingNetworks, new Network[]{network}); 3390 mConfig.underlyingNetworks = new Network[] {network}; 3391 mConfig.mtu = calculateVpnMtu(); 3392 3393 final LinkProperties newLp = makeLinkProperties(); 3394 3395 // If MTU is < 1280, IPv6 addresses will be removed. If there are no addresses 3396 // left (e.g. IPv6-only VPN network), mark VPN as having lost the session. 3397 if (newLp.getLinkAddresses().isEmpty()) { 3398 onSessionLost( 3399 token, 3400 new IkeIOException( 3401 new IOException("No valid addresses for MTU < 1280"))); 3402 return; 3403 } 3404 3405 final Set<LinkAddress> removedAddrs = new HashSet<>(oldLp.getLinkAddresses()); 3406 removedAddrs.removeAll(newLp.getLinkAddresses()); 3407 3408 // If addresses were removed despite no IKE config change, IPv6 addresses must 3409 // have been removed due to MTU size. Restart the VPN to ensure all IPv6 3410 // unconnected sockets on the new VPN network are closed and retried on the new 3411 // VPN network. 3412 if (!removedAddrs.isEmpty()) { 3413 startNewNetworkAgent( 3414 mNetworkAgent, "MTU too low for IPv6; restarting network agent"); 3415 3416 for (LinkAddress removed : removedAddrs) { 3417 mTunnelIface.removeAddress( 3418 removed.getAddress(), removed.getPrefixLength()); 3419 } 3420 } else { 3421 // Put below 3 updates into else block is because agentConnect() will do 3422 // those things, so there is no need to do the redundant work. 3423 if (!newLp.equals(oldLp)) doSendLinkProperties(mNetworkAgent, newLp); 3424 if (underlyingNetworkHasChanged) { 3425 mNetworkCapabilities = 3426 new NetworkCapabilities.Builder(mNetworkCapabilities) 3427 .setUnderlyingNetworks( 3428 Collections.singletonList(network)) 3429 .build(); 3430 doSetUnderlyingNetworks(mNetworkAgent, 3431 Collections.singletonList(network)); 3432 } 3433 } 3434 } 3435 3436 mTunnelIface.setUnderlyingNetwork(network); 3437 3438 // Transforms do not need to be persisted; the IkeSession will keep them alive for 3439 // us 3440 mIpSecManager.applyTunnelModeTransform( 3441 mTunnelIface, IpSecManager.DIRECTION_IN, inTransform); 3442 mIpSecManager.applyTunnelModeTransform( 3443 mTunnelIface, IpSecManager.DIRECTION_OUT, outTransform); 3444 } catch (IOException e) { 3445 Log.d(TAG, "Transform application failed for token " + token, e); 3446 onSessionLost(token, e); 3447 } 3448 } 3449 3450 /** 3451 * Called when a new default network is connected. 3452 * 3453 * <p>The Ikev2VpnRunner will unconditionally switch to the new network. If the IKE session 3454 * has mobility, Ikev2VpnRunner will migrate the existing IkeSession to the new network. 3455 * Otherwise, Ikev2VpnRunner will kill the old IKE state, and start a new IkeSession 3456 * instance. 3457 * 3458 * <p>This method MUST always be called on the mExecutor thread in order to ensure 3459 * consistency of the Ikev2VpnRunner fields. 3460 */ onDefaultNetworkChanged(@onNull Network network)3461 public void onDefaultNetworkChanged(@NonNull Network network) { 3462 mEventChanges.log("[UnderlyingNW] Default network changed to " + network); 3463 Log.d(TAG, "onDefaultNetworkChanged: " + network); 3464 3465 // If there is a new default network brought up, cancel the retry task to prevent 3466 // establishing an unnecessary IKE session. 3467 cancelRetryNewIkeSessionFuture(); 3468 3469 // If there is a new default network brought up, cancel the obsolete reset and retry 3470 // task. 3471 cancelHandleNetworkLostTimeout(); 3472 3473 if (!mIsRunning) { 3474 Log.d(TAG, "onDefaultNetworkChanged after exit"); 3475 return; // VPN has been shut down. 3476 } 3477 3478 mActiveNetwork = network; 3479 mUnderlyingLinkProperties = null; 3480 mUnderlyingNetworkCapabilities = null; 3481 mRetryCount = 0; 3482 } 3483 3484 @NonNull getIkeSessionParams(@onNull Network underlyingNetwork)3485 private IkeSessionParams getIkeSessionParams(@NonNull Network underlyingNetwork) { 3486 final IkeTunnelConnectionParams ikeTunConnParams = 3487 mProfile.getIkeTunnelConnectionParams(); 3488 final IkeSessionParams.Builder builder; 3489 if (ikeTunConnParams != null) { 3490 builder = new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams()) 3491 .setNetwork(underlyingNetwork); 3492 } else { 3493 builder = VpnIkev2Utils.makeIkeSessionParamsBuilder(mContext, mProfile, 3494 underlyingNetwork); 3495 } 3496 if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) { 3497 builder.setNattKeepAliveDelaySeconds(guessNattKeepaliveTimerForNetwork()); 3498 } 3499 if (mProfile.isAutomaticIpVersionSelectionEnabled()) { 3500 builder.setIpVersion(guessEspIpVersionForNetwork()); 3501 builder.setEncapType(guessEspEncapTypeForNetwork()); 3502 } 3503 return builder.build(); 3504 } 3505 3506 @NonNull getChildSessionParams()3507 private ChildSessionParams getChildSessionParams() { 3508 final IkeTunnelConnectionParams ikeTunConnParams = 3509 mProfile.getIkeTunnelConnectionParams(); 3510 if (ikeTunConnParams != null) { 3511 return ikeTunConnParams.getTunnelModeChildSessionParams(); 3512 } else { 3513 return VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms()); 3514 } 3515 } 3516 calculateVpnMtu()3517 private int calculateVpnMtu() { 3518 final Network underlyingNetwork = mIkeConnectionInfo.getNetwork(); 3519 final LinkProperties lp = mConnectivityManager.getLinkProperties(underlyingNetwork); 3520 if (underlyingNetwork == null || lp == null) { 3521 // Return the max MTU defined in VpnProfile as the fallback option when there is no 3522 // underlying network or LinkProperties is null. 3523 return mProfile.getMaxMtu(); 3524 } 3525 3526 int underlyingMtu = lp.getMtu(); 3527 3528 // Try to get MTU from kernel if MTU is not set in LinkProperties. 3529 if (underlyingMtu == 0) { 3530 try { 3531 underlyingMtu = mDeps.getJavaNetworkInterfaceMtu(lp.getInterfaceName(), 3532 mProfile.getMaxMtu()); 3533 } catch (SocketException e) { 3534 Log.d(TAG, "Got a SocketException when getting MTU from kernel: " + e); 3535 return mProfile.getMaxMtu(); 3536 } 3537 } 3538 3539 return mDeps.calculateVpnMtu( 3540 getChildSessionParams().getSaProposals(), 3541 mProfile.getMaxMtu(), 3542 underlyingMtu, 3543 mIkeConnectionInfo.getLocalAddress() instanceof Inet4Address); 3544 } 3545 3546 /** 3547 * Start a new IKE session. 3548 * 3549 * <p>This method MUST always be called on the mExecutor thread in order to ensure 3550 * consistency of the Ikev2VpnRunner fields. 3551 * 3552 * @param underlyingNetwork if the value is {@code null}, which means there is no active 3553 * network can be used, do nothing and return immediately. Otherwise, use the 3554 * given network to start a new IKE session. 3555 */ startOrMigrateIkeSession(@ullable Network underlyingNetwork)3556 private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) { 3557 if (underlyingNetwork == null) { 3558 Log.d(TAG, "There is no active network for starting an IKE session"); 3559 return; 3560 } 3561 3562 if (maybeMigrateIkeSessionAndUpdateVpnTransportInfo(underlyingNetwork)) return; 3563 3564 startIkeSession(underlyingNetwork); 3565 } 3566 guessEspIpVersionForNetwork()3567 private int guessEspIpVersionForNetwork() { 3568 if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) { 3569 Log.d(TAG, "Running over VCN, esp IP version is auto"); 3570 return ESP_IP_VERSION_AUTO; 3571 } 3572 final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); 3573 final int ipVersion = (carrierconfig != null) 3574 ? carrierconfig.ipVersion : ESP_IP_VERSION_AUTO; 3575 if (carrierconfig != null) { 3576 Log.d(TAG, "Get customized IP version (" + ipVersion + ") on SIM (mccmnc=" 3577 + carrierconfig.mccMnc + ")"); 3578 } 3579 return ipVersion; 3580 } 3581 guessEspEncapTypeForNetwork()3582 private int guessEspEncapTypeForNetwork() { 3583 if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) { 3584 Log.d(TAG, "Running over VCN, encap type is auto"); 3585 return ESP_ENCAP_TYPE_AUTO; 3586 } 3587 final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); 3588 final int encapType = (carrierconfig != null) 3589 ? carrierconfig.encapType : ESP_ENCAP_TYPE_AUTO; 3590 if (carrierconfig != null) { 3591 Log.d(TAG, "Get customized encap type (" + encapType + ") on SIM (mccmnc=" 3592 + carrierconfig.mccMnc + ")"); 3593 } 3594 return encapType; 3595 } 3596 3597 guessNattKeepaliveTimerForNetwork()3598 private int guessNattKeepaliveTimerForNetwork() { 3599 final TransportInfo transportInfo = mUnderlyingNetworkCapabilities.getTransportInfo(); 3600 if (transportInfo instanceof VcnTransportInfo) { 3601 final int nattKeepaliveSec = 3602 ((VcnTransportInfo) transportInfo).getMinUdpPort4500NatTimeoutSeconds(); 3603 Log.d(TAG, "Running over VCN, keepalive timer : " + nattKeepaliveSec + "s"); 3604 if (VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET 3605 != nattKeepaliveSec) { 3606 return nattKeepaliveSec; 3607 } 3608 // else fall back to carrier config, if any 3609 } 3610 final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork(); 3611 final int nattKeepaliveSec = (carrierconfig != null) 3612 ? carrierconfig.keepaliveDelaySec : AUTOMATIC_KEEPALIVE_DELAY_SECONDS; 3613 if (carrierconfig != null) { 3614 Log.d(TAG, "Get customized keepalive (" + nattKeepaliveSec + "s) on SIM (mccmnc=" 3615 + carrierconfig.mccMnc + ")"); 3616 } 3617 return nattKeepaliveSec; 3618 } 3619 3620 /** 3621 * Returns the carrier config for the underlying network, or null if not a cell network. 3622 */ 3623 @Nullable getCarrierConfigForUnderlyingNetwork()3624 private CarrierConfigInfo getCarrierConfigForUnderlyingNetwork() { 3625 final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities); 3626 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 3627 Log.d(TAG, "Underlying network is not a cellular network"); 3628 return null; 3629 } 3630 3631 synchronized (Vpn.this) { 3632 if (mCachedCarrierConfigInfoPerSubId.contains(subId)) { 3633 Log.d(TAG, "Get cached config"); 3634 return mCachedCarrierConfigInfoPerSubId.get(subId); 3635 } 3636 } 3637 3638 final TelephonyManager perSubTm = mTelephonyManager.createForSubscriptionId(subId); 3639 if (perSubTm.getSimApplicationState() != TelephonyManager.SIM_STATE_LOADED) { 3640 Log.d(TAG, "SIM card is not ready on sub " + subId); 3641 return null; 3642 } 3643 3644 final PersistableBundle carrierConfig = 3645 mCarrierConfigManager.getConfigForSubId(subId); 3646 if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { 3647 return null; 3648 } 3649 3650 final int natKeepalive = 3651 carrierConfig.getInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT); 3652 final int preferredIpProtocol = carrierConfig.getInt( 3653 KEY_PREFERRED_IKE_PROTOCOL_INT, PREFERRED_IKE_PROTOCOL_UNKNOWN); 3654 final String mccMnc = perSubTm.getSimOperator(subId); 3655 final CarrierConfigInfo info = 3656 buildCarrierConfigInfo(mccMnc, natKeepalive, preferredIpProtocol); 3657 synchronized (Vpn.this) { 3658 mCachedCarrierConfigInfoPerSubId.put(subId, info); 3659 } 3660 3661 return info; 3662 } 3663 buildCarrierConfigInfo(String mccMnc, int natKeepalive, int preferredIpPortocol)3664 private CarrierConfigInfo buildCarrierConfigInfo(String mccMnc, 3665 int natKeepalive, int preferredIpPortocol) { 3666 final int ipVersion; 3667 final int encapType; 3668 switch (preferredIpPortocol) { 3669 case PREFERRED_IKE_PROTOCOL_AUTO: 3670 ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO; 3671 encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO; 3672 break; 3673 case PREFERRED_IKE_PROTOCOL_IPV4_UDP: 3674 ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4; 3675 encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; 3676 break; 3677 case PREFERRED_IKE_PROTOCOL_IPV6_UDP: 3678 ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV6; 3679 encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; 3680 break; 3681 case PREFERRED_IKE_PROTOCOL_IPV6_ESP: 3682 ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV6; 3683 encapType = IkeSessionParams.ESP_ENCAP_TYPE_NONE; 3684 break; 3685 default: 3686 // By default, PREFERRED_IKE_PROTOCOL_IPV4_UDP is used for safety. This is 3687 // because some carriers' networks do not support IPv6 very well, and using 3688 // IPv4 can help to prevent problems. 3689 ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4; 3690 encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; 3691 break; 3692 } 3693 return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion); 3694 } 3695 getOrGuessKeepaliveDelaySeconds()3696 private int getOrGuessKeepaliveDelaySeconds() { 3697 if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) { 3698 return guessNattKeepaliveTimerForNetwork(); 3699 } else if (mProfile.getIkeTunnelConnectionParams() != null) { 3700 return mProfile.getIkeTunnelConnectionParams() 3701 .getIkeSessionParams().getNattKeepAliveDelaySeconds(); 3702 } 3703 return DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; 3704 } 3705 maybeMigrateIkeSessionAndUpdateVpnTransportInfo( @onNull Network underlyingNetwork)3706 boolean maybeMigrateIkeSessionAndUpdateVpnTransportInfo( 3707 @NonNull Network underlyingNetwork) { 3708 final int keepaliveDelaySec = getOrGuessKeepaliveDelaySeconds(); 3709 final boolean migrated = maybeMigrateIkeSession(underlyingNetwork, keepaliveDelaySec); 3710 if (migrated) { 3711 updateVpnTransportInfoAndNetCap(keepaliveDelaySec); 3712 } 3713 return migrated; 3714 } 3715 updateVpnTransportInfoAndNetCap(int keepaliveDelaySec)3716 public void updateVpnTransportInfoAndNetCap(int keepaliveDelaySec) { 3717 final VpnTransportInfo info; 3718 synchronized (Vpn.this) { 3719 info = new VpnTransportInfo( 3720 getActiveVpnType(), 3721 mConfig.session, 3722 mConfig.allowBypass && !mLockdown, 3723 areLongLivedTcpConnectionsExpensive(keepaliveDelaySec)); 3724 } 3725 final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo()); 3726 if (ncUpdateRequired) { 3727 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) 3728 .setTransportInfo(info) 3729 .build(); 3730 mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities); 3731 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); 3732 } 3733 } 3734 maybeMigrateIkeSession(@onNull Network underlyingNetwork, int keepaliveDelaySeconds)3735 private boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork, 3736 int keepaliveDelaySeconds) { 3737 if (mSession == null || !mMobikeEnabled) return false; 3738 3739 // IKE session can schedule a migration event only when IKE AUTH is finished 3740 // and mMobikeEnabled is true. 3741 Log.d(TAG, "Migrate IKE Session with token " 3742 + mCurrentToken 3743 + " to network " 3744 + underlyingNetwork); 3745 3746 final int ipVersion; 3747 final int encapType; 3748 if (mProfile.isAutomaticIpVersionSelectionEnabled()) { 3749 ipVersion = guessEspIpVersionForNetwork(); 3750 encapType = guessEspEncapTypeForNetwork(); 3751 } else if (mProfile.getIkeTunnelConnectionParams() != null) { 3752 ipVersion = mProfile.getIkeTunnelConnectionParams() 3753 .getIkeSessionParams().getIpVersion(); 3754 encapType = mProfile.getIkeTunnelConnectionParams() 3755 .getIkeSessionParams().getEncapType(); 3756 } else { 3757 ipVersion = ESP_IP_VERSION_AUTO; 3758 encapType = ESP_ENCAP_TYPE_AUTO; 3759 } 3760 3761 mSession.setNetwork(underlyingNetwork, ipVersion, encapType, keepaliveDelaySeconds); 3762 return true; 3763 } 3764 startIkeSession(@onNull Network underlyingNetwork)3765 private void startIkeSession(@NonNull Network underlyingNetwork) { 3766 Log.d(TAG, "Start new IKE session on network " + underlyingNetwork); 3767 mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork); 3768 3769 try { 3770 // Clear mInterface to prevent Ikev2VpnRunner being cleared when 3771 // interfaceRemoved() is called. 3772 synchronized (Vpn.this) { 3773 // Ignore stale runner. 3774 if (mVpnRunner != this) return; 3775 3776 mInterface = null; 3777 } 3778 // Without MOBIKE, we have no way to seamlessly migrate. Close on old 3779 // (non-default) network, and start the new one. 3780 resetIkeState(); 3781 3782 // TODO: Remove the need for adding two unused addresses with 3783 // IPsec tunnels. 3784 final InetAddress address = InetAddress.getLocalHost(); 3785 3786 // When onChildOpened is called and transforms are applied, it is 3787 // guaranteed that the underlying network is still "network", because the 3788 // all the network switch events will be deferred before onChildOpened is 3789 // called. Thus it is safe to build a mTunnelIface before IKE setup. 3790 mTunnelIface = 3791 mIpSecManager.createIpSecTunnelInterface( 3792 address /* unused */, address /* unused */, underlyingNetwork); 3793 NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName()); 3794 3795 final int token = ++mCurrentToken; 3796 mSession = 3797 mIkev2SessionCreator.createIkeSession( 3798 mContext, 3799 getIkeSessionParams(underlyingNetwork), 3800 getChildSessionParams(), 3801 mExecutor, 3802 new VpnIkev2Utils.IkeSessionCallbackImpl( 3803 TAG, IkeV2VpnRunner.this, token), 3804 new VpnIkev2Utils.ChildSessionCallbackImpl( 3805 TAG, IkeV2VpnRunner.this, token)); 3806 Log.d(TAG, "IKE session started for token " + token); 3807 } catch (Exception e) { 3808 Log.i(TAG, "Setup failed for token " + mCurrentToken + ". Aborting", e); 3809 onSessionLost(mCurrentToken, e); 3810 } 3811 } 3812 3813 /** 3814 * Schedule starting an IKE session. 3815 * @param delayMs the delay after which to try starting the session. This should be 3816 * RETRY_DELAY_AUTO_BACKOFF for automatic retries with backoff. 3817 */ scheduleStartIkeSession(final long delayMs)3818 private void scheduleStartIkeSession(final long delayMs) { 3819 if (mScheduledHandleRetryIkeSessionFuture != null) { 3820 Log.d(TAG, "There is a pending retrying task, skip the new retrying task"); 3821 return; 3822 } 3823 final long retryDelayMs = RETRY_DELAY_AUTO_BACKOFF != delayMs 3824 ? delayMs 3825 : mDeps.getNextRetryDelayMs(mRetryCount++); 3826 Log.d(TAG, "Retry new IKE session after " + retryDelayMs + " milliseconds."); 3827 // If the default network is lost during the retry delay, the mActiveNetwork will be 3828 // null, and the new IKE session won't be established until there is a new default 3829 // network bringing up. 3830 mScheduledHandleRetryIkeSessionFuture = 3831 mExecutor.schedule(() -> { 3832 startOrMigrateIkeSession(mActiveNetwork); 3833 3834 // Reset mScheduledHandleRetryIkeSessionFuture since it's already run on 3835 // executor thread. 3836 mScheduledHandleRetryIkeSessionFuture = null; 3837 }, retryDelayMs, TimeUnit.MILLISECONDS); 3838 } 3839 significantCapsChange(@ullable final NetworkCapabilities left, @Nullable final NetworkCapabilities right)3840 private boolean significantCapsChange(@Nullable final NetworkCapabilities left, 3841 @Nullable final NetworkCapabilities right) { 3842 if (left == right) return false; 3843 return null == left 3844 || null == right 3845 || !Arrays.equals(left.getTransportTypes(), right.getTransportTypes()) 3846 || !Arrays.equals(left.getCapabilities(), right.getCapabilities()) 3847 || !Arrays.equals(left.getEnterpriseIds(), right.getEnterpriseIds()) 3848 || !Objects.equals(left.getTransportInfo(), right.getTransportInfo()) 3849 || !Objects.equals(left.getAllowedUids(), right.getAllowedUids()) 3850 || !Objects.equals(left.getUnderlyingNetworks(), right.getUnderlyingNetworks()) 3851 || !Objects.equals(left.getNetworkSpecifier(), right.getNetworkSpecifier()); 3852 } 3853 3854 /** Called when the NetworkCapabilities of underlying network is changed */ onDefaultNetworkCapabilitiesChanged(@onNull NetworkCapabilities nc)3855 public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) { 3856 if (significantCapsChange(mUnderlyingNetworkCapabilities, nc)) { 3857 // TODO : make this log terser 3858 mEventChanges.log("[UnderlyingNW] Cap changed from " 3859 + mUnderlyingNetworkCapabilities + " to " + nc); 3860 } 3861 final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities; 3862 mUnderlyingNetworkCapabilities = nc; 3863 if (oldNc == null || !nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) { 3864 // A new default network is available, or the subscription has changed. 3865 // Try to migrate the session, or failing that, start a new one. 3866 scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); 3867 } 3868 } 3869 3870 /** Called when the LinkProperties of underlying network is changed */ onDefaultNetworkLinkPropertiesChanged(@onNull LinkProperties lp)3871 public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) { 3872 final LinkProperties oldLp = mUnderlyingLinkProperties; 3873 mEventChanges.log("[UnderlyingNW] Lp changed from " + oldLp + " to " + lp); 3874 mUnderlyingLinkProperties = lp; 3875 if (oldLp == null || !LinkPropertiesUtils.isIdenticalAllLinkAddresses(oldLp, lp)) { 3876 // If some of the link addresses changed, the IKE session may need to be migrated 3877 // or restarted, for example if the available IP families have changed or if the 3878 // source address used has gone away. See IkeConnectionController#onNetworkSetByUser 3879 // and IkeConnectionController#selectAndSetRemoteAddress for where this ends up 3880 // re-evaluating the session. 3881 scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS); 3882 } 3883 } 3884 onValidationStatus(int status)3885 public void onValidationStatus(int status) { 3886 mEventChanges.log("[Validation] validation status " + status); 3887 if (status == NetworkAgent.VALIDATION_STATUS_VALID) { 3888 // No data stall now. Reset it. 3889 mExecutor.execute(() -> { 3890 mValidationFailRetryCount = 0; 3891 if (mScheduledHandleDataStallFuture != null) { 3892 Log.d(TAG, "Recovered from stall. Cancel pending reset action."); 3893 mScheduledHandleDataStallFuture.cancel(false /* mayInterruptIfRunning */); 3894 mScheduledHandleDataStallFuture = null; 3895 } 3896 }); 3897 } else { 3898 // Skip other invalid status if the scheduled recovery exists. 3899 if (mScheduledHandleDataStallFuture != null) return; 3900 3901 if (mValidationFailRetryCount < MAX_MOBIKE_RECOVERY_ATTEMPT) { 3902 Log.d(TAG, "Validation failed"); 3903 3904 // Trigger MOBIKE to recover first. 3905 mExecutor.schedule(() -> { 3906 maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork); 3907 }, mDeps.getValidationFailRecoverySeconds(mValidationFailRetryCount++), 3908 TimeUnit.SECONDS); 3909 return; 3910 } 3911 3912 // Data stall is not recovered by MOBIKE. Try to reset session to recover it. 3913 mScheduledHandleDataStallFuture = mExecutor.schedule(() -> { 3914 // Only perform the recovery when the network is still bad. 3915 if (mValidationFailRetryCount > 0) { 3916 Log.d(TAG, "Reset session to recover stalled network"); 3917 // This will reset old state if it exists. 3918 startIkeSession(mActiveNetwork); 3919 } 3920 3921 // Reset mScheduledHandleDataStallFuture since it's already run on executor 3922 // thread. 3923 mScheduledHandleDataStallFuture = null; 3924 // TODO: compute the delay based on the last recovery timestamp 3925 }, mDeps.getValidationFailRecoverySeconds(mValidationFailRetryCount++), 3926 TimeUnit.SECONDS); 3927 } 3928 } 3929 3930 /** 3931 * Handles loss of the default underlying network 3932 * 3933 * <p>If the IKE Session has mobility, Ikev2VpnRunner will schedule a teardown event with a 3934 * delay so that the IKE Session can migrate if a new network is available soon. Otherwise, 3935 * Ikev2VpnRunner will kill the IKE session and reset the VPN. 3936 * 3937 * <p>This method MUST always be called on the mExecutor thread in order to ensure 3938 * consistency of the Ikev2VpnRunner fields. 3939 */ onDefaultNetworkLost(@onNull Network network)3940 public void onDefaultNetworkLost(@NonNull Network network) { 3941 mEventChanges.log("[UnderlyingNW] Network lost " + network); 3942 // If the default network is torn down, there is no need to call 3943 // startOrMigrateIkeSession() since it will always check if there is an active network 3944 // can be used or not. 3945 cancelRetryNewIkeSessionFuture(); 3946 3947 if (!isActiveNetwork(network)) { 3948 Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network); 3949 3950 // Do nothing; this signals that either: (1) a new/better Network was found, 3951 // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in 3952 // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, 3953 // or an error was encountered somewhere else). In both cases, all resources and 3954 // sessions are torn down via resetIkeState(). 3955 return; 3956 } else { 3957 mActiveNetwork = null; 3958 mUnderlyingNetworkCapabilities = null; 3959 mUnderlyingLinkProperties = null; 3960 } 3961 3962 if (mScheduledHandleNetworkLostFuture != null) { 3963 final IllegalStateException exception = 3964 new IllegalStateException( 3965 "Found a pending mScheduledHandleNetworkLostFuture"); 3966 Log.i( 3967 TAG, 3968 "Unexpected error in onDefaultNetworkLost. Tear down session", 3969 exception); 3970 handleSessionLost(exception, network); 3971 return; 3972 } 3973 3974 Log.d(TAG, "Schedule a delay handleSessionLost for losing network " 3975 + network 3976 + " on session with token " 3977 + mCurrentToken); 3978 3979 final int token = mCurrentToken; 3980 // Delay the teardown in case a new network will be available soon. For example, 3981 // during handover between two WiFi networks, Android will disconnect from the 3982 // first WiFi and then connects to the second WiFi. 3983 mScheduledHandleNetworkLostFuture = 3984 mExecutor.schedule( 3985 () -> { 3986 if (isActiveToken(token)) { 3987 handleSessionLost(new IkeNetworkLostException(network), 3988 network); 3989 3990 synchronized (Vpn.this) { 3991 // Ignore stale runner. 3992 if (mVpnRunner != this) return; 3993 3994 updateState(DetailedState.DISCONNECTED, 3995 "Network lost"); 3996 } 3997 } else { 3998 Log.d( 3999 TAG, 4000 "Scheduled handleSessionLost fired for " 4001 + "obsolete token " 4002 + token); 4003 } 4004 4005 // Reset mScheduledHandleNetworkLostFuture since it's 4006 // already run on executor thread. 4007 mScheduledHandleNetworkLostFuture = null; 4008 }, 4009 NETWORK_LOST_TIMEOUT_MS, 4010 TimeUnit.MILLISECONDS); 4011 4012 } 4013 cancelHandleNetworkLostTimeout()4014 private void cancelHandleNetworkLostTimeout() { 4015 if (mScheduledHandleNetworkLostFuture != null) { 4016 // It does not matter what to put in #cancel(boolean), because it is impossible 4017 // that the task tracked by mScheduledHandleNetworkLostFuture is 4018 // in-progress since both that task and onDefaultNetworkChanged are submitted to 4019 // mExecutor who has only one thread. 4020 Log.d(TAG, "Cancel the task for handling network lost timeout"); 4021 mScheduledHandleNetworkLostFuture.cancel(false /* mayInterruptIfRunning */); 4022 mScheduledHandleNetworkLostFuture = null; 4023 } 4024 } 4025 cancelRetryNewIkeSessionFuture()4026 private void cancelRetryNewIkeSessionFuture() { 4027 if (mScheduledHandleRetryIkeSessionFuture != null) { 4028 // It does not matter what to put in #cancel(boolean), because it is impossible 4029 // that the task tracked by mScheduledHandleRetryIkeSessionFuture is 4030 // in-progress since both that task and onDefaultNetworkChanged are submitted to 4031 // mExecutor who has only one thread. 4032 Log.d(TAG, "Cancel the task for handling new ike session timeout"); 4033 mScheduledHandleRetryIkeSessionFuture.cancel(false /* mayInterruptIfRunning */); 4034 mScheduledHandleRetryIkeSessionFuture = null; 4035 } 4036 } 4037 4038 /** Marks the state as FAILED, and disconnects. */ markFailedAndDisconnect(Exception exception)4039 private void markFailedAndDisconnect(Exception exception) { 4040 synchronized (Vpn.this) { 4041 // Ignore stale runner. 4042 if (mVpnRunner != this) return; 4043 4044 updateState(DetailedState.FAILED, exception.getMessage()); 4045 } 4046 4047 disconnectVpnRunner(); 4048 } 4049 4050 /** 4051 * Handles loss of a session 4052 * 4053 * <p>The loss of a session might be due to an onLost() call, the IKE session getting torn 4054 * down for any reason, or an error in updating state (transform application, VPN setup) 4055 * 4056 * <p>This method MUST always be called on the mExecutor thread in order to ensure 4057 * consistency of the Ikev2VpnRunner fields. 4058 */ onSessionLost(int token, @Nullable Exception exception)4059 public void onSessionLost(int token, @Nullable Exception exception) { 4060 mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork 4061 + (null == exception ? "" : " reason " + exception.getMessage())); 4062 Log.d(TAG, "onSessionLost() called for token " + token); 4063 4064 if (!isActiveToken(token)) { 4065 Log.d(TAG, "onSessionLost() called for obsolete token " + token); 4066 4067 // Do nothing; this signals that either: (1) a new/better Network was found, 4068 // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in 4069 // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited, 4070 // or an error was encountered somewhere else). In both cases, all resources and 4071 // sessions are torn down via resetIkeState(). 4072 return; 4073 } 4074 4075 handleSessionLost(exception, mActiveNetwork); 4076 } 4077 handleSessionLost(@ullable Exception exception, @Nullable Network network)4078 private void handleSessionLost(@Nullable Exception exception, @Nullable Network network) { 4079 // Cancel mScheduledHandleNetworkLostFuture if the session it is going to terminate is 4080 // already terminated due to other failures. 4081 cancelHandleNetworkLostTimeout(); 4082 4083 String category = null; 4084 int errorClass = -1; 4085 int errorCode = -1; 4086 if (exception instanceof IllegalArgumentException) { 4087 // Failed to build IKE/ChildSessionParams; fatal profile configuration error 4088 markFailedAndDisconnect(exception); 4089 return; 4090 } 4091 4092 if (exception instanceof IkeProtocolException) { 4093 final IkeProtocolException ikeException = (IkeProtocolException) exception; 4094 category = VpnManager.CATEGORY_EVENT_IKE_ERROR; 4095 errorCode = ikeException.getErrorType(); 4096 4097 switch (ikeException.getErrorType()) { 4098 case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough 4099 case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough 4100 case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough 4101 case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough 4102 case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough 4103 case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE: 4104 // All the above failures are configuration errors, and are terminal 4105 errorClass = VpnManager.ERROR_CLASS_NOT_RECOVERABLE; 4106 break; 4107 // All other cases possibly recoverable. 4108 default: 4109 errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; 4110 } 4111 } else if (exception instanceof IkeNetworkLostException) { 4112 category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR; 4113 errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; 4114 errorCode = VpnManager.ERROR_CODE_NETWORK_LOST; 4115 } else if (exception instanceof IkeNonProtocolException) { 4116 category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR; 4117 errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; 4118 if (exception.getCause() instanceof UnknownHostException) { 4119 errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST; 4120 } else if (exception.getCause() instanceof IkeTimeoutException) { 4121 errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT; 4122 } else if (exception.getCause() instanceof IOException) { 4123 errorCode = VpnManager.ERROR_CODE_NETWORK_IO; 4124 } 4125 } else if (exception != null) { 4126 Log.wtf(TAG, "onSessionLost: exception = " + exception); 4127 } 4128 4129 synchronized (Vpn.this) { 4130 // Ignore stale runner. 4131 if (mVpnRunner != this) return; 4132 4133 // TODO(b/230548427): Remove SDK check once VPN related stuff are 4134 // decoupled from ConnectivityServiceTest. 4135 if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) { 4136 sendEventToVpnManagerApp(category, errorClass, errorCode, 4137 getPackage(), mSessionKey, makeVpnProfileStateLocked(), 4138 mActiveNetwork, 4139 getRedactedNetworkCapabilities(mUnderlyingNetworkCapabilities), 4140 getRedactedLinkProperties(mUnderlyingLinkProperties)); 4141 } 4142 } 4143 4144 if (errorClass == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) { 4145 markFailedAndDisconnect(exception); 4146 return; 4147 } else { 4148 scheduleStartIkeSession(RETRY_DELAY_AUTO_BACKOFF); 4149 } 4150 4151 // Close all obsolete state, but keep VPN alive incase a usable network comes up. 4152 // (Mirrors VpnService behavior) 4153 Log.d(TAG, "Resetting state for token: " + mCurrentToken); 4154 4155 synchronized (Vpn.this) { 4156 // Ignore stale runner. 4157 if (mVpnRunner != this) return; 4158 4159 // Since this method handles non-fatal errors only, set mInterface to null to 4160 // prevent the NetworkManagementEventObserver from killing this VPN based on the 4161 // interface going down (which we expect). 4162 mInterface = null; 4163 if (mConfig != null) { 4164 mConfig.interfaze = null; 4165 4166 // Set as unroutable to prevent traffic leaking while the interface is down. 4167 if (mConfig.routes != null) { 4168 final List<RouteInfo> oldRoutes = new ArrayList<>(mConfig.routes); 4169 4170 mConfig.routes.clear(); 4171 for (final RouteInfo route : oldRoutes) { 4172 mConfig.routes.add(new RouteInfo(route.getDestination(), 4173 null /*gateway*/, null /*iface*/, RTN_UNREACHABLE)); 4174 } 4175 if (mNetworkAgent != null) { 4176 doSendLinkProperties(mNetworkAgent, makeLinkProperties()); 4177 } 4178 } 4179 } 4180 } 4181 4182 resetIkeState(); 4183 } 4184 4185 /** 4186 * Cleans up all IKE state 4187 * 4188 * <p>This method MUST always be called on the mExecutor thread in order to ensure 4189 * consistency of the Ikev2VpnRunner fields. 4190 */ resetIkeState()4191 private void resetIkeState() { 4192 if (mTunnelIface != null) { 4193 // No need to call setInterfaceDown(); the IpSecInterface is being fully torn down. 4194 mTunnelIface.close(); 4195 mTunnelIface = null; 4196 } 4197 if (mSession != null) { 4198 mSession.kill(); // Kill here to make sure all resources are released immediately 4199 mSession = null; 4200 } 4201 mIkeConnectionInfo = null; 4202 mMobikeEnabled = false; 4203 } 4204 4205 /** 4206 * Disconnects and shuts down this VPN. 4207 * 4208 * <p>This method resets all internal Ikev2VpnRunner state, but unless called via 4209 * VpnRunner#exit(), this Ikev2VpnRunner will still be listed as the active VPN of record 4210 * until the next VPN is started, or the Ikev2VpnRunner is explicitly exited. This is 4211 * necessary to ensure that the detailed state is shown in the Settings VPN menus; if the 4212 * active VPN is cleared, Settings VPNs will not show the resultant state or errors. 4213 * 4214 * <p>This method MUST always be called on the mExecutor thread in order to ensure 4215 * consistency of the Ikev2VpnRunner fields. 4216 */ disconnectVpnRunner()4217 private void disconnectVpnRunner() { 4218 mEventChanges.log("[VPNRunner] Disconnect runner, underlying net " + mActiveNetwork); 4219 mActiveNetwork = null; 4220 mUnderlyingNetworkCapabilities = null; 4221 mUnderlyingLinkProperties = null; 4222 mIsRunning = false; 4223 4224 resetIkeState(); 4225 4226 mCarrierConfigManager.unregisterCarrierConfigChangeListener( 4227 mCarrierConfigChangeListener); 4228 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 4229 clearVpnNetworkPreference(mSessionKey); 4230 4231 mExecutor.shutdown(); 4232 } 4233 4234 @Override exitVpnRunner()4235 public void exitVpnRunner() { 4236 try { 4237 mExecutor.execute(() -> { 4238 disconnectVpnRunner(); 4239 }); 4240 } catch (RejectedExecutionException ignored) { 4241 // The Ikev2VpnRunner has already shut down. 4242 } 4243 } 4244 } 4245 4246 /** 4247 * Bringing up a VPN connection takes time, and that is all this thread 4248 * does. Here we have plenty of time. The only thing we need to take 4249 * care of is responding to interruptions as soon as possible. Otherwise 4250 * requests will pile up. This could be done in a Handler as a state 4251 * machine, but it is much easier to read in the current form. 4252 */ 4253 private class LegacyVpnRunner extends VpnRunner { 4254 private static final String TAG = "LegacyVpnRunner"; 4255 4256 private final String[] mDaemons; 4257 private final String[][] mArguments; 4258 private final LocalSocket[] mSockets; 4259 private final String mOuterInterface; 4260 private final AtomicInteger mOuterConnection = 4261 new AtomicInteger(ConnectivityManager.TYPE_NONE); 4262 private final VpnProfile mProfile; 4263 4264 private long mBringupStartTime = -1; 4265 4266 /** 4267 * Watch for the outer connection (passing in the constructor) going away. 4268 */ 4269 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 4270 @Override 4271 public void onReceive(Context context, Intent intent) { 4272 if (!mEnableTeardown) return; 4273 4274 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 4275 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 4276 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 4277 NetworkInfo info = (NetworkInfo)intent.getExtra( 4278 ConnectivityManager.EXTRA_NETWORK_INFO); 4279 if (info != null && !info.isConnectedOrConnecting()) { 4280 try { 4281 mObserver.interfaceStatusChanged(mOuterInterface, false); 4282 } catch (RemoteException e) {} 4283 } 4284 } 4285 } 4286 } 4287 }; 4288 4289 // GuardedBy("Vpn.this") (annotation can't be applied to constructor) LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile)4290 LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { 4291 super(TAG); 4292 if (racoon == null && mtpd == null) { 4293 throw new IllegalArgumentException( 4294 "Arguments to racoon and mtpd must not both be null"); 4295 } 4296 mConfig = config; 4297 mDaemons = new String[] {"racoon", "mtpd"}; 4298 // TODO: clear arguments from memory once launched 4299 mArguments = new String[][] {racoon, mtpd}; 4300 mSockets = new LocalSocket[mDaemons.length]; 4301 4302 // This is the interface which VPN is running on, 4303 // mConfig.interfaze will change to point to OUR 4304 // internal interface soon. TODO - add inner/outer to mconfig 4305 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 4306 // we will leave the VPN up. We should check that it's still there/connected after 4307 // registering 4308 mOuterInterface = mConfig.interfaze; 4309 4310 mProfile = profile; 4311 4312 if (!TextUtils.isEmpty(mOuterInterface)) { 4313 for (Network network : mConnectivityManager.getAllNetworks()) { 4314 final LinkProperties lp = mConnectivityManager.getLinkProperties(network); 4315 if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { 4316 final NetworkInfo netInfo = mConnectivityManager.getNetworkInfo(network); 4317 if (netInfo != null) { 4318 mOuterConnection.set(netInfo.getType()); 4319 break; 4320 } 4321 } 4322 } 4323 } 4324 4325 IntentFilter filter = new IntentFilter(); 4326 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 4327 mContext.registerReceiver(mBroadcastReceiver, filter); 4328 } 4329 4330 /** 4331 * Checks if the parameter matches the underlying interface 4332 * 4333 * <p>If the underlying interface is torn down, the LegacyVpnRunner also should be. It has 4334 * no ability to migrate between interfaces (or Networks). 4335 */ exitIfOuterInterfaceIs(String interfaze)4336 public void exitIfOuterInterfaceIs(String interfaze) { 4337 if (interfaze.equals(mOuterInterface)) { 4338 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 4339 exitVpnRunner(); 4340 } 4341 } 4342 4343 /** Tears down this LegacyVpn connection */ 4344 @Override exitVpnRunner()4345 public void exitVpnRunner() { 4346 // We assume that everything is reset after stopping the daemons. 4347 interrupt(); 4348 4349 // Always disconnect. This may be called again in cleanupVpnStateLocked() if 4350 // exitVpnRunner() was called from exit(), but it will be a no-op. 4351 agentDisconnect(); 4352 try { 4353 mContext.unregisterReceiver(mBroadcastReceiver); 4354 } catch (IllegalArgumentException e) {} 4355 } 4356 4357 @Override run()4358 public void run() { 4359 // Wait for the previous thread since it has been interrupted. 4360 Log.v(TAG, "Waiting"); 4361 synchronized (TAG) { 4362 Log.v(TAG, "Executing"); 4363 try { 4364 bringup(); 4365 waitForDaemonsToStop(); 4366 interrupted(); // Clear interrupt flag if execute called exit. 4367 } catch (InterruptedException e) { 4368 } finally { 4369 for (LocalSocket socket : mSockets) { 4370 IoUtils.closeQuietly(socket); 4371 } 4372 // This sleep is necessary for racoon to successfully complete sending delete 4373 // message to server. 4374 try { 4375 Thread.sleep(50); 4376 } catch (InterruptedException e) { 4377 } 4378 for (String daemon : mDaemons) { 4379 mDeps.stopService(daemon); 4380 } 4381 } 4382 agentDisconnect(); 4383 } 4384 } 4385 checkInterruptAndDelay(boolean sleepLonger)4386 private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException { 4387 long now = SystemClock.elapsedRealtime(); 4388 if (now - mBringupStartTime <= 60000) { 4389 Thread.sleep(sleepLonger ? 200 : 1); 4390 } else { 4391 updateState(DetailedState.FAILED, "checkpoint"); 4392 throw new IllegalStateException("VPN bringup took too long"); 4393 } 4394 } 4395 checkAndFixupArguments(@onNull final InetAddress endpointAddress)4396 private void checkAndFixupArguments(@NonNull final InetAddress endpointAddress) { 4397 final String endpointAddressString = endpointAddress.getHostAddress(); 4398 // Perform some safety checks before inserting the address in place. 4399 // Position 0 in mDaemons and mArguments must be racoon, and position 1 must be mtpd. 4400 if (!"racoon".equals(mDaemons[0]) || !"mtpd".equals(mDaemons[1])) { 4401 throw new IllegalStateException("Unexpected daemons order"); 4402 } 4403 4404 // Respectively, the positions at which racoon and mtpd take the server address 4405 // argument are 1 and 2. Not all types of VPN require both daemons however, and 4406 // in that case the corresponding argument array is null. 4407 if (mArguments[0] != null) { 4408 if (!mProfile.server.equals(mArguments[0][1])) { 4409 throw new IllegalStateException("Invalid server argument for racoon"); 4410 } 4411 mArguments[0][1] = endpointAddressString; 4412 } 4413 4414 if (mArguments[1] != null) { 4415 if (!mProfile.server.equals(mArguments[1][2])) { 4416 throw new IllegalStateException("Invalid server argument for mtpd"); 4417 } 4418 mArguments[1][2] = endpointAddressString; 4419 } 4420 } 4421 bringup()4422 private void bringup() { 4423 // Catch all exceptions so we can clean up a few things. 4424 try { 4425 // resolve never returns null. If it does because of some bug, it will be 4426 // caught by the catch() block below and cleanup gracefully. 4427 final InetAddress endpointAddress = mDeps.resolve(mProfile.server); 4428 4429 // Big hack : dynamically replace the address of the server in the arguments 4430 // with the resolved address. 4431 checkAndFixupArguments(endpointAddress); 4432 4433 // Initialize the timer. 4434 mBringupStartTime = SystemClock.elapsedRealtime(); 4435 4436 // Wait for the daemons to stop. 4437 for (String daemon : mDaemons) { 4438 while (!mDeps.isServiceStopped(daemon)) { 4439 checkInterruptAndDelay(true); 4440 } 4441 } 4442 4443 // Clear the previous state. 4444 final File state = mDeps.getStateFile(); 4445 state.delete(); 4446 if (state.exists()) { 4447 throw new IllegalStateException("Cannot delete the state"); 4448 } 4449 new File("/data/misc/vpn/abort").delete(); 4450 4451 updateState(DetailedState.CONNECTING, "execute"); 4452 4453 // Start the daemon with arguments. 4454 for (int i = 0; i < mDaemons.length; ++i) { 4455 String[] arguments = mArguments[i]; 4456 if (arguments == null) { 4457 continue; 4458 } 4459 4460 // Start the daemon. 4461 String daemon = mDaemons[i]; 4462 mDeps.startService(daemon); 4463 4464 // Wait for the daemon to start. 4465 while (!mDeps.isServiceRunning(daemon)) { 4466 checkInterruptAndDelay(true); 4467 } 4468 4469 // Create the control socket. 4470 mSockets[i] = new LocalSocket(); 4471 4472 // Wait for the socket to connect and send over the arguments. 4473 mDeps.sendArgumentsToDaemon(daemon, mSockets[i], arguments, 4474 this::checkInterruptAndDelay); 4475 } 4476 4477 // Wait for the daemons to create the new state. 4478 while (!state.exists()) { 4479 // Check if a running daemon is dead. 4480 for (int i = 0; i < mDaemons.length; ++i) { 4481 String daemon = mDaemons[i]; 4482 if (mArguments[i] != null && !mDeps.isServiceRunning(daemon)) { 4483 throw new IllegalStateException(daemon + " is dead"); 4484 } 4485 } 4486 checkInterruptAndDelay(true); 4487 } 4488 4489 // Now we are connected. Read and parse the new state. 4490 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 4491 if (parameters.length != 7) { 4492 throw new IllegalStateException("Cannot parse the state: '" 4493 + String.join("', '", parameters) + "'"); 4494 } 4495 4496 // Set the interface and the addresses in the config. 4497 synchronized (Vpn.this) { 4498 mConfig.interfaze = parameters[0].trim(); 4499 4500 mConfig.addLegacyAddresses(parameters[1]); 4501 // Set the routes if they are not set in the config. 4502 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 4503 mConfig.addLegacyRoutes(parameters[2]); 4504 } 4505 4506 // Set the DNS servers if they are not set in the config. 4507 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 4508 String dnsServers = parameters[3].trim(); 4509 if (!dnsServers.isEmpty()) { 4510 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 4511 } 4512 } 4513 4514 // Set the search domains if they are not set in the config. 4515 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 4516 String searchDomains = parameters[4].trim(); 4517 if (!searchDomains.isEmpty()) { 4518 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 4519 } 4520 } 4521 4522 // Add a throw route for the VPN server endpoint, if one was specified. 4523 if (endpointAddress instanceof Inet4Address) { 4524 mConfig.routes.add(new RouteInfo( 4525 new IpPrefix(endpointAddress, 32), null /*gateway*/, 4526 null /*iface*/, RTN_THROW)); 4527 } else if (endpointAddress instanceof Inet6Address) { 4528 mConfig.routes.add(new RouteInfo( 4529 new IpPrefix(endpointAddress, 128), null /*gateway*/, 4530 null /*iface*/, RTN_THROW)); 4531 } else { 4532 Log.e(TAG, "Unknown IP address family for VPN endpoint: " 4533 + endpointAddress); 4534 } 4535 4536 // Here is the last step and it must be done synchronously. 4537 // Set the start time 4538 mConfig.startTime = SystemClock.elapsedRealtime(); 4539 4540 // Check if the thread was interrupted while we were waiting on the lock. 4541 checkInterruptAndDelay(false); 4542 4543 // Check if the interface is gone while we are waiting. 4544 if (!mDeps.isInterfacePresent(Vpn.this, mConfig.interfaze)) { 4545 throw new IllegalStateException(mConfig.interfaze + " is gone"); 4546 } 4547 4548 // Now INetworkManagementEventObserver is watching our back. 4549 mInterface = mConfig.interfaze; 4550 prepareStatusIntent(); 4551 4552 agentConnect(); 4553 4554 Log.i(TAG, "Connected!"); 4555 } 4556 } catch (Exception e) { 4557 Log.i(TAG, "Aborting", e); 4558 updateState(DetailedState.FAILED, e.getMessage()); 4559 exitVpnRunner(); 4560 } 4561 } 4562 4563 /** 4564 * Check all daemons every two seconds. Return when one of them is stopped. 4565 * The caller will move to the disconnected state when this function returns, 4566 * which can happen if a daemon failed or if the VPN was torn down. 4567 */ waitForDaemonsToStop()4568 private void waitForDaemonsToStop() throws InterruptedException { 4569 if (!mNetworkInfo.isConnected()) { 4570 return; 4571 } 4572 while (true) { 4573 Thread.sleep(2000); 4574 for (int i = 0; i < mDaemons.length; i++) { 4575 if (mArguments[i] != null && mDeps.isServiceStopped(mDaemons[i])) { 4576 return; 4577 } 4578 } 4579 } 4580 } 4581 } 4582 verifyCallingUidAndPackage(String packageName)4583 private void verifyCallingUidAndPackage(String packageName) { 4584 mDeps.verifyCallingUidAndPackage(mContext, packageName, mUserId); 4585 } 4586 4587 @VisibleForTesting getProfileNameForPackage(String packageName)4588 String getProfileNameForPackage(String packageName) { 4589 return Credentials.PLATFORM_VPN + mUserId + "_" + packageName; 4590 } 4591 4592 @VisibleForTesting validateRequiredFeatures(VpnProfile profile)4593 void validateRequiredFeatures(VpnProfile profile) { 4594 switch (profile.type) { 4595 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 4596 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 4597 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 4598 case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS: 4599 if (!mContext.getPackageManager().hasSystemFeature( 4600 PackageManager.FEATURE_IPSEC_TUNNELS)) { 4601 throw new UnsupportedOperationException( 4602 "Ikev2VpnProfile(s) requires PackageManager.FEATURE_IPSEC_TUNNELS"); 4603 } 4604 break; 4605 default: 4606 return; 4607 } 4608 } 4609 4610 /** 4611 * Stores an app-provisioned VPN profile and returns whether the app is already prepared. 4612 * 4613 * @param packageName the package name of the app provisioning this profile 4614 * @param profile the profile to be stored and provisioned 4615 * @returns whether or not the app has already been granted user consent 4616 */ provisionVpnProfile( @onNull String packageName, @NonNull VpnProfile profile)4617 public synchronized boolean provisionVpnProfile( 4618 @NonNull String packageName, @NonNull VpnProfile profile) { 4619 requireNonNull(packageName, "No package name provided"); 4620 requireNonNull(profile, "No profile provided"); 4621 4622 verifyCallingUidAndPackage(packageName); 4623 enforceNotRestrictedUser(); 4624 validateRequiredFeatures(profile); 4625 4626 if (profile.isRestrictedToTestNetworks) { 4627 mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS, 4628 "Test-mode profiles require the MANAGE_TEST_NETWORKS permission"); 4629 } 4630 4631 final byte[] encodedProfile = profile.encode(); 4632 if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) { 4633 throw new IllegalArgumentException("Profile too big"); 4634 } 4635 4636 // Permissions checked during startVpnProfile() 4637 final long token = Binder.clearCallingIdentity(); 4638 try { 4639 getVpnProfileStore().put(getProfileNameForPackage(packageName), encodedProfile); 4640 } finally { 4641 Binder.restoreCallingIdentity(token); 4642 } 4643 4644 // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. 4645 // This mirrors the prepareAndAuthorize that is used by VpnService. 4646 4647 // Return whether the app is already pre-consented 4648 return isVpnProfilePreConsented(mContext, packageName); 4649 } 4650 isCurrentIkev2VpnLocked(@onNull String packageName)4651 private boolean isCurrentIkev2VpnLocked(@NonNull String packageName) { 4652 return isCurrentPreparedPackage(packageName) && isIkev2VpnRunner(); 4653 } 4654 4655 /** 4656 * Deletes an app-provisioned VPN profile. 4657 * 4658 * @param packageName the package name of the app provisioning this profile 4659 */ deleteVpnProfile( @onNull String packageName)4660 public synchronized void deleteVpnProfile( 4661 @NonNull String packageName) { 4662 requireNonNull(packageName, "No package name provided"); 4663 4664 verifyCallingUidAndPackage(packageName); 4665 enforceNotRestrictedUser(); 4666 4667 final long token = Binder.clearCallingIdentity(); 4668 try { 4669 // If this profile is providing the current VPN, turn it off, disabling 4670 // always-on as well if enabled. 4671 if (isCurrentIkev2VpnLocked(packageName)) { 4672 if (mAlwaysOn) { 4673 // Will transitively call prepareInternal(VpnConfig.LEGACY_VPN). 4674 setAlwaysOnPackage(null, false, null); 4675 } else { 4676 prepareInternal(VpnConfig.LEGACY_VPN); 4677 } 4678 } 4679 4680 getVpnProfileStore().remove(getProfileNameForPackage(packageName)); 4681 } finally { 4682 Binder.restoreCallingIdentity(token); 4683 } 4684 } 4685 4686 /** 4687 * Retrieves the VpnProfile. 4688 * 4689 * <p>Must be used only as SYSTEM_UID, otherwise the key/UID pair will not match anything in the 4690 * keystore. 4691 */ 4692 @VisibleForTesting 4693 @Nullable getVpnProfilePrivileged(@onNull String packageName)4694 VpnProfile getVpnProfilePrivileged(@NonNull String packageName) { 4695 if (!mDeps.isCallerSystem()) { 4696 Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID "); 4697 return null; 4698 } 4699 4700 final byte[] encoded = getVpnProfileStore().get(getProfileNameForPackage(packageName)); 4701 if (encoded == null) return null; 4702 4703 return VpnProfile.decode("" /* Key unused */, encoded); 4704 } 4705 isIkev2VpnRunner()4706 private boolean isIkev2VpnRunner() { 4707 return (mVpnRunner instanceof IkeV2VpnRunner); 4708 } 4709 4710 @GuardedBy("this") 4711 @Nullable getSessionKeyLocked()4712 private String getSessionKeyLocked() { 4713 // Add log for debugging flaky test. b/242833779 4714 final boolean isIkev2VpnRunner = isIkev2VpnRunner(); 4715 final String sessionKey = 4716 isIkev2VpnRunner ? ((IkeV2VpnRunner) mVpnRunner).mSessionKey : null; 4717 Log.d(TAG, "getSessionKeyLocked: isIkev2VpnRunner = " + isIkev2VpnRunner 4718 + ", sessionKey = " + sessionKey); 4719 return sessionKey; 4720 } 4721 4722 /** 4723 * Starts an already provisioned VPN Profile, keyed by package name. 4724 * 4725 * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService). 4726 * Privileged (system) callers should use startVpnProfilePrivileged instead. Otherwise the UIDs 4727 * will not match during appop checks. 4728 * 4729 * @param packageName the package name of the app provisioning this profile 4730 */ startVpnProfile(@onNull String packageName)4731 public synchronized String startVpnProfile(@NonNull String packageName) { 4732 requireNonNull(packageName, "No package name provided"); 4733 4734 enforceNotRestrictedUser(); 4735 4736 // Prepare VPN for startup 4737 if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) { 4738 throw new SecurityException("User consent not granted for package " + packageName); 4739 } 4740 4741 final long token = Binder.clearCallingIdentity(); 4742 try { 4743 final VpnProfile profile = getVpnProfilePrivileged(packageName); 4744 if (profile == null) { 4745 throw new IllegalArgumentException("No profile found for " + packageName); 4746 } 4747 4748 startVpnProfilePrivileged(profile, packageName); 4749 if (!isIkev2VpnRunner()) { 4750 throw new IllegalStateException("mVpnRunner shouldn't be null and should also be " 4751 + "an instance of Ikev2VpnRunner"); 4752 } 4753 return getSessionKeyLocked(); 4754 } finally { 4755 Binder.restoreCallingIdentity(token); 4756 } 4757 } 4758 startVpnProfilePrivileged( @onNull VpnProfile profile, @NonNull String packageName)4759 private synchronized void startVpnProfilePrivileged( 4760 @NonNull VpnProfile profile, @NonNull String packageName) { 4761 // Make sure VPN is prepared. This method can be called by user apps via startVpnProfile(), 4762 // by the Setting app via startLegacyVpn(), or by ConnectivityService via 4763 // startAlwaysOnVpn(), so this is the common place to prepare the VPN. This also has the 4764 // nice property of ensuring there are no other VpnRunner instances running. 4765 prepareInternal(packageName); 4766 updateState(DetailedState.CONNECTING, "startPlatformVpn"); 4767 4768 try { 4769 // Build basic config 4770 final VpnConfig config = new VpnConfig(); 4771 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 4772 config.legacy = true; 4773 config.session = profile.name; 4774 config.user = profile.key; 4775 4776 // TODO: Add support for configuring meteredness via Settings. Until then, use a 4777 // safe default. 4778 config.isMetered = true; 4779 } else { 4780 config.user = packageName; 4781 config.isMetered = profile.isMetered; 4782 } 4783 config.startTime = SystemClock.elapsedRealtime(); 4784 config.proxyInfo = profile.proxy; 4785 config.requiresInternetValidation = profile.requiresInternetValidation; 4786 config.excludeLocalRoutes = profile.excludeLocalRoutes; 4787 config.allowBypass = profile.isBypassable; 4788 config.disallowedApplications = getAppExclusionList(mPackage); 4789 mConfig = config; 4790 4791 switch (profile.type) { 4792 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 4793 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 4794 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 4795 case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS: 4796 mVpnRunner = 4797 new IkeV2VpnRunner( 4798 Ikev2VpnProfile.fromVpnProfile(profile), 4799 mDeps.newScheduledThreadPoolExecutor()); 4800 mVpnRunner.start(); 4801 break; 4802 default: 4803 mConfig = null; 4804 updateState(DetailedState.FAILED, "Invalid platform VPN type"); 4805 Log.d(TAG, "Unknown VPN profile type: " + profile.type); 4806 break; 4807 } 4808 4809 // Record that the VPN connection is established by an app which uses VpnManager API. 4810 if (!VpnConfig.LEGACY_VPN.equals(packageName)) { 4811 mAppOpsManager.startOp( 4812 AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null, 4813 null); 4814 } 4815 } catch (GeneralSecurityException e) { 4816 // Reset mConfig 4817 mConfig = null; 4818 4819 updateState(DetailedState.FAILED, "VPN startup failed"); 4820 throw new IllegalArgumentException("VPN startup failed", e); 4821 } 4822 } 4823 4824 @GuardedBy("this") stopVpnRunnerAndNotifyAppLocked()4825 private void stopVpnRunnerAndNotifyAppLocked() { 4826 // Build intent first because the sessionKey will be reset after performing 4827 // VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in 4828 // VpnRunner.exit() to prevent design being changed in the future. 4829 // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from 4830 // ConnectivityServiceTest. 4831 final int ownerUid = mOwnerUID; 4832 Intent intent = null; 4833 if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { 4834 intent = buildVpnManagerEventIntent( 4835 VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, 4836 -1 /* errorClass */, -1 /* errorCode*/, mPackage, 4837 getSessionKeyLocked(), makeVpnProfileStateLocked(), 4838 null /* underlyingNetwork */, null /* nc */, null /* lp */); 4839 } 4840 // cleanupVpnStateLocked() is called from mVpnRunner.exit() 4841 mVpnRunner.exit(); 4842 if (intent != null && isVpnApp(mPackage)) { 4843 notifyVpnManagerVpnStopped(mPackage, ownerUid, intent); 4844 } 4845 } 4846 4847 /** 4848 * Stops an already running VPN Profile for the given package. 4849 * 4850 * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService). 4851 * Privileged (system) callers should (re-)prepare the LEGACY_VPN instead. 4852 * 4853 * @param packageName the package name of the app provisioning this profile 4854 */ stopVpnProfile(@onNull String packageName)4855 public synchronized void stopVpnProfile(@NonNull String packageName) { 4856 requireNonNull(packageName, "No package name provided"); 4857 4858 enforceNotRestrictedUser(); 4859 4860 // To stop the VPN profile, the caller must be the current prepared package and must be 4861 // running an Ikev2VpnProfile. 4862 if (isCurrentIkev2VpnLocked(packageName)) { 4863 stopVpnRunnerAndNotifyAppLocked(); 4864 } 4865 } 4866 notifyVpnManagerVpnStopped(String packageName, int ownerUID, Intent intent)4867 private synchronized void notifyVpnManagerVpnStopped(String packageName, int ownerUID, 4868 Intent intent) { 4869 mAppOpsManager.finishOp( 4870 AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, ownerUID, packageName, null); 4871 // The underlying network, NetworkCapabilities and LinkProperties are not 4872 // necessary to send to VPN app since the purpose of this event is to notify 4873 // VPN app that VPN is deactivated by the user. 4874 // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from 4875 // ConnectivityServiceTest. 4876 if (SdkLevel.isAtLeastT()) { 4877 mEventChanges.log("[VMEvent] " + packageName + " stopped"); 4878 sendEventToVpnManagerApp(intent, packageName); 4879 } 4880 } 4881 storeAppExclusionList(@onNull String packageName, @NonNull List<String> excludedApps)4882 private boolean storeAppExclusionList(@NonNull String packageName, 4883 @NonNull List<String> excludedApps) { 4884 byte[] data; 4885 try { 4886 final PersistableBundle bundle = PersistableBundleUtils.fromList( 4887 excludedApps, PersistableBundleUtils.STRING_SERIALIZER); 4888 data = PersistableBundleUtils.toDiskStableBytes(bundle); 4889 } catch (IOException e) { 4890 Log.e(TAG, "problem writing into stream", e); 4891 return false; 4892 } 4893 4894 final long oldId = Binder.clearCallingIdentity(); 4895 try { 4896 getVpnProfileStore().put(getVpnAppExcludedForPackage(packageName), data); 4897 } finally { 4898 Binder.restoreCallingIdentity(oldId); 4899 } 4900 return true; 4901 } 4902 4903 @VisibleForTesting getVpnAppExcludedForPackage(String packageName)4904 String getVpnAppExcludedForPackage(String packageName) { 4905 return VPN_APP_EXCLUDED + mUserId + "_" + packageName; 4906 } 4907 4908 /** 4909 * Set the application exclusion list for the specified VPN profile. 4910 * 4911 * @param packageName the package name of the app provisioning this profile 4912 * @param excludedApps the list of excluded packages 4913 * 4914 * @return whether setting the list is successful or not 4915 */ setAppExclusionList(@onNull String packageName, @NonNull List<String> excludedApps)4916 public synchronized boolean setAppExclusionList(@NonNull String packageName, 4917 @NonNull List<String> excludedApps) { 4918 enforceNotRestrictedUser(); 4919 if (!storeAppExclusionList(packageName, excludedApps)) return false; 4920 4921 updateAppExclusionList(excludedApps); 4922 4923 return true; 4924 } 4925 4926 /** 4927 * Triggers an update of the VPN network's excluded UIDs if a VPN is running. 4928 */ refreshPlatformVpnAppExclusionList()4929 public synchronized void refreshPlatformVpnAppExclusionList() { 4930 updateAppExclusionList(getAppExclusionList(mPackage)); 4931 } 4932 updateAppExclusionList(@onNull List<String> excludedApps)4933 private synchronized void updateAppExclusionList(@NonNull List<String> excludedApps) { 4934 // Re-build and update NetworkCapabilities via NetworkAgent. 4935 if (mNetworkAgent != null) { 4936 // Only update the platform VPN 4937 if (isIkev2VpnRunner()) { 4938 mConfig.disallowedApplications = List.copyOf(excludedApps); 4939 mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities) 4940 .setUids(createUserAndRestrictedProfilesRanges( 4941 mUserId, null /* allowedApplications */, excludedApps)) 4942 .build(); 4943 setVpnNetworkPreference(getSessionKeyLocked(), 4944 createUserAndRestrictedProfilesRanges(mUserId, 4945 mConfig.allowedApplications, mConfig.disallowedApplications)); 4946 doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities); 4947 } 4948 } 4949 } 4950 4951 /** 4952 * Gets the application exclusion list for the specified VPN profile. 4953 * 4954 * @param packageName the package name of the app provisioning this profile 4955 * @return the list of excluded packages for the specified VPN profile or empty list if there is 4956 * no provisioned VPN profile. 4957 */ 4958 @NonNull getAppExclusionList(@onNull String packageName)4959 public synchronized List<String> getAppExclusionList(@NonNull String packageName) { 4960 final long oldId = Binder.clearCallingIdentity(); 4961 try { 4962 final byte[] bytes = getVpnProfileStore().get(getVpnAppExcludedForPackage(packageName)); 4963 4964 if (bytes == null || bytes.length == 0) return new ArrayList<>(); 4965 4966 final PersistableBundle bundle = PersistableBundleUtils.fromDiskStableBytes(bytes); 4967 return PersistableBundleUtils.toList(bundle, STRING_DESERIALIZER); 4968 } catch (IOException e) { 4969 Log.e(TAG, "problem reading from stream", e); 4970 } finally { 4971 Binder.restoreCallingIdentity(oldId); 4972 } 4973 4974 return new ArrayList<>(); 4975 } 4976 getStateFromLegacyState(int legacyState)4977 private @VpnProfileState.State int getStateFromLegacyState(int legacyState) { 4978 switch (legacyState) { 4979 case LegacyVpnInfo.STATE_CONNECTING: 4980 return VpnProfileState.STATE_CONNECTING; 4981 case LegacyVpnInfo.STATE_CONNECTED: 4982 return VpnProfileState.STATE_CONNECTED; 4983 case LegacyVpnInfo.STATE_DISCONNECTED: 4984 return VpnProfileState.STATE_DISCONNECTED; 4985 case LegacyVpnInfo.STATE_FAILED: 4986 return VpnProfileState.STATE_FAILED; 4987 default: 4988 Log.wtf(TAG, "Unhandled state " + legacyState 4989 + ", treat it as STATE_DISCONNECTED"); 4990 return VpnProfileState.STATE_DISCONNECTED; 4991 } 4992 } 4993 4994 @GuardedBy("this") 4995 @NonNull makeVpnProfileStateLocked()4996 private VpnProfileState makeVpnProfileStateLocked() { 4997 return new VpnProfileState(getStateFromLegacyState(mLegacyState), 4998 isIkev2VpnRunner() ? getSessionKeyLocked() : null, mAlwaysOn, mLockdown); 4999 } 5000 5001 @NonNull makeDisconnectedVpnProfileState()5002 private VpnProfileState makeDisconnectedVpnProfileState() { 5003 return new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, null /* sessionKey */, 5004 false /* alwaysOn */, false /* lockdown */); 5005 } 5006 5007 /** 5008 * Retrieve the VpnProfileState for the profile provisioned by the given package. 5009 * 5010 * @return the VpnProfileState with current information, or null if there was no profile 5011 * provisioned and started by the given package. 5012 */ 5013 @Nullable getProvisionedVpnProfileState( @onNull String packageName)5014 public synchronized VpnProfileState getProvisionedVpnProfileState( 5015 @NonNull String packageName) { 5016 requireNonNull(packageName, "No package name provided"); 5017 enforceNotRestrictedUser(); 5018 return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileStateLocked() : null; 5019 } 5020 5021 /** Proxy to allow different testing setups */ 5022 // TODO: b/240492694 Remove VpnNetworkAgentWrapper and this method when 5023 // NetworkAgent#sendLinkProperties can be un-finalized. doSendLinkProperties( @onNull NetworkAgent agent, @NonNull LinkProperties lp)5024 private static void doSendLinkProperties( 5025 @NonNull NetworkAgent agent, @NonNull LinkProperties lp) { 5026 if (agent instanceof VpnNetworkAgentWrapper) { 5027 ((VpnNetworkAgentWrapper) agent).doSendLinkProperties(lp); 5028 } else { 5029 agent.sendLinkProperties(lp); 5030 } 5031 } 5032 5033 /** Proxy to allow different testing setups */ 5034 // TODO: b/240492694 Remove VpnNetworkAgentWrapper and this method when 5035 // NetworkAgent#sendNetworkCapabilities can be un-finalized. doSendNetworkCapabilities( @onNull NetworkAgent agent, @NonNull NetworkCapabilities nc)5036 private static void doSendNetworkCapabilities( 5037 @NonNull NetworkAgent agent, @NonNull NetworkCapabilities nc) { 5038 if (agent instanceof VpnNetworkAgentWrapper) { 5039 ((VpnNetworkAgentWrapper) agent).doSendNetworkCapabilities(nc); 5040 } else { 5041 agent.sendNetworkCapabilities(nc); 5042 } 5043 } 5044 5045 /** Proxy to allow different testing setups */ 5046 // TODO: b/240492694 Remove VpnNetworkAgentWrapper and this method when 5047 // NetworkAgent#setUnderlyingNetworks can be un-finalized. doSetUnderlyingNetworks( @onNull NetworkAgent agent, @NonNull List<Network> networks)5048 private void doSetUnderlyingNetworks( 5049 @NonNull NetworkAgent agent, @NonNull List<Network> networks) { 5050 logUnderlyNetworkChanges(networks); 5051 5052 if (agent instanceof VpnNetworkAgentWrapper) { 5053 ((VpnNetworkAgentWrapper) agent).doSetUnderlyingNetworks(networks); 5054 } else { 5055 agent.setUnderlyingNetworks(networks); 5056 } 5057 } 5058 5059 /** 5060 * Proxy to allow testing 5061 * 5062 * @hide 5063 */ 5064 // TODO: b/240492694 Remove VpnNetworkAgentWrapper when NetworkAgent's methods can be 5065 // un-finalized. 5066 @VisibleForTesting 5067 public static class VpnNetworkAgentWrapper extends NetworkAgent { 5068 private final ValidationStatusCallback mCallback; 5069 /** Create an VpnNetworkAgentWrapper */ VpnNetworkAgentWrapper( @onNull Context context, @NonNull Looper looper, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider, @Nullable ValidationStatusCallback callback)5070 public VpnNetworkAgentWrapper( 5071 @NonNull Context context, 5072 @NonNull Looper looper, 5073 @NonNull String logTag, 5074 @NonNull NetworkCapabilities nc, 5075 @NonNull LinkProperties lp, 5076 @NonNull NetworkScore score, 5077 @NonNull NetworkAgentConfig config, 5078 @Nullable NetworkProvider provider, 5079 @Nullable ValidationStatusCallback callback) { 5080 super(context, looper, logTag, nc, lp, score, config, provider); 5081 mCallback = callback; 5082 } 5083 5084 /** Update the LinkProperties */ doSendLinkProperties(@onNull LinkProperties lp)5085 public void doSendLinkProperties(@NonNull LinkProperties lp) { 5086 sendLinkProperties(lp); 5087 } 5088 5089 /** Update the NetworkCapabilities */ doSendNetworkCapabilities(@onNull NetworkCapabilities nc)5090 public void doSendNetworkCapabilities(@NonNull NetworkCapabilities nc) { 5091 sendNetworkCapabilities(nc); 5092 } 5093 5094 /** Set the underlying networks */ doSetUnderlyingNetworks(@onNull List<Network> networks)5095 public void doSetUnderlyingNetworks(@NonNull List<Network> networks) { 5096 setUnderlyingNetworks(networks); 5097 } 5098 5099 @Override onNetworkUnwanted()5100 public void onNetworkUnwanted() { 5101 // We are user controlled, not driven by NetworkRequest. 5102 } 5103 5104 @Override onValidationStatus(int status, Uri redirectUri)5105 public void onValidationStatus(int status, Uri redirectUri) { 5106 if (mCallback != null) { 5107 mCallback.onValidationStatus(status); 5108 } 5109 } 5110 } 5111 5112 /** 5113 * Proxy to allow testing 5114 * 5115 * @hide 5116 */ 5117 @VisibleForTesting 5118 public static class IkeSessionWrapper { 5119 private final IkeSession mImpl; 5120 5121 /** Create an IkeSessionWrapper */ IkeSessionWrapper(IkeSession session)5122 public IkeSessionWrapper(IkeSession session) { 5123 mImpl = session; 5124 } 5125 5126 /** Update the underlying network of the IKE Session */ setNetwork(@onNull Network network, int ipVersion, int encapType, int keepaliveDelaySeconds)5127 public void setNetwork(@NonNull Network network, int ipVersion, int encapType, 5128 int keepaliveDelaySeconds) { 5129 mImpl.setNetwork(network, ipVersion, encapType, keepaliveDelaySeconds); 5130 } 5131 5132 /** Set the underpinned network */ setUnderpinnedNetwork(@onNull Network underpinnedNetwork)5133 public void setUnderpinnedNetwork(@NonNull Network underpinnedNetwork) { 5134 mImpl.setUnderpinnedNetwork(underpinnedNetwork); 5135 } 5136 5137 /** Forcibly terminate the IKE Session */ kill()5138 public void kill() { 5139 mImpl.kill(); 5140 } 5141 } 5142 5143 /** 5144 * Proxy to allow testing 5145 * 5146 * @hide 5147 */ 5148 @VisibleForTesting 5149 public static class Ikev2SessionCreator { 5150 /** Creates a IKE session */ createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)5151 public IkeSessionWrapper createIkeSession( 5152 @NonNull Context context, 5153 @NonNull IkeSessionParams ikeSessionParams, 5154 @NonNull ChildSessionParams firstChildSessionParams, 5155 @NonNull Executor userCbExecutor, 5156 @NonNull IkeSessionCallback ikeSessionCallback, 5157 @NonNull ChildSessionCallback firstChildSessionCallback) { 5158 return new IkeSessionWrapper( 5159 new IkeSession( 5160 context, 5161 ikeSessionParams, 5162 firstChildSessionParams, 5163 userCbExecutor, 5164 ikeSessionCallback, 5165 firstChildSessionCallback)); 5166 } 5167 } 5168 5169 /** 5170 * Returns the entire range of UIDs available to a macro-user. This is something like 0-99999. 5171 */ 5172 @VisibleForTesting createUidRangeForUser(int userId)5173 static Range<Integer> createUidRangeForUser(int userId) { 5174 return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); 5175 } 5176 getVpnManagerEventClassName(int code)5177 private String getVpnManagerEventClassName(int code) { 5178 switch (code) { 5179 case VpnManager.ERROR_CLASS_NOT_RECOVERABLE: 5180 return "ERROR_CLASS_NOT_RECOVERABLE"; 5181 case VpnManager.ERROR_CLASS_RECOVERABLE: 5182 return "ERROR_CLASS_RECOVERABLE"; 5183 default: 5184 return "UNKNOWN_CLASS"; 5185 } 5186 } 5187 getVpnManagerEventErrorName(int code)5188 private String getVpnManagerEventErrorName(int code) { 5189 switch (code) { 5190 case VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST: 5191 return "ERROR_CODE_NETWORK_UNKNOWN_HOST"; 5192 case VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT: 5193 return "ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT"; 5194 case VpnManager.ERROR_CODE_NETWORK_IO: 5195 return "ERROR_CODE_NETWORK_IO"; 5196 case VpnManager.ERROR_CODE_NETWORK_LOST: 5197 return "ERROR_CODE_NETWORK_LOST"; 5198 default: 5199 return "UNKNOWN_ERROR"; 5200 } 5201 } 5202 5203 /** Dumps VPN state. */ dump(IndentingPrintWriter pw)5204 public void dump(IndentingPrintWriter pw) { 5205 synchronized (Vpn.this) { 5206 pw.println("Active package name: " + mPackage); 5207 pw.println("Active vpn type: " + getActiveVpnType()); 5208 pw.println("NetworkCapabilities: " + mNetworkCapabilities); 5209 if (isIkev2VpnRunner()) { 5210 final IkeV2VpnRunner runner = ((IkeV2VpnRunner) mVpnRunner); 5211 pw.println("SessionKey: " + runner.mSessionKey); 5212 pw.println("MOBIKE " + (runner.mMobikeEnabled ? "enabled" : "disabled")); 5213 pw.println("Profile: " + runner.mProfile); 5214 pw.println("Token: " + runner.mCurrentToken); 5215 pw.println("Validation failed retry count:" + runner.mValidationFailRetryCount); 5216 if (runner.mScheduledHandleDataStallFuture != null) { 5217 pw.println("Reset session scheduled"); 5218 } 5219 } 5220 pw.println(); 5221 pw.println("mCachedCarrierConfigInfoPerSubId=" + mCachedCarrierConfigInfoPerSubId); 5222 5223 pw.println("mEventChanges (most recent first):"); 5224 pw.increaseIndent(); 5225 mEventChanges.reverseDump(pw); 5226 pw.decreaseIndent(); 5227 } 5228 } 5229 getCellSubIdForNetworkCapabilities(@ullable NetworkCapabilities nc)5230 private static int getCellSubIdForNetworkCapabilities(@Nullable NetworkCapabilities nc) { 5231 if (nc == null) return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 5232 5233 if (!nc.hasTransport(TRANSPORT_CELLULAR)) { 5234 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 5235 } 5236 5237 final NetworkSpecifier specifier = nc.getNetworkSpecifier(); 5238 if (specifier instanceof TelephonyNetworkSpecifier) { 5239 return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); 5240 } 5241 5242 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 5243 } 5244 } 5245