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.net.ConnectivityManager.NETID_UNSET; 21 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 23 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; 24 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; 25 import static android.net.RouteInfo.RTN_THROW; 26 import static android.net.RouteInfo.RTN_UNREACHABLE; 27 28 import static com.android.internal.util.Preconditions.checkNotNull; 29 30 import android.Manifest; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.UserIdInt; 34 import android.app.AppGlobals; 35 import android.app.AppOpsManager; 36 import android.app.Notification; 37 import android.app.NotificationManager; 38 import android.app.PendingIntent; 39 import android.content.BroadcastReceiver; 40 import android.content.ComponentName; 41 import android.content.Context; 42 import android.content.Intent; 43 import android.content.IntentFilter; 44 import android.content.ServiceConnection; 45 import android.content.pm.ApplicationInfo; 46 import android.content.pm.PackageManager; 47 import android.content.pm.PackageManager.NameNotFoundException; 48 import android.content.pm.ResolveInfo; 49 import android.content.pm.UserInfo; 50 import android.net.ConnectivityManager; 51 import android.net.INetworkManagementEventObserver; 52 import android.net.Ikev2VpnProfile; 53 import android.net.IpPrefix; 54 import android.net.IpSecManager; 55 import android.net.IpSecManager.IpSecTunnelInterface; 56 import android.net.IpSecTransform; 57 import android.net.LinkAddress; 58 import android.net.LinkProperties; 59 import android.net.LocalSocket; 60 import android.net.LocalSocketAddress; 61 import android.net.Network; 62 import android.net.NetworkAgent; 63 import android.net.NetworkAgentConfig; 64 import android.net.NetworkCapabilities; 65 import android.net.NetworkInfo; 66 import android.net.NetworkInfo.DetailedState; 67 import android.net.NetworkProvider; 68 import android.net.NetworkRequest; 69 import android.net.RouteInfo; 70 import android.net.UidRange; 71 import android.net.VpnManager; 72 import android.net.VpnService; 73 import android.net.ipsec.ike.ChildSessionCallback; 74 import android.net.ipsec.ike.ChildSessionConfiguration; 75 import android.net.ipsec.ike.ChildSessionParams; 76 import android.net.ipsec.ike.IkeSession; 77 import android.net.ipsec.ike.IkeSessionCallback; 78 import android.net.ipsec.ike.IkeSessionParams; 79 import android.os.Binder; 80 import android.os.Build.VERSION_CODES; 81 import android.os.Bundle; 82 import android.os.FileUtils; 83 import android.os.IBinder; 84 import android.os.INetworkManagementService; 85 import android.os.Looper; 86 import android.os.Parcel; 87 import android.os.ParcelFileDescriptor; 88 import android.os.Process; 89 import android.os.RemoteException; 90 import android.os.SystemClock; 91 import android.os.SystemService; 92 import android.os.UserHandle; 93 import android.os.UserManager; 94 import android.provider.Settings; 95 import android.security.Credentials; 96 import android.security.KeyStore; 97 import android.text.TextUtils; 98 import android.util.ArraySet; 99 import android.util.Log; 100 101 import com.android.internal.R; 102 import com.android.internal.annotations.GuardedBy; 103 import com.android.internal.annotations.VisibleForTesting; 104 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 105 import com.android.internal.net.LegacyVpnInfo; 106 import com.android.internal.net.VpnConfig; 107 import com.android.internal.net.VpnInfo; 108 import com.android.internal.net.VpnProfile; 109 import com.android.internal.notification.SystemNotificationChannels; 110 import com.android.internal.util.ArrayUtils; 111 import com.android.server.ConnectivityService; 112 import com.android.server.DeviceIdleController; 113 import com.android.server.LocalServices; 114 import com.android.server.net.BaseNetworkObserver; 115 116 import libcore.io.IoUtils; 117 118 import java.io.File; 119 import java.io.IOException; 120 import java.io.InputStream; 121 import java.io.OutputStream; 122 import java.math.BigInteger; 123 import java.net.Inet4Address; 124 import java.net.Inet6Address; 125 import java.net.InetAddress; 126 import java.nio.charset.StandardCharsets; 127 import java.security.GeneralSecurityException; 128 import java.util.ArrayList; 129 import java.util.Arrays; 130 import java.util.Collection; 131 import java.util.Collections; 132 import java.util.List; 133 import java.util.Objects; 134 import java.util.Set; 135 import java.util.SortedSet; 136 import java.util.TreeSet; 137 import java.util.concurrent.Executor; 138 import java.util.concurrent.ExecutorService; 139 import java.util.concurrent.Executors; 140 import java.util.concurrent.atomic.AtomicInteger; 141 142 /** 143 * @hide 144 */ 145 public class Vpn { 146 private static final String NETWORKTYPE = "VPN"; 147 private static final String TAG = "Vpn"; 148 private static final boolean LOGD = true; 149 150 // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on 151 // the device idle whitelist during service launch and VPN bootstrap. 152 private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000; 153 154 // Settings for how much of the address space should be routed so that Vpn considers 155 // "most" of the address space is routed. This is used to determine whether this Vpn 156 // should be marked with the INTERNET capability. 157 private static final long MOST_IPV4_ADDRESSES_COUNT; 158 private static final BigInteger MOST_IPV6_ADDRESSES_COUNT; 159 static { 160 // 85% of the address space must be routed for Vpn to consider this VPN to provide 161 // INTERNET access. 162 final int howManyPercentIsMost = 85; 163 164 final long twoPower32 = 1L << 32; 165 MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100; 166 final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128); 167 MOST_IPV6_ADDRESSES_COUNT = twoPower128 168 .multiply(BigInteger.valueOf(howManyPercentIsMost)) 169 .divide(BigInteger.valueOf(100)); 170 } 171 // How many routes to evaluate before bailing and declaring this Vpn should provide 172 // the INTERNET capability. This is necessary because computing the address space is 173 // O(n²) and this is running in the system service, so a limit is needed to alleviate 174 // the risk of attack. 175 // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm 176 // is actually O(n²)+O(n²). 177 private static final int MAX_ROUTES_TO_EVALUATE = 150; 178 179 /** 180 * Largest profile size allowable for Platform VPNs. 181 * 182 * <p>The largest platform VPN profiles use IKEv2 RSA Certificate Authentication and have two 183 * X509Certificates, and one RSAPrivateKey. This should lead to a max size of 2x 12kB for the 184 * certificates, plus a reasonable upper bound on the private key of 32kB. The rest of the 185 * profile is expected to be negligible in size. 186 */ 187 @VisibleForTesting static final int MAX_VPN_PROFILE_SIZE_BYTES = 1 << 17; // 128kB 188 189 // TODO: create separate trackers for each unique VPN to support 190 // automated reconnection 191 192 private final Context mContext; 193 private final NetworkInfo mNetworkInfo; 194 @VisibleForTesting protected String mPackage; 195 private int mOwnerUID; 196 private boolean mIsPackageTargetingAtLeastQ; 197 private String mInterface; 198 private Connection mConnection; 199 200 /** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */ 201 @VisibleForTesting protected VpnRunner mVpnRunner; 202 203 private PendingIntent mStatusIntent; 204 private volatile boolean mEnableTeardown = true; 205 private final INetworkManagementService mNetd; 206 @VisibleForTesting 207 protected VpnConfig mConfig; 208 @VisibleForTesting 209 protected NetworkAgent mNetworkAgent; 210 private final Looper mLooper; 211 @VisibleForTesting 212 protected final NetworkCapabilities mNetworkCapabilities; 213 private final SystemServices mSystemServices; 214 private final Ikev2SessionCreator mIkev2SessionCreator; 215 216 /** 217 * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This 218 * only applies to {@link VpnService} connections. 219 */ 220 @VisibleForTesting protected boolean mAlwaysOn = false; 221 222 /** 223 * Whether to disable traffic outside of this VPN even when the VPN is not connected. System 224 * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is 225 * not set. Applies to all types of VPNs. 226 */ 227 @VisibleForTesting protected boolean mLockdown = false; 228 229 /** 230 * Set of packages in addition to the VPN app itself that can access the network directly when 231 * VPN is not connected even if {@code mLockdown} is set. 232 */ 233 private @NonNull List<String> mLockdownWhitelist = Collections.emptyList(); 234 235 /** 236 * A memory of what UIDs this class told netd to block for the lockdown feature. 237 * 238 * Netd maintains ranges of UIDs for which network should be restricted to using only the VPN 239 * for the lockdown feature. This class manages these UIDs and sends this information to netd. 240 * To avoid sending the same commands multiple times (which would be wasteful) and to be able 241 * to revoke lists (when the rules should change), it's simplest to keep this cache of what 242 * netd knows, so it can be diffed and sent most efficiently. 243 * 244 * The contents of this list must only be changed when updating the UIDs lists with netd, 245 * since it needs to keep in sync with the picture netd has of them. 246 * 247 * @see mLockdown 248 */ 249 @GuardedBy("this") 250 private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>(); 251 252 // Handle of the user initiating VPN. 253 private final int mUserHandle; 254 Vpn(Looper looper, Context context, INetworkManagementService netService, @UserIdInt int userHandle, @NonNull KeyStore keyStore)255 public Vpn(Looper looper, Context context, INetworkManagementService netService, 256 @UserIdInt int userHandle, @NonNull KeyStore keyStore) { 257 this(looper, context, netService, userHandle, keyStore, 258 new SystemServices(context), new Ikev2SessionCreator()); 259 } 260 261 @VisibleForTesting Vpn(Looper looper, Context context, INetworkManagementService netService, int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator)262 protected Vpn(Looper looper, Context context, INetworkManagementService netService, 263 int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices, 264 Ikev2SessionCreator ikev2SessionCreator) { 265 mContext = context; 266 mNetd = netService; 267 mUserHandle = userHandle; 268 mLooper = looper; 269 mSystemServices = systemServices; 270 mIkev2SessionCreator = ikev2SessionCreator; 271 272 mPackage = VpnConfig.LEGACY_VPN; 273 mOwnerUID = getAppUid(mPackage, mUserHandle); 274 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage); 275 276 try { 277 netService.registerObserver(mObserver); 278 } catch (RemoteException e) { 279 Log.wtf(TAG, "Problem registering observer", e); 280 } 281 282 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE, 283 "" /* subtypeName */); 284 mNetworkCapabilities = new NetworkCapabilities(); 285 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); 286 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); 287 updateCapabilities(null /* defaultNetwork */); 288 289 loadAlwaysOnPackage(keyStore); 290 } 291 292 /** 293 * Set whether this object is responsible for watching for {@link NetworkInfo} 294 * teardown. When {@code false}, teardown is handled externally by someone 295 * else. 296 */ setEnableTeardown(boolean enableTeardown)297 public void setEnableTeardown(boolean enableTeardown) { 298 mEnableTeardown = enableTeardown; 299 } 300 301 /** 302 * Update current state, dispatching event to listeners. 303 */ 304 @VisibleForTesting updateState(DetailedState detailedState, String reason)305 protected void updateState(DetailedState detailedState, String reason) { 306 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 307 mNetworkInfo.setDetailedState(detailedState, reason, null); 308 if (mNetworkAgent != null) { 309 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 310 } 311 updateAlwaysOnNotification(detailedState); 312 } 313 314 /** 315 * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a 316 * defensive copy. 317 * 318 * <p>Does not propagate updated capabilities to apps. 319 * 320 * @param defaultNetwork underlying network for VPNs following platform's default 321 */ updateCapabilities(@ullable Network defaultNetwork)322 public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) { 323 if (mConfig == null) { 324 // VPN is not running. 325 return null; 326 } 327 328 Network[] underlyingNetworks = mConfig.underlyingNetworks; 329 if (underlyingNetworks == null && defaultNetwork != null) { 330 // null underlying networks means to track the default. 331 underlyingNetworks = new Network[] { defaultNetwork }; 332 } 333 // Only apps targeting Q and above can explicitly declare themselves as metered. 334 final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered; 335 336 applyUnderlyingCapabilities( 337 mContext.getSystemService(ConnectivityManager.class), 338 underlyingNetworks, 339 mNetworkCapabilities, 340 isAlwaysMetered); 341 342 return new NetworkCapabilities(mNetworkCapabilities); 343 } 344 345 @VisibleForTesting applyUnderlyingCapabilities( ConnectivityManager cm, Network[] underlyingNetworks, NetworkCapabilities caps, boolean isAlwaysMetered)346 public static void applyUnderlyingCapabilities( 347 ConnectivityManager cm, 348 Network[] underlyingNetworks, 349 NetworkCapabilities caps, 350 boolean isAlwaysMetered) { 351 int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; 352 int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; 353 int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; 354 boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered 355 boolean roaming = false; // roaming if any underlying is roaming 356 boolean congested = false; // congested if any underlying is congested 357 boolean suspended = true; // suspended if all underlying are suspended 358 359 boolean hadUnderlyingNetworks = false; 360 if (null != underlyingNetworks) { 361 for (Network underlying : underlyingNetworks) { 362 // TODO(b/124469351): Get capabilities directly from ConnectivityService instead. 363 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying); 364 if (underlyingCaps == null) continue; 365 hadUnderlyingNetworks = true; 366 for (int underlyingType : underlyingCaps.getTransportTypes()) { 367 transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType); 368 } 369 370 // Merge capabilities of this underlying network. For bandwidth, assume the 371 // worst case. 372 downKbps = NetworkCapabilities.minBandwidth(downKbps, 373 underlyingCaps.getLinkDownstreamBandwidthKbps()); 374 upKbps = NetworkCapabilities.minBandwidth(upKbps, 375 underlyingCaps.getLinkUpstreamBandwidthKbps()); 376 // If this underlying network is metered, the VPN is metered (it may cost money 377 // to send packets on this network). 378 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED); 379 // If this underlying network is roaming, the VPN is roaming (the billing structure 380 // is different than the usual, local one). 381 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING); 382 // If this underlying network is congested, the VPN is congested (the current 383 // condition of the network affects the performance of this network). 384 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); 385 // If this network is not suspended, the VPN is not suspended (the VPN 386 // is able to transfer some data). 387 suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); 388 } 389 } 390 if (!hadUnderlyingNetworks) { 391 // No idea what the underlying networks are; assume sane defaults 392 metered = true; 393 roaming = false; 394 congested = false; 395 suspended = false; 396 } 397 398 caps.setTransportTypes(transportTypes); 399 caps.setLinkDownstreamBandwidthKbps(downKbps); 400 caps.setLinkUpstreamBandwidthKbps(upKbps); 401 caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered); 402 caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); 403 caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); 404 caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended); 405 } 406 407 /** 408 * Chooses whether to force all connections to go though VPN. 409 * 410 * Used to enable/disable legacy VPN lockdown. 411 * 412 * This uses the same ip rule mechanism as 413 * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling 414 * that function will be replaced and saved with the always-on state. 415 * 416 * @param lockdown whether to prevent all traffic outside of a VPN. 417 */ setLockdown(boolean lockdown)418 public synchronized void setLockdown(boolean lockdown) { 419 enforceControlPermissionOrInternalCaller(); 420 421 setVpnForcedLocked(lockdown); 422 mLockdown = lockdown; 423 424 // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by 425 // LockdownVpnTracker.isEnabled() which keeps track of its own state. 426 if (mAlwaysOn) { 427 saveAlwaysOnPackage(); 428 } 429 } 430 431 /** 432 * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected. 433 * 434 * @return {@code true} if VPN lockdown is enabled. 435 */ getLockdown()436 public synchronized boolean getLockdown() { 437 return mLockdown; 438 } 439 440 /** 441 * Returns whether VPN is configured as always-on. 442 */ getAlwaysOn()443 public synchronized boolean getAlwaysOn() { 444 return mAlwaysOn; 445 } 446 447 /** 448 * Checks if a VPN app supports always-on mode. 449 * 450 * <p>In order to support the always-on feature, an app has to either have an installed 451 * PlatformVpnProfile, or: 452 * 453 * <ul> 454 * <li>target {@link VERSION_CODES#N API 24} or above, and 455 * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} 456 * meta-data field. 457 * </ul> 458 * 459 * @param packageName the canonical package name of the VPN app 460 * @param keyStore the keystore instance to use for checking if the app has a Platform VPN 461 * profile installed. 462 * @return {@code true} if and only if the VPN app exists and supports always-on mode 463 */ isAlwaysOnPackageSupported(String packageName, @NonNull KeyStore keyStore)464 public boolean isAlwaysOnPackageSupported(String packageName, @NonNull KeyStore keyStore) { 465 enforceSettingsPermission(); 466 467 if (packageName == null) { 468 return false; 469 } 470 471 final long oldId = Binder.clearCallingIdentity(); 472 try { 473 if (getVpnProfilePrivileged(packageName, keyStore) != null) { 474 return true; 475 } 476 } finally { 477 Binder.restoreCallingIdentity(oldId); 478 } 479 480 PackageManager pm = mContext.getPackageManager(); 481 ApplicationInfo appInfo = null; 482 try { 483 appInfo = pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle); 484 } catch (NameNotFoundException unused) { 485 Log.w(TAG, "Can't find \"" + packageName + "\" when checking always-on support"); 486 } 487 if (appInfo == null || appInfo.targetSdkVersion < VERSION_CODES.N) { 488 return false; 489 } 490 491 final Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 492 intent.setPackage(packageName); 493 List<ResolveInfo> services = 494 pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, mUserHandle); 495 if (services == null || services.size() == 0) { 496 return false; 497 } 498 499 for (ResolveInfo rInfo : services) { 500 final Bundle metaData = rInfo.serviceInfo.metaData; 501 if (metaData != null && 502 !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) { 503 return false; 504 } 505 } 506 507 return true; 508 } 509 510 /** 511 * Configures an always-on VPN connection through a specific application. This connection is 512 * automatically granted and persisted after a reboot. 513 * 514 * <p>The designated package should either have a PlatformVpnProfile installed, or declare a 515 * {@link VpnService} in its manifest guarded by {@link 516 * android.Manifest.permission.BIND_VPN_SERVICE}, otherwise the call will fail. 517 * 518 * <p>Note that this method does not check if the VPN app supports always-on mode. The check is 519 * delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this method 520 * in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}. 521 * 522 * @param packageName the package to designate as always-on VPN supplier. 523 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 524 * @param lockdownWhitelist packages to be whitelisted from lockdown. 525 * @param keyStore the Keystore instance to use for checking of PlatformVpnProfile(s) 526 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 527 */ setAlwaysOnPackage( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore)528 public synchronized boolean setAlwaysOnPackage( 529 @Nullable String packageName, 530 boolean lockdown, 531 @Nullable List<String> lockdownWhitelist, 532 @NonNull KeyStore keyStore) { 533 enforceControlPermissionOrInternalCaller(); 534 535 if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist, keyStore)) { 536 saveAlwaysOnPackage(); 537 return true; 538 } 539 return false; 540 } 541 542 /** 543 * Configures an always-on VPN connection through a specific application, the same as {@link 544 * #setAlwaysOnPackage}. 545 * 546 * <p>Does not perform permission checks. Does not persist any of the changes to storage. 547 * 548 * @param packageName the package to designate as always-on VPN supplier. 549 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 550 * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if 551 * {@code lockdown} is {@code true}. Packages must not contain commas. 552 * @param keyStore the system keystore instance to check for profiles 553 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 554 */ 555 @GuardedBy("this") setAlwaysOnPackageInternal( @ullable String packageName, boolean lockdown, @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore)556 private boolean setAlwaysOnPackageInternal( 557 @Nullable String packageName, boolean lockdown, 558 @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore) { 559 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 560 Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); 561 return false; 562 } 563 564 if (lockdownWhitelist != null) { 565 for (String pkg : lockdownWhitelist) { 566 if (pkg.contains(",")) { 567 Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg); 568 return false; 569 } 570 } 571 } 572 573 if (packageName != null) { 574 final VpnProfile profile; 575 final long oldId = Binder.clearCallingIdentity(); 576 try { 577 profile = getVpnProfilePrivileged(packageName, keyStore); 578 } finally { 579 Binder.restoreCallingIdentity(oldId); 580 } 581 582 // Pre-authorize new always-on VPN package. 583 final int grantType = 584 (profile == null) ? VpnManager.TYPE_VPN_SERVICE : VpnManager.TYPE_VPN_PLATFORM; 585 if (!setPackageAuthorization(packageName, grantType)) { 586 return false; 587 } 588 mAlwaysOn = true; 589 } else { 590 packageName = VpnConfig.LEGACY_VPN; 591 mAlwaysOn = false; 592 } 593 594 mLockdown = (mAlwaysOn && lockdown); 595 mLockdownWhitelist = (mLockdown && lockdownWhitelist != null) 596 ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist)) 597 : Collections.emptyList(); 598 599 if (isCurrentPreparedPackage(packageName)) { 600 updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); 601 setVpnForcedLocked(mLockdown); 602 } else { 603 // Prepare this app. The notification will update as a side-effect of updateState(). 604 // It also calls setVpnForcedLocked(). 605 prepareInternal(packageName); 606 } 607 return true; 608 } 609 isNullOrLegacyVpn(String packageName)610 private static boolean isNullOrLegacyVpn(String packageName) { 611 return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName); 612 } 613 614 /** 615 * @return the package name of the VPN controller responsible for always-on VPN, 616 * or {@code null} if none is set or always-on VPN is controlled through 617 * lockdown instead. 618 */ getAlwaysOnPackage()619 public synchronized String getAlwaysOnPackage() { 620 enforceControlPermissionOrInternalCaller(); 621 return (mAlwaysOn ? mPackage : null); 622 } 623 624 /** 625 * @return an immutable list of packages whitelisted from always-on VPN lockdown. 626 */ getLockdownWhitelist()627 public synchronized List<String> getLockdownWhitelist() { 628 return mLockdown ? mLockdownWhitelist : null; 629 } 630 631 /** 632 * Save the always-on package and lockdown config into Settings.Secure 633 */ 634 @GuardedBy("this") saveAlwaysOnPackage()635 private void saveAlwaysOnPackage() { 636 final long token = Binder.clearCallingIdentity(); 637 try { 638 mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP, 639 getAlwaysOnPackage(), mUserHandle); 640 mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 641 (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); 642 mSystemServices.settingsSecurePutStringForUser( 643 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, 644 String.join(",", mLockdownWhitelist), mUserHandle); 645 } finally { 646 Binder.restoreCallingIdentity(token); 647 } 648 } 649 650 /** Load the always-on package and lockdown config from Settings. */ 651 @GuardedBy("this") loadAlwaysOnPackage(@onNull KeyStore keyStore)652 private void loadAlwaysOnPackage(@NonNull KeyStore keyStore) { 653 final long token = Binder.clearCallingIdentity(); 654 try { 655 final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser( 656 Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle); 657 final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser( 658 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0; 659 final String whitelistString = mSystemServices.settingsSecureGetStringForUser( 660 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle); 661 final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString) 662 ? Collections.emptyList() : Arrays.asList(whitelistString.split(",")); 663 setAlwaysOnPackageInternal( 664 alwaysOnPackage, alwaysOnLockdown, whitelistedPackages, keyStore); 665 } finally { 666 Binder.restoreCallingIdentity(token); 667 } 668 } 669 670 /** 671 * Starts the currently selected always-on VPN 672 * 673 * @param keyStore the keyStore instance for looking up PlatformVpnProfile(s) 674 * @return {@code true} if the service was started, the service was already connected, or there 675 * was no always-on VPN to start. {@code false} otherwise. 676 */ startAlwaysOnVpn(@onNull KeyStore keyStore)677 public boolean startAlwaysOnVpn(@NonNull KeyStore keyStore) { 678 final String alwaysOnPackage; 679 synchronized (this) { 680 alwaysOnPackage = getAlwaysOnPackage(); 681 // Skip if there is no service to start. 682 if (alwaysOnPackage == null) { 683 return true; 684 } 685 // Remove always-on VPN if it's not supported. 686 if (!isAlwaysOnPackageSupported(alwaysOnPackage, keyStore)) { 687 setAlwaysOnPackage(null, false, null, keyStore); 688 return false; 689 } 690 // Skip if the service is already established. This isn't bulletproof: it's not bound 691 // until after establish(), so if it's mid-setup onStartCommand will be sent twice, 692 // which may restart the connection. 693 if (getNetworkInfo().isConnected()) { 694 return true; 695 } 696 } 697 698 final long oldId = Binder.clearCallingIdentity(); 699 try { 700 // Prefer VPN profiles, if any exist. 701 VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage, keyStore); 702 if (profile != null) { 703 startVpnProfilePrivileged(profile, alwaysOnPackage, 704 null /* keyStore for private key retrieval - unneeded */); 705 706 // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was 707 // correctly parsed, and the VPN has started running in a different thread. The only 708 // other possibility is that the above call threw an exception, which will be 709 // caught below, and returns false (clearing the always-on VPN). Once started, the 710 // Platform VPN cannot permanently fail, and is resilient to temporary failures. It 711 // will continue retrying until shut down by the user, or always-on is toggled off. 712 return true; 713 } 714 715 // Tell the OS that background services in this app need to be allowed for 716 // a short time, so we can bootstrap the VPN service. 717 DeviceIdleController.LocalService idleController = 718 LocalServices.getService(DeviceIdleController.LocalService.class); 719 idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, 720 VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn"); 721 722 // Start the VPN service declared in the app's manifest. 723 Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); 724 serviceIntent.setPackage(alwaysOnPackage); 725 try { 726 return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null; 727 } catch (RuntimeException e) { 728 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e); 729 return false; 730 } 731 } catch (Exception e) { 732 Log.e(TAG, "Error starting always-on VPN", e); 733 return false; 734 } finally { 735 Binder.restoreCallingIdentity(oldId); 736 } 737 } 738 739 /** 740 * Prepare for a VPN application. This method is designed to solve 741 * race conditions. It first compares the current prepared package 742 * with {@code oldPackage}. If they are the same, the prepared 743 * package is revoked and replaced with {@code newPackage}. If 744 * {@code oldPackage} is {@code null}, the comparison is omitted. 745 * If {@code newPackage} is the same package or {@code null}, the 746 * revocation is omitted. This method returns {@code true} if the 747 * operation is succeeded. 748 * 749 * Legacy VPN is handled specially since it is not a real package. 750 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 751 * it can be revoked by itself. 752 * 753 * The permission checks to verify that the VPN has already been granted 754 * user consent are dependent on the type of the VPN being prepared. See 755 * {@link AppOpsManager#OP_ACTIVATE_VPN} and {@link 756 * AppOpsManager#OP_ACTIVATE_PLATFORM_VPN} for more information. 757 * 758 * Note: when we added VPN pre-consent in 759 * https://android.googlesource.com/platform/frameworks/base/+/0554260 760 * the names oldPackage and newPackage became misleading, because when 761 * an app is pre-consented, we actually prepare oldPackage, not newPackage. 762 * 763 * Their meanings actually are: 764 * 765 * - oldPackage non-null, newPackage null: App calling VpnService#prepare(). 766 * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn(). 767 * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect 768 * and revoke any current app VPN and re-prepare legacy vpn. 769 * 770 * TODO: Rename the variables - or split this method into two - and end this confusion. 771 * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN) 772 * to prepare(oldPackage=null, newPackage=LEGACY_VPN) 773 * 774 * @param oldPackage The package name of the old VPN application 775 * @param newPackage The package name of the new VPN application 776 * @param vpnType The type of VPN being prepared. One of {@link VpnManager.VpnType} Preparing a 777 * platform VPN profile requires only the lesser ACTIVATE_PLATFORM_VPN appop. 778 * @return true if the operation succeeded. 779 */ prepare( String oldPackage, String newPackage, @VpnManager.VpnType int vpnType)780 public synchronized boolean prepare( 781 String oldPackage, String newPackage, @VpnManager.VpnType int vpnType) { 782 if (oldPackage != null) { 783 // Stop an existing always-on VPN from being dethroned by other apps. 784 if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) { 785 return false; 786 } 787 788 // Package is not the same or old package was reinstalled. 789 if (!isCurrentPreparedPackage(oldPackage)) { 790 // The package doesn't match. We return false (to obtain user consent) unless the 791 // user has already consented to that VPN package. 792 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 793 && isVpnPreConsented(mContext, oldPackage, vpnType)) { 794 prepareInternal(oldPackage); 795 return true; 796 } 797 return false; 798 } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 799 && !isVpnPreConsented(mContext, oldPackage, vpnType)) { 800 // Currently prepared VPN is revoked, so unprepare it and return false. 801 prepareInternal(VpnConfig.LEGACY_VPN); 802 return false; 803 } 804 } 805 806 // Return true if we do not need to revoke. 807 if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) && 808 isCurrentPreparedPackage(newPackage))) { 809 return true; 810 } 811 812 // Check that the caller is authorized. 813 enforceControlPermission(); 814 815 // Stop an existing always-on VPN from being dethroned by other apps. 816 if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) { 817 return false; 818 } 819 820 prepareInternal(newPackage); 821 return true; 822 } 823 isCurrentPreparedPackage(String packageName)824 private boolean isCurrentPreparedPackage(String packageName) { 825 // We can't just check that packageName matches mPackage, because if the app was uninstalled 826 // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the 827 // calling package may not be the same as the prepared package. Check both UID and package. 828 return getAppUid(packageName, mUserHandle) == mOwnerUID && mPackage.equals(packageName); 829 } 830 831 /** Prepare the VPN for the given package. Does not perform permission checks. */ 832 @GuardedBy("this") prepareInternal(String newPackage)833 private void prepareInternal(String newPackage) { 834 long token = Binder.clearCallingIdentity(); 835 try { 836 // Reset the interface. 837 if (mInterface != null) { 838 mStatusIntent = null; 839 agentDisconnect(); 840 jniReset(mInterface); 841 mInterface = null; 842 mNetworkCapabilities.setUids(null); 843 } 844 845 // Revoke the connection or stop the VpnRunner. 846 if (mConnection != null) { 847 try { 848 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 849 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 850 } catch (Exception e) { 851 // ignore 852 } 853 mContext.unbindService(mConnection); 854 cleanupVpnStateLocked(); 855 } else if (mVpnRunner != null) { 856 // cleanupVpnStateLocked() is called from mVpnRunner.exit() 857 mVpnRunner.exit(); 858 } 859 860 try { 861 mNetd.denyProtect(mOwnerUID); 862 } catch (Exception e) { 863 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 864 } 865 866 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 867 mPackage = newPackage; 868 mOwnerUID = getAppUid(newPackage, mUserHandle); 869 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); 870 try { 871 mNetd.allowProtect(mOwnerUID); 872 } catch (Exception e) { 873 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 874 } 875 mConfig = null; 876 877 updateState(DetailedState.IDLE, "prepare"); 878 setVpnForcedLocked(mLockdown); 879 } finally { 880 Binder.restoreCallingIdentity(token); 881 } 882 } 883 884 /** Set whether a package has the ability to launch VPNs without user intervention. */ setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType)885 public boolean setPackageAuthorization(String packageName, @VpnManager.VpnType int vpnType) { 886 // Check if the caller is authorized. 887 enforceControlPermissionOrInternalCaller(); 888 889 final int uid = getAppUid(packageName, mUserHandle); 890 if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { 891 // Authorization for nonexistent packages (or fake ones) can't be updated. 892 return false; 893 } 894 895 final long token = Binder.clearCallingIdentity(); 896 try { 897 final int[] toChange; 898 899 // Clear all AppOps if the app is being unauthorized. 900 switch (vpnType) { 901 case VpnManager.TYPE_VPN_NONE: 902 toChange = new int[] { 903 AppOpsManager.OP_ACTIVATE_VPN, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN 904 }; 905 break; 906 case VpnManager.TYPE_VPN_PLATFORM: 907 toChange = new int[] {AppOpsManager.OP_ACTIVATE_PLATFORM_VPN}; 908 break; 909 case VpnManager.TYPE_VPN_SERVICE: 910 toChange = new int[] {AppOpsManager.OP_ACTIVATE_VPN}; 911 break; 912 default: 913 Log.wtf(TAG, "Unrecognized VPN type while granting authorization"); 914 return false; 915 } 916 917 final AppOpsManager appOpMgr = 918 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 919 for (final int appOp : toChange) { 920 appOpMgr.setMode( 921 appOp, 922 uid, 923 packageName, 924 vpnType == VpnManager.TYPE_VPN_NONE 925 ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED); 926 } 927 return true; 928 } catch (Exception e) { 929 Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e); 930 } finally { 931 Binder.restoreCallingIdentity(token); 932 } 933 return false; 934 } 935 isVpnPreConsented(Context context, String packageName, int vpnType)936 private static boolean isVpnPreConsented(Context context, String packageName, int vpnType) { 937 switch (vpnType) { 938 case VpnManager.TYPE_VPN_SERVICE: 939 return isVpnServicePreConsented(context, packageName); 940 case VpnManager.TYPE_VPN_PLATFORM: 941 return isVpnProfilePreConsented(context, packageName); 942 default: 943 return false; 944 } 945 } 946 doesPackageHaveAppop(Context context, String packageName, int appop)947 private static boolean doesPackageHaveAppop(Context context, String packageName, int appop) { 948 final AppOpsManager appOps = 949 (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 950 951 // Verify that the caller matches the given package and has the required permission. 952 return appOps.noteOpNoThrow(appop, Binder.getCallingUid(), packageName) 953 == AppOpsManager.MODE_ALLOWED; 954 } 955 isVpnServicePreConsented(Context context, String packageName)956 private static boolean isVpnServicePreConsented(Context context, String packageName) { 957 return doesPackageHaveAppop(context, packageName, AppOpsManager.OP_ACTIVATE_VPN); 958 } 959 isVpnProfilePreConsented(Context context, String packageName)960 private static boolean isVpnProfilePreConsented(Context context, String packageName) { 961 return doesPackageHaveAppop(context, packageName, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN) 962 || isVpnServicePreConsented(context, packageName); 963 } 964 getAppUid(final String app, final int userHandle)965 private int getAppUid(final String app, final int userHandle) { 966 if (VpnConfig.LEGACY_VPN.equals(app)) { 967 return Process.myUid(); 968 } 969 PackageManager pm = mContext.getPackageManager(); 970 return Binder.withCleanCallingIdentity(() -> { 971 try { 972 return pm.getPackageUidAsUser(app, userHandle); 973 } catch (NameNotFoundException e) { 974 return -1; 975 } 976 }); 977 } 978 979 private boolean doesPackageTargetAtLeastQ(String packageName) { 980 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 981 return true; 982 } 983 PackageManager pm = mContext.getPackageManager(); 984 try { 985 ApplicationInfo appInfo = 986 pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle); 987 return appInfo.targetSdkVersion >= VERSION_CODES.Q; 988 } catch (NameNotFoundException unused) { 989 Log.w(TAG, "Can't find \"" + packageName + "\""); 990 return false; 991 } 992 } 993 994 public NetworkInfo getNetworkInfo() { 995 return mNetworkInfo; 996 } 997 998 public int getNetId() { 999 final NetworkAgent agent = mNetworkAgent; 1000 if (null == agent) return NETID_UNSET; 1001 final Network network = agent.getNetwork(); 1002 if (null == network) return NETID_UNSET; 1003 return network.netId; 1004 } 1005 1006 private LinkProperties makeLinkProperties() { 1007 boolean allowIPv4 = mConfig.allowIPv4; 1008 boolean allowIPv6 = mConfig.allowIPv6; 1009 1010 LinkProperties lp = new LinkProperties(); 1011 1012 lp.setInterfaceName(mInterface); 1013 1014 if (mConfig.addresses != null) { 1015 for (LinkAddress address : mConfig.addresses) { 1016 lp.addLinkAddress(address); 1017 allowIPv4 |= address.getAddress() instanceof Inet4Address; 1018 allowIPv6 |= address.getAddress() instanceof Inet6Address; 1019 } 1020 } 1021 1022 if (mConfig.routes != null) { 1023 for (RouteInfo route : mConfig.routes) { 1024 lp.addRoute(route); 1025 InetAddress address = route.getDestination().getAddress(); 1026 allowIPv4 |= address instanceof Inet4Address; 1027 allowIPv6 |= address instanceof Inet6Address; 1028 } 1029 } 1030 1031 if (mConfig.dnsServers != null) { 1032 for (String dnsServer : mConfig.dnsServers) { 1033 InetAddress address = InetAddress.parseNumericAddress(dnsServer); 1034 lp.addDnsServer(address); 1035 allowIPv4 |= address instanceof Inet4Address; 1036 allowIPv6 |= address instanceof Inet6Address; 1037 } 1038 } 1039 1040 lp.setHttpProxy(mConfig.proxyInfo); 1041 1042 if (!allowIPv4) { 1043 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); 1044 } 1045 if (!allowIPv6) { 1046 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); 1047 } 1048 1049 // Concatenate search domains into a string. 1050 StringBuilder buffer = new StringBuilder(); 1051 if (mConfig.searchDomains != null) { 1052 for (String domain : mConfig.searchDomains) { 1053 buffer.append(domain).append(' '); 1054 } 1055 } 1056 lp.setDomains(buffer.toString().trim()); 1057 1058 if (mConfig.mtu > 0) { 1059 lp.setMtu(mConfig.mtu); 1060 } 1061 1062 // TODO: Stop setting the MTU in jniCreate 1063 1064 return lp; 1065 } 1066 1067 /** 1068 * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without 1069 * registering a new NetworkAgent. This is not always possible if the new VPN configuration 1070 * has certain changes, in which case this method would just return {@code false}. 1071 */ 1072 private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { 1073 // NetworkAgentConfig cannot be updated without registering a new NetworkAgent. 1074 if (oldConfig.allowBypass != mConfig.allowBypass) { 1075 Log.i(TAG, "Handover not possible due to changes to allowBypass"); 1076 return false; 1077 } 1078 1079 // TODO: we currently do not support seamless handover if the allowed or disallowed 1080 // applications have changed. Consider diffing UID ranges and only applying the delta. 1081 if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) || 1082 !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) { 1083 Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps"); 1084 return false; 1085 } 1086 1087 agent.sendLinkProperties(makeLinkProperties()); 1088 return true; 1089 } 1090 1091 private void agentConnect() { 1092 LinkProperties lp = makeLinkProperties(); 1093 1094 // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel 1095 // that falls back to the default network, which by definition provides INTERNET (unless 1096 // there is no default network, in which case none of this matters in any sense). 1097 // Also, always setting the INTERNET bit guarantees that when a VPN applies to an app, 1098 // the VPN will always be reported as the network by getDefaultNetwork and callbacks 1099 // registered with registerDefaultNetworkCallback. This in turn protects the invariant 1100 // that an app calling ConnectivityManager#bindProcessToNetwork(getDefaultNetwork()) 1101 // behaves the same as when it uses the default network. 1102 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 1103 1104 mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); 1105 1106 NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); 1107 networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown; 1108 1109 mNetworkCapabilities.setOwnerUid(mOwnerUID); 1110 mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID}); 1111 mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle, 1112 mConfig.allowedApplications, mConfig.disallowedApplications)); 1113 long token = Binder.clearCallingIdentity(); 1114 try { 1115 mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */, 1116 mNetworkInfo, mNetworkCapabilities, lp, 1117 ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig, 1118 NetworkProvider.ID_VPN) { 1119 @Override 1120 public void unwanted() { 1121 // We are user controlled, not driven by NetworkRequest. 1122 } 1123 }; 1124 } finally { 1125 Binder.restoreCallingIdentity(token); 1126 } 1127 mNetworkInfo.setIsAvailable(true); 1128 updateState(DetailedState.CONNECTED, "agentConnect"); 1129 } 1130 1131 private boolean canHaveRestrictedProfile(int userId) { 1132 long token = Binder.clearCallingIdentity(); 1133 try { 1134 return UserManager.get(mContext).canHaveRestrictedProfile(userId); 1135 } finally { 1136 Binder.restoreCallingIdentity(token); 1137 } 1138 } 1139 1140 private void agentDisconnect(NetworkAgent networkAgent) { 1141 if (networkAgent != null) { 1142 NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); 1143 networkInfo.setIsAvailable(false); 1144 networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 1145 networkAgent.sendNetworkInfo(networkInfo); 1146 } 1147 } 1148 1149 private void agentDisconnect() { 1150 if (mNetworkInfo.isConnected()) { 1151 mNetworkInfo.setIsAvailable(false); 1152 updateState(DetailedState.DISCONNECTED, "agentDisconnect"); 1153 mNetworkAgent = null; 1154 } 1155 } 1156 1157 /** 1158 * Establish a VPN network and return the file descriptor of the VPN interface. This methods 1159 * returns {@code null} if the application is revoked or not prepared. 1160 * 1161 * <p>This method supports ONLY VpnService-based VPNs. For Platform VPNs, see {@link 1162 * provisionVpnProfile} and {@link startVpnProfile} 1163 * 1164 * @param config The parameters to configure the network. 1165 * @return The file descriptor of the VPN interface. 1166 */ 1167 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 1168 // Check if the caller is already prepared. 1169 if (Binder.getCallingUid() != mOwnerUID) { 1170 return null; 1171 } 1172 // Check to ensure consent hasn't been revoked since we were prepared. 1173 if (!isVpnServicePreConsented(mContext, mPackage)) { 1174 return null; 1175 } 1176 // Check if the service is properly declared. 1177 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 1178 intent.setClassName(mPackage, config.user); 1179 long token = Binder.clearCallingIdentity(); 1180 try { 1181 // Restricted users are not allowed to create VPNs, they are tied to Owner 1182 enforceNotRestrictedUser(); 1183 1184 ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, 1185 null, 0, mUserHandle); 1186 if (info == null) { 1187 throw new SecurityException("Cannot find " + config.user); 1188 } 1189 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 1190 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 1191 } 1192 } catch (RemoteException e) { 1193 throw new SecurityException("Cannot find " + config.user); 1194 } finally { 1195 Binder.restoreCallingIdentity(token); 1196 } 1197 1198 // Save the old config in case we need to go back. 1199 VpnConfig oldConfig = mConfig; 1200 String oldInterface = mInterface; 1201 Connection oldConnection = mConnection; 1202 NetworkAgent oldNetworkAgent = mNetworkAgent; 1203 Set<UidRange> oldUsers = mNetworkCapabilities.getUids(); 1204 1205 // Configure the interface. Abort if any of these steps fails. 1206 ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); 1207 try { 1208 String interfaze = jniGetName(tun.getFd()); 1209 1210 // TEMP use the old jni calls until there is support for netd address setting 1211 StringBuilder builder = new StringBuilder(); 1212 for (LinkAddress address : config.addresses) { 1213 builder.append(" "); 1214 builder.append(address); 1215 } 1216 if (jniSetAddresses(interfaze, builder.toString()) < 1) { 1217 throw new IllegalArgumentException("At least one address must be specified"); 1218 } 1219 Connection connection = new Connection(); 1220 if (!mContext.bindServiceAsUser(intent, connection, 1221 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 1222 new UserHandle(mUserHandle))) { 1223 throw new IllegalStateException("Cannot bind " + config.user); 1224 } 1225 1226 mConnection = connection; 1227 mInterface = interfaze; 1228 1229 // Fill more values. 1230 config.user = mPackage; 1231 config.interfaze = mInterface; 1232 config.startTime = SystemClock.elapsedRealtime(); 1233 mConfig = config; 1234 1235 // Set up forwarding and DNS rules. 1236 // First attempt to do a seamless handover that only changes the interface name and 1237 // parameters. If that fails, disconnect. 1238 if (oldConfig != null 1239 && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) { 1240 // Keep mNetworkAgent unchanged 1241 } else { 1242 mNetworkAgent = null; 1243 updateState(DetailedState.CONNECTING, "establish"); 1244 // Set up forwarding and DNS rules. 1245 agentConnect(); 1246 // Remove the old tun's user forwarding rules 1247 // The new tun's user rules have already been added above so they will take over 1248 // as rules are deleted. This prevents data leakage as the rules are moved over. 1249 agentDisconnect(oldNetworkAgent); 1250 } 1251 1252 if (oldConnection != null) { 1253 mContext.unbindService(oldConnection); 1254 } 1255 1256 if (oldInterface != null && !oldInterface.equals(interfaze)) { 1257 jniReset(oldInterface); 1258 } 1259 1260 try { 1261 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); 1262 } catch (IOException e) { 1263 throw new IllegalStateException( 1264 "Cannot set tunnel's fd as blocking=" + config.blocking, e); 1265 } 1266 } catch (RuntimeException e) { 1267 IoUtils.closeQuietly(tun); 1268 // If this is not seamless handover, disconnect partially-established network when error 1269 // occurs. 1270 if (oldNetworkAgent != mNetworkAgent) { 1271 agentDisconnect(); 1272 } 1273 // restore old state 1274 mConfig = oldConfig; 1275 mConnection = oldConnection; 1276 mNetworkCapabilities.setUids(oldUsers); 1277 mNetworkAgent = oldNetworkAgent; 1278 mInterface = oldInterface; 1279 throw e; 1280 } 1281 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 1282 return tun; 1283 } 1284 1285 private boolean isRunningLocked() { 1286 return mNetworkAgent != null && mInterface != null; 1287 } 1288 1289 // Returns true if the VPN has been established and the calling UID is its owner. Used to check 1290 // that a call to mutate VPN state is admissible. 1291 @VisibleForTesting 1292 protected boolean isCallerEstablishedOwnerLocked() { 1293 return isRunningLocked() && Binder.getCallingUid() == mOwnerUID; 1294 } 1295 1296 // Note: Return type guarantees results are deduped and sorted, which callers require. 1297 private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) { 1298 SortedSet<Integer> uids = new TreeSet<>(); 1299 for (String app : packageNames) { 1300 int uid = getAppUid(app, userHandle); 1301 if (uid != -1) uids.add(uid); 1302 } 1303 return uids; 1304 } 1305 1306 /** 1307 * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs 1308 * associated with one user, and any restricted profiles attached to that user. 1309 * 1310 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 1311 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 1312 * in each user and profile will be included. 1313 * 1314 * @param userHandle The userId to create UID ranges for along with any of its restricted 1315 * profiles. 1316 * @param allowedApplications (optional) whitelist of applications to include. 1317 * @param disallowedApplications (optional) blacklist of applications to exclude. 1318 */ 1319 @VisibleForTesting 1320 Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle, 1321 @Nullable List<String> allowedApplications, 1322 @Nullable List<String> disallowedApplications) { 1323 final Set<UidRange> ranges = new ArraySet<>(); 1324 1325 // Assign the top-level user to the set of ranges 1326 addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications); 1327 1328 // If the user can have restricted profiles, assign all its restricted profiles too 1329 if (canHaveRestrictedProfile(userHandle)) { 1330 final long token = Binder.clearCallingIdentity(); 1331 List<UserInfo> users; 1332 try { 1333 users = UserManager.get(mContext).getUsers(true); 1334 } finally { 1335 Binder.restoreCallingIdentity(token); 1336 } 1337 for (UserInfo user : users) { 1338 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) { 1339 addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications); 1340 } 1341 } 1342 } 1343 return ranges; 1344 } 1345 1346 /** 1347 * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs 1348 * associated with one user. 1349 * 1350 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 1351 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 1352 * in the user will be included. 1353 * 1354 * @param ranges {@link Set} of {@link UidRange}s to which to add. 1355 * @param userHandle The userId to add to {@param ranges}. 1356 * @param allowedApplications (optional) whitelist of applications to include. 1357 * @param disallowedApplications (optional) blacklist of applications to exclude. 1358 */ 1359 @VisibleForTesting 1360 void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle, 1361 @Nullable List<String> allowedApplications, 1362 @Nullable List<String> disallowedApplications) { 1363 if (allowedApplications != null) { 1364 // Add ranges covering all UIDs for allowedApplications. 1365 int start = -1, stop = -1; 1366 for (int uid : getAppsUids(allowedApplications, userHandle)) { 1367 if (start == -1) { 1368 start = uid; 1369 } else if (uid != stop + 1) { 1370 ranges.add(new UidRange(start, stop)); 1371 start = uid; 1372 } 1373 stop = uid; 1374 } 1375 if (start != -1) ranges.add(new UidRange(start, stop)); 1376 } else if (disallowedApplications != null) { 1377 // Add all ranges for user skipping UIDs for disallowedApplications. 1378 final UidRange userRange = UidRange.createForUser(userHandle); 1379 int start = userRange.start; 1380 for (int uid : getAppsUids(disallowedApplications, userHandle)) { 1381 if (uid == start) { 1382 start++; 1383 } else { 1384 ranges.add(new UidRange(start, uid - 1)); 1385 start = uid + 1; 1386 } 1387 } 1388 if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop)); 1389 } else { 1390 // Add all UIDs for the user. 1391 ranges.add(UidRange.createForUser(userHandle)); 1392 } 1393 } 1394 1395 // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that 1396 // apply to userHandle. 1397 static private List<UidRange> uidRangesForUser(int userHandle, Set<UidRange> existingRanges) { 1398 // UidRange#createForUser returns the entire range of UIDs available to a macro-user. 1399 // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE} 1400 final UidRange userRange = UidRange.createForUser(userHandle); 1401 final List<UidRange> ranges = new ArrayList<>(); 1402 for (UidRange range : existingRanges) { 1403 if (userRange.containsRange(range)) { 1404 ranges.add(range); 1405 } 1406 } 1407 return ranges; 1408 } 1409 1410 /** 1411 * Updates UID ranges for this VPN and also updates its internal capabilities. 1412 * 1413 * <p>Should be called on primary ConnectivityService thread. 1414 */ 1415 public void onUserAdded(int userHandle) { 1416 // If the user is restricted tie them to the parent user's VPN 1417 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 1418 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 1419 synchronized(Vpn.this) { 1420 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); 1421 if (existingRanges != null) { 1422 try { 1423 addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications, 1424 mConfig.disallowedApplications); 1425 // ConnectivityService will call {@link #updateCapabilities} and apply 1426 // those for VPN network. 1427 mNetworkCapabilities.setUids(existingRanges); 1428 } catch (Exception e) { 1429 Log.wtf(TAG, "Failed to add restricted user to owner", e); 1430 } 1431 } 1432 setVpnForcedLocked(mLockdown); 1433 } 1434 } 1435 } 1436 1437 /** 1438 * Updates UID ranges for this VPN and also updates its capabilities. 1439 * 1440 * <p>Should be called on primary ConnectivityService thread. 1441 */ 1442 public void onUserRemoved(int userHandle) { 1443 // clean up if restricted 1444 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 1445 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 1446 synchronized(Vpn.this) { 1447 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); 1448 if (existingRanges != null) { 1449 try { 1450 final List<UidRange> removedRanges = 1451 uidRangesForUser(userHandle, existingRanges); 1452 existingRanges.removeAll(removedRanges); 1453 // ConnectivityService will call {@link #updateCapabilities} and 1454 // apply those for VPN network. 1455 mNetworkCapabilities.setUids(existingRanges); 1456 } catch (Exception e) { 1457 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 1458 } 1459 } 1460 setVpnForcedLocked(mLockdown); 1461 } 1462 } 1463 } 1464 1465 /** 1466 * Called when the user associated with this VPN has just been stopped. 1467 */ 1468 public synchronized void onUserStopped() { 1469 // Switch off networking lockdown (if it was enabled) 1470 setLockdown(false); 1471 mAlwaysOn = false; 1472 1473 // Quit any active connections 1474 agentDisconnect(); 1475 } 1476 1477 /** 1478 * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN 1479 * service app itself and whitelisted packages, to only sockets that have had {@code protect()} 1480 * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the 1481 * kernel. 1482 * 1483 * The exception for the VPN UID isn't technically necessary -- setup should use protected 1484 * sockets -- but in practice it saves apps that don't protect their sockets from breaking. 1485 * 1486 * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to 1487 * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}. 1488 * 1489 * @param enforce {@code true} to require that all traffic under the jurisdiction of this 1490 * {@link Vpn} goes through a VPN connection or is blocked until one is 1491 * available, {@code false} to lift the requirement. 1492 * 1493 * @see #mBlockedUidsAsToldToNetd 1494 */ 1495 @GuardedBy("this") 1496 private void setVpnForcedLocked(boolean enforce) { 1497 final List<String> exemptedPackages; 1498 if (isNullOrLegacyVpn(mPackage)) { 1499 exemptedPackages = null; 1500 } else { 1501 exemptedPackages = new ArrayList<>(mLockdownWhitelist); 1502 exemptedPackages.add(mPackage); 1503 } 1504 final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd); 1505 1506 final Set<UidRange> rangesToTellNetdToAdd; 1507 if (enforce) { 1508 final Set<UidRange> rangesThatShouldBeBlocked = 1509 createUserAndRestrictedProfilesRanges(mUserHandle, 1510 /* allowedApplications */ null, 1511 /* disallowedApplications */ exemptedPackages); 1512 1513 // The UID range of the first user (0-99999) would block the IPSec traffic, which comes 1514 // directly from the kernel and is marked as uid=0. So we adjust the range to allow 1515 // it through (b/69873852). 1516 for (UidRange range : rangesThatShouldBeBlocked) { 1517 if (range.start == 0) { 1518 rangesThatShouldBeBlocked.remove(range); 1519 if (range.stop != 0) { 1520 rangesThatShouldBeBlocked.add(new UidRange(1, range.stop)); 1521 } 1522 } 1523 } 1524 1525 rangesToTellNetdToRemove.removeAll(rangesThatShouldBeBlocked); 1526 rangesToTellNetdToAdd = rangesThatShouldBeBlocked; 1527 // The ranges to tell netd to add are the ones that should be blocked minus the 1528 // ones it already knows to block. Note that this will change the contents of 1529 // rangesThatShouldBeBlocked, but the list of ranges that should be blocked is 1530 // not used after this so it's fine to destroy it. 1531 rangesToTellNetdToAdd.removeAll(mBlockedUidsAsToldToNetd); 1532 } else { 1533 rangesToTellNetdToAdd = Collections.emptySet(); 1534 } 1535 1536 // If mBlockedUidsAsToldToNetd used to be empty, this will always be a no-op. 1537 setAllowOnlyVpnForUids(false, rangesToTellNetdToRemove); 1538 // If nothing should be blocked now, this will now be a no-op. 1539 setAllowOnlyVpnForUids(true, rangesToTellNetdToAdd); 1540 } 1541 1542 /** 1543 * Tell netd to add or remove a list of {@link UidRange}s to the list of UIDs that are only 1544 * allowed to make connections through sockets that have had {@code protect()} called on them. 1545 * 1546 * @param enforce {@code true} to add to the blacklist, {@code false} to remove. 1547 * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is 1548 * {@code true}) or to remove. 1549 * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, 1550 * including added ranges that already existed or removed ones that didn't. 1551 */ 1552 @GuardedBy("this") 1553 private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) { 1554 if (ranges.size() == 0) { 1555 return true; 1556 } 1557 final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]); 1558 try { 1559 mNetd.setAllowOnlyVpnForUids(enforce, rangesArray); 1560 } catch (RemoteException | RuntimeException e) { 1561 Log.e(TAG, "Updating blocked=" + enforce 1562 + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e); 1563 return false; 1564 } 1565 if (enforce) { 1566 mBlockedUidsAsToldToNetd.addAll(ranges); 1567 } else { 1568 mBlockedUidsAsToldToNetd.removeAll(ranges); 1569 } 1570 return true; 1571 } 1572 1573 /** 1574 * Return the configuration of the currently running VPN. 1575 */ 1576 public VpnConfig getVpnConfig() { 1577 enforceControlPermission(); 1578 return mConfig; 1579 } 1580 1581 @Deprecated 1582 public synchronized void interfaceStatusChanged(String iface, boolean up) { 1583 try { 1584 mObserver.interfaceStatusChanged(iface, up); 1585 } catch (RemoteException e) { 1586 // ignored; target is local 1587 } 1588 } 1589 1590 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 1591 @Override 1592 public void interfaceStatusChanged(String interfaze, boolean up) { 1593 synchronized (Vpn.this) { 1594 if (!up && mVpnRunner != null && mVpnRunner instanceof LegacyVpnRunner) { 1595 ((LegacyVpnRunner) mVpnRunner).exitIfOuterInterfaceIs(interfaze); 1596 } 1597 } 1598 } 1599 1600 @Override 1601 public void interfaceRemoved(String interfaze) { 1602 synchronized (Vpn.this) { 1603 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 1604 if (mConnection != null) { 1605 mContext.unbindService(mConnection); 1606 cleanupVpnStateLocked(); 1607 } else if (mVpnRunner != null) { 1608 // cleanupVpnStateLocked() is called from mVpnRunner.exit() 1609 mVpnRunner.exit(); 1610 } 1611 } 1612 } 1613 } 1614 }; 1615 1616 private void cleanupVpnStateLocked() { 1617 mStatusIntent = null; 1618 mNetworkCapabilities.setUids(null); 1619 mConfig = null; 1620 mInterface = null; 1621 1622 // Unconditionally clear both VpnService and VpnRunner fields. 1623 mVpnRunner = null; 1624 mConnection = null; 1625 agentDisconnect(); 1626 } 1627 1628 private void enforceControlPermission() { 1629 mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller"); 1630 } 1631 1632 private void enforceControlPermissionOrInternalCaller() { 1633 // Require the caller to be either an application with CONTROL_VPN permission or a process 1634 // in the system server. 1635 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN, 1636 "Unauthorized Caller"); 1637 } 1638 1639 private void enforceSettingsPermission() { 1640 mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_SETTINGS, 1641 "Unauthorized Caller"); 1642 } 1643 1644 private class Connection implements ServiceConnection { 1645 private IBinder mService; 1646 1647 @Override 1648 public void onServiceConnected(ComponentName name, IBinder service) { 1649 mService = service; 1650 } 1651 1652 @Override 1653 public void onServiceDisconnected(ComponentName name) { 1654 mService = null; 1655 } 1656 } 1657 1658 private void prepareStatusIntent() { 1659 final long token = Binder.clearCallingIdentity(); 1660 try { 1661 mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext); 1662 } finally { 1663 Binder.restoreCallingIdentity(token); 1664 } 1665 } 1666 1667 public synchronized boolean addAddress(String address, int prefixLength) { 1668 if (!isCallerEstablishedOwnerLocked()) { 1669 return false; 1670 } 1671 boolean success = jniAddAddress(mInterface, address, prefixLength); 1672 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1673 return success; 1674 } 1675 1676 public synchronized boolean removeAddress(String address, int prefixLength) { 1677 if (!isCallerEstablishedOwnerLocked()) { 1678 return false; 1679 } 1680 boolean success = jniDelAddress(mInterface, address, prefixLength); 1681 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1682 return success; 1683 } 1684 1685 /** 1686 * Updates underlying network set. 1687 * 1688 * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from 1689 * ConnectivityService thread to get updated capabilities. 1690 */ 1691 public synchronized boolean setUnderlyingNetworks(Network[] networks) { 1692 if (!isCallerEstablishedOwnerLocked()) { 1693 return false; 1694 } 1695 if (networks == null) { 1696 mConfig.underlyingNetworks = null; 1697 } else { 1698 mConfig.underlyingNetworks = new Network[networks.length]; 1699 for (int i = 0; i < networks.length; ++i) { 1700 if (networks[i] == null) { 1701 mConfig.underlyingNetworks[i] = null; 1702 } else { 1703 mConfig.underlyingNetworks[i] = new Network(networks[i].netId); 1704 } 1705 } 1706 } 1707 return true; 1708 } 1709 1710 public synchronized Network[] getUnderlyingNetworks() { 1711 if (!isRunningLocked()) { 1712 return null; 1713 } 1714 return mConfig.underlyingNetworks; 1715 } 1716 1717 /** 1718 * This method should only be called by ConnectivityService because it doesn't 1719 * have enough data to fill VpnInfo.primaryUnderlyingIface field. 1720 */ 1721 public synchronized VpnInfo getVpnInfo() { 1722 if (!isRunningLocked()) { 1723 return null; 1724 } 1725 1726 VpnInfo info = new VpnInfo(); 1727 info.ownerUid = mOwnerUID; 1728 info.vpnIface = mInterface; 1729 return info; 1730 } 1731 1732 public synchronized boolean appliesToUid(int uid) { 1733 if (!isRunningLocked()) { 1734 return false; 1735 } 1736 return mNetworkCapabilities.appliesToUid(uid); 1737 } 1738 1739 /** 1740 * Gets the currently running App-based VPN type 1741 * 1742 * @return the {@link VpnManager.VpnType}. {@link VpnManager.TYPE_VPN_NONE} if not running an 1743 * app-based VPN. While VpnService-based VPNs are always app VPNs and LegacyVpn is always 1744 * Settings-based, the Platform VPNs can be initiated by both apps and Settings. 1745 */ 1746 public synchronized int getActiveAppVpnType() { 1747 if (VpnConfig.LEGACY_VPN.equals(mPackage)) { 1748 return VpnManager.TYPE_VPN_NONE; 1749 } 1750 1751 if (mVpnRunner != null && mVpnRunner instanceof IkeV2VpnRunner) { 1752 return VpnManager.TYPE_VPN_PLATFORM; 1753 } else { 1754 return VpnManager.TYPE_VPN_SERVICE; 1755 } 1756 } 1757 1758 /** 1759 * @param uid The target uid. 1760 * 1761 * @return {@code true} if {@code uid} is included in one of the mBlockedUidsAsToldToNetd 1762 * ranges and the VPN is not connected, or if the VPN is connected but does not apply to 1763 * the {@code uid}. 1764 * 1765 * @apiNote This method don't check VPN lockdown status. 1766 * @see #mBlockedUidsAsToldToNetd 1767 */ 1768 public synchronized boolean isBlockingUid(int uid) { 1769 if (mNetworkInfo.isConnected()) { 1770 return !appliesToUid(uid); 1771 } else { 1772 return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid); 1773 } 1774 } 1775 1776 private void updateAlwaysOnNotification(DetailedState networkState) { 1777 final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); 1778 1779 final UserHandle user = UserHandle.of(mUserHandle); 1780 final long token = Binder.clearCallingIdentity(); 1781 try { 1782 final NotificationManager notificationManager = NotificationManager.from(mContext); 1783 if (!visible) { 1784 notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user); 1785 return; 1786 } 1787 final Intent intent = new Intent(); 1788 intent.setComponent(ComponentName.unflattenFromString(mContext.getString( 1789 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))); 1790 intent.putExtra("lockdown", mLockdown); 1791 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1792 final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser( 1793 intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user); 1794 final Notification.Builder builder = 1795 new Notification.Builder(mContext, SystemNotificationChannels.VPN) 1796 .setSmallIcon(R.drawable.vpn_connected) 1797 .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected)) 1798 .setContentText(mContext.getString(R.string.vpn_lockdown_config)) 1799 .setContentIntent(configIntent) 1800 .setCategory(Notification.CATEGORY_SYSTEM) 1801 .setVisibility(Notification.VISIBILITY_PUBLIC) 1802 .setOngoing(true) 1803 .setColor(mContext.getColor(R.color.system_notification_accent_color)); 1804 notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, 1805 builder.build(), user); 1806 } finally { 1807 Binder.restoreCallingIdentity(token); 1808 } 1809 } 1810 1811 /** 1812 * Facade for system service calls that change, or depend on, state outside of 1813 * {@link ConnectivityService} and have hard-to-mock interfaces. 1814 * 1815 * @see com.android.server.connectivity.VpnTest 1816 */ 1817 @VisibleForTesting 1818 public static class SystemServices { 1819 private final Context mContext; 1820 1821 public SystemServices(@NonNull Context context) { 1822 mContext = context; 1823 } 1824 1825 /** 1826 * @see PendingIntent#getActivityAsUser() 1827 */ 1828 public PendingIntent pendingIntentGetActivityAsUser( 1829 Intent intent, int flags, UserHandle user) { 1830 return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags, 1831 null /*options*/, user); 1832 } 1833 1834 /** 1835 * @see Settings.Secure#putStringForUser 1836 */ 1837 public void settingsSecurePutStringForUser(String key, String value, int userId) { 1838 Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId); 1839 } 1840 1841 /** 1842 * @see Settings.Secure#putIntForUser 1843 */ 1844 public void settingsSecurePutIntForUser(String key, int value, int userId) { 1845 Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId); 1846 } 1847 1848 /** 1849 * @see Settings.Secure#getStringForUser 1850 */ 1851 public String settingsSecureGetStringForUser(String key, int userId) { 1852 return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId); 1853 } 1854 1855 /** 1856 * @see Settings.Secure#getIntForUser 1857 */ 1858 public int settingsSecureGetIntForUser(String key, int def, int userId) { 1859 return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId); 1860 } 1861 1862 public boolean isCallerSystem() { 1863 return Binder.getCallingUid() == Process.SYSTEM_UID; 1864 } 1865 } 1866 1867 private native int jniCreate(int mtu); 1868 private native String jniGetName(int tun); 1869 private native int jniSetAddresses(String interfaze, String addresses); 1870 private native void jniReset(String interfaze); 1871 private native int jniCheck(String interfaze); 1872 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); 1873 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 1874 1875 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 1876 for (RouteInfo route : prop.getAllRoutes()) { 1877 // Currently legacy VPN only works on IPv4. 1878 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 1879 return route; 1880 } 1881 } 1882 1883 throw new IllegalStateException("Unable to find IPv4 default gateway"); 1884 } 1885 1886 private void enforceNotRestrictedUser() { 1887 Binder.withCleanCallingIdentity(() -> { 1888 final UserManager mgr = UserManager.get(mContext); 1889 final UserInfo user = mgr.getUserInfo(mUserHandle); 1890 1891 if (user.isRestricted()) { 1892 throw new SecurityException("Restricted users cannot configure VPNs"); 1893 } 1894 }); 1895 } 1896 1897 /** 1898 * Start legacy VPN, controlling native daemons as needed. Creates a 1899 * secondary thread to perform connection work, returning quickly. 1900 * 1901 * Should only be called to respond to Binder requests as this enforces caller permission. Use 1902 * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the 1903 * permission check only when the caller is trusted (or the call is initiated by the system). 1904 */ 1905 public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) { 1906 enforceControlPermission(); 1907 long token = Binder.clearCallingIdentity(); 1908 try { 1909 startLegacyVpnPrivileged(profile, keyStore, egress); 1910 } finally { 1911 Binder.restoreCallingIdentity(token); 1912 } 1913 } 1914 1915 /** 1916 * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check 1917 * permissions under the assumption that the caller is the system. 1918 * 1919 * Callers are responsible for checking permissions if needed. 1920 */ 1921 public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore, 1922 LinkProperties egress) { 1923 UserManager mgr = UserManager.get(mContext); 1924 UserInfo user = mgr.getUserInfo(mUserHandle); 1925 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, 1926 new UserHandle(mUserHandle))) { 1927 throw new SecurityException("Restricted users cannot establish VPNs"); 1928 } 1929 1930 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 1931 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 1932 final String iface = ipv4DefaultRoute.getInterface(); 1933 1934 // Load certificates. 1935 String privateKey = ""; 1936 String userCert = ""; 1937 String caCert = ""; 1938 String serverCert = ""; 1939 if (!profile.ipsecUserCert.isEmpty()) { 1940 privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; 1941 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 1942 userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1943 } 1944 if (!profile.ipsecCaCert.isEmpty()) { 1945 byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 1946 caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1947 } 1948 if (!profile.ipsecServerCert.isEmpty()) { 1949 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 1950 serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1951 } 1952 if (userCert == null || caCert == null || serverCert == null) { 1953 throw new IllegalStateException("Cannot load credentials"); 1954 } 1955 1956 // Prepare arguments for racoon. 1957 String[] racoon = null; 1958 switch (profile.type) { 1959 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 1960 // Secret key is still just the alias (not the actual private key). The private key 1961 // is retrieved from the KeyStore during conversion of the VpnProfile to an 1962 // Ikev2VpnProfile. 1963 profile.ipsecSecret = Ikev2VpnProfile.PREFIX_KEYSTORE_ALIAS + privateKey; 1964 profile.ipsecUserCert = userCert; 1965 // Fallthrough 1966 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 1967 profile.ipsecCaCert = caCert; 1968 1969 // Start VPN profile 1970 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); 1971 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore); 1972 return; 1973 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 1974 // Ikev2VpnProfiles expect a base64-encoded preshared key. 1975 profile.ipsecSecret = 1976 Ikev2VpnProfile.encodeForIpsecSecret(profile.ipsecSecret.getBytes()); 1977 1978 // Start VPN profile 1979 profile.setAllowedAlgorithms(Ikev2VpnProfile.DEFAULT_ALGORITHMS); 1980 startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore); 1981 return; 1982 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 1983 racoon = new String[] { 1984 iface, profile.server, "udppsk", profile.ipsecIdentifier, 1985 profile.ipsecSecret, "1701", 1986 }; 1987 break; 1988 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 1989 racoon = new String[] { 1990 iface, profile.server, "udprsa", privateKey, userCert, 1991 caCert, serverCert, "1701", 1992 }; 1993 break; 1994 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 1995 racoon = new String[] { 1996 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 1997 profile.ipsecSecret, profile.username, profile.password, "", gateway, 1998 }; 1999 break; 2000 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 2001 racoon = new String[] { 2002 iface, profile.server, "xauthrsa", privateKey, userCert, 2003 caCert, serverCert, profile.username, profile.password, "", gateway, 2004 }; 2005 break; 2006 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 2007 racoon = new String[] { 2008 iface, profile.server, "hybridrsa", 2009 caCert, serverCert, profile.username, profile.password, "", gateway, 2010 }; 2011 break; 2012 } 2013 2014 // Prepare arguments for mtpd. 2015 String[] mtpd = null; 2016 switch (profile.type) { 2017 case VpnProfile.TYPE_PPTP: 2018 mtpd = new String[] { 2019 iface, "pptp", profile.server, "1723", 2020 "name", profile.username, "password", profile.password, 2021 "linkname", "vpn", "refuse-eap", "nodefaultroute", 2022 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 2023 (profile.mppe ? "+mppe" : "nomppe"), 2024 }; 2025 break; 2026 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 2027 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 2028 mtpd = new String[] { 2029 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 2030 "name", profile.username, "password", profile.password, 2031 "linkname", "vpn", "refuse-eap", "nodefaultroute", 2032 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 2033 }; 2034 break; 2035 } 2036 2037 VpnConfig config = new VpnConfig(); 2038 config.legacy = true; 2039 config.user = profile.key; 2040 config.interfaze = iface; 2041 config.session = profile.name; 2042 config.isMetered = false; 2043 config.proxyInfo = profile.proxy; 2044 2045 config.addLegacyRoutes(profile.routes); 2046 if (!profile.dnsServers.isEmpty()) { 2047 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 2048 } 2049 if (!profile.searchDomains.isEmpty()) { 2050 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 2051 } 2052 startLegacyVpn(config, racoon, mtpd, profile); 2053 } 2054 2055 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, 2056 VpnProfile profile) { 2057 stopVpnRunnerPrivileged(); 2058 2059 // Prepare for the new request. 2060 prepareInternal(VpnConfig.LEGACY_VPN); 2061 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 2062 2063 // Start a new LegacyVpnRunner and we are done! 2064 mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile); 2065 mVpnRunner.start(); 2066 } 2067 2068 /** 2069 * Checks if this the currently running VPN (if any) was started by the Settings app 2070 * 2071 * <p>This includes both Legacy VPNs and Platform VPNs. 2072 */ 2073 private boolean isSettingsVpnLocked() { 2074 return mVpnRunner != null && VpnConfig.LEGACY_VPN.equals(mPackage); 2075 } 2076 2077 /** Stop VPN runner. Permissions must be checked by callers. */ 2078 public synchronized void stopVpnRunnerPrivileged() { 2079 if (!isSettingsVpnLocked()) { 2080 return; 2081 } 2082 2083 final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner; 2084 2085 mVpnRunner.exit(); 2086 mVpnRunner = null; 2087 2088 // LegacyVpn uses daemons that must be shut down before new ones are brought up. 2089 // The same limitation does not apply to Platform VPNs. 2090 if (isLegacyVpn) { 2091 synchronized (LegacyVpnRunner.TAG) { 2092 // wait for old thread to completely finish before spinning up 2093 // new instance, otherwise state updates can be out of order. 2094 } 2095 } 2096 } 2097 2098 /** 2099 * Return the information of the current ongoing legacy VPN. 2100 */ 2101 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 2102 // Check if the caller is authorized. 2103 enforceControlPermission(); 2104 return getLegacyVpnInfoPrivileged(); 2105 } 2106 2107 /** 2108 * Return the information of the current ongoing legacy VPN. 2109 * Callers are responsible for checking permissions if needed. 2110 */ 2111 private synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() { 2112 if (!isSettingsVpnLocked()) return null; 2113 2114 final LegacyVpnInfo info = new LegacyVpnInfo(); 2115 info.key = mConfig.user; 2116 info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); 2117 if (mNetworkInfo.isConnected()) { 2118 info.intent = mStatusIntent; 2119 } 2120 return info; 2121 } 2122 2123 public synchronized VpnConfig getLegacyVpnConfig() { 2124 if (isSettingsVpnLocked()) { 2125 return mConfig; 2126 } else { 2127 return null; 2128 } 2129 } 2130 2131 /** This class represents the common interface for all VPN runners. */ 2132 private abstract class VpnRunner extends Thread { 2133 2134 protected VpnRunner(String name) { 2135 super(name); 2136 } 2137 2138 public abstract void run(); 2139 2140 /** 2141 * Disconnects the NetworkAgent and cleans up all state related to the VpnRunner. 2142 * 2143 * <p>All outer Vpn instance state is cleaned up in cleanupVpnStateLocked() 2144 */ 2145 protected abstract void exitVpnRunner(); 2146 2147 /** 2148 * Triggers the cleanup of the VpnRunner, and additionally cleans up Vpn instance-wide state 2149 * 2150 * <p>This method ensures that simple calls to exit() will always clean up global state 2151 * properly. 2152 */ 2153 protected final void exit() { 2154 synchronized (Vpn.this) { 2155 exitVpnRunner(); 2156 cleanupVpnStateLocked(); 2157 } 2158 } 2159 } 2160 2161 interface IkeV2VpnRunnerCallback { 2162 void onDefaultNetworkChanged(@NonNull Network network); 2163 2164 void onChildOpened( 2165 @NonNull Network network, @NonNull ChildSessionConfiguration childConfig); 2166 2167 void onChildTransformCreated( 2168 @NonNull Network network, @NonNull IpSecTransform transform, int direction); 2169 2170 void onSessionLost(@NonNull Network network); 2171 } 2172 2173 /** 2174 * Internal class managing IKEv2/IPsec VPN connectivity 2175 * 2176 * <p>The IKEv2 VPN will listen to, and run based on the lifecycle of Android's default Network. 2177 * As a new default is selected, old IKE sessions will be torn down, and a new one will be 2178 * started. 2179 * 2180 * <p>This class uses locking minimally - the Vpn instance lock is only ever held when fields of 2181 * the outer class are modified. As such, care must be taken to ensure that no calls are added 2182 * that might modify the outer class' state without acquiring a lock. 2183 * 2184 * <p>The overall structure of the Ikev2VpnRunner is as follows: 2185 * 2186 * <ol> 2187 * <li>Upon startup, a NetworkRequest is registered with ConnectivityManager. This is called 2188 * any time a new default network is selected 2189 * <li>When a new default is connected, an IKE session is started on that Network. If there 2190 * were any existing IKE sessions on other Networks, they are torn down before starting 2191 * the new IKE session 2192 * <li>Upon establishment, the onChildTransformCreated() callback is called twice, one for 2193 * each direction, and finally onChildOpened() is called 2194 * <li>Upon the onChildOpened() call, the VPN is fully set up. 2195 * <li>Subsequent Network changes result in new onDefaultNetworkChanged() callbacks. See (2). 2196 * </ol> 2197 */ 2198 class IkeV2VpnRunner extends VpnRunner implements IkeV2VpnRunnerCallback { 2199 @NonNull private static final String TAG = "IkeV2VpnRunner"; 2200 2201 @NonNull private final IpSecManager mIpSecManager; 2202 @NonNull private final Ikev2VpnProfile mProfile; 2203 @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback; 2204 2205 /** 2206 * Executor upon which ALL callbacks must be run. 2207 * 2208 * <p>This executor MUST be a single threaded executor, in order to ensure the consistency 2209 * of the mutable Ikev2VpnRunner fields. The Ikev2VpnRunner is built mostly lock-free by 2210 * virtue of everything being serialized on this executor. 2211 */ 2212 @NonNull private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); 2213 2214 /** Signal to ensure shutdown is honored even if a new Network is connected. */ 2215 private boolean mIsRunning = true; 2216 2217 @Nullable private IpSecTunnelInterface mTunnelIface; 2218 @Nullable private IkeSession mSession; 2219 @Nullable private Network mActiveNetwork; 2220 2221 IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) { 2222 super(TAG); 2223 mProfile = profile; 2224 mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); 2225 mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this); 2226 } 2227 2228 @Override 2229 public void run() { 2230 // Unless the profile is restricted to test networks, explicitly use only the network 2231 // that ConnectivityService thinks is the "best." In other words, only ever use the 2232 // currently selected default network. This does mean that in both onLost() and 2233 // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs. 2234 // 2235 // When restricted to test networks, select any network with TRANSPORT_TEST. Since the 2236 // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, 2237 // this is considered safe. 2238 final ConnectivityManager cm = ConnectivityManager.from(mContext); 2239 final NetworkRequest req; 2240 2241 if (mProfile.isRestrictedToTestNetworks()) { 2242 req = new NetworkRequest.Builder() 2243 .clearCapabilities() 2244 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 2245 .build(); 2246 } else { 2247 req = cm.getDefaultRequest(); 2248 } 2249 2250 cm.requestNetwork(req, mNetworkCallback); 2251 } 2252 2253 private boolean isActiveNetwork(@Nullable Network network) { 2254 return Objects.equals(mActiveNetwork, network) && mIsRunning; 2255 } 2256 2257 /** 2258 * Called when an IKE Child session has been opened, signalling completion of the startup. 2259 * 2260 * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor 2261 * thread in order to ensure consistency of the Ikev2VpnRunner fields. 2262 */ 2263 public void onChildOpened( 2264 @NonNull Network network, @NonNull ChildSessionConfiguration childConfig) { 2265 if (!isActiveNetwork(network)) { 2266 Log.d(TAG, "onOpened called for obsolete network " + network); 2267 2268 // Do nothing; this signals that either: (1) a new/better Network was found, 2269 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this 2270 // IKE session was already shut down (exited, or an error was encountered somewhere 2271 // else). In both cases, all resources and sessions are torn down via 2272 // resetIkeState(). 2273 return; 2274 } 2275 2276 try { 2277 final String interfaceName = mTunnelIface.getInterfaceName(); 2278 final int maxMtu = mProfile.getMaxMtu(); 2279 final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses(); 2280 final List<String> dnsAddrStrings = new ArrayList<>(); 2281 2282 final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors( 2283 childConfig.getOutboundTrafficSelectors()); 2284 for (final LinkAddress address : internalAddresses) { 2285 mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength()); 2286 } 2287 for (InetAddress addr : childConfig.getInternalDnsServers()) { 2288 dnsAddrStrings.add(addr.getHostAddress()); 2289 } 2290 2291 final NetworkAgent networkAgent; 2292 final LinkProperties lp; 2293 2294 synchronized (Vpn.this) { 2295 mInterface = interfaceName; 2296 mConfig.mtu = maxMtu; 2297 mConfig.interfaze = mInterface; 2298 2299 mConfig.addresses.clear(); 2300 mConfig.addresses.addAll(internalAddresses); 2301 2302 mConfig.routes.clear(); 2303 mConfig.routes.addAll(newRoutes); 2304 2305 if (mConfig.dnsServers == null) mConfig.dnsServers = new ArrayList<>(); 2306 mConfig.dnsServers.clear(); 2307 mConfig.dnsServers.addAll(dnsAddrStrings); 2308 2309 networkAgent = mNetworkAgent; 2310 2311 // The below must be done atomically with the mConfig update, otherwise 2312 // isRunningLocked() will be racy. 2313 if (networkAgent == null) { 2314 if (isSettingsVpnLocked()) { 2315 prepareStatusIntent(); 2316 } 2317 agentConnect(); 2318 return; // Link properties are already sent. 2319 } 2320 2321 lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked 2322 } 2323 2324 networkAgent.sendLinkProperties(lp); 2325 } catch (Exception e) { 2326 Log.d(TAG, "Error in ChildOpened for network " + network, e); 2327 onSessionLost(network); 2328 } 2329 } 2330 2331 /** 2332 * Called when an IPsec transform has been created, and should be applied. 2333 * 2334 * <p>This method is called multiple times over the lifetime of an IkeSession (or default 2335 * network), and is MUST always be called on the mExecutor thread in order to ensure 2336 * consistency of the Ikev2VpnRunner fields. 2337 */ 2338 public void onChildTransformCreated( 2339 @NonNull Network network, @NonNull IpSecTransform transform, int direction) { 2340 if (!isActiveNetwork(network)) { 2341 Log.d(TAG, "ChildTransformCreated for obsolete network " + network); 2342 2343 // Do nothing; this signals that either: (1) a new/better Network was found, 2344 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this 2345 // IKE session was already shut down (exited, or an error was encountered somewhere 2346 // else). In both cases, all resources and sessions are torn down via 2347 // resetIkeState(). 2348 return; 2349 } 2350 2351 try { 2352 // Transforms do not need to be persisted; the IkeSession will keep 2353 // them alive for us 2354 mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform); 2355 } catch (IOException e) { 2356 Log.d(TAG, "Transform application failed for network " + network, e); 2357 onSessionLost(network); 2358 } 2359 } 2360 2361 /** 2362 * Called when a new default network is connected. 2363 * 2364 * <p>The Ikev2VpnRunner will unconditionally switch to the new network, killing the old IKE 2365 * state in the process, and starting a new IkeSession instance. 2366 * 2367 * <p>This method is called multiple times over the lifetime of the Ikev2VpnRunner, and is 2368 * called on the ConnectivityService thread. Thus, the actual work MUST be proxied to the 2369 * mExecutor thread in order to ensure consistency of the Ikev2VpnRunner fields. 2370 */ 2371 public void onDefaultNetworkChanged(@NonNull Network network) { 2372 Log.d(TAG, "Starting IKEv2/IPsec session on new network: " + network); 2373 2374 // Proxy to the Ikev2VpnRunner (single-thread) executor to ensure consistency in lieu 2375 // of locking. 2376 mExecutor.execute(() -> { 2377 try { 2378 if (!mIsRunning) { 2379 Log.d(TAG, "onDefaultNetworkChanged after exit"); 2380 return; // VPN has been shut down. 2381 } 2382 2383 // Without MOBIKE, we have no way to seamlessly migrate. Close on old 2384 // (non-default) network, and start the new one. 2385 resetIkeState(); 2386 mActiveNetwork = network; 2387 2388 final IkeSessionParams ikeSessionParams = 2389 VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, network); 2390 final ChildSessionParams childSessionParams = 2391 VpnIkev2Utils.buildChildSessionParams(mProfile.getAllowedAlgorithms()); 2392 2393 // TODO: Remove the need for adding two unused addresses with 2394 // IPsec tunnels. 2395 final InetAddress address = InetAddress.getLocalHost(); 2396 mTunnelIface = 2397 mIpSecManager.createIpSecTunnelInterface( 2398 address /* unused */, 2399 address /* unused */, 2400 network); 2401 mNetd.setInterfaceUp(mTunnelIface.getInterfaceName()); 2402 2403 mSession = mIkev2SessionCreator.createIkeSession( 2404 mContext, 2405 ikeSessionParams, 2406 childSessionParams, 2407 mExecutor, 2408 new VpnIkev2Utils.IkeSessionCallbackImpl( 2409 TAG, IkeV2VpnRunner.this, network), 2410 new VpnIkev2Utils.ChildSessionCallbackImpl( 2411 TAG, IkeV2VpnRunner.this, network)); 2412 Log.d(TAG, "Ike Session started for network " + network); 2413 } catch (Exception e) { 2414 Log.i(TAG, "Setup failed for network " + network + ". Aborting", e); 2415 onSessionLost(network); 2416 } 2417 }); 2418 } 2419 2420 /** 2421 * Handles loss of a session 2422 * 2423 * <p>The loss of a session might be due to an onLost() call, the IKE session getting torn 2424 * down for any reason, or an error in updating state (transform application, VPN setup) 2425 * 2426 * <p>This method MUST always be called on the mExecutor thread in order to ensure 2427 * consistency of the Ikev2VpnRunner fields. 2428 */ 2429 public void onSessionLost(@NonNull Network network) { 2430 if (!isActiveNetwork(network)) { 2431 Log.d(TAG, "onSessionLost() called for obsolete network " + network); 2432 2433 // Do nothing; this signals that either: (1) a new/better Network was found, 2434 // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this 2435 // IKE session was already shut down (exited, or an error was encountered somewhere 2436 // else). In both cases, all resources and sessions are torn down via 2437 // onSessionLost() and resetIkeState(). 2438 return; 2439 } 2440 2441 mActiveNetwork = null; 2442 2443 // Close all obsolete state, but keep VPN alive incase a usable network comes up. 2444 // (Mirrors VpnService behavior) 2445 Log.d(TAG, "Resetting state for network: " + network); 2446 2447 synchronized (Vpn.this) { 2448 // Since this method handles non-fatal errors only, set mInterface to null to 2449 // prevent the NetworkManagementEventObserver from killing this VPN based on the 2450 // interface going down (which we expect). 2451 mInterface = null; 2452 mConfig.interfaze = null; 2453 2454 // Set as unroutable to prevent traffic leaking while the interface is down. 2455 if (mConfig != null && mConfig.routes != null) { 2456 final List<RouteInfo> oldRoutes = new ArrayList<>(mConfig.routes); 2457 2458 mConfig.routes.clear(); 2459 for (final RouteInfo route : oldRoutes) { 2460 mConfig.routes.add(new RouteInfo(route.getDestination(), RTN_UNREACHABLE)); 2461 } 2462 if (mNetworkAgent != null) { 2463 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 2464 } 2465 } 2466 } 2467 2468 resetIkeState(); 2469 } 2470 2471 /** 2472 * Cleans up all IKE state 2473 * 2474 * <p>This method MUST always be called on the mExecutor thread in order to ensure 2475 * consistency of the Ikev2VpnRunner fields. 2476 */ 2477 private void resetIkeState() { 2478 if (mTunnelIface != null) { 2479 // No need to call setInterfaceDown(); the IpSecInterface is being fully torn down. 2480 mTunnelIface.close(); 2481 mTunnelIface = null; 2482 } 2483 if (mSession != null) { 2484 mSession.kill(); // Kill here to make sure all resources are released immediately 2485 mSession = null; 2486 } 2487 } 2488 2489 /** 2490 * Cleans up all Ikev2VpnRunner internal state 2491 * 2492 * <p>This method MUST always be called on the mExecutor thread in order to ensure 2493 * consistency of the Ikev2VpnRunner fields. 2494 */ 2495 private void shutdownVpnRunner() { 2496 mActiveNetwork = null; 2497 mIsRunning = false; 2498 2499 resetIkeState(); 2500 2501 final ConnectivityManager cm = ConnectivityManager.from(mContext); 2502 cm.unregisterNetworkCallback(mNetworkCallback); 2503 2504 mExecutor.shutdown(); 2505 } 2506 2507 @Override 2508 public void exitVpnRunner() { 2509 mExecutor.execute(() -> { 2510 shutdownVpnRunner(); 2511 }); 2512 } 2513 } 2514 2515 /** 2516 * Bringing up a VPN connection takes time, and that is all this thread 2517 * does. Here we have plenty of time. The only thing we need to take 2518 * care of is responding to interruptions as soon as possible. Otherwise 2519 * requests will pile up. This could be done in a Handler as a state 2520 * machine, but it is much easier to read in the current form. 2521 */ 2522 private class LegacyVpnRunner extends VpnRunner { 2523 private static final String TAG = "LegacyVpnRunner"; 2524 2525 private final String[] mDaemons; 2526 private final String[][] mArguments; 2527 private final LocalSocket[] mSockets; 2528 private final String mOuterInterface; 2529 private final AtomicInteger mOuterConnection = 2530 new AtomicInteger(ConnectivityManager.TYPE_NONE); 2531 private final VpnProfile mProfile; 2532 2533 private long mBringupStartTime = -1; 2534 2535 /** 2536 * Watch for the outer connection (passing in the constructor) going away. 2537 */ 2538 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 2539 @Override 2540 public void onReceive(Context context, Intent intent) { 2541 if (!mEnableTeardown) return; 2542 2543 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 2544 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 2545 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 2546 NetworkInfo info = (NetworkInfo)intent.getExtra( 2547 ConnectivityManager.EXTRA_NETWORK_INFO); 2548 if (info != null && !info.isConnectedOrConnecting()) { 2549 try { 2550 mObserver.interfaceStatusChanged(mOuterInterface, false); 2551 } catch (RemoteException e) {} 2552 } 2553 } 2554 } 2555 } 2556 }; 2557 2558 LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { 2559 super(TAG); 2560 mConfig = config; 2561 mDaemons = new String[] {"racoon", "mtpd"}; 2562 // TODO: clear arguments from memory once launched 2563 mArguments = new String[][] {racoon, mtpd}; 2564 mSockets = new LocalSocket[mDaemons.length]; 2565 2566 // This is the interface which VPN is running on, 2567 // mConfig.interfaze will change to point to OUR 2568 // internal interface soon. TODO - add inner/outer to mconfig 2569 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 2570 // we will leave the VPN up. We should check that it's still there/connected after 2571 // registering 2572 mOuterInterface = mConfig.interfaze; 2573 2574 mProfile = profile; 2575 2576 if (!TextUtils.isEmpty(mOuterInterface)) { 2577 final ConnectivityManager cm = ConnectivityManager.from(mContext); 2578 for (Network network : cm.getAllNetworks()) { 2579 final LinkProperties lp = cm.getLinkProperties(network); 2580 if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { 2581 final NetworkInfo networkInfo = cm.getNetworkInfo(network); 2582 if (networkInfo != null) mOuterConnection.set(networkInfo.getType()); 2583 } 2584 } 2585 } 2586 2587 IntentFilter filter = new IntentFilter(); 2588 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 2589 mContext.registerReceiver(mBroadcastReceiver, filter); 2590 } 2591 2592 /** 2593 * Checks if the parameter matches the underlying interface 2594 * 2595 * <p>If the underlying interface is torn down, the LegacyVpnRunner also should be. It has 2596 * no ability to migrate between interfaces (or Networks). 2597 */ 2598 public void exitIfOuterInterfaceIs(String interfaze) { 2599 if (interfaze.equals(mOuterInterface)) { 2600 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 2601 exitVpnRunner(); 2602 } 2603 } 2604 2605 /** Tears down this LegacyVpn connection */ 2606 @Override 2607 public void exitVpnRunner() { 2608 // We assume that everything is reset after stopping the daemons. 2609 interrupt(); 2610 2611 // Always disconnect. This may be called again in cleanupVpnStateLocked() if 2612 // exitVpnRunner() was called from exit(), but it will be a no-op. 2613 agentDisconnect(); 2614 try { 2615 mContext.unregisterReceiver(mBroadcastReceiver); 2616 } catch (IllegalArgumentException e) {} 2617 } 2618 2619 @Override 2620 public void run() { 2621 // Wait for the previous thread since it has been interrupted. 2622 Log.v(TAG, "Waiting"); 2623 synchronized (TAG) { 2624 Log.v(TAG, "Executing"); 2625 try { 2626 bringup(); 2627 waitForDaemonsToStop(); 2628 interrupted(); // Clear interrupt flag if execute called exit. 2629 } catch (InterruptedException e) { 2630 } finally { 2631 for (LocalSocket socket : mSockets) { 2632 IoUtils.closeQuietly(socket); 2633 } 2634 // This sleep is necessary for racoon to successfully complete sending delete 2635 // message to server. 2636 try { 2637 Thread.sleep(50); 2638 } catch (InterruptedException e) { 2639 } 2640 for (String daemon : mDaemons) { 2641 SystemService.stop(daemon); 2642 } 2643 } 2644 agentDisconnect(); 2645 } 2646 } 2647 2648 private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException { 2649 long now = SystemClock.elapsedRealtime(); 2650 if (now - mBringupStartTime <= 60000) { 2651 Thread.sleep(sleepLonger ? 200 : 1); 2652 } else { 2653 updateState(DetailedState.FAILED, "checkpoint"); 2654 throw new IllegalStateException("VPN bringup took too long"); 2655 } 2656 } 2657 2658 private void bringup() { 2659 // Catch all exceptions so we can clean up a few things. 2660 try { 2661 // Initialize the timer. 2662 mBringupStartTime = SystemClock.elapsedRealtime(); 2663 2664 // Wait for the daemons to stop. 2665 for (String daemon : mDaemons) { 2666 while (!SystemService.isStopped(daemon)) { 2667 checkInterruptAndDelay(true); 2668 } 2669 } 2670 2671 // Clear the previous state. 2672 File state = new File("/data/misc/vpn/state"); 2673 state.delete(); 2674 if (state.exists()) { 2675 throw new IllegalStateException("Cannot delete the state"); 2676 } 2677 new File("/data/misc/vpn/abort").delete(); 2678 2679 // Check if we need to restart any of the daemons. 2680 boolean restart = false; 2681 for (String[] arguments : mArguments) { 2682 restart = restart || (arguments != null); 2683 } 2684 if (!restart) { 2685 agentDisconnect(); 2686 return; 2687 } 2688 updateState(DetailedState.CONNECTING, "execute"); 2689 2690 // Start the daemon with arguments. 2691 for (int i = 0; i < mDaemons.length; ++i) { 2692 String[] arguments = mArguments[i]; 2693 if (arguments == null) { 2694 continue; 2695 } 2696 2697 // Start the daemon. 2698 String daemon = mDaemons[i]; 2699 SystemService.start(daemon); 2700 2701 // Wait for the daemon to start. 2702 while (!SystemService.isRunning(daemon)) { 2703 checkInterruptAndDelay(true); 2704 } 2705 2706 // Create the control socket. 2707 mSockets[i] = new LocalSocket(); 2708 LocalSocketAddress address = new LocalSocketAddress( 2709 daemon, LocalSocketAddress.Namespace.RESERVED); 2710 2711 // Wait for the socket to connect. 2712 while (true) { 2713 try { 2714 mSockets[i].connect(address); 2715 break; 2716 } catch (Exception e) { 2717 // ignore 2718 } 2719 checkInterruptAndDelay(true); 2720 } 2721 mSockets[i].setSoTimeout(500); 2722 2723 // Send over the arguments. 2724 OutputStream out = mSockets[i].getOutputStream(); 2725 for (String argument : arguments) { 2726 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 2727 if (bytes.length >= 0xFFFF) { 2728 throw new IllegalArgumentException("Argument is too large"); 2729 } 2730 out.write(bytes.length >> 8); 2731 out.write(bytes.length); 2732 out.write(bytes); 2733 checkInterruptAndDelay(false); 2734 } 2735 out.write(0xFF); 2736 out.write(0xFF); 2737 2738 // Wait for End-of-File. 2739 InputStream in = mSockets[i].getInputStream(); 2740 while (true) { 2741 try { 2742 if (in.read() == -1) { 2743 break; 2744 } 2745 } catch (Exception e) { 2746 // ignore 2747 } 2748 checkInterruptAndDelay(true); 2749 } 2750 } 2751 2752 // Wait for the daemons to create the new state. 2753 while (!state.exists()) { 2754 // Check if a running daemon is dead. 2755 for (int i = 0; i < mDaemons.length; ++i) { 2756 String daemon = mDaemons[i]; 2757 if (mArguments[i] != null && !SystemService.isRunning(daemon)) { 2758 throw new IllegalStateException(daemon + " is dead"); 2759 } 2760 } 2761 checkInterruptAndDelay(true); 2762 } 2763 2764 // Now we are connected. Read and parse the new state. 2765 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 2766 if (parameters.length != 7) { 2767 throw new IllegalStateException("Cannot parse the state"); 2768 } 2769 2770 // Set the interface and the addresses in the config. 2771 mConfig.interfaze = parameters[0].trim(); 2772 2773 mConfig.addLegacyAddresses(parameters[1]); 2774 // Set the routes if they are not set in the config. 2775 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 2776 mConfig.addLegacyRoutes(parameters[2]); 2777 } 2778 2779 // Set the DNS servers if they are not set in the config. 2780 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 2781 String dnsServers = parameters[3].trim(); 2782 if (!dnsServers.isEmpty()) { 2783 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 2784 } 2785 } 2786 2787 // Set the search domains if they are not set in the config. 2788 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 2789 String searchDomains = parameters[4].trim(); 2790 if (!searchDomains.isEmpty()) { 2791 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 2792 } 2793 } 2794 2795 // Add a throw route for the VPN server endpoint, if one was specified. 2796 String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5]; 2797 if (!endpoint.isEmpty()) { 2798 try { 2799 InetAddress addr = InetAddress.parseNumericAddress(endpoint); 2800 if (addr instanceof Inet4Address) { 2801 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW)); 2802 } else if (addr instanceof Inet6Address) { 2803 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW)); 2804 } else { 2805 Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint); 2806 } 2807 } catch (IllegalArgumentException e) { 2808 Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e); 2809 } 2810 } 2811 2812 // Here is the last step and it must be done synchronously. 2813 synchronized (Vpn.this) { 2814 // Set the start time 2815 mConfig.startTime = SystemClock.elapsedRealtime(); 2816 2817 // Check if the thread was interrupted while we were waiting on the lock. 2818 checkInterruptAndDelay(false); 2819 2820 // Check if the interface is gone while we are waiting. 2821 if (jniCheck(mConfig.interfaze) == 0) { 2822 throw new IllegalStateException(mConfig.interfaze + " is gone"); 2823 } 2824 2825 // Now INetworkManagementEventObserver is watching our back. 2826 mInterface = mConfig.interfaze; 2827 prepareStatusIntent(); 2828 2829 agentConnect(); 2830 2831 Log.i(TAG, "Connected!"); 2832 } 2833 } catch (Exception e) { 2834 Log.i(TAG, "Aborting", e); 2835 updateState(DetailedState.FAILED, e.getMessage()); 2836 exitVpnRunner(); 2837 } 2838 } 2839 2840 /** 2841 * Check all daemons every two seconds. Return when one of them is stopped. 2842 * The caller will move to the disconnected state when this function returns, 2843 * which can happen if a daemon failed or if the VPN was torn down. 2844 */ 2845 private void waitForDaemonsToStop() throws InterruptedException { 2846 if (!mNetworkInfo.isConnected()) { 2847 return; 2848 } 2849 while (true) { 2850 Thread.sleep(2000); 2851 for (int i = 0; i < mDaemons.length; i++) { 2852 if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { 2853 return; 2854 } 2855 } 2856 } 2857 } 2858 } 2859 2860 private void verifyCallingUidAndPackage(String packageName) { 2861 if (getAppUid(packageName, mUserHandle) != Binder.getCallingUid()) { 2862 throw new SecurityException("Mismatched package and UID"); 2863 } 2864 } 2865 2866 @VisibleForTesting 2867 String getProfileNameForPackage(String packageName) { 2868 return Credentials.PLATFORM_VPN + mUserHandle + "_" + packageName; 2869 } 2870 2871 @VisibleForTesting 2872 void validateRequiredFeatures(VpnProfile profile) { 2873 switch (profile.type) { 2874 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 2875 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 2876 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 2877 if (!mContext.getPackageManager().hasSystemFeature( 2878 PackageManager.FEATURE_IPSEC_TUNNELS)) { 2879 throw new UnsupportedOperationException( 2880 "Ikev2VpnProfile(s) requires PackageManager.FEATURE_IPSEC_TUNNELS"); 2881 } 2882 break; 2883 default: 2884 return; 2885 } 2886 } 2887 2888 /** 2889 * Stores an app-provisioned VPN profile and returns whether the app is already prepared. 2890 * 2891 * @param packageName the package name of the app provisioning this profile 2892 * @param profile the profile to be stored and provisioned 2893 * @param keyStore the System keystore instance to save VPN profiles 2894 * @returns whether or not the app has already been granted user consent 2895 */ 2896 public synchronized boolean provisionVpnProfile( 2897 @NonNull String packageName, @NonNull VpnProfile profile, @NonNull KeyStore keyStore) { 2898 checkNotNull(packageName, "No package name provided"); 2899 checkNotNull(profile, "No profile provided"); 2900 checkNotNull(keyStore, "KeyStore missing"); 2901 2902 verifyCallingUidAndPackage(packageName); 2903 enforceNotRestrictedUser(); 2904 validateRequiredFeatures(profile); 2905 2906 if (profile.isRestrictedToTestNetworks) { 2907 mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS, 2908 "Test-mode profiles require the MANAGE_TEST_NETWORKS permission"); 2909 } 2910 2911 final byte[] encodedProfile = profile.encode(); 2912 if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) { 2913 throw new IllegalArgumentException("Profile too big"); 2914 } 2915 2916 // Permissions checked during startVpnProfile() 2917 Binder.withCleanCallingIdentity( 2918 () -> { 2919 keyStore.put( 2920 getProfileNameForPackage(packageName), 2921 encodedProfile, 2922 Process.SYSTEM_UID, 2923 0 /* flags */); 2924 }); 2925 2926 // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. 2927 // This mirrors the prepareAndAuthorize that is used by VpnService. 2928 2929 // Return whether the app is already pre-consented 2930 return isVpnProfilePreConsented(mContext, packageName); 2931 } 2932 2933 private boolean isCurrentIkev2VpnLocked(@NonNull String packageName) { 2934 return isCurrentPreparedPackage(packageName) && mVpnRunner instanceof IkeV2VpnRunner; 2935 } 2936 2937 /** 2938 * Deletes an app-provisioned VPN profile. 2939 * 2940 * @param packageName the package name of the app provisioning this profile 2941 * @param keyStore the System keystore instance to save VPN profiles 2942 */ 2943 public synchronized void deleteVpnProfile( 2944 @NonNull String packageName, @NonNull KeyStore keyStore) { 2945 checkNotNull(packageName, "No package name provided"); 2946 checkNotNull(keyStore, "KeyStore missing"); 2947 2948 verifyCallingUidAndPackage(packageName); 2949 enforceNotRestrictedUser(); 2950 2951 Binder.withCleanCallingIdentity( 2952 () -> { 2953 // If this profile is providing the current VPN, turn it off, disabling 2954 // always-on as well if enabled. 2955 if (isCurrentIkev2VpnLocked(packageName)) { 2956 if (mAlwaysOn) { 2957 // Will transitively call prepareInternal(VpnConfig.LEGACY_VPN). 2958 setAlwaysOnPackage(null, false, null, keyStore); 2959 } else { 2960 prepareInternal(VpnConfig.LEGACY_VPN); 2961 } 2962 } 2963 2964 keyStore.delete(getProfileNameForPackage(packageName), Process.SYSTEM_UID); 2965 }); 2966 } 2967 2968 /** 2969 * Retrieves the VpnProfile. 2970 * 2971 * <p>Must be used only as SYSTEM_UID, otherwise the key/UID pair will not match anything in the 2972 * keystore. 2973 */ 2974 @VisibleForTesting 2975 @Nullable 2976 VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) { 2977 if (!mSystemServices.isCallerSystem()) { 2978 Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID "); 2979 return null; 2980 } 2981 2982 final byte[] encoded = keyStore.get(getProfileNameForPackage(packageName)); 2983 if (encoded == null) return null; 2984 2985 return VpnProfile.decode("" /* Key unused */, encoded); 2986 } 2987 2988 /** 2989 * Starts an already provisioned VPN Profile, keyed by package name. 2990 * 2991 * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService). 2992 * Privileged (system) callers should use startVpnProfilePrivileged instead. Otherwise the UIDs 2993 * will not match during appop checks. 2994 * 2995 * @param packageName the package name of the app provisioning this profile 2996 * @param keyStore the System keystore instance to retrieve VPN profiles 2997 */ 2998 public synchronized void startVpnProfile( 2999 @NonNull String packageName, @NonNull KeyStore keyStore) { 3000 checkNotNull(packageName, "No package name provided"); 3001 checkNotNull(keyStore, "KeyStore missing"); 3002 3003 enforceNotRestrictedUser(); 3004 3005 // Prepare VPN for startup 3006 if (!prepare(packageName, null /* newPackage */, VpnManager.TYPE_VPN_PLATFORM)) { 3007 throw new SecurityException("User consent not granted for package " + packageName); 3008 } 3009 3010 Binder.withCleanCallingIdentity( 3011 () -> { 3012 final VpnProfile profile = getVpnProfilePrivileged(packageName, keyStore); 3013 if (profile == null) { 3014 throw new IllegalArgumentException("No profile found for " + packageName); 3015 } 3016 3017 startVpnProfilePrivileged(profile, packageName, 3018 null /* keyStore for private key retrieval - unneeded */); 3019 }); 3020 } 3021 3022 private synchronized void startVpnProfilePrivileged( 3023 @NonNull VpnProfile profile, @NonNull String packageName, @Nullable KeyStore keyStore) { 3024 // Make sure VPN is prepared. This method can be called by user apps via startVpnProfile(), 3025 // by the Setting app via startLegacyVpn(), or by ConnectivityService via 3026 // startAlwaysOnVpn(), so this is the common place to prepare the VPN. This also has the 3027 // nice property of ensuring there are no other VpnRunner instances running. 3028 prepareInternal(packageName); 3029 updateState(DetailedState.CONNECTING, "startPlatformVpn"); 3030 3031 try { 3032 // Build basic config 3033 mConfig = new VpnConfig(); 3034 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 3035 mConfig.legacy = true; 3036 mConfig.session = profile.name; 3037 mConfig.user = profile.key; 3038 3039 // TODO: Add support for configuring meteredness via Settings. Until then, use a 3040 // safe default. 3041 mConfig.isMetered = true; 3042 } else { 3043 mConfig.user = packageName; 3044 mConfig.isMetered = profile.isMetered; 3045 } 3046 mConfig.startTime = SystemClock.elapsedRealtime(); 3047 mConfig.proxyInfo = profile.proxy; 3048 3049 switch (profile.type) { 3050 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 3051 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 3052 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 3053 mVpnRunner = 3054 new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile, keyStore)); 3055 mVpnRunner.start(); 3056 break; 3057 default: 3058 updateState(DetailedState.FAILED, "Invalid platform VPN type"); 3059 Log.d(TAG, "Unknown VPN profile type: " + profile.type); 3060 break; 3061 } 3062 } catch (IOException | GeneralSecurityException e) { 3063 // Reset mConfig 3064 mConfig = null; 3065 3066 updateState(DetailedState.FAILED, "VPN startup failed"); 3067 throw new IllegalArgumentException("VPN startup failed", e); 3068 } 3069 } 3070 3071 /** 3072 * Stops an already running VPN Profile for the given package. 3073 * 3074 * <p>This method is meant to be called by apps (via VpnManager and ConnectivityService). 3075 * Privileged (system) callers should (re-)prepare the LEGACY_VPN instead. 3076 * 3077 * @param packageName the package name of the app provisioning this profile 3078 */ 3079 public synchronized void stopVpnProfile(@NonNull String packageName) { 3080 checkNotNull(packageName, "No package name provided"); 3081 3082 enforceNotRestrictedUser(); 3083 3084 // To stop the VPN profile, the caller must be the current prepared package and must be 3085 // running an Ikev2VpnProfile. 3086 if (isCurrentIkev2VpnLocked(packageName)) { 3087 prepareInternal(VpnConfig.LEGACY_VPN); 3088 } 3089 } 3090 3091 /** 3092 * Proxy to allow testing 3093 * 3094 * @hide 3095 */ 3096 @VisibleForTesting 3097 public static class Ikev2SessionCreator { 3098 /** Creates a IKE session */ 3099 public IkeSession createIkeSession( 3100 @NonNull Context context, 3101 @NonNull IkeSessionParams ikeSessionParams, 3102 @NonNull ChildSessionParams firstChildSessionParams, 3103 @NonNull Executor userCbExecutor, 3104 @NonNull IkeSessionCallback ikeSessionCallback, 3105 @NonNull ChildSessionCallback firstChildSessionCallback) { 3106 return new IkeSession( 3107 context, 3108 ikeSessionParams, 3109 firstChildSessionParams, 3110 userCbExecutor, 3111 ikeSessionCallback, 3112 firstChildSessionCallback); 3113 } 3114 } 3115 } 3116