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