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