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