1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.connectivity; 18 19 import static android.Manifest.permission.BIND_VPN_SERVICE; 20 import static android.net.ConnectivityManager.NETID_UNSET; 21 import static android.net.RouteInfo.RTN_THROW; 22 import static android.net.RouteInfo.RTN_UNREACHABLE; 23 24 import android.Manifest; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.UserIdInt; 28 import android.app.AppGlobals; 29 import android.app.AppOpsManager; 30 import android.app.PendingIntent; 31 import android.content.BroadcastReceiver; 32 import android.content.ComponentName; 33 import android.content.ContentResolver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.ServiceConnection; 38 import android.content.pm.PackageManager; 39 import android.content.pm.PackageManager.NameNotFoundException; 40 import android.content.pm.ResolveInfo; 41 import android.content.pm.UserInfo; 42 import android.net.ConnectivityManager; 43 import android.net.INetworkManagementEventObserver; 44 import android.net.IpPrefix; 45 import android.net.LinkAddress; 46 import android.net.LinkProperties; 47 import android.net.LocalSocket; 48 import android.net.LocalSocketAddress; 49 import android.net.Network; 50 import android.net.NetworkAgent; 51 import android.net.NetworkCapabilities; 52 import android.net.NetworkInfo; 53 import android.net.NetworkInfo.DetailedState; 54 import android.net.NetworkMisc; 55 import android.net.RouteInfo; 56 import android.net.UidRange; 57 import android.net.Uri; 58 import android.os.Binder; 59 import android.os.FileUtils; 60 import android.os.IBinder; 61 import android.os.INetworkManagementService; 62 import android.os.Looper; 63 import android.os.Parcel; 64 import android.os.ParcelFileDescriptor; 65 import android.os.PatternMatcher; 66 import android.os.Process; 67 import android.os.RemoteException; 68 import android.os.SystemClock; 69 import android.os.SystemService; 70 import android.os.UserHandle; 71 import android.os.UserManager; 72 import android.provider.Settings; 73 import android.security.Credentials; 74 import android.security.KeyStore; 75 import android.text.TextUtils; 76 import android.util.ArraySet; 77 import android.util.Log; 78 79 import com.android.internal.annotations.GuardedBy; 80 import com.android.internal.annotations.VisibleForTesting; 81 import com.android.internal.net.LegacyVpnInfo; 82 import com.android.internal.net.VpnConfig; 83 import com.android.internal.net.VpnInfo; 84 import com.android.internal.net.VpnProfile; 85 import com.android.server.net.BaseNetworkObserver; 86 87 import libcore.io.IoUtils; 88 89 import java.io.File; 90 import java.io.IOException; 91 import java.io.InputStream; 92 import java.io.OutputStream; 93 import java.net.Inet4Address; 94 import java.net.Inet6Address; 95 import java.net.InetAddress; 96 import java.nio.charset.StandardCharsets; 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.Collection; 100 import java.util.Collections; 101 import java.util.List; 102 import java.util.Set; 103 import java.util.SortedSet; 104 import java.util.TreeSet; 105 import java.util.concurrent.atomic.AtomicInteger; 106 107 /** 108 * @hide 109 */ 110 public class Vpn { 111 private static final String NETWORKTYPE = "VPN"; 112 private static final String TAG = "Vpn"; 113 private static final boolean LOGD = true; 114 115 // TODO: create separate trackers for each unique VPN to support 116 // automated reconnection 117 118 private Context mContext; 119 private NetworkInfo mNetworkInfo; 120 private String mPackage; 121 private int mOwnerUID; 122 private String mInterface; 123 private Connection mConnection; 124 private LegacyVpnRunner mLegacyVpnRunner; 125 private PendingIntent mStatusIntent; 126 private volatile boolean mEnableTeardown = true; 127 private final INetworkManagementService mNetd; 128 private VpnConfig mConfig; 129 private NetworkAgent mNetworkAgent; 130 private final Looper mLooper; 131 private final NetworkCapabilities mNetworkCapabilities; 132 133 /** 134 * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This 135 * only applies to {@link VpnService} connections. 136 */ 137 private boolean mAlwaysOn = false; 138 139 /** 140 * Whether to disable traffic outside of this VPN even when the VPN is not connected. System 141 * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is 142 * not set. 143 */ 144 private boolean mLockdown = false; 145 146 /** 147 * List of UIDs that are set to use this VPN by default. Normally, every UID in the user is 148 * added to this set but that can be changed by adding allowed or disallowed applications. It 149 * is non-null iff the VPN is connected. 150 * 151 * Unless the VPN has set allowBypass=true, these UIDs are forced into the VPN. 152 * 153 * @see VpnService.Builder#addAllowedApplication(String) 154 * @see VpnService.Builder#addDisallowedApplication(String) 155 */ 156 @GuardedBy("this") 157 private Set<UidRange> mVpnUsers = null; 158 159 /** 160 * List of UIDs for which networking should be blocked until VPN is ready, during brief periods 161 * when VPN is not running. For example, during system startup or after a crash. 162 * @see mLockdown 163 */ 164 @GuardedBy("this") 165 private Set<UidRange> mBlockedUsers = new ArraySet<>(); 166 167 // Handle of user initiating VPN. 168 private final int mUserHandle; 169 170 // Listen to package remove and change event in this user 171 private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() { 172 @Override 173 public void onReceive(Context context, Intent intent) { 174 final Uri data = intent.getData(); 175 final String packageName = data == null ? null : data.getSchemeSpecificPart(); 176 if (packageName == null) { 177 return; 178 } 179 180 synchronized (Vpn.this) { 181 // Avoid race that always-on package has been unset 182 if (!packageName.equals(getAlwaysOnPackage())) { 183 return; 184 } 185 186 final String action = intent.getAction(); 187 Log.i(TAG, "Received broadcast " + action + " for always-on package " + packageName 188 + " in user " + mUserHandle); 189 190 switch(action) { 191 case Intent.ACTION_PACKAGE_REPLACED: 192 // Start vpn after app upgrade 193 startAlwaysOnVpn(); 194 break; 195 case Intent.ACTION_PACKAGE_REMOVED: 196 final boolean isPackageRemoved = !intent.getBooleanExtra( 197 Intent.EXTRA_REPLACING, false); 198 if (isPackageRemoved) { 199 setAndSaveAlwaysOnPackage(null, false); 200 } 201 break; 202 } 203 } 204 } 205 }; 206 207 private boolean mIsPackageIntentReceiverRegistered = false; 208 209 public Vpn(Looper looper, Context context, INetworkManagementService netService, 210 int userHandle) { 211 mContext = context; 212 mNetd = netService; 213 mUserHandle = userHandle; 214 mLooper = looper; 215 216 mPackage = VpnConfig.LEGACY_VPN; 217 mOwnerUID = getAppUid(mPackage, mUserHandle); 218 219 try { 220 netService.registerObserver(mObserver); 221 } catch (RemoteException e) { 222 Log.wtf(TAG, "Problem registering observer", e); 223 } 224 225 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, ""); 226 // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332 227 mNetworkCapabilities = new NetworkCapabilities(); 228 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); 229 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); 230 } 231 232 /** 233 * Set if this object is responsible for watching for {@link NetworkInfo} 234 * teardown. When {@code false}, teardown is handled externally by someone 235 * else. 236 */ 237 public void setEnableTeardown(boolean enableTeardown) { 238 mEnableTeardown = enableTeardown; 239 } 240 241 /** 242 * Update current state, dispaching event to listeners. 243 */ 244 private void updateState(DetailedState detailedState, String reason) { 245 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 246 mNetworkInfo.setDetailedState(detailedState, reason, null); 247 if (mNetworkAgent != null) { 248 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 249 } 250 } 251 252 /** 253 * Configures an always-on VPN connection through a specific application. 254 * This connection is automatically granted and persisted after a reboot. 255 * 256 * <p>The designated package should exist and declare a {@link VpnService} in its 257 * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, 258 * otherwise the call will fail. 259 * 260 * @param packageName the package to designate as always-on VPN supplier. 261 * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting. 262 * @return {@code true} if the package has been set as always-on, {@code false} otherwise. 263 */ 264 public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) { 265 enforceControlPermissionOrInternalCaller(); 266 if (VpnConfig.LEGACY_VPN.equals(packageName)) { 267 Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on."); 268 return false; 269 } 270 271 if (packageName != null) { 272 // Pre-authorize new always-on VPN package. 273 if (!setPackageAuthorization(packageName, true)) { 274 return false; 275 } 276 mAlwaysOn = true; 277 } else { 278 packageName = VpnConfig.LEGACY_VPN; 279 mAlwaysOn = false; 280 } 281 282 mLockdown = (mAlwaysOn && lockdown); 283 if (!isCurrentPreparedPackage(packageName)) { 284 prepareInternal(packageName); 285 } 286 maybeRegisterPackageChangeReceiverLocked(packageName); 287 setVpnForcedLocked(mLockdown); 288 return true; 289 } 290 291 private static boolean isNullOrLegacyVpn(String packageName) { 292 return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName); 293 } 294 295 private void unregisterPackageChangeReceiverLocked() { 296 // register previous intent filter 297 if (mIsPackageIntentReceiverRegistered) { 298 mContext.unregisterReceiver(mPackageIntentReceiver); 299 mIsPackageIntentReceiverRegistered = false; 300 } 301 } 302 303 private void maybeRegisterPackageChangeReceiverLocked(String packageName) { 304 // Unregister IntentFilter listening for previous always-on package change 305 unregisterPackageChangeReceiverLocked(); 306 307 if (!isNullOrLegacyVpn(packageName)) { 308 mIsPackageIntentReceiverRegistered = true; 309 310 IntentFilter intentFilter = new IntentFilter(); 311 // Protected intent can only be sent by system. No permission required in register. 312 intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 313 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 314 intentFilter.addDataScheme("package"); 315 intentFilter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL); 316 mContext.registerReceiverAsUser( 317 mPackageIntentReceiver, UserHandle.of(mUserHandle), intentFilter, null, null); 318 } 319 } 320 321 /** 322 * @return the package name of the VPN controller responsible for always-on VPN, 323 * or {@code null} if none is set or always-on VPN is controlled through 324 * lockdown instead. 325 * @hide 326 */ 327 public synchronized String getAlwaysOnPackage() { 328 enforceControlPermissionOrInternalCaller(); 329 return (mAlwaysOn ? mPackage : null); 330 } 331 332 /** 333 * Save the always-on package and lockdown config into Settings.Secure 334 */ 335 public synchronized void saveAlwaysOnPackage() { 336 final long token = Binder.clearCallingIdentity(); 337 try { 338 final ContentResolver cr = mContext.getContentResolver(); 339 Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP, 340 getAlwaysOnPackage(), mUserHandle); 341 Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 342 (mLockdown ? 1 : 0), mUserHandle); 343 } finally { 344 Binder.restoreCallingIdentity(token); 345 } 346 } 347 348 /** 349 * Set and save always-on package and lockdown config 350 * @see Vpn#setAlwaysOnPackage(String, boolean) 351 * @see Vpn#saveAlwaysOnPackage() 352 * 353 * @return result of Vpn#setAndSaveAlwaysOnPackage(String, boolean) 354 */ 355 private synchronized boolean setAndSaveAlwaysOnPackage(String packageName, boolean lockdown) { 356 if (setAlwaysOnPackage(packageName, lockdown)) { 357 saveAlwaysOnPackage(); 358 return true; 359 } else { 360 return false; 361 } 362 } 363 364 /** 365 * @return {@code true} if the service was started, the service was already connected, or there 366 * was no always-on VPN to start. {@code false} otherwise. 367 */ 368 public boolean startAlwaysOnVpn() { 369 final String alwaysOnPackage; 370 synchronized (this) { 371 alwaysOnPackage = getAlwaysOnPackage(); 372 // Skip if there is no service to start. 373 if (alwaysOnPackage == null) { 374 return true; 375 } 376 // Skip if the service is already established. This isn't bulletproof: it's not bound 377 // until after establish(), so if it's mid-setup onStartCommand will be sent twice, 378 // which may restart the connection. 379 if (getNetworkInfo().isConnected()) { 380 return true; 381 } 382 } 383 384 // Start the VPN service declared in the app's manifest. 385 Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE); 386 serviceIntent.setPackage(alwaysOnPackage); 387 try { 388 return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null; 389 } catch (RuntimeException e) { 390 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e); 391 return false; 392 } 393 } 394 395 /** 396 * Prepare for a VPN application. This method is designed to solve 397 * race conditions. It first compares the current prepared package 398 * with {@code oldPackage}. If they are the same, the prepared 399 * package is revoked and replaced with {@code newPackage}. If 400 * {@code oldPackage} is {@code null}, the comparison is omitted. 401 * If {@code newPackage} is the same package or {@code null}, the 402 * revocation is omitted. This method returns {@code true} if the 403 * operation is succeeded. 404 * 405 * Legacy VPN is handled specially since it is not a real package. 406 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 407 * it can be revoked by itself. 408 * 409 * Note: when we added VPN pre-consent in http://ag/522961 the names oldPackage 410 * and newPackage become misleading, because when an app is pre-consented, we 411 * actually prepare oldPackage, not newPackage. 412 * 413 * Their meanings actually are: 414 * 415 * - oldPackage non-null, newPackage null: App calling VpnService#prepare(). 416 * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn(). 417 * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect 418 * and revoke any current app VPN and re-prepare legacy vpn. 419 * 420 * TODO: Rename the variables - or split this method into two - and end this confusion. 421 * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN) 422 * to prepare(oldPackage=null, newPackage=LEGACY_VPN) 423 * 424 * @param oldPackage The package name of the old VPN application 425 * @param newPackage The package name of the new VPN application 426 * 427 * @return true if the operation is succeeded. 428 */ 429 public synchronized boolean prepare(String oldPackage, String newPackage) { 430 if (oldPackage != null) { 431 // Stop an existing always-on VPN from being dethroned by other apps. 432 if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) { 433 return false; 434 } 435 436 // Package is not same or old package was reinstalled. 437 if (!isCurrentPreparedPackage(oldPackage)) { 438 // The package doesn't match. We return false (to obtain user consent) unless the 439 // user has already consented to that VPN package. 440 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) { 441 prepareInternal(oldPackage); 442 return true; 443 } 444 return false; 445 } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN) 446 && !isVpnUserPreConsented(oldPackage)) { 447 // Currently prepared VPN is revoked, so unprepare it and return false. 448 prepareInternal(VpnConfig.LEGACY_VPN); 449 return false; 450 } 451 } 452 453 // Return true if we do not need to revoke. 454 if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) && 455 isCurrentPreparedPackage(newPackage))) { 456 return true; 457 } 458 459 // Check that the caller is authorized. 460 enforceControlPermission(); 461 462 // Stop an existing always-on VPN from being dethroned by other apps. 463 if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) { 464 return false; 465 } 466 467 prepareInternal(newPackage); 468 return true; 469 } 470 471 private boolean isCurrentPreparedPackage(String packageName) { 472 // We can't just check that packageName matches mPackage, because if the app was uninstalled 473 // and reinstalled it will no longer be prepared. Instead check the UID. 474 return getAppUid(packageName, mUserHandle) == mOwnerUID; 475 } 476 477 /** Prepare the VPN for the given package. Does not perform permission checks. */ 478 private void prepareInternal(String newPackage) { 479 long token = Binder.clearCallingIdentity(); 480 try { 481 // Reset the interface. 482 if (mInterface != null) { 483 mStatusIntent = null; 484 agentDisconnect(); 485 jniReset(mInterface); 486 mInterface = null; 487 mVpnUsers = null; 488 } 489 490 // Revoke the connection or stop LegacyVpnRunner. 491 if (mConnection != null) { 492 try { 493 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 494 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 495 } catch (Exception e) { 496 // ignore 497 } 498 mContext.unbindService(mConnection); 499 mConnection = null; 500 } else if (mLegacyVpnRunner != null) { 501 mLegacyVpnRunner.exit(); 502 mLegacyVpnRunner = null; 503 } 504 505 try { 506 mNetd.denyProtect(mOwnerUID); 507 } catch (Exception e) { 508 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 509 } 510 511 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 512 mPackage = newPackage; 513 mOwnerUID = getAppUid(newPackage, mUserHandle); 514 try { 515 mNetd.allowProtect(mOwnerUID); 516 } catch (Exception e) { 517 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 518 } 519 mConfig = null; 520 521 updateState(DetailedState.IDLE, "prepare"); 522 } finally { 523 Binder.restoreCallingIdentity(token); 524 } 525 } 526 527 /** 528 * Set whether a package has the ability to launch VPNs without user intervention. 529 */ 530 public boolean setPackageAuthorization(String packageName, boolean authorized) { 531 // Check if the caller is authorized. 532 enforceControlPermissionOrInternalCaller(); 533 534 int uid = getAppUid(packageName, mUserHandle); 535 if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) { 536 // Authorization for nonexistent packages (or fake ones) can't be updated. 537 return false; 538 } 539 540 long token = Binder.clearCallingIdentity(); 541 try { 542 AppOpsManager appOps = 543 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 544 appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, uid, packageName, 545 authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); 546 return true; 547 } catch (Exception e) { 548 Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e); 549 } finally { 550 Binder.restoreCallingIdentity(token); 551 } 552 return false; 553 } 554 555 private boolean isVpnUserPreConsented(String packageName) { 556 AppOpsManager appOps = 557 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 558 559 // Verify that the caller matches the given package and has permission to activate VPNs. 560 return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(), 561 packageName) == AppOpsManager.MODE_ALLOWED; 562 } 563 564 private int getAppUid(String app, int userHandle) { 565 if (VpnConfig.LEGACY_VPN.equals(app)) { 566 return Process.myUid(); 567 } 568 PackageManager pm = mContext.getPackageManager(); 569 int result; 570 try { 571 result = pm.getPackageUidAsUser(app, userHandle); 572 } catch (NameNotFoundException e) { 573 result = -1; 574 } 575 return result; 576 } 577 578 public NetworkInfo getNetworkInfo() { 579 return mNetworkInfo; 580 } 581 582 public int getNetId() { 583 return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET; 584 } 585 586 private LinkProperties makeLinkProperties() { 587 boolean allowIPv4 = mConfig.allowIPv4; 588 boolean allowIPv6 = mConfig.allowIPv6; 589 590 LinkProperties lp = new LinkProperties(); 591 592 lp.setInterfaceName(mInterface); 593 594 if (mConfig.addresses != null) { 595 for (LinkAddress address : mConfig.addresses) { 596 lp.addLinkAddress(address); 597 allowIPv4 |= address.getAddress() instanceof Inet4Address; 598 allowIPv6 |= address.getAddress() instanceof Inet6Address; 599 } 600 } 601 602 if (mConfig.routes != null) { 603 for (RouteInfo route : mConfig.routes) { 604 lp.addRoute(route); 605 InetAddress address = route.getDestination().getAddress(); 606 allowIPv4 |= address instanceof Inet4Address; 607 allowIPv6 |= address instanceof Inet6Address; 608 } 609 } 610 611 if (mConfig.dnsServers != null) { 612 for (String dnsServer : mConfig.dnsServers) { 613 InetAddress address = InetAddress.parseNumericAddress(dnsServer); 614 lp.addDnsServer(address); 615 allowIPv4 |= address instanceof Inet4Address; 616 allowIPv6 |= address instanceof Inet6Address; 617 } 618 } 619 620 if (!allowIPv4) { 621 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); 622 } 623 if (!allowIPv6) { 624 lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); 625 } 626 627 // Concatenate search domains into a string. 628 StringBuilder buffer = new StringBuilder(); 629 if (mConfig.searchDomains != null) { 630 for (String domain : mConfig.searchDomains) { 631 buffer.append(domain).append(' '); 632 } 633 } 634 lp.setDomains(buffer.toString().trim()); 635 636 // TODO: Stop setting the MTU in jniCreate and set it here. 637 638 return lp; 639 } 640 641 private void agentConnect() { 642 LinkProperties lp = makeLinkProperties(); 643 644 if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) { 645 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 646 } else { 647 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 648 } 649 650 mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); 651 652 NetworkMisc networkMisc = new NetworkMisc(); 653 networkMisc.allowBypass = mConfig.allowBypass && !mLockdown; 654 655 long token = Binder.clearCallingIdentity(); 656 try { 657 mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE, 658 mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) { 659 @Override 660 public void unwanted() { 661 // We are user controlled, not driven by NetworkRequest. 662 } 663 }; 664 } finally { 665 Binder.restoreCallingIdentity(token); 666 } 667 668 mVpnUsers = createUserAndRestrictedProfilesRanges(mUserHandle, 669 mConfig.allowedApplications, mConfig.disallowedApplications); 670 mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()])); 671 672 mNetworkInfo.setIsAvailable(true); 673 updateState(DetailedState.CONNECTED, "agentConnect"); 674 } 675 676 private boolean canHaveRestrictedProfile(int userId) { 677 long token = Binder.clearCallingIdentity(); 678 try { 679 return UserManager.get(mContext).canHaveRestrictedProfile(userId); 680 } finally { 681 Binder.restoreCallingIdentity(token); 682 } 683 } 684 685 private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) { 686 networkInfo.setIsAvailable(false); 687 networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 688 if (networkAgent != null) { 689 networkAgent.sendNetworkInfo(networkInfo); 690 } 691 } 692 693 private void agentDisconnect(NetworkAgent networkAgent) { 694 NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); 695 agentDisconnect(networkInfo, networkAgent); 696 } 697 698 private void agentDisconnect() { 699 if (mNetworkInfo.isConnected()) { 700 agentDisconnect(mNetworkInfo, mNetworkAgent); 701 mNetworkAgent = null; 702 } 703 } 704 705 /** 706 * Establish a VPN network and return the file descriptor of the VPN 707 * interface. This methods returns {@code null} if the application is 708 * revoked or not prepared. 709 * 710 * @param config The parameters to configure the network. 711 * @return The file descriptor of the VPN interface. 712 */ 713 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 714 // Check if the caller is already prepared. 715 UserManager mgr = UserManager.get(mContext); 716 if (Binder.getCallingUid() != mOwnerUID) { 717 return null; 718 } 719 // Check to ensure consent hasn't been revoked since we were prepared. 720 if (!isVpnUserPreConsented(mPackage)) { 721 return null; 722 } 723 // Check if the service is properly declared. 724 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 725 intent.setClassName(mPackage, config.user); 726 long token = Binder.clearCallingIdentity(); 727 try { 728 // Restricted users are not allowed to create VPNs, they are tied to Owner 729 UserInfo user = mgr.getUserInfo(mUserHandle); 730 if (user.isRestricted()) { 731 throw new SecurityException("Restricted users cannot establish VPNs"); 732 } 733 734 ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, 735 null, 0, mUserHandle); 736 if (info == null) { 737 throw new SecurityException("Cannot find " + config.user); 738 } 739 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 740 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 741 } 742 } catch (RemoteException e) { 743 throw new SecurityException("Cannot find " + config.user); 744 } finally { 745 Binder.restoreCallingIdentity(token); 746 } 747 748 // Save the old config in case we need to go back. 749 VpnConfig oldConfig = mConfig; 750 String oldInterface = mInterface; 751 Connection oldConnection = mConnection; 752 NetworkAgent oldNetworkAgent = mNetworkAgent; 753 mNetworkAgent = null; 754 Set<UidRange> oldUsers = mVpnUsers; 755 756 // Configure the interface. Abort if any of these steps fails. 757 ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); 758 try { 759 updateState(DetailedState.CONNECTING, "establish"); 760 String interfaze = jniGetName(tun.getFd()); 761 762 // TEMP use the old jni calls until there is support for netd address setting 763 StringBuilder builder = new StringBuilder(); 764 for (LinkAddress address : config.addresses) { 765 builder.append(" " + address); 766 } 767 if (jniSetAddresses(interfaze, builder.toString()) < 1) { 768 throw new IllegalArgumentException("At least one address must be specified"); 769 } 770 Connection connection = new Connection(); 771 if (!mContext.bindServiceAsUser(intent, connection, 772 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 773 new UserHandle(mUserHandle))) { 774 throw new IllegalStateException("Cannot bind " + config.user); 775 } 776 777 mConnection = connection; 778 mInterface = interfaze; 779 780 // Fill more values. 781 config.user = mPackage; 782 config.interfaze = mInterface; 783 config.startTime = SystemClock.elapsedRealtime(); 784 mConfig = config; 785 786 // Set up forwarding and DNS rules. 787 agentConnect(); 788 789 if (oldConnection != null) { 790 mContext.unbindService(oldConnection); 791 } 792 // Remove the old tun's user forwarding rules 793 // The new tun's user rules have already been added so they will take over 794 // as rules are deleted. This prevents data leakage as the rules are moved over. 795 agentDisconnect(oldNetworkAgent); 796 if (oldInterface != null && !oldInterface.equals(interfaze)) { 797 jniReset(oldInterface); 798 } 799 800 try { 801 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); 802 } catch (IOException e) { 803 throw new IllegalStateException( 804 "Cannot set tunnel's fd as blocking=" + config.blocking, e); 805 } 806 } catch (RuntimeException e) { 807 IoUtils.closeQuietly(tun); 808 agentDisconnect(); 809 // restore old state 810 mConfig = oldConfig; 811 mConnection = oldConnection; 812 mVpnUsers = oldUsers; 813 mNetworkAgent = oldNetworkAgent; 814 mInterface = oldInterface; 815 throw e; 816 } 817 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 818 return tun; 819 } 820 821 private boolean isRunningLocked() { 822 return mNetworkAgent != null && mInterface != null; 823 } 824 825 // Returns true if the VPN has been established and the calling UID is its owner. Used to check 826 // that a call to mutate VPN state is admissible. 827 private boolean isCallerEstablishedOwnerLocked() { 828 return isRunningLocked() && Binder.getCallingUid() == mOwnerUID; 829 } 830 831 // Note: Return type guarantees results are deduped and sorted, which callers require. 832 private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) { 833 SortedSet<Integer> uids = new TreeSet<Integer>(); 834 for (String app : packageNames) { 835 int uid = getAppUid(app, userHandle); 836 if (uid != -1) uids.add(uid); 837 } 838 return uids; 839 } 840 841 /** 842 * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs 843 * associated with one user, and any restricted profiles attached to that user. 844 * 845 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 846 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 847 * in each user and profile will be included. 848 * 849 * @param userHandle The userId to create UID ranges for along with any of its restricted 850 * profiles. 851 * @param allowedApplications (optional) whitelist of applications to include. 852 * @param disallowedApplications (optional) blacklist of applications to exclude. 853 */ 854 @VisibleForTesting 855 Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle, 856 @Nullable List<String> allowedApplications, 857 @Nullable List<String> disallowedApplications) { 858 final Set<UidRange> ranges = new ArraySet<>(); 859 860 // Assign the top-level user to the set of ranges 861 addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications); 862 863 // If the user can have restricted profiles, assign all its restricted profiles too 864 if (canHaveRestrictedProfile(userHandle)) { 865 final long token = Binder.clearCallingIdentity(); 866 List<UserInfo> users; 867 try { 868 users = UserManager.get(mContext).getUsers(true); 869 } finally { 870 Binder.restoreCallingIdentity(token); 871 } 872 for (UserInfo user : users) { 873 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) { 874 addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications); 875 } 876 } 877 } 878 return ranges; 879 } 880 881 /** 882 * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs 883 * associated with one user. 884 * 885 * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided, 886 * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs 887 * in the user will be included. 888 * 889 * @param ranges {@link Set} of {@link UidRange}s to which to add. 890 * @param userHandle The userId to add to {@param ranges}. 891 * @param allowedApplications (optional) whitelist of applications to include. 892 * @param disallowedApplications (optional) blacklist of applications to exclude. 893 */ 894 @VisibleForTesting 895 void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle, 896 @Nullable List<String> allowedApplications, 897 @Nullable List<String> disallowedApplications) { 898 if (allowedApplications != null) { 899 // Add ranges covering all UIDs for allowedApplications. 900 int start = -1, stop = -1; 901 for (int uid : getAppsUids(allowedApplications, userHandle)) { 902 if (start == -1) { 903 start = uid; 904 } else if (uid != stop + 1) { 905 ranges.add(new UidRange(start, stop)); 906 start = uid; 907 } 908 stop = uid; 909 } 910 if (start != -1) ranges.add(new UidRange(start, stop)); 911 } else if (disallowedApplications != null) { 912 // Add all ranges for user skipping UIDs for disallowedApplications. 913 final UidRange userRange = UidRange.createForUser(userHandle); 914 int start = userRange.start; 915 for (int uid : getAppsUids(disallowedApplications, userHandle)) { 916 if (uid == start) { 917 start++; 918 } else { 919 ranges.add(new UidRange(start, uid - 1)); 920 start = uid + 1; 921 } 922 } 923 if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop)); 924 } else { 925 // Add all UIDs for the user. 926 ranges.add(UidRange.createForUser(userHandle)); 927 } 928 } 929 930 // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that 931 // apply to userHandle. 932 private List<UidRange> uidRangesForUser(int userHandle) { 933 final UidRange userRange = UidRange.createForUser(userHandle); 934 final List<UidRange> ranges = new ArrayList<UidRange>(); 935 for (UidRange range : mVpnUsers) { 936 if (userRange.containsRange(range)) { 937 ranges.add(range); 938 } 939 } 940 return ranges; 941 } 942 943 private void removeVpnUserLocked(int userHandle) { 944 if (mVpnUsers == null) { 945 throw new IllegalStateException("VPN is not active"); 946 } 947 final List<UidRange> ranges = uidRangesForUser(userHandle); 948 if (mNetworkAgent != null) { 949 mNetworkAgent.removeUidRanges(ranges.toArray(new UidRange[ranges.size()])); 950 } 951 mVpnUsers.removeAll(ranges); 952 } 953 954 public void onUserAdded(int userHandle) { 955 // If the user is restricted tie them to the parent user's VPN 956 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 957 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 958 synchronized(Vpn.this) { 959 if (mVpnUsers != null) { 960 try { 961 addUserToRanges(mVpnUsers, userHandle, mConfig.allowedApplications, 962 mConfig.disallowedApplications); 963 if (mNetworkAgent != null) { 964 final List<UidRange> ranges = uidRangesForUser(userHandle); 965 mNetworkAgent.addUidRanges(ranges.toArray(new UidRange[ranges.size()])); 966 } 967 } catch (Exception e) { 968 Log.wtf(TAG, "Failed to add restricted user to owner", e); 969 } 970 } 971 if (mAlwaysOn) { 972 setVpnForcedLocked(mLockdown); 973 } 974 } 975 } 976 } 977 978 public void onUserRemoved(int userHandle) { 979 // clean up if restricted 980 UserInfo user = UserManager.get(mContext).getUserInfo(userHandle); 981 if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) { 982 synchronized(Vpn.this) { 983 if (mVpnUsers != null) { 984 try { 985 removeVpnUserLocked(userHandle); 986 } catch (Exception e) { 987 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 988 } 989 } 990 if (mAlwaysOn) { 991 setVpnForcedLocked(mLockdown); 992 } 993 } 994 } 995 } 996 997 /** 998 * Called when the user associated with this VPN has just been stopped. 999 */ 1000 public synchronized void onUserStopped() { 1001 // Switch off networking lockdown (if it was enabled) 1002 setVpnForcedLocked(false); 1003 mAlwaysOn = false; 1004 1005 unregisterPackageChangeReceiverLocked(); 1006 // Quit any active connections 1007 agentDisconnect(); 1008 } 1009 1010 /** 1011 * Restrict network access from all UIDs affected by this {@link Vpn}, apart from the VPN 1012 * service app itself, to only sockets that have had {@code protect()} called on them. All 1013 * non-VPN traffic is blocked via a {@code PROHIBIT} response from the kernel. 1014 * 1015 * The exception for the VPN UID isn't technically necessary -- setup should use protected 1016 * sockets -- but in practice it saves apps that don't protect their sockets from breaking. 1017 * 1018 * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to 1019 * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}. 1020 * 1021 * @param enforce {@code true} to require that all traffic under the jurisdiction of this 1022 * {@link Vpn} goes through a VPN connection or is blocked until one is 1023 * available, {@code false} to lift the requirement. 1024 * 1025 * @see #mBlockedUsers 1026 */ 1027 @GuardedBy("this") 1028 private void setVpnForcedLocked(boolean enforce) { 1029 final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers); 1030 if (enforce) { 1031 final Set<UidRange> addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle, 1032 /* allowedApplications */ null, 1033 /* disallowedApplications */ Collections.singletonList(mPackage)); 1034 1035 removedRanges.removeAll(addedRanges); 1036 addedRanges.removeAll(mBlockedUsers); 1037 1038 setAllowOnlyVpnForUids(false, removedRanges); 1039 setAllowOnlyVpnForUids(true, addedRanges); 1040 } else { 1041 setAllowOnlyVpnForUids(false, removedRanges); 1042 } 1043 } 1044 1045 /** 1046 * Either add or remove a list of {@link UidRange}s to the list of UIDs that are only allowed 1047 * to make connections through sockets that have had {@code protect()} called on them. 1048 * 1049 * @param enforce {@code true} to add to the blacklist, {@code false} to remove. 1050 * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is 1051 * {@code true}) or to remove. 1052 * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise, 1053 * including added ranges that already existed or removed ones that didn't. 1054 */ 1055 @GuardedBy("this") 1056 private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) { 1057 if (ranges.size() == 0) { 1058 return true; 1059 } 1060 final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]); 1061 try { 1062 mNetd.setAllowOnlyVpnForUids(enforce, rangesArray); 1063 } catch (RemoteException | RuntimeException e) { 1064 Log.e(TAG, "Updating blocked=" + enforce 1065 + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e); 1066 return false; 1067 } 1068 if (enforce) { 1069 mBlockedUsers.addAll(ranges); 1070 } else { 1071 mBlockedUsers.removeAll(ranges); 1072 } 1073 return true; 1074 } 1075 1076 /** 1077 * Return the configuration of the currently running VPN. 1078 */ 1079 public VpnConfig getVpnConfig() { 1080 enforceControlPermission(); 1081 return mConfig; 1082 } 1083 1084 @Deprecated 1085 public synchronized void interfaceStatusChanged(String iface, boolean up) { 1086 try { 1087 mObserver.interfaceStatusChanged(iface, up); 1088 } catch (RemoteException e) { 1089 // ignored; target is local 1090 } 1091 } 1092 1093 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 1094 @Override 1095 public void interfaceStatusChanged(String interfaze, boolean up) { 1096 synchronized (Vpn.this) { 1097 if (!up && mLegacyVpnRunner != null) { 1098 mLegacyVpnRunner.check(interfaze); 1099 } 1100 } 1101 } 1102 1103 @Override 1104 public void interfaceRemoved(String interfaze) { 1105 synchronized (Vpn.this) { 1106 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 1107 mStatusIntent = null; 1108 mVpnUsers = null; 1109 mConfig = null; 1110 mInterface = null; 1111 if (mConnection != null) { 1112 mContext.unbindService(mConnection); 1113 mConnection = null; 1114 agentDisconnect(); 1115 } else if (mLegacyVpnRunner != null) { 1116 mLegacyVpnRunner.exit(); 1117 mLegacyVpnRunner = null; 1118 } 1119 } 1120 } 1121 } 1122 }; 1123 1124 private void enforceControlPermission() { 1125 mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller"); 1126 } 1127 1128 private void enforceControlPermissionOrInternalCaller() { 1129 // Require caller to be either an application with CONTROL_VPN permission or a process 1130 // in the system server. 1131 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN, 1132 "Unauthorized Caller"); 1133 } 1134 1135 private class Connection implements ServiceConnection { 1136 private IBinder mService; 1137 1138 @Override 1139 public void onServiceConnected(ComponentName name, IBinder service) { 1140 mService = service; 1141 } 1142 1143 @Override 1144 public void onServiceDisconnected(ComponentName name) { 1145 mService = null; 1146 } 1147 } 1148 1149 private void prepareStatusIntent() { 1150 final long token = Binder.clearCallingIdentity(); 1151 try { 1152 mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext); 1153 } finally { 1154 Binder.restoreCallingIdentity(token); 1155 } 1156 } 1157 1158 public synchronized boolean addAddress(String address, int prefixLength) { 1159 if (!isCallerEstablishedOwnerLocked()) { 1160 return false; 1161 } 1162 boolean success = jniAddAddress(mInterface, address, prefixLength); 1163 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1164 return success; 1165 } 1166 1167 public synchronized boolean removeAddress(String address, int prefixLength) { 1168 if (!isCallerEstablishedOwnerLocked()) { 1169 return false; 1170 } 1171 boolean success = jniDelAddress(mInterface, address, prefixLength); 1172 mNetworkAgent.sendLinkProperties(makeLinkProperties()); 1173 return success; 1174 } 1175 1176 public synchronized boolean setUnderlyingNetworks(Network[] networks) { 1177 if (!isCallerEstablishedOwnerLocked()) { 1178 return false; 1179 } 1180 if (networks == null) { 1181 mConfig.underlyingNetworks = null; 1182 } else { 1183 mConfig.underlyingNetworks = new Network[networks.length]; 1184 for (int i = 0; i < networks.length; ++i) { 1185 if (networks[i] == null) { 1186 mConfig.underlyingNetworks[i] = null; 1187 } else { 1188 mConfig.underlyingNetworks[i] = new Network(networks[i].netId); 1189 } 1190 } 1191 } 1192 return true; 1193 } 1194 1195 public synchronized Network[] getUnderlyingNetworks() { 1196 if (!isRunningLocked()) { 1197 return null; 1198 } 1199 return mConfig.underlyingNetworks; 1200 } 1201 1202 /** 1203 * This method should only be called by ConnectivityService. Because it doesn't 1204 * have enough data to fill VpnInfo.primaryUnderlyingIface field. 1205 */ 1206 public synchronized VpnInfo getVpnInfo() { 1207 if (!isRunningLocked()) { 1208 return null; 1209 } 1210 1211 VpnInfo info = new VpnInfo(); 1212 info.ownerUid = mOwnerUID; 1213 info.vpnIface = mInterface; 1214 return info; 1215 } 1216 1217 public synchronized boolean appliesToUid(int uid) { 1218 if (!isRunningLocked()) { 1219 return false; 1220 } 1221 for (UidRange uidRange : mVpnUsers) { 1222 if (uidRange.contains(uid)) { 1223 return true; 1224 } 1225 } 1226 return false; 1227 } 1228 1229 /** 1230 * @return {@code true} if {@param uid} is blocked by an always-on VPN. 1231 * A UID is blocked if it's included in one of the mBlockedUsers ranges and the VPN is 1232 * not connected, or if the VPN is connected but does not apply to the UID. 1233 * 1234 * @see #mBlockedUsers 1235 */ 1236 public synchronized boolean isBlockingUid(int uid) { 1237 if (!mLockdown) { 1238 return false; 1239 } 1240 1241 if (mNetworkInfo.isConnected()) { 1242 return !appliesToUid(uid); 1243 } else { 1244 for (UidRange uidRange : mBlockedUsers) { 1245 if (uidRange.contains(uid)) { 1246 return true; 1247 } 1248 } 1249 return false; 1250 } 1251 } 1252 1253 private native int jniCreate(int mtu); 1254 private native String jniGetName(int tun); 1255 private native int jniSetAddresses(String interfaze, String addresses); 1256 private native void jniReset(String interfaze); 1257 private native int jniCheck(String interfaze); 1258 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); 1259 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 1260 1261 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 1262 for (RouteInfo route : prop.getAllRoutes()) { 1263 // Currently legacy VPN only works on IPv4. 1264 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 1265 return route; 1266 } 1267 } 1268 1269 throw new IllegalStateException("Unable to find IPv4 default gateway"); 1270 } 1271 1272 /** 1273 * Start legacy VPN, controlling native daemons as needed. Creates a 1274 * secondary thread to perform connection work, returning quickly. 1275 * 1276 * Should only be called to respond to Binder requests as this enforces caller permission. Use 1277 * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the 1278 * permission check only when the caller is trusted (or the call is initiated by the system). 1279 */ 1280 public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) { 1281 enforceControlPermission(); 1282 long token = Binder.clearCallingIdentity(); 1283 try { 1284 startLegacyVpnPrivileged(profile, keyStore, egress); 1285 } finally { 1286 Binder.restoreCallingIdentity(token); 1287 } 1288 } 1289 1290 /** 1291 * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check 1292 * permissions under the assumption that the caller is the system. 1293 * 1294 * Callers are responsible for checking permissions if needed. 1295 */ 1296 public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore, 1297 LinkProperties egress) { 1298 UserManager mgr = UserManager.get(mContext); 1299 UserInfo user = mgr.getUserInfo(mUserHandle); 1300 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, 1301 new UserHandle(mUserHandle))) { 1302 throw new SecurityException("Restricted users cannot establish VPNs"); 1303 } 1304 1305 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 1306 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 1307 final String iface = ipv4DefaultRoute.getInterface(); 1308 1309 // Load certificates. 1310 String privateKey = ""; 1311 String userCert = ""; 1312 String caCert = ""; 1313 String serverCert = ""; 1314 if (!profile.ipsecUserCert.isEmpty()) { 1315 privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; 1316 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 1317 userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1318 } 1319 if (!profile.ipsecCaCert.isEmpty()) { 1320 byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 1321 caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1322 } 1323 if (!profile.ipsecServerCert.isEmpty()) { 1324 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 1325 serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 1326 } 1327 if (privateKey == null || userCert == null || caCert == null || serverCert == null) { 1328 throw new IllegalStateException("Cannot load credentials"); 1329 } 1330 1331 // Prepare arguments for racoon. 1332 String[] racoon = null; 1333 switch (profile.type) { 1334 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 1335 racoon = new String[] { 1336 iface, profile.server, "udppsk", profile.ipsecIdentifier, 1337 profile.ipsecSecret, "1701", 1338 }; 1339 break; 1340 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 1341 racoon = new String[] { 1342 iface, profile.server, "udprsa", privateKey, userCert, 1343 caCert, serverCert, "1701", 1344 }; 1345 break; 1346 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 1347 racoon = new String[] { 1348 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 1349 profile.ipsecSecret, profile.username, profile.password, "", gateway, 1350 }; 1351 break; 1352 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 1353 racoon = new String[] { 1354 iface, profile.server, "xauthrsa", privateKey, userCert, 1355 caCert, serverCert, profile.username, profile.password, "", gateway, 1356 }; 1357 break; 1358 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 1359 racoon = new String[] { 1360 iface, profile.server, "hybridrsa", 1361 caCert, serverCert, profile.username, profile.password, "", gateway, 1362 }; 1363 break; 1364 } 1365 1366 // Prepare arguments for mtpd. 1367 String[] mtpd = null; 1368 switch (profile.type) { 1369 case VpnProfile.TYPE_PPTP: 1370 mtpd = new String[] { 1371 iface, "pptp", profile.server, "1723", 1372 "name", profile.username, "password", profile.password, 1373 "linkname", "vpn", "refuse-eap", "nodefaultroute", 1374 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 1375 (profile.mppe ? "+mppe" : "nomppe"), 1376 }; 1377 break; 1378 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 1379 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 1380 mtpd = new String[] { 1381 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 1382 "name", profile.username, "password", profile.password, 1383 "linkname", "vpn", "refuse-eap", "nodefaultroute", 1384 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 1385 }; 1386 break; 1387 } 1388 1389 VpnConfig config = new VpnConfig(); 1390 config.legacy = true; 1391 config.user = profile.key; 1392 config.interfaze = iface; 1393 config.session = profile.name; 1394 1395 config.addLegacyRoutes(profile.routes); 1396 if (!profile.dnsServers.isEmpty()) { 1397 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 1398 } 1399 if (!profile.searchDomains.isEmpty()) { 1400 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 1401 } 1402 startLegacyVpn(config, racoon, mtpd); 1403 } 1404 1405 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { 1406 stopLegacyVpnPrivileged(); 1407 1408 // Prepare for the new request. 1409 prepareInternal(VpnConfig.LEGACY_VPN); 1410 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 1411 1412 // Start a new LegacyVpnRunner and we are done! 1413 mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); 1414 mLegacyVpnRunner.start(); 1415 } 1416 1417 /** Stop legacy VPN. Permissions must be checked by callers. */ 1418 public synchronized void stopLegacyVpnPrivileged() { 1419 if (mLegacyVpnRunner != null) { 1420 mLegacyVpnRunner.exit(); 1421 mLegacyVpnRunner = null; 1422 1423 synchronized (LegacyVpnRunner.TAG) { 1424 // wait for old thread to completely finish before spinning up 1425 // new instance, otherwise state updates can be out of order. 1426 } 1427 } 1428 } 1429 1430 /** 1431 * Return the information of the current ongoing legacy VPN. 1432 */ 1433 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 1434 // Check if the caller is authorized. 1435 enforceControlPermission(); 1436 return getLegacyVpnInfoPrivileged(); 1437 } 1438 1439 /** 1440 * Return the information of the current ongoing legacy VPN. 1441 * Callers are responsible for checking permissions if needed. 1442 */ 1443 public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() { 1444 if (mLegacyVpnRunner == null) return null; 1445 1446 final LegacyVpnInfo info = new LegacyVpnInfo(); 1447 info.key = mConfig.user; 1448 info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); 1449 if (mNetworkInfo.isConnected()) { 1450 info.intent = mStatusIntent; 1451 } 1452 return info; 1453 } 1454 1455 public VpnConfig getLegacyVpnConfig() { 1456 if (mLegacyVpnRunner != null) { 1457 return mConfig; 1458 } else { 1459 return null; 1460 } 1461 } 1462 1463 /** 1464 * Bringing up a VPN connection takes time, and that is all this thread 1465 * does. Here we have plenty of time. The only thing we need to take 1466 * care of is responding to interruptions as soon as possible. Otherwise 1467 * requests will be piled up. This can be done in a Handler as a state 1468 * machine, but it is much easier to read in the current form. 1469 */ 1470 private class LegacyVpnRunner extends Thread { 1471 private static final String TAG = "LegacyVpnRunner"; 1472 1473 private final String[] mDaemons; 1474 private final String[][] mArguments; 1475 private final LocalSocket[] mSockets; 1476 private final String mOuterInterface; 1477 private final AtomicInteger mOuterConnection = 1478 new AtomicInteger(ConnectivityManager.TYPE_NONE); 1479 1480 private long mTimer = -1; 1481 1482 /** 1483 * Watch for the outer connection (passing in the constructor) going away. 1484 */ 1485 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 1486 @Override 1487 public void onReceive(Context context, Intent intent) { 1488 if (!mEnableTeardown) return; 1489 1490 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1491 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1492 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 1493 NetworkInfo info = (NetworkInfo)intent.getExtra( 1494 ConnectivityManager.EXTRA_NETWORK_INFO); 1495 if (info != null && !info.isConnectedOrConnecting()) { 1496 try { 1497 mObserver.interfaceStatusChanged(mOuterInterface, false); 1498 } catch (RemoteException e) {} 1499 } 1500 } 1501 } 1502 } 1503 }; 1504 1505 public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) { 1506 super(TAG); 1507 mConfig = config; 1508 mDaemons = new String[] {"racoon", "mtpd"}; 1509 // TODO: clear arguments from memory once launched 1510 mArguments = new String[][] {racoon, mtpd}; 1511 mSockets = new LocalSocket[mDaemons.length]; 1512 1513 // This is the interface which VPN is running on, 1514 // mConfig.interfaze will change to point to OUR 1515 // internal interface soon. TODO - add inner/outer to mconfig 1516 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 1517 // we will leave the VPN up. We should check that it's still there/connected after 1518 // registering 1519 mOuterInterface = mConfig.interfaze; 1520 1521 if (!TextUtils.isEmpty(mOuterInterface)) { 1522 final ConnectivityManager cm = ConnectivityManager.from(mContext); 1523 for (Network network : cm.getAllNetworks()) { 1524 final LinkProperties lp = cm.getLinkProperties(network); 1525 if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { 1526 final NetworkInfo networkInfo = cm.getNetworkInfo(network); 1527 if (networkInfo != null) mOuterConnection.set(networkInfo.getType()); 1528 } 1529 } 1530 } 1531 1532 IntentFilter filter = new IntentFilter(); 1533 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 1534 mContext.registerReceiver(mBroadcastReceiver, filter); 1535 } 1536 1537 public void check(String interfaze) { 1538 if (interfaze.equals(mOuterInterface)) { 1539 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 1540 exit(); 1541 } 1542 } 1543 1544 public void exit() { 1545 // We assume that everything is reset after stopping the daemons. 1546 interrupt(); 1547 for (LocalSocket socket : mSockets) { 1548 IoUtils.closeQuietly(socket); 1549 } 1550 agentDisconnect(); 1551 try { 1552 mContext.unregisterReceiver(mBroadcastReceiver); 1553 } catch (IllegalArgumentException e) {} 1554 } 1555 1556 @Override 1557 public void run() { 1558 // Wait for the previous thread since it has been interrupted. 1559 Log.v(TAG, "Waiting"); 1560 synchronized (TAG) { 1561 Log.v(TAG, "Executing"); 1562 execute(); 1563 monitorDaemons(); 1564 } 1565 } 1566 1567 private void checkpoint(boolean yield) throws InterruptedException { 1568 long now = SystemClock.elapsedRealtime(); 1569 if (mTimer == -1) { 1570 mTimer = now; 1571 Thread.sleep(1); 1572 } else if (now - mTimer <= 60000) { 1573 Thread.sleep(yield ? 200 : 1); 1574 } else { 1575 updateState(DetailedState.FAILED, "checkpoint"); 1576 throw new IllegalStateException("Time is up"); 1577 } 1578 } 1579 1580 private void execute() { 1581 // Catch all exceptions so we can clean up few things. 1582 boolean initFinished = false; 1583 try { 1584 // Initialize the timer. 1585 checkpoint(false); 1586 1587 // Wait for the daemons to stop. 1588 for (String daemon : mDaemons) { 1589 while (!SystemService.isStopped(daemon)) { 1590 checkpoint(true); 1591 } 1592 } 1593 1594 // Clear the previous state. 1595 File state = new File("/data/misc/vpn/state"); 1596 state.delete(); 1597 if (state.exists()) { 1598 throw new IllegalStateException("Cannot delete the state"); 1599 } 1600 new File("/data/misc/vpn/abort").delete(); 1601 initFinished = true; 1602 1603 // Check if we need to restart any of the daemons. 1604 boolean restart = false; 1605 for (String[] arguments : mArguments) { 1606 restart = restart || (arguments != null); 1607 } 1608 if (!restart) { 1609 agentDisconnect(); 1610 return; 1611 } 1612 updateState(DetailedState.CONNECTING, "execute"); 1613 1614 // Start the daemon with arguments. 1615 for (int i = 0; i < mDaemons.length; ++i) { 1616 String[] arguments = mArguments[i]; 1617 if (arguments == null) { 1618 continue; 1619 } 1620 1621 // Start the daemon. 1622 String daemon = mDaemons[i]; 1623 SystemService.start(daemon); 1624 1625 // Wait for the daemon to start. 1626 while (!SystemService.isRunning(daemon)) { 1627 checkpoint(true); 1628 } 1629 1630 // Create the control socket. 1631 mSockets[i] = new LocalSocket(); 1632 LocalSocketAddress address = new LocalSocketAddress( 1633 daemon, LocalSocketAddress.Namespace.RESERVED); 1634 1635 // Wait for the socket to connect. 1636 while (true) { 1637 try { 1638 mSockets[i].connect(address); 1639 break; 1640 } catch (Exception e) { 1641 // ignore 1642 } 1643 checkpoint(true); 1644 } 1645 mSockets[i].setSoTimeout(500); 1646 1647 // Send over the arguments. 1648 OutputStream out = mSockets[i].getOutputStream(); 1649 for (String argument : arguments) { 1650 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 1651 if (bytes.length >= 0xFFFF) { 1652 throw new IllegalArgumentException("Argument is too large"); 1653 } 1654 out.write(bytes.length >> 8); 1655 out.write(bytes.length); 1656 out.write(bytes); 1657 checkpoint(false); 1658 } 1659 out.write(0xFF); 1660 out.write(0xFF); 1661 out.flush(); 1662 1663 // Wait for End-of-File. 1664 InputStream in = mSockets[i].getInputStream(); 1665 while (true) { 1666 try { 1667 if (in.read() == -1) { 1668 break; 1669 } 1670 } catch (Exception e) { 1671 // ignore 1672 } 1673 checkpoint(true); 1674 } 1675 } 1676 1677 // Wait for the daemons to create the new state. 1678 while (!state.exists()) { 1679 // Check if a running daemon is dead. 1680 for (int i = 0; i < mDaemons.length; ++i) { 1681 String daemon = mDaemons[i]; 1682 if (mArguments[i] != null && !SystemService.isRunning(daemon)) { 1683 throw new IllegalStateException(daemon + " is dead"); 1684 } 1685 } 1686 checkpoint(true); 1687 } 1688 1689 // Now we are connected. Read and parse the new state. 1690 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 1691 if (parameters.length != 7) { 1692 throw new IllegalStateException("Cannot parse the state"); 1693 } 1694 1695 // Set the interface and the addresses in the config. 1696 mConfig.interfaze = parameters[0].trim(); 1697 1698 mConfig.addLegacyAddresses(parameters[1]); 1699 // Set the routes if they are not set in the config. 1700 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 1701 mConfig.addLegacyRoutes(parameters[2]); 1702 } 1703 1704 // Set the DNS servers if they are not set in the config. 1705 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 1706 String dnsServers = parameters[3].trim(); 1707 if (!dnsServers.isEmpty()) { 1708 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 1709 } 1710 } 1711 1712 // Set the search domains if they are not set in the config. 1713 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 1714 String searchDomains = parameters[4].trim(); 1715 if (!searchDomains.isEmpty()) { 1716 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 1717 } 1718 } 1719 1720 // Add a throw route for the VPN server endpoint, if one was specified. 1721 String endpoint = parameters[5]; 1722 if (!endpoint.isEmpty()) { 1723 try { 1724 InetAddress addr = InetAddress.parseNumericAddress(endpoint); 1725 if (addr instanceof Inet4Address) { 1726 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW)); 1727 } else if (addr instanceof Inet6Address) { 1728 mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW)); 1729 } else { 1730 Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint); 1731 } 1732 } catch (IllegalArgumentException e) { 1733 Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e); 1734 } 1735 } 1736 1737 // Here is the last step and it must be done synchronously. 1738 synchronized (Vpn.this) { 1739 // Set the start time 1740 mConfig.startTime = SystemClock.elapsedRealtime(); 1741 1742 // Check if the thread is interrupted while we are waiting. 1743 checkpoint(false); 1744 1745 // Check if the interface is gone while we are waiting. 1746 if (jniCheck(mConfig.interfaze) == 0) { 1747 throw new IllegalStateException(mConfig.interfaze + " is gone"); 1748 } 1749 1750 // Now INetworkManagementEventObserver is watching our back. 1751 mInterface = mConfig.interfaze; 1752 prepareStatusIntent(); 1753 1754 agentConnect(); 1755 1756 Log.i(TAG, "Connected!"); 1757 } 1758 } catch (Exception e) { 1759 Log.i(TAG, "Aborting", e); 1760 updateState(DetailedState.FAILED, e.getMessage()); 1761 exit(); 1762 } finally { 1763 // Kill the daemons if they fail to stop. 1764 if (!initFinished) { 1765 for (String daemon : mDaemons) { 1766 SystemService.stop(daemon); 1767 } 1768 } 1769 1770 // Do not leave an unstable state. 1771 if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) { 1772 agentDisconnect(); 1773 } 1774 } 1775 } 1776 1777 /** 1778 * Monitor the daemons we started, moving to disconnected state if the 1779 * underlying services fail. 1780 */ 1781 private void monitorDaemons() { 1782 if (!mNetworkInfo.isConnected()) { 1783 return; 1784 } 1785 1786 try { 1787 while (true) { 1788 Thread.sleep(2000); 1789 for (int i = 0; i < mDaemons.length; i++) { 1790 if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { 1791 return; 1792 } 1793 } 1794 } 1795 } catch (InterruptedException e) { 1796 Log.d(TAG, "interrupted during monitorDaemons(); stopping services"); 1797 } finally { 1798 for (String daemon : mDaemons) { 1799 SystemService.stop(daemon); 1800 } 1801 1802 agentDisconnect(); 1803 } 1804 } 1805 } 1806 } 1807