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