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