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