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.RouteInfo.RTN_THROW; 25 import static android.net.RouteInfo.RTN_UNREACHABLE; 26 27 import android.Manifest; 28 import android.annotation.NonNull; 29 import android.annotation.Nullable; 30 import android.annotation.UserIdInt; 31 import android.app.AppGlobals; 32 import android.app.AppOpsManager; 33 import android.app.Notification; 34 import android.app.NotificationManager; 35 import android.app.PendingIntent; 36 import android.content.BroadcastReceiver; 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.IntentFilter; 41 import android.content.ServiceConnection; 42 import android.content.pm.ApplicationInfo; 43 import android.content.pm.PackageManager; 44 import android.content.pm.PackageManager.NameNotFoundException; 45 import android.content.pm.ResolveInfo; 46 import android.content.pm.UserInfo; 47 import android.net.ConnectivityManager; 48 import android.net.INetworkManagementEventObserver; 49 import android.net.IpPrefix; 50 import android.net.LinkAddress; 51 import android.net.LinkProperties; 52 import android.net.LocalSocket; 53 import android.net.LocalSocketAddress; 54 import android.net.Network; 55 import android.net.NetworkAgent; 56 import android.net.NetworkCapabilities; 57 import android.net.NetworkFactory; 58 import android.net.NetworkInfo; 59 import android.net.NetworkInfo.DetailedState; 60 import android.net.NetworkMisc; 61 import android.net.NetworkUtils; 62 import android.net.RouteInfo; 63 import android.net.UidRange; 64 import android.net.VpnService; 65 import android.os.Binder; 66 import android.os.Build.VERSION_CODES; 67 import android.os.Bundle; 68 import android.os.FileUtils; 69 import android.os.IBinder; 70 import android.os.INetworkManagementService; 71 import android.os.Looper; 72 import android.os.Parcel; 73 import android.os.ParcelFileDescriptor; 74 import android.os.Process; 75 import android.os.RemoteException; 76 import android.os.SystemClock; 77 import android.os.SystemService; 78 import android.os.UserHandle; 79 import android.os.UserManager; 80 import android.provider.Settings; 81 import android.security.Credentials; 82 import android.security.KeyStore; 83 import android.text.TextUtils; 84 import android.util.ArraySet; 85 import android.util.Log; 86 87 import com.android.internal.R; 88 import com.android.internal.annotations.GuardedBy; 89 import com.android.internal.annotations.VisibleForTesting; 90 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 91 import com.android.internal.net.LegacyVpnInfo; 92 import com.android.internal.net.VpnConfig; 93 import com.android.internal.net.VpnInfo; 94 import com.android.internal.net.VpnProfile; 95 import com.android.internal.notification.SystemNotificationChannels; 96 import com.android.internal.util.ArrayUtils; 97 import com.android.server.ConnectivityService; 98 import com.android.server.DeviceIdleController; 99 import com.android.server.LocalServices; 100 import com.android.server.net.BaseNetworkObserver; 101 102 import libcore.io.IoUtils; 103 104 import java.io.File; 105 import java.io.IOException; 106 import java.io.InputStream; 107 import java.io.OutputStream; 108 import java.math.BigInteger; 109 import java.net.Inet4Address; 110 import java.net.Inet6Address; 111 import java.net.InetAddress; 112 import java.nio.charset.StandardCharsets; 113 import java.util.ArrayList; 114 import java.util.Arrays; 115 import java.util.Collection; 116 import java.util.Collections; 117 import java.util.Comparator; 118 import java.util.List; 119 import java.util.Objects; 120 import java.util.Set; 121 import java.util.SortedSet; 122 import java.util.TreeSet; 123 import java.util.concurrent.atomic.AtomicInteger; 124 125 /** 126 * @hide 127 */ 128 public class Vpn { 129 private static final String NETWORKTYPE = "VPN"; 130 private static final String TAG = "Vpn"; 131 private static final boolean LOGD = true; 132 133 // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on 134 // the device idle whitelist during service launch and VPN bootstrap. 135 private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000; 136 137 // Settings for how much of the address space should be routed so that Vpn considers 138 // "most" of the address space is routed. This is used to determine whether this Vpn 139 // should be marked with the INTERNET capability. 140 private static final long MOST_IPV4_ADDRESSES_COUNT; 141 private static final BigInteger MOST_IPV6_ADDRESSES_COUNT; 142 static { 143 // 85% of the address space must be routed for Vpn to consider this VPN to provide 144 // INTERNET access. 145 final int howManyPercentIsMost = 85; 146 147 final long twoPower32 = 1L << 32; 148 MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100; 149 final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128); 150 MOST_IPV6_ADDRESSES_COUNT = twoPower128 151 .multiply(BigInteger.valueOf(howManyPercentIsMost)) 152 .divide(BigInteger.valueOf(100)); 153 } 154 // How many routes to evaluate before bailing and declaring this Vpn should provide 155 // the INTERNET capability. This is necessary because computing the address space is 156 // O(n²) and this is running in the system service, so a limit is needed to alleviate 157 // the risk of attack. 158 // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm 159 // is actually O(n²)+O(n²). 160 private static final int MAX_ROUTES_TO_EVALUATE = 150; 161 162 // TODO: create separate trackers for each unique VPN to support 163 // automated reconnection 164 165 private final Context mContext; 166 private final NetworkInfo mNetworkInfo; 167 private String mPackage; 168 private int mOwnerUID; 169 private boolean mIsPackageTargetingAtLeastQ; 170 private String mInterface; 171 private Connection mConnection; 172 private LegacyVpnRunner mLegacyVpnRunner; 173 private PendingIntent mStatusIntent; 174 private volatile boolean mEnableTeardown = true; 175 private final INetworkManagementService mNetd; 176 @VisibleForTesting 177 protected VpnConfig mConfig; 178 @VisibleForTesting 179 protected NetworkAgent mNetworkAgent; 180 private final Looper mLooper; 181 @VisibleForTesting 182 protected final NetworkCapabilities mNetworkCapabilities; 183 private final SystemServices mSystemServices; 184 185 /** 186 * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This 187 * only applies to {@link VpnService} connections. 188 */ 189 private boolean mAlwaysOn = false; 190 191 /** 192 * Whether to disable traffic outside of this VPN even when the VPN is not connected. System 193 * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is 194 * not set. 195 */ 196 private boolean mLockdown = false; 197 198 /** 199 * Set of packages in addition to the VPN app itself that can access the network directly when 200 * VPN is not connected even if {@code mLockdown} is set. 201 */ 202 private @NonNull List<String> mLockdownWhitelist = Collections.emptyList(); 203 204 /** 205 * List of UIDs for which networking should be blocked until VPN is ready, during brief periods 206 * when VPN is not running. For example, during system startup or after a crash. 207 * @see mLockdown 208 */ 209 @GuardedBy("this") 210 private Set<UidRange> mBlockedUsers = new ArraySet<>(); 211 212 // Handle of the user initiating VPN. 213 private final int mUserHandle; 214 Vpn(Looper looper, Context context, INetworkManagementService netService, @UserIdInt int userHandle)215 public Vpn(Looper looper, Context context, INetworkManagementService netService, 216 @UserIdInt int userHandle) { 217 this(looper, context, netService, userHandle, new SystemServices(context)); 218 } 219 220 @VisibleForTesting Vpn(Looper looper, Context context, INetworkManagementService netService, int userHandle, SystemServices systemServices)221 protected Vpn(Looper looper, Context context, INetworkManagementService netService, 222 int userHandle, SystemServices systemServices) { 223 mContext = context; 224 mNetd = netService; 225 mUserHandle = userHandle; 226 mLooper = looper; 227 mSystemServices = systemServices; 228 229 mPackage = VpnConfig.LEGACY_VPN; 230 mOwnerUID = getAppUid(mPackage, mUserHandle); 231 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage); 232 233 try { 234 netService.registerObserver(mObserver); 235 } catch (RemoteException e) { 236 Log.wtf(TAG, "Problem registering observer", e); 237 } 238 239 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE, 240 "" /* subtypeName */); 241 mNetworkCapabilities = new NetworkCapabilities(); 242 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); 243 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); 244 updateCapabilities(null /* defaultNetwork */); 245 246 loadAlwaysOnPackage(); 247 } 248 249 /** 250 * Set whether this object is responsible for watching for {@link NetworkInfo} 251 * teardown. When {@code false}, teardown is handled externally by someone 252 * else. 253 */ setEnableTeardown(boolean enableTeardown)254 public void setEnableTeardown(boolean enableTeardown) { 255 mEnableTeardown = enableTeardown; 256 } 257 258 /** 259 * Update current state, dispaching event to listeners. 260 */ 261 @VisibleForTesting updateState(DetailedState detailedState, String reason)262 protected void updateState(DetailedState detailedState, String reason) { 263 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 264 mNetworkInfo.setDetailedState(detailedState, reason, null); 265 if (mNetworkAgent != null) { 266 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 267 } 268 updateAlwaysOnNotification(detailedState); 269 } 270 271 /** 272 * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a 273 * defensive copy. 274 * 275 * <p>Does not propagate updated capabilities to apps. 276 * 277 * @param defaultNetwork underlying network for VPNs following platform's default 278 */ updateCapabilities( @ullable Network defaultNetwork)279 public synchronized NetworkCapabilities updateCapabilities( 280 @Nullable Network defaultNetwork) { 281 if (mConfig == null) { 282 // VPN is not running. 283 return null; 284 } 285 286 Network[] underlyingNetworks = mConfig.underlyingNetworks; 287 if (underlyingNetworks == null && defaultNetwork != null) { 288 // null underlying networks means to track the default. 289 underlyingNetworks = new Network[] { defaultNetwork }; 290 } 291 // Only apps targeting Q and above can explicitly declare themselves as metered. 292 final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered; 293 294 applyUnderlyingCapabilities( 295 mContext.getSystemService(ConnectivityManager.class), 296 underlyingNetworks, 297 mNetworkCapabilities, 298 isAlwaysMetered); 299 300 return new NetworkCapabilities(mNetworkCapabilities); 301 } 302 303 @VisibleForTesting applyUnderlyingCapabilities( ConnectivityManager cm, Network[] underlyingNetworks, NetworkCapabilities caps, boolean isAlwaysMetered)304 public static void applyUnderlyingCapabilities( 305 ConnectivityManager cm, 306 Network[] underlyingNetworks, 307 NetworkCapabilities caps, 308 boolean isAlwaysMetered) { 309 int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; 310 int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; 311 int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; 312 // VPN's meteredness is OR'd with isAlwaysMetered and meteredness of its underlying 313 // networks. 314 boolean metered = isAlwaysMetered; 315 boolean roaming = false; 316 boolean congested = false; 317 318 boolean hadUnderlyingNetworks = false; 319 if (null != underlyingNetworks) { 320 for (Network underlying : underlyingNetworks) { 321 // TODO(b/124469351): Get capabilities directly from ConnectivityService instead. 322 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying); 323 if (underlyingCaps == null) continue; 324 hadUnderlyingNetworks = true; 325 for (int underlyingType : underlyingCaps.getTransportTypes()) { 326 transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType); 327 } 328 329 // When we have multiple networks, we have to assume the 330 // worst-case link speed and restrictions. 331 downKbps = NetworkCapabilities.minBandwidth(downKbps, 332 underlyingCaps.getLinkDownstreamBandwidthKbps()); 333 upKbps = NetworkCapabilities.minBandwidth(upKbps, 334 underlyingCaps.getLinkUpstreamBandwidthKbps()); 335 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED); 336 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING); 337 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); 338 } 339 } 340 if (!hadUnderlyingNetworks) { 341 // No idea what the underlying networks are; assume sane defaults 342 metered = true; 343 roaming = false; 344 congested = false; 345 } 346 347 caps.setTransportTypes(transportTypes); 348 caps.setLinkDownstreamBandwidthKbps(downKbps); 349 caps.setLinkUpstreamBandwidthKbps(upKbps); 350 caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered); 351 caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); 352 caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); 353 } 354 355 /** 356 * Chooses whether to force all connections to go though VPN. 357 * 358 * Used to enable/disable legacy VPN lockdown. 359 * 360 * This uses the same ip rule mechanism as 361 * {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling 362 * that function will be replaced and saved with the always-on state. 363 * 364 * @param lockdown whether to prevent all traffic outside of a VPN. 365 */ setLockdown(boolean lockdown)366 public synchronized void setLockdown(boolean lockdown) { 367 enforceControlPermissionOrInternalCaller(); 368 369 setVpnForcedLocked(lockdown); 370 mLockdown = lockdown; 371 372 // Update app lockdown setting if it changed. Legacy VPN lockdown status is controlled by 373 // LockdownVpnTracker.isEnabled() which keeps track of its own state. 374 if (mAlwaysOn) { 375 saveAlwaysOnPackage(); 376 } 377 } 378 379 /** 380 * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected. 381 * 382 * @return {@code true} if VPN lockdown is enabled. 383 */ getLockdown()384 public synchronized boolean getLockdown() { 385 return mLockdown; 386 } 387 388 /** 389 * Returns whether VPN is configured as always-on. 390 */ getAlwaysOn()391 public synchronized boolean getAlwaysOn() { 392 return mAlwaysOn; 393 } 394 395 /** 396 * Checks if a VPN app supports always-on mode. 397 * 398 * In order to support the always-on feature, an app has to 399 * <ul> 400 * <li>target {@link VERSION_CODES#N API 24} or above, and 401 * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} 402 * meta-data field. 403 * </ul> 404 * 405 * @param packageName the canonical package name of the VPN app 406 * @return {@code true} if and only if the VPN app exists and supports always-on mode 407 */ isAlwaysOnPackageSupported(String packageName)408 public boolean isAlwaysOnPackageSupported(String packageName) { 409 enforceSettingsPermission(); 410 411 if (packageName == null) { 412 return false; 413 } 414 415 PackageManager pm = mContext.getPackageManager(); 416 ApplicationInfo appInfo = null; 417 try { 418 appInfo = pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle); 419 } catch (NameNotFoundException unused) { 420 Log.w(TAG, "Can't find \"" + packageName + "\" when checking always-on support"); 421 } 422 if (appInfo == null || appInfo.targetSdkVersion < VERSION_CODES.N) { 423 return false; 424 } 425 426 final Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 427 intent.setPackage(packageName); 428 List<ResolveInfo> services = 429 pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, mUserHandle); 430 if (services == null || services.size() == 0) { 431 return false; 432 } 433 434 for (ResolveInfo rInfo : services) { 435 final Bundle metaData = rInfo.serviceInfo.metaData; 436 if (metaData != null && 437 !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) { 438 return false; 439 } 440 } 441 442 return true; 443 } 444 445 /** 446 * Configures an always-on VPN connection through a specific application. 447 * This connection is automatically granted and persisted after a reboot. 448 * 449 * <p>The designated package should exist and declare a {@link VpnService} in its 450 * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, 451 * otherwise the call will fail. 452 * 453 * <p>Note that this method does not check if the VPN app supports always-on mode. The check is 454 * delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this 455 * method in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}. 456 * 457 * @param packageName the package to designate as always-on VPN supplier. 458 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 459 * @param lockdownWhitelist packages to be whitelisted from lockdown. 460 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 461 */ setAlwaysOnPackage( String packageName, boolean lockdown, List<String> lockdownWhitelist)462 public synchronized boolean setAlwaysOnPackage( 463 String packageName, boolean lockdown, List<String> lockdownWhitelist) { 464 enforceControlPermissionOrInternalCaller(); 465 466 if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist)) { 467 saveAlwaysOnPackage(); 468 return true; 469 } 470 return false; 471 } 472 473 /** 474 * Configures an always-on VPN connection through a specific application, the same as 475 * {@link #setAlwaysOnPackage}. 476 * 477 * Does not perform permission checks. Does not persist any of the changes to storage. 478 * 479 * @param packageName the package to designate as always-on VPN supplier. 480 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 481 * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if 482 * {@code lockdown} is {@code true}. Packages must not contain commas. 483 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 484 */ 485 @GuardedBy("this") setAlwaysOnPackageInternal( String packageName, boolean lockdown, List<String> lockdownWhitelist)486 private boolean setAlwaysOnPackageInternal( 487 String packageName, boolean lockdown, List<String> lockdownWhitelist) { 488 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 489 Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); 490 return false; 491 } 492 493 if (lockdownWhitelist != null) { 494 for (String pkg : lockdownWhitelist) { 495 if (pkg.contains(",")) { 496 Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg); 497 return false; 498 } 499 } 500 } 501 502 if (packageName != null) { 503 // Pre-authorize new always-on VPN package. 504 if (!setPackageAuthorization(packageName, true)) { 505 return false; 506 } 507 mAlwaysOn = true; 508 } else { 509 packageName = VpnConfig.LEGACY_VPN; 510 mAlwaysOn = false; 511 } 512 513 mLockdown = (mAlwaysOn && lockdown); 514 mLockdownWhitelist = (mLockdown && lockdownWhitelist != null) 515 ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist)) 516 : Collections.emptyList(); 517 518 if (isCurrentPreparedPackage(packageName)) { 519 updateAlwaysOnNotification(mNetworkInfo.getDetailedState()); 520 setVpnForcedLocked(mLockdown); 521 } else { 522 // Prepare this app. The notification will update as a side-effect of updateState(). 523 // It also calls setVpnForcedLocked(). 524 prepareInternal(packageName); 525 } 526 return true; 527 } 528 isNullOrLegacyVpn(String packageName)529 private static boolean isNullOrLegacyVpn(String packageName) { 530 return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName); 531 } 532 533 /** 534 * @return the package name of the VPN controller responsible for always-on VPN, 535 * or {@code null} if none is set or always-on VPN is controlled through 536 * lockdown instead. 537 */ getAlwaysOnPackage()538 public synchronized String getAlwaysOnPackage() { 539 enforceControlPermissionOrInternalCaller(); 540 return (mAlwaysOn ? mPackage : null); 541 } 542 543 /** 544 * @return an immutable list of packages whitelisted from always-on VPN lockdown. 545 */ getLockdownWhitelist()546 public synchronized List<String> getLockdownWhitelist() { 547 return mLockdown ? mLockdownWhitelist : null; 548 } 549 550 /** 551 * Save the always-on package and lockdown config into Settings.Secure 552 */ 553 @GuardedBy("this") saveAlwaysOnPackage()554 private void saveAlwaysOnPackage() { 555 final long token = Binder.clearCallingIdentity(); 556 try { 557 mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP, 558 getAlwaysOnPackage(), mUserHandle); 559 mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 560 (mAlwaysOn && mLockdown ? 1 : 0), mUserHandle); 561 mSystemServices.settingsSecurePutStringForUser( 562 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, 563 String.join(",", mLockdownWhitelist), mUserHandle); 564 } finally { 565 Binder.restoreCallingIdentity(token); 566 } 567 } 568 569 /** 570 * Load the always-on package and lockdown config from Settings.Secure 571 */ 572 @GuardedBy("this") loadAlwaysOnPackage()573 private void loadAlwaysOnPackage() { 574 final long token = Binder.clearCallingIdentity(); 575 try { 576 final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser( 577 Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle); 578 final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser( 579 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0; 580 final String whitelistString = mSystemServices.settingsSecureGetStringForUser( 581 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle); 582 final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString) 583 ? Collections.emptyList() : Arrays.asList(whitelistString.split(",")); 584 setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown, whitelistedPackages); 585 } finally { 586 Binder.restoreCallingIdentity(token); 587 } 588 } 589 590 /** 591 * @return {@code true} if the service was started, the service was already connected, or there 592 * was no always-on VPN to start. {@code false} otherwise. 593 */ startAlwaysOnVpn()594 public boolean startAlwaysOnVpn() { 595 final String alwaysOnPackage; 596 synchronized (this) { 597 alwaysOnPackage = getAlwaysOnPackage(); 598 // Skip if there is no service to start. 599 if (alwaysOnPackage == null) { 600 return true; 601 } 602 // Remove always-on VPN if it's not supported. 603 if (!isAlwaysOnPackageSupported(alwaysOnPackage)) { 604 setAlwaysOnPackage(null, false, null); 605 return false; 606 } 607 // Skip if the service is already established. This isn't bulletproof: it's not bound 608 // until after establish(), so if it's mid-setup onStartCommand will be sent twice, 609 // which may restart the connection. 610 if (getNetworkInfo().isConnected()) { 611 return true; 612 } 613 } 614 615 // Tell the OS that background services in this app need to be allowed for 616 // a short time, so we can bootstrap the VPN service. 617 final long oldId = Binder.clearCallingIdentity(); 618 try { 619 DeviceIdleController.LocalService idleController = 620 LocalServices.getService(DeviceIdleController.LocalService.class); 621 idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, 622 VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn"); 623 624 // Start the VPN service declared in the app's manifest. 625 Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); 626 serviceIntent.setPackage(alwaysOnPackage); 627 try { 628 return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null; 629 } catch (RuntimeException e) { 630 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e); 631 return false; 632 } 633 } finally { 634 Binder.restoreCallingIdentity(oldId); 635 } 636 } 637 638 /** 639 * Prepare for a VPN application. This method is designed to solve 640 * race conditions. It first compares the current prepared package 641 * with {@code oldPackage}. If they are the same, the prepared 642 * package is revoked and replaced with {@code newPackage}. If 643 * {@code oldPackage} is {@code null}, the comparison is omitted. 644 * If {@code newPackage} is the same package or {@code null}, the 645 * revocation is omitted. This method returns {@code true} if the 646 * operation is succeeded. 647 * 648 * Legacy VPN is handled specially since it is not a real package. 649 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 650 * it can be revoked by itself. 651 * 652 * Note: when we added VPN pre-consent in 653 * https://android.googlesource.com/platform/frameworks/base/+/0554260 654 * the names oldPackage and newPackage became misleading, because when 655 * an app is pre-consented, we actually prepare oldPackage, not newPackage. 656 * 657 * Their meanings actually are: 658 * 659 * - oldPackage non-null, newPackage null: App calling VpnService#prepare(). 660 * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn(). 661 * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect 662 * and revoke any current app VPN and re-prepare legacy vpn. 663 * 664 * TODO: Rename the variables - or split this method into two - and end this confusion. 665 * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN) 666 * to prepare(oldPackage=null, newPackage=LEGACY_VPN) 667 * 668 * @param oldPackage The package name of the old VPN application 669 * @param newPackage The package name of the new VPN application 670 * 671 * @return true if the operation succeeded. 672 */ prepare(String oldPackage, String newPackage)673 public synchronized boolean prepare(String oldPackage, String newPackage) { 674 if (oldPackage != null) { 675 // Stop an existing always-on VPN from being dethroned by other apps. 676 if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) { 677 return false; 678 } 679 680 // Package is not the same or old package was reinstalled. 681 if (!isCurrentPreparedPackage(oldPackage)) { 682 // The package doesn't match. We return false (to obtain user consent) unless the 683 // user has already consented to that VPN package. 684 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) { 685 prepareInternal(oldPackage); 686 return true; 687 } 688 return false; 689 } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 690 && !isVpnUserPreConsented(oldPackage)) { 691 // Currently prepared VPN is revoked, so unprepare it and return false. 692 prepareInternal(VpnConfig.LEGACY_VPN); 693 return false; 694 } 695 } 696 697 // Return true if we do not need to revoke. 698 if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) && 699 isCurrentPreparedPackage(newPackage))) { 700 return true; 701 } 702 703 // Check that the caller is authorized. 704 enforceControlPermission(); 705 706 // Stop an existing always-on VPN from being dethroned by other apps. 707 if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) { 708 return false; 709 } 710 711 prepareInternal(newPackage); 712 return true; 713 } 714 isCurrentPreparedPackage(String packageName)715 private boolean isCurrentPreparedPackage(String packageName) { 716 // We can't just check that packageName matches mPackage, because if the app was uninstalled 717 // and reinstalled it will no longer be prepared. Instead check the UID. 718 return getAppUid(packageName, mUserHandle) == mOwnerUID; 719 } 720 721 /** Prepare the VPN for the given package. Does not perform permission checks. */ prepareInternal(String newPackage)722 private void prepareInternal(String newPackage) { 723 long token = Binder.clearCallingIdentity(); 724 try { 725 // Reset the interface. 726 if (mInterface != null) { 727 mStatusIntent = null; 728 agentDisconnect(); 729 jniReset(mInterface); 730 mInterface = null; 731 mNetworkCapabilities.setUids(null); 732 } 733 734 // Revoke the connection or stop LegacyVpnRunner. 735 if (mConnection != null) { 736 try { 737 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 738 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 739 } catch (Exception e) { 740 // ignore 741 } 742 mContext.unbindService(mConnection); 743 mConnection = null; 744 } else if (mLegacyVpnRunner != null) { 745 mLegacyVpnRunner.exit(); 746 mLegacyVpnRunner = null; 747 } 748 749 try { 750 mNetd.denyProtect(mOwnerUID); 751 } catch (Exception e) { 752 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 753 } 754 755 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 756 mPackage = newPackage; 757 mOwnerUID = getAppUid(newPackage, mUserHandle); 758 mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); 759 try { 760 mNetd.allowProtect(mOwnerUID); 761 } catch (Exception e) { 762 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 763 } 764 mConfig = null; 765 766 updateState(DetailedState.IDLE, "prepare"); 767 setVpnForcedLocked(mLockdown); 768 } finally { 769 Binder.restoreCallingIdentity(token); 770 } 771 } 772 773 /** 774 * Set whether a package has the ability to launch VPNs without user intervention. 775 */ setPackageAuthorization(String packageName, boolean authorized)776 public boolean setPackageAuthorization(String packageName, boolean authorized) { 777 // Check if the caller is authorized. 778 enforceControlPermissionOrInternalCaller(); 779 780 int uid = getAppUid(packageName, mUserHandle); 781 if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { 782 // Authorization for nonexistent packages (or fake ones) can't be updated. 783 return false; 784 } 785 786 long token = Binder.clearCallingIdentity(); 787 try { 788 AppOpsManager appOps = 789 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 790 appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, uid, packageName, 791 authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); 792 return true; 793 } catch (Exception e) { 794 Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e); 795 } finally { 796 Binder.restoreCallingIdentity(token); 797 } 798 return false; 799 } 800 isVpnUserPreConsented(String packageName)801 private boolean isVpnUserPreConsented(String packageName) { 802 AppOpsManager appOps = 803 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 804 805 // Verify that the caller matches the given package and has permission to activate VPNs. 806 return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(), 807 packageName) == AppOpsManager.MODE_ALLOWED; 808 } 809 getAppUid(String app, int userHandle)810 private int getAppUid(String app, int userHandle) { 811 if (VpnConfig.LEGACY_VPN.equals(app)) { 812 return Process.myUid(); 813 } 814 PackageManager pm = mContext.getPackageManager(); 815 int result; 816 try { 817 result = pm.getPackageUidAsUser(app, userHandle); 818 } catch (NameNotFoundException e) { 819 result = -1; 820 } 821 return result; 822 } 823 doesPackageTargetAtLeastQ(String packageName)824 private boolean doesPackageTargetAtLeastQ(String packageName) { 825 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 826 return true; 827 } 828 PackageManager pm = mContext.getPackageManager(); 829 try { 830 ApplicationInfo appInfo = 831 pm.getApplicationInfoAsUser(packageName, 0 /*flags*/, mUserHandle); 832 return appInfo.targetSdkVersion >= VERSION_CODES.Q; 833 } catch (NameNotFoundException unused) { 834 Log.w(TAG, "Can't find \"" + packageName + "\""); 835 return false; 836 } 837 } 838 getNetworkInfo()839 public NetworkInfo getNetworkInfo() { 840 return mNetworkInfo; 841 } 842 getNetId()843 public int getNetId() { 844 return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET; 845 } 846 makeLinkProperties()847 private LinkProperties makeLinkProperties() { 848 boolean allowIPv4 = mConfig.allowIPv4; 849 boolean allowIPv6 = mConfig.allowIPv6; 850 851 LinkProperties lp = new LinkProperties(); 852 853 lp.setInterfaceName(mInterface); 854 855 if (mConfig.addresses != null) { 856 for (LinkAddress address : mConfig.addresses) { 857 lp.addLinkAddress(address); 858 allowIPv4 |= address.getAddress() instanceof Inet4Address; 859 allowIPv6 |= address.getAddress() instanceof Inet6Address; 860 } 861 } 862 863 if (mConfig.routes != null) { 864 for (RouteInfo route : mConfig.routes) { 865 lp.addRoute(route); 866 InetAddress address = route.getDestination().getAddress(); 867 allowIPv4 |= address instanceof Inet4Address; 868 allowIPv6 |= address instanceof Inet6Address; 869 } 870 } 871 872 if (mConfig.dnsServers != null) { 873 for (String dnsServer : mConfig.dnsServers) { 874 InetAddress address = InetAddress.parseNumericAddress(dnsServer); 875 lp.addDnsServer(address); 876 allowIPv4 |= address instanceof Inet4Address; 877 allowIPv6 |= address instanceof Inet6Address; 878 } 879 } 880 881 lp.setHttpProxy(mConfig.proxyInfo); 882 883 if (!allowIPv4) { 884 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); 885 } 886 if (!allowIPv6) { 887 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); 888 } 889 890 // Concatenate search domains into a string. 891 StringBuilder buffer = new StringBuilder(); 892 if (mConfig.searchDomains != null) { 893 for (String domain : mConfig.searchDomains) { 894 buffer.append(domain).append(' '); 895 } 896 } 897 lp.setDomains(buffer.toString().trim()); 898 899 // TODO: Stop setting the MTU in jniCreate and set it here. 900 901 return lp; 902 } 903 904 /** 905 * Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space. 906 * 907 * This returns true if the passed LinkedProperties contains routes to either most of the IPv4 908 * space or to most of the IPv6 address space, where "most" is defined by the value of the 909 * MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched 910 * by any of the routes, then it's decided that most of the space is routed. 911 * @hide 912 */ 913 @VisibleForTesting providesRoutesToMostDestinations(LinkProperties lp)914 static boolean providesRoutesToMostDestinations(LinkProperties lp) { 915 final List<RouteInfo> routes = lp.getAllRoutes(); 916 if (routes.size() > MAX_ROUTES_TO_EVALUATE) return true; 917 final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator(); 918 TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator); 919 TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator); 920 for (final RouteInfo route : routes) { 921 if (route.getType() == RouteInfo.RTN_UNREACHABLE) continue; 922 IpPrefix destination = route.getDestination(); 923 if (destination.isIPv4()) { 924 ipv4Prefixes.add(destination); 925 } else { 926 ipv6Prefixes.add(destination); 927 } 928 } 929 if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) { 930 return true; 931 } 932 return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes) 933 .compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0; 934 } 935 936 /** 937 * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without 938 * registering a new NetworkAgent. This is not always possible if the new VPN configuration 939 * has certain changes, in which case this method would just return {@code false}. 940 */ updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig)941 private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) { 942 // NetworkMisc cannot be updated without registering a new NetworkAgent. 943 if (oldConfig.allowBypass != mConfig.allowBypass) { 944 Log.i(TAG, "Handover not possible due to changes to allowBypass"); 945 return false; 946 } 947 948 // TODO: we currently do not support seamless handover if the allowed or disallowed 949 // applications have changed. Consider diffing UID ranges and only applying the delta. 950 if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) || 951 !Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) { 952 Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps"); 953 return false; 954 } 955 956 agent.sendLinkProperties(makeLinkProperties()); 957 return true; 958 } 959 agentConnect()960 private void agentConnect() { 961 LinkProperties lp = makeLinkProperties(); 962 963 // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel 964 // that falls back to the default network, which by definition provides INTERNET (unless 965 // there is no default network, in which case none of this matters in any sense). 966 // Also, it guarantees that when a VPN applies to an app, the VPN will always be reported 967 // as the network by getDefaultNetwork and registerDefaultNetworkCallback. This in turn 968 // protects the invariant that apps calling CM#bindProcessToNetwork(getDefaultNetwork()) 969 // the same as if they use the default network. 970 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 971 972 mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); 973 974 NetworkMisc networkMisc = new NetworkMisc(); 975 networkMisc.allowBypass = mConfig.allowBypass && !mLockdown; 976 977 mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid()); 978 mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle, 979 mConfig.allowedApplications, mConfig.disallowedApplications)); 980 long token = Binder.clearCallingIdentity(); 981 try { 982 mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */, 983 mNetworkInfo, mNetworkCapabilities, lp, 984 ConnectivityConstants.VPN_DEFAULT_SCORE, networkMisc, 985 NetworkFactory.SerialNumber.VPN) { 986 @Override 987 public void unwanted() { 988 // We are user controlled, not driven by NetworkRequest. 989 } 990 }; 991 } finally { 992 Binder.restoreCallingIdentity(token); 993 } 994 mNetworkInfo.setIsAvailable(true); 995 updateState(DetailedState.CONNECTED, "agentConnect"); 996 } 997 canHaveRestrictedProfile(int userId)998 private boolean canHaveRestrictedProfile(int userId) { 999 long token = Binder.clearCallingIdentity(); 1000 try { 1001 return UserManager.get(mContext).canHaveRestrictedProfile(userId); 1002 } finally { 1003 Binder.restoreCallingIdentity(token); 1004 } 1005 } 1006 agentDisconnect(NetworkAgent networkAgent)1007 private void agentDisconnect(NetworkAgent networkAgent) { 1008 if (networkAgent != null) { 1009 NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); 1010 networkInfo.setIsAvailable(false); 1011 networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 1012 networkAgent.sendNetworkInfo(networkInfo); 1013 } 1014 } 1015 agentDisconnect()1016 private void agentDisconnect() { 1017 if (mNetworkInfo.isConnected()) { 1018 mNetworkInfo.setIsAvailable(false); 1019 updateState(DetailedState.DISCONNECTED, "agentDisconnect"); 1020 mNetworkAgent = null; 1021 } 1022 } 1023 1024 /** 1025 * Establish a VPN network and return the file descriptor of the VPN interface. This methods 1026 * returns {@code null} if the application is revoked or not prepared. 1027 * 1028 * @param config The parameters to configure the network. 1029 * @return The file descriptor of the VPN interface. 1030 */ establish(VpnConfig config)1031 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 1032 // Check if the caller is already prepared. 1033 UserManager mgr = UserManager.get(mContext); 1034 if (Binder.getCallingUid() != mOwnerUID) { 1035 return null; 1036 } 1037 // Check to ensure consent hasn't been revoked since we were prepared. 1038 if (!isVpnUserPreConsented(mPackage)) { 1039 return null; 1040 } 1041 // Check if the service is properly declared. 1042 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 1043 intent.setClassName(mPackage, config.user); 1044 long token = Binder.clearCallingIdentity(); 1045 try { 1046 // Restricted users are not allowed to create VPNs, they are tied to Owner 1047 UserInfo user = mgr.getUserInfo(mUserHandle); 1048 if (user.isRestricted()) { 1049 throw new SecurityException("Restricted users cannot establish VPNs"); 1050 } 1051 1052 ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, 1053 null, 0, mUserHandle); 1054 if (info == null) { 1055 throw new SecurityException("Cannot find " + config.user); 1056 } 1057 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 1058 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 1059 } 1060 } catch (RemoteException e) { 1061 throw new SecurityException("Cannot find " + config.user); 1062 } finally { 1063 Binder.restoreCallingIdentity(token); 1064 } 1065 1066 // Save the old config in case we need to go back. 1067 VpnConfig oldConfig = mConfig; 1068 String oldInterface = mInterface; 1069 Connection oldConnection = mConnection; 1070 NetworkAgent oldNetworkAgent = mNetworkAgent; 1071 Set<UidRange> oldUsers = mNetworkCapabilities.getUids(); 1072 1073 // Configure the interface. Abort if any of these steps fails. 1074 ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); 1075 try { 1076 String interfaze = jniGetName(tun.getFd()); 1077 1078 // TEMP use the old jni calls until there is support for netd address setting 1079 StringBuilder builder = new StringBuilder(); 1080 for (LinkAddress address : config.addresses) { 1081 builder.append(" " + address); 1082 } 1083 if (jniSetAddresses(interfaze, builder.toString()) < 1) { 1084 throw new IllegalArgumentException("At least one address must be specified"); 1085 } 1086 Connection connection = new Connection(); 1087 if (!mContext.bindServiceAsUser(intent, connection, 1088 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 1089 new UserHandle(mUserHandle))) { 1090 throw new IllegalStateException("Cannot bind " + config.user); 1091 } 1092 1093 mConnection = connection; 1094 mInterface = interfaze; 1095 1096 // Fill more values. 1097 config.user = mPackage; 1098 config.interfaze = mInterface; 1099 config.startTime = SystemClock.elapsedRealtime(); 1100 mConfig = config; 1101 1102 // Set up forwarding and DNS rules. 1103 // First attempt to do a seamless handover that only changes the interface name and 1104 // parameters. If that fails, disconnect. 1105 if (oldConfig != null 1106 && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) { 1107 // Keep mNetworkAgent unchanged 1108 } else { 1109 mNetworkAgent = null; 1110 updateState(DetailedState.CONNECTING, "establish"); 1111 // Set up forwarding and DNS rules. 1112 agentConnect(); 1113 // Remove the old tun's user forwarding rules 1114 // The new tun's user rules have already been added above so they will take over 1115 // as rules are deleted. This prevents data leakage as the rules are moved over. 1116 agentDisconnect(oldNetworkAgent); 1117 } 1118 1119 if (oldConnection != null) { 1120 mContext.unbindService(oldConnection); 1121 } 1122 1123 if (oldInterface != null && !oldInterface.equals(interfaze)) { 1124 jniReset(oldInterface); 1125 } 1126 1127 try { 1128 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); 1129 } catch (IOException e) { 1130 throw new IllegalStateException( 1131 "Cannot set tunnel's fd as blocking=" + config.blocking, e); 1132 } 1133 } catch (RuntimeException e) { 1134 IoUtils.closeQuietly(tun); 1135 agentDisconnect(); 1136 // restore old state 1137 mConfig = oldConfig; 1138 mConnection = oldConnection; 1139 mNetworkCapabilities.setUids(oldUsers); 1140 mNetworkAgent = oldNetworkAgent; 1141 mInterface = oldInterface; 1142 throw e; 1143 } 1144 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 1145 return tun; 1146 } 1147 isRunningLocked()1148 private boolean isRunningLocked() { 1149 return mNetworkAgent != null && mInterface != null; 1150 } 1151 1152 // Returns true if the VPN has been established and the calling UID is its owner. Used to check 1153 // that a call to mutate VPN state is admissible. 1154 @VisibleForTesting isCallerEstablishedOwnerLocked()1155 protected boolean isCallerEstablishedOwnerLocked() { 1156 return isRunningLocked() && Binder.getCallingUid() == mOwnerUID; 1157 } 1158 1159 // Note: Return type guarantees results are deduped and sorted, which callers require. getAppsUids(List<String> packageNames, int userHandle)1160 private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) { 1161 SortedSet<Integer> uids = new TreeSet<Integer>(); 1162 for (String app : packageNames) { 1163 int uid = getAppUid(app, userHandle); 1164 if (uid != -1) uids.add(uid); 1165 } 1166 return uids; 1167 } 1168 1169 /** 1170 * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs 1171 * associated with one user, and any restricted profiles attached to that user. 1172 * 1173 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 1174 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 1175 * in each user and profile will be included. 1176 * 1177 * @param userHandle The userId to create UID ranges for along with any of its restricted 1178 * profiles. 1179 * @param allowedApplications (optional) whitelist of applications to include. 1180 * @param disallowedApplications (optional) blacklist of applications to exclude. 1181 */ 1182 @VisibleForTesting createUserAndRestrictedProfilesRanges(@serIdInt int userHandle, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications)1183 Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle, 1184 @Nullable List<String> allowedApplications, 1185 @Nullable List<String> disallowedApplications) { 1186 final Set<UidRange> ranges = new ArraySet<>(); 1187 1188 // Assign the top-level user to the set of ranges 1189 addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications); 1190 1191 // If the user can have restricted profiles, assign all its restricted profiles too 1192 if (canHaveRestrictedProfile(userHandle)) { 1193 final long token = Binder.clearCallingIdentity(); 1194 List<UserInfo> users; 1195 try { 1196 users = UserManager.get(mContext).getUsers(true); 1197 } finally { 1198 Binder.restoreCallingIdentity(token); 1199 } 1200 for (UserInfo user : users) { 1201 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) { 1202 addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications); 1203 } 1204 } 1205 } 1206 return ranges; 1207 } 1208 1209 /** 1210 * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs 1211 * associated with one user. 1212 * 1213 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 1214 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 1215 * in the user will be included. 1216 * 1217 * @param ranges {@link Set} of {@link UidRange}s to which to add. 1218 * @param userHandle The userId to add to {@param ranges}. 1219 * @param allowedApplications (optional) whitelist of applications to include. 1220 * @param disallowedApplications (optional) blacklist of applications to exclude. 1221 */ 1222 @VisibleForTesting addUserToRanges(@onNull Set<UidRange> ranges, @UserIdInt int userHandle, @Nullable List<String> allowedApplications, @Nullable List<String> disallowedApplications)1223 void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle, 1224 @Nullable List<String> allowedApplications, 1225 @Nullable List<String> disallowedApplications) { 1226 if (allowedApplications != null) { 1227 // Add ranges covering all UIDs for allowedApplications. 1228 int start = -1, stop = -1; 1229 for (int uid : getAppsUids(allowedApplications, userHandle)) { 1230 if (start == -1) { 1231 start = uid; 1232 } else if (uid != stop + 1) { 1233 ranges.add(new UidRange(start, stop)); 1234 start = uid; 1235 } 1236 stop = uid; 1237 } 1238 if (start != -1) ranges.add(new UidRange(start, stop)); 1239 } else if (disallowedApplications != null) { 1240 // Add all ranges for user skipping UIDs for disallowedApplications. 1241 final UidRange userRange = UidRange.createForUser(userHandle); 1242 int start = userRange.start; 1243 for (int uid : getAppsUids(disallowedApplications, userHandle)) { 1244 if (uid == start) { 1245 start++; 1246 } else { 1247 ranges.add(new UidRange(start, uid - 1)); 1248 start = uid + 1; 1249 } 1250 } 1251 if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop)); 1252 } else { 1253 // Add all UIDs for the user. 1254 ranges.add(UidRange.createForUser(userHandle)); 1255 } 1256 } 1257 1258 // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that 1259 // apply to userHandle. uidRangesForUser(int userHandle, Set<UidRange> existingRanges)1260 static private List<UidRange> uidRangesForUser(int userHandle, Set<UidRange> existingRanges) { 1261 // UidRange#createForUser returns the entire range of UIDs available to a macro-user. 1262 // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE} 1263 final UidRange userRange = UidRange.createForUser(userHandle); 1264 final List<UidRange> ranges = new ArrayList<UidRange>(); 1265 for (UidRange range : existingRanges) { 1266 if (userRange.containsRange(range)) { 1267 ranges.add(range); 1268 } 1269 } 1270 return ranges; 1271 } 1272 1273 /** 1274 * Updates UID ranges for this VPN and also updates its internal capabilities. 1275 * 1276 * <p>Should be called on primary ConnectivityService thread. 1277 */ onUserAdded(int userHandle)1278 public void onUserAdded(int userHandle) { 1279 // If the user is restricted tie them to the parent user's VPN 1280 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 1281 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 1282 synchronized(Vpn.this) { 1283 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); 1284 if (existingRanges != null) { 1285 try { 1286 addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications, 1287 mConfig.disallowedApplications); 1288 // ConnectivityService will call {@link #updateCapabilities} and apply 1289 // those for VPN network. 1290 mNetworkCapabilities.setUids(existingRanges); 1291 } catch (Exception e) { 1292 Log.wtf(TAG, "Failed to add restricted user to owner", e); 1293 } 1294 } 1295 setVpnForcedLocked(mLockdown); 1296 } 1297 } 1298 } 1299 1300 /** 1301 * Updates UID ranges for this VPN and also updates its capabilities. 1302 * 1303 * <p>Should be called on primary ConnectivityService thread. 1304 */ onUserRemoved(int userHandle)1305 public void onUserRemoved(int userHandle) { 1306 // clean up if restricted 1307 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 1308 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 1309 synchronized(Vpn.this) { 1310 final Set<UidRange> existingRanges = mNetworkCapabilities.getUids(); 1311 if (existingRanges != null) { 1312 try { 1313 final List<UidRange> removedRanges = 1314 uidRangesForUser(userHandle, existingRanges); 1315 existingRanges.removeAll(removedRanges); 1316 // ConnectivityService will call {@link #updateCapabilities} and 1317 // apply those for VPN network. 1318 mNetworkCapabilities.setUids(existingRanges); 1319 } catch (Exception e) { 1320 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 1321 } 1322 } 1323 setVpnForcedLocked(mLockdown); 1324 } 1325 } 1326 } 1327 1328 /** 1329 * Called when the user associated with this VPN has just been stopped. 1330 */ onUserStopped()1331 public synchronized void onUserStopped() { 1332 // Switch off networking lockdown (if it was enabled) 1333 setLockdown(false); 1334 mAlwaysOn = false; 1335 1336 // Quit any active connections 1337 agentDisconnect(); 1338 } 1339 1340 /** 1341 * Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN 1342 * service app itself and whitelisted packages, to only sockets that have had {@code protect()} 1343 * called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the 1344 * kernel. 1345 * 1346 * The exception for the VPN UID isn't technically necessary -- setup should use protected 1347 * sockets -- but in practice it saves apps that don't protect their sockets from breaking. 1348 * 1349 * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to 1350 * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}. 1351 * 1352 * @param enforce {@code true} to require that all traffic under the jurisdiction of this 1353 * {@link Vpn} goes through a VPN connection or is blocked until one is 1354 * available, {@code false} to lift the requirement. 1355 * 1356 * @see #mBlockedUsers 1357 */ 1358 @GuardedBy("this") setVpnForcedLocked(boolean enforce)1359 private void setVpnForcedLocked(boolean enforce) { 1360 final List<String> exemptedPackages; 1361 if (isNullOrLegacyVpn(mPackage)) { 1362 exemptedPackages = null; 1363 } else { 1364 exemptedPackages = new ArrayList<>(mLockdownWhitelist); 1365 exemptedPackages.add(mPackage); 1366 } 1367 final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers); 1368 1369 Set<UidRange> addedRanges = Collections.emptySet(); 1370 if (enforce) { 1371 addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, 1372 /* allowedApplications */ null, 1373 /* disallowedApplications */ exemptedPackages); 1374 1375 // The UID range of the first user (0-99999) would block the IPSec traffic, which comes 1376 // directly from the kernel and is marked as uid=0. So we adjust the range to allow 1377 // it through (b/69873852). 1378 for (UidRange range : addedRanges) { 1379 if (range.start == 0) { 1380 addedRanges.remove(range); 1381 if (range.stop != 0) { 1382 addedRanges.add(new UidRange(1, range.stop)); 1383 } 1384 } 1385 } 1386 1387 removedRanges.removeAll(addedRanges); 1388 addedRanges.removeAll(mBlockedUsers); 1389 } 1390 1391 setAllowOnlyVpnForUids(false, removedRanges); 1392 setAllowOnlyVpnForUids(true, addedRanges); 1393 } 1394 1395 /** 1396 * Either add or remove a list of {@link UidRange}s to the list of UIDs that are only allowed 1397 * to make connections through sockets that have had {@code protect()} called on them. 1398 * 1399 * @param enforce {@code true} to add to the blacklist, {@code false} to remove. 1400 * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is 1401 * {@code true}) or to remove. 1402 * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, 1403 * including added ranges that already existed or removed ones that didn't. 1404 */ 1405 @GuardedBy("this") setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges)1406 private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) { 1407 if (ranges.size() == 0) { 1408 return true; 1409 } 1410 final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]); 1411 try { 1412 mNetd.setAllowOnlyVpnForUids(enforce, rangesArray); 1413 } catch (RemoteException | RuntimeException e) { 1414 Log.e(TAG, "Updating blocked=" + enforce 1415 + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e); 1416 return false; 1417 } 1418 if (enforce) { 1419 mBlockedUsers.addAll(ranges); 1420 } else { 1421 mBlockedUsers.removeAll(ranges); 1422 } 1423 return true; 1424 } 1425 1426 /** 1427 * Return the configuration of the currently running VPN. 1428 */ getVpnConfig()1429 public VpnConfig getVpnConfig() { 1430 enforceControlPermission(); 1431 return mConfig; 1432 } 1433 1434 @Deprecated interfaceStatusChanged(String iface, boolean up)1435 public synchronized void interfaceStatusChanged(String iface, boolean up) { 1436 try { 1437 mObserver.interfaceStatusChanged(iface, up); 1438 } catch (RemoteException e) { 1439 // ignored; target is local 1440 } 1441 } 1442 1443 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 1444 @Override 1445 public void interfaceStatusChanged(String interfaze, boolean up) { 1446 synchronized (Vpn.this) { 1447 if (!up && mLegacyVpnRunner != null) { 1448 mLegacyVpnRunner.check(interfaze); 1449 } 1450 } 1451 } 1452 1453 @Override 1454 public void interfaceRemoved(String interfaze) { 1455 synchronized (Vpn.this) { 1456 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 1457 mStatusIntent = null; 1458 mNetworkCapabilities.setUids(null); 1459 mConfig = null; 1460 mInterface = null; 1461 if (mConnection != null) { 1462 mContext.unbindService(mConnection); 1463 mConnection = null; 1464 agentDisconnect(); 1465 } else if (mLegacyVpnRunner != null) { 1466 mLegacyVpnRunner.exit(); 1467 mLegacyVpnRunner = null; 1468 } 1469 } 1470 } 1471 } 1472 }; 1473 enforceControlPermission()1474 private void enforceControlPermission() { 1475 mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller"); 1476 } 1477 enforceControlPermissionOrInternalCaller()1478 private void enforceControlPermissionOrInternalCaller() { 1479 // Require the caller to be either an application with CONTROL_VPN permission or a process 1480 // in the system server. 1481 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN, 1482 "Unauthorized Caller"); 1483 } 1484 enforceSettingsPermission()1485 private void enforceSettingsPermission() { 1486 mContext.enforceCallingOrSelfPermission(Manifest.permission.NETWORK_SETTINGS, 1487 "Unauthorized Caller"); 1488 } 1489 1490 private class Connection implements ServiceConnection { 1491 private IBinder mService; 1492 1493 @Override onServiceConnected(ComponentName name, IBinder service)1494 public void onServiceConnected(ComponentName name, IBinder service) { 1495 mService = service; 1496 } 1497 1498 @Override onServiceDisconnected(ComponentName name)1499 public void onServiceDisconnected(ComponentName name) { 1500 mService = null; 1501 } 1502 } 1503 prepareStatusIntent()1504 private void prepareStatusIntent() { 1505 final long token = Binder.clearCallingIdentity(); 1506 try { 1507 mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext); 1508 } finally { 1509 Binder.restoreCallingIdentity(token); 1510 } 1511 } 1512 addAddress(String address, int prefixLength)1513 public synchronized boolean addAddress(String address, int prefixLength) { 1514 if (!isCallerEstablishedOwnerLocked()) { 1515 return false; 1516 } 1517 boolean success = jniAddAddress(mInterface, address, prefixLength); 1518 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1519 return success; 1520 } 1521 removeAddress(String address, int prefixLength)1522 public synchronized boolean removeAddress(String address, int prefixLength) { 1523 if (!isCallerEstablishedOwnerLocked()) { 1524 return false; 1525 } 1526 boolean success = jniDelAddress(mInterface, address, prefixLength); 1527 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1528 return success; 1529 } 1530 1531 /** 1532 * Updates underlying network set. 1533 * 1534 * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from 1535 * ConnectivityService thread to get updated capabilities. 1536 */ setUnderlyingNetworks(Network[] networks)1537 public synchronized boolean setUnderlyingNetworks(Network[] networks) { 1538 if (!isCallerEstablishedOwnerLocked()) { 1539 return false; 1540 } 1541 if (networks == null) { 1542 mConfig.underlyingNetworks = null; 1543 } else { 1544 mConfig.underlyingNetworks = new Network[networks.length]; 1545 for (int i = 0; i < networks.length; ++i) { 1546 if (networks[i] == null) { 1547 mConfig.underlyingNetworks[i] = null; 1548 } else { 1549 mConfig.underlyingNetworks[i] = new Network(networks[i].netId); 1550 } 1551 } 1552 } 1553 return true; 1554 } 1555 getUnderlyingNetworks()1556 public synchronized Network[] getUnderlyingNetworks() { 1557 if (!isRunningLocked()) { 1558 return null; 1559 } 1560 return mConfig.underlyingNetworks; 1561 } 1562 1563 /** 1564 * This method should only be called by ConnectivityService because it doesn't 1565 * have enough data to fill VpnInfo.primaryUnderlyingIface field. 1566 */ getVpnInfo()1567 public synchronized VpnInfo getVpnInfo() { 1568 if (!isRunningLocked()) { 1569 return null; 1570 } 1571 1572 VpnInfo info = new VpnInfo(); 1573 info.ownerUid = mOwnerUID; 1574 info.vpnIface = mInterface; 1575 return info; 1576 } 1577 appliesToUid(int uid)1578 public synchronized boolean appliesToUid(int uid) { 1579 if (!isRunningLocked()) { 1580 return false; 1581 } 1582 return mNetworkCapabilities.appliesToUid(uid); 1583 } 1584 1585 /** 1586 * @param uid The target uid. 1587 * 1588 * @return {@code true} if {@code uid} is included in one of the mBlockedUsers ranges and the 1589 * VPN is not connected, or if the VPN is connected but does not apply to the {@code uid}. 1590 * 1591 * @apiNote This method don't check VPN lockdown status. 1592 * @see #mBlockedUsers 1593 */ isBlockingUid(int uid)1594 public synchronized boolean isBlockingUid(int uid) { 1595 if (mNetworkInfo.isConnected()) { 1596 return !appliesToUid(uid); 1597 } else { 1598 return UidRange.containsUid(mBlockedUsers, uid); 1599 } 1600 } 1601 updateAlwaysOnNotification(DetailedState networkState)1602 private void updateAlwaysOnNotification(DetailedState networkState) { 1603 final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); 1604 1605 final UserHandle user = UserHandle.of(mUserHandle); 1606 final long token = Binder.clearCallingIdentity(); 1607 try { 1608 final NotificationManager notificationManager = NotificationManager.from(mContext); 1609 if (!visible) { 1610 notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user); 1611 return; 1612 } 1613 final Intent intent = new Intent(); 1614 intent.setComponent(ComponentName.unflattenFromString(mContext.getString( 1615 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))); 1616 intent.putExtra("lockdown", mLockdown); 1617 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1618 final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser( 1619 intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user); 1620 final Notification.Builder builder = 1621 new Notification.Builder(mContext, SystemNotificationChannels.VPN) 1622 .setSmallIcon(R.drawable.vpn_connected) 1623 .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected)) 1624 .setContentText(mContext.getString(R.string.vpn_lockdown_config)) 1625 .setContentIntent(configIntent) 1626 .setCategory(Notification.CATEGORY_SYSTEM) 1627 .setVisibility(Notification.VISIBILITY_PUBLIC) 1628 .setOngoing(true) 1629 .setColor(mContext.getColor(R.color.system_notification_accent_color)); 1630 notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, 1631 builder.build(), user); 1632 } finally { 1633 Binder.restoreCallingIdentity(token); 1634 } 1635 } 1636 1637 /** 1638 * Facade for system service calls that change, or depend on, state outside of 1639 * {@link ConnectivityService} and have hard-to-mock interfaces. 1640 * 1641 * @see com.android.server.connectivity.VpnTest 1642 */ 1643 @VisibleForTesting 1644 public static class SystemServices { 1645 private final Context mContext; 1646 SystemServices(@onNull Context context)1647 public SystemServices(@NonNull Context context) { 1648 mContext = context; 1649 } 1650 1651 /** 1652 * @see PendingIntent#getActivityAsUser() 1653 */ pendingIntentGetActivityAsUser( Intent intent, int flags, UserHandle user)1654 public PendingIntent pendingIntentGetActivityAsUser( 1655 Intent intent, int flags, UserHandle user) { 1656 return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags, 1657 null /*options*/, user); 1658 } 1659 1660 /** 1661 * @see Settings.Secure#putStringForUser 1662 */ settingsSecurePutStringForUser(String key, String value, int userId)1663 public void settingsSecurePutStringForUser(String key, String value, int userId) { 1664 Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId); 1665 } 1666 1667 /** 1668 * @see Settings.Secure#putIntForUser 1669 */ settingsSecurePutIntForUser(String key, int value, int userId)1670 public void settingsSecurePutIntForUser(String key, int value, int userId) { 1671 Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId); 1672 } 1673 1674 /** 1675 * @see Settings.Secure#getStringForUser 1676 */ settingsSecureGetStringForUser(String key, int userId)1677 public String settingsSecureGetStringForUser(String key, int userId) { 1678 return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId); 1679 } 1680 1681 /** 1682 * @see Settings.Secure#getIntForUser 1683 */ settingsSecureGetIntForUser(String key, int def, int userId)1684 public int settingsSecureGetIntForUser(String key, int def, int userId) { 1685 return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId); 1686 } 1687 } 1688 jniCreate(int mtu)1689 private native int jniCreate(int mtu); jniGetName(int tun)1690 private native String jniGetName(int tun); jniSetAddresses(String interfaze, String addresses)1691 private native int jniSetAddresses(String interfaze, String addresses); jniReset(String interfaze)1692 private native void jniReset(String interfaze); jniCheck(String interfaze)1693 private native int jniCheck(String interfaze); jniAddAddress(String interfaze, String address, int prefixLen)1694 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); jniDelAddress(String interfaze, String address, int prefixLen)1695 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 1696 findIPv4DefaultRoute(LinkProperties prop)1697 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 1698 for (RouteInfo route : prop.getAllRoutes()) { 1699 // Currently legacy VPN only works on IPv4. 1700 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 1701 return route; 1702 } 1703 } 1704 1705 throw new IllegalStateException("Unable to find IPv4 default gateway"); 1706 } 1707 1708 /** 1709 * Start legacy VPN, controlling native daemons as needed. Creates a 1710 * secondary thread to perform connection work, returning quickly. 1711 * 1712 * Should only be called to respond to Binder requests as this enforces caller permission. Use 1713 * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the 1714 * permission check only when the caller is trusted (or the call is initiated by the system). 1715 */ startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress)1716 public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) { 1717 enforceControlPermission(); 1718 long token = Binder.clearCallingIdentity(); 1719 try { 1720 startLegacyVpnPrivileged(profile, keyStore, egress); 1721 } finally { 1722 Binder.restoreCallingIdentity(token); 1723 } 1724 } 1725 1726 /** 1727 * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check 1728 * permissions under the assumption that the caller is the system. 1729 * 1730 * Callers are responsible for checking permissions if needed. 1731 */ startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore, LinkProperties egress)1732 public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore, 1733 LinkProperties egress) { 1734 UserManager mgr = UserManager.get(mContext); 1735 UserInfo user = mgr.getUserInfo(mUserHandle); 1736 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, 1737 new UserHandle(mUserHandle))) { 1738 throw new SecurityException("Restricted users cannot establish VPNs"); 1739 } 1740 1741 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 1742 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 1743 final String iface = ipv4DefaultRoute.getInterface(); 1744 1745 // Load certificates. 1746 String privateKey = ""; 1747 String userCert = ""; 1748 String caCert = ""; 1749 String serverCert = ""; 1750 if (!profile.ipsecUserCert.isEmpty()) { 1751 privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; 1752 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 1753 userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1754 } 1755 if (!profile.ipsecCaCert.isEmpty()) { 1756 byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 1757 caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1758 } 1759 if (!profile.ipsecServerCert.isEmpty()) { 1760 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 1761 serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1762 } 1763 if (privateKey == null || userCert == null || caCert == null || serverCert == null) { 1764 throw new IllegalStateException("Cannot load credentials"); 1765 } 1766 1767 // Prepare arguments for racoon. 1768 String[] racoon = null; 1769 switch (profile.type) { 1770 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 1771 racoon = new String[] { 1772 iface, profile.server, "udppsk", profile.ipsecIdentifier, 1773 profile.ipsecSecret, "1701", 1774 }; 1775 break; 1776 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 1777 racoon = new String[] { 1778 iface, profile.server, "udprsa", privateKey, userCert, 1779 caCert, serverCert, "1701", 1780 }; 1781 break; 1782 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 1783 racoon = new String[] { 1784 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 1785 profile.ipsecSecret, profile.username, profile.password, "", gateway, 1786 }; 1787 break; 1788 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 1789 racoon = new String[] { 1790 iface, profile.server, "xauthrsa", privateKey, userCert, 1791 caCert, serverCert, profile.username, profile.password, "", gateway, 1792 }; 1793 break; 1794 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 1795 racoon = new String[] { 1796 iface, profile.server, "hybridrsa", 1797 caCert, serverCert, profile.username, profile.password, "", gateway, 1798 }; 1799 break; 1800 } 1801 1802 // Prepare arguments for mtpd. 1803 String[] mtpd = null; 1804 switch (profile.type) { 1805 case VpnProfile.TYPE_PPTP: 1806 mtpd = new String[] { 1807 iface, "pptp", profile.server, "1723", 1808 "name", profile.username, "password", profile.password, 1809 "linkname", "vpn", "refuse-eap", "nodefaultroute", 1810 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 1811 (profile.mppe ? "+mppe" : "nomppe"), 1812 }; 1813 break; 1814 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 1815 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 1816 mtpd = new String[] { 1817 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 1818 "name", profile.username, "password", profile.password, 1819 "linkname", "vpn", "refuse-eap", "nodefaultroute", 1820 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 1821 }; 1822 break; 1823 } 1824 1825 VpnConfig config = new VpnConfig(); 1826 config.legacy = true; 1827 config.user = profile.key; 1828 config.interfaze = iface; 1829 config.session = profile.name; 1830 config.isMetered = false; 1831 config.proxyInfo = profile.proxy; 1832 1833 config.addLegacyRoutes(profile.routes); 1834 if (!profile.dnsServers.isEmpty()) { 1835 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 1836 } 1837 if (!profile.searchDomains.isEmpty()) { 1838 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 1839 } 1840 startLegacyVpn(config, racoon, mtpd, profile); 1841 } 1842 startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile)1843 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, 1844 VpnProfile profile) { 1845 stopLegacyVpnPrivileged(); 1846 1847 // Prepare for the new request. 1848 prepareInternal(VpnConfig.LEGACY_VPN); 1849 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 1850 1851 // Start a new LegacyVpnRunner and we are done! 1852 mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile); 1853 mLegacyVpnRunner.start(); 1854 } 1855 1856 /** Stop legacy VPN. Permissions must be checked by callers. */ stopLegacyVpnPrivileged()1857 public synchronized void stopLegacyVpnPrivileged() { 1858 if (mLegacyVpnRunner != null) { 1859 mLegacyVpnRunner.exit(); 1860 mLegacyVpnRunner = null; 1861 1862 synchronized (LegacyVpnRunner.TAG) { 1863 // wait for old thread to completely finish before spinning up 1864 // new instance, otherwise state updates can be out of order. 1865 } 1866 } 1867 } 1868 1869 /** 1870 * Return the information of the current ongoing legacy VPN. 1871 */ getLegacyVpnInfo()1872 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 1873 // Check if the caller is authorized. 1874 enforceControlPermission(); 1875 return getLegacyVpnInfoPrivileged(); 1876 } 1877 1878 /** 1879 * Return the information of the current ongoing legacy VPN. 1880 * Callers are responsible for checking permissions if needed. 1881 */ getLegacyVpnInfoPrivileged()1882 public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() { 1883 if (mLegacyVpnRunner == null) return null; 1884 1885 final LegacyVpnInfo info = new LegacyVpnInfo(); 1886 info.key = mConfig.user; 1887 info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); 1888 if (mNetworkInfo.isConnected()) { 1889 info.intent = mStatusIntent; 1890 } 1891 return info; 1892 } 1893 getLegacyVpnConfig()1894 public VpnConfig getLegacyVpnConfig() { 1895 if (mLegacyVpnRunner != null) { 1896 return mConfig; 1897 } else { 1898 return null; 1899 } 1900 } 1901 1902 /** 1903 * Bringing up a VPN connection takes time, and that is all this thread 1904 * does. Here we have plenty of time. The only thing we need to take 1905 * care of is responding to interruptions as soon as possible. Otherwise 1906 * requests will pile up. This could be done in a Handler as a state 1907 * machine, but it is much easier to read in the current form. 1908 */ 1909 private class LegacyVpnRunner extends Thread { 1910 private static final String TAG = "LegacyVpnRunner"; 1911 1912 private final String[] mDaemons; 1913 private final String[][] mArguments; 1914 private final LocalSocket[] mSockets; 1915 private final String mOuterInterface; 1916 private final AtomicInteger mOuterConnection = 1917 new AtomicInteger(ConnectivityManager.TYPE_NONE); 1918 private final VpnProfile mProfile; 1919 1920 private long mBringupStartTime = -1; 1921 1922 /** 1923 * Watch for the outer connection (passing in the constructor) going away. 1924 */ 1925 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 1926 @Override 1927 public void onReceive(Context context, Intent intent) { 1928 if (!mEnableTeardown) return; 1929 1930 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1931 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1932 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 1933 NetworkInfo info = (NetworkInfo)intent.getExtra( 1934 ConnectivityManager.EXTRA_NETWORK_INFO); 1935 if (info != null && !info.isConnectedOrConnecting()) { 1936 try { 1937 mObserver.interfaceStatusChanged(mOuterInterface, false); 1938 } catch (RemoteException e) {} 1939 } 1940 } 1941 } 1942 } 1943 }; 1944 LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile)1945 LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { 1946 super(TAG); 1947 mConfig = config; 1948 mDaemons = new String[] {"racoon", "mtpd"}; 1949 // TODO: clear arguments from memory once launched 1950 mArguments = new String[][] {racoon, mtpd}; 1951 mSockets = new LocalSocket[mDaemons.length]; 1952 1953 // This is the interface which VPN is running on, 1954 // mConfig.interfaze will change to point to OUR 1955 // internal interface soon. TODO - add inner/outer to mconfig 1956 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 1957 // we will leave the VPN up. We should check that it's still there/connected after 1958 // registering 1959 mOuterInterface = mConfig.interfaze; 1960 1961 mProfile = profile; 1962 1963 if (!TextUtils.isEmpty(mOuterInterface)) { 1964 final ConnectivityManager cm = ConnectivityManager.from(mContext); 1965 for (Network network : cm.getAllNetworks()) { 1966 final LinkProperties lp = cm.getLinkProperties(network); 1967 if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { 1968 final NetworkInfo networkInfo = cm.getNetworkInfo(network); 1969 if (networkInfo != null) mOuterConnection.set(networkInfo.getType()); 1970 } 1971 } 1972 } 1973 1974 IntentFilter filter = new IntentFilter(); 1975 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 1976 mContext.registerReceiver(mBroadcastReceiver, filter); 1977 } 1978 check(String interfaze)1979 public void check(String interfaze) { 1980 if (interfaze.equals(mOuterInterface)) { 1981 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 1982 exit(); 1983 } 1984 } 1985 exit()1986 public void exit() { 1987 // We assume that everything is reset after stopping the daemons. 1988 interrupt(); 1989 agentDisconnect(); 1990 try { 1991 mContext.unregisterReceiver(mBroadcastReceiver); 1992 } catch (IllegalArgumentException e) {} 1993 } 1994 1995 @Override run()1996 public void run() { 1997 // Wait for the previous thread since it has been interrupted. 1998 Log.v(TAG, "Waiting"); 1999 synchronized (TAG) { 2000 Log.v(TAG, "Executing"); 2001 try { 2002 bringup(); 2003 waitForDaemonsToStop(); 2004 interrupted(); // Clear interrupt flag if execute called exit. 2005 } catch (InterruptedException e) { 2006 } finally { 2007 for (LocalSocket socket : mSockets) { 2008 IoUtils.closeQuietly(socket); 2009 } 2010 // This sleep is necessary for racoon to successfully complete sending delete 2011 // message to server. 2012 try { 2013 Thread.sleep(50); 2014 } catch (InterruptedException e) { 2015 } 2016 for (String daemon : mDaemons) { 2017 SystemService.stop(daemon); 2018 } 2019 } 2020 agentDisconnect(); 2021 } 2022 } 2023 checkInterruptAndDelay(boolean sleepLonger)2024 private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException { 2025 long now = SystemClock.elapsedRealtime(); 2026 if (now - mBringupStartTime <= 60000) { 2027 Thread.sleep(sleepLonger ? 200 : 1); 2028 } else { 2029 updateState(DetailedState.FAILED, "checkpoint"); 2030 throw new IllegalStateException("VPN bringup took too long"); 2031 } 2032 } 2033 bringup()2034 private void bringup() { 2035 // Catch all exceptions so we can clean up a few things. 2036 boolean initFinished = false; 2037 try { 2038 // Initialize the timer. 2039 mBringupStartTime = SystemClock.elapsedRealtime(); 2040 2041 // Wait for the daemons to stop. 2042 for (String daemon : mDaemons) { 2043 while (!SystemService.isStopped(daemon)) { 2044 checkInterruptAndDelay(true); 2045 } 2046 } 2047 2048 // Clear the previous state. 2049 File state = new File("/data/misc/vpn/state"); 2050 state.delete(); 2051 if (state.exists()) { 2052 throw new IllegalStateException("Cannot delete the state"); 2053 } 2054 new File("/data/misc/vpn/abort").delete(); 2055 initFinished = true; 2056 2057 // Check if we need to restart any of the daemons. 2058 boolean restart = false; 2059 for (String[] arguments : mArguments) { 2060 restart = restart || (arguments != null); 2061 } 2062 if (!restart) { 2063 agentDisconnect(); 2064 return; 2065 } 2066 updateState(DetailedState.CONNECTING, "execute"); 2067 2068 // Start the daemon with arguments. 2069 for (int i = 0; i < mDaemons.length; ++i) { 2070 String[] arguments = mArguments[i]; 2071 if (arguments == null) { 2072 continue; 2073 } 2074 2075 // Start the daemon. 2076 String daemon = mDaemons[i]; 2077 SystemService.start(daemon); 2078 2079 // Wait for the daemon to start. 2080 while (!SystemService.isRunning(daemon)) { 2081 checkInterruptAndDelay(true); 2082 } 2083 2084 // Create the control socket. 2085 mSockets[i] = new LocalSocket(); 2086 LocalSocketAddress address = new LocalSocketAddress( 2087 daemon, LocalSocketAddress.Namespace.RESERVED); 2088 2089 // Wait for the socket to connect. 2090 while (true) { 2091 try { 2092 mSockets[i].connect(address); 2093 break; 2094 } catch (Exception e) { 2095 // ignore 2096 } 2097 checkInterruptAndDelay(true); 2098 } 2099 mSockets[i].setSoTimeout(500); 2100 2101 // Send over the arguments. 2102 OutputStream out = mSockets[i].getOutputStream(); 2103 for (String argument : arguments) { 2104 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 2105 if (bytes.length >= 0xFFFF) { 2106 throw new IllegalArgumentException("Argument is too large"); 2107 } 2108 out.write(bytes.length >> 8); 2109 out.write(bytes.length); 2110 out.write(bytes); 2111 checkInterruptAndDelay(false); 2112 } 2113 out.write(0xFF); 2114 out.write(0xFF); 2115 out.flush(); 2116 2117 // Wait for End-of-File. 2118 InputStream in = mSockets[i].getInputStream(); 2119 while (true) { 2120 try { 2121 if (in.read() == -1) { 2122 break; 2123 } 2124 } catch (Exception e) { 2125 // ignore 2126 } 2127 checkInterruptAndDelay(true); 2128 } 2129 } 2130 2131 // Wait for the daemons to create the new state. 2132 while (!state.exists()) { 2133 // Check if a running daemon is dead. 2134 for (int i = 0; i < mDaemons.length; ++i) { 2135 String daemon = mDaemons[i]; 2136 if (mArguments[i] != null && !SystemService.isRunning(daemon)) { 2137 throw new IllegalStateException(daemon + " is dead"); 2138 } 2139 } 2140 checkInterruptAndDelay(true); 2141 } 2142 2143 // Now we are connected. Read and parse the new state. 2144 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 2145 if (parameters.length != 7) { 2146 throw new IllegalStateException("Cannot parse the state"); 2147 } 2148 2149 // Set the interface and the addresses in the config. 2150 mConfig.interfaze = parameters[0].trim(); 2151 2152 mConfig.addLegacyAddresses(parameters[1]); 2153 // Set the routes if they are not set in the config. 2154 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 2155 mConfig.addLegacyRoutes(parameters[2]); 2156 } 2157 2158 // Set the DNS servers if they are not set in the config. 2159 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 2160 String dnsServers = parameters[3].trim(); 2161 if (!dnsServers.isEmpty()) { 2162 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 2163 } 2164 } 2165 2166 // Set the search domains if they are not set in the config. 2167 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 2168 String searchDomains = parameters[4].trim(); 2169 if (!searchDomains.isEmpty()) { 2170 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 2171 } 2172 } 2173 2174 // Add a throw route for the VPN server endpoint, if one was specified. 2175 String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5]; 2176 if (!endpoint.isEmpty()) { 2177 try { 2178 InetAddress addr = InetAddress.parseNumericAddress(endpoint); 2179 if (addr instanceof Inet4Address) { 2180 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW)); 2181 } else if (addr instanceof Inet6Address) { 2182 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW)); 2183 } else { 2184 Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint); 2185 } 2186 } catch (IllegalArgumentException e) { 2187 Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e); 2188 } 2189 } 2190 2191 // Here is the last step and it must be done synchronously. 2192 synchronized (Vpn.this) { 2193 // Set the start time 2194 mConfig.startTime = SystemClock.elapsedRealtime(); 2195 2196 // Check if the thread was interrupted while we were waiting on the lock. 2197 checkInterruptAndDelay(false); 2198 2199 // Check if the interface is gone while we are waiting. 2200 if (jniCheck(mConfig.interfaze) == 0) { 2201 throw new IllegalStateException(mConfig.interfaze + " is gone"); 2202 } 2203 2204 // Now INetworkManagementEventObserver is watching our back. 2205 mInterface = mConfig.interfaze; 2206 prepareStatusIntent(); 2207 2208 agentConnect(); 2209 2210 Log.i(TAG, "Connected!"); 2211 } 2212 } catch (Exception e) { 2213 Log.i(TAG, "Aborting", e); 2214 updateState(DetailedState.FAILED, e.getMessage()); 2215 exit(); 2216 } 2217 } 2218 2219 /** 2220 * Check all daemons every two seconds. Return when one of them is stopped. 2221 * The caller will move to the disconnected state when this function returns, 2222 * which can happen if a daemon failed or if the VPN was torn down. 2223 */ waitForDaemonsToStop()2224 private void waitForDaemonsToStop() throws InterruptedException { 2225 if (!mNetworkInfo.isConnected()) { 2226 return; 2227 } 2228 while (true) { 2229 Thread.sleep(2000); 2230 for (int i = 0; i < mDaemons.length; i++) { 2231 if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { 2232 return; 2233 } 2234 } 2235 } 2236 } 2237 } 2238 } 2239