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