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